Skip To Article

Executable Markdown Files

Define Jupyter metadata to make Markdown files executable

Execution information can be added to MyST Markdown files, which allows you to perform computation using MyST’s notebook execution engine. First, you will need to define a kernel specification, after which you can introduce Markdown-based computation in several ways:

Kernel specification

Defining a kernel specification (kernelspec) informs the Jupyter server of the name of the kernel that should execute your code. When you call myst build --execute or myst start --execute, the MyST CLI starts a Jupyter kernel to execute your code and gather the execution results. Defining different kernelspecs in each notebook makes it possible to flexibly switch the package environment and programming language (e.g. to use R in one notebook, and Julia in another).

The kernelspec configuration should be defined in the page-level frontmatter of each executable markdown file (see Field Behavior for more information), and supports the same content that is validated by nbformat’s schema:

Table 1:A list of available kernelspec fields

fielddescription
namename of the kernel, e.g. python3
display_namehuman-readable name for the kernel, e.g. “Python 3.12”

The following contents is a frontmatter defines a document that uses the python kernel:

kernelspec:
  name: python3
  display_name: 'Python 3'

After we declare the frontmatter, the contents of each {code-cell} directive and {eval} role will be executed by the python kernel during the building process.

Use a different kernel

Furthermore, you can build MyST Markdown content with other programming languages like JavaScript, R, and Julia by installing the corresponding kernel. For example, to build a page that uses JavaScript in the {code-cell}, we could:

  1. Install a JavaScript kernel, e.g. ijavascript.
  2. Retrieve the kernel name with jupyter kernelspec list.
    In the default installation, the kernel name is javascript.
  3. Set the kernelspec in your document’s frontmatter:
    kernelspec:
      name: javascript
      display_name: JavaScript
  4. Define a code cell that uses the new kernel:
    ```{code-cell} javascript
    console.log("hello javascript kernel");
    ```

Code cells with the {code-cell} directive

You can use the {code-cell} directive to create block-level computational outputs in MyST Markdown.

{code-cell} directives have the following form:

```{code-cell} LANGUAGE
:key: value

CODE TO BE EXECUTED
```
  • LANGUAGE defines the language to be used in executing the code.
  • :key: value pairs will be treated as cell-level metadata.
  • CODE TO BE EXECUTED will be executed by the LANGUAGE kernel at build time.

For example, the following directive inserts a code cell into the page, and will be executed if you specify --execute with your MyST build.

```{code-cell} python
hello = "hello"
there = "there"
phrase = f"{hello}, {there}!"
print(phrase)
```
hello = "hello"
there = "there"
phrase = f"{hello}, {there}!"
print(phrase)
hello, there!

Add tags to {code-cell} directives

You can add tags to the {code-cell} directive. They will be parsed and used in the same way that cell tag metadata is used in .ipynb files.

For example, the following code defines a remove-input tag:

```{code-cell} python
:tags: remove-input
print("This will show output with no input!")
```

and results in the following:

This will show output with no input!

This can be particularly helpful for showing the output of a calculation or plot, which is reproducible in the source code, but not shown to the user like this matplotlib plot:

<Figure size 640x480 with 1 Axes>

For multiple tags you have two ways to provide them:

  • If you specify argument options with :, tags will be parsed as a comma-separated string. For example:

    ```{code-cell} python
    :tags: tag1, tag2,tag3
    # Note that whitespace is removed from tags!
    print("howdy!")
    ```
  • If you specify argument options with YAML, tags should be given as a YAML list. For example:

    ```{code-cell} python
    ---
    tags:
    - tag1
    - tag2
    ---
    print("howdy!")
    ```

For more about how to specify directive options, see MyST Syntax Overview.

Inline expressions with the {eval} role

You can use the {eval} role to evaluate code that is surrounded by text. This allows you to quickly insert its output in a way that flows with the text around it.

For example, the following MyST Markdown would re-use the variable defined above.

The phrase is: {eval}`phrase`.

This results in the following:

The phrase is: 'hello, there!'.

You can also modify the expression at the time of computation, for example:

The phrase manually computed is: {eval}`f"{hello}, {there} everybody!"`

This results in the following:

The phrase manually computed is: 'hello, there everybody!'

Markdown cells with block breaks

In Compatibility with jupytext, the jupytext tool for integrating text-based notebooks with existing Jupyter tools like JupyterLab is discussed. By default, when reading a MyST Markdown document, jupytext creates a single Markdown cell between adjacent code cells. The block-break (+++) syntax described in Blocks and Comments can be used to separate blocks of Markdown into distinct Markdown cells.

Compatibility with jupytext

jupytext is a Python package that converts between Jupyter Notebooks (ipynb files) and plain text documents (like MyST Markdown files). It provides both a commandline tool to perform these conversions, and an extension for JupyterLab to facilitate opening text-based notebooks with the Notebook viewer. MyST Markdown is understood by jupytext, which defines a md:myst format for reading from / writing to MyST Markdown.

The following command will convert a MyST markdown file example.md to the .ipynb notebook:

$ jupytext --from md:myst --to notebook example.md
MyST MarkdownMyST Markdown
Community-driven tools for the future of technical communication and publication, part of Jupyter.