{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Customizing nbconvert"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Under the hood, nbconvert uses [Jinja templates](https://jinja2.readthedocs.io/en/latest/intro.html) to specify how the notebooks should be formatted. These templates can be fully customized, allowing you to use nbconvert to create notebooks in different formats with different styles as well.\n",
    "\n",
    "Out of the box, nbconvert can be used to convert notebooks to plain Python files. For example, the following command converts the `example.ipynb` notebook to Python and prints out the result:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "# coding: utf-8\n",
      "\n",
      "# # Example notebook\n",
      "\n",
      "# ### Markdown cells\n",
      "# \n",
      "# This is an example notebook that can be converted with `nbconvert` to different formats. This is an example of a markdown cell.\n",
      "\n",
      "# ### LaTeX Equations\n",
      "# \n",
      "# Here is an equation:\n",
      "# \n",
      "# $$\n",
      "# y = \\sin(x)\n",
      "# $$\n",
      "\n",
      "# ### Code cells\n",
      "\n",
      "# In[1]:\n",
      "\n",
      "print(\"This is a code cell that produces some output\")\n",
      "\n",
      "\n",
      "# ### Inline figures\n",
      "\n",
      "# In[2]:\n",
      "\n",
      "get_ipython().magic('matplotlib inline')\n",
      "\n",
      "import matplotlib.pyplot as plt\n",
      "import numpy as np\n",
      "\n",
      "x = np.linspace(0, 2 * np.pi, 100)\n",
      "y = np.sin(x)\n",
      "plt.plot(x, y)\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "[NbConvertApp] Converting notebook example.ipynb to python\n"
     ]
    }
   ],
   "source": [
    "!jupyter nbconvert --to python 'example.ipynb' --stdout"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "From the code, you can see that non-code cells are also exported.  As mentioned above, if you want to change this behavior, you can use a custom template.  The custom template inherits from the Python template and overwrites the markdown blocks so that they are empty. \n",
    "\n",
    "Below is an example of a custom template, which we write to a file called `simplepython.tpl`. This template removes markdown cells from the output, and also changes how the execution count numbers are formatted:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting simplepython.tpl\n"
     ]
    }
   ],
   "source": [
    "%%writefile simplepython.tpl\n",
    "\n",
    "{% extends 'python.tpl'%}\n",
    "\n",
    "## remove markdown cells\n",
    "{% block markdowncell -%}\n",
    "{% endblock markdowncell %}\n",
    "\n",
    "## change the appearance of execution count\n",
    "{% block in_prompt %}\n",
    "# This was input cell with execution count: {{ cell.execution_count if cell.execution_count else ' ' }}\n",
    "{%- endblock in_prompt %}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Using this template, we see that the resulting Python code does not contain anything that was previously in a markdown cell, and has special comments regarding the execution counts:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "# coding: utf-8\n",
      "\n",
      "# This was input cell with execution count: 1\n",
      "print(\"This is a code cell that produces some output\")\n",
      "\n",
      "\n",
      "# This was input cell with execution count: 2\n",
      "get_ipython().magic('matplotlib inline')\n",
      "\n",
      "import matplotlib.pyplot as plt\n",
      "import numpy as np\n",
      "\n",
      "x = np.linspace(0, 2 * np.pi, 100)\n",
      "y = np.sin(x)\n",
      "plt.plot(x, y)\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "[NbConvertApp] Converting notebook example.ipynb to python\n"
     ]
    }
   ],
   "source": [
    "!jupyter nbconvert --to python 'example.ipynb' --stdout --template=simplepython.tpl"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Template structure\n",
    "\n",
    "Nbconvert templates consist of a set of nested blocks. When defining a new\n",
    "template, you extend an existing template by overriding some of the blocks.\n",
    "\n",
    "All the templates shipped in nbconvert have the basic structure described here,\n",
    "though some may define additional blocks."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<!--\n",
       "This is an HTML fragment that gets included into a notebook & rst document\n",
       "-->\n",
       "<style type=\"text/css\">\n",
       "/* Overrides of notebook CSS for static HTML export */\n",
       ".jp-tpl-structure {\n",
       "    font-family: sans;\n",
       "}\n",
       "\n",
       ".template_block {\n",
       "    background-color: hsla(120, 60%, 70%, 0.2);\n",
       "    margin: 10px;\n",
       "    padding: 5px;\n",
       "    border: 1px solid hsla(120, 60%, 70%, 0.5);\n",
       "    border-left: 2px solid black;\n",
       "}\n",
       "\n",
       ".template_block pre {\n",
       "    background: transparent;\n",
       "    padding: 0;\n",
       "}\n",
       "\n",
       ".big_vertical_ellipsis {\n",
       "    font-size: 24pt;\n",
       "}\n",
       "\n",
       "</style>\n",
       "\n",
       "<div class='jp-tpl-structure'>\n",
       "<h3>Main page</h3>\n",
       "<div class=\"template_block\">header</div>\n",
       "\n",
       "<div class=\"template_block\">body\n",
       "    <div class=\"template_block\">any_cell\n",
       "        <div class=\"template_block\">codecell\n",
       "            <div class=\"template_block\">input_group\n",
       "                <div class=\"template_block\">in_prompt</div>\n",
       "                <div class=\"template_block\">input</div>\n",
       "            </div>\n",
       "            <div class=\"template_block\">output_group\n",
       "                <div class=\"template_block\">output_prompt</div>\n",
       "                <div class=\"template_block\">outputs (see below)</div>\n",
       "            </div>\n",
       "        </div>\n",
       "    </div>\n",
       "    <div class=\"template_block\">any_cell\n",
       "        <div class=\"template_block\">markdowncell</div>\n",
       "    </div>\n",
       "    <div class=\"template_block\">any_cell\n",
       "        <div class=\"template_block\">rawcell</div>\n",
       "    </div>\n",
       "    <div class=\"template_block\">any_cell\n",
       "        <div class=\"template_block\">unknowncell</div>\n",
       "    </div>\n",
       "    <div class=\"big_vertical_ellipsis\">&#8942;</div>\n",
       "</div>\n",
       "\n",
       "<div class=\"template_block\">footer</div>\n",
       "\n",
       "<h3>Outputs</h3>\n",
       "\n",
       "<div class=\"template_block\">outputs\n",
       "    <div class=\"template_block\">output\n",
       "        <div class=\"template_block\">execute_result</div>\n",
       "    </div>\n",
       "    <div class=\"template_block\">output\n",
       "        <div class=\"template_block\">stream_stdout</div>\n",
       "    </div>\n",
       "    <div class=\"template_block\">output\n",
       "        <div class=\"template_block\">stream_stderr</div>\n",
       "    </div>\n",
       "    <div class=\"template_block\">output\n",
       "        <div class=\"template_block\">display_data\n",
       "            <div class=\"template_block\">data_priority\n",
       "                <div class=\"template_block\">data_pdf / data_svg / data_png /\n",
       "                    data_html / data_markdown / data_jpg / data_text /\n",
       "                    data_latex / data_javascript / data_other\n",
       "                </div>\n",
       "            </div>\n",
       "        </div>\n",
       "    </div>\n",
       "    <div class=\"template_block\">output\n",
       "        <div class=\"template_block\">error\n",
       "            <div class=\"template_block\">traceback_line</div>\n",
       "            <div class=\"big_vertical_ellipsis\">&#8942;</div>\n",
       "        </div>\n",
       "    </div>\n",
       "    <div class=\"big_vertical_ellipsis\">&#8942;</div>\n",
       "</div>\n",
       "\n",
       "<h3>Extra HTML blocks</h3>\n",
       "    <h4><pre>basic.tpl</pre></h4>\n",
       "        <div class=\"template_block\">output\n",
       "            <div class=\"template_block\">output_area_prompt</div>\n",
       "            <div class=\"template_block\">output (as above)</div>\n",
       "        </div>\n",
       "    <h4><pre>full.tpl</pre></h4>\n",
       "        <div class=\"template_block\">header\n",
       "            <pre>&lt;head&gt;</pre>\n",
       "            <div class=\"template_block\">html_head</div>\n",
       "            <pre>&lt;/head&gt;</pre>\n",
       "        </div>\n",
       "\n",
       "<h3>Extra Latex blocks</h3>\n",
       "<div class=\"template_block\">header\n",
       "    <div class=\"template_block\">docclass</div>\n",
       "    <div class=\"template_block\">packages</div>\n",
       "    <div class=\"template_block\">definitions\n",
       "        <div class=\"template_block\">title</div>\n",
       "        <div class=\"template_block\">date</div>\n",
       "        <div class=\"template_block\">author</div>\n",
       "    </div>\n",
       "    <div class=\"template_block\">commands\n",
       "        <div class=\"template_block\">margins</div>\n",
       "    </div>\n",
       "</div>\n",
       "<div class=\"template_block\">body\n",
       "    <div class=\"template_block\">predoc\n",
       "        <div class=\"template_block\">maketitle</div>\n",
       "        <div class=\"template_block\">abstract</div>\n",
       "    </div>\n",
       "    ... other fields as above ...\n",
       "    <div class=\"template_block\">postdoc\n",
       "        <div class=\"template_block\">bibliography</div>\n",
       "    </div>\n",
       "</div>\n",
       "</div>\n",
       "\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from IPython.display import HTML, display\n",
    "with open('template_structure.html') as f:\n",
    "    display(HTML(f.read()))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### A few gotchas\n",
    "\n",
    "Jinja blocks use `{% %}` by default which does not play nicely with LaTeX, so those are replaced by `((* *))` in LaTeX templates."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Templates that use cell metadata\n",
    "\n",
    "The notebook file format supports attaching arbitrary JSON metadata to each cell. \n",
    "Here, as an exercise, you will use the metadata to tag cells.\n",
    "\n",
    "First you need to choose another notebook you want to convert to html, and tag some of the cells with metadata. \n",
    "You can refer to the file `soln/celldiff.js` as an example or follow the Javascript tutorial to figure out how\n",
    "do change cell metadata.  Assuming you have a notebook with some of the cells tagged as `'Easy'`, `'Medium'`,\n",
    "`'Hard'`, or `<None>`, the notebook can be converted specially using a custom template.\n",
    "Design your template in the cells provided below.\n",
    "\n",
    "Hint: if your tags are located at `cell.metadata.example.difficulty`, the following Python code would get\n",
    "the value of the tag: \n",
    "\n",
    "```python\n",
    "cell['metadata'].get('example', {}).get('difficulty', '')\n",
    "```\n",
    "\n",
    "The following lines of code may be a helpful starting point:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting mytemplate.tpl\n"
     ]
    }
   ],
   "source": [
    "%%writefile mytemplate.tpl\n",
    "\n",
    "{% extends 'full.tpl'%}\n",
    "{% block any_cell %}\n",
    "    <div style=\"border:thin solid red\">\n",
    "        {{ super() }}\n",
    "    </div>\n",
    "{% endblock any_cell %}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "Once you have tagged the cells appropriately and written your template using the cell above, try converting your notebook using the following command:\n",
    "\n",
    "```bash\n",
    "jupyter nbconvert --to html <your notebook.ipynb> --template=mytemplate.tpl\n",
    "```"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
