##// 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 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 72 }
72 73
73 74 #-----------------------------------------------------------------------------
74 75 # Class
75 76 #-----------------------------------------------------------------------------
76 77
77 78 class ResourcesDict(collections.defaultdict):
78 79 def __missing__(self, key):
79 80 return ''
80 81
81 82
82 83 class Exporter(LoggingConfigurable):
83 84 """
84 85 Exports notebooks into other file formats. Uses Jinja 2 templating engine
85 86 to output new formats. Inherit from this class if you are creating a new
86 87 template type along with new filters/preprocessors. If the filters/
87 88 preprocessors provided by default suffice, there is no need to inherit from
88 89 this class. Instead, override the template_file and file_extension
89 90 traits via a config file.
90 91
91 92 {filters}
92 93 """
93 94
94 95 # finish the docstring
95 96 __doc__ = __doc__.format(filters = '- '+'\n - '.join(default_filters.keys()))
96 97
97 98
98 99 template_file = Unicode(u'default',
99 100 config=True,
100 101 help="Name of the template file to use")
101 102 def _template_file_changed(self, name, old, new):
102 103 if new=='default':
103 104 self.template_file = self.default_template
104 105 else:
105 106 self.template_file = new
106 107 self.template = None
107 108 self._load_template()
108 109
109 110 default_template = Unicode(u'')
110 111 template = Any()
111 112 environment = Any()
112 113
113 114 file_extension = Unicode(
114 115 'txt', config=True,
115 116 help="Extension of the file that should be written to disk"
116 117 )
117 118
118 119 template_path = List(['.'], config=True)
119 120 def _template_path_changed(self, name, old, new):
120 121 self._load_template()
121 122
122 123 default_template_path = Unicode(
123 124 os.path.join("..", "templates"),
124 125 help="Path where the template files are located.")
125 126
126 127 template_skeleton_path = Unicode(
127 128 os.path.join("..", "templates", "skeleton"),
128 129 help="Path where the template skeleton files are located.")
129 130
130 131 #Jinja block definitions
131 132 jinja_comment_block_start = Unicode("", config=True)
132 133 jinja_comment_block_end = Unicode("", config=True)
133 134 jinja_variable_block_start = Unicode("", config=True)
134 135 jinja_variable_block_end = Unicode("", config=True)
135 136 jinja_logic_block_start = Unicode("", config=True)
136 137 jinja_logic_block_end = Unicode("", config=True)
137 138
138 139 #Extension that the template files use.
139 140 template_extension = Unicode(".tpl", config=True)
140 141
141 142 #Configurability, allows the user to easily add filters and preprocessors.
142 143 preprocessors = List(config=True,
143 144 help="""List of preprocessors, by name or namespace, to enable.""")
144 145
145 146 filters = Dict(config=True,
146 147 help="""Dictionary of filters, by name and namespace, to add to the Jinja
147 148 environment.""")
148 149
149 150 default_preprocessors = List([nbpreprocessors.coalesce_streams,
150 151 nbpreprocessors.SVG2PDFPreprocessor,
151 152 nbpreprocessors.ExtractOutputPreprocessor,
152 153 nbpreprocessors.CSSHTMLHeaderPreprocessor,
153 154 nbpreprocessors.RevealHelpPreprocessor,
154 155 nbpreprocessors.LatexPreprocessor,
155 156 nbpreprocessors.SphinxPreprocessor],
156 157 config=True,
157 158 help="""List of preprocessors available by default, by name, namespace,
158 159 instance, or type.""")
159 160
160 161
161 162 def __init__(self, config=None, extra_loaders=None, **kw):
162 163 """
163 164 Public constructor
164 165
165 166 Parameters
166 167 ----------
167 168 config : config
168 169 User configuration instance.
169 170 extra_loaders : list[of Jinja Loaders]
170 171 ordered list of Jinja loader to find templates. Will be tried in order
171 172 before the default FileSystem ones.
172 173 template : str (optional, kw arg)
173 174 Template to use when exporting.
174 175 """
175 176 if not config:
176 177 config = self.default_config
177 178
178 179 super(Exporter, self).__init__(config=config, **kw)
179 180
180 181 #Init
181 182 self._init_template()
182 183 self._init_environment(extra_loaders=extra_loaders)
183 184 self._init_preprocessors()
184 185 self._init_filters()
185 186
186 187
187 188 @property
188 189 def default_config(self):
189 190 return Config()
190 191
191 192 def _config_changed(self, name, old, new):
192 193 """When setting config, make sure to start with our default_config"""
193 194 c = self.default_config
194 195 if new:
195 196 c.merge(new)
196 197 if c != old:
197 198 self.config = c
198 199 super(Exporter, self)._config_changed(name, old, c)
199 200
200 201
201 202 def _load_template(self):
202 203 """Load the Jinja template object from the template file
203 204
204 205 This is a no-op if the template attribute is already defined,
205 206 or the Jinja environment is not setup yet.
206 207
207 208 This is triggered by various trait changes that would change the template.
208 209 """
209 210 if self.template is not None:
210 211 return
211 212 # called too early, do nothing
212 213 if self.environment is None:
213 214 return
214 215 # Try different template names during conversion. First try to load the
215 216 # template by name with extension added, then try loading the template
216 217 # as if the name is explicitly specified, then try the name as a
217 218 # 'flavor', and lastly just try to load the template by module name.
218 219 module_name = self.__module__.rsplit('.', 1)[-1]
219 220 try_names = []
220 221 if self.template_file:
221 222 try_names.extend([
222 223 self.template_file + self.template_extension,
223 224 self.template_file,
224 225 module_name + '_' + self.template_file + self.template_extension,
225 226 ])
226 227 try_names.append(module_name + self.template_extension)
227 228 for try_name in try_names:
228 229 self.log.debug("Attempting to load template %s", try_name)
229 230 try:
230 231 self.template = self.environment.get_template(try_name)
231 232 except (TemplateNotFound, IOError):
232 233 pass
233 234 except Exception as e:
234 235 self.log.warn("Unexpected exception loading template: %s", try_name, exc_info=True)
235 236 else:
236 237 self.log.info("Loaded template %s", try_name)
237 238 break
238 239
239 240 def from_notebook_node(self, nb, resources=None, **kw):
240 241 """
241 242 Convert a notebook from a notebook node instance.
242 243
243 244 Parameters
244 245 ----------
245 246 nb : Notebook node
246 247 resources : dict (**kw)
247 248 of additional resources that can be accessed read/write by
248 249 preprocessors and filters.
249 250 """
250 251 nb_copy = copy.deepcopy(nb)
251 252 resources = self._init_resources(resources)
252 253
253 254 # Preprocess
254 255 nb_copy, resources = self._preprocess(nb_copy, resources)
255 256
256 257 self._load_template()
257 258
258 259 if self.template is not None:
259 260 output = self.template.render(nb=nb_copy, resources=resources)
260 261 else:
261 262 raise IOError('template file "%s" could not be found' % self.template_file)
262 263 return output, resources
263 264
264 265
265 266 def from_filename(self, filename, resources=None, **kw):
266 267 """
267 268 Convert a notebook from a notebook file.
268 269
269 270 Parameters
270 271 ----------
271 272 filename : str
272 273 Full filename of the notebook file to open and convert.
273 274 """
274 275
275 276 #Pull the metadata from the filesystem.
276 277 if resources is None:
277 278 resources = ResourcesDict()
278 279 if not 'metadata' in resources or resources['metadata'] == '':
279 280 resources['metadata'] = ResourcesDict()
280 281 basename = os.path.basename(filename)
281 282 notebook_name = basename[:basename.rfind('.')]
282 283 resources['metadata']['name'] = notebook_name
283 284
284 285 modified_date = datetime.datetime.fromtimestamp(os.path.getmtime(filename))
285 286 resources['metadata']['modified_date'] = modified_date.strftime("%B %d, %Y")
286 287
287 288 with io.open(filename) as f:
288 289 return self.from_notebook_node(nbformat.read(f, 'json'), resources=resources,**kw)
289 290
290 291
291 292 def from_file(self, file_stream, resources=None, **kw):
292 293 """
293 294 Convert a notebook from a notebook file.
294 295
295 296 Parameters
296 297 ----------
297 298 file_stream : file-like object
298 299 Notebook file-like object to convert.
299 300 """
300 301 return self.from_notebook_node(nbformat.read(file_stream, 'json'), resources=resources, **kw)
301 302
302 303
303 304 def register_preprocessor(self, preprocessor, enabled=False):
304 305 """
305 306 Register a preprocessor.
306 307 Preprocessors are classes that act upon the notebook before it is
307 308 passed into the Jinja templating engine. Preprocessors are also
308 309 capable of passing additional information to the Jinja
309 310 templating engine.
310 311
311 312 Parameters
312 313 ----------
313 314 preprocessor : preprocessor
314 315 """
315 316 if preprocessor is None:
316 317 raise TypeError('preprocessor')
317 318 isclass = isinstance(preprocessor, type)
318 319 constructed = not isclass
319 320
320 321 #Handle preprocessor's registration based on it's type
321 322 if constructed and isinstance(preprocessor, py3compat.string_types):
322 323 #Preprocessor is a string, import the namespace and recursively call
323 324 #this register_preprocessor method
324 325 preprocessor_cls = import_item(preprocessor)
325 326 return self.register_preprocessor(preprocessor_cls, enabled)
326 327
327 328 if constructed and hasattr(preprocessor, '__call__'):
328 329 #Preprocessor is a function, no need to construct it.
329 330 #Register and return the preprocessor.
330 331 if enabled:
331 332 preprocessor.enabled = True
332 333 self._preprocessors.append(preprocessor)
333 334 return preprocessor
334 335
335 336 elif isclass and isinstance(preprocessor, MetaHasTraits):
336 337 #Preprocessor is configurable. Make sure to pass in new default for
337 338 #the enabled flag if one was specified.
338 339 self.register_preprocessor(preprocessor(parent=self), enabled)
339 340
340 341 elif isclass:
341 342 #Preprocessor is not configurable, construct it
342 343 self.register_preprocessor(preprocessor(), enabled)
343 344
344 345 else:
345 346 #Preprocessor is an instance of something without a __call__
346 347 #attribute.
347 348 raise TypeError('preprocessor')
348 349
349 350
350 351 def register_filter(self, name, jinja_filter):
351 352 """
352 353 Register a filter.
353 354 A filter is a function that accepts and acts on one string.
354 355 The filters are accesible within the Jinja templating engine.
355 356
356 357 Parameters
357 358 ----------
358 359 name : str
359 360 name to give the filter in the Jinja engine
360 361 filter : filter
361 362 """
362 363 if jinja_filter is None:
363 364 raise TypeError('filter')
364 365 isclass = isinstance(jinja_filter, type)
365 366 constructed = not isclass
366 367
367 368 #Handle filter's registration based on it's type
368 369 if constructed and isinstance(jinja_filter, py3compat.string_types):
369 370 #filter is a string, import the namespace and recursively call
370 371 #this register_filter method
371 372 filter_cls = import_item(jinja_filter)
372 373 return self.register_filter(name, filter_cls)
373 374
374 375 if constructed and hasattr(jinja_filter, '__call__'):
375 376 #filter is a function, no need to construct it.
376 377 self.environment.filters[name] = jinja_filter
377 378 return jinja_filter
378 379
379 380 elif isclass and isinstance(jinja_filter, MetaHasTraits):
380 381 #filter is configurable. Make sure to pass in new default for
381 382 #the enabled flag if one was specified.
382 383 filter_instance = jinja_filter(parent=self)
383 384 self.register_filter(name, filter_instance )
384 385
385 386 elif isclass:
386 387 #filter is not configurable, construct it
387 388 filter_instance = jinja_filter()
388 389 self.register_filter(name, filter_instance)
389 390
390 391 else:
391 392 #filter is an instance of something without a __call__
392 393 #attribute.
393 394 raise TypeError('filter')
394 395
395 396
396 397 def _init_template(self):
397 398 """
398 399 Make sure a template name is specified. If one isn't specified, try to
399 400 build one from the information we know.
400 401 """
401 402 self._template_file_changed('template_file', self.template_file, self.template_file)
402 403
403 404
404 405 def _init_environment(self, extra_loaders=None):
405 406 """
406 407 Create the Jinja templating environment.
407 408 """
408 409 here = os.path.dirname(os.path.realpath(__file__))
409 410 loaders = []
410 411 if extra_loaders:
411 412 loaders.extend(extra_loaders)
412 413
413 414 paths = self.template_path
414 415 paths.extend([os.path.join(here, self.default_template_path),
415 416 os.path.join(here, self.template_skeleton_path)])
416 417 loaders.append(FileSystemLoader(paths))
417 418
418 419 self.environment = Environment(
419 420 loader= ChoiceLoader(loaders),
420 421 extensions=JINJA_EXTENSIONS
421 422 )
422 423
423 424 #Set special Jinja2 syntax that will not conflict with latex.
424 425 if self.jinja_logic_block_start:
425 426 self.environment.block_start_string = self.jinja_logic_block_start
426 427 if self.jinja_logic_block_end:
427 428 self.environment.block_end_string = self.jinja_logic_block_end
428 429 if self.jinja_variable_block_start:
429 430 self.environment.variable_start_string = self.jinja_variable_block_start
430 431 if self.jinja_variable_block_end:
431 432 self.environment.variable_end_string = self.jinja_variable_block_end
432 433 if self.jinja_comment_block_start:
433 434 self.environment.comment_start_string = self.jinja_comment_block_start
434 435 if self.jinja_comment_block_end:
435 436 self.environment.comment_end_string = self.jinja_comment_block_end
436 437
437 438
438 439 def _init_preprocessors(self):
439 440 """
440 441 Register all of the preprocessors needed for this exporter, disabled
441 442 unless specified explicitly.
442 443 """
443 444 self._preprocessors = []
444 445
445 446 #Load default preprocessors (not necessarly enabled by default).
446 447 if self.default_preprocessors:
447 448 for preprocessor in self.default_preprocessors:
448 449 self.register_preprocessor(preprocessor)
449 450
450 451 #Load user preprocessors. Enable by default.
451 452 if self.preprocessors:
452 453 for preprocessor in self.preprocessors:
453 454 self.register_preprocessor(preprocessor, enabled=True)
454 455
455 456
456 457 def _init_filters(self):
457 458 """
458 459 Register all of the filters required for the exporter.
459 460 """
460 461
461 462 #Add default filters to the Jinja2 environment
462 463 for key, value in default_filters.items():
463 464 self.register_filter(key, value)
464 465
465 466 #Load user filters. Overwrite existing filters if need be.
466 467 if self.filters:
467 468 for key, user_filter in self.filters.items():
468 469 self.register_filter(key, user_filter)
469 470
470 471
471 472 def _init_resources(self, resources):
472 473
473 474 #Make sure the resources dict is of ResourcesDict type.
474 475 if resources is None:
475 476 resources = ResourcesDict()
476 477 if not isinstance(resources, ResourcesDict):
477 478 new_resources = ResourcesDict()
478 479 new_resources.update(resources)
479 480 resources = new_resources
480 481
481 482 #Make sure the metadata extension exists in resources
482 483 if 'metadata' in resources:
483 484 if not isinstance(resources['metadata'], ResourcesDict):
484 485 resources['metadata'] = ResourcesDict(resources['metadata'])
485 486 else:
486 487 resources['metadata'] = ResourcesDict()
487 488 if not resources['metadata']['name']:
488 489 resources['metadata']['name'] = 'Notebook'
489 490
490 491 #Set the output extension
491 492 resources['output_extension'] = self.file_extension
492 493 return resources
493 494
494 495
495 496 def _preprocess(self, nb, resources):
496 497 """
497 498 Preprocess the notebook before passing it into the Jinja engine.
498 499 To preprocess the notebook is to apply all of the
499 500
500 501 Parameters
501 502 ----------
502 503 nb : notebook node
503 504 notebook that is being exported.
504 505 resources : a dict of additional resources that
505 506 can be accessed read/write by preprocessors
506 507 and filters.
507 508 """
508 509
509 510 # Do a copy.deepcopy first,
510 511 # we are never safe enough with what the preprocessors could do.
511 512 nbc = copy.deepcopy(nb)
512 513 resc = copy.deepcopy(resources)
513 514
514 515 #Run each preprocessor on the notebook. Carry the output along
515 516 #to each preprocessor
516 517 for preprocessor in self._preprocessors:
517 518 nbc, resc = preprocessor(nbc, resc)
518 519 return nbc, resc
@@ -1,6 +1,7 b''
1 1 from .ansi import *
2 2 from .datatypefilter import *
3 3 from .highlight import *
4 4 from .latex import *
5 5 from .markdown import *
6 6 from .strings import *
7 from .citation import * No newline at end of file
@@ -1,270 +1,274 b''
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 | markdown2latex )))
106 ((( cell.source | parse_citation | markdown2latex )))
107 107 ((* endblock markdowncell *))
108 108
109 109 ((* block headingcell scoped -*))
110 ((( ('#' * cell.level + cell.source) | replace('\n', ' ') | markdown2latex )))
110 ((( ('#' * cell.level + cell.source) | replace('\n', ' ') | parse_citation | 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
131 ((* block bibliography *))
132 ((* endblock bibliography *))
133
130 134 \end{document}
131 135 ((* endblock bodyEnd *))
132 136 ((* endblock body *))
133 137
134 138 ((* block header *))
135 139 %% This file was auto-generated by IPython.
136 140 %% Conversion from the original notebook file:
137 141 %%
138 142 \documentclass[11pt,english]{article}
139 143
140 144 %% This is the automatic preamble used by IPython. Note that it does *not*
141 145 %% include a documentclass declaration, that is added at runtime to the overall
142 146 %% document.
143 147
144 148 \usepackage{amsmath}
145 149 \usepackage{amssymb}
146 150 \usepackage{graphicx}
147 151 \usepackage{grffile}
148 152 \usepackage{ucs}
149 153 \usepackage[utf8x]{inputenc}
150 154
151 155 % Scale down larger images
152 156 \usepackage[export]{adjustbox}
153 157
154 158 %fancy verbatim
155 159 \usepackage{fancyvrb}
156 160 % needed for markdown enumerations to work
157 161 \usepackage{enumerate}
158 162
159 163 % Slightly bigger margins than the latex defaults
160 164 \usepackage{geometry}
161 165 \geometry{verbose,tmargin=3cm,bmargin=3cm,lmargin=2.5cm,rmargin=2.5cm}
162 166
163 167 % Define a few colors for use in code, links and cell shading
164 168 \usepackage{color}
165 169 \definecolor{orange}{cmyk}{0,0.4,0.8,0.2}
166 170 \definecolor{darkorange}{rgb}{.71,0.21,0.01}
167 171 \definecolor{darkgreen}{rgb}{.12,.54,.11}
168 172 \definecolor{myteal}{rgb}{.26, .44, .56}
169 173 \definecolor{gray}{gray}{0.45}
170 174 \definecolor{lightgray}{gray}{.95}
171 175 \definecolor{mediumgray}{gray}{.8}
172 176 \definecolor{inputbackground}{rgb}{.95, .95, .85}
173 177 \definecolor{outputbackground}{rgb}{.95, .95, .95}
174 178 \definecolor{traceback}{rgb}{1, .95, .95}
175 179
176 180 % new ansi colors
177 181 \definecolor{brown}{rgb}{0.54,0.27,0.07}
178 182 \definecolor{purple}{rgb}{0.5,0.0,0.5}
179 183 \definecolor{darkgray}{gray}{0.25}
180 184 \definecolor{lightred}{rgb}{1.0,0.39,0.28}
181 185 \definecolor{lightgreen}{rgb}{0.48,0.99,0.0}
182 186 \definecolor{lightblue}{rgb}{0.53,0.81,0.92}
183 187 \definecolor{lightpurple}{rgb}{0.87,0.63,0.87}
184 188 \definecolor{lightcyan}{rgb}{0.5,1.0,0.83}
185 189
186 190 % Framed environments for code cells (inputs, outputs, errors, ...). The
187 191 % various uses of \unskip (or not) at the end were fine-tuned by hand, so don't
188 192 % randomly change them unless you're sure of the effect it will have.
189 193 \usepackage{framed}
190 194
191 195 % remove extraneous vertical space in boxes
192 196 \setlength\fboxsep{0pt}
193 197
194 198 % codecell is the whole input+output set of blocks that a Code cell can
195 199 % generate.
196 200
197 201 % TODO: unfortunately, it seems that using a framed codecell environment breaks
198 202 % the ability of the frames inside of it to be broken across pages. This
199 203 % causes at least the problem of having lots of empty space at the bottom of
200 204 % pages as new frames are moved to the next page, and if a single frame is too
201 205 % long to fit on a page, will completely stop latex from compiling the
202 206 % document. So unless we figure out a solution to this, we'll have to instead
203 207 % leave the codecell env. as empty. I'm keeping the original codecell
204 208 % definition here (a thin vertical bar) for reference, in case we find a
205 209 % solution to the page break issue.
206 210
207 211 %% \newenvironment{codecell}{%
208 212 %% \def\FrameCommand{\color{mediumgray} \vrule width 1pt \hspace{5pt}}%
209 213 %% \MakeFramed{\vspace{-0.5em}}}
210 214 %% {\unskip\endMakeFramed}
211 215
212 216 % For now, make this a no-op...
213 217 \newenvironment{codecell}{}
214 218
215 219 \newenvironment{codeinput}{%
216 220 \def\FrameCommand{\colorbox{inputbackground}}%
217 221 \MakeFramed{\advance\hsize-\width \FrameRestore}}
218 222 {\unskip\endMakeFramed}
219 223
220 224 \newenvironment{codeoutput}{%
221 225 \def\FrameCommand{\colorbox{outputbackground}}%
222 226 \vspace{-1.4em}
223 227 \MakeFramed{\advance\hsize-\width \FrameRestore}}
224 228 {\unskip\medskip\endMakeFramed}
225 229
226 230 \newenvironment{traceback}{%
227 231 \def\FrameCommand{\colorbox{traceback}}%
228 232 \MakeFramed{\advance\hsize-\width \FrameRestore}}
229 233 {\endMakeFramed}
230 234
231 235 % Use and configure listings package for nicely formatted code
232 236 \usepackage{listingsutf8}
233 237 \lstset{
234 238 language=python,
235 239 inputencoding=utf8x,
236 240 extendedchars=\true,
237 241 aboveskip=\smallskipamount,
238 242 belowskip=\smallskipamount,
239 243 xleftmargin=2mm,
240 244 breaklines=true,
241 245 basicstyle=\small \ttfamily,
242 246 showstringspaces=false,
243 247 keywordstyle=\color{blue}\bfseries,
244 248 commentstyle=\color{myteal},
245 249 stringstyle=\color{darkgreen},
246 250 identifierstyle=\color{darkorange},
247 251 columns=fullflexible, % tighter character kerning, like verb
248 252 }
249 253
250 254 % The hyperref package gives us a pdf with properly built
251 255 % internal navigation ('pdf bookmarks' for the table of contents,
252 256 % internal cross-reference links, web links for URLs, etc.)
253 257 \usepackage{hyperref}
254 258 \hypersetup{
255 259 breaklinks=true, % so long urls are correctly broken across lines
256 260 colorlinks=true,
257 261 urlcolor=blue,
258 262 linkcolor=darkorange,
259 263 citecolor=darkgreen,
260 264 }
261 265
262 266 % hardcode size of all verbatim environments to be a bit smaller
263 267 \makeatletter
264 268 \g@addto@macro\@verbatim\small\topsep=0.5em\partopsep=0pt
265 269 \makeatother
266 270
267 271 % Prevent overflowing lines due to urls and other hard-to-break entities.
268 272 \sloppy
269 273
270 274 ((* endblock *))
@@ -1,469 +1,472 b''
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 ((* block bibliography *))
196 ((* endblock bibliography *))
197
195 198 % End of document
196 199 \end{document}
197 200 ((* endblock bodyEnd *))
198 201 ((* endblock body *))
199 202
200 203 %==============================================================================
201 204 % Footer
202 205 %==============================================================================
203 206 ((* block footer *))
204 207 ((* endblock footer *))
205 208
206 209 %==============================================================================
207 210 % Headings
208 211 %
209 212 % Purpose: Format pynb headers as sphinx headers. Depending on the Sphinx
210 213 % style that is active, this will change. Thus sphinx styles will
211 214 % override the values here.
212 215 %==============================================================================
213 216 ((* block headingcell -*))
214 217 \
215 218 ((*- if cell.level == 1 -*))
216 219 ((* block h1 -*))part((* endblock h1 -*))
217 220 ((*- elif cell.level == 2 -*))
218 221 ((* block h2 -*))chapter((* endblock h2 -*))
219 222 ((*- elif cell.level == 3 -*))
220 223 ((* block h3 -*))section((* endblock h3 -*))
221 224 ((*- elif cell.level == 4 -*))
222 225 ((* block h4 -*))subsection((* endblock h4 -*))
223 226 ((*- elif cell.level == 5 -*))
224 227 ((* block h5 -*))subsubsection((* endblock h5 -*))
225 228 ((*- elif cell.level == 6 -*))
226 229 ((* block h6 -*))paragraph((* endblock h6 -*))
227 230
228 231 ((= It's important to make sure that underscores (which tend to be common
229 232 in IPYNB file titles) do not make their way into latex. Sometimes this
230 233 causes latex to barf. =))
231 234 ((*- endif -*))
232 {((( cell.source | markdown2latex )))}
235 {((( cell.source | parse_citation | markdown2latex )))}
233 236 ((*- endblock headingcell *))
234 237
235 238 %==============================================================================
236 239 % Markdown
237 240 %
238 241 % Purpose: Convert markdown to latex. Here markdown2latex is explicitly
239 242 % called since we know we want latex output.
240 243 %==============================================================================
241 244 ((*- block markdowncell scoped-*))
242 ((( cell.source | markdown2latex )))
245 ((( cell.source | parse_citation | markdown2latex )))
243 246 ((*- endblock markdowncell -*))
244 247
245 248 %==============================================================================
246 249 % Rawcell
247 250 %
248 251 % Purpose: Raw text cells allow the user to manually inject document code that
249 252 % will not get touched by the templating system.
250 253 %==============================================================================
251 254 ((*- block rawcell *))
252 255 ((( cell.source | wrap_text(wrap_size) )))
253 256 ((* endblock rawcell -*))
254 257
255 258 %==============================================================================
256 259 % Unknowncell
257 260 %
258 261 % Purpose: This is the catch anything unhandled. To display this data, we
259 262 % remove all possible latex conflicts and wrap the characters so they
260 263 % can't flow off of the page.
261 264 %==============================================================================
262 265 ((* block unknowncell scoped*))
263 266 % Unsupported cell type, no formatting
264 267 ((( cell.source | wrap_text | escape_latex )))
265 268 ((* endblock unknowncell *))
266 269
267 270 %==============================================================================
268 271 % Input
269 272 %==============================================================================
270 273 ((* block input *))
271 274
272 275 % Make sure that atleast 4 lines are below the HR
273 276 \needspace{((( min_header_lines )))\baselineskip}
274 277
275 278 ((* if resources.sphinx.outputstyle == 'simple' *))
276 279
277 280 % Add a horizantal break, along with break title.
278 281 \vspace{10pt}
279 282 {\scriptsize Input}\\*
280 283 \rule[10pt]{\linewidth}{0.5pt}
281 284 \vspace{-25pt}
282 285
283 286 % Add contents below.
284 287 ((( cell.input | highlight2latex )))
285 288
286 289 ((* elif resources.sphinx.outputstyle == 'notebook' *))
287 290 \vspace{6pt}
288 291 ((( write_prompt("In", cell.prompt_number, "nbframe-in-prompt") )))
289 292 \vspace{-2.65\baselineskip}
290 293 \begin{ColorVerbatim}
291 294 \vspace{-0.7\baselineskip}
292 295 ((( cell.input | highlight2latex )))
293 296 ((* if cell.input == None or cell.input == '' *))
294 297 \vspace{0.3\baselineskip}
295 298 ((* else *))
296 299 \vspace{-0.2\baselineskip}
297 300 ((* endif *))
298 301 \end{ColorVerbatim}
299 302 ((* endif *))
300 303 ((* endblock input *))
301 304
302 305 %==============================================================================
303 306 % Output_Group
304 307 %
305 308 % Purpose: Make sure that only one header bar only attaches to the output
306 309 % once. By keeping track of when an input group is started
307 310 %==============================================================================
308 311 ((* block output_group *))
309 312 ((* if cell.outputs.__len__() > 0 *))
310 313
311 314 % If the first block is an image, minipage the image. Else
312 315 % request a certain amount of space for the input text.
313 316 ((( iff_figure(cell.outputs[0], "\\begin{minipage}{1.0\\textwidth}", "\\needspace{" ~ min_header_lines ~ "\\baselineskip}") )))
314 317
315 318 ((* if resources.sphinx.outputstyle == 'simple' *))
316 319
317 320 % Add a horizantal break, along with break title.
318 321 \vspace{10pt}
319 322 {\scriptsize Output}\\*
320 323 \rule[10pt]{\linewidth}{0.5pt}
321 324 \vspace{-20pt}
322 325
323 326 % Add the contents of the first block.
324 327 ((( render_output(cell.outputs[0]) )))
325 328
326 329 % Close the minipage.
327 330 ((( iff_figure(cell.outputs[0], "\\end{minipage}", "") )))
328 331
329 332 % Add remainer of the document contents below.
330 333 ((* for output in cell.outputs[1:] *))
331 334 ((( render_output(output, cell.prompt_number) )))
332 335 ((* endfor *))
333 336 ((* elif resources.sphinx.outputstyle == 'notebook' *))
334 337
335 338 % Add document contents.
336 339 ((* for output in cell.outputs *))
337 340 ((( render_output(output, cell.prompt_number) )))
338 341 ((* endfor *))
339 342 ((* endif *))
340 343 ((* endif *))
341 344 ((* endblock *))
342 345
343 346 %==============================================================================
344 347 % Additional formating
345 348 %==============================================================================
346 349 ((* block data_text *))
347 350 ((( custom_verbatim(output.text) | ansi2latex )))
348 351 ((* endblock *))
349 352
350 353 ((* block traceback_line *))
351 354 ((( conditionally_center_output( line | indent| strip_ansi ) )))
352 355 ((* endblock traceback_line *))
353 356
354 357 %==============================================================================
355 358 % Supported image formats
356 359 %==============================================================================
357 360 ((*- block data_png -*))
358 361 ((( conditionally_center_output(insert_graphics(output.png_filename | posix_path)) )))
359 362 ((*- endblock -*))
360 363
361 364 ((*- block data_jpg -*))
362 365 ((( conditionally_center_output(insert_graphics(output.jpg_filename | posix_path)) )))
363 366 ((*- endblock -*))
364 367
365 368 ((*- block data_svg -*))
366 369 ((( conditionally_center_output(insert_graphics(output.svg_filename | posix_path)) )))
367 370 ((*- endblock -*))
368 371
369 372 ((*- block data_pdf -*))
370 373 ((( conditionally_center_output(insert_graphics(output.pdf_filename | posix_path)) )))
371 374 ((*- endblock -*))
372 375
373 376 ((*- block data_latex *))
374 377 ((* if resources.sphinx.centeroutput *))
375 378 \begin{center}
376 379 ((* endif -*))
377 380 ((( output.latex | strip_math_space )))
378 381 ((*- if resources.sphinx.centeroutput *))
379 382 \end{center}
380 383 ((* endif -*))
381 384 ((*- endblock -*))
382 385
383 386 %==============================================================================
384 387 % Support Macros
385 388 %==============================================================================
386 389
387 390 % Name: write_prompt
388 391 % Purpose: Renders an output/input prompt for notebook style pdfs
389 392 ((* macro write_prompt(prompt, number, color) -*))
390 393 \makebox[0.1\linewidth]{\smaller\hfill\tt\color{((( color )))}((( prompt )))\hspace{4pt}{[}((( number ))){]}:\hspace{4pt}}\\*
391 394 ((*- endmacro *))
392 395
393 396 % Name: render_output
394 397 % Purpose: Renders an output block appropriately.
395 398 ((* macro render_output(output, prompt_number) -*))
396 399 ((*- if output.output_type == 'pyerr' -*))
397 400 ((*- block pyerr scoped *))
398 401 ((( custom_verbatim(super()) )))
399 402 ((* endblock pyerr -*))
400 403 ((*- else -*))
401 404
402 405 ((* if resources.sphinx.outputstyle == 'notebook' *))
403 406 ((*- if output.output_type == 'pyout' -*))
404 407 ((( write_prompt("Out", prompt_number, "nbframe-out-prompt") )))
405 408 \vspace{-2.55\baselineskip}
406 409 ((*- endif -*))
407 410
408 411 \begin{InvisibleVerbatim}
409 412 \vspace{-0.5\baselineskip}
410 413 ((*- endif -*))
411 414
412 415 ((*- block display_data scoped -*))
413 416 ((( super() )))
414 417 ((*- endblock display_data -*))
415 418
416 419 ((* if resources.sphinx.outputstyle == 'notebook' *))
417 420 \end{InvisibleVerbatim}
418 421 ((*- endif -*))
419 422 ((*- endif -*))
420 423 ((*- endmacro *))
421 424
422 425 % Name: iff_figure
423 426 % Purpose: If the output block provided is a figure type, the 'true_content'
424 427 % parameter will be returned. Else, the 'false_content'.
425 428 ((* macro iff_figure(output, true_content, false_content) -*))
426 429 ((*- set is_figure = false -*))
427 430 ((*- for type in output | filter_data_type -*))
428 431 ((*- if type in ['pdf', 'svg', 'png', 'jpeg','html']*))
429 432 ((*- set is_figure = true -*))
430 433 ((*- endif -*))
431 434 ((*- endfor -*))
432 435
433 436 ((* if is_figure -*))
434 437 ((( true_content )))
435 438 ((*- else -*))
436 439 ((( false_content )))
437 440 ((*- endif *))
438 441 ((*- endmacro *))
439 442
440 443 % Name: custom_verbatim
441 444 % Purpose: This macro creates a verbatim style block that fits the existing
442 445 % sphinx style more readily than standard verbatim blocks.
443 446 ((* macro custom_verbatim(text) -*))
444 447 \begin{alltt}
445 448 ((*- if resources.sphinx.centeroutput *))\begin{center} ((* endif -*))
446 449 ((( text | wrap_text(wrap_size) | escape_latex )))
447 450 ((*- if resources.sphinx.centeroutput *))\end{center}((* endif -*))
448 451 \end{alltt}
449 452 ((*- endmacro *))
450 453
451 454 % Name: conditionally_center_output
452 455 % Purpose: This macro centers the output if the output centering is enabled.
453 456 ((* macro conditionally_center_output(text) -*))
454 457 ((* if resources.sphinx.centeroutput *))
455 458 {\centering
456 459 ((* endif *))
457 460 ((( text )))
458 461 ((* if resources.sphinx.centeroutput *))}
459 462 ((* endif *))
460 463 ((*- endmacro *))
461 464
462 465 % Name: insert_graphics
463 466 % Purpose: This macro will insert an image in the latex document given a path.
464 467 ((* macro insert_graphics(path) -*))
465 468 \begin{center}
466 469 \includegraphics[max size={\textwidth}{\textheight}]{((( path )))}
467 470 \par
468 471 \end{center}
469 472 ((*- endmacro *))
General Comments 0
You need to be logged in to leave comments. Login now