The MyST Syntax Guide

As a base, MyST adheres to the CommonMark specification. For this, it uses the markdown-it-py parser, which is a well-structured markdown parser for Python that is CommonMark-compliant and also extensible.

MyST adds several new syntax options to CommonMark in order to be used with Sphinx, the documentation generation engine used extensively in the Python ecosystem.

Below is a summary of the syntax ‘tokens’ parsed, and further details of a few major extensions from the CommonMark flavor of markdown.

MyST builds on the tokens defined by markdown-it, to extend the syntax described in the CommonMark Spec, which the parser is tested against.

Block Tokens

Block tokens span multiple lines of content. They are broken down into two sections:

Extended block tokens

Token

Description

Example

FrontMatter

A YAML block at the start of the document enclosed by ---

---
key: value
---

Directives

enclosed in 3 or more backticks followed by the directive name wrapped in curly brackets {}. See Directives - a block-level extension point for more details.

```{directive}
:option: value

content
```

Math

Two $ characters wrapping multi-line math

$$
a=1
$$

Table

Standard markdown table style, with pipe separation.

| a    | b    |
| :--- | ---: |
| c    | d    |

LineComment

A commented line. See Comments for more information.

% this is a comment

BlockBreak

Define blocks of text. See Block Breaks for more information.

+++ {"meta": "data"}

Footnote

A definition for a referencing footnote, that is placed at the bottom of the document. See Footnotes for more details.

[^ref]: Some footnote text

CommonMark tokens

Token

Description

Example

HTMLBlock

Any valid HTML (rendered in HTML output only)

<p>some text</p>

BlockCode

indented text (4 spaces or a tab)

    included as literal *text*

Heading

Level 1-6 headings, denoted by number of #

### Heading level 3

SetextHeading

Underlined header (using multiple = or -)

Header
======

Quote

quoted text

> this is a quote

CodeFence

enclosed in 3 or more backticks with an optional language name

```python
print('this is python')
```

ThematicBreak

Creates a horizontal line in the output

---

List

bullet points or enumerated.

- item
  - nested item
1. numbered item

LinkDefinition

A substitution for an inline link, which can have a reference target (no spaces), and an optional title (in ")

[key]: https://www.google.com "a title"

Paragraph

General inline text

any *text*

Span (Inline) Tokens

Span (or inline) tokens are defined on a single line of content. They are broken down into two sections below:

Extended inline tokens

Token

Description

Example

Role

See Roles - an in-line extension point for more information.

`{rolename}`interpreted text`

Target

Precedes element to target, e.g. header. See Targets and Cross-Referencing for more information.

(target)=

Math

dollar enclosed math

$a=1$ or $$a=1$$

FootReference

Reference a footnote. See Footnotes for more details.

[^abc]

CommonMark inline tokens

Token

Description

Example

HTMLSpan

any valid HTML (rendered in HTML output only)

<p>some text</p>

EscapeSequence

escaped symbols (to avoid them being interpreted as other syntax elements)

\*

AutoLink

link that is shown in final output

<http://www.google.com>

InlineCode

literal text

`a=1`

LineBreak

Soft or hard (ends with spaces or backslash)

A hard break\

Image

link to an image

![alt](src "title")

Link

Reference LinkDefinitions

[text](target "title") or [text][key]

Strong

bold text

**strong**

Emphasis

italic text

*emphasis*

RawText

any text

any text

Directives - a block-level extension point

Directives syntax is defined with triple-backticks and curly-brackets. It is effectively a code block with curly brackets around the language, and a directive name in place of a language name. It is similar to how RMarkdown defines “runnable cells”. Here is the basic structure:

MyST

reStructuredText

```{directivename} arguments
---
key1: val1
key2: val2
---
This is
directive content
```
.. directivename:: arguments
   :key1: val1
   :key2: val2

   This is
   directive content

For example, the following code:

```{admonition} This is my admonition
This is my note
```

Will generate this admonition:

This is my admonition

This is my note

For directives that are meant to parse content for your site, you may use markdown as the markup language inside…

```{admonition} My markdown link
Here is [markdown link syntax](https://jupyter.org)
```

As a short-hand for directives that require no arguments, and when no paramter options are used (see below), you may start the content directly after the directive name.

```{note} Notes require **no** arguments, so content can start here.
```

Note

Notes require no arguments, so content can start here.

Parameterizing directives

For directives that take parameters as input, you may parameterize them by beginning your directive content with YAML frontmatter. This needs to be surrounded by --- lines. Everything in between will be parsed by YAML and passed as keyword arguments to your directive. For example:

```{code-block} python
---
lineno-start: 10
emphasize-lines: 1, 3
caption: |
    This is my
    multi-line caption. It is *pretty nifty* ;-)
---
a = 2
print('my 1st line')
print(f'my {a}nd line')
```
This is my multi-line caption. It is pretty nifty ;-)
10
11
12
a = 2
print('my 1st line')
print(f'my {a}nd line')

As a short-hand alternative, more closely resembling the reStructuredText syntax, options may also be denoted by an initial block, whereby all lines start with ‘:’, for example:

```{code-block} python
:lineno-start: 10
:emphasize-lines: 1, 3

a = 2
print('my 1st line')
print(f'my {a}nd line')
```

Nesting directives

You can nest directives by ensuring that the ticklines corresponding to the outermost directive are longer than the ticklines for the inner directives. For example, nest a warning inside a note block like so:

````{note}
The next info should be nested
```{warning}
Here's my warning
```
````

Here’s how it looks rendered:

Note

The next info should be nested

Warning

Here’s my warning

You can indent inner-code fences, so long as they aren’t indented by more than 3 spaces. Otherwise, they will be rendered as “raw code” blocks:

````{note}
The warning block will be properly-parsed

   ```{warning}
   Here's my warning
   ```

But the next block will be parsed as raw text

    ```{warning}
    Here's my raw text warning that isn't parsed...
    ```
````

Note

The warning block will be properly-parsed

Warning

Here’s my warning

But the next block will be parsed as raw text

```{warning}
Here's my raw text warning that isn't parsed...
```

This can really be abused if you’d like ;-)

Note

The next info should be nested

Warning

Here’s my warning

Yep another admonition

# All this fuss was about this boring python?!
print('yep!')

Roles - an in-line extension point

Roles are similar to directives - they allow you to define arbitrary new functionality in Sphinx, but they are used in-line. To define an in-line role, use the following form:

MyST

reStructuredText

{role-name}`role content`
:role-name:`role content`

For example, the following code:

Since Pythagoras, we know that {math}`a^2 + b^2 = c^2`

Becomes:

Since Pythagoras, we know that \(a^2 + b^2 = c^2\)

You can use roles to do things like reference equations and other items in your book. For example:

```{math} e^{i\pi} + 1 = 0
---
label: euler
---
```

Euler's identity, equation {math:numref}`euler`, was elected one of the
most beautiful mathematical formulas.

Becomes:

(1)\[e^{i\pi} + 1 = 0\]

Euler’s identity, equation (1), was elected one of the most beautiful mathematical formulas.

Extra markdown syntax

Here is some extra markdown syntax which provides functionality in rST that doesn’t exist in CommonMark. In most cases, these are syntactic short-cuts to calling roles and directives. We’ll cover some common ones below.

This tale describes the rST and MyST equivalents:

Type

MyST

reStructuredText

Math shortcuts

$x^2$

N/A

Front matter

---
key: val
---
:key: val

Comments

% comment

.. comment

Targets

(mytarget)=

.. _mytarget:

Math shortcuts

Math can be called in-line with single $ characters around your math. For example, $x_{hey}=it+is^{math}$ renders as \(x_{hey}=it+is^{math}\). This is equivalent to writing:

{math}`x_{hey}=it+is^{math}`

Block-level math can be provided with $$ signs that wrap the math block you’d like to parse. For example:

$$
   \begin{eqnarray}
      y    & = & ax^2 + bx + c \\
      f(x) & = & x^2 + 2xy + y^2
   \end{eqnarray}
$$

becomes

\[\begin{split} \begin{eqnarray} y & = & ax^2 + bx + c \\ f(x) & = & x^2 + 2xy + y^2 \end{eqnarray} \end{split}\]

This is equivalent to the following directive:

```{math}
   \begin{eqnarray}
      y    & = & ax^2 + bx + c \\
      f(x) & = & x^2 + 2xy + y^2
   \end{eqnarray}
```

You can also add labels to block equations:

$$
e = mc^2
$$ (eqn:best)

This is the best equation {eq}`eqn:best`
(2)\[ e = mc^2 \]

This is the best equation (2)

Front Matter

This is a YAML block at the start of the document, as used for example in jekyll. Sphinx intercepts these data and stores them within the global environment (as discussed here).

A classic use-case is to specify ‘orphan’ documents, that are not specified in any toctrees. For example, inserting the following syntax at the top of a page will cause Sphinx to treat it as an orphan page:

---
orphan: true
---

This is an orphan document, not specified in any toctrees.

Comments

You may add comments by putting the % character at the beginning of a line. This will prevent the line from being parsed into the output document.

For example, this code:

% my comment

Is below, but it won’t be parsed into the document.

Important

Since comments are a block-level entity, they will terminate the previous block. In practical terms, this means that the following lines will be broken up into two paragraphs, resulting in a new line between them:

a line
% a comment
another line

a line

another line

Block Breaks

You may add a block break by putting +++ at the beginning of a line. This constuct’s intended use case is for mapping to cell based document formats, like jupyter notebooks, to indicate a new text cell. It will not show up in the rendered text, but is stored in the internal document structure for use by developers.

For example, this code:

+++ some text

Is below, but it won’t be parsed into the document.

Targets and Cross-Referencing

Targets are used to define custom anchors that you can refer to elsewhere in your documentation. They generally go before section titles so that you can easily refer to them.

Tip

If you’d like to automatically generate targets for each of your section headers, check out the autosectionlabel sphinx feature. See Automatically create targets for section headers for more details.

Target headers are defined with this syntax:

(header_target)=

They can then be referred to with the ref inline role:

{ref}`header_target`

By default, the reference will use the text of the target (such as the section title), but also you can directly specify the text:

{ref}`my text <header_target>`

For example, see this ref: Targets and Cross-Referencing, and here’s a ref back to the top of this page: my text.

Alternatively using the markdown syntax:

[my text](header_target)

is synonymous with using the any inline role:

{any}`my text <header_target>`

Using the same example, see this ref: Targets and Cross-Referencing, and here’s a ref back to the top of this page: my text.

Footnotes

Footnote labels start with ^ and can then be any alpha-numeric string (no spaces), which is case-insensitive. The actual label is not displayed in the rendered text; instead they are numbered, in the order which they are referenced. All footnote definitions are collected, and displayed at the bottom of the page (ordered by number). Note that un-referenced footnote definitions will not be displayed.

This is a footnote reference.[^myref]

[^myref]: This **is** the footnote definition.

This is a footnote reference.1

Any preceding text after a footnote definitions, which is indented by four or more spaces, will also be included in the footnote definition, e.g.

A longer footnote definition.[^mylongdef]

[^mylongdef]: This is the footnote definition.

    That continues for all indented lines

    - even other block elements

    Plus any preceding unindented lines,
that are not separated by a blank line

This is not part of the footnote.

A longer footnote definition.2

This is not part of the footnote.

Important

Although footnote references can be used just fine within directives, e.g.1, it it recommended that footnote definitions are not set within directives, unless they will only be referenced within that same directive:

[^other]

[^other]: A definition within a directive

3

This is because, in the current implementation, they may not be available to reference in text above that particular directive.


1(1,2)

This is the footnote definition.

2

This is the footnote definition.

That continues for all indented lines

  • even other block elements

Plus any preceding unindented lines, that are not separated by a blank line

3

A definition within a directive