diff --git a/doc/conf.py b/doc/conf.py index ea519832..3078781a 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -24,6 +24,9 @@ # If True, the build process is continued even if an exception occurs: #nbsphinx_allow_errors = True +# If True, this enables wrapping of markdown cells in sphinx-directives: +#nbsphinx_allow_directives = True + # Controls when a cell will time out (defaults to 30; use -1 for no timeout): #nbsphinx_timeout = 60 diff --git a/doc/markdown-cells.ipynb b/doc/markdown-cells.ipynb index 2a448fb4..0992f9bd 100644 --- a/doc/markdown-cells.ipynb +++ b/doc/markdown-cells.ipynb @@ -172,6 +172,59 @@ "The linked files are automatically copied to the HTML output directory.\n", "For LaTeX output, no link is created." ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Encapsulate Cell in Sphinx Directive" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "nbsphinx-directive": true + }, + "source": [ + "Important\n", + "---------\n", + "This facilitates the use of Sphinx Directives, like admonitions (eg. ``.. important:: ``), with processed markdown inside. \n", + "\n", + "The first line of the cell must contain the admonition type. It also has to be underlined with `-` to be processed correctly and to give similar look within the notebook.\n", + "\n", + "Also the above mentioned markdown like:\n", + "\n", + "- Equations: $\\text{e}^{i\\pi} = -1$, \n", + "- Links: [link to somewhere](#Links-to-Other-Notebooks) or \n", + "- *emphasis*, **boldface** and `preformatted text` \n", + "\n", + "can be used within this cell. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note\n", + "----\n", + "To use this behaviour there exist three possibilities:\n", + "\n", + "- add this metadata switch to the cells metadata to enable for the single cell\n", + " ```python3\n", + " {\n", + " \"nbsphinx-directive\": true\n", + " }\n", + " ```\n", + "- add this metadata switch to the notebooks metadata to enable notebook wide:\n", + " ```python3\n", + " {\n", + " \"nbsphinx\": {\n", + " \"allow_directives\": true\n", + " },\n", + " }\n", + " ```\n", + "- add `nbsphinx_allow_directives = True` in `conf.py` to enable doc-wide" + ] } ], "metadata": { @@ -191,6 +244,9 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.1+" + }, + "nbsphinx": { + "allow_directives": true } }, "nbformat": 4, diff --git a/nbsphinx.py b/nbsphinx.py index 7c3aee4e..b72c4bb6 100644 --- a/nbsphinx.py +++ b/nbsphinx.py @@ -162,8 +162,12 @@ {%- if 'nbsphinx-toctree' in cell.metadata %} {{ cell | extract_toctree }} {%- else %} +{%- if nb.metadata.nbsphinx.allow_directives or 'nbsphinx-directive' in cell.metadata %} +{{ cell | wrap_cell}} +{%- else %} {{ super() }} -{% endif %} +{%- endif %} +{%- endif %} {% endblock markdowncell %} @@ -363,9 +367,11 @@ class Exporter(nbconvert.RSTExporter): """ - def __init__(self, allow_errors=False, timeout=30, codecell_lexer='none'): + def __init__(self, allow_errors=False, allow_directives=False, + timeout=30, codecell_lexer='none'): """Initialize the Exporter.""" self._allow_errors = allow_errors + self._allow_directives = allow_directives self._timeout = timeout self._codecell_lexer = codecell_lexer loader = jinja2.DictLoader({'nbsphinx-rst.tpl': RST_TEMPLATE}) @@ -375,6 +381,7 @@ def __init__(self, allow_errors=False, timeout=30, codecell_lexer='none'): 'markdown2rst': markdown2rst, 'get_empty_lines': _get_empty_lines, 'extract_toctree': _extract_toctree, + 'wrap_cell': _wrap_cell, }) def from_notebook_node(self, nb, resources=None, **kw): @@ -398,6 +405,14 @@ def from_notebook_node(self, nb, resources=None, **kw): allow_errors=allow_errors, timeout=timeout) nb, resources = pp.preprocess(nb, resources) + # check allow directive + if self._allow_directives: + allow_directives = self._allow_directives + else: + allow_directives = nbsphinx_metadata.get('allow_directives', False) + nbsphinx_metadata['allow_directives'] = allow_directives + nb.metadata['nbsphinx'] = nbsphinx_metadata + # Call into RSTExporter rststr, resources = super(Exporter, self).from_notebook_node( nb, resources, **kw) @@ -441,6 +456,7 @@ def parse(self, inputstring, document): resources['unique_key'] = env.docname.replace('/', '_') exporter = Exporter(allow_errors=env.config.nbsphinx_allow_errors, + allow_directives=env.config.nbsphinx_allow_directives, timeout=env.config.nbsphinx_timeout, codecell_lexer=env.config.nbsphinx_codecell_lexer) @@ -667,6 +683,22 @@ def _extract_toctree(cell): return '\n '.join(lines) +def _wrap_cell(cell): + """Wrap cell content from Markdown cell in sphinx directive.""" + text = cell.source.split('\n', 2) + + # wrap only if at least 3 lines exist + # and if first line corresponds to second line + if (len(text) > 2) and (text[1] == ('-' * len(text[0]))): + text = "".join([".. ", text[0].lower(), ":: \n\n ", + markdown2rst(text[2]) + .replace("\n", '\n '), "\n"]) + else: + text = markdown2rst(cell.source) + + return text + + def _get_empty_lines(text): """Get number of empty lines before and after code.""" before = len(text) - len(text.lstrip('\n')) @@ -931,6 +963,7 @@ def setup(app): _add_notebook_parser(app) app.add_config_value('nbsphinx_allow_errors', False, rebuild='') + app.add_config_value('nbsphinx_allow_directives', False, rebuild='') app.add_config_value('nbsphinx_timeout', 30, rebuild='') app.add_config_value('nbsphinx_codecell_lexer', 'none', rebuild='env')