##// END OF EJS Templates
Cleaning of reveal converter to make the PR
damianavila -
Show More
@@ -1,339 +1,207 b''
1 from __future__ import absolute_import
1 from __future__ import absolute_import
2
2
3 from converters.html import ConverterHTML
3 from converters.html import ConverterHTML
4 from converters.utils import text_cell#, output_container
4 from converters.utils import text_cell
5 from converters.utils import highlight, coalesce_streams#, ansi2html
5 from converters.utils import highlight, coalesce_streams
6
7 #from IPython.utils import path
8 #from IPython.utils.text import indent, dedent
9 from markdown import markdown
6 from markdown import markdown
7
10 import os
8 import os
11 import io
9 import io
12 import itertools
10 import itertools
13
11
14
12
15 class ConverterReveal(ConverterHTML):
13 class ConverterReveal(ConverterHTML):
16 #"""
14 #"""
17 #Convert a notebook to a html slideshow.
15 #Convert a notebook to a html slideshow.
18
16
19 #It generates a static html slideshow based in markdown and reveal.js.
17 #It generates a static html slideshow based reveal.js.
20 #The delimiters for each slide, subslide, and fragment are retrieved
18 #The delimiters for each "Header slide", "Slide"", and "Fragment"
21 #from the 'slideshow' metadata.
19 #are retrieved from the 'slideshow' metadata.
22 #"""
20 #"""
23
21
24 #def __init__(self):
25 #super(ConverterReveal, self).__init__()
26
27 #extension = 'html'
28 #blank_symbol = ' '
29
30 #def in_tag(self, tag, src, attrs=None):
31 #"""Return a list of elements bracketed by the given tag"""
32 #attr_s = '' if attrs is None else \
33 #' '.join("%s=%s" % (attr, value)
34 #for attr, value in attrs.iteritems())
35 #return ['<%s %s>' % (tag, attr_s), src, '</%s>' % tag]
36
37 #def _ansi_colored(self, text):
38 #return ['<pre>%s</pre>' % ansi2html(text)]
39
40 #def _stylesheet(self, fname):
41 #with io.open(fname, encoding='utf-8') as f:
42 #s = f.read()
43 #return self.in_tag('style', s, dict(type='"text/css"'))
44
45 #def _out_prompt(self, output):
46 #if output.output_type == 'pyout':
47 #content = 'Out[%s]:' % self._get_prompt_number(output)
48 #else:
49 #content = ''
50 #return ['<div class="prompt output_prompt">%s</div>' % content]
51
52 #def header_body(self):
53 #"""Return the body of the header as a list of strings."""
54
55 #from pygments.formatters import HtmlFormatter
56
57 #header = []
58 #static = os.path.join(path.get_ipython_package_dir(),
59 #'frontend', 'html', 'notebook', 'static',
60 #)
61 #here = os.path.split(os.path.realpath(__file__))[0]
62 #css = os.path.join(static, 'css')
63 #for sheet in [
64 ## do we need jquery and prettify?
65 ## os.path.join(static, 'jquery', 'css', 'themes', 'base',
66 ## 'jquery-ui.min.css'),
67 ## os.path.join(static, 'prettify', 'prettify.css'),
68 #os.path.join(css, 'boilerplate.css'),
69 #os.path.join(css, 'fbm.css'),
70 #os.path.join(css, 'notebook.css'),
71 #os.path.join(css, 'renderedhtml.css'),
72 ## our overrides:
73 #os.path.join(here, '..', 'css', 'static_html.css'),
74 #]:
75 #header.extend(self._stylesheet(sheet))
76
77 ## pygments css
78 #pygments_css = HtmlFormatter().get_style_defs('.highlight')
79 #header.extend(['<meta charset="UTF-8">'])
80 #header.extend(self.in_tag('style', pygments_css,
81 #dict(type='"text/css"')))
82
83 ## TODO: this should be allowed to use local mathjax:
84 #header.extend(self.in_tag('script', '', {'type': '"text/javascript"',
85 #'src': '"https://c328740.ssl.cf1.rackcdn.com/mathjax/'
86 #'latest/MathJax.js?config=TeX-AMS_HTML"',
87 #}))
88 #with io.open(os.path.join(here, '..', 'js', 'initmathjax.js'),
89 #encoding='utf-8') as f:
90 #header.extend(self.in_tag('script', f.read(),
91 #{'type': '"text/javascript"'}))
92 #return header
93
94 #def optional_header(self):
95 #return ['<html>', '<head>'] + self.header_body() + \
96 #['</head>', '<body>']
97
98 #def optional_footer(self):
99 #return ['</body>', '</html>']
100
101 @text_cell
22 @text_cell
102 def render_heading(self, cell):
23 def render_heading(self, cell):
103 marker = cell.level
24 marker = cell.level
104 return [self.meta2str(cell.metadata),
25 return [self.meta2str(cell.metadata),
105 u'<h{1}>\n {0}\n</h{1}>'.format(cell.source, marker)]
26 u'<h{1}>\n {0}\n</h{1}>'.format(cell.source, marker)]
106
27
107 def render_code(self, cell):
28 def render_code(self, cell):
108 if not cell.input:
29 if not cell.input:
109 return []
30 return []
110
31
111 lines = []
32 lines = []
112 meta_code = self.meta2str(cell.metadata)
33 meta_code = self.meta2str(cell.metadata)
113 lines.extend([meta_code])
34 lines.extend([meta_code])
114
35
115 lines.extend(['<div class="cell border-box-sizing code_cell vbox">'])
36 lines.extend(['<div class="cell border-box-sizing code_cell vbox">'])
116
37
117 lines.append('<div class="input hbox">')
38 lines.append('<div class="input hbox">')
118 n = self._get_prompt_number(cell)
39 n = self._get_prompt_number(cell)
119 lines.append(
40 lines.append(
120 '<div class="prompt input_prompt">In&nbsp;[%s]:</div>' % n
41 '<div class="prompt input_prompt">In&nbsp;[%s]:</div>' % n
121 )
42 )
122 lines.append('<div class="input_area box-flex1">')
43 lines.append('<div class="input_area box-flex1">')
123 lines.append(highlight(cell.input))
44 lines.append(highlight(cell.input))
124 lines.append('</div>') # input_area
45 lines.append('</div>') # input_area
125 lines.append('</div>') # input
46 lines.append('</div>') # input
126
47
127 if cell.outputs:
48 if cell.outputs:
128 lines.append('<div class="vbox output_wrapper">')
49 lines.append('<div class="vbox output_wrapper">')
129 lines.append('<div class="output vbox">')
50 lines.append('<div class="output vbox">')
130
51
131 for output in coalesce_streams(cell.outputs):
52 for output in coalesce_streams(cell.outputs):
132 conv_fn = self.dispatch(output.output_type)
53 conv_fn = self.dispatch(output.output_type)
133 lines.extend(conv_fn(output))
54 lines.extend(conv_fn(output))
134
55
135 lines.append('</div>') # output
56 lines.append('</div>') # output
136 lines.append('</div>') # output_wrapper
57 lines.append('</div>') # output_wrapper
137
58
138 lines.append('</div>') # cell
59 lines.append('</div>') # cell
139
60
140 return lines
61 return lines
141
62
142 @text_cell
63 @text_cell
143 def render_markdown(self, cell):
64 def render_markdown(self, cell):
144 return [self.meta2str(cell.metadata), markdown(cell.source)]
65 return [self.meta2str(cell.metadata), markdown(cell.source)]
145
66
146 def render_raw(self, cell):
67 def render_raw(self, cell):
147 if self.raw_as_verbatim:
68 if self.raw_as_verbatim:
148 return [self.in_tag('pre', self.meta2str(cell.metadata)),
69 return [self.in_tag('pre', self.meta2str(cell.metadata)),
149 self.in_tag('pre', cell.source)] # testing
70 self.in_tag('pre', cell.source)]
150 else:
71 else:
151 return [self.meta2str(cell.metadata), cell.source]
72 return [self.meta2str(cell.metadata), cell.source]
152
73
153 #@output_container
154 #def render_pyout(self, output):
155 #for fmt in ['html', 'latex', 'png', 'jpeg', 'svg', 'text']:
156 #if fmt in output:
157 #conv_fn = self.dispatch_display_format(fmt)
158 #return conv_fn(output)
159 #return []
160
161 #render_display_data = render_pyout
162
163 #@output_container
164 #def render_stream(self, output):
165 #return self._ansi_colored(output.text)
166
167 #@output_container
168 #def render_pyerr(self, output):
169 ## Note: a traceback is a *list* of frames.
170 ## lines = []
171
172 ## stb =
173 #return self._ansi_colored('\n'.join(output.traceback))
174
175 #def _img_lines(self, img_file):
176 #return ['<img src="%s">' % img_file, '</img>']
177
178 #def _unknown_lines(self, data):
179 #return ['<h2>Warning:: Unknown cell</h2>'] + self.in_tag('pre', data)
180
181 #def render_display_format_png(self, output):
182 #return ['<img src="data:image/png;base64,%s"></img>' % output.png]
183
184 #def render_display_format_svg(self, output):
185 #return [output.svg]
186
187 #def render_display_format_jpeg(self, output):
188 #return ['<img src="data:image/jpeg;base64,%s"></img>' % output.jpeg]
189
190 #def render_display_format_text(self, output):
191 #return self._ansi_colored(output.text)
192
193 #def render_display_format_html(self, output):
194 #return [output.html]
195
196 #def render_display_format_latex(self, output):
197 #return [output.latex]
198
199 #def render_display_format_json(self, output):
200 ## html ignores json
201 #return []
202
203 #def render_display_format_javascript(self, output):
204 #return [output.javascript]
205
206 def meta2str(self, meta):
74 def meta2str(self, meta):
207 "transform metadata dict (containing slides delimiters) to string "
75 "transform metadata dict (containing slides delimiters) to string "
208 try:
76 try:
209 meta_tuple = meta[u'slideshow'].items()
77 meta_tuple = meta[u'slideshow'].items()
210 except KeyError as e: # if there is not slideshow metadata
78 except KeyError as e: # if there is not slideshow metadata
211 meta_tuple = [(u'slide_type', u'untouched')]
79 meta_tuple = [(u'slide_type', u'untouched')]
212 meta_list = [[x + ' = ' + unicode(y)] for x, y in meta_tuple]
80 meta_list = [[x + ' = ' + unicode(y)] for x, y in meta_tuple]
213 return u'\n'.join(list(itertools.chain(*meta_list)))
81 return u'\n'.join(list(itertools.chain(*meta_list)))
214
82
215 def convert(self, cell_separator='\n'):
83 def convert(self, cell_separator='\n'):
216 """
84 """
217 Specific method to converts notebook to a string representation.
85 Specific method to converts notebook to a string representation.
218
86
219 Parameters
87 Parameters
220 ----------
88 ----------
221 cell_separator : string
89 cell_separator : string
222 Character or string to join cells with. Default is "\n"
90 Character or string to join cells with. Default is "\n"
223
91
224 Returns
92 Returns
225 -------
93 -------
226 out : string
94 out : string
227 """
95 """
228
96
229 lines = []
97 lines = []
230 lines.extend(self.optional_header())
98 lines.extend(self.optional_header())
231 begin = ['<div class="reveal"><div class="slides">']
99 begin = ['<div class="reveal"><div class="slides">']
232 lines.extend(begin)
100 lines.extend(begin)
233 slides_list = self.build_slides()
101 slides_list = self.build_slides()
234 lines.extend(slides_list)
102 lines.extend(slides_list)
235 end = ['</div></div>']
103 end = ['</div></div>']
236 lines.extend(end)
104 lines.extend(end)
237 lines.extend(self.optional_footer())
105 lines.extend(self.optional_footer())
238 return u'\n'.join(lines)
106 return u'\n'.join(lines)
239
107
240 def clean_text(self, cell_separator='\n'):
108 def clean_text(self, cell_separator='\n'):
241 "clean and reorganize the text list to be slided"
109 "clean and reorganize the text list to be slided"
242 text = self.main_body(cell_separator)
110 text = self.main_body(cell_separator)
243 self.delim = [u'slide_type = untouched',
111 self.delim = [u'slide_type = untouched',
244 u'slide_type = -',
112 u'slide_type = -',
245 u'slide_type = header_slide',
113 u'slide_type = header_slide',
246 u'slide_type = slide',
114 u'slide_type = slide',
247 u'slide_type = fragment',
115 u'slide_type = fragment',
248 u'slide_type = skip']
116 u'slide_type = skip']
249 text_cell_render = \
117 text_cell_render = \
250 u'<div class="text_cell_render border-box-sizing rendered_html">'
118 u'<div class="text_cell_render border-box-sizing rendered_html">'
251 for i, j in enumerate(text):
119 for i, j in enumerate(text):
252 if j in self.delim and text[i - 1] == text_cell_render:
120 if j in self.delim and text[i - 1] == text_cell_render:
253 if j == self.delim[0]:
121 if j == self.delim[0]:
254 text[i - 1] = self.delim[0]
122 text[i - 1] = self.delim[0]
255 elif j == self.delim[1]:
123 elif j == self.delim[1]:
256 text[i - 1] = self.delim[1]
124 text[i - 1] = self.delim[1]
257 elif j == self.delim[2]:
125 elif j == self.delim[2]:
258 text[i - 1] = self.delim[2]
126 text[i - 1] = self.delim[2]
259 elif j == self.delim[3]:
127 elif j == self.delim[3]:
260 text[i - 1] = self.delim[3]
128 text[i - 1] = self.delim[3]
261 elif j == self.delim[4]:
129 elif j == self.delim[4]:
262 text[i - 1] = self.delim[4]
130 text[i - 1] = self.delim[4]
263 else:
131 else:
264 text[i - 1] = self.delim[5]
132 text[i - 1] = self.delim[5]
265 text[i] = text_cell_render
133 text[i] = text_cell_render
266 text[0] = u'slide_type = header_slide' # defensive code
134 text[0] = u'slide_type = header_slide' # defensive code
267 text.append(u'slide_type = untouched') # to end search of skipped
135 text.append(u'slide_type = untouched') # to end search of skipped
268 return text
136 return text
269
137
270 def build_slides(self):
138 def build_slides(self):
271 "build the slides structure from text list and delimiters"
139 "build the slides structure from text list and delimiters"
272 text = self.clean_text()
140 text = self.clean_text()
273 left = '<section>'
141 left = '<section>'
274 right = '</section>'
142 right = '</section>'
275 set_delim = self.delim[:5]
143 set_delim = self.delim[:5]
276 #elimination of skipped cells
144 #elimination of skipped cells
277 for i, j in enumerate(text):
145 for i, j in enumerate(text):
278 if j == u'slide_type = skip':
146 if j == u'slide_type = skip':
279 text.pop(i)
147 text.pop(i)
280 while not text[i] in set_delim:
148 while not text[i] in set_delim:
281 text.pop(i)
149 text.pop(i)
282 # elimination of none names
150 # elimination of none names
283 for i, j in enumerate(text):
151 for i, j in enumerate(text):
284 if j in [u'slide_type = untouched', u'slide_type = -']:
152 if j in [u'slide_type = untouched', u'slide_type = -']:
285 text.pop(i)
153 text.pop(i)
286 #generation of slides as a list of list
154 #generation of slides as a list of list
287 slides = [list(x[1]) for x in itertools.groupby(text,
155 slides = [list(x[1]) for x in itertools.groupby(text,
288 lambda x: x == u'slide_type = header_slide') if not x[0]]
156 lambda x: x == u'slide_type = header_slide') if not x[0]]
289 for slide in slides:
157 for slide in slides:
290 slide.insert(0, left)
158 slide.insert(0, left)
291 slide.append(right)
159 slide.append(right)
292 # encapsulation of each fragment
160 # encapsulation of each fragment
293 for i, j in enumerate(slide):
161 for i, j in enumerate(slide):
294 if j == u'slide_type = fragment':
162 if j == u'slide_type = fragment':
295 slide.pop(i)
163 slide.pop(i)
296 slide[i] = slide[i][:4] + ' class="fragment"' + slide[i][4:]
164 slide[i] = slide[i][:4] + ' class="fragment"' + slide[i][4:]
297 # encapsulation of each nested slide
165 # encapsulation of each nested slide
298 if u'slide_type = slide' in slide:
166 if u'slide_type = slide' in slide:
299 slide.insert(0, '<section>')
167 slide.insert(0, '<section>')
300 slide.append('</section>')
168 slide.append('</section>')
301 for i, j in enumerate(slide):
169 for i, j in enumerate(slide):
302 if j == u'slide_type = slide':
170 if j == u'slide_type = slide':
303 slide[i] = right + left
171 slide[i] = right + left
304 return list(itertools.chain(*slides))
172 return list(itertools.chain(*slides))
305
173
306 def save(self, outfile=None, encoding=None):
174 def save(self, outfile=None, encoding=None):
307 "read and parse notebook into self.nb"
175 "read and parse notebook into self.nb"
308 if outfile is None:
176 if outfile is None:
309 outfile = self.outbase + '_slides.' + 'html'
177 outfile = self.outbase + '_slides.' + 'html'
310 if encoding is None:
178 if encoding is None:
311 encoding = self.default_encoding
179 encoding = self.default_encoding
312 with io.open(outfile, 'w', encoding=encoding) as f:
180 with io.open(outfile, 'w', encoding=encoding) as f:
313 f.write(self.output)
181 f.write(self.output)
314 return os.path.abspath(outfile)
182 return os.path.abspath(outfile)
315
183
316 def template_read(self):
184 def template_read(self):
317 "read the reveal_template.html"
185 "read the reveal_template.html"
318 here = os.path.split(os.path.realpath(__file__))[0]
186 here = os.path.split(os.path.realpath(__file__))[0]
319 reveal_template = os.path.join(here, '..', 'templates',
187 reveal_template = os.path.join(here, '..', 'templates',
320 'reveal_base.html')
188 'reveal_base.html')
321 with io.open(reveal_template, 'r', encoding='utf-8') as f:
189 with io.open(reveal_template, 'r', encoding='utf-8') as f:
322 template = f.readlines()
190 template = f.readlines()
323 template = [s.strip() for s in template]
191 template = [s.strip() for s in template]
324 return template
192 return template
325
193
326 def template_split(self):
194 def template_split(self):
327 "split the reveal_template.html in header and footer lists"
195 "split the reveal_template.html in header and footer lists"
328 temp = self.template_read()
196 temp = self.template_read()
329 splitted_temp = [list(x[1]) for x in itertools.groupby(temp,
197 splitted_temp = [list(x[1]) for x in itertools.groupby(temp,
330 lambda x: x == u'%slides%') if not x[0]]
198 lambda x: x == u'%slides%') if not x[0]]
331 return splitted_temp
199 return splitted_temp
332
200
333 def optional_header(self):
201 def optional_header(self):
334 optional_header_body = self.template_split()
202 optional_header_body = self.template_split()
335 return optional_header_body[0]
203 return optional_header_body[0]
336
204
337 def optional_footer(self):
205 def optional_footer(self):
338 optional_footer_body = self.template_split()
206 optional_footer_body = self.template_split()
339 return optional_footer_body[1] No newline at end of file
207 return optional_footer_body[1]
General Comments 0
You need to be logged in to leave comments. Login now