from __future__ import absolute_import from converters.html import ConverterHTML from converters.utils import text_cell#, output_container from converters.utils import highlight, coalesce_streams#, ansi2html #from IPython.utils import path #from IPython.utils.text import indent, dedent from markdown import markdown import os import io import itertools class ConverterReveal(ConverterHTML): #""" #Convert a notebook to a html slideshow. #It generates a static html slideshow based in markdown and reveal.js. #The delimiters for each slide, subslide, and fragment are retrieved #from the 'slideshow' metadata. #""" #def __init__(self): #super(ConverterReveal, self).__init__() #extension = 'html' #blank_symbol = ' ' #def in_tag(self, tag, src, attrs=None): #"""Return a list of elements bracketed by the given tag""" #attr_s = '' if attrs is None else \ #' '.join("%s=%s" % (attr, value) #for attr, value in attrs.iteritems()) #return ['<%s %s>' % (tag, attr_s), src, '' % tag] #def _ansi_colored(self, text): #return ['
%s
' % ansi2html(text)] #def _stylesheet(self, fname): #with io.open(fname, encoding='utf-8') as f: #s = f.read() #return self.in_tag('style', s, dict(type='"text/css"')) #def _out_prompt(self, output): #if output.output_type == 'pyout': #content = 'Out[%s]:' % self._get_prompt_number(output) #else: #content = '' #return ['
%s
' % content] #def header_body(self): #"""Return the body of the header as a list of strings.""" #from pygments.formatters import HtmlFormatter #header = [] #static = os.path.join(path.get_ipython_package_dir(), #'frontend', 'html', 'notebook', 'static', #) #here = os.path.split(os.path.realpath(__file__))[0] #css = os.path.join(static, 'css') #for sheet in [ ## do we need jquery and prettify? ## os.path.join(static, 'jquery', 'css', 'themes', 'base', ## 'jquery-ui.min.css'), ## os.path.join(static, 'prettify', 'prettify.css'), #os.path.join(css, 'boilerplate.css'), #os.path.join(css, 'fbm.css'), #os.path.join(css, 'notebook.css'), #os.path.join(css, 'renderedhtml.css'), ## our overrides: #os.path.join(here, '..', 'css', 'static_html.css'), #]: #header.extend(self._stylesheet(sheet)) ## pygments css #pygments_css = HtmlFormatter().get_style_defs('.highlight') #header.extend(['']) #header.extend(self.in_tag('style', pygments_css, #dict(type='"text/css"'))) ## TODO: this should be allowed to use local mathjax: #header.extend(self.in_tag('script', '', {'type': '"text/javascript"', #'src': '"https://c328740.ssl.cf1.rackcdn.com/mathjax/' #'latest/MathJax.js?config=TeX-AMS_HTML"', #})) #with io.open(os.path.join(here, '..', 'js', 'initmathjax.js'), #encoding='utf-8') as f: #header.extend(self.in_tag('script', f.read(), #{'type': '"text/javascript"'})) #return header #def optional_header(self): #return ['', ''] + self.header_body() + \ #['', ''] #def optional_footer(self): #return ['', ''] @text_cell def render_heading(self, cell): marker = cell.level return [self.meta2str(cell.metadata), u'\n {0}\n'.format(cell.source, marker)] def render_code(self, cell): if not cell.input: return [] lines = [] meta_code = self.meta2str(cell.metadata) lines.extend([meta_code]) lines.extend(['
']) lines.append('
') n = self._get_prompt_number(cell) lines.append( '
In [%s]:
' % n ) lines.append('
') lines.append(highlight(cell.input)) lines.append('
') # input_area lines.append('
') # input if cell.outputs: lines.append('
') lines.append('
') for output in coalesce_streams(cell.outputs): conv_fn = self.dispatch(output.output_type) lines.extend(conv_fn(output)) lines.append('
') # output lines.append('
') # output_wrapper lines.append('
') # cell return lines @text_cell def render_markdown(self, cell): return [self.meta2str(cell.metadata), markdown(cell.source)] def render_raw(self, cell): if self.raw_as_verbatim: return [self.in_tag('pre', self.meta2str(cell.metadata)), self.in_tag('pre', cell.source)] # testing else: return [self.meta2str(cell.metadata), cell.source] #@output_container #def render_pyout(self, output): #for fmt in ['html', 'latex', 'png', 'jpeg', 'svg', 'text']: #if fmt in output: #conv_fn = self.dispatch_display_format(fmt) #return conv_fn(output) #return [] #render_display_data = render_pyout #@output_container #def render_stream(self, output): #return self._ansi_colored(output.text) #@output_container #def render_pyerr(self, output): ## Note: a traceback is a *list* of frames. ## lines = [] ## stb = #return self._ansi_colored('\n'.join(output.traceback)) #def _img_lines(self, img_file): #return ['' % img_file, ''] #def _unknown_lines(self, data): #return ['

Warning:: Unknown cell

'] + self.in_tag('pre', data) #def render_display_format_png(self, output): #return ['' % output.png] #def render_display_format_svg(self, output): #return [output.svg] #def render_display_format_jpeg(self, output): #return ['' % output.jpeg] #def render_display_format_text(self, output): #return self._ansi_colored(output.text) #def render_display_format_html(self, output): #return [output.html] #def render_display_format_latex(self, output): #return [output.latex] #def render_display_format_json(self, output): ## html ignores json #return [] #def render_display_format_javascript(self, output): #return [output.javascript] def meta2str(self, meta): "transform metadata dict (containing slides delimiters) to string " try: meta_tuple = meta[u'slideshow'].items() except KeyError as e: # if there is not slideshow metadata meta_tuple = [(u'slide_type', u'untouched')] meta_list = [[x + ' = ' + unicode(y)] for x, y in meta_tuple] return u'\n'.join(list(itertools.chain(*meta_list))) def convert(self, cell_separator='\n'): """ Specific method to converts notebook to a string representation. Parameters ---------- cell_separator : string Character or string to join cells with. Default is "\n" Returns ------- out : string """ lines = [] lines.extend(self.optional_header()) begin = ['
'] lines.extend(begin) slides_list = self.build_slides() lines.extend(slides_list) end = ['
'] lines.extend(end) lines.extend(self.optional_footer()) return u'\n'.join(lines) def clean_text(self, cell_separator='\n'): "clean and reorganize the text list to be slided" text = self.main_body(cell_separator) self.delim = [u'slide_type = untouched', u'slide_type = -', u'slide_type = header_slide', u'slide_type = slide', u'slide_type = fragment', u'slide_type = skip'] text_cell_render = \ u'
' for i, j in enumerate(text): if j in self.delim and text[i - 1] == text_cell_render: if j == self.delim[0]: text[i - 1] = self.delim[0] elif j == self.delim[1]: text[i - 1] = self.delim[1] elif j == self.delim[2]: text[i - 1] = self.delim[2] elif j == self.delim[3]: text[i - 1] = self.delim[3] elif j == self.delim[4]: text[i - 1] = self.delim[4] else: text[i - 1] = self.delim[5] text[i] = text_cell_render text[0] = u'slide_type = header_slide' # defensive code text.append(u'slide_type = untouched') # to end search of skipped return text def build_slides(self): "build the slides structure from text list and delimiters" text = self.clean_text() left = '
' right = '
' set_delim = self.delim[:5] #elimination of skipped cells for i, j in enumerate(text): if j == u'slide_type = skip': text.pop(i) while not text[i] in set_delim: text.pop(i) # elimination of none names for i, j in enumerate(text): if j in [u'slide_type = untouched', u'slide_type = -']: text.pop(i) #generation of slides as a list of list slides = [list(x[1]) for x in itertools.groupby(text, lambda x: x == u'slide_type = header_slide') if not x[0]] for slide in slides: slide.insert(0, left) slide.append(right) # encapsulation of each fragment for i, j in enumerate(slide): if j == u'slide_type = fragment': slide.pop(i) slide[i] = slide[i][:4] + ' class="fragment"' + slide[i][4:] # encapsulation of each nested slide if u'slide_type = slide' in slide: slide.insert(0, '
') slide.append('
') for i, j in enumerate(slide): if j == u'slide_type = slide': slide[i] = right + left return list(itertools.chain(*slides)) def save(self, outfile=None, encoding=None): "read and parse notebook into self.nb" if outfile is None: outfile = self.outbase + '_slides.' + 'html' if encoding is None: encoding = self.default_encoding with io.open(outfile, 'w', encoding=encoding) as f: f.write(self.output) return os.path.abspath(outfile) def template_read(self): "read the reveal_template.html" here = os.path.split(os.path.realpath(__file__))[0] reveal_template = os.path.join(here, '..', 'templates', 'reveal_base.html') with io.open(reveal_template, 'r', encoding='utf-8') as f: template = f.readlines() template = [s.strip() for s in template] return template def template_split(self): "split the reveal_template.html in header and footer lists" temp = self.template_read() splitted_temp = [list(x[1]) for x in itertools.groupby(temp, lambda x: x == u'%slides%') if not x[0]] return splitted_temp def optional_header(self): optional_header_body = self.template_split() return optional_header_body[0] def optional_footer(self): optional_footer_body = self.template_split() return optional_footer_body[1]