Write notebook extensions

Note: This document is a draft.

TODO: this document doesn't (and won't) contain code... Thus it has no reason to be a notebook and should be converted to a regular RST document.

This document contains generic notes describing how to personalize and extend Jupyter notebooks. It doesn't contain instructions for writing/installing a specific extension.

My wish-list/todolist of extensions is there.

How can the notebook be extended?

Extensions

The Jupyter's frontend (Notebook client) and backend (server application) are both customizable.

Their behavior can be extended by creating, respectively:

  • nbextension: a frontend extension written in Javascript, CSS, ...
    • a Javascript AMD module that exports a function load_ipython_extension
  • server extension: a backend extension written in Python
    • a Python module that implements load_jupyter_server_extension
  • bundler extension: a backend extension written in Python
    • a Python module that implements bundle

To display the list of installed extensions:

jupyter nbextension list jupyter serverextension list jupyter bundlerextension list

Source

Templates (does it only concern nbconvert ?)

TODO: WHAT ABOUT:

TODO: for nbconvert, see also:

Themes

TODO: WHAT ABOUT:

Configuration files

TODO Frontend configuration file: ~/.jupyter/jupyter_notebook_config.py

This file is generated with the following command:

jupyter notebook --generate-config

See http://stackoverflow.com/questions/32071672/where-should-i-place-my-settings-and-profiles-for-use-with-ipython-jupyter-4-0

It seems there are one configuration file for the frontend part (see the previous link) and another one for the backend part. TODO: mention both...

TODO there is also a configuration file for nbconvert: ~/.jupyter/jupyter_nbconvert_config.py

See https://jupyter.readthedocs.io/en/latest/migrating.html#finding-the-location-of-important-files

Frontend extensions

Embeded Javascript in cells

Note: This is not an actual extension, just an useful trick.

This is the simplest solution as there is nothing to install or configure. HTML/Javascript code is directly written in documents cells.

This is can be satisfactory for small "one-time" functionalities, but this is clearly not convenient in most cases.

This hack has an advantage: the "extension" is contained within the document and follow it everywhere without additional installation on execution platforms.

Example

%%html

In [1]:
%%javascript
var toc = document.getElementById("toc");
toc.innerHTML = "Table of contents:";
toc.innerHTML += "<ol>"

var h2_list = document.getElementsByTagName("h2");
for (var i = 0; i < h2_list.length; i++) {
    var h2 = h2_list[i];
    var h2_str = h2.textContent.slice(0, -1);  // "slice(0, -1)" remove the last character 
    toc.innerHTML += "<li><a href=\"#" + h2_str.replace(/\s+/g, '-') + "\">" + h2_str + "</a></li>";
}

toc.innerHTML += "</ol>"

Configuring the notebook frontend

Note: This is not an actual extension but it can be useful.

Notebook frontend and its underlying libraries can be configured through Javascript statements. Those statements can be ... persistent ...

For instance, Jupyter use Codemirror (https://codemirror.net) to edit notebooks cells. This library can be configured ...

Codemirror's options list is there: https://codemirror.net/doc/manual.html#commands.

See http://jupyter-notebook.readthedocs.io/en/latest/frontend_config.html

Nbextensions

Lets write a tiny nbextension.

Create a hello directory wherever you want in your file system and write the following file in hello/main.js:

define([
        'base/js/namespace',
        'base/js/events'
        ],
        function(Jupyter, events) {
            var load_ipython_extension = function () {
                alert("Hello, world!");
            };

            return {
                load_ipython_extension : load_ipython_extension
            };
        });

Write the following file in hello/hello.yaml:

Type: IPython Notebook Extension
Name: Hello
Link: README.md
Description: This is an minimal nbextension example.
Main: main.js
Compatibility: 4.x

Then install it with the following command:

jupyter nbextension install hello --user

On my system, it copy files in ~/Library/Jupyter/nbextensions/.

To be usable, the extension have to be activated with the following command:

jupyter nbextension enable hello/main --user

On my system, it update the following file: ~/.jupyter/nbconfig/notebook.json.

Et voilà! Now you can open or reload a notebook.

You can also check its installation with:

jupyter nbextension list --user

To remove this extension, first disable it:

jupyter nbextension disable hello/main --user

then uninstall it:

jupyter nbextension uninstall hello --user

Packages

"Since it is rare to have a server extension that does not have any frontend components (an nbextension), for convenience and consistency, all these client and server extensions with their assets can be packaged and versioned together as a Python package with a few simple commands. This makes installing the package of extensions easier and less error-prone for the user."

Source

TODO

  • First, get a clear view of all possible extension mechanisms in notebook (python extensions, embedded JS, html export, templates, magics, themes, ...) and make snippets for each

Useful links

Extension examples

Zoom on a very useful extension example: TOC (table of contents)