##// END OF EJS Templates
fix absolute import
Matthias BUSSONNIER -
Show More
@@ -1,248 +1,248 b''
1 from __future__ import absolute_import
1 from __future__ import absolute_import
2
2
3 from converters.html import ConverterHTML
3 from .html import ConverterHTML
4 from converters.utils import text_cell
4 from .utils import text_cell
5 from converters.utils import highlight, coalesce_streams
5 from .utils import highlight, coalesce_streams
6
6
7 from IPython.utils import path
7 from IPython.utils import path
8 from markdown import markdown
8 from markdown import markdown
9
9
10 import os
10 import os
11 import io
11 import io
12 import itertools
12 import itertools
13
13
14
14
15 class ConverterReveal(ConverterHTML):
15 class ConverterReveal(ConverterHTML):
16 """
16 """
17 Convert a ipython notebook to a html slideshow
17 Convert a ipython notebook to a html slideshow
18 based in reveal.js library.
18 based in reveal.js library.
19 """
19 """
20
20
21 @text_cell
21 @text_cell
22 def render_heading(self, cell):
22 def render_heading(self, cell):
23 marker = cell.level
23 marker = cell.level
24 return [self.meta2str(cell.metadata),
24 return [self.meta2str(cell.metadata),
25 u'<h{1}>\n {0}\n</h{1}>'.format(cell.source, marker)]
25 u'<h{1}>\n {0}\n</h{1}>'.format(cell.source, marker)]
26
26
27 def render_code(self, cell):
27 def render_code(self, cell):
28 if not cell.input:
28 if not cell.input:
29 return []
29 return []
30 lines = []
30 lines = []
31 meta_code = self.meta2str(cell.metadata)
31 meta_code = self.meta2str(cell.metadata)
32 lines.extend([meta_code])
32 lines.extend([meta_code])
33 lines.extend(['<div class="cell border-box-sizing code_cell vbox">'])
33 lines.extend(['<div class="cell border-box-sizing code_cell vbox">'])
34 lines.append('<div class="input hbox">')
34 lines.append('<div class="input hbox">')
35 n = self._get_prompt_number(cell)
35 n = self._get_prompt_number(cell)
36 lines.append(
36 lines.append(
37 '<div class="prompt input_prompt">In&nbsp;[%s]:</div>' % n
37 '<div class="prompt input_prompt">In&nbsp;[%s]:</div>' % n
38 )
38 )
39 lines.append('<div class="input_area box-flex1">')
39 lines.append('<div class="input_area box-flex1">')
40 lines.append(highlight(cell.input))
40 lines.append(highlight(cell.input))
41 lines.append('</div>') # input_area
41 lines.append('</div>') # input_area
42 lines.append('</div>') # input
42 lines.append('</div>') # input
43 if cell.outputs:
43 if cell.outputs:
44 lines.append('<div class="vbox output_wrapper">')
44 lines.append('<div class="vbox output_wrapper">')
45 lines.append('<div class="output vbox">')
45 lines.append('<div class="output vbox">')
46 for output in coalesce_streams(cell.outputs):
46 for output in coalesce_streams(cell.outputs):
47 conv_fn = self.dispatch(output.output_type)
47 conv_fn = self.dispatch(output.output_type)
48 lines.extend(conv_fn(output))
48 lines.extend(conv_fn(output))
49 lines.append('</div>') # output
49 lines.append('</div>') # output
50 lines.append('</div>') # output_wrapper
50 lines.append('</div>') # output_wrapper
51 lines.append('</div>') # cell
51 lines.append('</div>') # cell
52 return lines
52 return lines
53
53
54 @text_cell
54 @text_cell
55 def render_markdown(self, cell):
55 def render_markdown(self, cell):
56 return [self.meta2str(cell.metadata), markdown(cell.source)]
56 return [self.meta2str(cell.metadata), markdown(cell.source)]
57
57
58 def render_raw(self, cell):
58 def render_raw(self, cell):
59 if self.raw_as_verbatim:
59 if self.raw_as_verbatim:
60 return [self.in_tag('pre', self.meta2str(cell.metadata)),
60 return [self.in_tag('pre', self.meta2str(cell.metadata)),
61 self.in_tag('pre', cell.source)]
61 self.in_tag('pre', cell.source)]
62 else:
62 else:
63 return [self.meta2str(cell.metadata), cell.source]
63 return [self.meta2str(cell.metadata), cell.source]
64
64
65 def meta2str(self, meta):
65 def meta2str(self, meta):
66 "transform metadata dict (containing slides delimiters) to string "
66 "transform metadata dict (containing slides delimiters) to string "
67 try:
67 try:
68 meta_tuple = meta[u'slideshow'].items()
68 meta_tuple = meta[u'slideshow'].items()
69 except KeyError as e: # if there is not slideshow metadata
69 except KeyError as e: # if there is not slideshow metadata
70 meta_tuple = [(u'slide_type', u'untouched')]
70 meta_tuple = [(u'slide_type', u'untouched')]
71 meta_list = [[x + ' = ' + unicode(y)] for x, y in meta_tuple]
71 meta_list = [[x + ' = ' + unicode(y)] for x, y in meta_tuple]
72 return u'\n'.join(list(itertools.chain(*meta_list)))
72 return u'\n'.join(list(itertools.chain(*meta_list)))
73
73
74 def convert(self, cell_separator='\n'):
74 def convert(self, cell_separator='\n'):
75 """
75 """
76 Specific method to converts notebook to a string representation.
76 Specific method to converts notebook to a string representation.
77
77
78 Parameters
78 Parameters
79 ----------
79 ----------
80 cell_separator : string
80 cell_separator : string
81 Character or string to join cells with. Default is "\n"
81 Character or string to join cells with. Default is "\n"
82
82
83 Returns
83 Returns
84 -------
84 -------
85 out : string
85 out : string
86 """
86 """
87
87
88 lines = []
88 lines = []
89 lines.extend(self.optional_header())
89 lines.extend(self.optional_header())
90 begin = ['<div class="reveal"><div class="slides">']
90 begin = ['<div class="reveal"><div class="slides">']
91 lines.extend(begin)
91 lines.extend(begin)
92 slides_list = self.build_slides()
92 slides_list = self.build_slides()
93 lines.extend(slides_list)
93 lines.extend(slides_list)
94 end = ['</div></div>']
94 end = ['</div></div>']
95 lines.extend(end)
95 lines.extend(end)
96 lines.extend(self.optional_footer())
96 lines.extend(self.optional_footer())
97 return u'\n'.join(lines)
97 return u'\n'.join(lines)
98
98
99 def clean_text(self, cell_separator='\n'):
99 def clean_text(self, cell_separator='\n'):
100 "clean and reorganize the text list to be slided"
100 "clean and reorganize the text list to be slided"
101 text = self.main_body(cell_separator)
101 text = self.main_body(cell_separator)
102 self.delim = [u'slide_type = untouched',
102 self.delim = [u'slide_type = untouched',
103 u'slide_type = -',
103 u'slide_type = -',
104 u'slide_type = slide',
104 u'slide_type = slide',
105 u'slide_type = subslide',
105 u'slide_type = subslide',
106 u'slide_type = fragment',
106 u'slide_type = fragment',
107 u'slide_type = notes',
107 u'slide_type = notes',
108 u'slide_type = skip'] # keep this one the last
108 u'slide_type = skip'] # keep this one the last
109 text_cell_render = \
109 text_cell_render = \
110 u'<div class="text_cell_render border-box-sizing rendered_html">'
110 u'<div class="text_cell_render border-box-sizing rendered_html">'
111 for i, j in enumerate(text):
111 for i, j in enumerate(text):
112 if j in self.delim and text[i - 1] == text_cell_render:
112 if j in self.delim and text[i - 1] == text_cell_render:
113 if j == self.delim[0]:
113 if j == self.delim[0]:
114 text[i - 1] = self.delim[0]
114 text[i - 1] = self.delim[0]
115 elif j == self.delim[1]:
115 elif j == self.delim[1]:
116 text[i - 1] = self.delim[1]
116 text[i - 1] = self.delim[1]
117 elif j == self.delim[2]:
117 elif j == self.delim[2]:
118 text[i - 1] = self.delim[2]
118 text[i - 1] = self.delim[2]
119 elif j == self.delim[3]:
119 elif j == self.delim[3]:
120 text[i - 1] = self.delim[3]
120 text[i - 1] = self.delim[3]
121 elif j == self.delim[4]:
121 elif j == self.delim[4]:
122 text[i - 1] = self.delim[4]
122 text[i - 1] = self.delim[4]
123 elif j == self.delim[5]:
123 elif j == self.delim[5]:
124 text[i - 1] = self.delim[5]
124 text[i - 1] = self.delim[5]
125 else:
125 else:
126 text[i - 1] = self.delim[6]
126 text[i - 1] = self.delim[6]
127 text[i] = text_cell_render
127 text[i] = text_cell_render
128 return text
128 return text
129
129
130 def build_slides(self):
130 def build_slides(self):
131 "build the slides structure from text list and delimiters"
131 "build the slides structure from text list and delimiters"
132 text = self.clean_text()
132 text = self.clean_text()
133 left = '<section>'
133 left = '<section>'
134 right = '</section>'
134 right = '</section>'
135 notes_start = '<aside class="notes">'
135 notes_start = '<aside class="notes">'
136 notes_end = '</aside>'
136 notes_end = '</aside>'
137 #encapsulation of skipped cells
137 #encapsulation of skipped cells
138 for i, j in enumerate(text):
138 for i, j in enumerate(text):
139 if j == u'slide_type = skip':
139 if j == u'slide_type = skip':
140 text.pop(i)
140 text.pop(i)
141 text[i] = text[i][:4] + \
141 text[i] = text[i][:4] + \
142 ' style=display:none' + text[i][4:]
142 ' style=display:none' + text[i][4:]
143 #encapsulation of notes cells
143 #encapsulation of notes cells
144 for i, j in enumerate(text):
144 for i, j in enumerate(text):
145 if j == u'slide_type = notes':
145 if j == u'slide_type = notes':
146 text.pop(i)
146 text.pop(i)
147 temp_list = []
147 temp_list = []
148 while not text[i] in self.delim[:6]:
148 while not text[i] in self.delim[:6]:
149 temp_list.append(text.pop(i))
149 temp_list.append(text.pop(i))
150 else:
150 else:
151 temp_list.insert(0, notes_start)
151 temp_list.insert(0, notes_start)
152 temp_list.append(notes_end)
152 temp_list.append(notes_end)
153 text[i:i] = temp_list
153 text[i:i] = temp_list
154 # elimination of none names
154 # elimination of none names
155 for i, j in enumerate(text):
155 for i, j in enumerate(text):
156 if j in [u'slide_type = untouched', u'slide_type = -']:
156 if j in [u'slide_type = untouched', u'slide_type = -']:
157 text.pop(i)
157 text.pop(i)
158 #generation of slides as a list of list
158 #generation of slides as a list of list
159 slides = [list(x[1]) for x in itertools.groupby(text,
159 slides = [list(x[1]) for x in itertools.groupby(text,
160 lambda x: x == u'slide_type = slide') if not x[0]]
160 lambda x: x == u'slide_type = slide') if not x[0]]
161 for slide in slides:
161 for slide in slides:
162 slide.insert(0, left)
162 slide.insert(0, left)
163 slide.append(right)
163 slide.append(right)
164 # encapsulation of each fragment
164 # encapsulation of each fragment
165 for i, j in enumerate(slide):
165 for i, j in enumerate(slide):
166 if j == u'slide_type = fragment':
166 if j == u'slide_type = fragment':
167 slide.pop(i)
167 slide.pop(i)
168 slide[i] = slide[i][:4] + \
168 slide[i] = slide[i][:4] + \
169 ' class="fragment"' + slide[i][4:]
169 ' class="fragment"' + slide[i][4:]
170 # encapsulation of each nested slide
170 # encapsulation of each nested slide
171 if u'slide_type = subslide' in slide:
171 if u'slide_type = subslide' in slide:
172 slide.insert(0, left)
172 slide.insert(0, left)
173 slide.append(right)
173 slide.append(right)
174 for i, j in enumerate(slide):
174 for i, j in enumerate(slide):
175 if j == u'slide_type = subslide':
175 if j == u'slide_type = subslide':
176 slide[i] = right + left
176 slide[i] = right + left
177 return list(itertools.chain(*slides))
177 return list(itertools.chain(*slides))
178
178
179 def render(self):
179 def render(self):
180 "read, convert, and save self.infile"
180 "read, convert, and save self.infile"
181 if not hasattr(self, 'nb'):
181 if not hasattr(self, 'nb'):
182 self.read()
182 self.read()
183 self.output = self.convert()
183 self.output = self.convert()
184 assert(type(self.output) == unicode)
184 assert(type(self.output) == unicode)
185 return self.save()
185 return self.save()
186
186
187 def save(self, outfile=None, encoding=None):
187 def save(self, outfile=None, encoding=None):
188 "read and parse notebook into self.nb"
188 "read and parse notebook into self.nb"
189 if outfile is None:
189 if outfile is None:
190 outfile = self.outbase + '_slides.' + 'html'
190 outfile = self.outbase + '_slides.' + 'html'
191 if encoding is None:
191 if encoding is None:
192 encoding = self.default_encoding
192 encoding = self.default_encoding
193 with io.open(outfile, 'w', encoding=encoding) as f:
193 with io.open(outfile, 'w', encoding=encoding) as f:
194 f.write(self.output)
194 f.write(self.output)
195 return os.path.abspath(outfile)
195 return os.path.abspath(outfile)
196
196
197 def header_body(self):
197 def header_body(self):
198 "return the body of the header as a list of strings"
198 "return the body of the header as a list of strings"
199 from pygments.formatters import HtmlFormatter
199 from pygments.formatters import HtmlFormatter
200 header = []
200 header = []
201 static = os.path.join(path.get_ipython_package_dir(),
201 static = os.path.join(path.get_ipython_package_dir(),
202 'frontend', 'html', 'notebook', 'static',)
202 'frontend', 'html', 'notebook', 'static',)
203 here = os.path.split(os.path.realpath(__file__))[0]
203 here = os.path.split(os.path.realpath(__file__))[0]
204 css = os.path.join(static, 'css')
204 css = os.path.join(static, 'css')
205 for sheet in [
205 for sheet in [
206 # do we need jquery and prettify?
206 # do we need jquery and prettify?
207 # os.path.join(static, 'jquery', 'css', 'themes', 'base',
207 # os.path.join(static, 'jquery', 'css', 'themes', 'base',
208 # 'jquery-ui.min.css'),
208 # 'jquery-ui.min.css'),
209 # os.path.join(static, 'prettify', 'prettify.css'),
209 # os.path.join(static, 'prettify', 'prettify.css'),
210 os.path.join(css, 'boilerplate.css'),
210 os.path.join(css, 'boilerplate.css'),
211 os.path.join(css, 'style.min.css'),
211 os.path.join(css, 'style.min.css'),
212 # our overrides:
212 # our overrides:
213 os.path.join(here, '..', 'css', 'reveal_html.css'),
213 os.path.join(here, '..', 'css', 'reveal_html.css'),
214 ]:
214 ]:
215 header.extend(self._stylesheet(sheet))
215 header.extend(self._stylesheet(sheet))
216 # pygments css
216 # pygments css
217 pygments_css = HtmlFormatter().get_style_defs('.highlight')
217 pygments_css = HtmlFormatter().get_style_defs('.highlight')
218 header.extend(['<meta charset="UTF-8">'])
218 header.extend(['<meta charset="UTF-8">'])
219 header.extend(self.in_tag('style', pygments_css,
219 header.extend(self.in_tag('style', pygments_css,
220 dict(type='"text/css"')))
220 dict(type='"text/css"')))
221 return header
221 return header
222
222
223 def template_read(self, templ):
223 def template_read(self, templ):
224 "read the reveal_template.html"
224 "read the reveal_template.html"
225 here = os.path.split(os.path.realpath(__file__))[0]
225 here = os.path.split(os.path.realpath(__file__))[0]
226 reveal_template = os.path.join(here, '..', 'templates',
226 reveal_template = os.path.join(here, '..', 'templates',
227 templ)
227 templ)
228 with io.open(reveal_template, 'r', encoding='utf-8') as f:
228 with io.open(reveal_template, 'r', encoding='utf-8') as f:
229 template = f.readlines()
229 template = f.readlines()
230 template = [s.strip() for s in template]
230 template = [s.strip() for s in template]
231 return template
231 return template
232
232
233 def template_split(self):
233 def template_split(self):
234 "split the reveal_template.html in header and footer lists"
234 "split the reveal_template.html in header and footer lists"
235 temp = self.template_read('reveal_base.html')
235 temp = self.template_read('reveal_base.html')
236 splitted_temp = [list(x[1]) for x in itertools.groupby(temp,
236 splitted_temp = [list(x[1]) for x in itertools.groupby(temp,
237 lambda x: x == u'%slides%') if not x[0]]
237 lambda x: x == u'%slides%') if not x[0]]
238 return splitted_temp
238 return splitted_temp
239
239
240 def optional_header(self):
240 def optional_header(self):
241 optional_header_body = self.template_split()
241 optional_header_body = self.template_split()
242 return ['<!DOCTYPE html>', '<html>', '<head>'] + \
242 return ['<!DOCTYPE html>', '<html>', '<head>'] + \
243 optional_header_body[0] + self.header_body() + \
243 optional_header_body[0] + self.header_body() + \
244 ['</head>', '<body>']
244 ['</head>', '<body>']
245
245
246 def optional_footer(self):
246 def optional_footer(self):
247 optional_footer_body = self.template_split()
247 optional_footer_body = self.template_split()
248 return optional_footer_body[1] + ['</body>', '</html>'] No newline at end of file
248 return optional_footer_body[1] + ['</body>', '</html>']
General Comments 0
You need to be logged in to leave comments. Login now