##// END OF EJS Templates
Adding citation support.
Brian E. Granger -
Show More
@@ -0,0 +1,70 b''
1 """Citation handling for LaTeX output."""
2
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2013, the IPython Development Team.
5 #
6 # Distributed under the terms of the Modified BSD License.
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
10
11 #-----------------------------------------------------------------------------
12 # Code
13 #-----------------------------------------------------------------------------
14
15
16 __all__ = ['parse_citation']
17
18
19 def parse_citation(s):
20 """Parse citations in Markdown cells.
21
22 This looks for HTML tags having a data attribute names `data-cite`
23 and replaces it by the call to LaTeX cite command. The tranformation
24 looks like this:
25
26 `<cite data-cite="granger">(Granger, 2013)</cite>`
27
28 Becomes
29
30 `\\cite{granger}`
31
32 Any HTML tag can be used, which allows the citations to be formatted
33 in HTML in any manner.
34 """
35 try:
36 from lxml import html
37 except ImportError:
38 return s
39
40 tree = html.fragment_fromstring(s, create_parent='div')
41 _process_node_cite(tree)
42 s = html.tostring(tree)
43 s = s.lstrip('<div>')
44 s = s.rstrip('</div>')
45 return s
46
47
48 def _process_node_cite(node):
49 """Do the citation replacement as we walk the lxml tree."""
50
51 def _get(o, name):
52 value = getattr(o, name)
53 return '' if value is None else value
54
55 if 'data-cite' in node.attrib:
56 cite = '\cite{%(ref)s}' % {'ref': node.attrib['data-cite']}
57 prev = node.getprevious()
58 if prev is not None:
59 prev.tail = _get(prev, 'tail') + cite + _get(node, 'tail')
60 else:
61 parent = node.getparent()
62 if parent is not None:
63 parent.text = _get(parent, 'text') + cite + _get(node, 'tail')
64 try:
65 node.getparent().remove(node)
66 except AttributeError:
67 pass
68 else:
69 for child in node:
70 _process_node_cite(child)
@@ -0,0 +1,54 b''
1 #-----------------------------------------------------------------------------
2 # Copyright (c) 2013, the IPython Development Team.
3 #
4 # Distributed under the terms of the Modified BSD License.
5 #
6 # The full license is in the file COPYING.txt, distributed with this software.
7 #-----------------------------------------------------------------------------
8
9 #-----------------------------------------------------------------------------
10 # Imports
11 #-----------------------------------------------------------------------------
12
13 from ..citation import parse_citation
14
15 #-----------------------------------------------------------------------------
16 # Tests
17 #-----------------------------------------------------------------------------
18
19 test_md = """
20 # My Heading
21
22 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus ac magna non augue
23 porttitor scelerisque ac id diam <cite data-cite="granger">Granger</cite>. Mauris elit
24 velit, lobortis sed interdum at, vestibulum vitae libero <strong data-cite="fperez">Perez</strong>.
25 Lorem ipsum dolor sit amet, consectetur adipiscing elit
26 <em data-cite="takluyver">Thomas</em>. Quisque iaculis ligula ut ipsum mattis viverra.
27
28 * One <cite data-cite="jdfreder">Jonathan</cite>.
29 * Two <cite data-cite="carreau">Matthias</cite>.
30 * Three <cite data-cite="ivanov">Paul</cite>.
31 """
32
33 test_md_parsed = """
34 # My Heading
35
36 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus ac magna non augue
37 porttitor scelerisque ac id diam \cite{granger}. Mauris elit
38 velit, lobortis sed interdum at, vestibulum vitae libero \cite{fperez}.
39 Lorem ipsum dolor sit amet, consectetur adipiscing elit
40 \cite{takluyver}. Quisque iaculis ligula ut ipsum mattis viverra.
41
42 * One \cite{jdfreder}.
43 * Two \cite{carreau}.
44 * Three \cite{ivanov}.
45 """
46
47 def test_parse_citation():
48 """Are citations parsed properly?"""
49 try:
50 import lxml
51 except ImportError:
52 assert test_md == parse_citation(test_md)
53 else:
54 assert test_md_parsed == parse_citation(test_md)
@@ -1,518 +1,519 b''
1 """This module defines Exporter, a highly configurable converter
1 """This module defines Exporter, a highly configurable converter
2 that uses Jinja2 to export notebook files into different formats.
2 that uses Jinja2 to export notebook files into different formats.
3 """
3 """
4
4
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
6 # Copyright (c) 2013, the IPython Development Team.
7 #
7 #
8 # Distributed under the terms of the Modified BSD License.
8 # Distributed under the terms of the Modified BSD License.
9 #
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16
16
17 from __future__ import print_function, absolute_import
17 from __future__ import print_function, absolute_import
18
18
19 # Stdlib imports
19 # Stdlib imports
20 import io
20 import io
21 import os
21 import os
22 import inspect
22 import inspect
23 import copy
23 import copy
24 import collections
24 import collections
25 import datetime
25 import datetime
26
26
27 # other libs/dependencies
27 # other libs/dependencies
28 from jinja2 import Environment, FileSystemLoader, ChoiceLoader, TemplateNotFound
28 from jinja2 import Environment, FileSystemLoader, ChoiceLoader, TemplateNotFound
29
29
30 # IPython imports
30 # IPython imports
31 from IPython.config.configurable import LoggingConfigurable
31 from IPython.config.configurable import LoggingConfigurable
32 from IPython.config import Config
32 from IPython.config import Config
33 from IPython.nbformat import current as nbformat
33 from IPython.nbformat import current as nbformat
34 from IPython.utils.traitlets import MetaHasTraits, DottedObjectName, Unicode, List, Dict, Any
34 from IPython.utils.traitlets import MetaHasTraits, DottedObjectName, Unicode, List, Dict, Any
35 from IPython.utils.importstring import import_item
35 from IPython.utils.importstring import import_item
36 from IPython.utils.text import indent
36 from IPython.utils.text import indent
37 from IPython.utils import py3compat
37 from IPython.utils import py3compat
38
38
39 from IPython.nbconvert import preprocessors as nbpreprocessors
39 from IPython.nbconvert import preprocessors as nbpreprocessors
40 from IPython.nbconvert import filters
40 from IPython.nbconvert import filters
41
41
42 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
43 # Globals and constants
43 # Globals and constants
44 #-----------------------------------------------------------------------------
44 #-----------------------------------------------------------------------------
45
45
46 #Jinja2 extensions to load.
46 #Jinja2 extensions to load.
47 JINJA_EXTENSIONS = ['jinja2.ext.loopcontrols']
47 JINJA_EXTENSIONS = ['jinja2.ext.loopcontrols']
48
48
49 default_filters = {
49 default_filters = {
50 'indent': indent,
50 'indent': indent,
51 'markdown2html': filters.markdown2html,
51 'markdown2html': filters.markdown2html,
52 'ansi2html': filters.ansi2html,
52 'ansi2html': filters.ansi2html,
53 'filter_data_type': filters.DataTypeFilter,
53 'filter_data_type': filters.DataTypeFilter,
54 'get_lines': filters.get_lines,
54 'get_lines': filters.get_lines,
55 'highlight2html': filters.highlight2html,
55 'highlight2html': filters.highlight2html,
56 'highlight2latex': filters.highlight2latex,
56 'highlight2latex': filters.highlight2latex,
57 'ipython2python': filters.ipython2python,
57 'ipython2python': filters.ipython2python,
58 'posix_path': filters.posix_path,
58 'posix_path': filters.posix_path,
59 'markdown2latex': filters.markdown2latex,
59 'markdown2latex': filters.markdown2latex,
60 'markdown2rst': filters.markdown2rst,
60 'markdown2rst': filters.markdown2rst,
61 'comment_lines': filters.comment_lines,
61 'comment_lines': filters.comment_lines,
62 'strip_ansi': filters.strip_ansi,
62 'strip_ansi': filters.strip_ansi,
63 'strip_dollars': filters.strip_dollars,
63 'strip_dollars': filters.strip_dollars,
64 'strip_files_prefix': filters.strip_files_prefix,
64 'strip_files_prefix': filters.strip_files_prefix,
65 'html2text' : filters.html2text,
65 'html2text' : filters.html2text,
66 'add_anchor': filters.add_anchor,
66 'add_anchor': filters.add_anchor,
67 'ansi2latex': filters.ansi2latex,
67 'ansi2latex': filters.ansi2latex,
68 'strip_math_space': filters.strip_math_space,
68 'strip_math_space': filters.strip_math_space,
69 'wrap_text': filters.wrap_text,
69 'wrap_text': filters.wrap_text,
70 'escape_latex': filters.escape_latex,
70 'escape_latex': filters.escape_latex,
71 'parse_citation': filters.parse_citation
71 }
72 }
72
73
73 #-----------------------------------------------------------------------------
74 #-----------------------------------------------------------------------------
74 # Class
75 # Class
75 #-----------------------------------------------------------------------------
76 #-----------------------------------------------------------------------------
76
77
77 class ResourcesDict(collections.defaultdict):
78 class ResourcesDict(collections.defaultdict):
78 def __missing__(self, key):
79 def __missing__(self, key):
79 return ''
80 return ''
80
81
81
82
82 class Exporter(LoggingConfigurable):
83 class Exporter(LoggingConfigurable):
83 """
84 """
84 Exports notebooks into other file formats. Uses Jinja 2 templating engine
85 Exports notebooks into other file formats. Uses Jinja 2 templating engine
85 to output new formats. Inherit from this class if you are creating a new
86 to output new formats. Inherit from this class if you are creating a new
86 template type along with new filters/preprocessors. If the filters/
87 template type along with new filters/preprocessors. If the filters/
87 preprocessors provided by default suffice, there is no need to inherit from
88 preprocessors provided by default suffice, there is no need to inherit from
88 this class. Instead, override the template_file and file_extension
89 this class. Instead, override the template_file and file_extension
89 traits via a config file.
90 traits via a config file.
90
91
91 {filters}
92 {filters}
92 """
93 """
93
94
94 # finish the docstring
95 # finish the docstring
95 __doc__ = __doc__.format(filters = '- '+'\n - '.join(default_filters.keys()))
96 __doc__ = __doc__.format(filters = '- '+'\n - '.join(default_filters.keys()))
96
97
97
98
98 template_file = Unicode(u'default',
99 template_file = Unicode(u'default',
99 config=True,
100 config=True,
100 help="Name of the template file to use")
101 help="Name of the template file to use")
101 def _template_file_changed(self, name, old, new):
102 def _template_file_changed(self, name, old, new):
102 if new=='default':
103 if new=='default':
103 self.template_file = self.default_template
104 self.template_file = self.default_template
104 else:
105 else:
105 self.template_file = new
106 self.template_file = new
106 self.template = None
107 self.template = None
107 self._load_template()
108 self._load_template()
108
109
109 default_template = Unicode(u'')
110 default_template = Unicode(u'')
110 template = Any()
111 template = Any()
111 environment = Any()
112 environment = Any()
112
113
113 file_extension = Unicode(
114 file_extension = Unicode(
114 'txt', config=True,
115 'txt', config=True,
115 help="Extension of the file that should be written to disk"
116 help="Extension of the file that should be written to disk"
116 )
117 )
117
118
118 template_path = List(['.'], config=True)
119 template_path = List(['.'], config=True)
119 def _template_path_changed(self, name, old, new):
120 def _template_path_changed(self, name, old, new):
120 self._load_template()
121 self._load_template()
121
122
122 default_template_path = Unicode(
123 default_template_path = Unicode(
123 os.path.join("..", "templates"),
124 os.path.join("..", "templates"),
124 help="Path where the template files are located.")
125 help="Path where the template files are located.")
125
126
126 template_skeleton_path = Unicode(
127 template_skeleton_path = Unicode(
127 os.path.join("..", "templates", "skeleton"),
128 os.path.join("..", "templates", "skeleton"),
128 help="Path where the template skeleton files are located.")
129 help="Path where the template skeleton files are located.")
129
130
130 #Jinja block definitions
131 #Jinja block definitions
131 jinja_comment_block_start = Unicode("", config=True)
132 jinja_comment_block_start = Unicode("", config=True)
132 jinja_comment_block_end = Unicode("", config=True)
133 jinja_comment_block_end = Unicode("", config=True)
133 jinja_variable_block_start = Unicode("", config=True)
134 jinja_variable_block_start = Unicode("", config=True)
134 jinja_variable_block_end = Unicode("", config=True)
135 jinja_variable_block_end = Unicode("", config=True)
135 jinja_logic_block_start = Unicode("", config=True)
136 jinja_logic_block_start = Unicode("", config=True)
136 jinja_logic_block_end = Unicode("", config=True)
137 jinja_logic_block_end = Unicode("", config=True)
137
138
138 #Extension that the template files use.
139 #Extension that the template files use.
139 template_extension = Unicode(".tpl", config=True)
140 template_extension = Unicode(".tpl", config=True)
140
141
141 #Configurability, allows the user to easily add filters and preprocessors.
142 #Configurability, allows the user to easily add filters and preprocessors.
142 preprocessors = List(config=True,
143 preprocessors = List(config=True,
143 help="""List of preprocessors, by name or namespace, to enable.""")
144 help="""List of preprocessors, by name or namespace, to enable.""")
144
145
145 filters = Dict(config=True,
146 filters = Dict(config=True,
146 help="""Dictionary of filters, by name and namespace, to add to the Jinja
147 help="""Dictionary of filters, by name and namespace, to add to the Jinja
147 environment.""")
148 environment.""")
148
149
149 default_preprocessors = List([nbpreprocessors.coalesce_streams,
150 default_preprocessors = List([nbpreprocessors.coalesce_streams,
150 nbpreprocessors.SVG2PDFPreprocessor,
151 nbpreprocessors.SVG2PDFPreprocessor,
151 nbpreprocessors.ExtractOutputPreprocessor,
152 nbpreprocessors.ExtractOutputPreprocessor,
152 nbpreprocessors.CSSHTMLHeaderPreprocessor,
153 nbpreprocessors.CSSHTMLHeaderPreprocessor,
153 nbpreprocessors.RevealHelpPreprocessor,
154 nbpreprocessors.RevealHelpPreprocessor,
154 nbpreprocessors.LatexPreprocessor,
155 nbpreprocessors.LatexPreprocessor,
155 nbpreprocessors.SphinxPreprocessor],
156 nbpreprocessors.SphinxPreprocessor],
156 config=True,
157 config=True,
157 help="""List of preprocessors available by default, by name, namespace,
158 help="""List of preprocessors available by default, by name, namespace,
158 instance, or type.""")
159 instance, or type.""")
159
160
160
161
161 def __init__(self, config=None, extra_loaders=None, **kw):
162 def __init__(self, config=None, extra_loaders=None, **kw):
162 """
163 """
163 Public constructor
164 Public constructor
164
165
165 Parameters
166 Parameters
166 ----------
167 ----------
167 config : config
168 config : config
168 User configuration instance.
169 User configuration instance.
169 extra_loaders : list[of Jinja Loaders]
170 extra_loaders : list[of Jinja Loaders]
170 ordered list of Jinja loader to find templates. Will be tried in order
171 ordered list of Jinja loader to find templates. Will be tried in order
171 before the default FileSystem ones.
172 before the default FileSystem ones.
172 template : str (optional, kw arg)
173 template : str (optional, kw arg)
173 Template to use when exporting.
174 Template to use when exporting.
174 """
175 """
175 if not config:
176 if not config:
176 config = self.default_config
177 config = self.default_config
177
178
178 super(Exporter, self).__init__(config=config, **kw)
179 super(Exporter, self).__init__(config=config, **kw)
179
180
180 #Init
181 #Init
181 self._init_template()
182 self._init_template()
182 self._init_environment(extra_loaders=extra_loaders)
183 self._init_environment(extra_loaders=extra_loaders)
183 self._init_preprocessors()
184 self._init_preprocessors()
184 self._init_filters()
185 self._init_filters()
185
186
186
187
187 @property
188 @property
188 def default_config(self):
189 def default_config(self):
189 return Config()
190 return Config()
190
191
191 def _config_changed(self, name, old, new):
192 def _config_changed(self, name, old, new):
192 """When setting config, make sure to start with our default_config"""
193 """When setting config, make sure to start with our default_config"""
193 c = self.default_config
194 c = self.default_config
194 if new:
195 if new:
195 c.merge(new)
196 c.merge(new)
196 if c != old:
197 if c != old:
197 self.config = c
198 self.config = c
198 super(Exporter, self)._config_changed(name, old, c)
199 super(Exporter, self)._config_changed(name, old, c)
199
200
200
201
201 def _load_template(self):
202 def _load_template(self):
202 """Load the Jinja template object from the template file
203 """Load the Jinja template object from the template file
203
204
204 This is a no-op if the template attribute is already defined,
205 This is a no-op if the template attribute is already defined,
205 or the Jinja environment is not setup yet.
206 or the Jinja environment is not setup yet.
206
207
207 This is triggered by various trait changes that would change the template.
208 This is triggered by various trait changes that would change the template.
208 """
209 """
209 if self.template is not None:
210 if self.template is not None:
210 return
211 return
211 # called too early, do nothing
212 # called too early, do nothing
212 if self.environment is None:
213 if self.environment is None:
213 return
214 return
214 # Try different template names during conversion. First try to load the
215 # Try different template names during conversion. First try to load the
215 # template by name with extension added, then try loading the template
216 # template by name with extension added, then try loading the template
216 # as if the name is explicitly specified, then try the name as a
217 # as if the name is explicitly specified, then try the name as a
217 # 'flavor', and lastly just try to load the template by module name.
218 # 'flavor', and lastly just try to load the template by module name.
218 module_name = self.__module__.rsplit('.', 1)[-1]
219 module_name = self.__module__.rsplit('.', 1)[-1]
219 try_names = []
220 try_names = []
220 if self.template_file:
221 if self.template_file:
221 try_names.extend([
222 try_names.extend([
222 self.template_file + self.template_extension,
223 self.template_file + self.template_extension,
223 self.template_file,
224 self.template_file,
224 module_name + '_' + self.template_file + self.template_extension,
225 module_name + '_' + self.template_file + self.template_extension,
225 ])
226 ])
226 try_names.append(module_name + self.template_extension)
227 try_names.append(module_name + self.template_extension)
227 for try_name in try_names:
228 for try_name in try_names:
228 self.log.debug("Attempting to load template %s", try_name)
229 self.log.debug("Attempting to load template %s", try_name)
229 try:
230 try:
230 self.template = self.environment.get_template(try_name)
231 self.template = self.environment.get_template(try_name)
231 except (TemplateNotFound, IOError):
232 except (TemplateNotFound, IOError):
232 pass
233 pass
233 except Exception as e:
234 except Exception as e:
234 self.log.warn("Unexpected exception loading template: %s", try_name, exc_info=True)
235 self.log.warn("Unexpected exception loading template: %s", try_name, exc_info=True)
235 else:
236 else:
236 self.log.info("Loaded template %s", try_name)
237 self.log.info("Loaded template %s", try_name)
237 break
238 break
238
239
239 def from_notebook_node(self, nb, resources=None, **kw):
240 def from_notebook_node(self, nb, resources=None, **kw):
240 """
241 """
241 Convert a notebook from a notebook node instance.
242 Convert a notebook from a notebook node instance.
242
243
243 Parameters
244 Parameters
244 ----------
245 ----------
245 nb : Notebook node
246 nb : Notebook node
246 resources : dict (**kw)
247 resources : dict (**kw)
247 of additional resources that can be accessed read/write by
248 of additional resources that can be accessed read/write by
248 preprocessors and filters.
249 preprocessors and filters.
249 """
250 """
250 nb_copy = copy.deepcopy(nb)
251 nb_copy = copy.deepcopy(nb)
251 resources = self._init_resources(resources)
252 resources = self._init_resources(resources)
252
253
253 # Preprocess
254 # Preprocess
254 nb_copy, resources = self._preprocess(nb_copy, resources)
255 nb_copy, resources = self._preprocess(nb_copy, resources)
255
256
256 self._load_template()
257 self._load_template()
257
258
258 if self.template is not None:
259 if self.template is not None:
259 output = self.template.render(nb=nb_copy, resources=resources)
260 output = self.template.render(nb=nb_copy, resources=resources)
260 else:
261 else:
261 raise IOError('template file "%s" could not be found' % self.template_file)
262 raise IOError('template file "%s" could not be found' % self.template_file)
262 return output, resources
263 return output, resources
263
264
264
265
265 def from_filename(self, filename, resources=None, **kw):
266 def from_filename(self, filename, resources=None, **kw):
266 """
267 """
267 Convert a notebook from a notebook file.
268 Convert a notebook from a notebook file.
268
269
269 Parameters
270 Parameters
270 ----------
271 ----------
271 filename : str
272 filename : str
272 Full filename of the notebook file to open and convert.
273 Full filename of the notebook file to open and convert.
273 """
274 """
274
275
275 #Pull the metadata from the filesystem.
276 #Pull the metadata from the filesystem.
276 if resources is None:
277 if resources is None:
277 resources = ResourcesDict()
278 resources = ResourcesDict()
278 if not 'metadata' in resources or resources['metadata'] == '':
279 if not 'metadata' in resources or resources['metadata'] == '':
279 resources['metadata'] = ResourcesDict()
280 resources['metadata'] = ResourcesDict()
280 basename = os.path.basename(filename)
281 basename = os.path.basename(filename)
281 notebook_name = basename[:basename.rfind('.')]
282 notebook_name = basename[:basename.rfind('.')]
282 resources['metadata']['name'] = notebook_name
283 resources['metadata']['name'] = notebook_name
283
284
284 modified_date = datetime.datetime.fromtimestamp(os.path.getmtime(filename))
285 modified_date = datetime.datetime.fromtimestamp(os.path.getmtime(filename))
285 resources['metadata']['modified_date'] = modified_date.strftime("%B %d, %Y")
286 resources['metadata']['modified_date'] = modified_date.strftime("%B %d, %Y")
286
287
287 with io.open(filename) as f:
288 with io.open(filename) as f:
288 return self.from_notebook_node(nbformat.read(f, 'json'), resources=resources,**kw)
289 return self.from_notebook_node(nbformat.read(f, 'json'), resources=resources,**kw)
289
290
290
291
291 def from_file(self, file_stream, resources=None, **kw):
292 def from_file(self, file_stream, resources=None, **kw):
292 """
293 """
293 Convert a notebook from a notebook file.
294 Convert a notebook from a notebook file.
294
295
295 Parameters
296 Parameters
296 ----------
297 ----------
297 file_stream : file-like object
298 file_stream : file-like object
298 Notebook file-like object to convert.
299 Notebook file-like object to convert.
299 """
300 """
300 return self.from_notebook_node(nbformat.read(file_stream, 'json'), resources=resources, **kw)
301 return self.from_notebook_node(nbformat.read(file_stream, 'json'), resources=resources, **kw)
301
302
302
303
303 def register_preprocessor(self, preprocessor, enabled=False):
304 def register_preprocessor(self, preprocessor, enabled=False):
304 """
305 """
305 Register a preprocessor.
306 Register a preprocessor.
306 Preprocessors are classes that act upon the notebook before it is
307 Preprocessors are classes that act upon the notebook before it is
307 passed into the Jinja templating engine. Preprocessors are also
308 passed into the Jinja templating engine. Preprocessors are also
308 capable of passing additional information to the Jinja
309 capable of passing additional information to the Jinja
309 templating engine.
310 templating engine.
310
311
311 Parameters
312 Parameters
312 ----------
313 ----------
313 preprocessor : preprocessor
314 preprocessor : preprocessor
314 """
315 """
315 if preprocessor is None:
316 if preprocessor is None:
316 raise TypeError('preprocessor')
317 raise TypeError('preprocessor')
317 isclass = isinstance(preprocessor, type)
318 isclass = isinstance(preprocessor, type)
318 constructed = not isclass
319 constructed = not isclass
319
320
320 #Handle preprocessor's registration based on it's type
321 #Handle preprocessor's registration based on it's type
321 if constructed and isinstance(preprocessor, py3compat.string_types):
322 if constructed and isinstance(preprocessor, py3compat.string_types):
322 #Preprocessor is a string, import the namespace and recursively call
323 #Preprocessor is a string, import the namespace and recursively call
323 #this register_preprocessor method
324 #this register_preprocessor method
324 preprocessor_cls = import_item(preprocessor)
325 preprocessor_cls = import_item(preprocessor)
325 return self.register_preprocessor(preprocessor_cls, enabled)
326 return self.register_preprocessor(preprocessor_cls, enabled)
326
327
327 if constructed and hasattr(preprocessor, '__call__'):
328 if constructed and hasattr(preprocessor, '__call__'):
328 #Preprocessor is a function, no need to construct it.
329 #Preprocessor is a function, no need to construct it.
329 #Register and return the preprocessor.
330 #Register and return the preprocessor.
330 if enabled:
331 if enabled:
331 preprocessor.enabled = True
332 preprocessor.enabled = True
332 self._preprocessors.append(preprocessor)
333 self._preprocessors.append(preprocessor)
333 return preprocessor
334 return preprocessor
334
335
335 elif isclass and isinstance(preprocessor, MetaHasTraits):
336 elif isclass and isinstance(preprocessor, MetaHasTraits):
336 #Preprocessor is configurable. Make sure to pass in new default for
337 #Preprocessor is configurable. Make sure to pass in new default for
337 #the enabled flag if one was specified.
338 #the enabled flag if one was specified.
338 self.register_preprocessor(preprocessor(parent=self), enabled)
339 self.register_preprocessor(preprocessor(parent=self), enabled)
339
340
340 elif isclass:
341 elif isclass:
341 #Preprocessor is not configurable, construct it
342 #Preprocessor is not configurable, construct it
342 self.register_preprocessor(preprocessor(), enabled)
343 self.register_preprocessor(preprocessor(), enabled)
343
344
344 else:
345 else:
345 #Preprocessor is an instance of something without a __call__
346 #Preprocessor is an instance of something without a __call__
346 #attribute.
347 #attribute.
347 raise TypeError('preprocessor')
348 raise TypeError('preprocessor')
348
349
349
350
350 def register_filter(self, name, jinja_filter):
351 def register_filter(self, name, jinja_filter):
351 """
352 """
352 Register a filter.
353 Register a filter.
353 A filter is a function that accepts and acts on one string.
354 A filter is a function that accepts and acts on one string.
354 The filters are accesible within the Jinja templating engine.
355 The filters are accesible within the Jinja templating engine.
355
356
356 Parameters
357 Parameters
357 ----------
358 ----------
358 name : str
359 name : str
359 name to give the filter in the Jinja engine
360 name to give the filter in the Jinja engine
360 filter : filter
361 filter : filter
361 """
362 """
362 if jinja_filter is None:
363 if jinja_filter is None:
363 raise TypeError('filter')
364 raise TypeError('filter')
364 isclass = isinstance(jinja_filter, type)
365 isclass = isinstance(jinja_filter, type)
365 constructed = not isclass
366 constructed = not isclass
366
367
367 #Handle filter's registration based on it's type
368 #Handle filter's registration based on it's type
368 if constructed and isinstance(jinja_filter, py3compat.string_types):
369 if constructed and isinstance(jinja_filter, py3compat.string_types):
369 #filter is a string, import the namespace and recursively call
370 #filter is a string, import the namespace and recursively call
370 #this register_filter method
371 #this register_filter method
371 filter_cls = import_item(jinja_filter)
372 filter_cls = import_item(jinja_filter)
372 return self.register_filter(name, filter_cls)
373 return self.register_filter(name, filter_cls)
373
374
374 if constructed and hasattr(jinja_filter, '__call__'):
375 if constructed and hasattr(jinja_filter, '__call__'):
375 #filter is a function, no need to construct it.
376 #filter is a function, no need to construct it.
376 self.environment.filters[name] = jinja_filter
377 self.environment.filters[name] = jinja_filter
377 return jinja_filter
378 return jinja_filter
378
379
379 elif isclass and isinstance(jinja_filter, MetaHasTraits):
380 elif isclass and isinstance(jinja_filter, MetaHasTraits):
380 #filter is configurable. Make sure to pass in new default for
381 #filter is configurable. Make sure to pass in new default for
381 #the enabled flag if one was specified.
382 #the enabled flag if one was specified.
382 filter_instance = jinja_filter(parent=self)
383 filter_instance = jinja_filter(parent=self)
383 self.register_filter(name, filter_instance )
384 self.register_filter(name, filter_instance )
384
385
385 elif isclass:
386 elif isclass:
386 #filter is not configurable, construct it
387 #filter is not configurable, construct it
387 filter_instance = jinja_filter()
388 filter_instance = jinja_filter()
388 self.register_filter(name, filter_instance)
389 self.register_filter(name, filter_instance)
389
390
390 else:
391 else:
391 #filter is an instance of something without a __call__
392 #filter is an instance of something without a __call__
392 #attribute.
393 #attribute.
393 raise TypeError('filter')
394 raise TypeError('filter')
394
395
395
396
396 def _init_template(self):
397 def _init_template(self):
397 """
398 """
398 Make sure a template name is specified. If one isn't specified, try to
399 Make sure a template name is specified. If one isn't specified, try to
399 build one from the information we know.
400 build one from the information we know.
400 """
401 """
401 self._template_file_changed('template_file', self.template_file, self.template_file)
402 self._template_file_changed('template_file', self.template_file, self.template_file)
402
403
403
404
404 def _init_environment(self, extra_loaders=None):
405 def _init_environment(self, extra_loaders=None):
405 """
406 """
406 Create the Jinja templating environment.
407 Create the Jinja templating environment.
407 """
408 """
408 here = os.path.dirname(os.path.realpath(__file__))
409 here = os.path.dirname(os.path.realpath(__file__))
409 loaders = []
410 loaders = []
410 if extra_loaders:
411 if extra_loaders:
411 loaders.extend(extra_loaders)
412 loaders.extend(extra_loaders)
412
413
413 paths = self.template_path
414 paths = self.template_path
414 paths.extend([os.path.join(here, self.default_template_path),
415 paths.extend([os.path.join(here, self.default_template_path),
415 os.path.join(here, self.template_skeleton_path)])
416 os.path.join(here, self.template_skeleton_path)])
416 loaders.append(FileSystemLoader(paths))
417 loaders.append(FileSystemLoader(paths))
417
418
418 self.environment = Environment(
419 self.environment = Environment(
419 loader= ChoiceLoader(loaders),
420 loader= ChoiceLoader(loaders),
420 extensions=JINJA_EXTENSIONS
421 extensions=JINJA_EXTENSIONS
421 )
422 )
422
423
423 #Set special Jinja2 syntax that will not conflict with latex.
424 #Set special Jinja2 syntax that will not conflict with latex.
424 if self.jinja_logic_block_start:
425 if self.jinja_logic_block_start:
425 self.environment.block_start_string = self.jinja_logic_block_start
426 self.environment.block_start_string = self.jinja_logic_block_start
426 if self.jinja_logic_block_end:
427 if self.jinja_logic_block_end:
427 self.environment.block_end_string = self.jinja_logic_block_end
428 self.environment.block_end_string = self.jinja_logic_block_end
428 if self.jinja_variable_block_start:
429 if self.jinja_variable_block_start:
429 self.environment.variable_start_string = self.jinja_variable_block_start
430 self.environment.variable_start_string = self.jinja_variable_block_start
430 if self.jinja_variable_block_end:
431 if self.jinja_variable_block_end:
431 self.environment.variable_end_string = self.jinja_variable_block_end
432 self.environment.variable_end_string = self.jinja_variable_block_end
432 if self.jinja_comment_block_start:
433 if self.jinja_comment_block_start:
433 self.environment.comment_start_string = self.jinja_comment_block_start
434 self.environment.comment_start_string = self.jinja_comment_block_start
434 if self.jinja_comment_block_end:
435 if self.jinja_comment_block_end:
435 self.environment.comment_end_string = self.jinja_comment_block_end
436 self.environment.comment_end_string = self.jinja_comment_block_end
436
437
437
438
438 def _init_preprocessors(self):
439 def _init_preprocessors(self):
439 """
440 """
440 Register all of the preprocessors needed for this exporter, disabled
441 Register all of the preprocessors needed for this exporter, disabled
441 unless specified explicitly.
442 unless specified explicitly.
442 """
443 """
443 self._preprocessors = []
444 self._preprocessors = []
444
445
445 #Load default preprocessors (not necessarly enabled by default).
446 #Load default preprocessors (not necessarly enabled by default).
446 if self.default_preprocessors:
447 if self.default_preprocessors:
447 for preprocessor in self.default_preprocessors:
448 for preprocessor in self.default_preprocessors:
448 self.register_preprocessor(preprocessor)
449 self.register_preprocessor(preprocessor)
449
450
450 #Load user preprocessors. Enable by default.
451 #Load user preprocessors. Enable by default.
451 if self.preprocessors:
452 if self.preprocessors:
452 for preprocessor in self.preprocessors:
453 for preprocessor in self.preprocessors:
453 self.register_preprocessor(preprocessor, enabled=True)
454 self.register_preprocessor(preprocessor, enabled=True)
454
455
455
456
456 def _init_filters(self):
457 def _init_filters(self):
457 """
458 """
458 Register all of the filters required for the exporter.
459 Register all of the filters required for the exporter.
459 """
460 """
460
461
461 #Add default filters to the Jinja2 environment
462 #Add default filters to the Jinja2 environment
462 for key, value in default_filters.items():
463 for key, value in default_filters.items():
463 self.register_filter(key, value)
464 self.register_filter(key, value)
464
465
465 #Load user filters. Overwrite existing filters if need be.
466 #Load user filters. Overwrite existing filters if need be.
466 if self.filters:
467 if self.filters:
467 for key, user_filter in self.filters.items():
468 for key, user_filter in self.filters.items():
468 self.register_filter(key, user_filter)
469 self.register_filter(key, user_filter)
469
470
470
471
471 def _init_resources(self, resources):
472 def _init_resources(self, resources):
472
473
473 #Make sure the resources dict is of ResourcesDict type.
474 #Make sure the resources dict is of ResourcesDict type.
474 if resources is None:
475 if resources is None:
475 resources = ResourcesDict()
476 resources = ResourcesDict()
476 if not isinstance(resources, ResourcesDict):
477 if not isinstance(resources, ResourcesDict):
477 new_resources = ResourcesDict()
478 new_resources = ResourcesDict()
478 new_resources.update(resources)
479 new_resources.update(resources)
479 resources = new_resources
480 resources = new_resources
480
481
481 #Make sure the metadata extension exists in resources
482 #Make sure the metadata extension exists in resources
482 if 'metadata' in resources:
483 if 'metadata' in resources:
483 if not isinstance(resources['metadata'], ResourcesDict):
484 if not isinstance(resources['metadata'], ResourcesDict):
484 resources['metadata'] = ResourcesDict(resources['metadata'])
485 resources['metadata'] = ResourcesDict(resources['metadata'])
485 else:
486 else:
486 resources['metadata'] = ResourcesDict()
487 resources['metadata'] = ResourcesDict()
487 if not resources['metadata']['name']:
488 if not resources['metadata']['name']:
488 resources['metadata']['name'] = 'Notebook'
489 resources['metadata']['name'] = 'Notebook'
489
490
490 #Set the output extension
491 #Set the output extension
491 resources['output_extension'] = self.file_extension
492 resources['output_extension'] = self.file_extension
492 return resources
493 return resources
493
494
494
495
495 def _preprocess(self, nb, resources):
496 def _preprocess(self, nb, resources):
496 """
497 """
497 Preprocess the notebook before passing it into the Jinja engine.
498 Preprocess the notebook before passing it into the Jinja engine.
498 To preprocess the notebook is to apply all of the
499 To preprocess the notebook is to apply all of the
499
500
500 Parameters
501 Parameters
501 ----------
502 ----------
502 nb : notebook node
503 nb : notebook node
503 notebook that is being exported.
504 notebook that is being exported.
504 resources : a dict of additional resources that
505 resources : a dict of additional resources that
505 can be accessed read/write by preprocessors
506 can be accessed read/write by preprocessors
506 and filters.
507 and filters.
507 """
508 """
508
509
509 # Do a copy.deepcopy first,
510 # Do a copy.deepcopy first,
510 # we are never safe enough with what the preprocessors could do.
511 # we are never safe enough with what the preprocessors could do.
511 nbc = copy.deepcopy(nb)
512 nbc = copy.deepcopy(nb)
512 resc = copy.deepcopy(resources)
513 resc = copy.deepcopy(resources)
513
514
514 #Run each preprocessor on the notebook. Carry the output along
515 #Run each preprocessor on the notebook. Carry the output along
515 #to each preprocessor
516 #to each preprocessor
516 for preprocessor in self._preprocessors:
517 for preprocessor in self._preprocessors:
517 nbc, resc = preprocessor(nbc, resc)
518 nbc, resc = preprocessor(nbc, resc)
518 return nbc, resc
519 return nbc, resc
@@ -1,6 +1,7 b''
1 from .ansi import *
1 from .ansi import *
2 from .datatypefilter import *
2 from .datatypefilter import *
3 from .highlight import *
3 from .highlight import *
4 from .latex import *
4 from .latex import *
5 from .markdown import *
5 from .markdown import *
6 from .strings import * No newline at end of file
6 from .strings import *
7 from .citation import * No newline at end of file
@@ -1,270 +1,274 b''
1 ((*- extends 'display_priority.tplx' -*))
1 ((*- extends 'display_priority.tplx' -*))
2
2
3
3
4 \nonstopmode
4 \nonstopmode
5
5
6 ((* block in_prompt *))
6 ((* block in_prompt *))
7 ((* endblock in_prompt *))
7 ((* endblock in_prompt *))
8
8
9 ((* block output_prompt *))
9 ((* block output_prompt *))
10 ((* endblock output_prompt *))
10 ((* endblock output_prompt *))
11
11
12 ((* block codecell *))
12 ((* block codecell *))
13 \begin{codecell}
13 \begin{codecell}
14 ((( super() )))
14 ((( super() )))
15 \end{codecell}
15 \end{codecell}
16 ((* endblock *))
16 ((* endblock *))
17
17
18 ((* block input *))
18 ((* block input *))
19 \begin{codeinput}
19 \begin{codeinput}
20 \begin{lstlisting}
20 \begin{lstlisting}
21 ((( cell.input )))
21 ((( cell.input )))
22 \end{lstlisting}
22 \end{lstlisting}
23 \end{codeinput}
23 \end{codeinput}
24 ((* endblock input *))
24 ((* endblock input *))
25
25
26 ((= Those Two are for error displaying
26 ((= Those Two are for error displaying
27 even if the first one seem to do nothing,
27 even if the first one seem to do nothing,
28 it introduces a new line
28 it introduces a new line
29 =))
29 =))
30
30
31 ((* block pyerr *))
31 ((* block pyerr *))
32 \begin{traceback}
32 \begin{traceback}
33 \begin{verbatim}
33 \begin{verbatim}
34 ((( super() )))
34 ((( super() )))
35 \end{verbatim}
35 \end{verbatim}
36 \end{traceback}
36 \end{traceback}
37 ((* endblock pyerr *))
37 ((* endblock pyerr *))
38
38
39 ((* block traceback_line *))
39 ((* block traceback_line *))
40 ((( line | indent | strip_ansi )))
40 ((( line | indent | strip_ansi )))
41 ((* endblock traceback_line *))
41 ((* endblock traceback_line *))
42 ((= .... =))
42 ((= .... =))
43
43
44 ((*- block output_group -*))
44 ((*- block output_group -*))
45 \begin{codeoutput}
45 \begin{codeoutput}
46 ((( super() )))
46 ((( super() )))
47 \end{codeoutput}
47 \end{codeoutput}
48 ((* endblock *))
48 ((* endblock *))
49
49
50 ((*- block data_png -*))
50 ((*- block data_png -*))
51 \begin{center}
51 \begin{center}
52 \includegraphics[max size={0.7\textwidth}{0.9\textheight}]{((( output.png_filename | posix_path )))}
52 \includegraphics[max size={0.7\textwidth}{0.9\textheight}]{((( output.png_filename | posix_path )))}
53 \par
53 \par
54 \end{center}
54 \end{center}
55 ((*- endblock -*))
55 ((*- endblock -*))
56
56
57 ((*- block data_jpg -*))
57 ((*- block data_jpg -*))
58 \begin{center}
58 \begin{center}
59 \includegraphics[max size={0.7\textwidth}{0.9\textheight}]{((( output.jpeg_filename | posix_path )))}
59 \includegraphics[max size={0.7\textwidth}{0.9\textheight}]{((( output.jpeg_filename | posix_path )))}
60 \par
60 \par
61 \end{center}
61 \end{center}
62 ((*- endblock -*))
62 ((*- endblock -*))
63
63
64 ((*- block data_svg -*))
64 ((*- block data_svg -*))
65 \begin{center}
65 \begin{center}
66 \includegraphics[width=0.7\textwidth]{((( output.svg_filename | posix_path )))}
66 \includegraphics[width=0.7\textwidth]{((( output.svg_filename | posix_path )))}
67 \par
67 \par
68 \end{center}
68 \end{center}
69 ((*- endblock -*))
69 ((*- endblock -*))
70
70
71 ((*- block data_pdf -*))
71 ((*- block data_pdf -*))
72 \begin{center}
72 \begin{center}
73 \includegraphics[width=0.7\textwidth]{((( output.pdf_filename | posix_path )))}
73 \includegraphics[width=0.7\textwidth]{((( output.pdf_filename | posix_path )))}
74 \par
74 \par
75 \end{center}
75 \end{center}
76 ((*- endblock -*))
76 ((*- endblock -*))
77
77
78 ((* block pyout *))
78 ((* block pyout *))
79 ((* block data_priority scoped *))
79 ((* block data_priority scoped *))
80 ((( super() )))
80 ((( super() )))
81 ((* endblock *))
81 ((* endblock *))
82 ((* endblock pyout *))
82 ((* endblock pyout *))
83
83
84 ((* block data_text *))
84 ((* block data_text *))
85 \begin{verbatim}
85 \begin{verbatim}
86 ((( output.text )))
86 ((( output.text )))
87 \end{verbatim}
87 \end{verbatim}
88 ((* endblock *))
88 ((* endblock *))
89
89
90 ((* block data_latex -*))
90 ((* block data_latex -*))
91 ((*- if output.latex.startswith('$'): -*)) \begin{equation*}
91 ((*- if output.latex.startswith('$'): -*)) \begin{equation*}
92 ((( output.latex | strip_dollars )))
92 ((( output.latex | strip_dollars )))
93 \end{equation*}
93 \end{equation*}
94 ((*- else -*))
94 ((*- else -*))
95 ((( output.latex )))
95 ((( output.latex )))
96 ((*- endif *))
96 ((*- endif *))
97 ((* endblock *))
97 ((* endblock *))
98
98
99 ((* block stream *))
99 ((* block stream *))
100 \begin{Verbatim}[commandchars=\\\{\}]
100 \begin{Verbatim}[commandchars=\\\{\}]
101 ((( output.text | ansi2latex )))
101 ((( output.text | ansi2latex )))
102 \end{Verbatim}
102 \end{Verbatim}
103 ((* endblock stream *))
103 ((* endblock stream *))
104
104
105 ((* block markdowncell scoped *))
105 ((* block markdowncell scoped *))
106 ((( cell.source | markdown2latex )))
106 ((( cell.source | parse_citation | markdown2latex )))
107 ((* endblock markdowncell *))
107 ((* endblock markdowncell *))
108
108
109 ((* block headingcell scoped -*))
109 ((* block headingcell scoped -*))
110 ((( ('#' * cell.level + cell.source) | replace('\n', ' ') | markdown2latex )))
110 ((( ('#' * cell.level + cell.source) | replace('\n', ' ') | parse_citation | markdown2latex )))
111 ((* endblock headingcell *))
111 ((* endblock headingcell *))
112
112
113 ((* block rawcell scoped *))
113 ((* block rawcell scoped *))
114 ((( cell.source | comment_lines )))
114 ((( cell.source | comment_lines )))
115 ((* endblock rawcell *))
115 ((* endblock rawcell *))
116
116
117 ((* block unknowncell scoped *))
117 ((* block unknowncell scoped *))
118 unknown type ((( cell.type )))
118 unknown type ((( cell.type )))
119 ((* endblock unknowncell *))
119 ((* endblock unknowncell *))
120
120
121 ((* block body *))
121 ((* block body *))
122
122
123 ((* block bodyBegin *))
123 ((* block bodyBegin *))
124 \begin{document}
124 \begin{document}
125 ((* endblock bodyBegin *))
125 ((* endblock bodyBegin *))
126
126
127 ((( super() )))
127 ((( super() )))
128
128
129 ((* block bodyEnd *))
129 ((* block bodyEnd *))
130
131 ((* block bibliography *))
132 ((* endblock bibliography *))
133
130 \end{document}
134 \end{document}
131 ((* endblock bodyEnd *))
135 ((* endblock bodyEnd *))
132 ((* endblock body *))
136 ((* endblock body *))
133
137
134 ((* block header *))
138 ((* block header *))
135 %% This file was auto-generated by IPython.
139 %% This file was auto-generated by IPython.
136 %% Conversion from the original notebook file:
140 %% Conversion from the original notebook file:
137 %%
141 %%
138 \documentclass[11pt,english]{article}
142 \documentclass[11pt,english]{article}
139
143
140 %% This is the automatic preamble used by IPython. Note that it does *not*
144 %% This is the automatic preamble used by IPython. Note that it does *not*
141 %% include a documentclass declaration, that is added at runtime to the overall
145 %% include a documentclass declaration, that is added at runtime to the overall
142 %% document.
146 %% document.
143
147
144 \usepackage{amsmath}
148 \usepackage{amsmath}
145 \usepackage{amssymb}
149 \usepackage{amssymb}
146 \usepackage{graphicx}
150 \usepackage{graphicx}
147 \usepackage{grffile}
151 \usepackage{grffile}
148 \usepackage{ucs}
152 \usepackage{ucs}
149 \usepackage[utf8x]{inputenc}
153 \usepackage[utf8x]{inputenc}
150
154
151 % Scale down larger images
155 % Scale down larger images
152 \usepackage[export]{adjustbox}
156 \usepackage[export]{adjustbox}
153
157
154 %fancy verbatim
158 %fancy verbatim
155 \usepackage{fancyvrb}
159 \usepackage{fancyvrb}
156 % needed for markdown enumerations to work
160 % needed for markdown enumerations to work
157 \usepackage{enumerate}
161 \usepackage{enumerate}
158
162
159 % Slightly bigger margins than the latex defaults
163 % Slightly bigger margins than the latex defaults
160 \usepackage{geometry}
164 \usepackage{geometry}
161 \geometry{verbose,tmargin=3cm,bmargin=3cm,lmargin=2.5cm,rmargin=2.5cm}
165 \geometry{verbose,tmargin=3cm,bmargin=3cm,lmargin=2.5cm,rmargin=2.5cm}
162
166
163 % Define a few colors for use in code, links and cell shading
167 % Define a few colors for use in code, links and cell shading
164 \usepackage{color}
168 \usepackage{color}
165 \definecolor{orange}{cmyk}{0,0.4,0.8,0.2}
169 \definecolor{orange}{cmyk}{0,0.4,0.8,0.2}
166 \definecolor{darkorange}{rgb}{.71,0.21,0.01}
170 \definecolor{darkorange}{rgb}{.71,0.21,0.01}
167 \definecolor{darkgreen}{rgb}{.12,.54,.11}
171 \definecolor{darkgreen}{rgb}{.12,.54,.11}
168 \definecolor{myteal}{rgb}{.26, .44, .56}
172 \definecolor{myteal}{rgb}{.26, .44, .56}
169 \definecolor{gray}{gray}{0.45}
173 \definecolor{gray}{gray}{0.45}
170 \definecolor{lightgray}{gray}{.95}
174 \definecolor{lightgray}{gray}{.95}
171 \definecolor{mediumgray}{gray}{.8}
175 \definecolor{mediumgray}{gray}{.8}
172 \definecolor{inputbackground}{rgb}{.95, .95, .85}
176 \definecolor{inputbackground}{rgb}{.95, .95, .85}
173 \definecolor{outputbackground}{rgb}{.95, .95, .95}
177 \definecolor{outputbackground}{rgb}{.95, .95, .95}
174 \definecolor{traceback}{rgb}{1, .95, .95}
178 \definecolor{traceback}{rgb}{1, .95, .95}
175
179
176 % new ansi colors
180 % new ansi colors
177 \definecolor{brown}{rgb}{0.54,0.27,0.07}
181 \definecolor{brown}{rgb}{0.54,0.27,0.07}
178 \definecolor{purple}{rgb}{0.5,0.0,0.5}
182 \definecolor{purple}{rgb}{0.5,0.0,0.5}
179 \definecolor{darkgray}{gray}{0.25}
183 \definecolor{darkgray}{gray}{0.25}
180 \definecolor{lightred}{rgb}{1.0,0.39,0.28}
184 \definecolor{lightred}{rgb}{1.0,0.39,0.28}
181 \definecolor{lightgreen}{rgb}{0.48,0.99,0.0}
185 \definecolor{lightgreen}{rgb}{0.48,0.99,0.0}
182 \definecolor{lightblue}{rgb}{0.53,0.81,0.92}
186 \definecolor{lightblue}{rgb}{0.53,0.81,0.92}
183 \definecolor{lightpurple}{rgb}{0.87,0.63,0.87}
187 \definecolor{lightpurple}{rgb}{0.87,0.63,0.87}
184 \definecolor{lightcyan}{rgb}{0.5,1.0,0.83}
188 \definecolor{lightcyan}{rgb}{0.5,1.0,0.83}
185
189
186 % Framed environments for code cells (inputs, outputs, errors, ...). The
190 % Framed environments for code cells (inputs, outputs, errors, ...). The
187 % various uses of \unskip (or not) at the end were fine-tuned by hand, so don't
191 % various uses of \unskip (or not) at the end were fine-tuned by hand, so don't
188 % randomly change them unless you're sure of the effect it will have.
192 % randomly change them unless you're sure of the effect it will have.
189 \usepackage{framed}
193 \usepackage{framed}
190
194
191 % remove extraneous vertical space in boxes
195 % remove extraneous vertical space in boxes
192 \setlength\fboxsep{0pt}
196 \setlength\fboxsep{0pt}
193
197
194 % codecell is the whole input+output set of blocks that a Code cell can
198 % codecell is the whole input+output set of blocks that a Code cell can
195 % generate.
199 % generate.
196
200
197 % TODO: unfortunately, it seems that using a framed codecell environment breaks
201 % TODO: unfortunately, it seems that using a framed codecell environment breaks
198 % the ability of the frames inside of it to be broken across pages. This
202 % the ability of the frames inside of it to be broken across pages. This
199 % causes at least the problem of having lots of empty space at the bottom of
203 % causes at least the problem of having lots of empty space at the bottom of
200 % pages as new frames are moved to the next page, and if a single frame is too
204 % pages as new frames are moved to the next page, and if a single frame is too
201 % long to fit on a page, will completely stop latex from compiling the
205 % long to fit on a page, will completely stop latex from compiling the
202 % document. So unless we figure out a solution to this, we'll have to instead
206 % document. So unless we figure out a solution to this, we'll have to instead
203 % leave the codecell env. as empty. I'm keeping the original codecell
207 % leave the codecell env. as empty. I'm keeping the original codecell
204 % definition here (a thin vertical bar) for reference, in case we find a
208 % definition here (a thin vertical bar) for reference, in case we find a
205 % solution to the page break issue.
209 % solution to the page break issue.
206
210
207 %% \newenvironment{codecell}{%
211 %% \newenvironment{codecell}{%
208 %% \def\FrameCommand{\color{mediumgray} \vrule width 1pt \hspace{5pt}}%
212 %% \def\FrameCommand{\color{mediumgray} \vrule width 1pt \hspace{5pt}}%
209 %% \MakeFramed{\vspace{-0.5em}}}
213 %% \MakeFramed{\vspace{-0.5em}}}
210 %% {\unskip\endMakeFramed}
214 %% {\unskip\endMakeFramed}
211
215
212 % For now, make this a no-op...
216 % For now, make this a no-op...
213 \newenvironment{codecell}{}
217 \newenvironment{codecell}{}
214
218
215 \newenvironment{codeinput}{%
219 \newenvironment{codeinput}{%
216 \def\FrameCommand{\colorbox{inputbackground}}%
220 \def\FrameCommand{\colorbox{inputbackground}}%
217 \MakeFramed{\advance\hsize-\width \FrameRestore}}
221 \MakeFramed{\advance\hsize-\width \FrameRestore}}
218 {\unskip\endMakeFramed}
222 {\unskip\endMakeFramed}
219
223
220 \newenvironment{codeoutput}{%
224 \newenvironment{codeoutput}{%
221 \def\FrameCommand{\colorbox{outputbackground}}%
225 \def\FrameCommand{\colorbox{outputbackground}}%
222 \vspace{-1.4em}
226 \vspace{-1.4em}
223 \MakeFramed{\advance\hsize-\width \FrameRestore}}
227 \MakeFramed{\advance\hsize-\width \FrameRestore}}
224 {\unskip\medskip\endMakeFramed}
228 {\unskip\medskip\endMakeFramed}
225
229
226 \newenvironment{traceback}{%
230 \newenvironment{traceback}{%
227 \def\FrameCommand{\colorbox{traceback}}%
231 \def\FrameCommand{\colorbox{traceback}}%
228 \MakeFramed{\advance\hsize-\width \FrameRestore}}
232 \MakeFramed{\advance\hsize-\width \FrameRestore}}
229 {\endMakeFramed}
233 {\endMakeFramed}
230
234
231 % Use and configure listings package for nicely formatted code
235 % Use and configure listings package for nicely formatted code
232 \usepackage{listingsutf8}
236 \usepackage{listingsutf8}
233 \lstset{
237 \lstset{
234 language=python,
238 language=python,
235 inputencoding=utf8x,
239 inputencoding=utf8x,
236 extendedchars=\true,
240 extendedchars=\true,
237 aboveskip=\smallskipamount,
241 aboveskip=\smallskipamount,
238 belowskip=\smallskipamount,
242 belowskip=\smallskipamount,
239 xleftmargin=2mm,
243 xleftmargin=2mm,
240 breaklines=true,
244 breaklines=true,
241 basicstyle=\small \ttfamily,
245 basicstyle=\small \ttfamily,
242 showstringspaces=false,
246 showstringspaces=false,
243 keywordstyle=\color{blue}\bfseries,
247 keywordstyle=\color{blue}\bfseries,
244 commentstyle=\color{myteal},
248 commentstyle=\color{myteal},
245 stringstyle=\color{darkgreen},
249 stringstyle=\color{darkgreen},
246 identifierstyle=\color{darkorange},
250 identifierstyle=\color{darkorange},
247 columns=fullflexible, % tighter character kerning, like verb
251 columns=fullflexible, % tighter character kerning, like verb
248 }
252 }
249
253
250 % The hyperref package gives us a pdf with properly built
254 % The hyperref package gives us a pdf with properly built
251 % internal navigation ('pdf bookmarks' for the table of contents,
255 % internal navigation ('pdf bookmarks' for the table of contents,
252 % internal cross-reference links, web links for URLs, etc.)
256 % internal cross-reference links, web links for URLs, etc.)
253 \usepackage{hyperref}
257 \usepackage{hyperref}
254 \hypersetup{
258 \hypersetup{
255 breaklinks=true, % so long urls are correctly broken across lines
259 breaklinks=true, % so long urls are correctly broken across lines
256 colorlinks=true,
260 colorlinks=true,
257 urlcolor=blue,
261 urlcolor=blue,
258 linkcolor=darkorange,
262 linkcolor=darkorange,
259 citecolor=darkgreen,
263 citecolor=darkgreen,
260 }
264 }
261
265
262 % hardcode size of all verbatim environments to be a bit smaller
266 % hardcode size of all verbatim environments to be a bit smaller
263 \makeatletter
267 \makeatletter
264 \g@addto@macro\@verbatim\small\topsep=0.5em\partopsep=0pt
268 \g@addto@macro\@verbatim\small\topsep=0.5em\partopsep=0pt
265 \makeatother
269 \makeatother
266
270
267 % Prevent overflowing lines due to urls and other hard-to-break entities.
271 % Prevent overflowing lines due to urls and other hard-to-break entities.
268 \sloppy
272 \sloppy
269
273
270 ((* endblock *))
274 ((* endblock *))
@@ -1,469 +1,472 b''
1 ((= NBConvert Sphinx-Latex Template
1 ((= NBConvert Sphinx-Latex Template
2
2
3 Purpose: Allow export of PDF friendly Latex inspired by Sphinx. Most of the
3 Purpose: Allow export of PDF friendly Latex inspired by Sphinx. Most of the
4 template is derived directly from Sphinx source.
4 template is derived directly from Sphinx source.
5
5
6 Inheritance: null>display_priority
6 Inheritance: null>display_priority
7
7
8 Note: For best display, use latex syntax highlighting. =))
8 Note: For best display, use latex syntax highlighting. =))
9
9
10 ((*- extends 'display_priority.tplx' -*))
10 ((*- extends 'display_priority.tplx' -*))
11
11
12
12
13 \nonstopmode
13 \nonstopmode
14
14
15 %==============================================================================
15 %==============================================================================
16 % Declarations
16 % Declarations
17 %==============================================================================
17 %==============================================================================
18
18
19 % In order to make sure that the input/output header follows the code it
19 % In order to make sure that the input/output header follows the code it
20 % preceeds, the needspace package is used to request that a certain
20 % preceeds, the needspace package is used to request that a certain
21 % amount of lines (specified by this variable) are reserved. If those
21 % amount of lines (specified by this variable) are reserved. If those
22 % lines aren't available on the current page, the documenter will break
22 % lines aren't available on the current page, the documenter will break
23 % to the next page and the header along with accomanying lines will be
23 % to the next page and the header along with accomanying lines will be
24 % rendered together. This value specifies the number of lines that
24 % rendered together. This value specifies the number of lines that
25 % the header will be forced to group with without a page break.
25 % the header will be forced to group with without a page break.
26 ((*- set min_header_lines = 4 -*))
26 ((*- set min_header_lines = 4 -*))
27
27
28 % This is the number of characters that are permitted per line. It's
28 % This is the number of characters that are permitted per line. It's
29 % important that this limit is set so characters do not run off the
29 % important that this limit is set so characters do not run off the
30 % edges of latex pages (since latex does not always seem smart enough
30 % edges of latex pages (since latex does not always seem smart enough
31 % to prevent this in some cases.) This is only applied to textual output
31 % to prevent this in some cases.) This is only applied to textual output
32 ((* if resources.sphinx.outputstyle == 'simple' *))
32 ((* if resources.sphinx.outputstyle == 'simple' *))
33 ((*- set wrap_size = 85 -*))
33 ((*- set wrap_size = 85 -*))
34 ((* elif resources.sphinx.outputstyle == 'notebook' *))
34 ((* elif resources.sphinx.outputstyle == 'notebook' *))
35 ((*- set wrap_size = 70 -*))
35 ((*- set wrap_size = 70 -*))
36 ((* endif *))
36 ((* endif *))
37
37
38 %==============================================================================
38 %==============================================================================
39 % Header
39 % Header
40 %==============================================================================
40 %==============================================================================
41 ((* block header *))
41 ((* block header *))
42
42
43 % Header, overrides base
43 % Header, overrides base
44
44
45 % Make sure that the sphinx doc style knows who it inherits from.
45 % Make sure that the sphinx doc style knows who it inherits from.
46 \def\sphinxdocclass{(((parentdocumentclass)))}
46 \def\sphinxdocclass{(((parentdocumentclass)))}
47
47
48 % Declare the document class
48 % Declare the document class
49 \documentclass[letterpaper,10pt,english]{((( resources.sphinx.texinputs | posix_path )))/sphinx(((documentclass)))}
49 \documentclass[letterpaper,10pt,english]{((( resources.sphinx.texinputs | posix_path )))/sphinx(((documentclass)))}
50
50
51 % Imports
51 % Imports
52 \usepackage[utf8]{inputenc}
52 \usepackage[utf8]{inputenc}
53 \DeclareUnicodeCharacter{00A0}{\\nobreakspace}
53 \DeclareUnicodeCharacter{00A0}{\\nobreakspace}
54 \usepackage[T1]{fontenc}
54 \usepackage[T1]{fontenc}
55 \usepackage{babel}
55 \usepackage{babel}
56 \usepackage{times}
56 \usepackage{times}
57 \usepackage{import}
57 \usepackage{import}
58 \usepackage[((( resources.sphinx.chapterstyle )))]{((( resources.sphinx.texinputs | posix_path )))/fncychap}
58 \usepackage[((( resources.sphinx.chapterstyle )))]{((( resources.sphinx.texinputs | posix_path )))/fncychap}
59 \usepackage{longtable}
59 \usepackage{longtable}
60 \usepackage{((( resources.sphinx.texinputs | posix_path )))/sphinx}
60 \usepackage{((( resources.sphinx.texinputs | posix_path )))/sphinx}
61 \usepackage{multirow}
61 \usepackage{multirow}
62
62
63 \usepackage{amsmath}
63 \usepackage{amsmath}
64 \usepackage{amssymb}
64 \usepackage{amssymb}
65 \usepackage{ucs}
65 \usepackage{ucs}
66 \usepackage{enumerate}
66 \usepackage{enumerate}
67
67
68 % Used to make the Input/Output rules follow around the contents.
68 % Used to make the Input/Output rules follow around the contents.
69 \usepackage{needspace}
69 \usepackage{needspace}
70
70
71 % Pygments requirements
71 % Pygments requirements
72 \usepackage{fancyvrb}
72 \usepackage{fancyvrb}
73 \usepackage{color}
73 \usepackage{color}
74 % ansi colors additions
74 % ansi colors additions
75 \definecolor{darkgreen}{rgb}{.12,.54,.11}
75 \definecolor{darkgreen}{rgb}{.12,.54,.11}
76 \definecolor{lightgray}{gray}{.95}
76 \definecolor{lightgray}{gray}{.95}
77 \definecolor{brown}{rgb}{0.54,0.27,0.07}
77 \definecolor{brown}{rgb}{0.54,0.27,0.07}
78 \definecolor{purple}{rgb}{0.5,0.0,0.5}
78 \definecolor{purple}{rgb}{0.5,0.0,0.5}
79 \definecolor{darkgray}{gray}{0.25}
79 \definecolor{darkgray}{gray}{0.25}
80 \definecolor{lightred}{rgb}{1.0,0.39,0.28}
80 \definecolor{lightred}{rgb}{1.0,0.39,0.28}
81 \definecolor{lightgreen}{rgb}{0.48,0.99,0.0}
81 \definecolor{lightgreen}{rgb}{0.48,0.99,0.0}
82 \definecolor{lightblue}{rgb}{0.53,0.81,0.92}
82 \definecolor{lightblue}{rgb}{0.53,0.81,0.92}
83 \definecolor{lightpurple}{rgb}{0.87,0.63,0.87}
83 \definecolor{lightpurple}{rgb}{0.87,0.63,0.87}
84 \definecolor{lightcyan}{rgb}{0.5,1.0,0.83}
84 \definecolor{lightcyan}{rgb}{0.5,1.0,0.83}
85
85
86 % Needed to box output/input
86 % Needed to box output/input
87 \usepackage{tikz}
87 \usepackage{tikz}
88 \usetikzlibrary{calc,arrows,shadows}
88 \usetikzlibrary{calc,arrows,shadows}
89 \usepackage[framemethod=tikz]{mdframed}
89 \usepackage[framemethod=tikz]{mdframed}
90
90
91 \usepackage{alltt}
91 \usepackage{alltt}
92
92
93 % Used to load and display graphics
93 % Used to load and display graphics
94 \usepackage{graphicx}
94 \usepackage{graphicx}
95 \graphicspath{ {figs/} }
95 \graphicspath{ {figs/} }
96 \usepackage[Export]{adjustbox} % To resize
96 \usepackage[Export]{adjustbox} % To resize
97
97
98 % used so that images for notebooks which have spaces in the name can still be included
98 % used so that images for notebooks which have spaces in the name can still be included
99 \usepackage{grffile}
99 \usepackage{grffile}
100
100
101
101
102 % For formatting output while also word wrapping.
102 % For formatting output while also word wrapping.
103 \usepackage{listings}
103 \usepackage{listings}
104 \lstset{breaklines=true}
104 \lstset{breaklines=true}
105 \lstset{basicstyle=\small\ttfamily}
105 \lstset{basicstyle=\small\ttfamily}
106 \def\smaller{\fontsize{9.5pt}{9.5pt}\selectfont}
106 \def\smaller{\fontsize{9.5pt}{9.5pt}\selectfont}
107
107
108 %Pygments definitions
108 %Pygments definitions
109 ((( resources.sphinx.pygment_definitions )))
109 ((( resources.sphinx.pygment_definitions )))
110
110
111 %Set pygments styles if needed...
111 %Set pygments styles if needed...
112 ((* if resources.sphinx.outputstyle == 'notebook' *))
112 ((* if resources.sphinx.outputstyle == 'notebook' *))
113 \definecolor{nbframe-border}{rgb}{0.867,0.867,0.867}
113 \definecolor{nbframe-border}{rgb}{0.867,0.867,0.867}
114 \definecolor{nbframe-bg}{rgb}{0.969,0.969,0.969}
114 \definecolor{nbframe-bg}{rgb}{0.969,0.969,0.969}
115 \definecolor{nbframe-in-prompt}{rgb}{0.0,0.0,0.502}
115 \definecolor{nbframe-in-prompt}{rgb}{0.0,0.0,0.502}
116 \definecolor{nbframe-out-prompt}{rgb}{0.545,0.0,0.0}
116 \definecolor{nbframe-out-prompt}{rgb}{0.545,0.0,0.0}
117
117
118 \newenvironment{ColorVerbatim}
118 \newenvironment{ColorVerbatim}
119 {\begin{mdframed}[%
119 {\begin{mdframed}[%
120 roundcorner=1.0pt, %
120 roundcorner=1.0pt, %
121 backgroundcolor=nbframe-bg, %
121 backgroundcolor=nbframe-bg, %
122 userdefinedwidth=1\linewidth, %
122 userdefinedwidth=1\linewidth, %
123 leftmargin=0.1\linewidth, %
123 leftmargin=0.1\linewidth, %
124 innerleftmargin=0pt, %
124 innerleftmargin=0pt, %
125 innerrightmargin=0pt, %
125 innerrightmargin=0pt, %
126 linecolor=nbframe-border, %
126 linecolor=nbframe-border, %
127 linewidth=1pt, %
127 linewidth=1pt, %
128 usetwoside=false, %
128 usetwoside=false, %
129 everyline=true, %
129 everyline=true, %
130 innerlinewidth=3pt, %
130 innerlinewidth=3pt, %
131 innerlinecolor=nbframe-bg, %
131 innerlinecolor=nbframe-bg, %
132 middlelinewidth=1pt, %
132 middlelinewidth=1pt, %
133 middlelinecolor=nbframe-bg, %
133 middlelinecolor=nbframe-bg, %
134 outerlinewidth=0.5pt, %
134 outerlinewidth=0.5pt, %
135 outerlinecolor=nbframe-border, %
135 outerlinecolor=nbframe-border, %
136 needspace=0pt
136 needspace=0pt
137 ]}
137 ]}
138 {\end{mdframed}}
138 {\end{mdframed}}
139
139
140 \newenvironment{InvisibleVerbatim}
140 \newenvironment{InvisibleVerbatim}
141 {\begin{mdframed}[leftmargin=0.1\linewidth,innerleftmargin=3pt,innerrightmargin=3pt, userdefinedwidth=1\linewidth, linewidth=0pt, linecolor=white, usetwoside=false]}
141 {\begin{mdframed}[leftmargin=0.1\linewidth,innerleftmargin=3pt,innerrightmargin=3pt, userdefinedwidth=1\linewidth, linewidth=0pt, linecolor=white, usetwoside=false]}
142 {\end{mdframed}}
142 {\end{mdframed}}
143
143
144 \renewenvironment{Verbatim}[1][\unskip]
144 \renewenvironment{Verbatim}[1][\unskip]
145 {\begin{alltt}\smaller}
145 {\begin{alltt}\smaller}
146 {\end{alltt}}
146 {\end{alltt}}
147 ((* endif *))
147 ((* endif *))
148
148
149 % Help prevent overflowing lines due to urls and other hard-to-break
149 % Help prevent overflowing lines due to urls and other hard-to-break
150 % entities. This doesn't catch everything...
150 % entities. This doesn't catch everything...
151 \sloppy
151 \sloppy
152
152
153 % Document level variables
153 % Document level variables
154 \title{((( resources.metadata.name | escape_latex )))}
154 \title{((( resources.metadata.name | escape_latex )))}
155 \date{((( resources.sphinx.date | escape_latex )))}
155 \date{((( resources.sphinx.date | escape_latex )))}
156 \release{((( resources.sphinx.version | escape_latex )))}
156 \release{((( resources.sphinx.version | escape_latex )))}
157 \author{((( resources.sphinx.author | escape_latex )))}
157 \author{((( resources.sphinx.author | escape_latex )))}
158 \renewcommand{\releasename}{((( resources.sphinx.release | escape_latex )))}
158 \renewcommand{\releasename}{((( resources.sphinx.release | escape_latex )))}
159
159
160 % TODO: Add option for the user to specify a logo for his/her export.
160 % TODO: Add option for the user to specify a logo for his/her export.
161 \newcommand{\sphinxlogo}{}
161 \newcommand{\sphinxlogo}{}
162
162
163 % Make the index page of the document.
163 % Make the index page of the document.
164 \makeindex
164 \makeindex
165
165
166 % Import sphinx document type specifics.
166 % Import sphinx document type specifics.
167 ((* block sphinxheader *))((* endblock sphinxheader *))
167 ((* block sphinxheader *))((* endblock sphinxheader *))
168 ((* endblock header *))
168 ((* endblock header *))
169
169
170 %==============================================================================
170 %==============================================================================
171 % Body
171 % Body
172 %==============================================================================
172 %==============================================================================
173 ((* block body *))
173 ((* block body *))
174 ((* block bodyBegin *))
174 ((* block bodyBegin *))
175 % Body
175 % Body
176
176
177 % Start of the document
177 % Start of the document
178 \begin{document}
178 \begin{document}
179
179
180 ((* if resources.sphinx.header *))
180 ((* if resources.sphinx.header *))
181 \maketitle
181 \maketitle
182 ((* endif *))
182 ((* endif *))
183
183
184 ((* block toc *))
184 ((* block toc *))
185 \tableofcontents
185 \tableofcontents
186 ((* endblock toc *))
186 ((* endblock toc *))
187
187
188 ((* endblock bodyBegin *))
188 ((* endblock bodyBegin *))
189 ((( super() )))
189 ((( super() )))
190 ((* block bodyEnd *))
190 ((* block bodyEnd *))
191
191
192 \renewcommand{\indexname}{Index}
192 \renewcommand{\indexname}{Index}
193 \printindex
193 \printindex
194
194
195 ((* block bibliography *))
196 ((* endblock bibliography *))
197
195 % End of document
198 % End of document
196 \end{document}
199 \end{document}
197 ((* endblock bodyEnd *))
200 ((* endblock bodyEnd *))
198 ((* endblock body *))
201 ((* endblock body *))
199
202
200 %==============================================================================
203 %==============================================================================
201 % Footer
204 % Footer
202 %==============================================================================
205 %==============================================================================
203 ((* block footer *))
206 ((* block footer *))
204 ((* endblock footer *))
207 ((* endblock footer *))
205
208
206 %==============================================================================
209 %==============================================================================
207 % Headings
210 % Headings
208 %
211 %
209 % Purpose: Format pynb headers as sphinx headers. Depending on the Sphinx
212 % Purpose: Format pynb headers as sphinx headers. Depending on the Sphinx
210 % style that is active, this will change. Thus sphinx styles will
213 % style that is active, this will change. Thus sphinx styles will
211 % override the values here.
214 % override the values here.
212 %==============================================================================
215 %==============================================================================
213 ((* block headingcell -*))
216 ((* block headingcell -*))
214 \
217 \
215 ((*- if cell.level == 1 -*))
218 ((*- if cell.level == 1 -*))
216 ((* block h1 -*))part((* endblock h1 -*))
219 ((* block h1 -*))part((* endblock h1 -*))
217 ((*- elif cell.level == 2 -*))
220 ((*- elif cell.level == 2 -*))
218 ((* block h2 -*))chapter((* endblock h2 -*))
221 ((* block h2 -*))chapter((* endblock h2 -*))
219 ((*- elif cell.level == 3 -*))
222 ((*- elif cell.level == 3 -*))
220 ((* block h3 -*))section((* endblock h3 -*))
223 ((* block h3 -*))section((* endblock h3 -*))
221 ((*- elif cell.level == 4 -*))
224 ((*- elif cell.level == 4 -*))
222 ((* block h4 -*))subsection((* endblock h4 -*))
225 ((* block h4 -*))subsection((* endblock h4 -*))
223 ((*- elif cell.level == 5 -*))
226 ((*- elif cell.level == 5 -*))
224 ((* block h5 -*))subsubsection((* endblock h5 -*))
227 ((* block h5 -*))subsubsection((* endblock h5 -*))
225 ((*- elif cell.level == 6 -*))
228 ((*- elif cell.level == 6 -*))
226 ((* block h6 -*))paragraph((* endblock h6 -*))
229 ((* block h6 -*))paragraph((* endblock h6 -*))
227
230
228 ((= It's important to make sure that underscores (which tend to be common
231 ((= It's important to make sure that underscores (which tend to be common
229 in IPYNB file titles) do not make their way into latex. Sometimes this
232 in IPYNB file titles) do not make their way into latex. Sometimes this
230 causes latex to barf. =))
233 causes latex to barf. =))
231 ((*- endif -*))
234 ((*- endif -*))
232 {((( cell.source | markdown2latex )))}
235 {((( cell.source | parse_citation | markdown2latex )))}
233 ((*- endblock headingcell *))
236 ((*- endblock headingcell *))
234
237
235 %==============================================================================
238 %==============================================================================
236 % Markdown
239 % Markdown
237 %
240 %
238 % Purpose: Convert markdown to latex. Here markdown2latex is explicitly
241 % Purpose: Convert markdown to latex. Here markdown2latex is explicitly
239 % called since we know we want latex output.
242 % called since we know we want latex output.
240 %==============================================================================
243 %==============================================================================
241 ((*- block markdowncell scoped-*))
244 ((*- block markdowncell scoped-*))
242 ((( cell.source | markdown2latex )))
245 ((( cell.source | parse_citation | markdown2latex )))
243 ((*- endblock markdowncell -*))
246 ((*- endblock markdowncell -*))
244
247
245 %==============================================================================
248 %==============================================================================
246 % Rawcell
249 % Rawcell
247 %
250 %
248 % Purpose: Raw text cells allow the user to manually inject document code that
251 % Purpose: Raw text cells allow the user to manually inject document code that
249 % will not get touched by the templating system.
252 % will not get touched by the templating system.
250 %==============================================================================
253 %==============================================================================
251 ((*- block rawcell *))
254 ((*- block rawcell *))
252 ((( cell.source | wrap_text(wrap_size) )))
255 ((( cell.source | wrap_text(wrap_size) )))
253 ((* endblock rawcell -*))
256 ((* endblock rawcell -*))
254
257
255 %==============================================================================
258 %==============================================================================
256 % Unknowncell
259 % Unknowncell
257 %
260 %
258 % Purpose: This is the catch anything unhandled. To display this data, we
261 % Purpose: This is the catch anything unhandled. To display this data, we
259 % remove all possible latex conflicts and wrap the characters so they
262 % remove all possible latex conflicts and wrap the characters so they
260 % can't flow off of the page.
263 % can't flow off of the page.
261 %==============================================================================
264 %==============================================================================
262 ((* block unknowncell scoped*))
265 ((* block unknowncell scoped*))
263 % Unsupported cell type, no formatting
266 % Unsupported cell type, no formatting
264 ((( cell.source | wrap_text | escape_latex )))
267 ((( cell.source | wrap_text | escape_latex )))
265 ((* endblock unknowncell *))
268 ((* endblock unknowncell *))
266
269
267 %==============================================================================
270 %==============================================================================
268 % Input
271 % Input
269 %==============================================================================
272 %==============================================================================
270 ((* block input *))
273 ((* block input *))
271
274
272 % Make sure that atleast 4 lines are below the HR
275 % Make sure that atleast 4 lines are below the HR
273 \needspace{((( min_header_lines )))\baselineskip}
276 \needspace{((( min_header_lines )))\baselineskip}
274
277
275 ((* if resources.sphinx.outputstyle == 'simple' *))
278 ((* if resources.sphinx.outputstyle == 'simple' *))
276
279
277 % Add a horizantal break, along with break title.
280 % Add a horizantal break, along with break title.
278 \vspace{10pt}
281 \vspace{10pt}
279 {\scriptsize Input}\\*
282 {\scriptsize Input}\\*
280 \rule[10pt]{\linewidth}{0.5pt}
283 \rule[10pt]{\linewidth}{0.5pt}
281 \vspace{-25pt}
284 \vspace{-25pt}
282
285
283 % Add contents below.
286 % Add contents below.
284 ((( cell.input | highlight2latex )))
287 ((( cell.input | highlight2latex )))
285
288
286 ((* elif resources.sphinx.outputstyle == 'notebook' *))
289 ((* elif resources.sphinx.outputstyle == 'notebook' *))
287 \vspace{6pt}
290 \vspace{6pt}
288 ((( write_prompt("In", cell.prompt_number, "nbframe-in-prompt") )))
291 ((( write_prompt("In", cell.prompt_number, "nbframe-in-prompt") )))
289 \vspace{-2.65\baselineskip}
292 \vspace{-2.65\baselineskip}
290 \begin{ColorVerbatim}
293 \begin{ColorVerbatim}
291 \vspace{-0.7\baselineskip}
294 \vspace{-0.7\baselineskip}
292 ((( cell.input | highlight2latex )))
295 ((( cell.input | highlight2latex )))
293 ((* if cell.input == None or cell.input == '' *))
296 ((* if cell.input == None or cell.input == '' *))
294 \vspace{0.3\baselineskip}
297 \vspace{0.3\baselineskip}
295 ((* else *))
298 ((* else *))
296 \vspace{-0.2\baselineskip}
299 \vspace{-0.2\baselineskip}
297 ((* endif *))
300 ((* endif *))
298 \end{ColorVerbatim}
301 \end{ColorVerbatim}
299 ((* endif *))
302 ((* endif *))
300 ((* endblock input *))
303 ((* endblock input *))
301
304
302 %==============================================================================
305 %==============================================================================
303 % Output_Group
306 % Output_Group
304 %
307 %
305 % Purpose: Make sure that only one header bar only attaches to the output
308 % Purpose: Make sure that only one header bar only attaches to the output
306 % once. By keeping track of when an input group is started
309 % once. By keeping track of when an input group is started
307 %==============================================================================
310 %==============================================================================
308 ((* block output_group *))
311 ((* block output_group *))
309 ((* if cell.outputs.__len__() > 0 *))
312 ((* if cell.outputs.__len__() > 0 *))
310
313
311 % If the first block is an image, minipage the image. Else
314 % If the first block is an image, minipage the image. Else
312 % request a certain amount of space for the input text.
315 % request a certain amount of space for the input text.
313 ((( iff_figure(cell.outputs[0], "\\begin{minipage}{1.0\\textwidth}", "\\needspace{" ~ min_header_lines ~ "\\baselineskip}") )))
316 ((( iff_figure(cell.outputs[0], "\\begin{minipage}{1.0\\textwidth}", "\\needspace{" ~ min_header_lines ~ "\\baselineskip}") )))
314
317
315 ((* if resources.sphinx.outputstyle == 'simple' *))
318 ((* if resources.sphinx.outputstyle == 'simple' *))
316
319
317 % Add a horizantal break, along with break title.
320 % Add a horizantal break, along with break title.
318 \vspace{10pt}
321 \vspace{10pt}
319 {\scriptsize Output}\\*
322 {\scriptsize Output}\\*
320 \rule[10pt]{\linewidth}{0.5pt}
323 \rule[10pt]{\linewidth}{0.5pt}
321 \vspace{-20pt}
324 \vspace{-20pt}
322
325
323 % Add the contents of the first block.
326 % Add the contents of the first block.
324 ((( render_output(cell.outputs[0]) )))
327 ((( render_output(cell.outputs[0]) )))
325
328
326 % Close the minipage.
329 % Close the minipage.
327 ((( iff_figure(cell.outputs[0], "\\end{minipage}", "") )))
330 ((( iff_figure(cell.outputs[0], "\\end{minipage}", "") )))
328
331
329 % Add remainer of the document contents below.
332 % Add remainer of the document contents below.
330 ((* for output in cell.outputs[1:] *))
333 ((* for output in cell.outputs[1:] *))
331 ((( render_output(output, cell.prompt_number) )))
334 ((( render_output(output, cell.prompt_number) )))
332 ((* endfor *))
335 ((* endfor *))
333 ((* elif resources.sphinx.outputstyle == 'notebook' *))
336 ((* elif resources.sphinx.outputstyle == 'notebook' *))
334
337
335 % Add document contents.
338 % Add document contents.
336 ((* for output in cell.outputs *))
339 ((* for output in cell.outputs *))
337 ((( render_output(output, cell.prompt_number) )))
340 ((( render_output(output, cell.prompt_number) )))
338 ((* endfor *))
341 ((* endfor *))
339 ((* endif *))
342 ((* endif *))
340 ((* endif *))
343 ((* endif *))
341 ((* endblock *))
344 ((* endblock *))
342
345
343 %==============================================================================
346 %==============================================================================
344 % Additional formating
347 % Additional formating
345 %==============================================================================
348 %==============================================================================
346 ((* block data_text *))
349 ((* block data_text *))
347 ((( custom_verbatim(output.text) | ansi2latex )))
350 ((( custom_verbatim(output.text) | ansi2latex )))
348 ((* endblock *))
351 ((* endblock *))
349
352
350 ((* block traceback_line *))
353 ((* block traceback_line *))
351 ((( conditionally_center_output( line | indent| strip_ansi ) )))
354 ((( conditionally_center_output( line | indent| strip_ansi ) )))
352 ((* endblock traceback_line *))
355 ((* endblock traceback_line *))
353
356
354 %==============================================================================
357 %==============================================================================
355 % Supported image formats
358 % Supported image formats
356 %==============================================================================
359 %==============================================================================
357 ((*- block data_png -*))
360 ((*- block data_png -*))
358 ((( conditionally_center_output(insert_graphics(output.png_filename | posix_path)) )))
361 ((( conditionally_center_output(insert_graphics(output.png_filename | posix_path)) )))
359 ((*- endblock -*))
362 ((*- endblock -*))
360
363
361 ((*- block data_jpg -*))
364 ((*- block data_jpg -*))
362 ((( conditionally_center_output(insert_graphics(output.jpg_filename | posix_path)) )))
365 ((( conditionally_center_output(insert_graphics(output.jpg_filename | posix_path)) )))
363 ((*- endblock -*))
366 ((*- endblock -*))
364
367
365 ((*- block data_svg -*))
368 ((*- block data_svg -*))
366 ((( conditionally_center_output(insert_graphics(output.svg_filename | posix_path)) )))
369 ((( conditionally_center_output(insert_graphics(output.svg_filename | posix_path)) )))
367 ((*- endblock -*))
370 ((*- endblock -*))
368
371
369 ((*- block data_pdf -*))
372 ((*- block data_pdf -*))
370 ((( conditionally_center_output(insert_graphics(output.pdf_filename | posix_path)) )))
373 ((( conditionally_center_output(insert_graphics(output.pdf_filename | posix_path)) )))
371 ((*- endblock -*))
374 ((*- endblock -*))
372
375
373 ((*- block data_latex *))
376 ((*- block data_latex *))
374 ((* if resources.sphinx.centeroutput *))
377 ((* if resources.sphinx.centeroutput *))
375 \begin{center}
378 \begin{center}
376 ((* endif -*))
379 ((* endif -*))
377 ((( output.latex | strip_math_space )))
380 ((( output.latex | strip_math_space )))
378 ((*- if resources.sphinx.centeroutput *))
381 ((*- if resources.sphinx.centeroutput *))
379 \end{center}
382 \end{center}
380 ((* endif -*))
383 ((* endif -*))
381 ((*- endblock -*))
384 ((*- endblock -*))
382
385
383 %==============================================================================
386 %==============================================================================
384 % Support Macros
387 % Support Macros
385 %==============================================================================
388 %==============================================================================
386
389
387 % Name: write_prompt
390 % Name: write_prompt
388 % Purpose: Renders an output/input prompt for notebook style pdfs
391 % Purpose: Renders an output/input prompt for notebook style pdfs
389 ((* macro write_prompt(prompt, number, color) -*))
392 ((* macro write_prompt(prompt, number, color) -*))
390 \makebox[0.1\linewidth]{\smaller\hfill\tt\color{((( color )))}((( prompt )))\hspace{4pt}{[}((( number ))){]}:\hspace{4pt}}\\*
393 \makebox[0.1\linewidth]{\smaller\hfill\tt\color{((( color )))}((( prompt )))\hspace{4pt}{[}((( number ))){]}:\hspace{4pt}}\\*
391 ((*- endmacro *))
394 ((*- endmacro *))
392
395
393 % Name: render_output
396 % Name: render_output
394 % Purpose: Renders an output block appropriately.
397 % Purpose: Renders an output block appropriately.
395 ((* macro render_output(output, prompt_number) -*))
398 ((* macro render_output(output, prompt_number) -*))
396 ((*- if output.output_type == 'pyerr' -*))
399 ((*- if output.output_type == 'pyerr' -*))
397 ((*- block pyerr scoped *))
400 ((*- block pyerr scoped *))
398 ((( custom_verbatim(super()) )))
401 ((( custom_verbatim(super()) )))
399 ((* endblock pyerr -*))
402 ((* endblock pyerr -*))
400 ((*- else -*))
403 ((*- else -*))
401
404
402 ((* if resources.sphinx.outputstyle == 'notebook' *))
405 ((* if resources.sphinx.outputstyle == 'notebook' *))
403 ((*- if output.output_type == 'pyout' -*))
406 ((*- if output.output_type == 'pyout' -*))
404 ((( write_prompt("Out", prompt_number, "nbframe-out-prompt") )))
407 ((( write_prompt("Out", prompt_number, "nbframe-out-prompt") )))
405 \vspace{-2.55\baselineskip}
408 \vspace{-2.55\baselineskip}
406 ((*- endif -*))
409 ((*- endif -*))
407
410
408 \begin{InvisibleVerbatim}
411 \begin{InvisibleVerbatim}
409 \vspace{-0.5\baselineskip}
412 \vspace{-0.5\baselineskip}
410 ((*- endif -*))
413 ((*- endif -*))
411
414
412 ((*- block display_data scoped -*))
415 ((*- block display_data scoped -*))
413 ((( super() )))
416 ((( super() )))
414 ((*- endblock display_data -*))
417 ((*- endblock display_data -*))
415
418
416 ((* if resources.sphinx.outputstyle == 'notebook' *))
419 ((* if resources.sphinx.outputstyle == 'notebook' *))
417 \end{InvisibleVerbatim}
420 \end{InvisibleVerbatim}
418 ((*- endif -*))
421 ((*- endif -*))
419 ((*- endif -*))
422 ((*- endif -*))
420 ((*- endmacro *))
423 ((*- endmacro *))
421
424
422 % Name: iff_figure
425 % Name: iff_figure
423 % Purpose: If the output block provided is a figure type, the 'true_content'
426 % Purpose: If the output block provided is a figure type, the 'true_content'
424 % parameter will be returned. Else, the 'false_content'.
427 % parameter will be returned. Else, the 'false_content'.
425 ((* macro iff_figure(output, true_content, false_content) -*))
428 ((* macro iff_figure(output, true_content, false_content) -*))
426 ((*- set is_figure = false -*))
429 ((*- set is_figure = false -*))
427 ((*- for type in output | filter_data_type -*))
430 ((*- for type in output | filter_data_type -*))
428 ((*- if type in ['pdf', 'svg', 'png', 'jpeg','html']*))
431 ((*- if type in ['pdf', 'svg', 'png', 'jpeg','html']*))
429 ((*- set is_figure = true -*))
432 ((*- set is_figure = true -*))
430 ((*- endif -*))
433 ((*- endif -*))
431 ((*- endfor -*))
434 ((*- endfor -*))
432
435
433 ((* if is_figure -*))
436 ((* if is_figure -*))
434 ((( true_content )))
437 ((( true_content )))
435 ((*- else -*))
438 ((*- else -*))
436 ((( false_content )))
439 ((( false_content )))
437 ((*- endif *))
440 ((*- endif *))
438 ((*- endmacro *))
441 ((*- endmacro *))
439
442
440 % Name: custom_verbatim
443 % Name: custom_verbatim
441 % Purpose: This macro creates a verbatim style block that fits the existing
444 % Purpose: This macro creates a verbatim style block that fits the existing
442 % sphinx style more readily than standard verbatim blocks.
445 % sphinx style more readily than standard verbatim blocks.
443 ((* macro custom_verbatim(text) -*))
446 ((* macro custom_verbatim(text) -*))
444 \begin{alltt}
447 \begin{alltt}
445 ((*- if resources.sphinx.centeroutput *))\begin{center} ((* endif -*))
448 ((*- if resources.sphinx.centeroutput *))\begin{center} ((* endif -*))
446 ((( text | wrap_text(wrap_size) | escape_latex )))
449 ((( text | wrap_text(wrap_size) | escape_latex )))
447 ((*- if resources.sphinx.centeroutput *))\end{center}((* endif -*))
450 ((*- if resources.sphinx.centeroutput *))\end{center}((* endif -*))
448 \end{alltt}
451 \end{alltt}
449 ((*- endmacro *))
452 ((*- endmacro *))
450
453
451 % Name: conditionally_center_output
454 % Name: conditionally_center_output
452 % Purpose: This macro centers the output if the output centering is enabled.
455 % Purpose: This macro centers the output if the output centering is enabled.
453 ((* macro conditionally_center_output(text) -*))
456 ((* macro conditionally_center_output(text) -*))
454 ((* if resources.sphinx.centeroutput *))
457 ((* if resources.sphinx.centeroutput *))
455 {\centering
458 {\centering
456 ((* endif *))
459 ((* endif *))
457 ((( text )))
460 ((( text )))
458 ((* if resources.sphinx.centeroutput *))}
461 ((* if resources.sphinx.centeroutput *))}
459 ((* endif *))
462 ((* endif *))
460 ((*- endmacro *))
463 ((*- endmacro *))
461
464
462 % Name: insert_graphics
465 % Name: insert_graphics
463 % Purpose: This macro will insert an image in the latex document given a path.
466 % Purpose: This macro will insert an image in the latex document given a path.
464 ((* macro insert_graphics(path) -*))
467 ((* macro insert_graphics(path) -*))
465 \begin{center}
468 \begin{center}
466 \includegraphics[max size={\textwidth}{\textheight}]{((( path )))}
469 \includegraphics[max size={\textwidth}{\textheight}]{((( path )))}
467 \par
470 \par
468 \end{center}
471 \end{center}
469 ((*- endmacro *))
472 ((*- endmacro *))
General Comments 0
You need to be logged in to leave comments. Login now