##// END OF EJS Templates
add possibility to preprocess ipynb files
Matthias BUSSONNIER -
Show More
@@ -1,151 +1,165 b''
1 """Base classes for the notebook conversion pipeline.
1 """Base classes for the notebook conversion pipeline.
2
2
3 This module defines Converter, from which all objects designed to implement
3 This module defines Converter, from which all objects designed to implement
4 a conversion of IPython notebooks to some other format should inherit.
4 a conversion of IPython notebooks to some other format should inherit.
5 """
5 """
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (c) 2012, the IPython Development Team.
7 # Copyright (c) 2012, the IPython Development Team.
8 #
8 #
9 # Distributed under the terms of the Modified BSD License.
9 # Distributed under the terms of the Modified BSD License.
10 #
10 #
11 # The full license is in the file COPYING.txt, distributed with this software.
11 # The full license is in the file COPYING.txt, distributed with this software.
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13
13
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 from __future__ import print_function, absolute_import
18 from __future__ import print_function, absolute_import
19
19
20 # Stdlib imports
20 # Stdlib imports
21 import io
21 import io
22 import os
22 import os
23 from IPython.utils import path
23 from IPython.utils import path
24
24
25 from jinja2 import Environment, FileSystemLoader
25 from jinja2 import Environment, FileSystemLoader
26 env = Environment(
26 env = Environment(
27 loader=FileSystemLoader('./templates/'),
27 loader=FileSystemLoader('./templates/'),
28 extensions=['jinja2.ext.loopcontrols']
28 extensions=['jinja2.ext.loopcontrols']
29 )
29 )
30
30
31 # IPython imports
31 # IPython imports
32 from IPython.nbformat import current as nbformat
32 from IPython.nbformat import current as nbformat
33 from IPython.config.configurable import Configurable
33 from IPython.config.configurable import Configurable
34 from IPython.utils.traitlets import ( Unicode, Any)
34 from IPython.utils.traitlets import ( Unicode, Any)
35
35
36 # Our own imports
36 # Our own imports
37 from IPython.utils.text import indent
37 from IPython.utils.text import indent
38 from .utils import remove_ansi
38 from .utils import remove_ansi
39 from markdown import markdown
39 from markdown import markdown
40 from .utils import highlight, ansi2html
40 from .utils import highlight, ansi2html
41 #-----------------------------------------------------------------------------
41 #-----------------------------------------------------------------------------
42 # Class declarations
42 # Class declarations
43 #-----------------------------------------------------------------------------
43 #-----------------------------------------------------------------------------
44 def rm_fake(strng):
44 def rm_fake(strng):
45 return strng.replace('/files/', '')
45 return strng.replace('/files/', '')
46
46
47 class ConversionException(Exception):
47 class ConversionException(Exception):
48 pass
48 pass
49
49
50
50
51 def python_comment(string):
51 def python_comment(string):
52 return '# '+'\n# '.join(string.split('\n'))
52 return '# '+'\n# '.join(string.split('\n'))
53
53
54
54
55
55
56 def header_body():
56 def header_body():
57 """Return the body of the header as a list of strings."""
57 """Return the body of the header as a list of strings."""
58
58
59 from pygments.formatters import HtmlFormatter
59 from pygments.formatters import HtmlFormatter
60
60
61 header = []
61 header = []
62 static = os.path.join(path.get_ipython_package_dir(),
62 static = os.path.join(path.get_ipython_package_dir(),
63 'frontend', 'html', 'notebook', 'static',
63 'frontend', 'html', 'notebook', 'static',
64 )
64 )
65 here = os.path.split(os.path.realpath(__file__))[0]
65 here = os.path.split(os.path.realpath(__file__))[0]
66 css = os.path.join(static, 'css')
66 css = os.path.join(static, 'css')
67 for sheet in [
67 for sheet in [
68 # do we need jquery and prettify?
68 # do we need jquery and prettify?
69 # os.path.join(static, 'jquery', 'css', 'themes', 'base',
69 # os.path.join(static, 'jquery', 'css', 'themes', 'base',
70 # 'jquery-ui.min.css'),
70 # 'jquery-ui.min.css'),
71 # os.path.join(static, 'prettify', 'prettify.css'),
71 # os.path.join(static, 'prettify', 'prettify.css'),
72 os.path.join(css, 'boilerplate.css'),
72 os.path.join(css, 'boilerplate.css'),
73 os.path.join(css, 'fbm.css'),
73 os.path.join(css, 'fbm.css'),
74 os.path.join(css, 'notebook.css'),
74 os.path.join(css, 'notebook.css'),
75 os.path.join(css, 'renderedhtml.css'),
75 os.path.join(css, 'renderedhtml.css'),
76 # our overrides:
76 # our overrides:
77 os.path.join(here, '..', 'css', 'static_html.css'),
77 os.path.join(here, '..', 'css', 'static_html.css'),
78 ]:
78 ]:
79
79
80 with io.open(sheet, encoding='utf-8') as f:
80 with io.open(sheet, encoding='utf-8') as f:
81 s = f.read()
81 s = f.read()
82 header.append(s)
82 header.append(s)
83
83
84 pygments_css = HtmlFormatter().get_style_defs('.highlight')
84 pygments_css = HtmlFormatter().get_style_defs('.highlight')
85 header.append(pygments_css)
85 header.append(pygments_css)
86 return header
86 return header
87
87
88 inlining = {}
88 inlining = {}
89 inlining['css'] = header_body()
89 inlining['css'] = header_body()
90
90
91
91
92 def filter_data_type(output):
92 def filter_data_type(output):
93 for fmt in ['html', 'pdf', 'svg', 'latex', 'png', 'jpg', 'jpeg' , 'text']:
93 for fmt in ['html', 'pdf', 'svg', 'latex', 'png', 'jpg', 'jpeg' , 'text']:
94 if fmt in output:
94 if fmt in output:
95 return [fmt]
95 return [fmt]
96
96
97
97
98 env.filters['filter_data_type'] = filter_data_type
98 env.filters['filter_data_type'] = filter_data_type
99 env.filters['pycomment'] = python_comment
99 env.filters['pycomment'] = python_comment
100 env.filters['indent'] = indent
100 env.filters['indent'] = indent
101 env.filters['rm_fake'] = rm_fake
101 env.filters['rm_fake'] = rm_fake
102 env.filters['rm_ansi'] = remove_ansi
102 env.filters['rm_ansi'] = remove_ansi
103 env.filters['markdown'] = markdown
103 env.filters['markdown'] = markdown
104 env.filters['highlight'] = highlight
104 env.filters['highlight'] = highlight
105 env.filters['ansi2html'] = ansi2html
105 env.filters['ansi2html'] = ansi2html
106
106
107 class ConverterTemplate(Configurable):
107 class ConverterTemplate(Configurable):
108
108
109 display_data_priority = ['pdf', 'svg', 'png', 'jpg', 'text']
109 display_data_priority = ['pdf', 'svg', 'png', 'jpg', 'text']
110 #-------------------------------------------------------------------------
110 #-------------------------------------------------------------------------
111 # Instance-level attributes that are set in the constructor for this
111 # Instance-level attributes that are set in the constructor for this
112 # class.
112 # class.
113 #-------------------------------------------------------------------------
113 #-------------------------------------------------------------------------
114 infile = Any()
114 infile = Any()
115
115
116
116
117 infile_dir = Unicode()
117 infile_dir = Unicode()
118
118
119 def __init__(self, tplfile='fullhtml', config=None, **kw):
119 def __init__(self, tplfile='fullhtml', preprocessors=[], config=None, **kw):
120 """
121 preprocessors: list of function to run on ipynb json data before conversion
122 to extract/inline file,
123
124
125
126 """
120 self.template = env.get_template(tplfile+'.tpl')
127 self.template = env.get_template(tplfile+'.tpl')
121 self.nb = None
128 self.nb = None
129 self.preprocessors = preprocessors
122 super(ConverterTemplate, self).__init__(config=config, **kw)
130 super(ConverterTemplate, self).__init__(config=config, **kw)
123
131
124 def process(self):
132 def process(self):
125 converted_cells = []
133 nb = self.nb
126 for worksheet in self.nb.worksheets:
134
135 for preprocessor in self.preprocessors:
136 nb = preprocessor(nb,{})
137
138 worksheets = []
139 for worksheet in nb.worksheets:
127 for cell in worksheet.cells:
140 for cell in worksheet.cells:
128 cell.type = cell.cell_type
141 cell.type = cell.cell_type
129 cell.haspyout = False
142 cell.haspyout = False
130 for out in cell.get('outputs', []):
143 for out in cell.get('outputs', []):
131 if out.output_type == 'pyout':
144 if out.output_type == 'pyout':
132 cell.haspyout = True
145 cell.haspyout = True
133 break
146 break
134 converted_cells.append(worksheet)
147 worksheets.append(worksheet)
148
135
149
136 return converted_cells
150 return worksheets
137
151
138 def convert(self):
152 def convert(self):
139 """ convert the ipynb file
153 """ convert the ipynb file
140
154
141 return both the converted ipynb file and a dict containing potential
155 return both the converted ipynb file and a dict containing potential
142 other resources
156 other resources
143 """
157 """
144 return self.template.render(worksheets=self.process(), inlining=inlining), {}
158 return self.template.render(worksheets=self.process(), inlining=inlining), {}
145
159
146
160
147 def read(self, filename):
161 def read(self, filename):
148 "read and parse notebook into NotebookNode called self.nb"
162 "read and parse notebook into NotebookNode called self.nb"
149 with io.open(filename) as f:
163 with io.open(filename) as f:
150 self.nb = nbformat.read(f, 'json')
164 self.nb = nbformat.read(f, 'json')
151
165
General Comments 0
You need to be logged in to leave comments. Login now