##// END OF EJS Templates
Start to organize template folder
Matthias BUSSONNIER -
Show More
@@ -1,281 +1,287
1 1 """Base classes for the notebook conversion pipeline.
2 2
3 3 This module defines Converter, from which all objects designed to implement
4 4 a conversion of IPython notebooks to some other format should inherit.
5 5 """
6 6 #-----------------------------------------------------------------------------
7 7 # Copyright (c) 2012, the IPython Development Team.
8 8 #
9 9 # Distributed under the terms of the Modified BSD License.
10 10 #
11 11 # The full license is in the file COPYING.txt, distributed with this software.
12 12 #-----------------------------------------------------------------------------
13 13
14 14 #-----------------------------------------------------------------------------
15 15 # Imports
16 16 #-----------------------------------------------------------------------------
17 17
18 18 from __future__ import print_function, absolute_import
19 19
20 20 # Stdlib imports
21 21 import io
22 22 import os
23 23 import re
24 24 from IPython.utils import path
25 25
26 26 from jinja2 import Environment, FileSystemLoader
27 27 env = Environment(
28 loader=FileSystemLoader('./templates/'),
28 loader=FileSystemLoader([
29 './templates/',
30 './templates/skeleton/',
31 ]),
29 32 extensions=['jinja2.ext.loopcontrols']
30 33 )
31 34
32 35 texenv = Environment(
33 loader=FileSystemLoader('./templates/tex/'),
36 loader=FileSystemLoader([
37 './templates/tex/',
38 './templates/skeleton/tex/',
39 ]),
34 40 extensions=['jinja2.ext.loopcontrols']
35 41 )
36 42
37 43 # IPython imports
38 44 from IPython.nbformat import current as nbformat
39 45 from IPython.config.configurable import Configurable
40 46 from IPython.utils.traitlets import ( Unicode, Any, List, Bool)
41 47
42 48 # Our own imports
43 49 from IPython.utils.text import indent
44 50 from .utils import remove_ansi
45 51 from markdown import markdown
46 52 from .utils import highlight, ansi2html
47 53 from .utils import markdown2latex
48 54 #-----------------------------------------------------------------------------
49 55 # Class declarations
50 56 #-----------------------------------------------------------------------------
51 57 def rm_fake(strng):
52 58 return strng.replace('/files/', '')
53 59
54 60 class ConversionException(Exception):
55 61 pass
56 62
57 63
58 64 def python_comment(string):
59 65 return '# '+'\n# '.join(string.split('\n'))
60 66
61 67
62 68
63 69 def header_body():
64 70 """Return the body of the header as a list of strings."""
65 71
66 72 from pygments.formatters import HtmlFormatter
67 73
68 74 header = []
69 75 static = os.path.join(path.get_ipython_package_dir(),
70 76 'frontend', 'html', 'notebook', 'static',
71 77 )
72 78 here = os.path.split(os.path.realpath(__file__))[0]
73 79 css = os.path.join(static, 'css')
74 80 for sheet in [
75 81 # do we need jquery and prettify?
76 82 # os.path.join(static, 'jquery', 'css', 'themes', 'base',
77 83 # 'jquery-ui.min.css'),
78 84 # os.path.join(static, 'prettify', 'prettify.css'),
79 85 os.path.join(css, 'boilerplate.css'),
80 86 os.path.join(css, 'fbm.css'),
81 87 os.path.join(css, 'notebook.css'),
82 88 os.path.join(css, 'renderedhtml.css'),
83 89 # our overrides:
84 90 os.path.join(here, '..', 'css', 'static_html.css'),
85 91 ]:
86 92
87 93 with io.open(sheet, encoding='utf-8') as f:
88 94 s = f.read()
89 95 header.append(s)
90 96
91 97 pygments_css = HtmlFormatter().get_style_defs('.highlight')
92 98 header.append(pygments_css)
93 99 return header
94 100
95 101 # todo, make the key part configurable.
96 102 def _new_figure(data, fmt, count):
97 103 """Create a new figure file in the given format.
98 104
99 105 Returns a path relative to the input file.
100 106 """
101 107 figname = '_fig_%02i.%s' % (count, fmt)
102 108
103 109 # Binary files are base64-encoded, SVG is already XML
104 110 if fmt in ('png', 'jpg', 'pdf'):
105 111 data = data.decode('base64')
106 112
107 113 return figname,data
108 114
109 115
110 116
111 117
112 118 inlining = {}
113 119 inlining['css'] = header_body()
114 120
115 121 LATEX_SUBS = (
116 122 (re.compile(r'\\'), r'\\textbackslash'),
117 123 (re.compile(r'([{}_#%&$])'), r'\\\1'),
118 124 (re.compile(r'~'), r'\~{}'),
119 125 (re.compile(r'\^'), r'\^{}'),
120 126 (re.compile(r'"'), r"''"),
121 127 (re.compile(r'\.\.\.+'), r'\\ldots'),
122 128 )
123 129
124 130 def escape_tex(value):
125 131 newval = value
126 132 for pattern, replacement in LATEX_SUBS:
127 133 newval = pattern.sub(replacement, newval)
128 134 return newval
129 135
130 136 texenv.block_start_string = '((*'
131 137 texenv.block_end_string = '*))'
132 138 texenv.variable_start_string = '((('
133 139 texenv.variable_end_string = ')))'
134 140 texenv.comment_start_string = '((='
135 141 texenv.comment_end_string = '=))'
136 142 texenv.filters['escape_tex'] = escape_tex
137 143
138 144 def cell_preprocessor(function):
139 145 """ wrap a function to be executed on all cells of a notebook
140 146
141 147 wrapped function parameters :
142 148 cell : the cell
143 149 other : external resources
144 150 index : index of the cell
145 151 """
146 152 def wrappedfunc(nb,other):
147 153 for worksheet in nb.worksheets :
148 154 for index, cell in enumerate(worksheet.cells):
149 155 worksheet.cells[index],other= function(cell,other,index)
150 156 return nb,other
151 157 return wrappedfunc
152 158
153 159
154 160
155 161 @cell_preprocessor
156 162 def haspyout_transformer(cell, other, count):
157 163 """
158 164 Add a haspyout flag to cell that have it
159 165
160 166 Easier for templating, where you can't know in advance
161 167 wether to write the out prompt
162 168
163 169 """
164 170 cell.type = cell.cell_type
165 171 cell.haspyout = False
166 172 for out in cell.get('outputs', []):
167 173 if out.output_type == 'pyout':
168 174 cell.haspyout = True
169 175 break
170 176 return cell,other
171 177
172 178
173 179 @cell_preprocessor
174 180 def extract_figure_transformer(cell,other,count):
175 181 for i,out in enumerate(cell.get('outputs', [])):
176 182 for type in ['html', 'pdf', 'svg', 'latex', 'png', 'jpg', 'jpeg']:
177 183 if out.hasattr(type):
178 184 figname,data = _new_figure(out[type], type,count)
179 185 cell.outputs[i][type] = figname
180 186 out['key_'+type] = figname
181 187 other[figname] = data
182 188 count = count+1
183 189 return cell,other
184 190
185 191
186 192 class ConverterTemplate(Configurable):
187 193 """ A Jinja2 base converter templates"""
188 194
189 195 display_data_priority = List(['html', 'pdf', 'svg', 'latex', 'png', 'jpg', 'jpeg' , 'text'],
190 196 config=True,
191 197 help= """
192 198 A list of ast.NodeTransformer subclass instances, which will be applied
193 199 to user input before code is run.
194 200 """
195 201 )
196 202
197 203 extract_figures = Bool(False,
198 204 config=True,
199 205 help= """
200 206 wether to remove figure data from ipynb and store them in auxiliary
201 207 dictionnary
202 208 """
203 209 )
204 210 #-------------------------------------------------------------------------
205 211 # Instance-level attributes that are set in the constructor for this
206 212 # class.
207 213 #-------------------------------------------------------------------------
208 214 infile = Any()
209 215
210 216
211 217 infile_dir = Unicode()
212 218
213 219 def filter_data_type(self,output):
214 220 for fmt in self.display_data_priority:
215 221 if fmt in output:
216 222 return [fmt]
217 223
218 224 def __init__(self, tplfile='fullhtml', preprocessors=[], config=None,tex_environement=False, **kw):
219 225 """
220 226 tplfile : jinja template file to process.
221 227
222 228 config: the Configurable confg object to pass around
223 229
224 230 preprocessors: list of function to run on ipynb json data before conversion
225 231 to extract/inline file,
226 232
227 233 """
228 234 super(ConverterTemplate, self).__init__(config=config, **kw)
229 235 self.env = texenv if tex_environement else env
230 236 self.ext = '.tplx' if tex_environement else '.tpl'
231 237 self.nb = None
232 238 self.preprocessors = preprocessors
233 239 self.preprocessors.append(haspyout_transformer)
234 240 if self.extract_figures:
235 241 self.preprocessors.append(extract_figure_transformer)
236 242
237 243 self.env.filters['filter_data_type'] = self.filter_data_type
238 244 self.env.filters['pycomment'] = python_comment
239 245 self.env.filters['indent'] = indent
240 246 self.env.filters['rm_fake'] = rm_fake
241 247 self.env.filters['rm_ansi'] = remove_ansi
242 248 self.env.filters['markdown'] = markdown
243 249 self.env.filters['highlight'] = highlight
244 250 self.env.filters['ansi2html'] = ansi2html
245 251 self.env.filters['markdown2latex'] = markdown2latex
246 252
247 253 self.template = self.env.get_template(tplfile+self.ext)
248 254
249 255
250 256
251 257 def process(self):
252 258 """
253 259 preprocess the notebook json for easier use with the templates.
254 260 will call all the `preprocessor`s in order before returning it.
255 261 """
256 262 nb = self.nb
257 263
258 264 # dict of 'resources' that could be made by the preprocessors
259 265 # like key/value data to extract files from ipynb like in latex conversion
260 266 resources = {}
261 267
262 268 for preprocessor in self.preprocessors:
263 269 nb,resources = preprocessor(nb,resources)
264 270
265 271 return nb, resources
266 272
267 273 def convert(self):
268 274 """ convert the ipynb file
269 275
270 276 return both the converted ipynb file and a dict containing potential
271 277 other resources
272 278 """
273 279 nb,resources = self.process()
274 280 return self.template.render(nb=nb, inlining=inlining), resources
275 281
276 282
277 283 def read(self, filename):
278 284 "read and parse notebook into NotebookNode called self.nb"
279 285 with io.open(filename) as f:
280 286 self.nb = nbformat.read(f, 'json')
281 287
1 NO CONTENT: file renamed from templates/Makefile to templates/skeleton/Makefile
1 NO CONTENT: file renamed from templates/display_priority.tpl to templates/skeleton/display_priority.tpl
1 NO CONTENT: file renamed from templates/null.tpl to templates/skeleton/null.tpl
General Comments 0
You need to be logged in to leave comments. Login now