1.1 --- a/actions/ExportPDF.py Thu Oct 31 23:46:00 2013 +0100
1.2 +++ b/actions/ExportPDF.py Fri Nov 01 01:45:00 2013 +0100
1.3 @@ -10,7 +10,7 @@
1.4 from MoinMoin.wikiutil import escape
1.5 from MoinSupport import ActionSupport, escattr, getFormatterClass, formatText, get_send_headers
1.6 from os.path import join
1.7 -import subprocess
1.8 +import subprocess, os, codecs
1.9
1.10 __version__ = "0.1"
1.11
1.12 @@ -18,24 +18,35 @@
1.13
1.14 # Configuration settings.
1.15
1.16 +# Choose one value for the export mode.
1.17 +
1.18 +PDF_EXPORT_MODE = "docbook"
1.19 +#PDF_EXPORT_MODE = "htmldoc"
1.20 +
1.21 +# Settings for "docbook" mode.
1.22 +
1.23 XSLT_PROCESSOR = "/usr/bin/xsltproc"
1.24 FO_PROCESSOR = "/usr/bin/fop"
1.25 DOCBOOK_STYLESHEET_BASE = "/usr/share/xml/docbook/stylesheet"
1.26
1.27 -# Tool settings.
1.28 +# Tool settings for "docbook" mode.
1.29
1.30 DOCBOOK_TO_FO_STYLESHEET = "docbook-xsl/fo/docbook.xsl"
1.31
1.32 +# Settings for "htmldoc" mode.
1.33 +
1.34 +HTMLDOC_PROCESSOR = "/usr/bin/htmldoc"
1.35 +
1.36 # NOTE: From docbook-xsl/fo/param.xsl.
1.37
1.38 -paper_sizes = [
1.39 +docbook_paper_sizes = [
1.40 "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "A10",
1.41 "B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "B10",
1.42 "C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "C10",
1.43 "A4landscape", "USletter", "USlandscape", "4A0", "2A0",
1.44 ]
1.45
1.46 -paper_size_labels = {
1.47 +docbook_paper_size_labels = {
1.48 "A4landscape" : "A4 landscape",
1.49 "USletter" : "US letter",
1.50 "USlandscape" : "US landscape",
1.51 @@ -43,10 +54,37 @@
1.52 "2A0" : "Double A0"
1.53 }
1.54
1.55 +# NOTE: From the htmldoc man page.
1.56 +
1.57 +htmldoc_paper_sizes = [
1.58 + "a4", "legal", "letter", "universal"
1.59 + ]
1.60 +
1.61 +htmldoc_paper_size_labels = {
1.62 + "a4" : "A4",
1.63 + "legal" : "US legal",
1.64 + "letter" : "US letter",
1.65 + "universal" : "US universal"
1.66 + }
1.67 +
1.68 class ExportPDF(ActionBase, ActionSupport):
1.69
1.70 "Export the current page as PDF."
1.71
1.72 + mode = PDF_EXPORT_MODE
1.73 +
1.74 + def _get_paper_sizes(self):
1.75 + if self.mode == "docbook":
1.76 + return docbook_paper_sizes
1.77 + else:
1.78 + return htmldoc_paper_sizes
1.79 +
1.80 + def _get_paper_size_labels(self):
1.81 + if self.mode == "docbook":
1.82 + return docbook_paper_size_labels
1.83 + else:
1.84 + return htmldoc_paper_size_labels
1.85 +
1.86 def get_form_html(self, buttons_html):
1.87
1.88 "Return the action's form incorporating the 'buttons_html'."
1.89 @@ -58,8 +96,9 @@
1.90 paper_size = form.get("paper-size", ["A4"])[0]
1.91
1.92 paper_size_options = []
1.93 + paper_size_labels = self._get_paper_size_labels()
1.94
1.95 - for size in paper_sizes:
1.96 + for size in self._get_paper_sizes():
1.97 paper_size_options.append('<option value="%s" %s>%s</option>' % (
1.98 escattr(size), self._get_selected(size, paper_size),
1.99 escape(_(paper_size_labels.get(size) or size))
1.100 @@ -89,15 +128,79 @@
1.101 "Attempt to post a comment."
1.102
1.103 _ = self._
1.104 - request = self.request
1.105 form = self.get_form()
1.106 - page = self.page
1.107
1.108 paper_size = form.get("paper-size", [""])[0]
1.109
1.110 - if not paper_size in paper_sizes:
1.111 + if not paper_size in self._get_paper_sizes():
1.112 return 0, _("A paper size must be chosen.")
1.113
1.114 + if self.mode == "docbook":
1.115 + return self._export_using_docbook(paper_size)
1.116 + elif self.mode == "htmldoc":
1.117 + return self._export_using_htmldoc(paper_size)
1.118 + else:
1.119 + return 0, _("The action must be configured to use a particular PDF generation tool.")
1.120 +
1.121 + def _export_using_htmldoc(self, paper_size):
1.122 +
1.123 + request = self.request
1.124 + page = self.page
1.125 +
1.126 + # Get the page in HTML format.
1.127 +
1.128 + fmt = getFormatterClass(request, "text_html")(request)
1.129 + fmt.setPage(page)
1.130 +
1.131 + page_as_html = []
1.132 + append = page_as_html.append
1.133 +
1.134 + append("""\
1.135 +<html>
1.136 +<head>
1.137 +<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
1.138 +</head>
1.139 +<body>
1.140 +""")
1.141 + append(formatText(page.get_raw_body(), request, fmt, inhibit_p=False))
1.142 + append("""\
1.143 +</body>
1.144 +</html>
1.145 +""")
1.146 +
1.147 + # Send the HTML to the htmldoc processor.
1.148 +
1.149 + os.environ["HTMLDOC_NOCGI"] = "1"
1.150 +
1.151 + p = subprocess.Popen([
1.152 + HTMLDOC_PROCESSOR,
1.153 + "-t", "pdf", "--quiet", "--webpage",
1.154 + "--size", paper_size,
1.155 + "-"
1.156 + ],
1.157 + shell=False,
1.158 + stdin=subprocess.PIPE,
1.159 + stdout=subprocess.PIPE,
1.160 + stderr=subprocess.PIPE)
1.161 +
1.162 + writer = codecs.getwriter("utf-8")(p.stdin)
1.163 + writer.write(u"".join(page_as_html))
1.164 +
1.165 + out, err = p.communicate()
1.166 +
1.167 + retcode = p.wait()
1.168 +
1.169 + if retcode != 0:
1.170 + return 0, err
1.171 +
1.172 + self._write_pdf(out)
1.173 + return 1, None
1.174 +
1.175 + def _export_using_docbook(self, paper_size):
1.176 +
1.177 + request = self.request
1.178 + page = self.page
1.179 +
1.180 # Get the page in DocBook format.
1.181
1.182 fmt = getFormatterClass(request, "text_docbook")(request)
1.183 @@ -155,13 +258,17 @@
1.184 if retcode != 0:
1.185 return 0, err
1.186
1.187 + self._write_pdf(out)
1.188 + return 1, None
1.189 +
1.190 + def _write_pdf(self, out):
1.191 + request = self.request
1.192 +
1.193 send_headers = get_send_headers(request)
1.194 headers = ["Content-Type: application/pdf"]
1.195 send_headers(headers)
1.196 request.write(out)
1.197
1.198 - return 1, None
1.199 -
1.200 def render_success(self, msg, msgtype=None):
1.201
1.202 """