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