Markdown¶
sphinx-hextra does not ship its own Markdown parser. It relies on
MyST, the de-facto Markdown flavour
for Sphinx, which you install as a separate extension:
uv add myst-parser
# or
pip install myst-parser
Then add "myst_parser" to the extensions list in conf.py. Once that is
in place, any file ending in .md goes through MyST on its way to Sphinx.
MyST is a strict superset of CommonMark with additions that map Markdown constructs onto docutils roles and directives — the underlying building blocks Sphinx is built on. Everything Sphinx can do, MyST can express; you are not locked out of any Sphinx feature because you chose Markdown.
The basics¶
Headings use # through ######. Every page should start with exactly one
H1:
# Page title
## A section
### A subsection
Paragraphs are separated by blank lines. Emphasis uses *italic* and
**bold**. Inline code uses backticks. Links use [text](url) and images
use .
Unordered lists use - or *, ordered lists use 1. (the numbers do not
have to be sequential — Markdown renumbers them on render).
Tables use pipes and dashes:
| Column A | Column B |
| -------- | -------- |
| cell | cell |
Blockquotes use >:
> "Documentation is a love letter that you write to your future self."
> — Damian Conway
Fenced code¶
Triple backticks with a language tag produce syntax-highlighted code blocks:
```python
def hello():
print("hi")
```
More on that in Syntax Highlighting.
Directives¶
Directives are where MyST stops looking like plain Markdown. The syntax is a fenced block whose language tag is a directive name in curly braces:
```{note}
This is a rendered note box.
```
All seven sphinx-hextra component directives
(callout, cards,
tabs, steps,
filetree, hero and feature
grid) use exactly this syntax.
colon fences vs backtick fences¶
When you need to nest a directive inside another directive, the outer fence
must use more backticks than the inner, which quickly becomes a
book-keeping exercise. MyST offers an alternative with colon_fence enabled:
myst_enable_extensions = ["colon_fence"]
Now you can use ::: instead of backticks, which keeps the total backtick
budget for actual code samples:
:::{note}
You can freely embed `inline code` without counting backticks.
:::
Roles¶
Roles are the inline equivalent of directives. They are written as
{role}`content`:
See the {doc}`configuration` page, or jump to the {ref}`install-section`.
Useful built-in roles: {doc}, {ref}, {math}, {kbd}, {file},
{command}. See the
MyST roles documentation
for the complete list.
Substitutions¶
If you find yourself repeating the same string — a version number, a URL, a
product name — define a substitution in the myst_substitutions dict in
conf.py:
myst_substitutions = {"version": "0.1.0"}
Then reference it in any page:
You are reading the docs for version {{ version }}.
Extensions worth enabling¶
MyST has a handful of optional syntax extensions that most projects end up using:
colon_fence— write:::fenced directives.deflist— definition lists (term\n: definition).tasklist— GitHub-style- [ ]and- [x]checkboxes.attrs_inline— inline{#id .class}attributes on spans, links, images.linkify— bare URLs automatically become links.dollarmath—$inline$and$$block$$math syntax. See LaTeX.amsmath— AMS LaTeX environments (\begin{align}…\end{align}).
Enable any combination of these in conf.py:
myst_enable_extensions = [
"colon_fence",
"deflist",
"tasklist",
"attrs_inline",
"dollarmath",
]
For the complete reference — every directive, role, and extension — see the MyST documentation.