Skip to content

Commit

Permalink
Allow optional setting of tags + add hide-X commands + code-prompt-sh…
Browse files Browse the repository at this point in the history
…ow/hide (#13)

* Allow optional setting of tags
* Add `hide-X` commands even though they are missing from the official documentation table
* Add `code-prompt-show/hide` values even though they aren't really useful for the classic purpose
* Fix upper bound because of pandas-stubs limit...
  • Loading branch information
kai-tub committed Oct 18, 2022
1 parent b048c67 commit e1ff311
Show file tree
Hide file tree
Showing 7 changed files with 1,117 additions and 759 deletions.
4 changes: 3 additions & 1 deletion common_nb_preprocessors/_constant_builder.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
try:
# TODO: check set html5lib as dependency
import bs4 # type: ignore
import html5lib # type: ignore
import lxml # type: ignore
import pandas
except ImportError:
raise ImportError(
"""\
This module is only used during development and requires
pandas + the `read_html` dependencies (bs4 and html5lib).
pandas + the `read_html` dependencies (bs4, html5lib, and lxml).
"""
)

Expand Down
84 changes: 54 additions & 30 deletions common_nb_preprocessors/myst_nb.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from enum import Enum
from typing import List, Optional

import nbformat
from pydantic import validate_arguments

from .metadata_injector import (
MetaDataListInjectorPreprocessor,
Expand All @@ -19,6 +21,21 @@ class MystNBCellTags(str, Enum):
All different Myst-NB cell tag configuration options.
"""

hide_input = "hide-input"
"""
Hide the source code of the cell behind a collapsible button.
See :ref:`sec/hide-input` for a visual example.
"""
hide_output = "hide-output"
"""
Hide the output of the cell behind a collapsible button.
See :ref:`sec/hide-output` for a visual example.
"""
hide_cell = "hide-cell"
"""
Hide the input as well as the output of the cell behind a collapsible button.
See :ref:`sec/hide-cell` for a visual example.
"""
remove_input = "remove-input"
"""
Removes the source code of the cell.
Expand Down Expand Up @@ -69,7 +86,8 @@ def _validate(cls) -> None:
cell_tags = _myst_nb_cell_tags["Tag"].tolist()
_nbclient_cell_tags = _read_unique_myst_nb_table(match="skip-execution")
cell_tags.extend(_nbclient_cell_tags["Tag"].tolist())
if set(cell_tags) != set(cls):
# if some aren't documented yet, which has happened quite often
if set(cell_tags) - set(cls) != set():
raise RuntimeError(f"{cls} out-of-date!")


Expand Down Expand Up @@ -112,6 +130,28 @@ class MystNBCellConf(str, Enum):
See :ref:`sec/output_stderr` for a visual example.
"""
code_prompt_show = "code_prompt_show"
"""
Define the prompt *text* that is displayed next to the
*expand/show* dialog. The text is displayed to inform the user
that the dialog can be expanded.
The optional `{type}` placeholder will be replaced with:
`content`, `source`, or `outputs`, depending on the `hide` tag.
See :ref:`sec/code_prompt_show` for a visual example.
"""
code_prompt_hide = "code_prompt_hide"
"""
Define the prompt *text* that is displayed next to the
*hide* dialog. The text is displayed to inform the user
that the dialog can be *collapsed/minimized*.
The optional `{type}` placeholder will be replaced with:
`content`, `source`, or `outputs`, depending on the `hide` tag.
See :ref:`sec/code_prompt_hide` for a visual example.
"""

merge_streams = "merge_streams"
"""
Expand Down Expand Up @@ -186,35 +226,14 @@ def _validate(cls) -> None:
raise RuntimeError(f"{cls} out-of-date!")


# MYST_NB_CELL_CONF = [
# "merge_streams",
# "remove_code_source",
# "remove_code_outputs",
# "number_source_lines",
# "output_stderr",
# "text_lexer",
# "error_lexer",
# "image",
# "figure",
# "markdown_format",
# ]

# JUPYTER_BOOK_CODE_TAGS = [
# "full-width",
# "output_scroll",
# "margin",
# "hide-input",
# "hide-output",
# "hide-cell",
# "remove-input",
# "remove-output",
# "remove-cell",
# "raises-exception",
# ]


@validate_arguments()
def myst_nb_metadata_injector(
file_content: str, prefix: str = "#", remove_line: bool = True, delimiter: str = "="
file_content: str,
/,
prefix: str = "#",
remove_line: bool = True,
delimiter: str = "=",
extra_tags: Optional[List[str]] = None,
) -> nbformat.NotebookNode:
"""
The preprocessor will inject all the MyST-NB specific tags into the
Expand All @@ -225,16 +244,21 @@ def myst_nb_metadata_injector(
:param file_content: contents of an `ipynb` file
:param prefix: Comment symbol that precedes the keys. Defaults to `#`.
:param remove_line: Set if the metadata comment lines should be removed after injection. Defaults to `True`.
:param extra_tags: Additional custom `tags` list for further customization.
Internally it calls `MetaDataListInjectorPrepreprocessor` and
`MetaDataMapInjectorPreprocessor`.
Refer to those classes for more details.
"""
nb = nbformat.reads(file_content, as_version=4)
metadata_tags = set(s.value for s in MystNBCellTags)
if extra_tags is not None:
metadata_tags = metadata_tags | set(extra_tags)

# could be done in one preprocess step
nb, _ = MetaDataListInjectorPreprocessor(
metadata_group="tags",
strings=list(MystNBCellTags),
strings=list(metadata_tags),
prefix=prefix,
remove_line=remove_line,
).preprocess(nb, None)
Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
nb_custom_formats = {
".ipynb": [
"common_nb_preprocessors.myst_nb_metadata_injector",
{"prefix": "#", "delimiter": "="},
{"prefix": "#", "delimiter": "=", "extra_tags": []},
]
}
# enable-end
Expand Down
158 changes: 158 additions & 0 deletions docs/usage.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
"Usually, this should be comment symbol(s) of the programming language.\n",
"By default, and used in the example above, the `prefix=#` as this is the comment symbol for the Python programming language.\n",
"The `delimiter` may be a character/string of your choice and will be used for separating key-value pairs.\n",
"If you would like to add _additional_ [tags](sec/tags-conf) (when writing custom CSS rules, for example), you can also specify these as a list of strings in the `extra_tags` option.\n",
"\n",
"To see a list of all possible configuration, see the [API documentation of mystnb_nb_metadata_injector](myst_nb_metadata_injector).\n",
"\n",
Expand Down Expand Up @@ -171,9 +172,12 @@
"metadata": {},
"source": [
"- [](sec/remove-input)\n",
"- [](sec/hide-input)\n",
"- [](sec/remove-stderr)\n",
"- [](sec/remove-output)\n",
"- [](sec/hide-output)\n",
"- [](sec/remove-cell)\n",
"- [](sec/hide-cell)\n",
"- [](sec/skip-execution)\n",
"- [](sec/raises-exception)"
]
Expand Down Expand Up @@ -263,6 +267,34 @@
"print(\"My code cell is removed\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"(sec/hide-input)=\n",
"### hide-input\n",
"\n",
"Hide the source code of the cell behind a collapsible button.\n",
"Useful if you want to draw the attention of the reader away from the code but still allow them to view the code if interested.\n",
"\n",
"Source:\n",
"\n",
"```python\n",
"# hide-input\n",
"print(\"My code cell is hidden behind a collapsible button.\")\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# hide-input\n",
"print(\"My code cell is hidden behind a collapsible button.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
Expand Down Expand Up @@ -351,6 +383,33 @@
"print(\"including the error output\", file=sys.stderr)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"(sec/hide-output)=\n",
"### hide-output\n",
"\n",
"Hide the output of the code cell behind a collapsible button.\n",
"This affects the entire output (`stderr` and `stdout`, like [](sec/remove-output)).\n",
"\n",
"Source:\n",
"```python\n",
"# hide-output\n",
"print(\"My output is hidden behind a collapsible button.\")\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# hide-output\n",
"print(\"My output is hidden behind a collapsible button.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
Expand Down Expand Up @@ -400,6 +459,32 @@
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"(sec/hide-cell)=\n",
"### hide-cell\n",
"\n",
"Hide the input as well as the output of the code cell behind a collapsible button.\n",
"\n",
"Source:\n",
"```python\n",
"# hide-cell\n",
"print(\"The input and output is hidden behind a collapsible button.\")\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# hide-cell\n",
"print(\"The input and output is hidden behind a collapsible button.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
Expand Down Expand Up @@ -487,6 +572,8 @@
"\n",
"- [](sec/remove_code_source)\n",
"- [](sec/remove_code_outputs)\n",
"- [](sec/code_prompt_show)\n",
"- [](sec/code_prompt_hide)\n",
"- [](sec/number_source_lines)\n",
"- [](sec/output_stderr)\n",
"- [](sec/merge_streams)\n",
Expand Down Expand Up @@ -579,6 +666,77 @@
"print(\"including the error output\", file=sys.stderr)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"(sec/code_prompt_show)=\n",
"### code_prompt_show\n",
"Prompt _text_ that is displayed to inform the user that the dialog can be _expanded_.\n",
"The optional `{type}` placeholder will be replaced with `content`, `source`, or `outputs`, depending on the `hide` tag ([](sec/hide-input), [](sec/hide-output), [](sec/hide-cell)).\n",
"\n",
":::{note}\n",
"Also requires the code cell to specify one of the `hide-X` options.\n",
":::\n",
"\n",
"Mainly included for completeness.\n",
"This would be an ideal example of a configuration value that should be set globally instead of individually within each code cell.\n",
"\n",
"\n",
"Source:\n",
"```python\n",
"# hide-input\n",
"# code_prompt_show = \"Click here to see my absolutely awesome {type}\"\n",
"print(\"Setting code_prompt_show\")\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# hide-input\n",
"# code_prompt_show = \"Click here to see my absolutely awesome {type}\"\n",
"print(\"Setting code_prompt_show\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"(sec/code_prompt_hide)=\n",
"### code_prompt_hide\n",
"Prompt _text_ that is displayed to inform the user that the dialog can be _collapsed/minimized_.\n",
"The optional `{type}` placeholder will be replaced with `content`, `source`, or `outputs`, depending on the `hide` tag ([](sec/hide-input), [](sec/hide-output), [](sec/hide-cell)).\n",
"\n",
":::{note}\n",
"Also requires the code cell to specify one of the `hide-X` options.\n",
":::\n",
"\n",
"Mainly included for completeness.\n",
"This would be an ideal example of a configuration value that should be set globally instead of individually within each code cell.\n",
"\n",
"Source:\n",
"```python\n",
"# hide-input\n",
"# code_prompt_hide = \"Click here to minimize my absolutely awesome {type} (What is wrong with it?! :( )\"\n",
"print(\"Expand the button above to see the text!\")\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# hide-input\n",
"# code_prompt_hide = \"Click here to minimize my awesome {type} (What is wrong with it?! 🥲)\"\n",
"print(\"Expand the button above to see the hide prompt!\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
Expand Down
Loading

0 comments on commit e1ff311

Please sign in to comment.