##// END OF EJS Templates
add a coalesce stream transformer
Matthias BUSSONNIER -
Show More
@@ -1,187 +1,188 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 import converters.transformers as trans
19 import converters.transformers as trans
20 from converters.jinja_filters import (python_comment, indent,
20 from converters.jinja_filters import (python_comment, indent,
21 rm_fake, remove_ansi, markdown, highlight,
21 rm_fake, remove_ansi, markdown, highlight,
22 ansi2html, markdown2latex, escape_tex, FilterDataType)
22 ansi2html, markdown2latex, escape_tex, FilterDataType)
23
23
24 from converters.utils import markdown2rst
24 from converters.utils import markdown2rst
25
25
26
26
27
27
28 # Stdlib imports
28 # Stdlib imports
29 import io
29 import io
30
30
31 from IPython.utils.traitlets import MetaHasTraits
31 from IPython.utils.traitlets import MetaHasTraits
32
32
33 from jinja2 import Environment, FileSystemLoader
33 from jinja2 import Environment, FileSystemLoader
34 env = Environment(
34 env = Environment(
35 loader=FileSystemLoader([
35 loader=FileSystemLoader([
36 './templates/',
36 './templates/',
37 './templates/skeleton/',
37 './templates/skeleton/',
38 ]),
38 ]),
39 extensions=['jinja2.ext.loopcontrols']
39 extensions=['jinja2.ext.loopcontrols']
40 )
40 )
41
41
42 texenv = Environment(
42 texenv = Environment(
43 loader=FileSystemLoader([
43 loader=FileSystemLoader([
44 './templates/tex/',
44 './templates/tex/',
45 './templates/skeleton/tex/',
45 './templates/skeleton/tex/',
46 ]),
46 ]),
47 extensions=['jinja2.ext.loopcontrols']
47 extensions=['jinja2.ext.loopcontrols']
48 )
48 )
49
49
50 # IPython imports
50 # IPython imports
51 from IPython.nbformat import current as nbformat
51 from IPython.nbformat import current as nbformat
52 from IPython.config.configurable import Configurable
52 from IPython.config.configurable import Configurable
53 from IPython.utils.traitlets import ( Unicode, List, Bool)
53 from IPython.utils.traitlets import ( Unicode, List, Bool)
54
54
55 #-----------------------------------------------------------------------------
55 #-----------------------------------------------------------------------------
56 # Class declarations
56 # Class declarations
57 #-----------------------------------------------------------------------------
57 #-----------------------------------------------------------------------------
58 class ConversionException(Exception):
58 class ConversionException(Exception):
59 pass
59 pass
60
60
61
61
62
62
63 texenv.block_start_string = '((*'
63 texenv.block_start_string = '((*'
64 texenv.block_end_string = '*))'
64 texenv.block_end_string = '*))'
65
65
66 texenv.variable_start_string = '((('
66 texenv.variable_start_string = '((('
67 texenv.variable_end_string = ')))'
67 texenv.variable_end_string = ')))'
68
68
69 texenv.comment_start_string = '((='
69 texenv.comment_start_string = '((='
70 texenv.comment_end_string = '=))'
70 texenv.comment_end_string = '=))'
71
71
72 texenv.filters['escape_tex'] = escape_tex
72 texenv.filters['escape_tex'] = escape_tex
73
73
74
74
75 class ConverterTemplate(Configurable):
75 class ConverterTemplate(Configurable):
76 """ A Jinja2 base converter templates
76 """ A Jinja2 base converter templates
77
77
78 Preprocess the ipynb files, feed it throug jinja templates,
78 Preprocess the ipynb files, feed it throug jinja templates,
79 and spit an converted files and a data object with other data
79 and spit an converted files and a data object with other data
80
80
81 shoudl be mostly configurable
81 shoudl be mostly configurable
82 """
82 """
83
83
84 pre_transformer_order = List(['haspyout_transformer'],
84 pre_transformer_order = List(['haspyout_transformer'],
85 config=True,
85 config=True,
86 help= """
86 help= """
87 An ordered list of pre transformer to apply to the ipynb
87 An ordered list of pre transformer to apply to the ipynb
88 file befor running through templates
88 file befor running through templates
89 """
89 """
90 )
90 )
91
91
92 tex_environement = Bool(False,
92 tex_environement = Bool(False,
93 config=True,
93 config=True,
94 help=""" is this a tex environment or not """)
94 help=""" is this a tex environment or not """)
95
95
96 template_file = Unicode('',
96 template_file = Unicode('',
97 config=True,
97 config=True,
98 help=""" Name of the template file to use """ )
98 help=""" Name of the template file to use """ )
99 #-------------------------------------------------------------------------
99 #-------------------------------------------------------------------------
100 # Instance-level attributes that are set in the constructor for this
100 # Instance-level attributes that are set in the constructor for this
101 # class.
101 # class.
102 #-------------------------------------------------------------------------
102 #-------------------------------------------------------------------------
103
103
104
104
105 preprocessors = []
105 preprocessors = []
106
106
107 def __init__(self, preprocessors={}, jinja_filters={}, config=None, **kw):
107 def __init__(self, preprocessors={}, jinja_filters={}, config=None, **kw):
108 """ Init a new converter.
108 """ Init a new converter.
109
109
110
110
111 config: the Configurable confgg object to pass around
111 config: the Configurable confgg object to pass around
112
112
113 preprocessors: dict of **availlable** key/value function to run on
113 preprocessors: dict of **availlable** key/value function to run on
114 ipynb json data before conversion to extract/inline file,
114 ipynb json data before conversion to extract/inline file,
115
115
116 jinja_filter : dict of supplementary jinja filter that should be made
116 jinja_filter : dict of supplementary jinja filter that should be made
117 availlable in template. If those are of Configurable Class type, they
117 availlable in template. If those are of Configurable Class type, they
118 will be instanciated with the config object as argument.
118 will be instanciated with the config object as argument.
119
119
120 """
120 """
121 super(ConverterTemplate, self).__init__(config=config, **kw)
121 super(ConverterTemplate, self).__init__(config=config, **kw)
122 self.env = texenv if self.tex_environement else env
122 self.env = texenv if self.tex_environement else env
123 self.ext = '.tplx' if self.tex_environement else '.tpl'
123 self.ext = '.tplx' if self.tex_environement else '.tpl'
124
124
125 for name in self.pre_transformer_order:
125 for name in self.pre_transformer_order:
126 transformer = getattr(preprocessors, name, getattr(trans, name, None))
126 transformer = getattr(preprocessors, name, getattr(trans, name, None))
127 if isinstance(transformer, MetaHasTraits):
127 if isinstance(transformer, MetaHasTraits):
128 transformer = transformer(config=config)
128 transformer = transformer(config=config)
129 self.preprocessors.append(transformer)
129 self.preprocessors.append(transformer)
130
130
131 ## for compat, remove later
131 ## for compat, remove later
132 self.preprocessors.append(trans.coalesce_streams)
132 self.preprocessors.append(trans.ExtractFigureTransformer(config=config))
133 self.preprocessors.append(trans.ExtractFigureTransformer(config=config))
133 self.preprocessors.append(trans.RevealHelpTransformer(config=config))
134 self.preprocessors.append(trans.RevealHelpTransformer(config=config))
134 self.preprocessors.append(trans.CSSHtmlHeaderTransformer(config=config))
135 self.preprocessors.append(trans.CSSHtmlHeaderTransformer(config=config))
135
136
136 ##
137 ##
137 self.env.filters['filter_data_type'] = FilterDataType(config=config)
138 self.env.filters['filter_data_type'] = FilterDataType(config=config)
138 self.env.filters['pycomment'] = python_comment
139 self.env.filters['pycomment'] = python_comment
139 self.env.filters['indent'] = indent
140 self.env.filters['indent'] = indent
140 self.env.filters['rm_fake'] = rm_fake
141 self.env.filters['rm_fake'] = rm_fake
141 self.env.filters['rm_ansi'] = remove_ansi
142 self.env.filters['rm_ansi'] = remove_ansi
142 self.env.filters['markdown'] = markdown
143 self.env.filters['markdown'] = markdown
143 self.env.filters['highlight'] = highlight
144 self.env.filters['highlight'] = highlight
144 self.env.filters['ansi2html'] = ansi2html
145 self.env.filters['ansi2html'] = ansi2html
145 self.env.filters['markdown2latex'] = markdown2latex
146 self.env.filters['markdown2latex'] = markdown2latex
146 self.env.filters['markdown2rst'] = markdown2rst
147 self.env.filters['markdown2rst'] = markdown2rst
147 for key, filtr in jinja_filters.iteritems():
148 for key, filtr in jinja_filters.iteritems():
148 if isinstance(filtr, MetaHasTraits):
149 if isinstance(filtr, MetaHasTraits):
149 self.env.filters[key] = filtr(config=config)
150 self.env.filters[key] = filtr(config=config)
150 else :
151 else :
151 self.env.filters[key] = filtr
152 self.env.filters[key] = filtr
152
153
153 self.template = self.env.get_template(self.template_file+self.ext)
154 self.template = self.env.get_template(self.template_file+self.ext)
154
155
155
156
156 def process(self, nb):
157 def process(self, nb):
157 """
158 """
158 preprocess the notebook json for easier use with the templates.
159 preprocess the notebook json for easier use with the templates.
159 will call all the `preprocessor`s in order before returning it.
160 will call all the `preprocessor`s in order before returning it.
160 """
161 """
161
162
162 # dict of 'resources' that could be made by the preprocessors
163 # dict of 'resources' that could be made by the preprocessors
163 # like key/value data to extract files from ipynb like in latex conversion
164 # like key/value data to extract files from ipynb like in latex conversion
164 resources = {}
165 resources = {}
165
166
166 for preprocessor in self.preprocessors:
167 for preprocessor in self.preprocessors:
167 nb, resources = preprocessor(nb, resources)
168 nb, resources = preprocessor(nb, resources)
168
169
169 return nb, resources
170 return nb, resources
170
171
171 def convert(self, nb):
172 def convert(self, nb):
172 """ convert the ipynb file
173 """ convert the ipynb file
173
174
174 return both the converted ipynb file and a dict containing potential
175 return both the converted ipynb file and a dict containing potential
175 other resources
176 other resources
176 """
177 """
177 nb, resources = self.process(nb)
178 nb, resources = self.process(nb)
178 return self.template.render(nb=nb, resources=resources), resources
179 return self.template.render(nb=nb, resources=resources), resources
179
180
180
181
181 def from_filename(self, filename):
182 def from_filename(self, filename):
182 "read and parse notebook into NotebookNode called self.nb"
183 "read and parse notebook into NotebookNode called self.nb"
183 with io.open(filename) as f:
184 with io.open(filename) as f:
184 return self.convert(nbformat.read(f, 'json'))
185 return self.convert(nbformat.read(f, 'json'))
185
186
186
187
187
188
@@ -1,293 +1,320 b''
1 """
1 """
2
2
3 """
3 """
4
4
5 from __future__ import print_function
5 from __future__ import print_function
6
6
7
7
8 from IPython.config.configurable import Configurable
8 from IPython.config.configurable import Configurable
9 from IPython.utils.traitlets import Unicode, Bool, Dict, List
9 from IPython.utils.traitlets import Unicode, Bool, Dict, List
10
10
11 class ConfigurableTransformers(Configurable):
11 class ConfigurableTransformers(Configurable):
12 """ A configurable transformer """
12 """ A configurable transformer """
13
13
14 def __init__(self, config=None, **kw):
14 def __init__(self, config=None, **kw):
15 super(ConfigurableTransformers, self).__init__(config=config, **kw)
15 super(ConfigurableTransformers, self).__init__(config=config, **kw)
16
16
17 def __call__(self, nb, other):
17 def __call__(self, nb, other):
18 try :
18 try :
19 for worksheet in nb.worksheets :
19 for worksheet in nb.worksheets :
20 for index, cell in enumerate(worksheet.cells):
20 for index, cell in enumerate(worksheet.cells):
21 worksheet.cells[index], other = self.cell_transform(cell, other, index)
21 worksheet.cells[index], other = self.cell_transform(cell, other, index)
22 return nb, other
22 return nb, other
23 except NotImplementedError:
23 except NotImplementedError:
24 raise NotImplementedError('should be implemented by subclass')
24 raise NotImplementedError('should be implemented by subclass')
25
25
26 def cell_transform(self, cell, other, index):
26 def cell_transform(self, cell, other, index):
27 """
27 """
28 Overwrite if you want to apply a transformation on each cell
28 Overwrite if you want to apply a transformation on each cell
29 """
29 """
30 raise NotImplementedError('should be implemented by subclass')
30 raise NotImplementedError('should be implemented by subclass')
31
31
32
32
33 class ActivatableTransformer(ConfigurableTransformers):
33 class ActivatableTransformer(ConfigurableTransformers):
34
34
35 enabled = Bool(False, config=True)
35 enabled = Bool(False, config=True)
36
36
37 def __call__(self, nb, other):
37 def __call__(self, nb, other):
38 if not self.enabled :
38 if not self.enabled :
39 return nb, other
39 return nb, other
40 else :
40 else :
41 return super(ActivatableTransformer, self).__call__(nb, other)
41 return super(ActivatableTransformer, self).__call__(nb, other)
42
42
43
43
44 def cell_preprocessor(function):
44 def cell_preprocessor(function):
45 """ wrap a function to be executed on all cells of a notebook
45 """ wrap a function to be executed on all cells of a notebook
46
46
47 wrapped function parameters :
47 wrapped function parameters :
48 cell : the cell
48 cell : the cell
49 other : external resources
49 other : external resources
50 index : index of the cell
50 index : index of the cell
51 """
51 """
52 def wrappedfunc(nb, other):
52 def wrappedfunc(nb, other):
53 for worksheet in nb.worksheets :
53 for worksheet in nb.worksheets :
54 for index, cell in enumerate(worksheet.cells):
54 for index, cell in enumerate(worksheet.cells):
55 worksheet.cells[index], other = function(cell, other, index)
55 worksheet.cells[index], other = function(cell, other, index)
56 return nb, other
56 return nb, other
57 return wrappedfunc
57 return wrappedfunc
58
58
59
59
60 @cell_preprocessor
60 @cell_preprocessor
61 def haspyout_transformer(cell, other, count):
61 def haspyout_transformer(cell, other, count):
62 """
62 """
63 Add a haspyout flag to cell that have it
63 Add a haspyout flag to cell that have it
64
64
65 Easier for templating, where you can't know in advance
65 Easier for templating, where you can't know in advance
66 wether to write the out prompt
66 wether to write the out prompt
67
67
68 """
68 """
69 cell.type = cell.cell_type
69 cell.type = cell.cell_type
70 cell.haspyout = False
70 cell.haspyout = False
71 for out in cell.get('outputs', []):
71 for out in cell.get('outputs', []):
72 if out.output_type == 'pyout':
72 if out.output_type == 'pyout':
73 cell.haspyout = True
73 cell.haspyout = True
74 break
74 break
75 return cell, other
75 return cell, other
76
76
77 @cell_preprocessor
78 def coalesce_streams(cell, other, count):
79 """merge consecutive sequences of stream output into single stream
80
81 to prevent extra newlines inserted at flush calls
82
83 TODO: handle \r deletion
84 """
85
86 outputs = cell.get('outputs', None)
87 if not outputs:
88 return cell, other
89 new_outputs = []
90 last = outputs[0]
91 new_outputs = [last]
92 for output in outputs[1:]:
93 if (output.output_type == 'stream' and
94 last.output_type == 'stream' and
95 last.stream == output.stream
96 ):
97 last.text += output.text
98 else:
99 new_outputs.append(output)
100
101 cell.outputs = new_outputs
102 return cell, other
103
77
104
78 # todo, make the key part configurable.
105 # todo, make the key part configurable.
79
106
80 class ExtractFigureTransformer(ActivatableTransformer):
107 class ExtractFigureTransformer(ActivatableTransformer):
81
108
82 extra_ext_map = Dict({},
109 extra_ext_map = Dict({},
83 config=True,
110 config=True,
84 help="""extra map to override extension based on type.
111 help="""extra map to override extension based on type.
85 Usefull for latex where svg will be converted to pdf before inclusion
112 Usefull for latex where svg will be converted to pdf before inclusion
86 """
113 """
87 )
114 )
88 display_data_priority = List(['html', 'pdf', 'svg', 'latex', 'png', 'jpg', 'jpeg' , 'text'],
115 display_data_priority = List(['html', 'pdf', 'svg', 'latex', 'png', 'jpg', 'jpeg' , 'text'],
89 config=True,
116 config=True,
90 help= """
117 help= """
91 An ordered list of prefered output type, the first
118 An ordered list of prefered output type, the first
92 encounterd will usually be used when converting discarding
119 encounterd will usually be used when converting discarding
93 the others.
120 the others.
94 """
121 """
95 )
122 )
96
123
97
124
98 #to do change this to .format {} syntax
125 #to do change this to .format {} syntax
99 key_tpl = Unicode('_fig_%02i.%s', config=True)
126 key_tpl = Unicode('_fig_%02i.%s', config=True)
100
127
101 def _get_ext(self, ext):
128 def _get_ext(self, ext):
102 if ext in self.extra_ext_map :
129 if ext in self.extra_ext_map :
103 return self.extra_ext_map[ext]
130 return self.extra_ext_map[ext]
104 return ext
131 return ext
105
132
106 def _new_figure(self, data, fmt, count):
133 def _new_figure(self, data, fmt, count):
107 """Create a new figure file in the given format.
134 """Create a new figure file in the given format.
108
135
109 Returns a path relative to the input file.
136 Returns a path relative to the input file.
110 """
137 """
111 figname = self.key_tpl % (count, self._get_ext(fmt))
138 figname = self.key_tpl % (count, self._get_ext(fmt))
112 key = self.key_tpl % (count, fmt)
139 key = self.key_tpl % (count, fmt)
113
140
114 # Binary files are base64-encoded, SVG is already XML
141 # Binary files are base64-encoded, SVG is already XML
115 if fmt in ('png', 'jpg', 'pdf'):
142 if fmt in ('png', 'jpg', 'pdf'):
116 data = data.decode('base64')
143 data = data.decode('base64')
117
144
118 return figname, key, data
145 return figname, key, data
119
146
120
147
121 def cell_transform(self, cell, other, count):
148 def cell_transform(self, cell, other, count):
122 if other.get('figures', None) is None :
149 if other.get('figures', None) is None :
123 other['figures'] = {}
150 other['figures'] = {}
124 for out in cell.get('outputs', []):
151 for out in cell.get('outputs', []):
125 for out_type in self.display_data_priority:
152 for out_type in self.display_data_priority:
126 if out.hasattr(out_type):
153 if out.hasattr(out_type):
127 figname, key, data = self._new_figure(out[out_type], out_type, count)
154 figname, key, data = self._new_figure(out[out_type], out_type, count)
128 out['key_'+out_type] = figname
155 out['key_'+out_type] = figname
129 other['figures'][key] = data
156 other['figures'][key] = data
130 count = count+1
157 count = count+1
131 return cell, other
158 return cell, other
132
159
133 class RevealHelpTransformer(ConfigurableTransformers):
160 class RevealHelpTransformer(ConfigurableTransformers):
134
161
135 section_open = False
162 section_open = False
136 subsection_open = False
163 subsection_open = False
137 fragment_open = False
164 fragment_open = False
138
165
139 def open_subsection(self):
166 def open_subsection(self):
140 self.subsection_open = True
167 self.subsection_open = True
141 return True
168 return True
142
169
143 def open_section(self):
170 def open_section(self):
144 self.section_open = True
171 self.section_open = True
145 return True
172 return True
146
173
147 def open_fragment(self):
174 def open_fragment(self):
148 self.fragment_open = True
175 self.fragment_open = True
149 return True
176 return True
150
177
151 # could probaly write those maybe_close/open
178 # could probaly write those maybe_close/open
152 # with a function functor
179 # with a function functor
153 def maybe_close_section(self):
180 def maybe_close_section(self):
154 """return True is already open, false otherwise
181 """return True is already open, false otherwise
155 and change state to close
182 and change state to close
156 """
183 """
157 if self.section_open :
184 if self.section_open :
158 self.section_open = False
185 self.section_open = False
159 return True
186 return True
160 else :
187 else :
161 return False
188 return False
162
189
163 def maybe_open_section(self):
190 def maybe_open_section(self):
164 """return True is already open, false otherwise
191 """return True is already open, false otherwise
165 and change state to close
192 and change state to close
166 """
193 """
167 if not self.section_open :
194 if not self.section_open :
168 self.section_open = True
195 self.section_open = True
169 return True
196 return True
170 else :
197 else :
171 return False
198 return False
172
199
173 def maybe_open_subsection(self):
200 def maybe_open_subsection(self):
174 """return True is already open, false otherwise
201 """return True is already open, false otherwise
175 and change state to close
202 and change state to close
176 """
203 """
177 if not self.subsection_open :
204 if not self.subsection_open :
178 self.subsection_open = True
205 self.subsection_open = True
179 return True
206 return True
180 else :
207 else :
181 return False
208 return False
182
209
183 def maybe_close_subsection(self):
210 def maybe_close_subsection(self):
184 """return True is already open, false otherwise
211 """return True is already open, false otherwise
185 and change state to close
212 and change state to close
186 """
213 """
187 if self.subsection_open :
214 if self.subsection_open :
188 self.subsection_open = False
215 self.subsection_open = False
189 return True
216 return True
190 else :
217 else :
191 return False
218 return False
192
219
193 def maybe_close_fragment(self):
220 def maybe_close_fragment(self):
194 """return True is already open, false otherwise
221 """return True is already open, false otherwise
195 and change state to close
222 and change state to close
196 """
223 """
197 if self.fragment_open :
224 if self.fragment_open :
198 self.fragment_open = False
225 self.fragment_open = False
199 return True
226 return True
200 else :
227 else :
201 return False
228 return False
202
229
203 def cell_transform(self, cell, other, count):
230 def cell_transform(self, cell, other, count):
204 ctype = cell.metadata.get('slideshow', {}).get('slide_type', None)
231 ctype = cell.metadata.get('slideshow', {}).get('slide_type', None)
205 if ctype in [None, '-'] :
232 if ctype in [None, '-'] :
206 cell.metadata.slideshow = {}
233 cell.metadata.slideshow = {}
207 cell.metadata.slideshow['slide_type'] = None
234 cell.metadata.slideshow['slide_type'] = None
208 elif ctype == 'fragment':
235 elif ctype == 'fragment':
209 cell.metadata.slideshow.close_fragment = self.maybe_close_fragment()
236 cell.metadata.slideshow.close_fragment = self.maybe_close_fragment()
210 cell.metadata.slideshow.close_subsection = False
237 cell.metadata.slideshow.close_subsection = False
211 cell.metadata.slideshow.close_section = False
238 cell.metadata.slideshow.close_section = False
212
239
213 cell.metadata.slideshow.open_section = self.maybe_open_section()
240 cell.metadata.slideshow.open_section = self.maybe_open_section()
214 cell.metadata.slideshow.open_subsection = self.maybe_open_subsection()
241 cell.metadata.slideshow.open_subsection = self.maybe_open_subsection()
215 cell.metadata.slideshow.open_fragment = self.open_fragment()
242 cell.metadata.slideshow.open_fragment = self.open_fragment()
216
243
217 elif ctype == 'subslide':
244 elif ctype == 'subslide':
218 cell.metadata.slideshow.close_fragment = self.maybe_close_fragment()
245 cell.metadata.slideshow.close_fragment = self.maybe_close_fragment()
219 cell.metadata.slideshow.close_subsection = self.maybe_close_subsection()
246 cell.metadata.slideshow.close_subsection = self.maybe_close_subsection()
220 cell.metadata.slideshow.close_section = False
247 cell.metadata.slideshow.close_section = False
221
248
222 cell.metadata.slideshow.open_section = self.maybe_open_section()
249 cell.metadata.slideshow.open_section = self.maybe_open_section()
223 cell.metadata.slideshow.open_subsection = self.open_subsection()
250 cell.metadata.slideshow.open_subsection = self.open_subsection()
224 cell.metadata.slideshow.open_fragment = False
251 cell.metadata.slideshow.open_fragment = False
225 elif ctype == 'slide':
252 elif ctype == 'slide':
226 cell.metadata.slideshow.close_fragment = self.maybe_close_fragment()
253 cell.metadata.slideshow.close_fragment = self.maybe_close_fragment()
227 cell.metadata.slideshow.close_subsection = self.maybe_close_subsection()
254 cell.metadata.slideshow.close_subsection = self.maybe_close_subsection()
228 cell.metadata.slideshow.close_section = self.maybe_close_section()
255 cell.metadata.slideshow.close_section = self.maybe_close_section()
229
256
230 cell.metadata.slideshow.open_section = self.open_section()
257 cell.metadata.slideshow.open_section = self.open_section()
231 cell.metadata.slideshow.open_subsection = self.open_subsection()
258 cell.metadata.slideshow.open_subsection = self.open_subsection()
232 cell.metadata.slideshow.open_fragment = False
259 cell.metadata.slideshow.open_fragment = False
233 return cell, other
260 return cell, other
234
261
235
262
236 class CSSHtmlHeaderTransformer(ActivatableTransformer):
263 class CSSHtmlHeaderTransformer(ActivatableTransformer):
237
264
238 def __call__(self, nb, resources):
265 def __call__(self, nb, resources):
239 """Fetch and add css to the resource dict
266 """Fetch and add css to the resource dict
240
267
241 Fetch css from IPython adn Pygment to add at the beginning
268 Fetch css from IPython adn Pygment to add at the beginning
242 of the html files.
269 of the html files.
243
270
244 Add this css in resources in the "inlining.css" key
271 Add this css in resources in the "inlining.css" key
245 """
272 """
246 resources['inlining'] = {}
273 resources['inlining'] = {}
247 resources['inlining']['css'] = self.header
274 resources['inlining']['css'] = self.header
248 return nb, resources
275 return nb, resources
249
276
250 header = []
277 header = []
251
278
252 def __init__(self, config=None, **kw):
279 def __init__(self, config=None, **kw):
253 super(CSSHtmlHeaderTransformer, self).__init__(config=config, **kw)
280 super(CSSHtmlHeaderTransformer, self).__init__(config=config, **kw)
254 if self.enabled :
281 if self.enabled :
255 self.regen_header()
282 self.regen_header()
256
283
257 def regen_header(self):
284 def regen_header(self):
258 ## lazy load asa this might not be use in many transformers
285 ## lazy load asa this might not be use in many transformers
259 import os
286 import os
260 from IPython.utils import path
287 from IPython.utils import path
261 import io
288 import io
262 from pygments.formatters import HtmlFormatter
289 from pygments.formatters import HtmlFormatter
263 header = []
290 header = []
264 static = os.path.join(path.get_ipython_package_dir(),
291 static = os.path.join(path.get_ipython_package_dir(),
265 'frontend', 'html', 'notebook', 'static',
292 'frontend', 'html', 'notebook', 'static',
266 )
293 )
267 here = os.path.split(os.path.realpath(__file__))[0]
294 here = os.path.split(os.path.realpath(__file__))[0]
268 css = os.path.join(static, 'css')
295 css = os.path.join(static, 'css')
269 for sheet in [
296 for sheet in [
270 # do we need jquery and prettify?
297 # do we need jquery and prettify?
271 # os.path.join(static, 'jquery', 'css', 'themes', 'base',
298 # os.path.join(static, 'jquery', 'css', 'themes', 'base',
272 # 'jquery-ui.min.css'),
299 # 'jquery-ui.min.css'),
273 # os.path.join(static, 'prettify', 'prettify.css'),
300 # os.path.join(static, 'prettify', 'prettify.css'),
274 os.path.join(css, 'boilerplate.css'),
301 os.path.join(css, 'boilerplate.css'),
275 os.path.join(css, 'fbm.css'),
302 os.path.join(css, 'fbm.css'),
276 os.path.join(css, 'notebook.css'),
303 os.path.join(css, 'notebook.css'),
277 os.path.join(css, 'renderedhtml.css'),
304 os.path.join(css, 'renderedhtml.css'),
278 os.path.join(css, 'style.min.css'),
305 os.path.join(css, 'style.min.css'),
279 # our overrides:
306 # our overrides:
280 os.path.join(here, '..', 'css', 'static_html.css'),
307 os.path.join(here, '..', 'css', 'static_html.css'),
281 ]:
308 ]:
282 try:
309 try:
283 with io.open(sheet, encoding='utf-8') as f:
310 with io.open(sheet, encoding='utf-8') as f:
284 s = f.read()
311 s = f.read()
285 header.append(s)
312 header.append(s)
286 except IOError:
313 except IOError:
287 # new version of ipython with style.min.css, pass
314 # new version of ipython with style.min.css, pass
288 pass
315 pass
289
316
290 pygments_css = HtmlFormatter().get_style_defs('.highlight')
317 pygments_css = HtmlFormatter().get_style_defs('.highlight')
291 header.append(pygments_css)
318 header.append(pygments_css)
292 self.header = header
319 self.header = header
293
320
General Comments 0
You need to be logged in to leave comments. Login now