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