diff --git a/liquid_tags/notebook.py b/liquid_tags/notebook.py index c5d3f11..eacbff8 100644 --- a/liquid_tags/notebook.py +++ b/liquid_tags/notebook.py @@ -17,138 +17,198 @@ config file: The cells[start:end] statement is optional, and can be used to specify which block of cells from the notebook to include. +Requirements +------------ +- The plugin requires IPython version 1.0 or above. It no longer supports the + standalone nbconvert package, which has been deprecated. + Details ------- -Because the conversion and formatting of notebooks is rather involved, there -are a few extra steps required for this plugin: +Because the notebook relies on some rather extensive custom CSS, the use of +this plugin requires additional CSS to be inserted into the blog theme. +After typing "make html" when using the notebook tag, a file called +``_nb_header.html`` will be produced in the main directory. The content +of the file should be included in the header of the theme. An easy way +to accomplish this is to add the following lines within the header template +of the theme you use: -- First, the plugin requires that the nbconvert package [1]_ to be in the - python path. For example, in bash, this can be set via + {% if EXTRA_HEADER %} + {{ EXTRA_HEADER }} + {% endif %} - >$ export PYTHONPATH=/path/to/nbconvert/ +and in your ``pelicanconf.py`` file, include the line: -- After typing "make html" when using the notebook tag, a file called - ``_nb_header.html`` will be produced in the main directory. The content - of the file should be included in the header of the theme. An easy way - to accomplish this is to add the following lines within the header template - of the theme you use: + EXTRA_HEADER = open('_nb_header.html').read().decode('utf-8') - {% if EXTRA_HEADER %} - {{ EXTRA_HEADER }} - {% endif %} - - and in your ``pelicanconf.py`` file, include the line: - - EXTRA_HEADER = open('_nb_header.html').read().decode('utf-8') - -[1] https://github.com/ipython/nbconvert +this will insert the appropriate CSS. All efforts have been made to ensure +that this CSS will not override formats within the blog theme, but there may +still be some conflicts. """ import re import os from .mdx_liquid_tags import LiquidTags -# nbconverters: part of the nbconvert package -from converters import ConverterBloggerHTML # requires nbconvert package -separate_available = False +try: + from IPython import nbconvert +except ImportError: + raise ValueError("IPython version 1.0+ required for notebook tag") +from IPython.nbconvert.filters.highlight import _pygment_highlight +from pygments.formatters import HtmlFormatter + +from IPython.nbconvert.exporters import BasicHTMLExporter +from IPython.config import Config + +from IPython.nbformat import current as nbformat +from IPython.nbconvert.transformers import ActivatableTransformer + +from IPython.utils.traitlets import Integer +from copy import deepcopy + +from jinja2 import DictLoader + +# assume not more than ten million cells in notebook +# this shouldn't ever be a problem +MAX_NB_CELLS = 9999999 + +#---------------------------------------------------------------------- +# Some code that will be added to the header: +# Some of the following javascript/css include is adapted from +# IPython/nbconvert/templates/fullhtml.tpl, while some are custom tags +# specifically designed to make the results look good within the +# pelican-octopress theme. +JS_INCLUDE = """ + + + +""" + +# This, for some reason, results in paranthetical statements being rendered +# in math mode. +DONT_USE = """ + +""" + +CSS_WRAPPER = """ + +""" + + +#---------------------------------------------------------------------- +# Create a custom transformer +class SubCell(ActivatableTransformer): + """A transformer to select a slice of the cells of a notebook""" + start = Integer(0, config=True, + help="first cell of notebook to be converted") + end = Integer(MAX_NB_CELLS, config=True, + help="last cell of notebook to be converted") + + def __call__(self, nb, resources): + nbc = deepcopy(nb) + for worksheet in nbc.worksheets : + cells = worksheet.cells[:] + end = min(len(cells), self.end) + worksheet.cells = cells[self.start:end] + return nbc, resources + +#---------------------------------------------------------------------- +# Customize the html template: +# This changes the
tags in basic_html.tpl to+{{output.text |ansi2html}}+ +{%- endblock stream_stdout %} + +{% block stream_stderr -%} + +{%- endblock stream_stderr %} + +{% block pyerr -%} + +{%- endblock pyerr %} + +{%- block data_text %} +{{output.text | ansi2html}}+{%- endblock -%} +"""}) + + +#---------------------------------------------------------------------- +# Custom highlighter: +# instead of using class='highlight', use class='highlight-ipynb' +def custom_highlighter(source, language='ipython'): + formatter = HtmlFormatter(cssclass='highlight-ipynb') + output = _pygment_highlight(source, formatter, language) + return output.replace('', '') + + +#---------------------------------------------------------------------- +# Below is the pelican plugin code. +# SYNTAX = "{% notebook /path/to/notebook.ipynb [ cells[start:end] ] %}" FORMAT = re.compile(r"""^(\s+)?(?P\S+)(\s+)?((cells\[)(?P -?[0-9]*):(?P -?[0-9]*)(\]))?(\s+)?$""") -def process_body(body): - body = '\n'.join(body) - - # replace the highlight tags - body = body.replace('highlight', 'highlight-ipynb') - - # specify tags - body = body.replace('" - - # specialize headers - for h in '123456': - body = body.replace('