# HG changeset patch # User Paul Boddie # Date 1383266700 -3600 # Node ID d785b3e054f85118d6d5897c7317736eec3c3410 # Parent bb07949085d121510ae64ae0c8037a430ea24b6a Added support for htmldoc as the PDF generation tool. diff -r bb07949085d1 -r d785b3e054f8 actions/ExportPDF.py --- a/actions/ExportPDF.py Thu Oct 31 23:46:00 2013 +0100 +++ b/actions/ExportPDF.py Fri Nov 01 01:45:00 2013 +0100 @@ -10,7 +10,7 @@ from MoinMoin.wikiutil import escape from MoinSupport import ActionSupport, escattr, getFormatterClass, formatText, get_send_headers from os.path import join -import subprocess +import subprocess, os, codecs __version__ = "0.1" @@ -18,24 +18,35 @@ # Configuration settings. +# Choose one value for the export mode. + +PDF_EXPORT_MODE = "docbook" +#PDF_EXPORT_MODE = "htmldoc" + +# Settings for "docbook" mode. + XSLT_PROCESSOR = "/usr/bin/xsltproc" FO_PROCESSOR = "/usr/bin/fop" DOCBOOK_STYLESHEET_BASE = "/usr/share/xml/docbook/stylesheet" -# Tool settings. +# Tool settings for "docbook" mode. DOCBOOK_TO_FO_STYLESHEET = "docbook-xsl/fo/docbook.xsl" +# Settings for "htmldoc" mode. + +HTMLDOC_PROCESSOR = "/usr/bin/htmldoc" + # NOTE: From docbook-xsl/fo/param.xsl. -paper_sizes = [ +docbook_paper_sizes = [ "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "A10", "B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "B10", "C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "C10", "A4landscape", "USletter", "USlandscape", "4A0", "2A0", ] -paper_size_labels = { +docbook_paper_size_labels = { "A4landscape" : "A4 landscape", "USletter" : "US letter", "USlandscape" : "US landscape", @@ -43,10 +54,37 @@ "2A0" : "Double A0" } +# NOTE: From the htmldoc man page. + +htmldoc_paper_sizes = [ + "a4", "legal", "letter", "universal" + ] + +htmldoc_paper_size_labels = { + "a4" : "A4", + "legal" : "US legal", + "letter" : "US letter", + "universal" : "US universal" + } + class ExportPDF(ActionBase, ActionSupport): "Export the current page as PDF." + mode = PDF_EXPORT_MODE + + def _get_paper_sizes(self): + if self.mode == "docbook": + return docbook_paper_sizes + else: + return htmldoc_paper_sizes + + def _get_paper_size_labels(self): + if self.mode == "docbook": + return docbook_paper_size_labels + else: + return htmldoc_paper_size_labels + def get_form_html(self, buttons_html): "Return the action's form incorporating the 'buttons_html'." @@ -58,8 +96,9 @@ paper_size = form.get("paper-size", ["A4"])[0] paper_size_options = [] + paper_size_labels = self._get_paper_size_labels() - for size in paper_sizes: + for size in self._get_paper_sizes(): paper_size_options.append('' % ( escattr(size), self._get_selected(size, paper_size), escape(_(paper_size_labels.get(size) or size)) @@ -89,15 +128,79 @@ "Attempt to post a comment." _ = self._ - request = self.request form = self.get_form() - page = self.page paper_size = form.get("paper-size", [""])[0] - if not paper_size in paper_sizes: + if not paper_size in self._get_paper_sizes(): return 0, _("A paper size must be chosen.") + if self.mode == "docbook": + return self._export_using_docbook(paper_size) + elif self.mode == "htmldoc": + return self._export_using_htmldoc(paper_size) + else: + return 0, _("The action must be configured to use a particular PDF generation tool.") + + def _export_using_htmldoc(self, paper_size): + + request = self.request + page = self.page + + # Get the page in HTML format. + + fmt = getFormatterClass(request, "text_html")(request) + fmt.setPage(page) + + page_as_html = [] + append = page_as_html.append + + append("""\ + + + + + +""") + append(formatText(page.get_raw_body(), request, fmt, inhibit_p=False)) + append("""\ + + +""") + + # Send the HTML to the htmldoc processor. + + os.environ["HTMLDOC_NOCGI"] = "1" + + p = subprocess.Popen([ + HTMLDOC_PROCESSOR, + "-t", "pdf", "--quiet", "--webpage", + "--size", paper_size, + "-" + ], + shell=False, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + + writer = codecs.getwriter("utf-8")(p.stdin) + writer.write(u"".join(page_as_html)) + + out, err = p.communicate() + + retcode = p.wait() + + if retcode != 0: + return 0, err + + self._write_pdf(out) + return 1, None + + def _export_using_docbook(self, paper_size): + + request = self.request + page = self.page + # Get the page in DocBook format. fmt = getFormatterClass(request, "text_docbook")(request) @@ -155,13 +258,17 @@ if retcode != 0: return 0, err + self._write_pdf(out) + return 1, None + + def _write_pdf(self, out): + request = self.request + send_headers = get_send_headers(request) headers = ["Content-Type: application/pdf"] send_headers(headers) request.write(out) - return 1, None - def render_success(self, msg, msgtype=None): """