##// END OF EJS Templates
fix markdown images...
MinRK -
Show More
@@ -1,519 +1,520 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 'citation2latex': filters.citation2latex
71 'citation2latex': filters.citation2latex,
72 'path2url': filters.path2url,
72 73 }
73 74
74 75 #-----------------------------------------------------------------------------
75 76 # Class
76 77 #-----------------------------------------------------------------------------
77 78
78 79 class ResourcesDict(collections.defaultdict):
79 80 def __missing__(self, key):
80 81 return ''
81 82
82 83
83 84 class Exporter(LoggingConfigurable):
84 85 """
85 86 Exports notebooks into other file formats. Uses Jinja 2 templating engine
86 87 to output new formats. Inherit from this class if you are creating a new
87 88 template type along with new filters/preprocessors. If the filters/
88 89 preprocessors provided by default suffice, there is no need to inherit from
89 90 this class. Instead, override the template_file and file_extension
90 91 traits via a config file.
91 92
92 93 {filters}
93 94 """
94 95
95 96 # finish the docstring
96 97 __doc__ = __doc__.format(filters = '- '+'\n - '.join(default_filters.keys()))
97 98
98 99
99 100 template_file = Unicode(u'default',
100 101 config=True,
101 102 help="Name of the template file to use")
102 103 def _template_file_changed(self, name, old, new):
103 104 if new=='default':
104 105 self.template_file = self.default_template
105 106 else:
106 107 self.template_file = new
107 108 self.template = None
108 109 self._load_template()
109 110
110 111 default_template = Unicode(u'')
111 112 template = Any()
112 113 environment = Any()
113 114
114 115 file_extension = Unicode(
115 116 'txt', config=True,
116 117 help="Extension of the file that should be written to disk"
117 118 )
118 119
119 120 template_path = List(['.'], config=True)
120 121 def _template_path_changed(self, name, old, new):
121 122 self._load_template()
122 123
123 124 default_template_path = Unicode(
124 125 os.path.join("..", "templates"),
125 126 help="Path where the template files are located.")
126 127
127 128 template_skeleton_path = Unicode(
128 129 os.path.join("..", "templates", "skeleton"),
129 130 help="Path where the template skeleton files are located.")
130 131
131 132 #Jinja block definitions
132 133 jinja_comment_block_start = Unicode("", config=True)
133 134 jinja_comment_block_end = Unicode("", config=True)
134 135 jinja_variable_block_start = Unicode("", config=True)
135 136 jinja_variable_block_end = Unicode("", config=True)
136 137 jinja_logic_block_start = Unicode("", config=True)
137 138 jinja_logic_block_end = Unicode("", config=True)
138 139
139 140 #Extension that the template files use.
140 141 template_extension = Unicode(".tpl", config=True)
141 142
142 143 #Configurability, allows the user to easily add filters and preprocessors.
143 144 preprocessors = List(config=True,
144 145 help="""List of preprocessors, by name or namespace, to enable.""")
145 146
146 147 filters = Dict(config=True,
147 148 help="""Dictionary of filters, by name and namespace, to add to the Jinja
148 149 environment.""")
149 150
150 151 default_preprocessors = List([nbpreprocessors.coalesce_streams,
151 152 nbpreprocessors.SVG2PDFPreprocessor,
152 153 nbpreprocessors.ExtractOutputPreprocessor,
153 154 nbpreprocessors.CSSHTMLHeaderPreprocessor,
154 155 nbpreprocessors.RevealHelpPreprocessor,
155 156 nbpreprocessors.LatexPreprocessor,
156 157 nbpreprocessors.SphinxPreprocessor],
157 158 config=True,
158 159 help="""List of preprocessors available by default, by name, namespace,
159 160 instance, or type.""")
160 161
161 162
162 163 def __init__(self, config=None, extra_loaders=None, **kw):
163 164 """
164 165 Public constructor
165 166
166 167 Parameters
167 168 ----------
168 169 config : config
169 170 User configuration instance.
170 171 extra_loaders : list[of Jinja Loaders]
171 172 ordered list of Jinja loader to find templates. Will be tried in order
172 173 before the default FileSystem ones.
173 174 template : str (optional, kw arg)
174 175 Template to use when exporting.
175 176 """
176 177 if not config:
177 178 config = self.default_config
178 179
179 180 super(Exporter, self).__init__(config=config, **kw)
180 181
181 182 #Init
182 183 self._init_template()
183 184 self._init_environment(extra_loaders=extra_loaders)
184 185 self._init_preprocessors()
185 186 self._init_filters()
186 187
187 188
188 189 @property
189 190 def default_config(self):
190 191 return Config()
191 192
192 193 def _config_changed(self, name, old, new):
193 194 """When setting config, make sure to start with our default_config"""
194 195 c = self.default_config
195 196 if new:
196 197 c.merge(new)
197 198 if c != old:
198 199 self.config = c
199 200 super(Exporter, self)._config_changed(name, old, c)
200 201
201 202
202 203 def _load_template(self):
203 204 """Load the Jinja template object from the template file
204 205
205 206 This is a no-op if the template attribute is already defined,
206 207 or the Jinja environment is not setup yet.
207 208
208 209 This is triggered by various trait changes that would change the template.
209 210 """
210 211 if self.template is not None:
211 212 return
212 213 # called too early, do nothing
213 214 if self.environment is None:
214 215 return
215 216 # Try different template names during conversion. First try to load the
216 217 # template by name with extension added, then try loading the template
217 218 # as if the name is explicitly specified, then try the name as a
218 219 # 'flavor', and lastly just try to load the template by module name.
219 220 module_name = self.__module__.rsplit('.', 1)[-1]
220 221 try_names = []
221 222 if self.template_file:
222 223 try_names.extend([
223 224 self.template_file + self.template_extension,
224 225 self.template_file,
225 226 module_name + '_' + self.template_file + self.template_extension,
226 227 ])
227 228 try_names.append(module_name + self.template_extension)
228 229 for try_name in try_names:
229 230 self.log.debug("Attempting to load template %s", try_name)
230 231 try:
231 232 self.template = self.environment.get_template(try_name)
232 233 except (TemplateNotFound, IOError):
233 234 pass
234 235 except Exception as e:
235 236 self.log.warn("Unexpected exception loading template: %s", try_name, exc_info=True)
236 237 else:
237 238 self.log.info("Loaded template %s", try_name)
238 239 break
239 240
240 241 def from_notebook_node(self, nb, resources=None, **kw):
241 242 """
242 243 Convert a notebook from a notebook node instance.
243 244
244 245 Parameters
245 246 ----------
246 247 nb : Notebook node
247 248 resources : dict (**kw)
248 249 of additional resources that can be accessed read/write by
249 250 preprocessors and filters.
250 251 """
251 252 nb_copy = copy.deepcopy(nb)
252 253 resources = self._init_resources(resources)
253 254
254 255 # Preprocess
255 256 nb_copy, resources = self._preprocess(nb_copy, resources)
256 257
257 258 self._load_template()
258 259
259 260 if self.template is not None:
260 261 output = self.template.render(nb=nb_copy, resources=resources)
261 262 else:
262 263 raise IOError('template file "%s" could not be found' % self.template_file)
263 264 return output, resources
264 265
265 266
266 267 def from_filename(self, filename, resources=None, **kw):
267 268 """
268 269 Convert a notebook from a notebook file.
269 270
270 271 Parameters
271 272 ----------
272 273 filename : str
273 274 Full filename of the notebook file to open and convert.
274 275 """
275 276
276 277 #Pull the metadata from the filesystem.
277 278 if resources is None:
278 279 resources = ResourcesDict()
279 280 if not 'metadata' in resources or resources['metadata'] == '':
280 281 resources['metadata'] = ResourcesDict()
281 282 basename = os.path.basename(filename)
282 283 notebook_name = basename[:basename.rfind('.')]
283 284 resources['metadata']['name'] = notebook_name
284 285
285 286 modified_date = datetime.datetime.fromtimestamp(os.path.getmtime(filename))
286 287 resources['metadata']['modified_date'] = modified_date.strftime("%B %d, %Y")
287 288
288 289 with io.open(filename) as f:
289 290 return self.from_notebook_node(nbformat.read(f, 'json'), resources=resources,**kw)
290 291
291 292
292 293 def from_file(self, file_stream, resources=None, **kw):
293 294 """
294 295 Convert a notebook from a notebook file.
295 296
296 297 Parameters
297 298 ----------
298 299 file_stream : file-like object
299 300 Notebook file-like object to convert.
300 301 """
301 302 return self.from_notebook_node(nbformat.read(file_stream, 'json'), resources=resources, **kw)
302 303
303 304
304 305 def register_preprocessor(self, preprocessor, enabled=False):
305 306 """
306 307 Register a preprocessor.
307 308 Preprocessors are classes that act upon the notebook before it is
308 309 passed into the Jinja templating engine. Preprocessors are also
309 310 capable of passing additional information to the Jinja
310 311 templating engine.
311 312
312 313 Parameters
313 314 ----------
314 315 preprocessor : preprocessor
315 316 """
316 317 if preprocessor is None:
317 318 raise TypeError('preprocessor')
318 319 isclass = isinstance(preprocessor, type)
319 320 constructed = not isclass
320 321
321 322 #Handle preprocessor's registration based on it's type
322 323 if constructed and isinstance(preprocessor, py3compat.string_types):
323 324 #Preprocessor is a string, import the namespace and recursively call
324 325 #this register_preprocessor method
325 326 preprocessor_cls = import_item(preprocessor)
326 327 return self.register_preprocessor(preprocessor_cls, enabled)
327 328
328 329 if constructed and hasattr(preprocessor, '__call__'):
329 330 #Preprocessor is a function, no need to construct it.
330 331 #Register and return the preprocessor.
331 332 if enabled:
332 333 preprocessor.enabled = True
333 334 self._preprocessors.append(preprocessor)
334 335 return preprocessor
335 336
336 337 elif isclass and isinstance(preprocessor, MetaHasTraits):
337 338 #Preprocessor is configurable. Make sure to pass in new default for
338 339 #the enabled flag if one was specified.
339 340 self.register_preprocessor(preprocessor(parent=self), enabled)
340 341
341 342 elif isclass:
342 343 #Preprocessor is not configurable, construct it
343 344 self.register_preprocessor(preprocessor(), enabled)
344 345
345 346 else:
346 347 #Preprocessor is an instance of something without a __call__
347 348 #attribute.
348 349 raise TypeError('preprocessor')
349 350
350 351
351 352 def register_filter(self, name, jinja_filter):
352 353 """
353 354 Register a filter.
354 355 A filter is a function that accepts and acts on one string.
355 356 The filters are accesible within the Jinja templating engine.
356 357
357 358 Parameters
358 359 ----------
359 360 name : str
360 361 name to give the filter in the Jinja engine
361 362 filter : filter
362 363 """
363 364 if jinja_filter is None:
364 365 raise TypeError('filter')
365 366 isclass = isinstance(jinja_filter, type)
366 367 constructed = not isclass
367 368
368 369 #Handle filter's registration based on it's type
369 370 if constructed and isinstance(jinja_filter, py3compat.string_types):
370 371 #filter is a string, import the namespace and recursively call
371 372 #this register_filter method
372 373 filter_cls = import_item(jinja_filter)
373 374 return self.register_filter(name, filter_cls)
374 375
375 376 if constructed and hasattr(jinja_filter, '__call__'):
376 377 #filter is a function, no need to construct it.
377 378 self.environment.filters[name] = jinja_filter
378 379 return jinja_filter
379 380
380 381 elif isclass and isinstance(jinja_filter, MetaHasTraits):
381 382 #filter is configurable. Make sure to pass in new default for
382 383 #the enabled flag if one was specified.
383 384 filter_instance = jinja_filter(parent=self)
384 385 self.register_filter(name, filter_instance )
385 386
386 387 elif isclass:
387 388 #filter is not configurable, construct it
388 389 filter_instance = jinja_filter()
389 390 self.register_filter(name, filter_instance)
390 391
391 392 else:
392 393 #filter is an instance of something without a __call__
393 394 #attribute.
394 395 raise TypeError('filter')
395 396
396 397
397 398 def _init_template(self):
398 399 """
399 400 Make sure a template name is specified. If one isn't specified, try to
400 401 build one from the information we know.
401 402 """
402 403 self._template_file_changed('template_file', self.template_file, self.template_file)
403 404
404 405
405 406 def _init_environment(self, extra_loaders=None):
406 407 """
407 408 Create the Jinja templating environment.
408 409 """
409 410 here = os.path.dirname(os.path.realpath(__file__))
410 411 loaders = []
411 412 if extra_loaders:
412 413 loaders.extend(extra_loaders)
413 414
414 415 paths = self.template_path
415 416 paths.extend([os.path.join(here, self.default_template_path),
416 417 os.path.join(here, self.template_skeleton_path)])
417 418 loaders.append(FileSystemLoader(paths))
418 419
419 420 self.environment = Environment(
420 421 loader= ChoiceLoader(loaders),
421 422 extensions=JINJA_EXTENSIONS
422 423 )
423 424
424 425 #Set special Jinja2 syntax that will not conflict with latex.
425 426 if self.jinja_logic_block_start:
426 427 self.environment.block_start_string = self.jinja_logic_block_start
427 428 if self.jinja_logic_block_end:
428 429 self.environment.block_end_string = self.jinja_logic_block_end
429 430 if self.jinja_variable_block_start:
430 431 self.environment.variable_start_string = self.jinja_variable_block_start
431 432 if self.jinja_variable_block_end:
432 433 self.environment.variable_end_string = self.jinja_variable_block_end
433 434 if self.jinja_comment_block_start:
434 435 self.environment.comment_start_string = self.jinja_comment_block_start
435 436 if self.jinja_comment_block_end:
436 437 self.environment.comment_end_string = self.jinja_comment_block_end
437 438
438 439
439 440 def _init_preprocessors(self):
440 441 """
441 442 Register all of the preprocessors needed for this exporter, disabled
442 443 unless specified explicitly.
443 444 """
444 445 self._preprocessors = []
445 446
446 447 #Load default preprocessors (not necessarly enabled by default).
447 448 if self.default_preprocessors:
448 449 for preprocessor in self.default_preprocessors:
449 450 self.register_preprocessor(preprocessor)
450 451
451 452 #Load user preprocessors. Enable by default.
452 453 if self.preprocessors:
453 454 for preprocessor in self.preprocessors:
454 455 self.register_preprocessor(preprocessor, enabled=True)
455 456
456 457
457 458 def _init_filters(self):
458 459 """
459 460 Register all of the filters required for the exporter.
460 461 """
461 462
462 463 #Add default filters to the Jinja2 environment
463 464 for key, value in default_filters.items():
464 465 self.register_filter(key, value)
465 466
466 467 #Load user filters. Overwrite existing filters if need be.
467 468 if self.filters:
468 469 for key, user_filter in self.filters.items():
469 470 self.register_filter(key, user_filter)
470 471
471 472
472 473 def _init_resources(self, resources):
473 474
474 475 #Make sure the resources dict is of ResourcesDict type.
475 476 if resources is None:
476 477 resources = ResourcesDict()
477 478 if not isinstance(resources, ResourcesDict):
478 479 new_resources = ResourcesDict()
479 480 new_resources.update(resources)
480 481 resources = new_resources
481 482
482 483 #Make sure the metadata extension exists in resources
483 484 if 'metadata' in resources:
484 485 if not isinstance(resources['metadata'], ResourcesDict):
485 486 resources['metadata'] = ResourcesDict(resources['metadata'])
486 487 else:
487 488 resources['metadata'] = ResourcesDict()
488 489 if not resources['metadata']['name']:
489 490 resources['metadata']['name'] = 'Notebook'
490 491
491 492 #Set the output extension
492 493 resources['output_extension'] = self.file_extension
493 494 return resources
494 495
495 496
496 497 def _preprocess(self, nb, resources):
497 498 """
498 499 Preprocess the notebook before passing it into the Jinja engine.
499 500 To preprocess the notebook is to apply all of the
500 501
501 502 Parameters
502 503 ----------
503 504 nb : notebook node
504 505 notebook that is being exported.
505 506 resources : a dict of additional resources that
506 507 can be accessed read/write by preprocessors
507 508 and filters.
508 509 """
509 510
510 511 # Do a copy.deepcopy first,
511 512 # we are never safe enough with what the preprocessors could do.
512 513 nbc = copy.deepcopy(nb)
513 514 resc = copy.deepcopy(resources)
514 515
515 516 #Run each preprocessor on the notebook. Carry the output along
516 517 #to each preprocessor
517 518 for preprocessor in self._preprocessors:
518 519 nbc, resc = preprocessor(nbc, resc)
519 520 return nbc, resc
@@ -1,31 +1,38 b''
1 1 """
2 2 Exporter that will export your ipynb to Markdown.
3 3 """
4 4 #-----------------------------------------------------------------------------
5 5 # Copyright (c) 2013, the IPython Development Team.
6 6 #
7 7 # Distributed under the terms of the Modified BSD License.
8 8 #
9 9 # The full license is in the file COPYING.txt, distributed with this software.
10 10 #-----------------------------------------------------------------------------
11 11
12 12 #-----------------------------------------------------------------------------
13 13 # Imports
14 14 #-----------------------------------------------------------------------------
15 15
16 from IPython.config import Config
16 17 from IPython.utils.traitlets import Unicode
17 18
18 19 from .exporter import Exporter
19 20
20 21 #-----------------------------------------------------------------------------
21 22 # Classes
22 23 #-----------------------------------------------------------------------------
23 24
24 25 class MarkdownExporter(Exporter):
25 26 """
26 27 Exports to a markdown document (.md)
27 28 """
28 29
29 30 file_extension = Unicode(
30 31 'md', config=True,
31 32 help="Extension of the file that should be written to disk")
33
34 @property
35 def default_config(self):
36 c = Config({'ExtractOutputPreprocessor':{'enabled':True}})
37 c.merge(super(MarkdownExporter,self).default_config)
38 return c
@@ -1,183 +1,190 b''
1 1 # coding: utf-8
2 2 """String filters.
3 3
4 4 Contains a collection of useful string manipulation filters for use in Jinja
5 5 templates.
6 6 """
7 7 #-----------------------------------------------------------------------------
8 8 # Copyright (c) 2013, the IPython Development Team.
9 9 #
10 10 # Distributed under the terms of the Modified BSD License.
11 11 #
12 12 # The full license is in the file COPYING.txt, distributed with this software.
13 13 #-----------------------------------------------------------------------------
14 14
15 15 #-----------------------------------------------------------------------------
16 16 # Imports
17 17 #-----------------------------------------------------------------------------
18 18
19 19 import os
20 20 import re
21 21 import textwrap
22 from urllib2 import quote
22 23 from xml.etree import ElementTree
23 24
24 25 from IPython.core.interactiveshell import InteractiveShell
25 26 from IPython.utils import py3compat
26 27
27 28 #-----------------------------------------------------------------------------
28 29 # Functions
29 30 #-----------------------------------------------------------------------------
30 31
31 32 __all__ = [
32 33 'wrap_text',
33 34 'html2text',
34 35 'add_anchor',
35 36 'strip_dollars',
36 37 'strip_files_prefix',
37 38 'comment_lines',
38 39 'get_lines',
39 40 'ipython2python',
40 41 'posix_path',
42 'path2url',
41 43 ]
42 44
43 45
44 46 def wrap_text(text, width=100):
45 47 """
46 48 Intelligently wrap text.
47 49 Wrap text without breaking words if possible.
48 50
49 51 Parameters
50 52 ----------
51 53 text : str
52 54 Text to wrap.
53 55 width : int, optional
54 56 Number of characters to wrap to, default 100.
55 57 """
56 58
57 59 split_text = text.split('\n')
58 60 wrp = map(lambda x:textwrap.wrap(x,width), split_text)
59 61 wrpd = map('\n'.join, wrp)
60 62 return '\n'.join(wrpd)
61 63
62 64
63 65 def html2text(element):
64 66 """extract inner text from html
65 67
66 68 Analog of jQuery's $(element).text()
67 69 """
68 70 if isinstance(element, py3compat.string_types):
69 71 element = ElementTree.fromstring(element)
70 72
71 73 text = element.text or ""
72 74 for child in element:
73 75 text += html2text(child)
74 76 text += (element.tail or "")
75 77 return text
76 78
77 79
78 80 def add_anchor(html):
79 81 """Add an anchor-link to an html header tag
80 82
81 83 For use in heading cells
82 84 """
83 85 h = ElementTree.fromstring(py3compat.cast_bytes_py2(html, encoding='utf-8'))
84 86 link = html2text(h).replace(' ', '-')
85 87 h.set('id', link)
86 88 a = ElementTree.Element("a", {"class" : "anchor-link", "href" : "#" + link})
87 89 a.text = u'ΒΆ'
88 90 h.append(a)
89 91
90 92 # Known issue of Python3.x, ElementTree.tostring() returns a byte string
91 93 # instead of a text string. See issue http://bugs.python.org/issue10942
92 94 # Workaround is to make sure the bytes are casted to a string.
93 95 return py3compat.decode(ElementTree.tostring(h), 'utf-8')
94 96
95 97
96 98 def strip_dollars(text):
97 99 """
98 100 Remove all dollar symbols from text
99 101
100 102 Parameters
101 103 ----------
102 104 text : str
103 105 Text to remove dollars from
104 106 """
105 107
106 108 return text.strip('$')
107 109
108 110
109 111 files_url_pattern = re.compile(r'(src|href)\=([\'"]?)files/')
110 112
111 113 def strip_files_prefix(text):
112 114 """
113 115 Fix all fake URLs that start with `files/`,
114 116 stripping out the `files/` prefix.
115 117
116 118 Parameters
117 119 ----------
118 120 text : str
119 121 Text in which to replace 'src="files/real...' with 'src="real...'
120 122 """
121 123 return files_url_pattern.sub(r"\1=\2", text)
122 124
123 125
124 126 def comment_lines(text, prefix='# '):
125 127 """
126 128 Build a Python comment line from input text.
127 129
128 130 Parameters
129 131 ----------
130 132 text : str
131 133 Text to comment out.
132 134 prefix : str
133 135 Character to append to the start of each line.
134 136 """
135 137
136 138 #Replace line breaks with line breaks and comment symbols.
137 139 #Also add a comment symbol at the beginning to comment out
138 140 #the first line.
139 141 return prefix + ('\n'+prefix).join(text.split('\n'))
140 142
141 143
142 144 def get_lines(text, start=None,end=None):
143 145 """
144 146 Split the input text into separate lines and then return the
145 147 lines that the caller is interested in.
146 148
147 149 Parameters
148 150 ----------
149 151 text : str
150 152 Text to parse lines from.
151 153 start : int, optional
152 154 First line to grab from.
153 155 end : int, optional
154 156 Last line to grab from.
155 157 """
156 158
157 159 # Split the input into lines.
158 160 lines = text.split("\n")
159 161
160 162 # Return the right lines.
161 163 return "\n".join(lines[start:end]) #re-join
162 164
163 165 def ipython2python(code):
164 166 """Transform IPython syntax to pure Python syntax
165 167
166 168 Parameters
167 169 ----------
168 170
169 171 code : str
170 172 IPython code, to be transformed to pure Python
171 173 """
172 174 shell = InteractiveShell.instance()
173 175 return shell.input_transformer_manager.transform_cell(code)
174 176
175 177 def posix_path(path):
176 178 """Turn a path into posix-style path/to/etc
177 179
178 180 Mainly for use in latex on Windows,
179 181 where native Windows paths are not allowed.
180 182 """
181 183 if os.path.sep != '/':
182 184 return path.replace(os.path.sep, '/')
183 185 return path
186
187 def path2url(path):
188 """Turn a file path into a URL"""
189 parts = path.split(os.path.sep)
190 return '/'.join(quote(part) for part in parts)
@@ -1,72 +1,72 b''
1 1 {% extends 'display_priority.tpl' %}
2 2
3 3
4 4 {% block in_prompt %}
5 5 {% endblock in_prompt %}
6 6
7 7 {% block output_prompt %}
8 8 {%- endblock output_prompt %}
9 9
10 10 {% block input %}
11 11 {{ cell.input | indent(4)}}
12 12 {% endblock input %}
13 13
14 14 {% block pyerr %}
15 15 {{ super() }}
16 16 {% endblock pyerr %}
17 17
18 18 {% block traceback_line %}
19 19 {{ line | indent | strip_ansi }}
20 20 {% endblock traceback_line %}
21 21
22 22 {% block pyout %}
23 23
24 24 {% block data_priority scoped %}
25 25 {{ super() }}
26 26 {% endblock %}
27 27 {% endblock pyout %}
28 28
29 29 {% block stream %}
30 30 {{ output.text | indent }}
31 31 {% endblock stream %}
32 32
33 33 {% block data_svg %}
34 [!image]({{ output.svg_filename }})
34 ![svg]({{ output.svg_filename | path2url }})
35 35 {% endblock data_svg %}
36 36
37 37 {% block data_png %}
38 [!image]({{ output.png_filename }})
38 ![png]({{ output.png_filename | path2url }})
39 39 {% endblock data_png %}
40 40
41 41 {% block data_jpg %}
42 [!image]({{ output.jpg_filename }})
42 ![jpeg]({{ output.jpeg_filename | path2url }})
43 43 {% endblock data_jpg %}
44 44
45 45 {% block data_latex %}
46 46 {{ output.latex }}
47 47 {% endblock data_latex %}
48 48
49 49 {% block data_html scoped %}
50 50 {{ output.html }}
51 51 {% endblock data_html %}
52 52
53 53 {% block data_text scoped %}
54 54 {{ output.text | indent }}
55 55 {% endblock data_text %}
56 56
57 57 {% block markdowncell scoped %}
58 58 {{ cell.source | wrap_text(80) }}
59 59 {% endblock markdowncell %}
60 60
61 61
62 62 {% block headingcell scoped %}
63 63 {{ '#' * cell.level }} {{ cell.source | replace('\n', ' ') }}
64 64 {% endblock headingcell %}
65 65
66 66 {% block rawcell scoped %}
67 67 {{ cell.source }}
68 68 {% endblock rawcell %}
69 69
70 70 {% block unknowncell scoped %}
71 71 unknown type {{ cell.type }}
72 72 {% endblock unknowncell %} No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now