Here’s a quick (and hopefully helpful) post for those wishing to blog in
Jekyll using Jupyter notebooks. As some of you may know, nbconvert
can
easily convert your .ipynb
files to markdown, which Jekyll can easily
turn into blog posts for you.
nbconvert --to markdown myfile.ipynb
However, an annoying part of this is that Markdown doesn’t include classes for input and outputs, which means they each get treated the same in the output. Not ideal.
Fortunately, you can customize nbconvert extensively. First, it’s possible to create your own exporter class, but this is a bit heavy for what we want to do. In our case, we’d simply like to extend the markdown exporter so that it outputs Jekyll-friendly markdown.
Extending nbconvert's
markdown template¶
Because nbconvert
uses Liquid Templates for its exporters, this is
relatively easy! For example,
here is nbconvert
’s markdown template.
You can see how it extends another template, then adds some modifications of
its own. What we need to do is create a new template that slightly modifies
the functionality of nbconvert
’s markdown template. Then we can use the same
markdown exporter, but with our custom template defining how the markdown is
created.
To treat input and output text differently, we’ll extend nbconvert
’s base
markdown template by creating a template file of our own. Simply write the
following lines into a file called mytemplate.tpl
.
{% highlight html %} {% raw %} {% extends ‘markdown.tpl’ %}
{% block input %}
{% endblock input %}
{% block stream %} {:.output_stream}
{{ output.text }}
{% endblock stream %}
{% block data_text %} {:.output_data_text}
{{ output.data['text/plain'] }}
{% endblock data_text %}
{% block traceback_line %} {:.output_traceback_line}
{{ line | strip_ansi }}
{% endblock traceback_line %}
{% block data_html %}
{% endblock data_html %} {% endraw %} {% endhighlight %}
Above, we’re doing two things:
- Overriding the input area block so that it is now wrapped in
<div>
tags. Note that we can set a custom class, and setmarkdown="1"
so that the markdown conversion occurs within the div. - Overriding various output text blocks so that we remove the indentation
that was used to denote a “code” cell. Instead, we’ll wrap the output text
in more common
```
characters, and use a trick to add a class to code blocks:{:.class_name}
syntax.
We can then directly reference this template when we call nbconvert
:
nbconvert --to markdown --template path/to/mytemplate.tpl myfile.ipynb
As a result, we now have classes around each of these divs that we can style however we like. For example, here are the CSS rules I added to remove the theme’s “code box” around each of the output areas:
.input_area div.highlighter-rouge {
background-color: #f7f7f7 !important;
}
.output_stream, .output_data_text, .output_traceback_line {
margin-left: 2% !important;
border: none !important;
border-radius: 4px !important;
background-color: #fafafa !important;
box-shadow: none !important;
}
.output_stream:before, .output_data_text:before, .output_traceback_line:before{
content: none !important;
}
It took me a while to figure out this pattern, so hopefully other people find it useful as well!