MyST supports a number of ways to include executable content in your project.
Installing Jupyter¶
Executable content in MyST is processed by a Jupyter server and appropriate kernel. In this lesson, we will run a local Jupyter server to execute code cells.
A pip requirements file, requirements.txt in the root of the repository specifies all of the dependencies you need.
You can install all of these in a virtual environment using pip and then launch Jupyter.
python3 -m venv ./venv
source ./venv/bin/activate
pip install -r requirements.txt
jupyter labpython -m venv venvFor Command Prompt
venv\Scripts\activate.batFor PowerShell
venv\Scripts\activate.ps1Then
pip install -r requirements.txt
jupyter labThis will automatically open the Jupyter Lab interface (at localhost:8888) in your browser, which we will use later.
Options¶
Jupyter Notebook outputs¶
MyST can use Jupyter notebooks, .ipynb files, as input just like Markdown.
If you have a notebook which you have executed, you can add it to the book.
Markdown cells will be rendered in exactly the same way as a Markdown file.
So you can use all of the MyST Markdown you have already learned.
Outputs such as images and interactive plots will also be rendered in the book.
Blocks can be labelled, either by editing a cell’s JSON metadata, or with the following syntax,
#| label: my-labelLabels are particularly useful when integrating notebooks into larger documents such as theses or technical reports. By assigning labels to code blocks, and their corresponding outputs, you can reference them directly within your text, making it clear which code produced which figure, table, or result. This example makes use of labels to reference figures from the Python notebook.
Figures can be given a caption in a similar way,
#| caption: Caption textWe will explore using Jupyter notebooks as input for MyST in Adding a Jupyter Notebook.
Executing at build time¶
MyST can also execute content at build time, through connecting to a Jupyter server.
Executable cells can be in the .ipynb format as well as written in Markdown using either the code-cell directive or eval role.
We will cover executing at build time with Jupyter Notebooks in Adding a Jupyter Notebook, and with Markdown in Executable Markdown.
In page execution¶
Through connecting your site to a remote Jupyter, it is also possible to execute code cells live, in the browser. This feature is excellent for presenting readers with interactive elements, such as data science workflows they can follow along, or exercises where they are invited to change code.
In page execution is not covered in this lesson.
Adding a Jupyter Notebook¶
In this repository we have included a Jupyter notebook, example.ipynb, which has been executed and includes outputs.
Executable Markdown¶
Unlike Jupyter notebook files, Markdown files do not store the output of executions.
This means to include the outputs in our project, we must execute the cells at build time.
To make a Markdown file executable, you must first add a kernelspec to the files frontmatter.
For example, in this page,
---
kernelspec:
name: python3
display_name: 'Python 3'
---The MyST Guide has a section on the advantages of the .md and .ipynb formats.
You can add a block of executable code using the code-cell directive.
The directive has the format,
:::{code-cell} <language>
:key: value
<code>
:::The key/value pairs allow you to tag the cell in the same way as with ipynb.
We will use the default Python kernel in these examples. However, you can use another kernel, such as Javascript, R or Julia by changing the page frontmatter and updating code cell blocks.
Put the following Python snippet in a code cell.
def fib(n):
if n < 0:
return
if n in [0, 1]:
return n
else:
return fib(n-2) + fib(n-1)
for i in range(10):
print(i, fib(i))Rebuild the book (with the --execute flag) and look at the result.
Now, add a label (using the key/value notation) to the code cell and reference it here.
Make the code cell a figure by adding a caption; notice how the reference changes.
You can also use the eval role to execute expressions in Markdown text.
Copy the following examples using the eval role and complete the statements to execute.
$6872 \times 3409$ is {eval}``
The first 15 multiples of 23 are {eval}``For the second example, you may want to use a list comprehension.
Cell Tags and Hiding Input¶
Cell tags in Jupyter Notebooks are metadata labels that you can assign to individual cells.
They are useful for customizing the behavior of cells, such as hiding code input.
Markdown cells allow you to add tags as well, e.g. :tags: [hide-input].
To hide the input of a code cell (so only the output is visible), you can add a tag like hide_input to that cell.
JB2 recognizes this tag and will hide the code input when rendering or exporting the notebook.
To add a tag:
Select the cell.
Open the “View” menu and enable the “Cell Toolbar” → “Tags”.
Add the tag
hide_input(or another tag recognized by your toolchain).
This feature is especially useful for creating clean, reader-friendly notebooks where you want to focus on results rather than code details, see below.
Source
print("This is the output of the cell, but the input code is hidden.")This is the output of the cell, but the input code is hidden.
Create a code cell that calculates the square of numbers from 5 to 8 and prints the results. Remove the input code from being displayed by adding the appropriate tag.
GitHub Actions Example¶
Here is an example GitHub Action workflow file to illustrate one possible way to build a virtual environment and execute notebooks during the book build. We will cover other aspects of the workflow file in later lessons (for example, GH Actions itself and PDF generation).
GitHub Action workflow example
name: MyST GitHub Pages Deploy
on:
push:
branches: [main]
env:
# `BASE_URL` determines the website is served from, including CSS & JS assets
# You may need to change this to `BASE_URL: ''`
BASE_URL: /${{ github.event.repository.name }}
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: 'pages'
cancel-in-progress: false
jobs:
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Pages
uses: actions/configure-pages@v3
- uses: actions/setup-node@v4
with:
node-version: 18.x
- uses: typst-community/setup-typst@v4
# Install Python and dependencies
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11' # or your version
- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
pip install jupyter-server nbclient nbformat ipykernel jupyter-client
# pip install plotly kaleido
python -m ipykernel install --user --name=python3
# Install MyST
- name: Install MyST Markdown
run: npm install -g mystmd
# Build PDF
- name: Build PDF
run: |
myst build --pdf
- name: Upload Output PDF as Artifact
uses: actions/upload-artifact@v4
with:
name: Output PDF
path: exports/book.pdf
compression-level: 0
# Build book
- name: Build execute
run: myst build --execute --html
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: './_build/html'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4