##// END OF EJS Templates
Implemented loading of pyerr, images and videos outside the markdown cell
damianavila -
Show More
@@ -1,185 +1,227 b''
1 from converters.markdown import ConverterMarkdown
1 from converters.markdown import ConverterMarkdown
2 from IPython.utils.text import indent
2 from IPython.utils.text import indent, dedent
3 from converters.utils import highlight, remove_ansi
3 import io
4 import io
4 import os
5 import os
5 import itertools
6 import itertools
6
7
7 class ConverterReveal(ConverterMarkdown):
8 class ConverterReveal(ConverterMarkdown):
8 """
9 """
9 Convert a notebook to a html slideshow.
10 Convert a notebook to a html slideshow.
10
11
11 It generates a static html slideshow based in markdown and reveal.js.
12 It generates a static html slideshow based in markdown and reveal.js.
12 The delimiters for each slide, subslide, and fragment are retrieved
13 The delimiters for each slide, subslide, and fragment are retrieved
13 from the 'slideshow' metadata.
14 from the 'slideshow' metadata.
14 """
15 """
15
16
16 def __init__(self, infile, highlight_source=False, show_prompts=True,
17 def __init__(self, infile, highlight_source=False, show_prompts=True,
17 inline_prompt=True):
18 inline_prompt=True):
18 super(ConverterReveal, self).__init__(infile)
19 super(ConverterReveal, self).__init__(infile)
19 self.highlight_source = highlight_source
20 self.highlight_source = highlight_source
20 self.show_prompts = show_prompts
21 self.show_prompts = show_prompts
21 self.inline_prompt = inline_prompt
22 self.inline_prompt = inline_prompt
22
23
23 def switch_meta(self, m_list):
24 def switch_meta(self, m_list):
24 "sort order m_list to [new_section, new_subsection, new_fragment]"
25 "sort order m_list to [new_section, new_subsection, new_fragment]"
25 if len(m_list) > 1:
26 if len(m_list) > 1:
26 # do not sort when m_list = [new_subsection, new_fragment]
27 # do not sort when m_list = [new_subsection, new_fragment]
27 if not (len(m_list) == 2 and m_list[1] == [u'new_fragment = True']):
28 if not (len(m_list) == 2 and m_list[1] == [u'new_fragment = True']):
28 m_list[0], m_list[1] = m_list[1], m_list[0]
29 m_list[0], m_list[1] = m_list[1], m_list[0]
29 return m_list
30 return m_list
30
31
31 def meta2str(self, meta):
32 def meta2str(self, meta):
32 "transform metadata dict (containing slides delimiters) to string "
33 "transform metadata dict (containing slides delimiters) to string "
33 try:
34 try:
34 meta_tuple = meta[u'slideshow'].items()
35 meta_tuple = meta[u'slideshow'].items()
35 except KeyError as e:
36 except KeyError as e:
36 meta_tuple = () # if there is not slideshow metadata
37 meta_tuple = () # if there is not slideshow metadata
37 meta_list = [[x + ' = ' + unicode(y)] for x, y in meta_tuple]
38 meta_list = [[x + ' = ' + unicode(y)] for x, y in meta_tuple]
38 meta_list = self.switch_meta(meta_list)
39 meta_list = self.switch_meta(meta_list)
39 return u'\n'.join(list(itertools.chain(*meta_list)))
40 return u'\n'.join(list(itertools.chain(*meta_list)))
40
41
41 def render_heading(self, cell):
42 def render_heading(self, cell):
42 return [self.meta2str(cell.metadata),
43 return [self.meta2str(cell.metadata),
43 '{0} {1}'.format('#' * cell.level, cell.source), '']
44 '{0} {1}'.format('#' * cell.level, cell.source), '']
44
45
45 def render_code(self, cell):
46 def render_code(self, cell):
46 if not cell.input:
47 if not cell.input:
47 return []
48 return []
48 lines = []
49 lines = []
49 meta_code = self.meta2str(cell.metadata)
50 meta_code = self.meta2str(cell.metadata)
50 lines.extend([meta_code])
51 lines.extend([meta_code])
51 lines.extend(['<!-- hack -->']) # to be proper parsed
52 lines.extend(['<!-- hack -->']) # to be proper parsed
52 n = self._get_prompt_number(cell)
53 n = self._get_prompt_number(cell)
53 if self.show_prompts and not self.inline_prompt:
54 if self.show_prompts and not self.inline_prompt:
54 lines.extend(['*In[%s]:*' % n, ''])
55 lines.extend(['*In[%s]:*' % n, ''])
55 if self.show_prompts and self.inline_prompt:
56 if self.show_prompts and self.inline_prompt:
56 prompt = 'In[%s]: ' % n
57 prompt = 'In[%s]: ' % n
57 input_lines = cell.input.split('\n')
58 input_lines = cell.input.split('\n')
58 src = (prompt + input_lines[0] + '\n' +
59 src = (prompt + input_lines[0] + '\n' +
59 indent('\n'.join(input_lines[1:]), nspaces=len(prompt)))
60 indent('\n'.join(input_lines[1:]), nspaces=len(prompt)))
60 else:
61 else:
61 src = cell.input
62 src = cell.input
62 src = highlight(src) if self.highlight_source else indent(src)
63 src = highlight(src) if self.highlight_source else indent(src)
63 lines.extend([src, ''])
64 lines.extend([src, ''])
64 if cell.outputs and self.show_prompts and not self.inline_prompt:
65 if cell.outputs and self.show_prompts and not self.inline_prompt:
65 lines.extend(['*Out[%s]:*' % n, ''])
66 lines.extend(['*Out[%s]:*' % n, ''])
66 for output in cell.outputs:
67 for output in cell.outputs:
67 conv_fn = self.dispatch(output.output_type)
68 conv_fn = self.dispatch(output.output_type)
68 lines.extend(conv_fn(output))
69 lines.extend(conv_fn(output))
69 #lines.append('')
70 #lines.append('')
70 return lines
71 return lines
71
72
72 def render_markdown(self, cell):
73 def render_markdown(self, cell):
73 return [self.meta2str(cell.metadata), cell.source, '']
74 return [self.meta2str(cell.metadata), cell.source, '']
74
75
75 def render_raw(self, cell):
76 def render_raw(self, cell):
76 if self.raw_as_verbatim:
77 if self.raw_as_verbatim:
77 return [indent(self.meta2str(cell.metadata)),
78 return [indent(self.meta2str(cell.metadata)),
78 indent(cell.source), '']
79 indent(cell.source), '']
79 else:
80 else:
80 return [self.meta2str(cell.metadata), cell.source, '']
81 return [self.meta2str(cell.metadata), cell.source, '']
81
82
83 def render_pyout(self, output):
84 for fmt in ['html', 'latex', 'png', 'jpeg', 'svg', 'text']:
85 if fmt in output:
86 conv_fn = self.dispatch_display_format(fmt)
87 return conv_fn(output)
88 return []
89
90 def render_pyerr(self, output):
91 # Note: a traceback is a *list* of frames.
92 return [indent(remove_ansi('\n'.join(output.traceback))), '']
93
94 def _img_lines(self, img_file):
95 return ['![](%s)' % img_file, '']
96
97 def render_display_format_png(self, output):
98 return ['<img src="data:image/png;base64,%s"></img>' % output.png, '']
99
100 def render_display_format_svg(self, output):
101 return [output.svg, '']
102
103 def render_display_format_jpeg(self, output):
104 return ['<img src="data:image/jpeg;base64,%s"></img>' % output.jpeg, '']
105
106 def render_display_format_text(self, output):
107 return [indent(output.text), '']
108
109 def _unknown_lines(self, data):
110 return ['Warning: Unknown cell', data, '']
111
112 def render_display_format_html(self, output):
113 return [dedent(output.html), '']
114
115 def render_display_format_latex(self, output):
116 return ['LaTeX::', indent(output.latex), '']
117
118 def render_display_format_json(self, output):
119 return ['JSON:', indent(output.json), '']
120
121 def render_display_format_javascript(self, output):
122 return ['JavaScript:', indent(output.javascript), '']
123
82 def convert(self, cell_separator='\n'):
124 def convert(self, cell_separator='\n'):
83 """
125 """
84 Specific method to converts notebook to a string representation.
126 Specific method to converts notebook to a string representation.
85
127
86 Parameters
128 Parameters
87 ----------
129 ----------
88 cell_separator : string
130 cell_separator : string
89 Character or string to join cells with. Default is "\n"
131 Character or string to join cells with. Default is "\n"
90
132
91 Returns
133 Returns
92 -------
134 -------
93 out : string
135 out : string
94 """
136 """
95
137
96 lines = []
138 lines = []
97 lines.extend(self.optional_header())
139 lines.extend(self.optional_header())
98 begin = ['<div class="reveal"><div class="slides">']
140 begin = ['<div class="reveal"><div class="slides">']
99 lines.extend(begin)
141 lines.extend(begin)
100 slides_list = self.build_slides(cell_separator)
142 slides_list = self.build_slides(cell_separator)
101 lines.extend(slides_list)
143 lines.extend(slides_list)
102 end = ['</div></div>']
144 end = ['</div></div>']
103 lines.extend(end)
145 lines.extend(end)
104 lines.extend(self.optional_footer())
146 lines.extend(self.optional_footer())
105 return u'\n'.join(lines)
147 return u'\n'.join(lines)
106
148
107 def build_slides(self, cell_separator='\n'):
149 def build_slides(self, cell_separator='\n'):
108 "build the slides structure from text list and delimiters"
150 "build the slides structure from text list and delimiters"
109 text = self.main_body(cell_separator)
151 text = self.main_body(cell_separator)
110 delim_false = [u'new_section = False',
152 delim_false = [u'new_section = False',
111 u'new_subsection = False',
153 u'new_subsection = False',
112 u'new_fragment = False']
154 u'new_fragment = False']
113 text = [x for x in text if not x in delim_false]
155 text = [x for x in text if not x in delim_false]
114 left = '<section data-markdown><script type="text/template">'
156 left = '<section data-markdown><script type="text/template">'
115 right = '</script></section>'
157 right = '</script></section>'
116 # build lists representing each slide delimited by new_section
158 # build lists representing each slide delimited by new_section
117 slides = [list(x[1]) for x in itertools.groupby(text,
159 slides = [list(x[1]) for x in itertools.groupby(text,
118 lambda x: x == u'new_section = True') if not x[0]]
160 lambda x: x == u'new_section = True') if not x[0]]
119 for slide in slides:
161 for slide in slides:
120 slide.insert(0, u'') # for proper interline in html file
162 slide.insert(0, u'') # for proper interline in html file
121 slide.insert(0, left)
163 slide.insert(0, left)
122 slide.append(right)
164 slide.append(right)
123 # build each vertical slide delimited by new_subsection
165 # build each vertical slide delimited by new_subsection
124 if slide[2] == u'new_subsection = True':
166 if slide[2] == u'new_subsection = True':
125 slide.pop(2)
167 slide.pop(2)
126 slide.insert(0, '<section>')
168 slide.insert(0, '<section>')
127 slide.append('</section>')
169 slide.append('</section>')
128 for i, j in enumerate(slide):
170 for i, j in enumerate(slide):
129 if j == u'new_subsection = True':
171 if j == u'new_subsection = True':
130 slide[i] = right + left
172 slide[i] = right + left
131 slide.insert(i + 1, u'') # for proper interline
173 slide.insert(i + 1, u'') # for proper interline
132 #defensive: if user do not begin new_subsection with a new_section
174 #defensive: if user do not begin new_subsection with a new_section
133 elif slide[4] == u'new_subsection = True':
175 elif slide[4] == u'new_subsection = True':
134 slide[4] = right
176 slide[4] = right
135 slide.insert(5, u'') # for proper interline
177 slide.insert(5, u'') # for proper interline
136 slide.insert(5, left)
178 slide.insert(5, left)
137 slide.insert(5, '<section>')
179 slide.insert(5, '<section>')
138 slide.append('</section>')
180 slide.append('</section>')
139 for i, j in enumerate(slide):
181 for i, j in enumerate(slide):
140 if j == u'new_subsection = True':
182 if j == u'new_subsection = True':
141 slide[i] = right + left
183 slide[i] = right + left
142 slide.insert(i + 1, u'') # for proper interline
184 slide.insert(i + 1, u'') # for proper interline
143 # build each fragment delimited by new_fragment
185 # build each fragment delimited by new_fragment
144 for i, j in enumerate(slide):
186 for i, j in enumerate(slide):
145 if j == u'new_fragment = True':
187 if j == u'new_fragment = True':
146 slide[i] = '<p class="fragment">'
188 slide[i] = '<p class="fragment">'
147 slide[i + 2] = '</p>'
189 slide[i + 2] = '</p>'
148 slide.insert(i + 3, u'') # for proper interline
190 slide.insert(i + 3, u'') # for proper interline
149 return list(itertools.chain(*slides))
191 return list(itertools.chain(*slides))
150
192
151 def save(self, outfile=None, encoding=None):
193 def save(self, outfile=None, encoding=None):
152 "read and parse notebook into self.nb"
194 "read and parse notebook into self.nb"
153 if outfile is None:
195 if outfile is None:
154 outfile = self.outbase + '_slides.' + 'html'
196 outfile = self.outbase + '_slides.' + 'html'
155 if encoding is None:
197 if encoding is None:
156 encoding = self.default_encoding
198 encoding = self.default_encoding
157 with io.open(outfile, 'w', encoding=encoding) as f:
199 with io.open(outfile, 'w', encoding=encoding) as f:
158 f.write(self.output)
200 f.write(self.output)
159 return os.path.abspath(outfile)
201 return os.path.abspath(outfile)
160
202
161 def template_read(self):
203 def template_read(self):
162 "read the reveal_template.html"
204 "read the reveal_template.html"
163 here = os.path.split(os.path.realpath(__file__))[0]
205 here = os.path.split(os.path.realpath(__file__))[0]
164 reveal_template = os.path.join(here, '..', 'templates',
206 reveal_template = os.path.join(here, '..', 'templates',
165 'reveal_base.html')
207 'reveal_base.html')
166 with io.open(reveal_template, 'r', encoding='utf-8') as f:
208 with io.open(reveal_template, 'r', encoding='utf-8') as f:
167 template = f.readlines()
209 template = f.readlines()
168 template = [s.strip() for s in template]
210 template = [s.strip() for s in template]
169 return template
211 return template
170
212
171 def template_split(self):
213 def template_split(self):
172 "split the reveal_template.html in header and footer lists"
214 "split the reveal_template.html in header and footer lists"
173 temp = self.template_read()
215 temp = self.template_read()
174 splitted_temp = [list(x[1]) for x in itertools.groupby(temp,
216 splitted_temp = [list(x[1]) for x in itertools.groupby(temp,
175 lambda x: x == u'%slides%') if not x[0]]
217 lambda x: x == u'%slides%') if not x[0]]
176 return splitted_temp
218 return splitted_temp
177
219
178 def optional_header(self):
220 def optional_header(self):
179 optional_header_body = self.template_split()
221 optional_header_body = self.template_split()
180 return optional_header_body[0]
222 return optional_header_body[0]
181
223
182 def optional_footer(self):
224 def optional_footer(self):
183 optional_footer_body = self.template_split()
225 optional_footer_body = self.template_split()
184 return optional_footer_body[1]
226 return optional_footer_body[1]
185
227
General Comments 0
You need to be logged in to leave comments. Login now