-
Notifications
You must be signed in to change notification settings - Fork 7
Notebook Markdown Formatting
In order to ensure that the MDAPL notebooks can be used as stand-alone notebooks and to make sure that the HTML output is as rich as possible, the prose in the notebooks is written with the MyST flavour of Markdown (cheatsheet available here). On top of that, a couple of other formatting options are supported through the use of Sphinx extensions and/or custom scripting.
Cross-references can be written with the regular Jupyter syntax which allows to reference (sub)sections in the same notebook or in different notebooks. Some custom scripting changes those links (and adds the relevant anchors) so that the Jupyter-friendly cross-references also work in the final output formats.
Notice that the text that contains the link in the Jupyter notebooks is replaced by the name of the chapter/(sub)section, so the prose that surrounds the link must make sense in both formats. For example:
We first introduced these primitives in [a previous section](./Other-Notebook.ipynb#Other-Section).
In the Jupyter notebook interface, this sentence reads “We first introduced these primitives in a previous section.”, but in other output formats (like HTML) the sentence will read “We first introduced these primitives in Section X.Y”.
Admonitions are supported by MyST syntax but they are rendered awkwardly in Jupyter, so we use a different approach in the notebooks.
Admonitions are enclosed by HTML comments.
The leading comment is <!-- begin name [style=] -->
and the trailing comment is <!-- end -->
.
name
is the (possibly space-separated) admonition type, which may be one of the supported types (as per this reference), a custom name defined in the preprocessing script, or an arbitrary name.
Arbitrary names must be complemented with the optional style=
option which defines the style to be used, and which must match one of the available styles per this reference.
If a single word, name
must be lower case and is automatically capitalised in the output.
If name
contains two or more words (sequences of space-separated characters), the output shows them as-is.
The whole admonition must be contained inside a single cell and the contents inside the two delimiting HTML comments follows this pattern:
- one “header” line to be displayed in the raw notebooks, e.g.
***Remark***:
; - an empty line; and
- one or more lines of actual content to be displayed inside the admonition.
- if all content lines are preceded by
>
, the admonition is displayed as a blockquote in the raw notebook and the blockquote is stripped from the rich HTML output.
- if all content lines are preceded by
<!-- begin My Admonition style=remark -->
***My Admonition***:
> This is my very own admonition!
>
> Isn't this neat?
<!-- end -->
Jupyter notebooks don't support the syntax [^anchor]
for footnotes, so we use an asterisk *
to mark a footnote and then use a custom admonition to present it.
In the prose, just include an asterisk *
to signal the presence of a footnote.
This asterisk has no real impact in the output, in that there are no plugins or custom scripting processing it.
The footnote itself is just a footnote
admonition.
The styling around the word “note” in the admonition looks uneven because the extra asterisk *
is used to link visually the footnote to the location where it shows up.
The sentence “Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo”* uses a single unique word.
<!-- begin footnote -->
***Note**:
> This is a valid English sentence where “Buffalo” refers to the city, the animal, and the verb that means “to bully”.
<!-- end -->
Support for exercises and solutions is added through the sphinx-exercise
Sphinx extension.
Much like with admonitions, the syntax for exercises and corresponding solutions looks awkward in Jupyter.
Exercises are enclosed between the HTML comments <!-- exercise label -->
and <!-- end -->
and solutions are tagged with <!-- solution label -->
preceding the “solution header”.
label
defines the anchor used to let solutions refer to their specific exercises. To prevent collision with other anchors, consider using a label prefix like ex-
.
The content within the delimiters must be in a single cell and follows a structure similar to that of admonitions:
- one “header” line, typically with a manual exercise number, e.g.,
***Exercise 13***:
; - one blank line; and
- one or more lines containing the exercise itself.
Unlike admonitions, exercises cannot be written inside blockquotes.
<!-- exercise ex-depth -->
***Exercise 13***:
Compute the depth of the results of the following APL expressions:
```APL
0
⍳10
(1 2 3)(4 5 6)
```
You can check your answers by making use of the function _depth_ `≡`.
<!-- end -->
<!-- solution ex-depth -->
***Solution 13***:
We can just check the results in the session:
```APL
≡0
0
≡⍳10
1
≡(1 2 3)(4 5 6)
2
```
It may be helpful to include a couple of solution examples for the readers to verify their code.
Cells that contain the output as if the correct solution had already been implemented can be tagged with skip-execution
to prevent the build system to re-run those cells.
For example, if the book has an exercise asking the reader to implement a function Inc
that adds 1 to the input argument, the following cells may look like:
Inc 1
2
Inc ¯10
¯9
However, if those cells are left as-is, the build system will run the notebook in sequence and will throw errors upon reaching those cells because Inc
hasn't been defined yet.
That is why we tag those cells with skip-execution
.
There are multiple ways to edit cell metadata in the Jupyter interface.
One of the most convenient ways is to use the menu “View” > “Cell Toolbar” > “Tags”.
Attention: The tag skip-execution
requires nbclient>=0.5.5
as per the discussion in this Jupyter Book issue and, in particular, this comment.
Figures are included with the regular markdown syntax for images: ![alt text](img_path)
.
Figures are expected to be included from within the folder res
.
This is relevant for the build process and because of the way links to figures work.
Figure captions are take verbatim from the alt text written within brackets []
in the markdown source.
The alt text/caption is not enclosed in quotes ""
.
To reference a figure in the HTML output use <!--figure-->placeholder text<!--filename-->
.
The second comment contains filename
, which should be the file name of the figure to reference without the res/
prefix and without the extension.
Notice that the placeholder text
is the text shown in the vanilla Jupyter notebooks and will have no link whatsoever.
At the same time, this placeholder text is replaced by the figure link in the style of Figure X.X
.
Therefore, the prose surrounding the placeholder text must make sense when the placeholder text is replaced by the figure name/number.
Generally, the placeholder text is a positional reference to the figure. For example:
![A cute cat](res/cute_cat.png)
<!--figure-->The figure above<!--cute_cat--> shows a cute cat.
In the Jupyter notebook interface, the sentence reads “The figure above shows a cute cat.” whereas the HTML output will show something like “Figure X.Y shows a cute cat.”.