Markdown (MyST)¶
ubCode can parse and preview Markdown as well as reStructuredText.
Enabling Markdown for a project, and choosing its flavour
(commonmark, gfm, or myst),
happens in your project configuration through the [parse.parsers.md] table —
see Parsers and file routing for the keys, file routing, and extension options.
The myst flavour is the full authoring surface.
Markdown is rendered through the same preview engine as reStructuredText,
so under myst the same directives and roles you already use in reStructuredText
render identically in Markdown —
you write them with MyST syntax rather than reStructuredText syntax.
This reference describes the Rendered preview mode; in Structural mode every directive and role renders as a uniform placeholder, identically for reStructuredText and MyST (see Authoring). For the handful of preview behaviours that apply to reStructuredText but not Markdown, see Differences from a Sphinx build.
Flavours¶
The flavour selects a base set of enabled syntax.
Only myst understands directives and roles;
choose it for Sphinx-Needs-style content in Markdown.
Flavour |
What it enables |
|---|---|
|
CommonMark, GFM tables, and the full MyST surface: directives, roles, targets, front matter, and footnotes. Optional extensions (definition lists, dollar math, colon fences, …) are enabled individually. |
|
GitHub Flavored Markdown: tables, strikethrough, task lists, autolinks, and GitHub-style alerts. No directives or roles. |
|
Plain CommonMark (the default). No tables, directives, roles, front matter, or footnotes. |
What renders¶
Under the myst flavour the preview renders the following constructs.
Several of them — task lists, GitHub-style alerts, definition and field lists,
and math — are optional extensions:
the gfm flavour turns task lists and alerts on by default,
while under myst you enable the ones you need (see Parsers and file routing).
Construct |
Syntax |
|---|---|
Headings |
|
Lists and task lists |
|
Tables |
GFM pipe tables with per-column alignment. |
Code blocks |
Fenced (backtick or |
Block quotes |
|
Alerts |
|
Footnotes |
reference markers |
Front matter |
a leading |
Definition and field lists |
a term line with |
Math |
|
Thematic breaks |
|
Links and images |
|
Cross-referencing with links¶
A Markdown link destination does not have to be a web address. Where it names project content, the link becomes a cross-reference: the destination is rewritten to the page it resolves to, and a link you gave no text takes the target’s title.
Destination |
Resolves to |
|---|---|
|
A target. |
|
Another source document, by path relative to this one.
A leading |
|
A place inside another document — a target that document defines. A plain heading is not reached — see the note below. |
|
The same as |
|
A file to download. The file is published beside the site and the link
offers it to the reader to save.
The two spellings differ over a |
|
An object in another project’s inventory
(see Intersphinx).
Narrow the search with up to three filters —
|
|
An external link, unchanged. |
Note
Linking to a heading needs an explicit target.
A #fragment reaches a target, a label or a document, but not a bare
heading — so give the heading a target and link to that:
(some-heading)=
## Some Heading
See [](#some-heading).
Resolving a fragment against headings directly is being designed as one piece; see issue #3082.
A destination that resolves to nothing keeps its text and stays a link,
so a broken reference is visible rather than silent,
and it is reported —
as std.ref or std.doc for project content,
intersphinx.ref for an inventory search,
or download.not_readable for a file that cannot be read.
The link points at # plus the name that could not be found:
the destination itself for a target or document,
and the #fragment alone where the document was found
but the place inside it was not
(the text then reads document#fragment, naming both halves).
Custom URL schemes¶
Declare other schemes under url_schemes to have them treated as external
links, optionally rewriting them:
[parse.parsers.md]
url_schemes = ["doi"] # recognise, rewrite nothing
# …or rewrite as well as recognise:
[parse.parsers.md.url_schemes]
doi = "https://doi.org/{{path}}"
gh = { url = "https://github.com/{{path}}", title = "GitHub: {{path}}" }
A template may substitute any part of the destination —
{{uri}}, {{scheme}}, {{netloc}}, {{path}}, {{params}},
{{query}} and {{fragment}}.
Substitution is plain text replacement, not Jinja:
any other {{name}} is left in the result as written,
and a part the destination does not have substitutes as the empty string.
{{params}} is always empty, so {{path}} keeps any ;segments.
title supplies the link text when you wrote none,
and classes adds HTML classes after any you attached inline.
inv, path and project are reserved for cross-referencing
and cannot be redefined as URL schemes;
an entry naming one is reported and ignored.
Turning cross-referencing off¶
Set all_links_external to treat every Markdown link
as a plain external URL:
[parse.parsers.md]
all_links_external = true
Nothing in the table above then applies.
Every destination — #target, a document path,
project:, path:, inv:,
and any scheme you declared under url_schemes —
reaches the page exactly as you wrote it,
no url_schemes template is applied,
and no link is reported as unresolved.
Use it for content that is authored elsewhere and only rendered here, where the destinations mean something to that other system.
Opening external links in a new tab¶
[parse.parsers.md]
links_external_new_tab = true
A link that renders as an external URL then carries
target="_blank" and rel="noreferrer noopener".
That is every plain web link,
every autolink whose scheme you did not declare,
and every destination a url_schemes entry rewrote.
Cross-references, downloads and inv: links are unaffected —
a link into your own project stays in the same tab.
Directives in MyST¶
A MyST directive is a fenced block whose info string is a name in braces.
Three fence forms are recognised — a backtick fence, a tilde fence,
or (only when the colon_fence extension is enabled) a colon fence:
```{name}
body
```
~~~{name}
body
~~~
:::{name}
body
:::
The argument is the text after {name} on the opening line;
options are given either as :key: value lines
or as a leading --- … --- YAML block;
the remaining lines are the body.
Because Markdown renders through the same engine as reStructuredText,
the same directive set is available and renders to the same rich shapes:
admonitions, image and figure, diagram directives,
need cards, if, version-change markers, and structural blocks.
For what each family renders (and which fall back to a placeholder),
see Directives;
for need directives and their cards see Needs;
for Mermaid and PlantUML see Diagrams.
A colon-fence admonition:
:::{note}
Colon fences avoid escaping backticks when the body contains fenced code.
:::
A need card, written with a backtick fence:
```{req} Login must be secure
:id: REQ_001
:status: open
The login form must be served over TLS.
```
Roles in MyST¶
An inline role is written {name}`text` —
the role name in braces, immediately followed by the target text in backticks.
The same roles available in reStructuredText are available in Markdown;
see Roles for the full set and how each renders.
Cross-reference roles such as {ref} and {need} hydrate exactly as they do
in reStructuredText:
until the project has been indexed in the background they show as placeholder chips,
and once indexing completes they become clickable links to their targets.
See {ref}`config_parsers` and the need {need}`REQ_001`.
Note that MyST has no bare-backtick role: single backticks are always inline code, never interpreted text (see Differences from a Sphinx build).
Differences from the reStructuredText preview¶
A few reStructuredText preview behaviours do not carry over to Markdown:
File splicing. The
.. include::mechanism does not apply to Markdown; a MyST{include}renders as a placeholder rather than splicing in the target file.Prolog and epilog.
rst_prologandrst_epilogare applied to reStructuredText documents only; they add nothing to a Markdown preview.No default role. Because single backticks are always inline code in MyST, there is no bare-interpreted-text default role, and the
default_rolesetting has no effect on Markdown.
See Differences from a Sphinx build for the complete register of preview-versus-build differences.
See also
Parsers and file routing — enabling Markdown, flavours, and extensions.
Directives — the directive set shared with reStructuredText.
Roles — the role set shared with reStructuredText.
Differences from a Sphinx build — where the preview differs from a Sphinx build.