diff --git a/pdf/Readme.rst b/pdf/Readme.rst new file mode 100644 index 0000000..4c06944 --- /dev/null +++ b/pdf/Readme.rst @@ -0,0 +1,7 @@ +------------- +PDF Generator +------------- + +The PDF Generator plugin automatically exports RST articles and pages +as PDF files as part of the site-generation process. PDFs are saved to +output/pdf/ diff --git a/pdf/__init__.py b/pdf/__init__.py new file mode 100644 index 0000000..3920e03 --- /dev/null +++ b/pdf/__init__.py @@ -0,0 +1 @@ +from .pdf import * diff --git a/pdf/pdf.py b/pdf/pdf.py new file mode 100644 index 0000000..5d25e67 --- /dev/null +++ b/pdf/pdf.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +''' +PDF Generator +------- + +The pdf plugin generates PDF files from RST sources. +''' + +from __future__ import unicode_literals, print_function + +from pelican import signals +from pelican.generators import Generator +from rst2pdf.createpdf import RstToPdf + +import os +import logging + +logger = logging.getLogger(__name__) + + +class PdfGenerator(Generator): + """Generate PDFs on the output dir, for all articles and pages coming from + rst""" + def __init__(self, *args, **kwargs): + super(PdfGenerator, self).__init__(*args, **kwargs) + + pdf_style_path = os.path.join(self.settings['PDF_STYLE_PATH']) + pdf_style = self.settings['PDF_STYLE'] + self.pdfcreator = RstToPdf(breakside=0, + stylesheets=[pdf_style], + style_path=[pdf_style_path]) + + def _create_pdf(self, obj, output_path): + if obj.source_path.endswith('.rst'): + filename = obj.slug + ".pdf" + output_pdf = os.path.join(output_path, filename) + # print('Generating pdf for', obj.source_path, 'in', output_pdf) + with open(obj.source_path) as f: + self.pdfcreator.createPdf(text=f.read(), output=output_pdf) + logger.info(' [ok] writing %s' % 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) diff --git a/pdf/test_pdf.py b/pdf/test_pdf.py new file mode 100644 index 0000000..d60493a --- /dev/null +++ b/pdf/test_pdf.py @@ -0,0 +1,41 @@ +import unittest +import os +import locale +import logging +import pdf + +from tempfile import mkdtemp +from pelican import Pelican +from pelican.settings import read_settings +from shutil import rmtree + +CUR_DIR = os.path.dirname(__file__) + +class TestPdfGeneration(unittest.TestCase): + def setUp(self, override=None): + import pdf + self.temp_path = mkdtemp(prefix='pelicantests.') + settings = { + 'PATH': os.path.join(os.path.dirname(CUR_DIR), '..', 'test_data', 'content'), + 'OUTPUT_PATH': self.temp_path, + 'PLUGINS': [pdf], + 'LOCALE': locale.normalize('en_US'), + } + if override: + settings.update(override) + + self.settings = read_settings(override=settings) + pelican = Pelican(settings=self.settings) + + try: + pelican.run() + except ValueError: + logging.warn('Relative links in the form of |filename|images/test.png are not yet handled by the pdf generator') + pass + + + def tearDown(self): + rmtree(self.temp_path) + + def test_existence(self): + assert os.path.exists(os.path.join(self.temp_path, 'pdf', 'this-is-a-super-article.pdf'))