Emulating IPython Notebooks in WordPress: Part 2

Input and Output

This is my second post about setting my WordPress blog to emulate an IPython notebook interface. In this post, I’ll talk about duplicating the Input/Output box style in the IPython notebook. My first post discussed source code highlighters, child themes, Pandas DataFrames, Matplotlib Figures, and MathJax support.

Output Box

I wanted to have a nice box that wraps all of the output from any of the code presented in the examples. This was fairly easy to accomplish by wrapping output in a division with the class “pyout”, i.e. <div class=”pyout”>…</div>. Then, I updated my CSS file to include the following:

This makes a nice dotted border around all of the code output.

Output Text

Next, to precede all output boxes with the text “Output:” is a little trickier. I could have added this text to every “pyout” division, but that would have been tedious and error prone. Fortunately, jQuery has a wrap function that wraps a given element in another set of tags. In this way, I could wrap all of my “pyout” boxes with another division containing the “Output:” text.

First of all, I wrote a custom JS script that wraps the “pyout” division. In my child theme folder, I created a file called “wrapper.js” that included the following code:

All “pyout” boxes are now surrounded by another division classed as “pyoutwrap”. Modifying my theme’s CSS file as below makes the “Output:” text bold and slightly larger than the actual code output.

Making these changes has no immediate effect, though, because you need to register this JS script with WordPress for it to be activated. This is accomplished by adding a couple of lines to “functions.php”, which is shown below in its entirety.

Much of this code was covered in the section on child themes from my previous post; however, notice that a new function wp_enqueue_script incorporates my new JS file into my site. A couple of the arguments to this function are very important, so they will all be described here. The first argument is simply the name with which I would like to register this script with WordPress. The second argument is the file location, making sure this is the full path by prefixing get_stylesheet_directory_uri(). The array argument ensures that jQuery is loaded before this script, otherwise things won’t work correctly. The string is just a version number, which is unnecessary, so I just put in a placeholder of ‘1.0’. The final argument, true, is critical. It puts this script at the end of the HTML, just before the closing </body> tag. In this way, the function is executed after the entire page is loaded. Otherwise, the script is loaded into the HTML head and is executed before the body, including my “pyout” box, is loaded.

Input Text

I followed a very similar procedure to add “Input:” before all of my code samples. Again, I used jQuery’s wrap function on all “crayon-syntax” classes. Below is the additional function call in “wrapper.js” and some new styling in “style.css”, respectively. I also changed Crayon’s “Top Margin” to “0px”, which can be done through Crayon’s Settings page.

Although this method works just fine, it wraps every Crayon code instance with the “pyinwrap”. That means that even non-Python code blocks will be prefaced with “Input:”. For now, this is going to be the best solution until I can figure out how to add Python-specific wrappers.

In Action

Now that everything is set, all of my Python input and output has a similar appearance to an IPython notebook session. (Not perfect, but close enough.)

Hello World!

Emulating IPython Notebooks in WordPress

I purchased this website many years ago with the intention of starting my own blog. At the time, I was teaching myself Python, and I thought it wouldn’t be that hard to write my own custom website using CGI and MySQL. Please don’t ever do this! Although I learned quite a bit about web servers, HTML, CSS, and SQL databases, it was way too much work, and my blog never took off.

Fast forward to 2015. After receiving yet another auto-payment notification for my unused website, I decide the time has finally come to make use of it. Fortunately, my hosting provider has an auto-install option for a WordPress blog. WordPress is popular. It’s apparently easy to use… Let’s give this a try.

One thing I’d like to write about is Python programming for data analysis with included examples. I’m a heavy user of IPython notebooks for data analysis, so I’d like to be able to incorporate some of the notebook display features into my blog. Unfortunately, a web search for some ideas on uploading notebooks to WordPress was surprisingly unhelpful given WordPress’s popularity.

IPython provides a tool, nbconvert, which can convert notebook files directly to HTML. This is great because you can easily send a webpage of an analysis to a colleague, for example. It is also the basis of the NBViewer website. This might make a good starting point; however, one of my biggest problems with the IPython notebook is that markdown cells are not spell-checked. My spelling skills are atrocious, so my notebooks are always rife with errors. Knowing this, I was reluctant to upload notebooks directly and decided to pursue other options.

Ultimately, I found a bunch of plugins and hacks that gave me much of the display functionality for emulating the look and feel of the IPython notebook. My adventures are documented below in case others might find this useful.

Code Highlighting

This was the easiest part of the whole process. There are many syntax highlighters available as WordPress plugins. I took a quick look at a couple of “Top ### Code Highlighting” pages for inspiration, but it seemed like all the highlight plugins are fairly similar. I finally chose Crayon, not for any particular reason, except that it was pretty high up on many of the top lists. The default display properties were not optimal for my taste, so I modified several options through the “Settings” link under Crayon on the Plugins admin page. The changes are as follows: 1) Display the Toolbar to “Never”, 2) Enable plain code view and display to “Disable Mouse Events”, 3) and Language Fallback to “Python”.

Now, my “Add Post” editor contains a Crayon button, which opens a source code import window, from which I can also alter any of the numerous global display options. To add some code from a notebook, simply copy-and-paste it into the Crayon source code window. Once inserted, the source code is wrapped in the appropriate pre tags. For example, the following highlighted Python code

Appears as this in the Text editor window after insertion with Crayon:

<pre class="lang:python decode:true " >print('hello')</pre>

Creating a Child Theme

After some experimentation, I realized that I was going to need to modify my site theme with some custom CSS, at the minimum. I read up on this topic on the web, and most people recommend that you create a Child Theme when doing any customization. A child theme is essentially an overlay on top of another base (Parent) theme. There are a couple of advantages here. First, if the underlying theme is updated, you won’t lose your customizations. In addition, the child overlay is a fairly minimal set of files, so you could transfer your changes to a new theme with very little effort. The WordPress documentation on Child Themes is a pretty decent place to find step-by-step information.

As of this writing, this site is using the default “twentyfifteen” theme. In my themes folder, wp-content/themes, I created a new theme folder called twentyfifteen-child that contains two files: style.css and functions.php.

The functions.php file simply contains a function theme_enqueue_styles that loads the main style sheet from the underlying parent theme. My file is shown below:

The style.css file is simply your custom style sheet that must contain a comment header with a tag Template that names the underlying parent theme. I simply copied the parent theme style.css file and added the “Template” line. My file is shown below:

Then I simply changed to the “twentyfifteen-child” theme from the WordPress theme manager.

Pandas DataFrame Tables

Pandas is a powerful data analysis library for Python. Among other things, Pandas provides a tabular data structure called DataFrame, which is very similar to the equivalently named structure in R. In IPython’s notebook and Qt Console interface, Pandas DataFrames are printed as nice HTML tables. For example, below is a chunk of code and the IPython output.

one two 0 b
0 5 1 A D
1 8 9 B A
2 9 3 C E

Emulating this was a little tricky. As a first step, convert your notebook to HTML:

$ ipython nbconvert test_notebook.ipynb

Open the resulting HTML file in a text editor. There is a ton of boilerplate junk here, but you can easily find the table by searching for “<table”. Copy all of the text up to and including the closing </table> tag, and paste this into the Text Post editor. This won’t work in the Visual editor, which does some conversions behind the scenes. Make sure the table class is set to “dataframe”. Wrap the table in a div with the class name “dftable”. Here is the raw HTML for the above table:

Next, I modified the CSS file of my Child Theme (style.css) to alter the default appearance of this class of table and the surrounding div.

Perhaps not the most elegant solution, but it does the trick.

Matplotlib Figures

IPython can display Matplotlib figures inline with the rest of the code and output. On export to HTML, the image is embedded into the raw HTML in base64 encoded text. Again, this is great when sharing the HTML files with collaborators, because everything is contained in one file. However, WordPress doesn’t handle this elegantly. In this case, using Matplotlib’s savefig command will create a hard copy version of the figure in addition to inlining it in the notebook. For example, the following set of commands will produce a very simple plot in a notebook along with a PNG of the same figure called “testing.png”:

testing

To emulate an IPython notebook with the inline set, I’ll probably just drop the savefig calls when transferring the code into my post. Then I can simply use the “Add Media” button in my post editor to upload and include the figure. An advantage of this procedure is that the figures are given their own URL, which people can reference in the future.

MathJax

Again, there are a bunch of MathJax plugins available for WordPress. I chose “Simple MathJax” because it sounded… simple. And it seemed to best emulate the way MathJax behaves in IPython notebook markdown cells. Once installed and enabled, I can can add inline MathJax by using a single \$ sign. For example, \$\frac{1}{2}\$ will be rendered as $\frac{1}{2}$. Block equations can be included with the double dollar sign \$\$, such that \$\$\alpha^{2}\$\$ is rendered as $$\alpha^{2}$$

EDIT: This following paragraph is no longer necessary. I filed a PR with these changes to this plugin. It has been merged into master. I’ll leave this here for reference, though.

One issue is that the escaping the dollar sign is not supported by default. In order to set this, go to the Plugins page and select “Edit” under Simple MathJax. This opens a text editor for modifying this plugin. Search for the following line:

Add processEscapes: true to the end of this line as such:

Now your should be able to add dollar signs to your post by preceding them with \, such as \$.

Final Thoughts

That covers most things that I want to do for the time being. However, I’ll probably come back to this topic again once I get frustrated with some other odd behavior of my site. I hope others find this useful. Leave me a comment if you want me to add/clarify anything.

Follow-up

I wrote a second post that shows how to add “Input:”/”Output:” text before all code boxes.