1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
|
Creating Custom Templates for nbconvert
=======================================
Selecting a template
--------------------
Most exporters in nbconvert are subclasses of ``TemplateExporter``, and make use of
jinja to render notebooks into the destination format.
Alternative nbconvert templates can be selected by name from the command line with the
``--template`` option. For example, to use the ``reveal`` template with the HTML exporter,
one can type.
.. sourcecode:: bash
jupyter nbconvert <path-to-notebook> --to html --template reveal
Where are nbconvert templates installed?
----------------------------------------
Nbconvert templates are *directories* containing resources for nbconvert template
exporters such as jinja templates and associated assets. They are installed in the
**data directory** of nbconvert, namely ``<installation prefix>/share/jupyter/nbconvert``.
Nbconvert includes several templates already.
For example, three HTML templates are provided in nbconvert core for the HTML exporter:
- ``lab`` (The default HTML template, which produces the same DOM structure as JupyterLab)
- ``classic`` (The HTML template styled after the classic notebook)
- ``reveal`` (For producing slideshows).
.. note::
Running ``jupyter --paths`` will show all Jupyter directories and search paths.
For example, on Linux, ``jupyter --paths`` returns:
.. code::
$ jupyter --paths
config:
/home/<username>/.jupyter
/<sys-prefix>/etc/jupyter
/usr/local/etc/jupyter
/etc/jupyter
data:
/home/<username>/.local/share/jupyter
/<sys-prefix>/share/jupyter
/usr/local/share/jupyter
/usr/share/jupyter
runtime:
/home/<username>/.local/share/jupyter/runtime
Adding Additional Template Paths
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In order to add additional paths to be searched, you need to pass ``TemplateExporter.extra_template_basedirs``
config options indicating the extra directories to search for templates. Be careful not to override
``TemplateExporter.template_paths`` unless you intend to replace ALL paths and don't want the default
locations included.
When using the commandline the extra template paths are added by calling
``--TemplateExporter.extra_template_basedirs=path/you/want/included``.
The content of nbconvert templates
----------------------------------
conf.json
~~~~~~~~~
Nbconvert templates all include a ``conf.json`` file at the root of the directory,
which is used to indicate
- the base template that it is inheriting from.
- the mimetypes of the template.
- preprocessors classes to register in the exporter when using that template.
Inspecting the configuration of the reveal template we see that it inherits from the lab
template, exports text/html, and enables two preprocessors called "100-pygments" and "500-reveal".
.. code::
{
"base_template": "lab",
"mimetypes": {
"text/html": true
},
"preprocessors": {
"100-pygments": {
"type": "nbconvert.preprocessors.CSSHTMLHeaderPreprocessor",
"enabled": true
},
"500-reveal": {
"type": "nbconvert.exporters.slides._RevealMetadataPreprocessor",
"enabled": true
}
}
}
Inheritance
~~~~~~~~~~~
Nbconvert walks up the inheritance structure determined by ``conf.json`` and produces an aggregated
configuration, merging the dictionaries of registered preprocessors.
The lexical ordering of the preprocessors by name determines the order in which they will be run.
Besides the ``conf.json`` file, nbconvert templates most typically include jinja templates files,
although any other resource from the base template can be overridden in the derived template.
For example, inspecting the content of the ``classic`` template located in
``share/jupyter/nbconvert/templates/classic``, we find the following content:
.. code::
share/jupyter/nbconvert/templates/classic
├── static
│ └── styles.css
├── conf.json
├── index.html.j2
└── base.html.j2
The ``classic`` template exporter includes a ``index.html.j2`` jinja template (which is the main entry point
for HTML exporters) as well as CSS and a base template file in ``base.html.j2``.
.. note::
A template inheriting from ``classic`` would specify ``"base_template": "classic"`` and could
override any of these files. For example, one could make a "classiker" template merely providing
an alternative ``styles.css`` file.
Inheritance in Jinja
~~~~~~~~~~~~~~~~~~~~
In nbconvert, jinja templates can inherit from any other jinja template available in its current directory
or base template directory by name. Jinja templates of other directories can be addressed by their relative path
from the Jupyter data directory.
For example, in the reveal template, ``index.html.j2`` extends ``base.html.j2`` which is in the same directory, and
``base.html.j2`` extends ``lab/base.html.j2``. This approach allows using content that is available in other templates
or may be overridden in the current template.
A practical example
~~~~~~~~~~~~~~~~~~~
Say you would like to modify the existing Markdown template to wrap each
output statement in a fenced code block:
.. code::
```output
(1, 2, 3)
```
Start by creating a new template directory, say ``mdoutput``. In it,
you have the following files::
conf.json
index.md.j2
The configuration file, ``conf.json`` states that your template
applies to markdown files::
{
"mimetypes": {
"text/markdown": true
}
}
The ``index.md.j2`` template entrypoint extends the existing markdown
template, and redefines how output blocks are rendered:
.. code::
{% extends 'markdown/index.md.j2' %}
{%- block traceback_line -%}
```output
{{ line.rstrip() | strip_ansi }}
```
{%- endblock traceback_line -%}
{%- block stream -%}
```output
{{ output.text.rstrip() }}
```
{%- endblock stream -%}
{%- block data_text scoped -%}
```output
{{ output.data['text/plain'].rstrip() }}
```
{%- endblock data_text -%}
You can now convert your notebook to markdown using the new template::
jupyter nbconvert --execute notebook.ipynb --to markdown --template=mdoutput
(If you put your template folder in a different location than your
notebook, remember to add
``--TemplateExporter.extra_template_basedirs=path/to/template/parent``.)
To further explore the possibilities of templating, take a look at the
root of all templates: ``null.j2``. You can find it in the
``./nbconvert/templates/base`` subfolder of one of the data paths given
by ``jupyter --paths``.
|