[silva.export.pdf][Emiliano D'Alterio] Added new export to PDF f...
[email protected] Mon, 07 Oct 2013 15:04:06 +0200
| Newsgroups | gmane.comp.web.zope.silva.cvs |
|---|---|
| Message-ID | <[email protected]> |
author: Emiliano D'Alterio
date: Mon Oct 07 15:03:59 2013 +0200
revision: 1:cf331910dcd7 in silva.export.pdf
branch:
details: https://hg.infrae.com/silva.export.pdf?cmd=changeset;node=cf331910dcd7
modified: .hgignore setup.py src/silva/export/pdf/configure.zcml src/silva/export/pdf/pdf.py
added: src/silva/export/pdf/configure.zcml src/silva/export/pdf/pdf.py
removed:
log: Added new export to PDF feature (still experimental and misses skin
choice).
diffstat:
.hgignore | 1 +
setup.py | 24 ++++++-----
src/silva/export/pdf/configure.zcml | 12 +++++
src/silva/export/pdf/pdf.py | 79 +++++++++++++++++++++++++++++++++++++
4 files changed, 105 insertions(+), 11 deletions(-)
diffs (149 lines):
diff -r 49268e92e2b2 -r cf331910dcd7 .hgignore
--- a/.hgignore Fri Feb 17 15:43:19 2012 +0100
+++ b/.hgignore Mon Oct 07 15:03:59 2013 +0200
@@ -1,3 +1,4 @@
+.DS_Store
.pyo
.pyc
.egg-info
diff -r 49268e92e2b2 -r cf331910dcd7 setup.py
--- a/setup.py Fri Feb 17 15:43:19 2012 +0100
+++ b/setup.py Mon Oct 07 15:03:59 2013 +0200
@@ -15,14 +15,14 @@
setup(name='silva.export.pdf',
version=version,
description="Export Silva content to PDF",
- long_description=open("README.txt").read() + "\n" +
- open(os.path.join("docs", "HISTORY.txt")).read(),
+ long_description=open("README.txt").read() + "\n" + open(
+ os.path.join("docs", "HISTORY.txt")).read(),
classifiers=[
- "Framework :: Zope2",
- "License :: OSI Approved :: BSD License",
- "Programming Language :: Python",
- "Topic :: Software Development :: Libraries :: Python Modules",
- ],
+ "Framework :: Zope2",
+ "License :: OSI Approved :: BSD License",
+ "Programming Language :: Python",
+ "Topic :: Software Development :: Libraries :: Python Modules",
+ ],
keywords='silva export pdf',
author='Infrae',
author_email='[email protected]',
@@ -34,10 +34,12 @@
include_package_data=True,
zip_safe=False,
install_requires=[
- 'Zope2',
- 'five.grok',
- 'silva.core.interfaces',
- ],
+ 'Zope2',
+ 'five.grok',
+ 'silva.core.interfaces',
+ 'silva.export.html',
+ 'xhtml2pdf'
+ ],
tests_require=tests_require,
extras_require={'test': tests_require},
)
diff -r 49268e92e2b2 -r cf331910dcd7 src/silva/export/pdf/configure.zcml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/silva/export/pdf/configure.zcml Mon Oct 07 15:03:59 2013 +0200
@@ -0,0 +1,12 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:grok="http://namespaces.zope.org/grok"
+ xmlns:browser="http://namespaces.zope.org/browser"
+ i18n_domain="silva">
+
+ <include package="five.grok" />
+
+ <!-- Grok package -->
+ <grok:grok package="." />
+
+</configure>
diff -r 49268e92e2b2 -r cf331910dcd7 src/silva/export/pdf/pdf.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/silva/export/pdf/pdf.py Mon Oct 07 15:03:59 2013 +0200
@@ -0,0 +1,79 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2012-2013 Infrae. All rights reserved.
+# See also LICENSE.txt
+
+import logging
+import shutil
+import tempfile
+import fnmatch
+import re
+import os
+
+from cStringIO import StringIO
+from zope.component import getAdapter
+from silva.core.interfaces import IPublishable, IContentExporter
+from zipfile import ZipFile, ZIP_DEFLATED
+from zope.interface import Interface
+from five import grok
+from xhtml2pdf import pisa
+
+
+logger = logging.getLogger('silva.export.pdf')
+
+
+def convert_html_to_pdf(html_file_path, pdf_file_path):
+ with open(html_file_path, 'r') as f:
+ html_data = f.read()
+ os.unlink(html_file_path)
+
+ for link in re.findall('href="(.*?)"', html_data, re.DOTALL):
+ if not 'http://' in link and '.html' in link:
+ ## We change the local links to be as xhtml2pdf expects,
+ ## so it will generate correct "GoToR" syntax for them.
+ local_pdf_link = 'pdf:%s' % (link.replace('.html', '.pdf'))
+ html_data = html_data.replace(link, local_pdf_link)
+
+ with open(pdf_file_path, "w+b") as pdf:
+ pisa.CreatePDF(html_data, dest=pdf, path=pdf_file_path,
+ encoding='UTF-8')
+
+ return pdf_file_path
+
+
+class IExportOptions(Interface):
+ pass
+
+
+class PDFExporter(grok.Adapter):
+ """Export content to HTML.
+ """
+ grok.provides(IContentExporter)
+ grok.context(IPublishable)
+ grok.name('pdf')
+
+ name = "PDF (zip)"
+ extension = "zip"
+ options = IExportOptions
+
+ def export(self, **options):
+ output = StringIO()
+ archive = ZipFile(output, "w", ZIP_DEFLATED)
+ temp_folder = tempfile.mkdtemp()
+ logger.info('Creating temp dir: %s' % (temp_folder))
+ HTMLEx = getAdapter(self.context, IContentExporter, name='html')
+ HTMLEx.export_to_folder(temp_folder, **options)
+ for root, dirs, files in os.walk(temp_folder):
+ for html_file in fnmatch.filter(files, '*.html'):
+ html_file_path = os.path.join(root, html_file)
+ pdf_file_name = '%s.pdf' % os.path.splitext(html_file)[0]
+ pdf_file_path = os.path.join(root, pdf_file_name)
+
+ archive.write(
+ convert_html_to_pdf(html_file_path, pdf_file_path),
+ os.path.relpath(pdf_file_path, temp_folder))
+
+ archive.close()
+ logger.info('Removing temp dir: %s' % (temp_folder))
+ shutil.rmtree(temp_folder)
+
+ return output.getvalue()