123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- # -*- coding: utf-8 -*-
- '''
- PDF Generator
- -------
- The pdf plugin generates PDF files from reStructuredText and Markdown sources.
- '''
- from __future__ import unicode_literals, print_function
- from io import open
- from pelican import signals
- from pelican.generators import Generator
- from pelican.readers import MarkdownReader
- import os
- import logging
- logger = logging.getLogger(__name__)
- import xhtml2pdf.util
- if 'pyPdf' not in dir(xhtml2pdf.util):
- try:
- from xhtml2pdf.util import PyPDF2
- xhtml2pdf.util.pyPdf = PyPDF2
- except ImportError:
- logger.error('Failed to monkeypatch xhtml2pdf. ' +
- 'You have missing dependencies')
- raise
- from rst2pdf.createpdf import RstToPdf
- class PdfGenerator(Generator):
- "Generate PDFs on the output dir, for all articles and pages"
- supported_md_fields = ['date']
- def __init__(self, *args, **kwargs):
- super(PdfGenerator, self).__init__(*args, **kwargs)
- if 'PDF_STYLE_PATH' in self.settings:
- pdf_style_path = [self.settings['PDF_STYLE_PATH']]
- else:
- pdf_style_path = []
- if 'PDF_STYLE' in self.settings:
- pdf_style = [self.settings['PDF_STYLE']]
- else:
- pdf_style = []
- self.pdfcreator = RstToPdf(breakside=0,
- stylesheets=pdf_style,
- style_path=pdf_style_path,
- raw_html=True)
- def _create_pdf(self, obj, output_path):
- filename = obj.slug + '.pdf'
- output_pdf = os.path.join(output_path, filename)
- mdreader = MarkdownReader(self.settings)
- _, ext = os.path.splitext(obj.source_path)
- if ext == '.rst':
- with open(obj.source_path, encoding='utf-8') as f:
- text = f.read()
- header = ''
- elif ext[1:] in mdreader.file_extensions and mdreader.enabled:
- text, meta = mdreader.read(obj.source_path)
- header = ''
- if 'title' in meta:
- title = meta['title']
- header = title + '\n' + '#' * len(title) + '\n\n'
- del meta['title']
- for k in meta.keys():
- # We can't support all fields, so we strip the ones that won't
- # look good
- if k not in self.supported_md_fields:
- del meta[k]
- header += '\n'.join([':%s: %s' % (k, meta[k]) for k in meta])
- header += '\n\n.. raw:: html\n\n\t'
- text = text.replace('\n', '\n\t')
- # rst2pdf casts the text to str and will break if it finds
- # non-escaped characters. Here we nicely escape them to XML/HTML
- # entities before proceeding
- text = text.encode('ascii', 'xmlcharrefreplace')
- else:
- # We don't support this format
- logger.warn('Ignoring unsupported file ' + obj.source_path)
- return
- logger.info(' [ok] writing %s' % output_pdf)
- self.pdfcreator.createPdf(text=(header+text),
- output=output_pdf)
- def generate_context(self):
- pass
- def generate_output(self, writer=None):
- # we don't use the writer passed as argument here
- # since we write our own files
- logger.info(' Generating PDF files...')
- pdf_path = os.path.join(self.output_path, 'pdf')
- if not os.path.exists(pdf_path):
- try:
- os.mkdir(pdf_path)
- except OSError:
- logger.error("Couldn't create the pdf output folder in " +
- pdf_path)
- for article in self.context['articles']:
- self._create_pdf(article, pdf_path)
- for page in self.context['pages']:
- self._create_pdf(page, pdf_path)
- def get_generators(generators):
- return PdfGenerator
- def register():
- signals.get_generators.connect(get_generators)
|