I learned about IPython Notebooks from the fantastic blog of jakevdp. Realizing what a great way they are to interactivly manipulate Python code and transform the results into web pages, I started playing around with them and the pelican site generator myself. I had a few science questions on my mind for which I thought writing things up with some nice graphical illustrations would clarify things for myself and maybe others. Then I arrived at a point where I had long input boxes in my web pages with Python code that was not very interesting. I just wanted to have some figures for illustration. Of course I could just generate some plots, save them and load them into the Notebook to display them. But that seemed like an unnecessary detour if I already created the plots in the notebook. Could I not just hide the input cells? It turns out the answer was apparently “no”.
So I interrupted the process of writing about the original problems that were on my mind and set out to modify the liquid_tags pelican plugin that generates these pages so that the input code cells can be hidden.
Hiding input cells in the IPython Notebook is a feature that is often requested but not implemented yet. Looking at the discussions of the various github issues that discuss this, it is not clear to me that it will ever be available. There are a lot of complications trying to do this right in an interactive notebook. However, the problem should be manageable in static web pages. So I set out to dig into the internals of the liquid_tags pelican plugin. The result is currently in my fork of the pelican-plugins repository.
I assume you have a basic familiarity with how to blog with pelican and IPython Notebooks. If not, have a look at these ressources first:
- Jake’s blog post on migrating to pelican
- themodernscientist’s blog post on blogging with notebooks and pelican
- The liquid_tags README
My branch comes with a new template file pelicanhtml.tpl
in liquid_tags
. To enable code collapsing, you need to copy this to the top level of your blog directory. Collapsible code boxes are then created by adding a comment line to the Python code. These come in two flavors:
- Boxes that are collapsed on load and can be expanded are created with the comment
# <!-- collapse=True -->
- Boxes that are expanded on load and can be collapsed are created with the comment
# <!-- collapse=False -->
If no collapse comment is given, the standard input box is created. Note that the pattern above has to match exactly, including the number of whitespaces, since the official release of the jinja2 templating engine does not yet support regular expressions. The collapse comment line is removed during page creation so that it is not visible in the examples below.
Here is an example of a rather long input code box using one of the matplotlib
example programs. This one is collapsed on load:
Here is a shorter code snippet, which is shown on load but can be collapsed:
x = numpy.random.normal(size=1000)
y = numpy.random.normal(size=1000)
fig = plt.figure(figsize=(5,5))
plt.scatter(x, y)
plt.draw()
Further Details on the Implementation¶
The expand/collapse function is implemented via jQuery’s .slideToggle()
. To work, this obviously requires that your readers have javascript enabled. This also means that if they don’t, they cannot unhide code, which is collapsed on load. JQuery is loaded via https from Google’s CDN. If you prefer not to use Google for whatever reason, change line 145 in liquid_tags/notebook.py
. The style of the Collapse/Expand header is defined starting at line 116 in the same file. An exception is the font style of this header, which is defined in the <span>
tags in lines 27 and 33 of liquid_tags/pelicanhtml.tpl
. The reason is that the code box would otherwise inherit the font properties. It might be cleaner to define the fonts for the header in the CSS and then fix them again the in the CSS for the input_area
. But this is supposed to be a quick hack and it works.