Zim

Merge lp:~johannes-reinhardt/zim/latex into lp:~jaap.karssenberg/zim/pyzim

Proposed by Johannes Reinhardt
Status: Merged
Merged at revision: not available
Proposed branch: lp:~johannes-reinhardt/zim/latex
Merge into: lp:~jaap.karssenberg/zim/pyzim
Diff against target: 649 lines (+383/-37)
15 files modified
data/manual/Help/Export.txt (+3/-3)
data/manual/Help/Export/HTML.txt (+37/-0)
data/manual/Help/Export/LaTeX.txt (+49/-0)
data/manual/Help/Menu_Items.txt (+1/-1)
data/manual/Help/Templates.txt (+12/-19)
data/templates/latex/article.tex (+23/-0)
data/templates/latex/part.tex (+4/-0)
data/templates/latex/report.tex (+25/-0)
tests/formats.py (+18/-0)
tests/notebook.py (+1/-0)
tests/templates.py (+1/-1)
zim/formats/__init__.py (+4/-3)
zim/formats/latex.py (+181/-0)
zim/gui/exportdialog.py (+4/-2)
zim/templates.py (+20/-8)
To merge this branch: bzr merge lp:~johannes-reinhardt/zim/latex
Reviewer Review Type Date Requested Status
Jaap Karssenberg Approve
Review via email: mp+20814@code.launchpad.net

Description of the change

This branch implements basic LaTeX export. Also templates can now set options in the dumper via template options.

To post a comment you must log in.
Revision history for this message
Jaap Karssenberg (jaap.karssenberg) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory 'data/manual/Help/Export'
2=== modified file 'data/manual/Help/Export.txt'
3--- data/manual/Help/Export.txt 2010-01-19 18:41:47 +0000
4+++ data/manual/Help/Export.txt 2010-03-06 12:44:20 +0000
5@@ -4,13 +4,13 @@
6
7 ====== Exporting ======
8
9-Zim will be able to export content to various formats but at the moment only exporting to (simple) Html is supported.
10+Zim will be able to export content to various formats. At the moment only exporting to (simple) [[Help:Export:HTML|HTML]] and [[Help:Export:LaTeX|LaTeX]] is supported.
11
12 To open op the export dialog in zim use the "//File//->//Export//" menu item. This dialog asks for a number of input fields before you can start exporting.
13
14 Under **Pages** you can check "Complete notebook" if you want to export all the pages in the notebook.
15
16-The **Format** is fixed on "Html" for now. Later other options will be added here.
17+The **Format** allows the choice of the output format.
18
19 The **Template** field asks you to select a template file (see below). When you select "''Other...''" in the combo box you can browse for another file in the input field below the combo box.
20
21@@ -23,7 +23,7 @@
22 TODO explain document root somewhere
23
24 ===== Templates =====
25-The export code only produces the tags that represent the content of the page. It does not add elements like a <head> section. [[Templates]] are used to create complete Html pages. A few standard templates are packaged with zim, but you can also make your own.
26+The export code only produces the tags that represent the content of the page. [[Templates]] are used to create complete output. A few standard templates are packaged with zim, see the pages for the output formats for a list and descriptions. You can also make your own.
27
28 ===== Exporting from the commandline =====
29 Try something like:
30
31=== added file 'data/manual/Help/Export/HTML.txt'
32--- data/manual/Help/Export/HTML.txt 1970-01-01 00:00:00 +0000
33+++ data/manual/Help/Export/HTML.txt 2010-03-06 12:44:20 +0000
34@@ -0,0 +1,37 @@
35+Content-Type: text/x-zim-wiki
36+Wiki-Format: zim 0.4
37+Creation-Date: 2010-03-02T11:46:37.806083
38+
39+====== HTML ======
40+Created Dienstag 02 März 2010
41+
42+
43+===== Dependencies =====
44+
45+No dependencies.
46+
47+===== Templates =====
48+
49+**"Default"**
50+This is a simple template intended as a base for custom styles. It has an inline style definition that is intended to match the (default) look of zim.
51+
52+**"Presentation"**
53+Template with a little more color than "Default". It is intended to convert a set of pages in an online presentation quickly. Simple javascript included for some basic keybindings:
54+
55+'''
56+Enter next page
57+Spacebar next page
58+backspace previous page
59+'''
60+
61+**"Print"**
62+This is a plain template intended for printing pages. It is use by the "Print to Browser" plugin.
63+
64+**"SlideShow (S5)"**
65+Template based on S5. S5 is "A Simple Standards-Based Slide Show System", which mean a slide show system completely written in html and javascript. Therefor these slide shows can be presented using a browser and be put on a website. See [[http://meyerweb.com/eric/tools/s5/|the S5 website]] for more information.
66+
67+Note that in order to use the output from this template you need to download the S5 package and copy the "ui" directory from the package to the same directory where you export your slideshow to.
68+
69+===== Template Options =====
70+
71+No template options available.
72
73=== added file 'data/manual/Help/Export/LaTeX.txt'
74--- data/manual/Help/Export/LaTeX.txt 1970-01-01 00:00:00 +0000
75+++ data/manual/Help/Export/LaTeX.txt 2010-03-06 12:44:20 +0000
76@@ -0,0 +1,49 @@
77+Content-Type: text/x-zim-wiki
78+Wiki-Format: zim 0.4
79+Creation-Date: 2010-03-02T11:46:43.066508
80+
81+====== LaTeX ======
82+Created Dienstag 02 März 2010
83+
84+The [[Plugins:Equation Editor|Equation Editor]] plugin is supported, equations entered with this plugin are automatically placed inside math environments. Embedded Images of types that are not supported by the TeX Engine of your choice may lead to compilation errors. For ''pdflatex'' the supported types are PDF, JPG, JBIG2, and PNG, for ''latex'' it is EPS. Index creation is currently not working.
85+
86+===== Dependencies =====
87+
88+All templates depend on several LaTeX packages
89+* ''inputenc'' package to use utf8 as input encoding.
90+* ''hyperref'' to realize links (or another appropriate definition for ''\href)''
91+* ''graphicx'' for including images
92+* ''amsmath, amssymb, color'' are needed for support of the equationeditor plugin
93+* ''ulem'' is used for underlines and strikeouts
94+
95+===== Templates =====
96+
97+The following templates are supplied:
98+
99+**"Report"**
100+
101+This templates is based (and depends) on the KOMA-Script Report Class ''scrreprt''. It generates a title page and a table of contents and is therefore more suitable for longer pages. To display checkboxes it depends on the ''wasysym'' package.
102+
103+**"Article"**
104+
105+This templates is based (and depends) on the KOMA-Script Report Class ''scrartcl''. It omits the lowest heading and is therefore not suitable for deeply structured documents. To display checkboxes it depends on the ''wasysym'' package.
106+
107+**"Part"**
108+
109+The result from this template can not be compiled on its own, it is designed to be one part of a larger document and be ''\include{}''ded in a master document.
110+
111+===== Template Options =====
112+
113+=== document_type ===
114+
115+Possible values: 'report', 'article', 'book'
116+Default: 'report'
117+
118+The exported LaTeX code will use only commands suitable for the given document class (e.g. sectioning commands).
119+
120+
121+
122+
123+
124+
125+
126
127=== modified file 'data/manual/Help/Menu_Items.txt'
128--- data/manual/Help/Menu_Items.txt 2010-01-19 18:41:47 +0000
129+++ data/manual/Help/Menu_Items.txt 2010-03-06 12:44:20 +0000
130@@ -164,7 +164,7 @@
131 **Equation**
132 Prompt for an equation written in latex and insert it as an image.
133
134-Only available if the [[Plugins:Equation Editor|Equation Editor plugin]] is enabled.
135+Only available if the [[:Plugins:Equation Editor|Equation Editor plugin]] is enabled.
136
137 **Diagram**
138 Prompt for an diagram defined in the dot language and insert it as an image.
139
140=== modified file 'data/manual/Help/Templates.txt'
141--- data/manual/Help/Templates.txt 2010-01-19 18:41:47 +0000
142+++ data/manual/Help/Templates.txt 2010-03-06 12:44:20 +0000
143@@ -9,25 +9,11 @@
144
145 ===== Templates for export =====
146
147-**"Default"**
148-This is a simple template intended as a base for custom styles. It has an inline style definition that is intended to match the (default) look of zim.
149-
150-**"Presentation"**
151-Template with a little more color than "Default". It is intended to convert a set of pages in an online presentation quickly. Simple javascript included for some basic keybindings:
152-
153-'''
154-Enter next page
155-Spacebar next page
156-backspace previous page
157-'''
158-
159-**"Print"**
160-This is a plain template intended for printing pages. It is use by the "Print to Browser" plugin.
161-
162-**"SlideShow (S5)"**
163-Template based on S5. S5 is "A Simple Standards-Based Slide Show System", which mean a slide show system completely written in html and javascript. Therefor these slide shows can be presented using a browser and be put on a website. See [[http://meyerweb.com/eric/tools/s5/|the S5 website]] for more information.
164-
165-Note that in order to use the output from this template you need to download the S5 package and copy the "ui" directory from the package to the same directory where you export your slideshow to.
166+For a list of templates for exporting see [[Help:Export]] and subpages.
167+
168+===== Template options =====
169+
170+Templates can also set template options that influence the generated output, by setting key-value pairs like in the example below. A list of available template options for a output format can be found at [[Help:Export]] and subpages.
171
172 ===== Special templates =====
173
174@@ -40,6 +26,8 @@
175
176 Template syntax:
177
178+
179+
180 '''
181 [% var %] # interpolates a variable
182
183@@ -59,6 +47,11 @@
184 [% strftime("%c", var) %] # date from variable
185 '''
186
187+
188+'''
189+[% options.option_name = value %] # set the template option option_name to value
190+'''
191+
192 Available variables:
193
194 '''
195
196=== added directory 'data/templates/latex'
197=== added file 'data/templates/latex/article.tex'
198--- data/templates/latex/article.tex 1970-01-01 00:00:00 +0000
199+++ data/templates/latex/article.tex 2010-03-06 12:44:20 +0000
200@@ -0,0 +1,23 @@
201+\documentclass{scrartcl}
202+\usepackage[utf8]{inputenc}
203+\usepackage{amssymb}
204+\usepackage{amsmath}
205+\usepackage[usenames]{color}
206+\usepackage{hyperref}
207+\usepackage{wasysym}
208+\usepackage{graphicx}
209+\usepackage{ulem}
210+
211+[% options.document_type = 'article' %]
212+
213+\title{[% page.basename %]}
214+\date{[% strftime("%A %d %B %Y") %]}
215+\author{}
216+
217+\begin{document}
218+
219+\maketitle
220+
221+[% page.body %]
222+
223+\end{document}
224
225=== added file 'data/templates/latex/part.tex'
226--- data/templates/latex/part.tex 1970-01-01 00:00:00 +0000
227+++ data/templates/latex/part.tex 2010-03-06 12:44:20 +0000
228@@ -0,0 +1,4 @@
229+[% options.document_type = 'report' %]
230+\part{[% page.basename %]}
231+
232+[% page.body %]
233
234=== added file 'data/templates/latex/report.tex'
235--- data/templates/latex/report.tex 1970-01-01 00:00:00 +0000
236+++ data/templates/latex/report.tex 2010-03-06 12:44:20 +0000
237@@ -0,0 +1,25 @@
238+\documentclass{scrreprt}
239+\usepackage[utf8]{inputenc}
240+\usepackage{amssymb}
241+\usepackage{amsmath}
242+\usepackage[usenames]{color}
243+\usepackage{hyperref}
244+\usepackage{wasysym}
245+\usepackage{graphicx}
246+\usepackage{ulem}
247+
248+[% options.document_type = 'report' %]
249+
250+\title{[% page.basename %]}
251+\date{[% strftime("%A %d %B %Y") %]}
252+\author{}
253+
254+\begin{document}
255+
256+\maketitle
257+
258+\tableofcontents
259+
260+[% page.body %]
261+
262+\end{document}
263
264=== modified file 'tests/formats.py'
265--- tests/formats.py 2010-01-09 20:54:09 +0000
266+++ tests/formats.py 2010-03-06 12:44:20 +0000
267@@ -347,6 +347,24 @@
268 self.assertEqualDiff(output, html.splitlines(True))
269
270
271+class TestLatexFormat(TestCase):
272+
273+ def testEncode(self):
274+ '''test the escaping of certain characters'''
275+ format = get_format('latex')
276+
277+ input = r'\foo $ % ^ \% bar'
278+ wanted = r'$\backslash$foo \$ \% \^{} $\backslash$\% bar'
279+ self.assertEqual(format.tex_encode(input), wanted)
280+
281+ def testExport(self):
282+ '''test the export of a wiki page to latex'''
283+ format = get_format('LaTeX')
284+ testpage = get_test_data_page('wiki','Test:wiki')
285+ tree = get_format('wiki').Parser().parse(testpage)
286+ output = format.Dumper(linker=StubLinker()).dump(tree)
287+ # TODO test template_options.document_type
288+
289 class StubLinker(object):
290
291 def set_usebase(self, usebase): pass
292
293=== modified file 'tests/notebook.py'
294--- tests/notebook.py 2010-01-17 21:28:14 +0000
295+++ tests/notebook.py 2010-03-06 12:44:20 +0000
296@@ -141,6 +141,7 @@
297 self.assertTrue(isinstance(page, Page))
298 index.add(page.name)
299 self.assertTrue(index.issuperset(self.notebook.testdata_manifest))
300+ print str(self.notebook.testdata_manifest)
301
302 def testManipulate(self):
303 '''Test renaming, moving and deleting pages in the notebook'''
304
305=== modified file 'tests/templates.py'
306--- tests/templates.py 2009-12-30 10:57:25 +0000
307+++ tests/templates.py 2010-03-06 12:44:20 +0000
308@@ -143,7 +143,7 @@
309 **foo bar !**
310 ''')
311 self.assertTrue(len(page.dump('html', linker=StubLinker())) > 0)
312- proxy = PageProxy(Notebook(), page, zim.formats.get_format('html'), StubLinker())
313+ proxy = PageProxy(Notebook(), page, zim.formats.get_format('html'), StubLinker(), {})
314 self.assertEqual(proxy.name, page.name)
315 self.assertEqual(proxy.namespace, page.namespace)
316 self.assertEqual(proxy.basename, page.basename)
317
318=== modified file 'zim/formats/__init__.py'
319--- zim/formats/__init__.py 2010-02-22 21:34:10 +0000
320+++ zim/formats/__init__.py 2010-03-06 12:44:20 +0000
321@@ -28,7 +28,7 @@
322 * link for links, attribute href gives the target
323 * img for images, attributes src, width, height an optionally href
324 * any text set on these elements should be rendered as alt
325- * class can be used to control plugin functionality, e.g. class=latex-equation
326+ * type can be used to control plugin functionality, e.g. type=equation
327
328 Unlike html we respect line breaks and other whitespace as is.
329 When rendering as html use the "white-space: pre" CSS definition to
330@@ -93,7 +93,7 @@
331
332 def list_formats(type):
333 if type == EXPORT_FORMAT:
334- return ['HTML']
335+ return ['HTML','LaTeX']
336 else:
337 assert False, 'TODO'
338
339@@ -507,8 +507,9 @@
340 'Dumper' which inherits from this base class.
341 '''
342
343- def __init__(self, linker=None):
344+ def __init__(self, linker=None, template_options=None):
345 self.linker = linker
346+ self.template_options = template_options or {}
347
348 def dump(self, tree):
349 '''ABSTRACT METHOD needs to be overloaded by sub-classes.
350
351=== added file 'zim/formats/latex.py'
352--- zim/formats/latex.py 1970-01-01 00:00:00 +0000
353+++ zim/formats/latex.py 2010-03-06 12:44:20 +0000
354@@ -0,0 +1,181 @@
355+# TODO: Licence Header and Copyright
356+
357+'''This modules handles export of LaTeX Code'''
358+
359+import re
360+
361+from zim.formats import *
362+from zim.parsing import TextBuffer, url_re
363+
364+info = {
365+ 'name': 'LaTeX',
366+ 'mime': 'application/x-tex',
367+ 'extension': 'tex',
368+ 'read': False,
369+ 'write': False,
370+ 'import': False,
371+ 'export': True,
372+}
373+
374+# reverse dict
375+bullet_types = {
376+ UNCHECKED_BOX : '\\item[\\Square] ',
377+ XCHECKED_BOX : '\\item[\\XBox] ',
378+ CHECKED_BOX : '\\item[\\CheckedBox] ',
379+ BULLET : '\\item ',
380+}
381+
382+sectioning = {
383+ 'report': {
384+ 1:'\\chapter{%s}',
385+ 2:'\\section{%s}',
386+ 3:'\\subsection{%s}',
387+ 4:'\\subsubsection{%s}',
388+ 5:'\\paragraph{%s}'
389+ },
390+ 'article': {
391+ 1:'\\section{%s}',
392+ 2:'\\subsection{%s}',
393+ 3:'\\subsubsection{%s}',
394+ 4:'\\paragraph{%s}',
395+ 5:'\\subparagraph{%s}'
396+ },
397+ 'book': {
398+ 1:'\\part{%s}',
399+ 2:'\\chapter{%s}',
400+ 3:'\\section{%s}',
401+ 4:'\\subsection{%s}',
402+ 5:'\\subsubsection{%s}'
403+ }
404+}
405+
406+
407+
408+encode_re = re.compile(r'(\&|\$|\^|\%|\#|\_|\\)')
409+encode_dict = {
410+ '\\': '$\\backslash$',
411+ '&': '\\$',
412+ '$': '\\$ ',
413+ '^': '\\^{}',
414+ '%': '\\%',
415+ '#': '\\# ',
416+ '_': '\\_',
417+}
418+
419+
420+def tex_encode(text):
421+ if not text is None:
422+ return encode_re.sub(lambda m: encode_dict[m.group(1)], text)
423+ else:
424+ return ''
425+
426+
427+class Dumper(DumperClass):
428+
429+ def dump(self, tree):
430+ assert isinstance(tree, ParseTree)
431+ assert self.linker, 'LaTeX dumper needs a linker object'
432+ self.linker.set_usebase(False)
433+
434+ self.document_type = self.template_options.get('document_type')
435+ # Option set in template - potentially tainted value
436+ if not self.document_type in ('report', 'article','book'):
437+ self.document_type = 'report' # arbitrary default
438+
439+ logger.info('used document type: %s'%self.document_type)
440+
441+ output = TextBuffer()
442+ self.dump_children(tree.getroot(), output)
443+ return output.get_lines()
444+
445+ def dump_children(self, list, output, list_level = -1):
446+ if list.text:
447+ output.append(tex_encode(list.text))
448+
449+ for element in list.getchildren():
450+ text = tex_encode(element.text)
451+ if element.tag == 'p':
452+ if 'indent' in element.attrib:
453+ indent = int(element.attrib['indent'])
454+ else:
455+ indent = 0
456+ myoutput = TextBuffer()
457+ self.dump_children(element,myoutput)
458+ if indent:
459+ myoutput.prefix_lines('\t'*indent)
460+ output.extend(myoutput)
461+ elif element.tag == 'ul':
462+ output.append('\\begin{itemize}\n')
463+ self.dump_children(element,output,list_level=list_level+1)
464+ output.append('\\end{itemize}')
465+ elif element.tag == 'h':
466+ level = int(element.attrib['level'])
467+ if level < 1: level = 1
468+ elif level > 5: level = 5
469+ output.append(sectioning[self.document_type][level]%(text))
470+ elif element.tag == 'li':
471+ if 'indent' in element.attrib:
472+ list_level = int(element.attrib['indent'])
473+ if 'bullet' in element.attrib:
474+ bullet = bullet_types[element.attrib['bullet']]
475+ else:
476+ bullet = bullet_types[BULLET]
477+ output.append('\t'*list_level+bullet)
478+ self.dump_children(element, output, list_level=list_level) # recurse
479+ output.append('\n')
480+ elif element.tag == 'pre':
481+ output.append('\n\\begin{verbatim}\n')
482+ output.append(element.text)
483+ output.append('\n\\end{verbatim}\n')
484+ elif element.tag == 'img':
485+ #we try to get images about the same visual size, therefore need to specify dot density
486+ #96 dpi seems to be common for computer monitors
487+ dpi = 96
488+ if 'type' in element.attrib:
489+ if element.attrib['type'] == 'equation':
490+ eqpath = self.linker.link(element.attrib['src'])
491+ eqfid = open(eqpath[6:-4] + '.tex','r')
492+ output.append('\\begin{math}\n')
493+ output.extend(eqfid.readlines())
494+ output.append('\n\\end{math}')
495+ eqfid.close()
496+ elif element.attrib['type'] == 'None':
497+ if 'width' in element.attrib and not 'height' in element.attrib:
498+ options = 'width=%fin, keepaspectratio=true'%(float(element.attrib['width'])/dpi)
499+ elif 'height' in element.attrib and not 'width' in element.attrib:
500+ options = 'height=%fin, keepaspectratio=true'%(float(element.attrib['height'])/dpi)
501+ else:
502+ options = ''
503+
504+ image = '\\includegraphics[%s]{%s}'%(options,self.linker.link(element.attrib['src'])[6:])
505+ if 'href' in element.attrib:
506+ output.append('\\href{%s}{%s}'%(element.attrib['href'],image))
507+ else:
508+ output.append(image)
509+ elif element.tag == 'link':
510+ href = self.linker.link(element.attrib['href'])
511+ output.append('\\href{%s}{%s}\n' % (href, text))
512+ elif element.tag == 'emphasis':
513+ output.append('\\emph{'+text+'}')
514+ elif element.tag == 'strong':
515+ output.append('\\textbf{'+text+'}')
516+ elif element.tag == 'mark':
517+ output.append('\\underline{'+text+'}')
518+ elif element.tag == 'strike':
519+ output.append('\\sout{'+text+'}')
520+ elif element.tag == 'code':
521+ success = False
522+ #Here we try several possible delimiters for the inline verb command of LaTeX
523+ for delim in '+*|$&%!-_':
524+ if not delim in text:
525+ success = True
526+ output.append('\\verb'+delim+text+delim)
527+ break
528+ if not success:
529+ assert False, 'Found no suitable delimiter for verbatim text: %s' % element
530+ pass
531+ else:
532+ assert False, 'Unknown node type: %s' % element
533+
534+ if element.tail:
535+ output.append(tex_encode(element.tail))
536
537=== modified file 'zim/gui/exportdialog.py'
538--- zim/gui/exportdialog.py 2009-12-08 21:15:20 +0000
539+++ zim/gui/exportdialog.py 2010-03-06 12:44:20 +0000
540@@ -69,7 +69,9 @@
541 # Template
542 def set_templates(formats_combobox, templates_combobox):
543 format = formats_combobox.get_active_text()
544- # TODO clear templates_combobox
545+ #clear combobox
546+ templates_model = templates_combobox.get_model()
547+ templates_model.clear()
548 template_dict = zim.templates.list_templates(format)
549 templates = sorted(template_dict.keys())
550 for name in templates:
551@@ -85,7 +87,7 @@
552 i = templates.index(template)
553 templates_combobox.set_active(i)
554 except ValueError:
555- pass
556+ templates_combobox.set_active(0)
557
558 table.attach(gtk.Label(_('Template')+': '), 0,1, 1,2)
559 # T: Label for template selection in export dialog
560
561=== modified file 'zim/templates.py'
562--- zim/templates.py 2009-12-24 10:30:47 +0000
563+++ zim/templates.py 2010-03-06 12:44:20 +0000
564@@ -59,6 +59,7 @@
565 import re
566 import logging
567 from time import strftime, strptime
568+from copy import deepcopy
569
570 import zim
571 import zim.formats
572@@ -206,9 +207,9 @@
573 token = GETToken(string[3:])
574 elif self._token_re.match(string):
575 raise TemplateSyntaxError, 'Unknown directive: %s' % self._token_re[1]
576- elif string.find('=') >= 0: # imlpicite SET
577+ elif string.find('=') >= 0: # implicit SET
578 token = SETToken(string)
579- else: # imlicite GET
580+ else: # implicit GET
581 token = GETToken(string)
582 self.stack[-1].append(token)
583
584@@ -255,18 +256,23 @@
585 '''Processes the template with a dict giving a set a standard
586 parameters for 'page' and returns a list of lines.
587 '''
588+ options = {} # this dict is accesible from the template and is
589+ # passed on to the format
590 dict = {
591 'zim': { 'version': zim.__version__ },
592- 'page': PageProxy(notebook, page, self.format, self.linker),
593+ 'page': PageProxy(
594+ notebook, page,
595+ self.format, self.linker, options),
596 'strftime': TemplateFunction(self.strftime),
597- 'url': TemplateFunction(self.url)
598+ 'url': TemplateFunction(self.url),
599+ 'options': options
600 }
601 output = GenericTemplate.process(self, dict)
602
603 # Caching last processed dict because any pages in the dict
604 # will be cached using a weakref dict. Assuming we process multiple
605 # pages after each other, and they share links like home / previous /
606- # next etc. this will is a cheap optimization.
607+ # next etc. this is a cheap optimization.
608 self._last_dict = dict
609 return output
610
611@@ -582,13 +588,14 @@
612 class PageProxy(object):
613 '''Exposes a single page object to the template.'''
614
615- def __init__(self, notebook, page, format, linker):
616+ def __init__(self, notebook, page, format, linker, options):
617 '''Constructor takes the page object to expose and a format.'''
618 # private attributes should be shielded by the template engine
619 self._page = page
620 self._notebook = notebook
621 self._format = format
622 self._linker = linker
623+ self._options = options
624 self._treeproxy_obj = None
625
626 def _treeproxy(self):
627@@ -626,7 +633,9 @@
628 for type, name, _ in self._page.get_links():
629 if type == 'page':
630 page = self._notebook.get_page(name)
631- yield PageProxy(self._notebook, page, self._format, self._linker)
632+ yield PageProxy(
633+ self._notebook, page,
634+ self._format, self._linker, self._options)
635
636 @property
637 def backlinks(self):
638@@ -659,7 +668,10 @@
639 format = self._pageproxy._format
640 linker = self._pageproxy._linker
641 linker.set_path(self._pageproxy._page)
642- return ''.join(format.Dumper(linker=linker).dump(body))
643+ dumper = format.Dumper(
644+ linker=linker,
645+ template_options=self._pageproxy._options )
646+ return ''.join(dumper.dump(body))
647
648 def _split_head(self, tree):
649 if not hasattr(self, '_servered_head'):