From 2c4f75e00882c1f9e26fb51f5e38baccf1dc9e58 Mon Sep 17 00:00:00 2001 From: Jake Vanderplas Date: Tue, 16 Jul 2013 15:00:33 -0700 Subject: [PATCH] make liquid_tags.notebook compatible with IPython 1.0 --- liquid_tags/notebook.py | 337 ++++++++++++++++++++++++---------------- 1 file changed, 205 insertions(+), 132 deletions(-) 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 -%} +
+
{{output.text |ansi2html}}
+
+{%- endblock stream_stderr %} + +{% block pyerr -%} +
+
{{super()}}
+
+{%- 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('