Repository: executablebooks/MyST-Parser
Pull request #717 (2023-02-23 05:33:12)

📚 DOCS: Full update
Just about ready for a release!

codecov[bot]: # [Codecov](https://codecov.io/gh/executablebooks/MyST-Parser/pull/717?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks) Report
Base: **89.80**% // Head: **89.81**% // Increases project coverage by **`+0.01%`** :tada:
> Coverage data is based on head [(`f7b66b3`)](https://codecov.io/gh/executablebooks/MyST-Parser/pull/717?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks) compared to base [(`7ecf1bb`)](https://codecov.io/gh/executablebooks/MyST-Parser/commit/7ecf1bb7b3f377ace86c86bb61d0d322a3937dce?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks).
> Patch coverage: 87.62% of modified lines in pull request are covered.

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master     #717      +/-   ##
==========================================
+ Coverage   89.80%   89.81%   +0.01%     
==========================================
  Files          23       23              
  Lines        2883     2946      +63     
==========================================
+ Hits         2589     2646      +57     
- Misses        294      300       +6     
```

| Flag | Coverage Δ | |
|---|---|---|
| pytests | `89.81% <87.62%> (+0.01%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/executablebooks/MyST-Parser/pull/717?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks) | Coverage Δ | |
|---|---|---|
| [myst\_parser/config/main.py](https://codecov.io/gh/executablebooks/MyST-Parser/pull/717?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks#diff-bXlzdF9wYXJzZXIvY29uZmlnL21haW4ucHk=) | `86.03% <ø> (ø)` | |
| [myst\_parser/sphinx\_ext/myst\_refs.py](https://codecov.io/gh/executablebooks/MyST-Parser/pull/717?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks#diff-bXlzdF9wYXJzZXIvc3BoaW54X2V4dC9teXN0X3JlZnMucHk=) | `88.76% <ø> (ø)` | |
| [myst\_parser/warnings\_.py](https://codecov.io/gh/executablebooks/MyST-Parser/pull/717?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks#diff-bXlzdF9wYXJzZXIvd2FybmluZ3NfLnB5) | `96.07% <ø> (ø)` | |
| [myst\_parser/mdit\_to\_docutils/base.py](https://codecov.io/gh/executablebooks/MyST-Parser/pull/717?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks#diff-bXlzdF9wYXJzZXIvbWRpdF90b19kb2N1dGlscy9iYXNlLnB5) | `92.25% <83.09%> (-0.62%)` | :arrow_down: |
| [myst\_parser/mdit\_to\_docutils/sphinx\_.py](https://codecov.io/gh/executablebooks/MyST-Parser/pull/717?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks#diff-bXlzdF9wYXJzZXIvbWRpdF90b19kb2N1dGlscy9zcGhpbnhfLnB5) | `97.72% <100.00%> (ø)` | |
| [myst\_parser/mocking.py](https://codecov.io/gh/executablebooks/MyST-Parser/pull/717?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks#diff-bXlzdF9wYXJzZXIvbW9ja2luZy5weQ==) | `84.82% <100.00%> (ø)` | |
| [myst\_parser/parsers/docutils\_.py](https://codecov.io/gh/executablebooks/MyST-Parser/pull/717?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks#diff-bXlzdF9wYXJzZXIvcGFyc2Vycy9kb2N1dGlsc18ucHk=) | `82.72% <100.00%> (+1.90%)` | :arrow_up: |
| [myst\_parser/mdit\_to\_docutils/transforms.py](https://codecov.io/gh/executablebooks/MyST-Parser/pull/717?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks#diff-bXlzdF9wYXJzZXIvbWRpdF90b19kb2N1dGlscy90cmFuc2Zvcm1zLnB5) | `90.78% <0.00%> (+3.94%)` | :arrow_up: |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks)

</details>

[:umbrella: View full report at Codecov](https://codecov.io/gh/executablebooks/MyST-Parser/pull/717?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks).   
:loudspeaker: Do you have feedback about the report comment? [Let us know in this issue](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=executablebooks).

chrisjsewell: Just to link, as we discussed on slack; I have tried to kick start some conversation here, as to a shorthand to essentially specify a role/directive in attribute syntax: https://github.com/jgm/djot/issues/146

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a4e3135..94293fd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,111 @@
 # Changelog
 
+## 0.19.0 - 2023-03-01
+
+This release brings a number of exciting new features, improvements, and upgrades 🎉
+
+Full Changelog: [v0.18.1...v0.19.0](https://github.com/executablebooks/MyST-Parser/compare/v0.18.1...v0.19.0)
+
+### 📚 Rewritten documentation
+
+The documentation has been almost completely rewritten,
+with a clearer structure, many more examples, rich hover tips, and a new live preview page ⚡️ (powered by [pyscript](https://pyscript.readthedocs.io/), <gh-pr:717>).
+
+The code base API is also now fully documented by [sphinx-autodoc2](https://sphinx-autodoc2.readthedocs.io/), which even allows for MyST docstrings! (<gh-pr:704>).
+
+### ⬆️ Add Sphinx 6 support, drop Sphinx 4
+
+The code base has been updated to support sphinx v6, and is no longer tested against sphinx v4 (<gh-pr:664>)
+
+### 📄 Extended docutils (single-page) support
+
+The `docutils` parser now supports many more features, and improvements to support live previews:
+
+- `myst_suppress_warnings` option added, mirroring Sphinx, to suppress MyST warnings (<gh-pr:655>)
+- `myst_meta_html` and `myst_substitutions` options are now supported (<gh-pr:672>)
+- `myst_heading_anchors` option is now supported (<gh-pr:678>)
+- Math block labels syntax is now supported (<gh-pr:668>)
+- Missing directive/role errors errors are now suppressable warnings (<gh-pr:687>)
+- Non-fatal directive parsing errors are now suppressable warnings (<gh-pr:682>)
+- Most of the extended markdown syntax below is also supported
+
+### 🔗 Extended Markdown links
+
+See the [Extended Markdown links](docs/syntax/cross-referencing.md) section for the full guide.
+
+You can now use standard Markdown link syntax to reference many different types of targets, in a more consistent way.
+
+- `[text](relative/path/myfile.md)` work as previously, to link to files,
+  but they can also be relative to source directory: `[text](/path/from/srcdir/myfile.md)`.
+  You can also use `<project:file.md>`
+- `<path:myfile.txt>` will link specifically to a downloadable file
+- `[text](#target)` or `<project:#target>` will link (in order of priority) to any local target, local heading anchor, target in the same project, or intersphinx (inventory) target
+- `[text](inv:name:domain:type#target)` will link specifically to a Sphinx inventory target, or to any inventory `<inv:#target>`, and can even use `*` wildcards like `<inv:*:*:*#*.target>`
+  - This can even be used in docutils, with the new `myst_inventories` config option
+  - The `myst-inv` CLI makes it easy to find the correct inventory target
+
+:::{tip}
+It is advised (although not immediately necessary) to prefix all internal references with `#`.
+For example, `[...](my-reference)`, should be changed to `[...](#my-reference)`.
+:::
+
+### `{}` Attributes syntax
+
+The [`attrs_inline` and `attrs_block`](docs/syntax/optional.md#attributes) extensions allow for common Markdown syntaxes to be extended with greater control over the output.
+
+For example, you can now add classes, ids, and other attributes to inline code, images, and links, as well as to code blocks and directives.
+
+- Inline code: `` `a = 1`{#id .class l=python} ``
+- Images: `![image](image.png){#id .class width=100px}`
+- Text spans: `[some text]{#id .class}`
+
+A paragraph block can have attributes too:
+
+```markdown
+{#id .class}
+This is a paragraph with an id and class
+```
+
+A code fence can be given line numbers and line emphasis:
+
+````markdown
+{#id .class lineno-start=1 emphasize-lines="2,3"}
+```python
+a = 1
+b = 2
+c = 3
+```
+````
+
+A definition list can be turned into a glossary, with referenceable terms:
+
+```markdown
+{.glossary}
+term name
+: Definition of the term
+```
+
+Quote blocks can be given an attribution:
+
+```markdown
+{attribution="Chris Sewell"}
+> My quote
+```
+
+### 👌 Miscellaneous improvements
+
+- Nested headings (e.g. inside directives) are now allowed in MyST and are correctly rendered in HTML (<gh-pr:711>)
+- The `colon_fence` extension now renders internal content as MyST, rather than as a code block (<gh-pr:713>)
+- The `include` directive in MyST documents now supports a `:heading-offset:` option, to offset the heading levels in the included document
+- The `myst_heading_slug_func` option now supports setting a `str` which points to a fully qualified function name, e.g. `"module.path.func"` (<gh-pr:696>)
+- The `myst_enable_checkboxes` option allows for task list checkboxes to be enabled/disabled (<gh-pr:686>)
+
+### Additional contributions
+
+- 🐛 FIX: Remove unnecessary assert in <gh-pr:659>, thanks to <gh-user:n-peugnet>
+- 🔧 ci(deps): setup dependabot (<gh-pr:669>), thanks to <gh-user:mmorel-35>
+- 🔧: Depend on typing_extensions only on `Python<3.8` in <gh-pr:642>, thanks to <gh-user:hukkin>
+
 ## 0.18.1 - 2022-27-09
 
 Full Changelog: [v0.18.0...v0.18.1](https://github.com/executablebooks/MyST-Parser/compare/v0.18.0...v0.18.1)
@@ -16,7 +122,7 @@ Full Changelog: [v0.17.2...v0.18.0](https://github.com/executablebooks/MyST-Pars
 
 This release adds support for Sphinx v5 (dropping v3), restructures the code base into modules, and also restructures the documentation, to make it easier for developers/users to follow.
 
-It also introduces **document-level configuration**  *via* the Markdown top-matter, under the `myst` key.
+It also introduces **document-level configuration**  *via* the Markdown front-matter, under the `myst` key.
 See the [Local configuration](docs/configuration.md) section for more information.
 
 ### Breaking changes
@@ -28,7 +134,7 @@ The `to_docutils`, `to_html`, `to_tokens` (from `myst_parser/main.py`) and `mock
 Instead, for single page builds, users should use the docutils parser API/CLI (see [](docs/docutils.md)),
 and for testing, functionality has been moved to <https://github.com/chrisjsewell/sphinx-pytest>.
 
-The top-level `html_meta` and `substitutions` top-matter keys have also been deprecated (i.e. they will still work but will emit a warning), as they now form part of the `myst` config, e.g.
+The top-level `html_meta` and `substitutions` front-matter keys have also been deprecated (i.e. they will still work but will emit a warning), as they now form part of the `myst` config, e.g.
 
 ```yaml
 ---
@@ -100,7 +206,7 @@ In addition, configuration to more finely tune this behaviour has been added.
 - `myst_url_schemes=("http", "https")`, sets what URL schemes are treated as (1)
 - `myst_ref_domains=("std", "py")`, sets what Sphinx reference domains are checked, when handling (3)
 
-See [Markdown Links and Referencing](docs/syntax/syntax.md#markdown-links-and-referencing) for more information.
+See [Markdown Links and Referencing](docs/syntax/cross-referencing.md) for more information.
 
 ### ‼️ Dollarmath is now disabled by default
 
@@ -143,7 +249,7 @@ would be equivalent to:
 # My Title with *emphasis*
 ```
 
-See [Front matter](docs/syntax/syntax.md#front-matter) for more information.
+See [Front matter](docs/configuration.md) for more information.
 
 ### 👌 Internal improvements
 
@@ -291,7 +397,7 @@ is converted to:
 
 These classes should be supported by most sphinx HTML themes.
 
-See [Tables syntax](docs/syntax/syntax.md#tables) for more information.
+See [Tables syntax](docs/syntax/tables.md) for more information.
 
 ### Pull Requests
 
@@ -382,7 +488,7 @@ In particular for users, this update alters the parsing of tables to be consiste
   > {sub-ref}`today` | {sub-ref}`wordcount-words` words | {sub-ref}`wordcount-minutes` min read
   ```
 
-  See [the roles syntax guide](docs/syntax/syntax.md) for further information.
+  See [the roles syntax guide](docs/syntax/roles-and-directives.md) for further information.
 
 - The **`dmath_double_inline`** configuration option allows display math (i.e. `$$`) within an inline context.
   See [the math syntax guide](docs/syntax/optional.md#math-shortcuts) for further information.
@@ -467,7 +573,7 @@ Minor fixes:
 : If the label is an integer, then it will always use this integer for the rendered label (i.e. they are manually numbered).
 : Add `myst_footnote_transition` configuration, to turn on/off transition line.
 : Add `footnotes` class to transition `<hr>` in HTML.
-: See [the syntax guide](docs/syntax/syntax.md) for further information.
+: See [the typography guide](docs/syntax/typography.md) for further information.
 
 👌 IMPROVE: `substitution` extension logic
 
diff --git a/docs/_static/local.css b/docs/_static/local.css
index 2b7933b..fea6282 100644
--- a/docs/_static/local.css
+++ b/docs/_static/local.css
@@ -1,25 +1,13 @@
+/** landing page logo **/
+#landing-page-logo {
+    background: none;
+}
+
 /** Add a counter before subsections **/
-h1 {
+h1:not(.rubric) {
     counter-reset: subsection;
     text-decoration: underline;
 }
-h2 {
-    counter-reset: subsubsection;
-}
-h2::before {
-    counter-increment: subsection;
-    content: counter(subsection) ". ";
-}
-.tippy-box h2::before {
-    content: unset;
-}
-h3::before {
-    counter-increment: subsubsection;
-    content: counter(subsection) "." counter(subsubsection) ". ";
-}
-.tippy-box h3::before {
-    content: unset;
-}
 
 /** MyST examples */
 .myst-example {
@@ -35,30 +23,43 @@ h3::before {
 .myst-example-render {
     padding: 0.5rem;
 }
+.myst-example-render > :first-child {
+    margin-top: 0.5rem;
+}
 
 /** No icon for admonitions with no-icon class */
-.admonition > .admonition-title, div.admonition.no-icon > .admonition-title::before {
+div.admonition.no-icon > .admonition-title::before {
     content: "";
 }
-.admonition > .admonition-title, div.admonition.no-icon > .admonition-title {
+div.admonition.no-icon > .admonition-title {
     padding-left: .6rem;
 }
 
 /* Live preview page */
-iframe.pyscript, textarea.pyscript {
-    width: 100%;
-    height: 400px;
-}
-iframe.pyscript {
-    padding: 4px;
+@media (min-width: 768px) {
+    .preview-input-tabs {
+        height: 100%;
+    }
+    textarea.pyscript.input {
+        height: 100%;
+    }
 }
 textarea.pyscript {
+    width: 100%;
+    min-height: 300px;
     padding: 30px 20px 20px;
     border-radius: 8px;
     resize: vertical;
     font-size: 16px;
     font-family: monospace;
 }
+textarea.pyscript.output {
+    height: 100%;
+}
+div.pyscript {
+    min-height: 300px;
+}
+
 .display-flex {
     display: flex;
 }
diff --git a/docs/conf.py b/docs/conf.py
index fe7c870..2633017 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -4,10 +4,11 @@
 # list see the documentation:
 # https://www.sphinx-doc.org/en/master/usage/configuration.html
 
+import hashlib
 from datetime import date
+from pathlib import Path
 
 from sphinx.application import Sphinx
-from sphinx.transforms.post_transforms import SphinxPostTransform
 
 from myst_parser import __version__
 
@@ -32,13 +33,16 @@ extensions = [
     "sphinx.ext.intersphinx",
     "sphinx.ext.viewcode",
     "sphinx.ext.autodoc",
+    "sphinx.ext.autosummary",
     "sphinx_design",
     "sphinx_copybutton",
     "sphinxext.rediraffe",
-    "sphinxcontrib.mermaid",
+    # disabled due to https://github.com/mgaitan/sphinxcontrib-mermaid/issues/109
+    # "sphinxcontrib.mermaid",
     "sphinxext.opengraph",
     "sphinx_pyscript",
     "sphinx_tippy",
+    "sphinx_togglebutton",
 ]
 
 # Add any paths that contain templates here, relative to this directory.
@@ -60,6 +64,7 @@ intersphinx_mapping = {
 # -- Autodoc settings ---------------------------------------------------
 
 autodoc2_packages = ["../myst_parser"]
+autodoc2_exclude_files = ["_docs.py"]
 autodoc2_hidden_objects = ["dunder", "private", "inherited"]
 autodoc2_replace_annotations = [
     ("re.Pattern", "typing.Pattern"),
@@ -70,9 +75,14 @@ autodoc2_replace_bases = [
     ("myst_parser._compat.TypedDict", "typing.TypedDict"),
     ("sphinx.directives.SphinxDirective", "sphinx.util.docutils.SphinxDirective"),
 ]
+autodoc2_docstring_parser_regexes = [
+    ("myst_parser", "myst"),
+    (r"myst_parser\.setup", "myst"),
+]
 nitpicky = True
 nitpick_ignore_regex = [
     (r"py:.*", r"docutils\..*"),
+    (r"py:.*", r"pygments\..*"),
 ]
 nitpick_ignore = [
     ("py:obj", "myst_parser._docs._ConfigBase"),
@@ -100,7 +110,6 @@ myst_enable_extensions = [
     "tasklist",
     "attrs_inline",
     "attrs_block",
-    "inv_link",
 ]
 myst_url_schemes = {
     "http": None,
@@ -130,6 +139,10 @@ myst_heading_anchors = 2
 myst_footnote_transition = True
 myst_dmath_double_inline = True
 myst_enable_checkboxes = True
+myst_substitutions = {
+    "role": "[role](#syntax/roles)",
+    "directive": "[directive](#syntax/directives)",
+}
 
 # -- HTML output -------------------------------------------------
 
@@ -145,6 +158,8 @@ html_theme_options = {
     "path_to_docs": "docs",
     "use_repository_button": True,
     "use_edit_page_button": True,
+    "use_issues_button": True,
+    "announcement": "<p><b>v0.19</b> is now out! See the Changelog for details</p>",
 }
 # OpenGraph metadata
 ogp_site_url = "https://myst-parser.readthedocs.io/en/latest"
@@ -162,6 +177,7 @@ html_css_files = ["local.css"]
 
 rediraffe_redirects = {
     "using/intro.md": "sphinx/intro.md",
+    "syntax/syntax.md": "syntax/typography.md",
     "sphinx/intro.md": "intro.md",
     "using/use_api.md": "api/index.md",
     "api/index.md": "api/reference.rst",
@@ -190,31 +206,19 @@ latex_engine = "xelatex"
 # -- Local Sphinx extensions -------------------------------------------------
 
 
-class StripUnsupportedLatex(SphinxPostTransform):
-    """Remove unsupported nodes from the doctree."""
-
-    default_priority = 900
-
-    def run(self):
-        if self.app.builder.format != "latex":
-            return
-        from docutils import nodes
-
-        for node in self.document.findall():
-            if node.tagname == "image" and node["uri"].endswith(".svg"):
-                node.parent.replace(node, nodes.inline("", "Removed SVG image"))
-            if node.tagname == "mermaid":
-                node.parent.replace(node, nodes.inline("", "Removed Mermaid diagram"))
-
-
 def setup(app: Sphinx):
     """Add functions to the Sphinx setup."""
     from myst_parser._docs import (
         DirectiveDoc,
         DocutilsCliHelpDirective,
+        MystAdmonitionDirective,
         MystConfigDirective,
         MystExampleDirective,
+        MystLexer,
+        MystToHTMLDirective,
         MystWarningsDirective,
+        NumberSections,
+        StripUnsupportedLatex,
     )
 
     app.add_directive("myst-config", MystConfigDirective)
@@ -222,14 +226,20 @@ def setup(app: Sphinx):
     app.add_directive("doc-directive", DirectiveDoc)
     app.add_directive("myst-warnings", MystWarningsDirective)
     app.add_directive("myst-example", MystExampleDirective)
+    app.add_directive("myst-admonitions", MystAdmonitionDirective)
+    app.add_directive("myst-to-html", MystToHTMLDirective)
     app.add_post_transform(StripUnsupportedLatex)
+    app.add_post_transform(NumberSections)
     app.connect("html-page-context", add_version_to_css)
+    app.add_lexer("myst", MystLexer)
 
 
-def add_version_to_css(app, pagename, templatename, context, doctree):
+def add_version_to_css(app: Sphinx, pagename, templatename, context, doctree):
     """Add the version number to the local.css file, to bust the cache for changes."""
     if app.builder.name != "html":
         return
     if "_static/local.css" in context.get("css_files", {}):
+        css = Path(app.srcdir, "_static/local.css").read_text("utf8")
+        hashed = hashlib.sha256(css.encode("utf-8")).hexdigest()
         index = context["css_files"].index("_static/local.css")
-        context["css_files"][index] = f"_static/local.css?v={__version__}"
+        context["css_files"][index] = f"_static/local.css?hash={hashed}"
diff --git a/docs/configuration.md b/docs/configuration.md
index 8125d9a..c97c9bb 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -32,12 +32,29 @@ Configuration specific to syntax extensions:
 :scope: global
 ```
 
-## Local configuration
+(syntax/frontmatter)=
 
-```{versionadded} 0.18
+## Frontmatter (local) configuration
+
+Frontmatter allows you to specify metadata and options about how a single document should behave or render.
+It is a [YAML](https://en.wikipedia.org/wiki/YAML) block at the start of the document, as used for example in [jekyll](https://jekyllrb.com/docs/front-matter/).
+The document should start with three or more `---` markers, and YAML is parsed until a closing `---` marker is found:
+
+```yaml
+---
+key1: value
+key2: [value1, value2]
+key3:
+  subkey1: value
+---
 ```
 
-The following configuration variables are available at the document level.
+:::{seealso}
+Frontmatter is also used for the [substitution syntax extension](syntax/substitutions),
+and can be used to store information for blog posting (see [ablog's myst-parser support](https://ablog.readthedocs.io/en/latest/manual/markdown/)).
+:::
+
+The following configuration variables are available to be set in the document frontmatter.
 These can be set in the document [front matter](syntax/frontmatter), under the `myst` key, e.g.
 
 ```yaml
@@ -52,6 +69,72 @@ myst:
 :scope: local
 ```
 
+(syntax/html_meta)=
+
+### Setting HTML Metadata
+
+The front-matter can contain the special key `html_meta`; a dict with data to add to the generated HTML as [`<meta>` elements](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta).
+This is equivalent to using the [meta directive](inv:sphinx#html-meta).
+
+HTML metadata can also be added globally in the `conf.py` *via* the `myst_html_meta` variable, in which case it will be added to all MyST documents.
+For each document, the `myst_html_meta` dict will be updated by the document level front-matter `html_meta`, with the front-matter taking precedence.
+
+::::{tab-set}
+:::{tab-item} Sphinx Configuration
+
+```python
+language = "en"
+myst_html_meta = {
+    "description lang=en": "metadata description",
+    "description lang=fr": "description des métadonnées",
+    "keywords": "Sphinx, MyST",
+    "property=og:locale":  "en_US"
+}
+```
+
+:::
+
+:::{tab-item} MyST Front-Matter
+
+```yaml
+---
+myst:
+  html_meta:
+    "description lang=en": "metadata description"
+    "description lang=fr": "description des métadonnées"
+    "keywords": "Sphinx, MyST"
+    "property=og:locale": "en_US"
+---
+```
+
+:::
+
+:::{tab-item} RestructuredText
+
+```restructuredtext
+.. meta::
+   :description lang=en: metadata description
+   :description lang=fr: description des métadonnées
+   :keywords: Sphinx, MyST
+   :property=og:locale: en_US
+```
+
+:::
+
+:::{tab-item} HTML Output
+
+```html
+<html lang="en">
+  <head>
+    <meta content="metadata description" lang="en" name="description" xml:lang="en" />
+    <meta content="description des métadonnées" lang="fr" name="description" xml:lang="fr" />
+    <meta name="keywords" content="Sphinx, MyST">
+    <meta content="en_US" property="og:locale" />
+```
+
+:::
+::::
+
 ### Extensions
 
 Configuration specific to syntax extensions:
@@ -90,9 +173,6 @@ html_admonition
 html_image
 : Convert HTML `<img>` elements to sphinx image nodes, [see here](syntax/images) for details
 
-inv_link
-: Enable the `inv:` schema for Markdown link destinations, [see here](syntax/inv_links) for details
-
 linkify
 : Automatically identify "bare" web URLs and add hyperlinks
 
diff --git a/docs/faq/index.md b/docs/faq/index.md
index dce40b1..aed98f3 100644
--- a/docs/faq/index.md
+++ b/docs/faq/index.md
@@ -9,7 +9,7 @@ These sections describe some common scenarios and use-cases for writing MyST wit
 (howto/include-rst)=
 ### Include rST files into a Markdown file
 
-As explained in [this section](syntax/directives/parsing), all MyST directives will parse their content as Markdown.
+As explained in [this section](#syntax/directives/parsing), all MyST directives will parse their content as Markdown.
 Therefore, using the conventional `include` directive, will parse the file contents as Markdown:
 
 ````md
@@ -20,7 +20,7 @@ Therefore, using the conventional `include` directive, will parse the file conte
 ```{include} snippets/include-md.md
 ```
 
-To include rST, we must first "wrap" the directive in the [eval-rst directive](syntax/directives/parsing):
+To include rST, we must first "wrap" the directive in the [eval-rst directive](#syntax/directives/parsing):
 
 ````md
 ```{eval-rst}
@@ -53,6 +53,10 @@ The [MyST-NB](https://myst-nb.readthedocs.io) tool provides a Sphinx extension f
 (howto/include-readme)=
 ### Include a file from outside the docs folder (like README.md)
 
+:::{seealso}
+<project:#organising-content/include>
+:::
+
 You can include a file, including one from outside the project using e.g.:
 
 ````md
@@ -102,80 +106,19 @@ If you encounter any issues with this feature, please don't hesitate to report i
 (howto/autodoc)=
 ### Use `sphinx.ext.autodoc` in Markdown files
 
-The [Sphinx extension `autodoc`](inv:sphinx#sphinx.ext.autodoc), which pulls in code documentation from docstrings, is currently hard-coded to parse reStructuredText.
-It is therefore incompatible with MyST's Markdown parser.
-However, the special [`eval-rst` directive](syntax/directives/parsing) can be used to "wrap" `autodoc` directives:
-
-````md
-```{eval-rst}
-.. autoclass:: myst_parser.mocking.MockRSTParser
-    :show-inheritance:
-    :members: parse
-```
-````
-
-```{eval-rst}
-.. autoclass:: myst_parser.mocking.MockRSTParser
-    :show-inheritance:
-    :members: parse
-    :noindex:
-```
-
-As with other objects in MyST, this can then be referenced:
-
-- Using the role `` {py:class}`myst_parser.mocking.MockRSTParser` ``: {py:class}`myst_parser.mocking.MockRSTParser`
-- Using the Markdown syntax `[MockRSTParser](myst_parser.mocking.MockRSTParser)`: [MockRSTParser](myst_parser.mocking.MockRSTParser)
-
-```{warning}
-This expects docstrings to be written in reStructuredText.
-We hope to support Markdown in the future, see [GitHub issue #228](https://github.com/executablebooks/MyST-Parser/issues/228).
-```
+See [](#syntax/apis) for this information.
 
 (howto/autosectionlabel)=
 ### Automatically create targets for section headers
 
-:::{important}
-
-New in `v0.13.0` ✨, myst-parser now provides a separate implementation of `autosectionlabel`, which implements GitHub Markdown style bookmark anchors, like `[](file.md#header-anchor)`.
-
-See the [](syntax/header-anchors) section of extended syntaxes.
-
+:::{versionadded} 0.13.0
+See [](#syntax/implicit-targets) for this information.
 :::
 
-If you'd like to *automatically* generate targets for each of your section headers,
-check out the [autosectionlabel](inv:sphinx#usage/*/autosectionlabel)
-sphinx feature. You can activate it in your Sphinx site by adding the following to your
-`conf.py` file:
-
-```python
-extensions = [
-    'sphinx.ext.autosectionlabel',
-]
-
-# Prefix document path to section labels, to use:
-# `path/to/file:heading` instead of just `heading`
-autosectionlabel_prefix_document = True
-```
-
-So, if you have a page at `myfolder/mypage.md` (relative to your documentation root)
-with the following structure:
-
-```md
-# Title
-
-## My Subtitle
-```
-
-Then the `autosectionlabel` feature will allow you to reference the section headers
-like so:
-
-```md
-{ref}`path/to/file_1:My Subtitle`
-```
 
 ### Suppress warnings
 
-Moved to [](myst-warnings)
+See <project:#myst-warnings> for this information.
 
 ### Sphinx-specific page front matter
 
diff --git a/docs/faq/snippets/include-md.md b/docs/faq/snippets/include-md.md
index 296421a..3935b1c 100644
--- a/docs/faq/snippets/include-md.md
+++ b/docs/faq/snippets/include-md.md
@@ -1,1 +1,1 @@
-Hallo I'm from a Markdown file, [with a reference](howto/autodoc).
+Hallo I'm from a Markdown file, [with a reference](#howto/autodoc).
diff --git a/docs/index.md b/docs/index.md
index 642ae72..7002212 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -2,7 +2,7 @@
 sd_hide_title: true
 ---
 
-# Overview
+# 🔎 Overview
 
 ::::{grid}
 :reverse:
@@ -15,6 +15,7 @@ sd_hide_title: true
 ```{image} _static/logo-square.svg
 :width: 200px
 :class: sd-m-auto
+:name: landing-page-logo
 ```
 
 :::
@@ -130,22 +131,35 @@ live-preview.md
 
 ```{toctree}
 :hidden:
-:caption: Guides
+:caption: ✏️ Authoring
+
+syntax/typography.md
+syntax/admonitions.md
+syntax/images_and_figures.md
+syntax/tables.md
+syntax/code_and_apis.md
+syntax/cross-referencing.md
+syntax/math.md
+```
+
+```{toctree}
+:hidden:
+:caption: 📚 Guides
 
-syntax/syntax
+configuration.md
+syntax/organising_content.md
 syntax/optional
 syntax/roles-and-directives.md
-configuration.md
 docutils.md
 faq/index.md
-develop/index.md
 ```
 
 ```{toctree}
 :hidden:
-:caption: Reference
+:caption: 📖 Reference
 
 develop/_changelog.md
+develop/index.md
 syntax/reference
 develop/background.md
 apidocs/index.rst
diff --git a/docs/intro.md b/docs/intro.md
index c488496..92772ba 100644
--- a/docs/intro.md
+++ b/docs/intro.md
@@ -1,14 +1,14 @@
 (intro/get-started)=
-# Get Started
+# 🚀 Get Started
 
-This page describes how to get started with the MyST parser, with a focus on enabling it in the Sphinx documentation engine.
+This page gives a quick overview of how to get started with MyST Markdown, and how to use it within Docutils and Sphinx.
 
 ## Installation
 
 [![PyPI][pypi-badge]][pypi-link]
 [![Conda][conda-badge]][conda-link]
 
-To install use [pip](https://pip.pypa.io):
+To install myst-parser use [pip](https://pip.pypa.io):
 
 ```bash
 pip install myst-parser
@@ -25,140 +25,97 @@ conda install -c conda-forge myst-parser
 [conda-badge]: https://anaconda.org/conda-forge/myst-parser/badges/version.svg
 [conda-link]: https://anaconda.org/conda-forge/myst-parser
 
-(intro/sphinx)=
-## Enable MyST in Sphinx
-
-To get started with Sphinx, see their [quick-start guide](inv:sphinx#usage/quickstart).
-
-To use the MyST parser in Sphinx, simply add the following to your `conf.py` file:
-
-```python
-extensions = ["myst_parser"]
-```
-
-This will activate the MyST Parser extension, causing all documents with the `.md` extension to be parsed as MyST.
-
-:::{tip}
-To parse single documents, see the [](docutils.md) section
-:::
-
 (intro/writing)=
-## Write a CommonMark document
-
-MyST is an extension of [CommonMark Markdown](https://commonmark.org/),
-that includes [additional syntax](syntax/syntax.md) for technical authoring,
-which integrates with Docutils and Sphinx.
+## Write a Markdown document
 
-To start off, create an empty file called `myfile.md` and give it a markdown title and text.
+To start off, create an empty file called `example.md` and give it a Markdown title and text.
+We can now use the `myst-docutils-demo` [CLI tool](docutils.md), from the installed package, to parse this file to HTML:
 
-```md
+:::{myst-to-html}
 # My nifty title
 
 Some **text**!
-```
+:::
 
-To parse to HTML, try the CLI:
-
-```html
-$ myst-docutils-html5 --stylesheet= myfile.md
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
-<meta charset="utf-8"/>
-<meta name="viewport" content="width=device-width, initial-scale=1" />
-<meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
-<title>My nifty title</title>
-
-</head>
-<body>
-<main id="my-nifty-title">
-<h1 class="title">My nifty title</h1>
-
-<p>Some <strong>text</strong>!</p>
-</main>
-</body>
-</html>
-```
+## Extend Markdown with MyST syntax
+
+MyST is an extension of [CommonMark Markdown](https://commonmark.org/),
+that includes a rich [additional syntax](syntax/typography.md) for technical authoring,
+and can integrate with Docutils and Sphinx.
 
-To include this document within a Sphinx project,
-include `myfile.md` in a [`toctree` directive](inv:sphinx#toctree-directive) on an index page.
+For example, MyST includes {{role}} and {{directive}} extensions points, to allow for richer features, such as [admonitions](syntax/admonitions.md) and [figures](syntax/images_and_figures.md).
 
-## Extend CommonMark with roles and directives
+Lets add an `admonition` directive and `sup` role to your Markdown page, like so:
 
-MyST allows any Sphinx role or directive to be used in a document.
-These are extensions points allowing for richer features, such as admonitions and figures.
 
-For example, add an `admonition` directive and `sup` role to your Markdown page, like so:
+::::{myst-to-html}
+:extensions: colon_fence
 
-````md
 # My nifty title
 
 Some **text**!
 
-```{admonition} Here's my title
+:::{admonition} Here's my title
 :class: tip
 
 Here's my admonition content.{sup}`1`
-```
-````
-
-Then convert to HTML:
-
-```html
-$ myst-docutils-html5 --stylesheet= myfile.md
-...
-<div class="admonition tip">
-<p class="admonition-title">Here's my title</p>
-<p>Here's my admonition content.<sup>1</sup></p>
-</div>
-...
-```
+:::
 
-:::{seealso}
-The full [](syntax/roles-and-directives.md) section
+::::
+
+:::{tip}
+MyST works with just about all Docutils and Sphinx roles and directives.
+
+Note, Sphinx provides a superset of the Docutils roles and directives, so some may not work in the Docutils CLI.
 :::
 
 (intro/reference)=
 ## Cross-referencing
 
-MyST-Parser offers powerful cross-referencing features, to link to documents, headers, figures and more.
+MyST-Parser offers powerful [cross-referencing features](syntax/cross-referencing.md), to link to documents, headers, figures and more.
 
 For example, to add a section *reference target*, and reference it:
 
-```md
+::::{myst-to-html}
 (header-label)=
 # A header
 
-[My reference](header-label)
-```
+[My reference](#header-label)
+::::
 
-```html
-$ myst-docutils-html5 --stylesheet= myfile.md
-...
-<span id="header-label"></span>
-<h1 class="title">A header</h1>
+(intro/sphinx)=
+## Enable MyST in Sphinx
 
-<p><a class="reference internal" href="#header-label">My reference</a></p>
-...
+To get started with Sphinx, see their [quick-start guide](inv:sphinx#usage/quickstart).
+
+To use the MyST parser in Sphinx, simply add the following to your `conf.py` [configuration file](inv:sphinx#usage/configuration):
+
+```python
+extensions = ["myst_parser"]
 ```
 
-:::{seealso}
-The [](syntax/referencing) section,\
-and the [ReadTheDocs cross-referencing](https://docs.readthedocs.io/en/stable/guides/cross-referencing-with-sphinx.html) documentation
+This will activate the MyST Parser extension, causing all documents with the `.md` extension to be parsed as MyST.
+
+Our `example.md` file can now be added as the [index page](inv:sphinx#usage/index),
+or see the [organising content section](#syntax/toctree) about creating `toctree` directives, to add `example.md` to.
+
+:::{tip}
+There are a range of great HTML themes that work well with MyST, such as [sphinx-book-theme](https://github.com/executablebooks/sphinx-book-theme) (used here),
+[pydata-sphinx-theme](https://github.com/pydata/pydata-sphinx-theme/) and
+[furo](https://github.com/pradyunsg/furo)
 :::
 
 ## Configuring MyST-Parser
 
-The [](configuration.md) section contains a complete list of configuration options for the MyST-Parser.
+The <project:configuration.md> section contains a complete list of configuration options for the MyST-Parser.
 
 These can be applied globally, e.g. in the sphinx `conf.py`:
 
 ```python
-myst_enable_extensions = [
-  "colon_fence",
-]
+myst_enable_extensions = ["colon_fence"]
 ```
 
-Or they can be applied to specific documents, at the top of the document:
+Or they can be applied to specific documents, at the top of the document, in frontmatter:
 
 ```yaml
 ---
@@ -171,10 +128,9 @@ myst:
 
 The other way to extend MyST in Sphinx is to install Sphinx extensions that define new roles, directives, etc.
 
-For example, let's install the `sphinxcontrib.mermaid` extension,
-which will allow us to generate [Mermaid diagrams](https://mermaid-js.github.io/mermaid/#/) with MyST.
+For example, let's install the [sphinx-design](https://github.com/executablebooks/sphinx-design) extension, which will allow us to create beautiful, screen-size responsive web-components.
 
-First, install `sphinxcontrib.mermaid`:
+First, install `sphinx-design`:
 
 ```shell
 pip install sphinxcontrib-mermaid
@@ -185,66 +141,94 @@ Next, add it to your list of extensions in `conf.py`:
 ```python
 extensions = [
   "myst_parser",
-  "sphinxcontrib.mermaid",
+  "sphinx_design",
 ]
 ```
 
-Now, add a **mermaid directive** to your markdown file.
-For example:
+Now, we can use the `design` directive to add a web-component to our Markdown file!
 
-````md
-# My nifty title
+::::{myst-example}
+:::{card} Card Title
+Header
+^^^
+Card content
++++
+Footer
+:::
+::::
 
-Some **text**!
 
-```{admonition} Here's my title
-:class: warning
+::::::{myst-example}
 
-Here's my admonition content
-```
+::::{tab-set}
+
+:::{tab-item} Label1
+Content 1
+:::
 
-(section-two)=
-## Here's another section
+:::{tab-item} Label2
+Content 2
+:::
 
-And some more content.
+::::
 
-% This comment won't make it into the outputs!
-And here's {ref}`a reference to this section <section-two>`.
-I can also reference the section {ref}`section-two` without specifying my title.
+::::::
 
-:::{note}
-And here's a note with a colon fence!
-:::
+% TODO this can uncommented once https://github.com/mgaitan/sphinxcontrib-mermaid/issues/109 is fixed
+% For example, let's install the `sphinxcontrib.mermaid` extension,
+% which will allow us to generate [Mermaid diagrams](https://mermaid-js.github.io/mermaid/#/) with MyST.
 
-And finally, here's a cool mermaid diagram!
-
-```{mermaid}
-sequenceDiagram
-  participant Alice
-  participant Bob
-  Alice->John: Hello John, how are you?
-  loop Healthcheck
-      John->John: Fight against hypochondria
-  end
-  Note right of John: Rational thoughts <br/>prevail...
-  John-->Alice: Great!
-  John->Bob: How about you?
-  Bob-->John: Jolly good!
-```
-````
-
-When you build your documentation, you should see something like this:
-
-```{mermaid}
-sequenceDiagram
-  participant Alice
-  participant Bob
-  Alice->John: Hello John, how are you?
-  loop Healthcheck
-      John->John: Fight against hypochondria
-  end
-  Note right of John: Rational thoughts <br/>prevail...
-  John-->Alice: Great!
-  John->Bob: How about you?
-  Bob-->John: Jolly good!
-```
+% First, install `sphinxcontrib.mermaid`:
+
+% ```shell
+% pip install sphinxcontrib-mermaid
+% ```
+
+% Next, add it to your list of extensions in `conf.py`:
+
+% ```python
+% extensions = [
+%   "myst_parser",
+%   "sphinxcontrib.mermaid",
+% ]
+% ```
+
+% Now, add a **mermaid directive** to your Markdown file.
+% For example:
+
+% :::{myst-example}
+% Here's a cool mermaid diagram!
+%
+% ```{mermaid}
+% sequenceDiagram
+%   participant Alice
+%   participant Bob
+%   Alice->John: Hello John, how are you?
+%   loop Healthcheck
+%       John->John: Fight against hypochondria
+%   end
+%   Note right of John: Rational thoughts <br/>prevail...
+%   John-->Alice: Great!
+%   John->Bob: How about you?
+%   Bob-->John: Jolly good!
+% ```
+% :::
+
+
+There are many other great Sphinx extensions that work with MyST, such as the ones used in this documentation:
+
+:sphinx-design: Add beautiful, responsive web-components to your documentation
+:sphinx-copybutton: Add a copy button to your code blocks
+:sphinxext-rediraffe: Add redirects to your documentation
+:sphinxext-opengraph: Add OpenGraph metadata to your documentation
+:sphinx-pyscript: Execute Python code in your documentation, [see here](https://github.com/sphinx-extensions2/sphinx-pyscript)
+:sphinx-tippy: Add tooltips to your documentation, [see here](https://github.com/sphinx-extensions2/sphinx-tippy)
+:sphinx-autodoc2: Generate documentation from docstrings, [see here](https://github.com/sphinx-extensions2/sphinx-autodoc2)
+:sphinx-togglebutton: Add collapsible content to your documentation
+:sphinxcontrib.mermaid: Generate [Mermaid diagrams](https://mermaid-js.github.io/mermaid/#/)
+
+
+:::{seealso}
+[sphinx-extensions](https://sphinx-extensions.readthedocs.io/en/latest/),
+for a curated and opinionated list of Sphinx extensions.
+:::
diff --git a/docs/live-preview.md b/docs/live-preview.md
index 095e534..d80dd0c 100644
--- a/docs/live-preview.md
+++ b/docs/live-preview.md
@@ -3,35 +3,38 @@ py-config:
   splashscreen:
     autoclose: true
   packages:
-    - myst-docutils
+    - myst-docutils==0.18
     - docutils==0.19
     - pygments
 ---
 
-# Live Preview
+# ⚡️ Live Preview
 
 This is a live preview of the MyST Markdown [docutils renderer](docutils.md).
-You can edit the text/configuration below and see the live output.[^note]
-
-[^note]: Additional styling is usually provided by Sphinx themes.
+You can edit the text/configuration below and see the live output.
 
 ```{py-script}
 :file: live_preview.py
 ```
 
-::::::::{grid} 1 1 1 2
+::::::::{grid} 1 1 2 2
 
 :::::::{grid-item}
-:child-align: end
+:child-align: start
 
 ```{raw} html
-<div><u><span id="myst-version"></span></u></div>
+<div><u><span id="myst-version">myst-parser v</span></u></div>
 ```
 
 :::::{tab-set}
+:class: preview-input-tabs
+
 ::::{tab-item} Input text
+:class-container: sd-h-100
+:class-content: sd-h-100
+
 ````{raw} html
-<textarea class="pyscript" id="input_myst">
+<textarea class="pyscript input" id="input_myst">
 # Heading 1
 
 Hallo world!
@@ -40,20 +43,23 @@ Hallo world!
 An admonition note!
 ```
 
+## Math
+
+```python
+from package import module
+module.call("string")
+```
+
+## Definition list
+
 term
 : definition
 
+## Math
+
 $$\pi = 3.14159$$
 
-```{list-table}
-:header-rows: 1
-:align: center
-
-* - Header 1
-  - Header 2
-* - Item 1
-  - Item 2
-```
+## Figures
 
 ```{figure} https://via.placeholder.com/150
 :width: 100px
@@ -61,28 +67,41 @@ $$\pi = 3.14159$$
 
 Figure caption
 ```
+
+## Tables
+
+```{list-table}
+:header-rows: 1
+:align: center
+
+* - Header 1
+  - Header 2
+* - Item 1 a
+  - Item 2 a
+* - Item 1 b
+  - Item 2 b
+```
 </textarea>
 ````
 
 ::::
 ::::{tab-item} Configuration (YAML)
-<textarea class="pyscript" id="input_config">
-# see: https://docutils.sourceforge.io/docs/user/config.html
+:class-container: sd-h-100
+:class-content: sd-h-100
+
+<textarea class="pyscript input" id="input_config">
 myst_enable_extensions:
 - colon_fence
 - deflist
 - dollarmath
-myst_highlight_code_blocks: false
-embed_stylesheet: true
-stylesheet_path:
-- minimal.css
+myst_highlight_code_blocks: true
 </textarea>
 ::::
 :::::
 
 :::::::
 :::::::{grid-item}
-:child-align: end
+:child-align: start
 
 ```{raw} html
 <div class="display-flex">
@@ -97,13 +116,13 @@ stylesheet_path:
 
 ::::{tab-set}
 :::{tab-item} HTML Render
-<iframe class="pyscript" id="output_html" readonly="true"></iframe>
+<div class="pyscript" id="output_html"></div>
 :::
 :::{tab-item} Raw Output
-<textarea class="pyscript" id="output_raw" readonly="true"></textarea>
+<textarea class="pyscript output" id="output_raw" readonly="true"></textarea>
 :::
 :::{tab-item} Warnings
-<textarea class="pyscript" id="output_warnings" readonly="true"></textarea>
+<textarea class="pyscript output" id="output_warnings" readonly="true"></textarea>
 :::
 ::::
 :::::::
diff --git a/docs/live_preview.py b/docs/live_preview.py
index ffd70b2..87e1224 100644
--- a/docs/live_preview.py
+++ b/docs/live_preview.py
@@ -3,12 +3,38 @@ from io import StringIO
 
 import yaml
 from docutils.core import publish_string
+from docutils.frontend import filter_settings_spec
+from docutils.writers.html5_polyglot import HTMLTranslator, Writer
 from js import document
 
 from myst_parser import __version__
 from myst_parser.parsers.docutils_ import Parser
 
 
+class SimpleTranslator(HTMLTranslator):
+    def visit_literal_block(self, node):
+        node["classes"].append("highlight")
+        return super().visit_literal_block(node)
+
+    def stylesheet_call(self, *args, **kwargs):
+        return ""
+
+
+class SimpleWriter(Writer):
+    settings_spec = filter_settings_spec(
+        Writer.settings_spec,
+        "template",
+    )
+
+    def apply_template(self):
+        subs = self.interpolation_dict()
+        return "%(body)s\n" % subs
+
+    def __init__(self):
+        self.parts = {}
+        self.translator_class = SimpleTranslator
+
+
 def convert(input_config: str, input_myst: str, writer_name: str) -> dict:
     warning_stream = StringIO()
     try:
@@ -21,14 +47,22 @@ def convert(input_config: str, input_myst: str, writer_name: str) -> dict:
         {
             "output_encoding": "unicode",
             "warning_stream": warning_stream,
+            # to mimic the sphinx parser
+            "doctitle_xform": False,
+            "sectsubtitle_xform": False,
+            "initial_header_level": 1,
         }
     )
     try:
         output = publish_string(
             input_myst,
             parser=Parser(),
-            writer_name=writer_name,
             settings_overrides=settings,
+            **(
+                {"writer": SimpleWriter()}
+                if "html" in writer_name
+                else {"writer_name": writer_name}
+            ),
         )
     except Exception as exc:
         output = f"ERROR: conversion:\n{exc}\n{traceback.format_exc()}"
@@ -38,7 +72,7 @@ def convert(input_config: str, input_myst: str, writer_name: str) -> dict:
 version_label = document.querySelector("span#myst-version")
 config_textarea = document.querySelector("textarea#input_config")
 input_textarea = document.querySelector("textarea#input_myst")
-output_iframe = document.querySelector("iframe#output_html")
+output_iframe = document.querySelector("div#output_html")
 output_raw = document.querySelector("textarea#output_raw")
 warnings_textarea = document.querySelector("textarea#output_warnings")
 oformat_select = document.querySelector("select#output_format")
@@ -48,11 +82,9 @@ def do_convert(event=None):
     result = convert(config_textarea.value, input_textarea.value, oformat_select.value)
     output_raw.value = result["output"]
     if "html" in oformat_select.value:
-        output_iframe.contentDocument.body.innerHTML = result["output"]
+        output_iframe.innerHTML = result["output"]
     else:
-        output_iframe.contentDocument.body.innerHTML = (
-            "Change output format to HTML to see output"
-        )
+        output_iframe.innerHTML = "Change output format to HTML to see output"
     warnings_textarea.value = result["warnings"]
 
 
diff --git a/docs/syntax/admonitions.md b/docs/syntax/admonitions.md
new file mode 100644
index 0000000..510c4d6
--- /dev/null
+++ b/docs/syntax/admonitions.md
@@ -0,0 +1,132 @@
+# Admonitions
+
+Admonitions (also known as callouts) highlight a particular block of text,
+that exists slightly apart from the narrative of your page, such as a note or a warning.
+
+Admonitions are a special case of {{directive}} extensions.
+It is advised to use admonitions with the [colon_fence](#syntax/colon_fence) extension, which signify that the content of the block is also MyST Markdown.
+
+::::{myst-example}
+
+:::{tip}
+Let's give readers a helpful hint!
+:::
+
+::::
+
+## Admonition types
+
+The following core admonition types are available:
+
+```{myst-admonitions} attention, caution, danger, error, hint, important, note, seealso, tip, warning
+```
+
+These admonitions take no argument, but may be specified with options:
+
+:class: A space-separated list of CSS classes to add to the admonition.
+:name: A reference target for the admonition (see [cross-referencing](#syntax/referencing)).
+
+::::{myst-example}
+
+:::{tip}
+:class: myclass1,myclass2
+:name: a-tip-reference
+Let's give readers a helpful hint!
+:::
+
+[Reference to my tip](#a-tip-reference)
+
+::::
+
+Sphinx also adds a number of additional admonition types, for denoting changes to the documentation, or to the codebase:
+
+::::{myst-example}
+
+:::{versionadded} 1.2.3
+Explanation of the new feature.
+:::
+
+:::{versionchanged} 1.2.3
+Explanation of the change.
+:::
+
+:::{deprecated} 1.2.3
+Explanation of the deprecation.
+:::
+
+::::
+
+## Admonition titles
+
+To provide a custom title for an admonition, use the `admonition` directive.
+If you also want to style the admonition as one of the core admonition types,
+you can use the `admonition` directive with the `class` option.
+
+::::{myst-example}
+
+:::{admonition} My custom title with *Markdown*!
+:class: tip
+
+This is a custom title for a tip admonition.
+:::
+
+::::
+
+## Collapsible admonitions
+
+The [sphinx-togglebutton](https://sphinx-togglebutton.readthedocs.io) extension allows you to create collapsible admonitions, by adding a `dropdown` class to the admonition.
+
+::::{myst-example}
+
+:::{note}
+:class: dropdown
+
+This admonition has been collapsed,
+meaning you can add longer form content here,
+without it taking up too much space on the page.
+:::
+
+::::
+
+## Other Containers (grids, tabs, cards, etc.)
+
+Using the [colon_fence](#syntax/colon_fence) extension,
+content block can be wrapped in containers with a custom CSS class.
+
+::::{myst-example}
+:::bg-primary
+This is a container with a custom CSS class.
+
+- It can contain multiple blocks
+:::
+::::
+
+Using the [sphinx-design](https://github.com/executablebooks/sphinx-design) extension,
+it is also possible to create beautiful, screen-size responsive web-components.
+
+::::{myst-example}
+:::{card} Card Title
+Header
+^^^
+Card content
++++
+Footer
+:::
+::::
+
+
+::::::{myst-example}
+
+::::{tab-set}
+
+:::{tab-item} Label1
+Content 1
+:::
+
+:::{tab-item} Label2
+Content 2
+:::
+
+::::
+
+::::::
diff --git a/docs/syntax/code_and_apis.md b/docs/syntax/code_and_apis.md
new file mode 100644
index 0000000..771b843
--- /dev/null
+++ b/docs/syntax/code_and_apis.md
@@ -0,0 +1,251 @@
+(syntax/code-blocks)=
+# Source code and APIs
+
+## Basic block syntax highlighting
+
+Code blocks contain a language identifier, which is used to determine the language of the code.
+This language is used to determine the syntax highlighting, using an available [pygments lexer](https://pygments.org/docs/lexers/).
+
+:::{myst-example}
+```python
+from a import b
+c = "string"
+```
+:::
+
+::::{admonition} Adding a language lexer
+:class: tip dropdown
+You can create and register your own lexer, using the [`pygments.lexers` entry point](https://pygments.org/docs/plugins/#register-plugins),
+or within a sphinx extension, with the [`app.add_lexer` method](inv:sphinx#*.Sphinx.add_lexer).
+::::
+
+::::{admonition} Show backticks inside raw markdown blocks
+:class: tip dropdown
+
+If you'd like to show backticks inside of your markdown,
+you can do so by nesting them in backticks of a greater length.
+Markdown will treat the outer-most backticks as the edges of the "raw" block and everything inside will show up.
+For example:
+
+:::{myst-example}
+`` `hi` ``
+
+````
+```
+hi
+```
+````
+:::
+
+::::
+
+## Inline syntax highlighting
+
+The [attrs_inline](#syntax/attributes/inline) extension can be used to apply syntax highlighting to inline code:
+
+:::{myst-example}
+Inline Python code `a = "b"`{l=python}
+:::
+
+## Numbering and highlighting lines
+
+To set a global default for line numbering, per lexer name,
+the `myst_number_code_blocks` [configuration option](#sphinx/config-options) can be used.
+For example, using:
+
+```python
+myst_number_code_blocks = ["typescript"]
+```
+
+Will number all code blocks with the `typescript` lexer by default.
+
+:::{myst-example}
+```typescript
+type MyBool = true | false;
+
+interface User {
+  name: string;
+  id: number;
+}
+```
+:::
+
+To apply numbering and highlighting to a specific code block,
+the [attrs_block](#syntax/attributes/block) extension can be used:
+
+:::{myst-example}
+{lineno-start=1 emphasize-lines="2,3"}
+```python
+a = 1
+b = 2
+c = 3
+```
+:::
+
+## Adding a caption
+
+With the `code-block` {{directive}},
+a caption can be added to a code blocks, as well as other options:
+
+:::{myst-example}
+```{code-block} python
+:caption: This is a caption
+:emphasize-lines: 2,3
+:lineno-start: 1
+
+a = 1
+b = 2
+c = 3
+```
+:::
+
+The following options are recognized:
+
+:::{admonition} Code block options
+:class: hint dropdown
+
+`linenos` : flag
+: Enable to generate line numbers for the code block
+
+`lineno-start` : integer
+: The starting line number for the code block (`linenos` is automatically enabled)
+
+`emphasize-lines` : comma-separated list of integers
+: Highlight the specified lines
+
+`caption` : string
+: The caption for the code block
+
+`force` : flag
+: Allow minor errors on highlighting to be ignored
+
+`name` : string
+: The name of the code block, which can be referenced elsewhere in the document
+
+`class` : string
+: The class to apply to the code block
+
+```{seealso}
+The [Sphinx documentation](inv:sphinx#code-block)
+```
+
+:::
+
+(syntax/literalinclude)=
+## Including code from files
+
+Longer pieces of code can be included from files using the `literalinclude` {{directive}}:
+
+:::{myst-example}
+```{literalinclude} examples/example.py
+```
+:::
+
+The file name is usually relative to the current file’s path. However, if it is absolute (starting with `/`), it is relative to the top source directory.
+
+To select only a sub-section of the file, the `lines`, `pyobject` or `start-after` and `end-before` options can be used:
+
+:::{myst-example}
+```{literalinclude} examples/example.py
+:start-after: start example
+:end-before: end example
+```
+:::
+
+```{seealso}
+The [Sphinx documentation](inv:sphinx#literalinclude)
+```
+
+(syntax/apis)=
+## Documenting whole APIs
+
+Sphinx and MyST provide means to analyse source code and automatically generate documentation and referenceable links for APIs.
+
+`sphinx.ext.autodoc` can be used ([see below](#syntax/apis/sphinx-autodoc)), however, it is not inherently compatible with MyST Markdown, and so the `sphinx-autodoc2` extension is recommended.
+
+(syntax/apis/sphinx-autodoc2)=
+### `sphinx-autodoc2`
+
+[`sphinx-autodoc2`](https://sphinx-autodoc2.readthedocs.io) is an extension for Sphinx that provides an integrated means to document Python APIs.
+
+As opposed to `sphinx.ext.autodoc`, `sphinx-autodoc2` performs static (rather than dynamic) analysis of the source code, integrates full package documenting, and also allows for docstrings to be written in both RestructureText and MyST.
+
+The `auto_mode` will automatically generate the full API documentation, as shown <project:/apidocs/index.rst>.
+
+Alternatively, the `autodoc2-object` directive can be used to generate documentation for a single object.
+To embed in a MyST document the MyST `render_plugin` should be specified, for example:
+
+````{myst-example}
+```{autodoc2-object} myst_parser.sphinx_ext.main.setup_sphinx
+render_plugin = "myst"
+no_index = true
+```
+````
+
+This can be referenced elsewhere in the document using the `:py:obj:` role, or a `#` link (see [cross-referencing](#syntax/referencing)).
+
+````{myst-example}
+- {py:obj}`myst_parser.sphinx_ext.main.setup_sphinx`
+- [](#myst_parser.sphinx_ext.main.setup_sphinx)
+````
+
+Additionally, summaries of multiple objects can be generated using the `autodoc2-summary` directive:
+
+````{myst-example}
+```{autodoc2-summary}
+:renderer: myst
+
+~myst_parser.sphinx_ext.main.setup_sphinx
+~myst_parser.sphinx_ext.main.create_myst_config
+```
+````
+
+#### Using MyST docstrings
+
+`sphinx-autodoc2` can be configured to use MyST docstrings (rather than RestructureText), for the entire project or select objects, by setting the `autodoc2_docstring_parser_regexes` configuration option:
+
+```python
+autodoc2_docstring_parser_regexes = [
+    # this will render all docstrings as Markdown
+    (r".*", "myst"),
+    # this will render select docstrings as Markdown
+    (r"mypackage\.mymodule\..*", "myst"),
+]
+```
+
+For example:
+
+````{myst-example}
+```{autodoc2-object} myst_parser.setup
+render_plugin = "myst"
+no_index = true
+docstring_parser_regexes = [
+    ["myst_parser\\.setup", "myst"],
+]
+```
+````
+
+(syntax/apis/sphinx-autodoc)=
+### `sphinx.ext.autodoc`
+
+[Sphinx extension `autodoc`](inv:sphinx#sphinx.ext.autodoc) also can generate documentation for Python objects.
+However, because it is hard-coded to generate RestructureText, the special [`eval-rst` directive](#syntax/directives/parsing) needs to be used:
+
+````{myst-example}
+```{eval-rst}
+.. autofunction:: myst_parser.sphinx_ext.main.setup_sphinx
+    :noindex:
+```
+````
+
+Summaries can also be generated with [`autosummary`](inv:sphinx#sphinx.ext.autosummary):
+
+````{myst-example}
+```{eval-rst}
+.. autosummary::
+    :nosignatures:
+
+    myst_parser.sphinx_ext.main.setup_sphinx
+    myst_parser.sphinx_ext.main.create_myst_config
+```
+````
diff --git a/docs/syntax/cross-referencing.md b/docs/syntax/cross-referencing.md
new file mode 100644
index 0000000..c9e4770
--- /dev/null
+++ b/docs/syntax/cross-referencing.md
@@ -0,0 +1,440 @@
+(syntax/referencing)=
+# Cross-references
+
+MyST-Parser offers powerful cross-referencing features, to link to URLs, documents, headers, figures and more,
+that are **portable** across output formats and generate **warnings** when broken.
+
+This page covers the basics of setting up referenceable targets for content and how to reference them.
+
+(syntax/targets)=
+## Creating explicit targets
+
+Targets are used to define custom anchors that you can refer to elsewhere in your documentation.
+
+There are three primary ways to create targets:
+
+1. Annotating a syntax block with `(target)=`
+2. Annotating a syntax bloc/inline/span with an `{#id}` attribute (using the [attrs_block](#syntax/attributes/block) and [attrs_inline](#syntax/attributes/inline) extensions)
+3. Adding a `name` option to a directive
+
+::::{myst-example}
+
+(heading-target)=
+### Heading
+
+{#paragraph-target}
+This is a paragraph, with an `id` attribute.
+
+This is a [span with an `id` attribute]{#span-target}.
+
+:::{note}
+:name: directive-target
+
+This is a directive with a `name` option
+:::
+
+[reference1](#heading-target), [reference2](#paragraph-target),
+[reference3](#span-target), [reference4](#directive-target)
+
+::::
+
+There are also other ways to create targets, specific to certain directives,
+such as [glossaries](#syntax/glossaries) create targets for terms, and [code APIs](#syntax/apis) create targets for objects:
+
+::::{myst-example}
+{.glossary}
+my other term
+: Definition of the term
+
+[Link to a term](<#my other term>)
+
+```{py:class} mypackage.MyClass
+:nocontentsentry:
+Docstring content
+```
+
+[Link to a class](#mypackage.MyClass)
+::::
+
+:::{seealso}
+The [footnotes section](#syntax/footnotes), covers how to create and link to footnotes,
+and the [sphinxcontrib.bibtex](https://pypi.org/project/sphinxcontrib-bibtex/) extension provides a means to reference bibliographies.
+:::
+
+(syntax/implicit-targets)=
+## Implicit targets
+
+Whole documents can be referenced by path.
+Headings within documents can also be assigned an implicit target,
+by setting the `myst_heading_anchors` configuration option.
+This is should be set to an integer, between 1 and 6, indicating the depth of headings to assign targets to.
+
+The anchor "slugs" are created according to the [GitHub implementation](https://github.com/Flet/github-slugger): heading titles are lower cased, punctuation is removed, spaces are replaced with `-`, and uniqueness is enforced by suffix enumeration.
+
+For example, using `myst_heading_anchors = 2`:
+
+::::{myst-example}
+## A heading with slug
+
+## A heading with slug
+
+<project:#a-heading-with-slug>
+
+[Explicit title](#a-heading-with-slug-1)
+::::
+
+For more information see the [auto-generated header anchors](#syntax/header-anchors) section.
+
+:::{warning}
+In general, it is discouraged to rely on implicit targets,
+since they are easy to break, if for example a document/heading is moved or renamed.
+:::
+
+## Markdown link syntax
+
+Markdown links come in three forms:
+
+*Autolinks* are [URIs][uri] surrounded by `<` and `>`, which must always have a scheme:
+
+```md
+<scheme:path?query#fragment>
+```
+
+*Inline links* allow for optional explicit text and titles (in HTML titles are rendered as tooltips):
+
+```md
+[Explicit *Markdown* text](destination "optional explicit title")
+```
+
+or, if the destination contains spaces,
+
+```md
+[Explicit *Markdown* text](<a destination> "optional explicit title")
+```
+
+*Reference links* define the destination separately in the document, and can be used multiple times:
+
+```md
+[Explicit *Markdown* text][label]
+[Another link][label]
+
+[label]: destination "optional explicit title"
+```
+
+:::{seealso}
+The [CommonMark specification](https://spec.commonmark.org/0.30/#links)
+:::
+
+[uri]: https://en.wikipedia.org/wiki/Uniform_Resource_Identifier
+[url]: https://en.wikipedia.org/wiki/URL
+
+### Default destination resolution
+
+The destination of a link can resolve to either an **external** target,
+such as a [URL] to another website,
+or an **internal** target, such as a file, heading or figure within the same project.
+
+By default, MyST will resolve link destinations according to the following rules:
+
+1. Destination beginning with a scheme (e.g. `xxx:`), will be handled according to that scheme:
+
+   {style=lower-roman}
+   1. Destinations beginning with `project:` will be treated as internal references
+   2. Destinations beginning with `path:` will be treated as downloadable files
+   3. Destinations beginning with `inv:` will be treated as intersphinx references
+   4. Autolinks or destinations beginning with  `http:`, `https:`, `ftp:`, or `mailto:` will be treated as external [URL] links.
+
+2. Destinations which point to a local file path are treated as links to that file.
+
+   {style=lower-roman}
+   1. If the destination is a relative path, it is resolved relative to the current file.
+   2. If the destination is an absolute path (starts with `/`), it is resolved relative to the root of the project (i.e. the source directory).
+   3. If that path relates to another document in the project (e.g. a `.md` or `.rst` file), then it will link to the first heading in that document.
+   4. Links to project documents can also include a `#` fragment identifier, to link to a specific heading in that document.
+   5. If the path is to a non-source file (e.g. a `.png` or `.pdf` file), then the link will be to the file itself, e.g. to download it.
+
+3. Destinations beginning with `#` will be treated as internal references.
+
+   {style=lower-roman}
+   1. First, explicit targets in the same file are searched for, if not found
+   2. Then, implicit targets in the same file are searched for, if not found
+   3. Then, explicit targets across the whole project are searched for, if not found
+   4. Then, intersphinx references are searched for, if not found
+   5. A warning is emitted and the destination is left as an external link.
+
+:::{note}
+Local file path resolution and cross-project references are not available in [single page builds](#myst-docutils)
+:::
+
+### Explicit vs implicit link text
+
+If the link text is explicitly given, e.g. `[text](#dest)`, then the rendered text will be that.
+This text can contain nested inline markup, such as `[*emphasis*](#syntax/emphasis)`{l=md}.
+
+If no text is given or it is an auto-link, e.g. `[](#dest)` or `<project:#dest>`, then MyST will attempt to resolve an implicit text.
+For example, if the destination is a heading, then the heading text will be used as the link text,
+or if the destination is a figure/table then the caption will be used as the link text.
+Otherwise, the link text will be the destination itself.
+
+### Examples
+
+#### Autolinks
+
+:::{myst-example}
+
+:External URL: <https://example.com>
+:Internal target reference: <project:#cross-references>
+:Internal file reference: <project:../intro.md>
+:Internal file -> heading reference: <project:../intro.md#-get-started>
+:Downloadable file: <path:example.txt>
+:Intersphinx reference: <inv:sphinx:std#index>
+
+:::
+
+#### Inline links with implicit text
+
+:::{myst-example}
+
+:External URL: [](https://example.com)
+:Internal target reference: [](#cross-references)
+:Internal file reference: [](../intro.md)
+:Internal file -> heading reference: [](../intro.md#-get-started)
+:Downloadable file: [](example.txt)
+:Intersphinx reference: [](inv:sphinx:std#index)
+
+:::
+
+#### Inline links with explicit text
+
+:::{myst-example}
+
+:External URL: [Explicit text](https://example.com)
+:Internal target reference: [Explicit text](#cross-references)
+:Internal file reference: [Explicit text](../intro.md)
+:Internal file -> heading reference: [Explicit text](../intro.md#-get-started)
+:Downloadable file: [Explicit text](example.txt)
+:Intersphinx reference: [Explicit text](inv:sphinx:std#index)
+
+:::
+
+### Customising external URL resolution
+
+:::{versionadded} 0.19
+`myst_url_schemes` now allows for customising how the links are converted to URLs,
+and the `attrs_inline` extension can be used to specify certain links as external.
+:::
+
+By default, all links which begin with `http:`, `https:`, `ftp:`, or `mailto:` will be treated as external [URL] links.
+You can customise this behaviour in a number of ways using [configuration options](../configuration.md).
+
+Most simply, by setting the `myst_all_links_external` configuration option to `True`,
+all links will be treated as external [URL] links.
+
+To apply selectively to specific links, you can enable the [attrs_inline](syntax/attributes/inline) extension,
+then add an `external` class to the link.\
+For example, `[my-external-link](my-external-link){.external}` becomes [my-external-link](my-external-link){.external}.
+
+To specify a custom list of URL schemes, you can set the `myst_url_schemes` configuration option.
+By default this is set to `["http", "https", "ftp", "mailto"]`.
+
+As well as being a list of strings, `myst_url_schemes` can also be a dictionary,
+where the keys are the URL schemes, and the values define how the links are converted to URLs.
+This allows you to customise the conversion of links to URLs for specific schemes, for example:
+
+```python
+myst_url_schemes = {
+    "http": None,
+    "https": None,
+    "wiki": "https://en.wikipedia.org/wiki/{{path}}#{{fragment}}",
+    "doi": "https://doi.org/{{path}}",
+    "gh-issue": {
+        "url": "https://github.com/executablebooks/MyST-Parser/issue/{{path}}#{{fragment}}",
+        "title": "Issue #{{path}}",
+        "classes": ["github"],
+    },
+}
+```
+
+Allows for links such as:
+
+- `[URI](wiki:Uniform_Resource_Identifier#URI_references)` is converted to [URI](wiki:Uniform_Resource_Identifier#URI_references)
+- `<doi:10.1186/gm483>` is converted to <doi:10.1186/gm483>
+- `<gh-issue:639>` is converted to <gh-issue:639>
+
+:::{tip}
+You can also use the [sphinx-tippy](https://sphinx-tippy.readthedocs.io) extension to add rich "hover" tooltips to links.
+
+Adding the `github` class above integrates well the [pydata-sphinx-theme's GitHub link formatting](https://pydata-sphinx-theme.readthedocs.io/en/stable/user_guide/theme-elements.html#link-shortening-for-git-repository-services)
+:::
+
+The value of each scheme can be:
+
+- `None`: the link is converted directly to an external URL.
+- A string: the link is converted to an external URL using the string as a template.
+- A dictionary: the link is converted to an external URL using the dictionary’s `url` key as a template.
+  - The (optional) `title` key is a template for the link’s implicit title, i.e. it is used if the link has no explicit title.
+  - The (optional) `classes` key is a list of classes to add to the link.
+
+The templates for `url` and `title` can use variables (enclosed by `{{ }}`), which are substituted for the corresponding parts of the link `<scheme>://<netloc>/<path>;<params>?<query>#<fragment>` (or the full link using `uri`).
+For example:
+
+- `scheme`: the URL scheme, e.g. `wiki`.
+- `path`: the path part of the URL, e.g. `Uniform_Resource_Identifier`.
+- `fragment`: the fragment part of the URL, e.g. `URI_references`.
+
+(syntax/inv_links)=
+### Cross-project (intersphinx) links
+
+:::{versionadded} 0.19
+:::
+
+Each Sphinx HTML build creates a file named `objects.inv` that contains a mapping from referenceable objects to [URIs][uri] relative to the HTML set’s root.
+Each object is uniquely identified by a `domain`, `type`, and `name`.
+As well as the relative location, the object can also include implicit `text` for the reference (like the text for a heading).
+
+You can use the `myst-inv` command line tool (installed with `myst_parser`) to visualise and filter any remote URL or local file path to this inventory file (or its parent):
+
+```yaml
+# $ myst-inv https://www.sphinx-doc.org/en/master -n index
+name: Sphinx
+version: 6.2.0
+base_url: https://www.sphinx-doc.org/en/master
+objects:
+  rst:
+    role:
+      index:
+        loc: usage/restructuredtext/directives.html#role-index
+        text: null
+  std:
+    doc:
+      index:
+        loc: index.html
+        text: Welcome
+```
+
+To load external inventories into your Sphinx project, you must load the [`sphinx.ext.intersphinx` extension](inv:sphinx#usage/*/intersphinx), and set the `intersphinx_mapping` configuration option.
+
+```python
+extensions = ["myst_parser", "sphinx.ext.intersphinx"]
+intersphinx_mapping = {
+    "sphinx": ("https://www.sphinx-doc.org/en/master", None),
+}
+```
+
+:::{admonition} Docutils configuration
+:class: note dropdown
+
+Use the `docutils.conf` configuration file, for more details see [](myst-docutils).
+
+```ini
+[general]
+myst-inventories:
+  sphinx: ["https://www.sphinx-doc.org/en/master", null]
+```
+
+:::
+
+you can then reference inventory objects by prefixing the `inv` schema to the destination [URI]: `inv:key:domain:type#name`.
+
+`key`, `domain` and `type` are optional, e.g. for `inv:#name`, all inventories, domains and types will be searched, with a [warning emitted](myst-warnings) if multiple matches are found.
+
+Additionally, `*` is a wildcard which matches zero or characters, e.g. `inv:*:std:doc#a*` will match all `std:doc` objects in all inventories, with a `name` beginning with `a`.
+Note, to match to a literal `*` use `\*`.
+
+Here are some examples:
+
+:::{list-table}
+:header-rows: 1
+
+* - Type
+  - Syntax
+  - Rendered
+
+* - Autolink, full
+  - `<inv:sphinx:std:doc#index>`{l=myst}
+  - <inv:sphinx:std:doc#index>
+
+* - Link, full
+  - `[Sphinx](inv:sphinx:std:doc#index)`{l=myst}
+  - [Sphinx](inv:sphinx:std:doc#index)
+
+* - Autolink, no type
+  - `<inv:sphinx:std#index>`{l=myst}
+  - <inv:sphinx:std#index>
+
+* - Autolink, no domain
+  - `<inv:sphinx:*:doc#index>`{l=myst}
+  - <inv:sphinx:*:doc#index>
+
+* - Autolink, only name
+  - `<inv:#*.Sphinx>`{l=myst}
+  - <inv:#*.Sphinx>
+
+:::
+
+## Reference roles
+
+Sphinx offers numerous [roles for referencing](#usage/restructuredtext/roles) specific objects.
+
+These can also within MyST documents, although it is recommended to use the Markdown syntax where possible, which is more portable and native to MyST.
+
+:::{myst-example}
+- {ref}`syntax/referencing`, {ref}`Explicit text <syntax/referencing>`
+- {term}`my other term`
+- {doc}`../intro`, {doc}`Explicit text <../intro>`
+- {download}`example.txt`, {download}`Explicit text <example.txt>`
+- {py:class}`mypackage.MyClass`, {py:class}`Explicit text <mypackage.MyClass>`
+- {external:class}`sphinx.application.Sphinx`, {external:class}`Explicit text <sphinx.application.Sphinx>`
+- {external+sphinx:ref}`code-examples`, {external+sphinx:ref}`Explicit text <code-examples>`
+
+---
+
+- <project:#syntax/referencing>, [][syntax], [Explicit text][syntax]
+- [](<#my other term>)
+- <project:../intro.md>, [Explicit text](../intro.md)
+- <path:example.txt>, [Explicit text](example.txt)
+- <project:#mypackage.MyClass>, [Explicit text](#mypackage.MyClass)
+- <inv:#*Sphinx>, [Explicit text](#sphinx.application.Sphinx)
+- <inv:sphinx#code-examples>, [Explicit text](inv:sphinx#code-examples)
+
+[syntax]: #syntax/referencing
+:::
+
+## Handling invalid references
+
+When building your documentation, it is recommended to run in [nitpicky mode](inv:sphinx:std:confval#nitpicky), which will emit warnings for any invalid references.
+
+you may encounter warnings such as:
+
+```
+intro.md:1: WARNING: 'myst' cross-reference target not found: 'reference' [myst.xref_missing]
+
+intro.md:2: WARNING: Multiple matches found for 'duplicate': inter:py:module:duplicate, inter:std:label:duplicate [myst.iref_ambiguous]
+```
+
+To fully suppress a specific warning type, you can use the `suppress_warnings` configuration option, in Sphinx’s `conf.py` file:
+
+```python
+suppress_warnings = ["myst.xref_missing", "myst.iref_ambiguous"]
+```
+
+or in `docutils.conf` or [command-line tool](../docutils.md):
+
+```ini
+[general]
+myst-suppress-warnings = myst.xref_missing, myst.iref_ambiguous
+```
+
+In Sphinx specific reference warnings can also be suppressed, using the <inv:sphinx#nitpick_ignore> and <inv:sphinx#nitpick_ignore_regex> configuration options.
+
+```python
+nitpick_ignore = [("myst", "reference")]
+```
+
+To handle ambiguous references,
+for intersphinx references see the [](syntax/inv_links) section,
+or the domains searched for all Markdown references can be restricted globally or per-document using the [`myst_ref_domains` configuration](../configuration.md).
+
+```python
+myst_ref_domains = ["std", "py"]
+```
diff --git a/docs/syntax/example.txt b/docs/syntax/example.txt
index e84df8e..787a481 100644
--- a/docs/syntax/example.txt
+++ b/docs/syntax/example.txt
@@ -1,1 +1,3 @@
-Hallo!
+Hallo
+there
+you!
diff --git a/docs/syntax/examples/content_child1.md b/docs/syntax/examples/content_child1.md
new file mode 100644
index 0000000..4c36cfe
--- /dev/null
+++ b/docs/syntax/examples/content_child1.md
@@ -0,0 +1,7 @@
+:orphan:
+
+# Content child 1
+
+## Sub heading
+
+# Other
diff --git a/docs/syntax/examples/content_child2.md b/docs/syntax/examples/content_child2.md
new file mode 100644
index 0000000..f682c91
--- /dev/null
+++ b/docs/syntax/examples/content_child2.md
@@ -0,0 +1,5 @@
+:orphan:
+
+# Content child 2
+
+## Sub heading
diff --git a/docs/syntax/examples/example.py b/docs/syntax/examples/example.py
new file mode 100644
index 0000000..96f3772
--- /dev/null
+++ b/docs/syntax/examples/example.py
@@ -0,0 +1,15 @@
+"""An example Python file."""
+
+# start example
+class MyClass:
+    """An example class."""
+
+    def __init__(self, x: int, y: int):
+        """An example method."""
+        self.x = x
+        self.y = y
+
+
+# end example
+
+a = 1
diff --git a/docs/syntax/examples/example_relative_include.txt b/docs/syntax/examples/example_relative_include.txt
new file mode 100644
index 0000000..251b8d7
--- /dev/null
+++ b/docs/syntax/examples/example_relative_include.txt
@@ -0,0 +1,4 @@
+# My heading
+
+[](../typography.md)
+![alt](../img/fun-fish.png){w=50}
diff --git a/docs/syntax/glossary.md b/docs/syntax/glossary.md
new file mode 100644
index 0000000..f455049
--- /dev/null
+++ b/docs/syntax/glossary.md
@@ -0,0 +1,38 @@
+---
+orphan: true
+---
+
+# Glossary
+
+(units/length)=
+## Length Units
+
+The following length units are supported by the reStructuredText
+parser:
+
+* em (em unit, the element's font size)
+* ex (ex unit, x-height of the element’s font)
+* mm (millimeters; 1 mm = 1/1000 m)
+* cm (centimeters; 1 cm = 10 mm)
+* in (inches; 1 in = 2.54 cm = 96 px)
+* px (pixels, 1 px = 1/96 in)
+* pt (points; 1 pt = 1/72 in)
+* pc (picas; 1 pc = 1/6 in = 12 pt)
+
+This set corresponds to the length units in [CSS2] (a subset of length
+units in [CSS3]).
+
+The following are all valid length values: "1.5em", "20 mm", ".5in".
+
+Length values without unit are completed with a writer-dependent
+default (e.g. "px" with HTML, "pt" with `latex2e`).
+
+[CSS2]: http://www.w3.org/TR/CSS2/syndata.html#length-units
+[CSS3]: http://www.w3.org/TR/css-values-3/#absolute-lengths
+
+(units/percentage)=
+## Percentage Units
+
+Percentage values have a percent sign ("%") as unit.  Percentage
+values are relative to other values, depending on the context in which
+they occur.
diff --git a/docs/syntax/images_and_figures.md b/docs/syntax/images_and_figures.md
new file mode 100644
index 0000000..3fb093c
--- /dev/null
+++ b/docs/syntax/images_and_figures.md
@@ -0,0 +1,156 @@
+# Images and figures
+
+MyST Markdown can be used to include images and figures in your documents as well as referencing those images easily throughout your project.
+
+## Inline images
+
+The standard Markdown syntax for images is:
+
+:::{myst-example}
+![fishy](img/fun-fish.png)
+:::
+
+This will create an **inline** image, which is displayed in the flow of the text.
+
+The [attrs_inline](syntax/attributes/inline) extension can be used to add attributes to an inline image:
+
+:::{myst-example}
+![fishy](img/fun-fish.png){.bg-warning w=100px align=center}
+:::
+
+The [html_image](syntax/images/html) extension can also be used, to allow MyST to parse HTML image tags:
+
+:::{myst-example}
+:highlight: html
+
+<img src="img/fun-fish.png" alt="fishy" width="200px" class="bg-primary">
+:::
+
+## Block level images
+
+To create a **block** image, use the `image` directive:
+
+:::{myst-example}
+```{image} img/fun-fish.png
+:alt: fishy
+:class: bg-primary
+:width: 200px
+:align: center
+```
+:::
+
+The following options are recognized:
+
+:::{admonition} Image options
+:class: hint
+
+``alt`` : text
+: Alternate text: a short description of the image, displayed by
+  applications that cannot display images, or spoken by applications
+  for visually impaired users.
+
+``height`` : [length](units/length)
+: The desired height of the image.
+  Used to reserve space or scale the image vertically.
+  When the "scale" option is also specified, they are combined.
+  For example, a height of 200px and a scale of 50 is equivalent to a height of 100px with no scale.
+
+``width`` : [length](units/length) or [percentage](units/percentage) of the current line width
+: The width of the image.
+  Used to reserve space or scale the image horizontally.  As with "height"
+  above, when the "scale" option is also specified, they are combined.
+
+``scale`` : integer percentage (the "%" symbol is optional)
+: The uniform scaling factor of the image.  The default is "100 %", i.e.
+  no scaling.
+
+``align`` : "top", "middle", "bottom", "left", "center", or "right"
+: The values "top", "middle", and "bottom" control an image's vertical alignment
+: The values "left", "center", and "right" control an image's horizontal alignment,
+  allowing the image to float and have the text flow around it.
+
+``target`` : text (URI or reference name)
+: Makes the image into a hyperlink reference ("clickable").
+
+``class``
+: A space-separated list of CSS classes to add to the image.
+
+``name``
+: A reference target for the admonition (see [cross-referencing](#syntax/referencing)).
+
+:::
+
+## Figures (images with captions)
+
+To create a **figure**, use the `figure` directive:
+
+:::{myst-example}
+```{figure} img/fun-fish.png
+:scale: 50 %
+:alt: map to buried treasure
+
+This is the caption of the figure (a simple paragraph).
+
+The legend consists of all elements after the caption.  In this
+case, the legend consists of this paragraph and the following
+table:
+
+| Symbol | Meaning |
+| ------ | ------- |
+| :fish: | fishy   |
+
+```
+:::
+
+The "figure" directive supports all of the options of the "image" directive, as well as the following:
+
+:::{admonition} Figure options
+:class: hint
+
+figwidth : "image", [length](units/length) or [percentage](units/percentage) of current line width
+: The width of the figure.  If the value is "image", the width of the
+  image is used.  Otherwise, the value is interpreted as a length or
+  percentage of the current line width.
+
+figclass : text
+: A space-separated list of CSS classes to add to the figure (`class` are added to the image).
+
+:::
+
+:::::{seealso}
+
+See the <project:#syntax/md-figures> section for information on how to create figures that use native Markdown images.
+
+::::{myst-example}
+:::{figure-md}
+![fishy](img/fun-fish.png){width=200px}
+
+This is a caption in __*Markdown*__
+:::
+::::
+
+:::::
+
+## Figures with multiple images
+
+See the [sphinx-subfigure](https://sphinx-subfigure.readthedocs.io) extension for a way to create figures with multiple images.
+
+% TODO this can uncommented once https://github.com/mgaitan/sphinxcontrib-mermaid/issues/109 is fixed
+% ## Diagrams
+
+% It is possible to use [mermaid diagrams](https://mermaid-js.github.io/mermaid) using the `sphinxcontrib.mermaid` extension.
+
+% :::{myst-example}
+% ```{mermaid}
+% flowchart LR
+%   A[Jupyter Notebook] --> C
+%   B[MyST Markdown] --> C
+%   C(mystjs) --> D{AST}
+%   D <--> E[LaTeX]
+%   E --> F[PDF]
+%   D --> G[Word]
+%   D --> H[React]
+%   D --> I[HTML]
+%   D <--> J[JATS]
+% ```
+% :::
diff --git a/docs/syntax/math.md b/docs/syntax/math.md
new file mode 100644
index 0000000..16ceee6
--- /dev/null
+++ b/docs/syntax/math.md
@@ -0,0 +1,93 @@
+# Math and equations
+
+Math can be written in the common LaTeX markup.
+There are several syntaxes to define inline and block math,
+depending on your preference.
+
+## Math role and directive
+
+The `math` {{role}} and {{directive}} are used used to define inline and block math respectively.
+
+The directive supports multiple equations, which should be separated by a blank line.
+Each single equation can have multiple aligned lines, which should be separated by `\\` characters, and each line can have multiple `&` characters to align the equations.
+
+The `label` option can also be used to reference the equation later on, with the `eq` role.
+
+
+:::{myst-example}
+Since Pythagoras, we know that {math}`a^2 + b^2 = c^2`.
+
+```{math}
+:label: mymath
+(a + b)^2 = a^2 + 2ab + b^2
+
+(a + b)^2  &=  (a + b)(a + b) \\
+           &=  a^2 + 2ab + b^2
+```
+
+The equation {eq}`mymath` is a quadratic equation.
+:::
+
+
+:::{seealso}
+Sphinx documentation on the [role](inv:sphinx:rst:role#math) and [directive](inv:sphinx:rst:directive#math),
+and [math support for HTML outputs in Sphinx](inv:sphinx#math-support).
+:::
+
+## Dollar delimited math
+
+Enabling the [dollarmath](#syntax/math/dollar) extension will allow parsing the following syntax:
+
+- Inline math: `$...$`
+- Display (block) math: `$$...$$`
+
+Additionally if `myst_dmath_allow_labels=True` is set (the default):
+
+- Display (block) math with equation label: `$$...$$ (1)`
+
+
+:::{myst-example}
+:highlight: latex
+
+$$
+(a + b)^2  &=  (a + b)(a + b) \\
+           &=  a^2 + 2ab + b^2
+$$ (mymath2)
+
+The equation {eq}`mymath2` is also a quadratic equation.
+:::
+
+
+:::{admonition} Escaping Dollars
+:class: tip dropdown
+
+Math can be escaped (negated) by adding a `\` before the first symbol, e.g. `\$a$` renders as \$a\$.
+Escaping can also be used inside math, e.g. `$a=\$3$` renders as $a=\$3$.
+
+Conversely `\\` will negate the escaping, so `\\$a$` renders as \\$a$.
+:::
+
+## Direct LaTeX Math
+
+Enabling the [amsmath](#syntax/amsmath) extension will directly parse the following top-level math environments:
+
+> equation, multline, gather, align, alignat, flalign, matrix, pmatrix, bmatrix, Bmatrix, vmatrix, Vmatrix, eqnarray.
+
+As expected, environments ending in `*` will not be numbered, for example:
+
+:::{myst-example}
+:highlight: latex
+
+\begin{gather*}
+a_1=b_1+c_1\\
+a_2=b_2+c_2-d_2+e_2
+\end{gather*}
+
+\begin{align}
+a_{11}& =b_{11}&
+  a_{12}& =b_{12}\\
+a_{21}& =b_{21}&
+  a_{22}& =b_{22}+c_{22}
+\end{align}
+
+:::
diff --git a/docs/syntax/optional.md b/docs/syntax/optional.md
index 7d6bc01..416e144 100644
--- a/docs/syntax/optional.md
+++ b/docs/syntax/optional.md
@@ -36,7 +36,6 @@ myst_enable_extensions = [
     "fieldlist",
     "html_admonition",
     "html_image",
-    "inv_link",
     "linkify",
     "replacements",
     "smartquotes",
@@ -52,6 +51,8 @@ myst_enable_extensions = [
 :::
 
 (syntax/typography)=
+(syntax/smartquotes)=
+(syntax/replacements)=
 
 ## Typography
 
@@ -60,7 +61,7 @@ Adding `"smartquotes"` to `myst_enable_extensions` (in the {{ confpy }}) will au
 - `'single quotes'`: 'single quotes'
 - `"double quotes"`: "double quotes"
 
-Adding `"replacements"` to `myst_enable_extensions` (in the {{ confpy }}) will automatically convert some common typographic texts
+Adding `"replacements"` to `myst_enable_extensions` (in the {{ confpy }}) will automatically convert some common typographic texts:
 
 text  | converted
 ----- | ----------
@@ -108,6 +109,7 @@ These options enable their respective Markdown parser plugins, as detailed in th
 `myst_dmath_enable=True` and `myst_amsmath_enable=True` are deprecated, and replaced by `myst_enable_extensions = ["dollarmath", "amsmath"]`
 :::
 
+(syntax/math/dollar)=
 ### Dollar delimited math
 
 Enabling `dollarmath` will parse the following syntax:
@@ -127,7 +129,7 @@ This is equivalent to writing:
 ```
 
 :::{admonition} Escaping Dollars
-:class: tip
+:class: tip dropdown
 
 Math can be escaped (negated) by adding a `\` before the first symbol, e.g. `\$a$` renders as \$a\$.
 Escaping can also be used inside math, e.g. `$a=\$3$` renders as $a=\$3$.
@@ -138,44 +140,37 @@ Conversely `\\` will negate the escaping, so `\\$a$` renders as \\$a$.
 Block-level math can be specified with `$$` signs that wrap the math block you'd like to parse.
 For example:
 
-```latex
-$$
-    y    & = ax^2 + bx + c \\
-    f(x) & = x^2 + 2xy + y^2
-$$
-```
-
-becomes
+:::{myst-example}
+:highlight: latex
 
 $$
     y    & = ax^2 + bx + c \\
     f(x) & = x^2 + 2xy + y^2
 $$
+:::
 
 This is equivalent to the following directive:
 
-````md
+:::{myst-example}
+
 ```{math}
     y    & = ax^2 + bx + c \\
     f(x) & = x^2 + 2xy + y^2
 ```
-````
 
-You can also add labels to block equations:
+:::
 
-```latex
-$$
-e = mc^2
-$$ (eqn:best)
+You can also add labels to block equations:
 
-This is the best equation {eq}`eqn:best`
-```
+:::{myst-example}
+:highlight: latex
 
 $$
 e = mc^2
 $$ (eqn:best)
 
 This is the best equation {eq}`eqn:best`
+:::
 
 There are a few other options available to control dollar math parsing:
 
@@ -192,42 +187,78 @@ These options can both be useful if you also wish to use `$` as a unit of curren
 To allow display math (i.e. `$$`) within an inline context, set `myst_dmath_double_inline = True` (`False` by default).
 This allows for example:
 
-```latex
-Hence, for $\alpha \in (0, 1)$,
-$$
-  \mathbb P (\alpha \bar{X} \ge \mu) \le \alpha;
-$$
-i.e., $[\alpha \bar{X}, \infty)$ is a lower 1-sided $1-\alpha$ confidence bound for $\mu$.
-```
+:::{myst-example}
+:highlight: latex
 
 Hence, for $\alpha \in (0, 1)$,
 $$
   \mathbb P (\alpha \bar{X} \ge \mu) \le \alpha;
 $$
 i.e., $[\alpha \bar{X}, \infty)$ is a lower 1-sided $1-\alpha$ confidence bound for $\mu$.
+:::
 
 ### Math in other block elements
 
 Math will also work when nested in other block elements, like lists or quotes:
 
-```md
+:::{myst-example}
+
 - A list
 - $$ a = 1 $$
 
 > A block quote
 > $$ a = 1 $$
-```
+:::
+
+(syntax/amsmath)=
+
+### Direct LaTeX Math
+
+By adding `"amsmath"` to `myst_enable_extensions` (in the {{ confpy }}),
+you can enable direct parsing of [amsmath](https://ctan.org/pkg/amsmath) LaTeX equations.
+These top-level math environments will then be directly parsed:
+
+> equation, multline, gather, align, alignat, flalign, matrix, pmatrix, bmatrix, Bmatrix, vmatrix, Vmatrix, eqnarray.
+
+As expected, environments ending in `*` will not be numbered, for example:
+
+:::{myst-example}
+:highlight: latex
+
+\begin{gather*}
+a_1=b_1+c_1\\
+a_2=b_2+c_2-d_2+e_2
+\end{gather*}
+
+\begin{align}
+a_{11}& =b_{11}&
+  a_{12}& =b_{12}\\
+a_{21}& =b_{21}&
+  a_{22}& =b_{22}+c_{22}
+\end{align}
+
+:::
+
+:::{note}
+`\labels` inside the environment are not currently identified, and so cannot be referenced.
+We hope to implement this in a future update (see [executablebooks/MyST-Parser#202](https://github.com/executablebooks/MyST-Parser/issues/202))!
+:::
+
+This syntax will also work when nested in other block elements, like lists or quotes:
+
+:::{myst-example}
 
 - A list
-- $$ a = 1 $$
+- \begin{gather*}
+  a_1=b_1+c_1\\a_2=b_2+c_2-d_2+e_2
+  \end{gather*}
 
 > A block quote
-> $$ a = 1 $$
-
-### Direct LaTeX Math
+> \begin{gather*}
+  a_1=b_1+c_1\\a_2=b_2+c_2-d_2+e_2
+  \end{gather*}
 
-Want to use [amsmath](https://ctan.org/pkg/amsmath) LaTeX directly, with no dollars?
-See [the extended syntax option](syntax/amsmath).
+:::
 
 (syntax/mathjax)=
 ### Mathjax and math parsing
@@ -303,10 +334,8 @@ Keys in the front-matter will override ones in the `conf.py`.
 
 You can use these substitutions inline or as blocks, and you can even nest substitutions in other substitutions (but circular references are prohibited):
 
-::::{tab-set}
-:::{tab-item} Markdown Input
+:::{myst-example}
 
-```md
 Inline: {{ key1 }}
 
 Block level:
@@ -317,37 +346,19 @@ Block level:
 | -------- | -------- |
 | {{key2}} | {{key3}} |
 
-```
 
 :::
 
-:::{tab-item} Rendered Output
-Inline: {{ key1 }}
-
-Block level:
-
-{{ key2 }}
-
-| col1     | col2     |
-| -------- | -------- |
-| {{key2}} | {{key3}} |
-
-:::
-::::
-
 :::{important}
 
 Substitutions will only be assessed where you would normally use Markdown, e.g. not in code blocks:
 
-````
-```
-{{ key1 }}
-```
-````
+:::{myst-example}
 
 ```
 {{ key1 }}
 ```
+:::
 
 One should also be wary of using unsuitable directives for inline substitutions.
 This may lead to unexpected outcomes.
@@ -357,15 +368,11 @@ This may lead to unexpected outcomes.
 Substitution references are assessed as [Jinja2 expressions](http://jinja.palletsprojects.com) which can use [filters](https://jinja.palletsprojects.com/en/2.11.x/templates/#list-of-builtin-filters), and also contains the [Sphinx Environment](inv:sphinx#extdev/envapi) in the context (as `env`).
 Therefore you can do things like:
 
-```md
-- version: {{ env.config.version }}
-- docname: {{ env.docname | upper }}
-- {{ "a" + "b" }}
-```
-
+:::{myst-example}
 - version: {{ env.config.version }}
 - docname: {{ env.docname | upper }}
 - {{ "a" + "b" }}
+:::
 
 You can also change the delimiter if necessary, for example setting in the `conf.py`:
 
@@ -388,15 +395,12 @@ The exact logic for handling substitutions is:
 Substitutions cannot be directly used in URLs, such as `[a link](https://{{key4}}.com)` or `<https://{{key4}}.com>`.
 However, since Jinja2 substitutions allow for Python methods to be used, you can use string formatting or replacements:
 
-```md
-{{ '[a link](https://{}.com)'.format(key4) }}
-
-{{ '<https://myst-parser.readthedocs.io/en/latest/REPLACE.html>'.replace('REPLACE', env.docname) }}
-```
+:::{myst-example}
 
 {{ '[a link](https://{}.com)'.format(key4) }}
 
 {{ '<https://myst-parser.readthedocs.io/en/latest/REPLACE.html>'.replace('REPLACE', env.docname) }}
+:::
 
 (syntax/colon_fence)=
 
@@ -408,26 +412,7 @@ you can also use `:::` delimiters to denote directives, instead of ```` ``` ````
 Using colons instead of back-ticks has the benefit of allowing the content to be rendered correctly, when you are working in any standard Markdown editor.
 It is ideal for admonition type directives (as documented in [Directives](syntax/directives)) or tables with titles, for example:
 
-::::::{tab-set}
-:::::{tab-item} Markdown Input
-```md
-:::{note}
-This text is **standard** _Markdown_
-:::
-
-:::{table} This is a **standard** _Markdown_ title
-:align: center
-:widths: grid
-
-abc | mnp | xyz
---- | --- | ---
-123 | 456 | 789
-:::
-```
-
-:::::
-
-:::::{tab-item} Rendered Output
+:::::{myst-example}
 
 :::{note}
 This text is **standard** _Markdown_
@@ -443,17 +428,10 @@ abc | mnp | xyz
 :::
 
 :::::
-::::::
 
 Similar to normal directives, these directives can also be nested:
 
-```md
-::::{important}
-:::{note}
-This text is **standard** _Markdown_
-:::
-::::
-```
+:::::{myst-example}
 
 ::::{important}
 :::{note}
@@ -461,15 +439,11 @@ This text is **standard** _Markdown_
 :::
 ::::
 
+:::::
+
 and also parameter options can be used:
 
-```md
-:::{admonition} This *is* also **Markdown**
-:class: warning
-
-This text is **standard** _Markdown_
-:::
-```
+:::::{myst-example}
 
 :::{admonition} This *is* also **Markdown**
 :class: warning
@@ -477,6 +451,7 @@ This text is **standard** _Markdown_
 This text is **standard** _Markdown_
 :::
 
+:::::
 
 (syntax/admonitions)=
 
@@ -503,12 +478,17 @@ For example, the following configuration in `conf.py` tells the `myst_parser` to
 myst_heading_anchors = 3
 ```
 
-You can then insert markdown links directly to anchors that are generated from your header titles in your documentation.
-For example `[](#auto-generated-header-anchors)`: [](#auto-generated-header-anchors).
+You can then insert markdown links directly to anchors that are generated from your header titles in your documentation:
+
+:::{myst-example}
+[](#auto-generated-header-anchors)
+:::
 
-The paths to other files should be relative to the current file, for example
-`[**link text**](./syntax.md#core-syntax)`: [**link text**](./syntax.md#core-syntax).
+The paths to other files should be relative to the current file:
 
+:::{myst-example}
+[**link text**](./typography.md#headings)
+:::
 
 ### Anchor slug structure
 
@@ -552,26 +532,22 @@ Definition lists utilise the [markdown-it-py deflist plugin](inv:markdown_it#md/
 
 This syntax can be useful, for example, as an alternative to nested bullet-lists:
 
+:::{myst-example}
 - Term 1
   - Definition
 - Term 2
   - Definition
+:::
 
 Using instead:
 
-```md
-Term 1
-: Definition
-
-Term 2
-: Definition
-```
-
+:::{myst-example}
 Term 1
 : Definition
 
 Term 2
 : Definition
+:::
 
 From the Pandoc documentation:
 
@@ -582,6 +558,7 @@ From the Pandoc documentation:
 
 Here is a more complex example, demonstrating some of these features:
 
+:::{myst-example}
 Term *with Markdown*
 : Definition [with reference](syntax/definition-lists)
 
@@ -598,29 +575,7 @@ Term 3
 : A final definition, that can even include images:
 
   <img src="img/fun-fish.png" alt="fishy" width="200px">
-
-This was created from:
-
-```md
-Term *with Markdown*
-: Definition [with reference](syntax/definition-lists)
-
-  A second paragraph
-: A second definition
-
-Term 2
-  ~ Definition 2a
-  ~ Definition 2b
-
-Term 3
-:     A code block
-
-: > A quote
-
-: A final definition, that can even include images:
-
-  <img src="img/fun-fish.png" alt="fishy" width="200px">
-```
+:::
 
 (syntax/tasklists)=
 ## Task Lists
@@ -630,13 +585,10 @@ you will be able to utilise task lists.
 Task lists utilise the [markdown-it-py tasklists plugin](inv:markdown_it#md/plugins),
 and are applied to markdown list items starting with `[ ]` or `[x]`:
 
-```markdown
-- [ ] An item that needs doing
-- [x] An item that is complete
-```
-
+:::{myst-example}
 - [ ] An item that needs doing
 - [x] An item that is complete
+:::
 
 (syntax/fieldlists)=
 ## Field Lists
@@ -644,28 +596,12 @@ and are applied to markdown list items starting with `[ ]` or `[x]`:
 ```{versionadded} 0.16.0
 ```
 
+By adding `"fieldlist"` to `myst_enable_extensions` (in the {{ confpy }}),
+you will be able to utilise field lists.
 Field lists are mappings from field names to field bodies,
 based on the [reStructureText syntax](https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#field-lists).
 
-````md
-:name only:
-:name: body
-:*Nested syntax*: Both name and body may contain **nested syntax**.
-:Paragraphs: Since the field marker may be quite long, the second
-   and subsequent lines of a paragraph do not have to line up
-   with the first line.
-:Blocks:
-
-  As well as paragraphs, any block syntaxes may be used in a field body:
-
-  - Me
-  - Myself
-  - I
-
-  ```python
-  print("Hello, world!")
-  ```
-````
+:::{myst-example}
 
 :name only:
 :name: body
@@ -684,23 +620,11 @@ based on the [reStructureText syntax](https://docutils.sourceforge.io/docs/ref/r
   ```python
   print("Hello, world!")
   ```
+:::
 
 A prominent use case of field lists is for use in API docstrings, as used in [Sphinx's docstring renderers](inv:sphinx#python-domain):
 
-````md
-```{py:function} send_message(sender, priority)
-
-Send a message to a recipient
-
-:param str sender: The person sending the message
-:param priority: The priority of the message, can be a number 1-5
-:type priority: int
-:return: the message id
-:rtype: int
-:raises ValueError: if the message_body exceeds 160 characters
-```
-````
-
+:::{myst-example}
 ```{py:function} send_message(sender, priority)
 
 Send a message to a recipient
@@ -712,6 +636,7 @@ Send a message to a recipient
 :rtype: int
 :raises ValueError: if the message_body exceeds 160 characters
 ```
+:::
 
 :::{note}
 Currently `sphinx.ext.autodoc` does not support MyST, see [](howto/autodoc).
@@ -779,43 +704,20 @@ you can enable parsing of block attributes before certain block syntaxes.
 
 For example, the following Markdown:
 
-```markdown
-{#mypara .bg-warning}
-Here is a paragraph with attributes.
-
-{ref}`A reference to my paragraph <mypara>`
-```
-
-will be rendered as:
-
+:::{myst-example}
 {#mypara .bg-warning}
 Here is a paragraph with attributes.
 
 {ref}`A reference to my paragraph <mypara>`
+:::
 
 `id` and `class` are supported for most block syntaxes,
 but only certain key-value attributes are supported for each syntax.
 
-For **ordered lists**, the `style` key is supported, and can be one of `decimal`, `lower-alpha`, `upper-alpha`, `lower-roman`, `upper-roman`:
-
-```markdown
-{style=lower-alpha}
-1. a
-2. b
 
-{style=upper-alpha}
-1. a
-2. b
-
-{style=lower-roman}
-1. a
-2. b
-
-{style=upper-roman}
-1. a
-2. b
-```
+For **ordered lists**, the `style` key is supported, and can be one of `decimal`, `lower-alpha`, `upper-alpha`, `lower-roman`, `upper-roman`:
 
+:::{myst-example}
 {style=lower-alpha}
 1. a
 2. b
@@ -831,34 +733,35 @@ For **ordered lists**, the `style` key is supported, and can be one of `decimal`
 {style=upper-roman}
 1. a
 2. b
+:::
 
 For **code fences**, the `lineno-start` and `emphasize-lines` keys are supported:
 
-````md
-{lineno-start=1 emphasize-lines="2,3"}
-```python
-a = 1
-b = 2
-c = 3
-```
-````
-
+:::{myst-example}
 {lineno-start=1 emphasize-lines="2,3"}
 ```python
 a = 1
 b = 2
 c = 3
 ```
+:::
 
 For **block quotes**, the `attribution` key is supported:
 
-```markdown
+:::{myst-example}
 {attribution="Chris Sewell"}
 > Hallo
-```
+:::
 
-{attribution="Chris Sewell"}
-> Hallo
+For *definition lists*, the adding a glossary key turns the definition list into a glossary (similar to using the [`glossary` directive](inv:sphinx:rst:directive#glossary) in Sphinx):
+
+:::{myst-example}
+{.glossary}
+term name
+: Definition of the term
+
+{term}`term name`
+:::
 
 (syntax/attributes/inline)=
 ### Inline attributes
@@ -868,7 +771,7 @@ you can enable parsing of inline attributes after certain inline syntaxes.
 
 For example, the following Markdown:
 
-```md
+:::{myst-example}
 
 - [A span of text with attributes]{#spanid .bg-warning},
   {ref}`a reference to the span <spanid>`
@@ -884,23 +787,7 @@ For example, the following Markdown:
 - ![An image with attribute](img/fun-fish.png){#imgid .bg-warning w=100px align=center}
   {ref}`a reference to the image <imgid>`
 
-```
-
-will be parsed as:
-
-- [A span of text with attributes]{#spanid .bg-warning},
-  {ref}`a reference to the span <spanid>`
-
-- `A literal with attributes`{#literalid .bg-warning},
-  {ref}`a reference to the literal <literalid>`
-
-- An autolink with attributes: <https://example.com>{.bg-warning title="a title"}
-
-- [A link with attributes](syntax/attributes){#linkid .bg-warning},
-  {ref}`a reference to the link <linkid>`
-
-- ![An image with attribute](img/fun-fish.png){#imgid .bg-warning w="100px" align=center}
-  {ref}`a reference to the image <imgid>`
+:::
 
 `id` and `class` are supported for most inline syntaxes,
 but only certain key-value attributes are supported for each syntax.
@@ -917,6 +804,7 @@ For **images**, the following attributes are supported (equivalent to the `image
 - `height`/`h` defines the height of the image (in `px`, `em`, `cm`, etc)
 - `align`/`a` defines the scale of the image (`left`, `center`, or `right`)
 
+(syntax/images/html)=
 (syntax/images)=
 ## HTML Images
 
@@ -924,31 +812,23 @@ MyST provides a few different syntaxes for including images in your documentatio
 
 The first is the standard Markdown syntax:
 
-```md
-![fishy](img/fun-fish.png)
-```
-
+:::{myst-example}
 ![fishy](img/fun-fish.png)
+:::
 
 This will correctly copy the image to the build folder and will render it in all output formats (HTML, TeX, etc).
 However, it is limited in the configuration that can be applied, for example setting a width.
 
 As discussed [above](syntax/directives), MyST allow for directives to be used such as `image` and `figure` (see {ref}`the sphinx documentation <sphinx:rst-primer>`):
 
-````md
+:::{myst-example}
 ```{image} img/fun-fish.png
 :alt: fishy
 :class: bg-primary
 :width: 200px
 :align: center
 ```
-````
-
-```{image} img/fun-fish.png
-:alt: fishy
-:class: bg-primary mb-1
-:width: 200px
-```
+:::
 
 Additional options can now be set, however, in contrast to the Markdown syntax, this syntax will not show the image in common Markdown viewers (for example when the files are viewed on GitHub).
 
@@ -960,22 +840,21 @@ HTML parsing to the rescue!
 By adding `"html_image"` to `myst_enable_extensions` (in the {{ confpy }}),
 MySt-Parser will attempt to convert any isolated `img` tags (i.e. not wrapped in any other HTML) to the internal representation used in sphinx.
 
-```html
-<img src="img/fun-fish.png" alt="fishy" width="200px">
-<img src="img/fun-fish.png" alt="fishy" width="200px" class="bg-primary">
-```
+:::{myst-example}
+:highlight: html
 
 <img src="img/fun-fish.png" alt="fishy" width="200px">
 <img src="img/fun-fish.png" alt="fishy" width="200px" class="bg-primary">
+:::
 
-Allowed attributes are equivalent to the `image` directive: src, alt, class, width, height and name.
+Allowed attributes are equivalent to the `image` directive: `src`, `alt`, `class`, `width`, `height` and `name`.
 Any other attributes will be dropped.
 
 HTML image can also be used inline!
 
 I'm an inline image: <img src="img/fun-fish.png" height="20px">
 
-(syntax/figures)=
+(syntax/md-figures)=
 
 ## Markdown Figures
 
@@ -989,17 +868,15 @@ to create a fully Markdown compliant version of the `figure` directive named `fi
 
 The figure block must contain **only** two components; an image, in either Markdown or HTML syntax, and a single paragraph for the caption.
 
-The title is optional and taken as the reference target of the figure:
+The first line argument is optional and taken as the reference target of the figure:
 
-```md
-:::{figure-md} fig-target
-:class: myclass
+::::{myst-example}
 
-<img src="img/fun-fish.png" alt="fishy" class="bg-primary mb-1" width="200px">
+:::{figure-md}
+![fishy](img/fun-fish.png){.bg-primary .mb-1 width=200px}
 
 This is a caption in **Markdown**
 :::
-```
 
 :::{figure-md} fig-target
 :class: myclass
@@ -1009,13 +886,13 @@ This is a caption in **Markdown**
 This is a caption in **Markdown**
 :::
 
-As we see here, the target we set can be referenced:
+::::
 
-```md
-[Go to the fish!](fig-target)
-```
+As we see here, the target we set can be referenced:
 
-[Go to the fish!](fig-target)
+:::{myst-example}
+[Go to the fish!](#fig-target)
+:::
 
 (syntax/html-admonition)=
 
@@ -1029,51 +906,35 @@ This is helpful when you care about viewing the "source" Markdown, such as in Ju
 If the first element within the `div` is `<div class="title">` or `<p class="title">`, then this will be set as the admonition title.
 All internal text (and the title) will be parsed as MyST-Markdown and all classes and an optional name will be passed to the admonition:
 
-```html
-<div class="admonition note" name="html-admonition" style="background: lightgreen; padding: 10px">
-<p class="title">This is the **title**</p>
-This is the *content*
-</div>
-```
+:::{myst-example}
+:highlight: html
 
 <div class="admonition note" name="html-admonition" style="background: lightgreen; padding: 10px">
-<div class="title">This is the **title**</div>
+<p class="title">This is the **title**</p>
 This is the *content*
 </div>
+:::
 
 During the Sphinx render, both the `class` and `name` attributes will be used by Sphinx, but any other attributes like `style` will be discarded.
 
-:::{warning}
+::::{warning}
 There can be no empty lines in the block, otherwise they will be read as two separate blocks.
 If you want to use multiple paragraphs then they can be enclosed in `<p>`:
 
-```html
-<div class="admonition note">
-<p>Paragraph 1</p>
-<p>Paragraph 2</p>
-</div>
-```
-
+:::{myst-example}
+:highlight: html
 <div class="admonition note">
 <p>Paragraph 1</p>
 <p>Paragraph 2</p>
 </div>
-
 :::
 
-You can also nest HTML admonitions:
+::::
 
-```html
-<div class="admonition">
-<p>Some **content**</p>
-  <div class="admonition tip">
-  <div class="title">A *title*</div>
-  <p>Paragraph 1</p>
-  <p>Paragraph 2</p>
-  </div>
-</div>
-```
+You can also nest HTML admonitions:
 
+:::{myst-example}
+:highlight: html
 <div class="admonition">
 <p>Some **content**</p>
   <div class="admonition tip">
@@ -1082,74 +943,4 @@ You can also nest HTML admonitions:
   <p>Paragraph 2</p>
   </div>
 </div>
-
-(syntax/amsmath)=
-
-## Direct LaTeX Math
-
-By adding `"amsmath"` to `myst_enable_extensions` (in the {{ confpy }}),
-you can enable direct parsing of [amsmath](https://ctan.org/pkg/amsmath) LaTeX equations.
-These top-level math environments will then be directly parsed:
-
-> equation, multline, gather, align, alignat, flalign, matrix, pmatrix, bmatrix, Bmatrix, vmatrix, Vmatrix, eqnarray.
-
-As expected, environments ending in `*` will not be numbered, for example:
-
-```latex
-\begin{gather*}
-a_1=b_1+c_1\\
-a_2=b_2+c_2-d_2+e_2
-\end{gather*}
-
-\begin{align}
-a_{11}& =b_{11}&
-  a_{12}& =b_{12}\\
-a_{21}& =b_{21}&
-  a_{22}& =b_{22}+c_{22}
-\end{align}
-```
-
-\begin{gather*}
-a_1=b_1+c_1\\
-a_2=b_2+c_2-d_2+e_2
-\end{gather*}
-
-\begin{align}
-a_{11}& =b_{11}&
-  a_{12}& =b_{12}\\
-a_{21}& =b_{21}&
-  a_{22}& =b_{22}+c_{22}
-\end{align}
-
-:::{note}
-`\labels` inside the environment are not currently identified, and so cannot be referenced.
-We hope to implement this in a future update (see [executablebooks/MyST-Parser#202](https://github.com/executablebooks/MyST-Parser/issues/202))!
-:::
-
-:::{important}
-See also [how Mathjax is configured with MyST-Parser](syntax/mathjax).
 :::
-
-This syntax will also work when nested in other block elements, like lists or quotes:
-
-```md
-- A list
-- \begin{gather*}
-  a_1=b_1+c_1\\a_2=b_2+c_2-d_2+e_2
-  \end{gather*}
-
-> A block quote
-> \begin{gather*}
-  a_1=b_1+c_1\\a_2=b_2+c_2-d_2+e_2
-  \end{gather*}
-```
-
-- A list
-- \begin{gather*}
-  a_1=b_1+c_1\\a_2=b_2+c_2-d_2+e_2
-  \end{gather*}
-
-> A block quote
-> \begin{gather*}
-  a_1=b_1+c_1\\a_2=b_2+c_2-d_2+e_2
-  \end{gather*}
diff --git a/docs/syntax/organising_content.md b/docs/syntax/organising_content.md
new file mode 100644
index 0000000..cec9e55
--- /dev/null
+++ b/docs/syntax/organising_content.md
@@ -0,0 +1,199 @@
+
+(organising-content)=
+# Organising content
+
+Sphinx allows you to organise your content into multiple documents, and to include content from other documents.
+
+This section describes how to do this with MyST Markdown.
+
+(hiya)=
+## Document structure
+
+Single MyST Markdown documents are structured using [headings](typography.md#headings).
+
+All headings at the root level of the document are included in the Table of Contents (ToC) for that page.
+
+Many HTML themes will already include this ToC in a sidebar, but you can also include it in the main content of the page using the contents {{directive}}:
+
+:::{myst-example}
+```{contents} Table of Contents
+:depth: 3
+```
+:::
+
+Options:
+
+:depth: Can be used to specify the depth of the ToC.
+:local: Can be used to only include headings in the current section of the document.
+:backlinks: Can be used to include a link to the ToC at the end of each section.
+:class: Is available to add a custom CSS class to the ToC.
+
+:::::{warning}
+
+Because the structure of the document is determined by the headings, it is problematic to have "non-consecutive" headings in a document, such as:
+
+```md
+# Heading 1
+### Heading 3
+```
+
+If you wish to include such a heading, you can use the [attrs_block](#syntax/attributes/block) extension to wrap the heading in a `div`, so that it is not included in the ToC:
+
+```md
+# Heading 1
+:::
+### Heading 3
+:::
+```
+
+:::::
+
+
+:::::{admonition} Setting a title in front-matter
+:class: tip dropdown
+
+```{versionadded} 0.17.0
+```
+
+The `myst_title_to_header = True`{l=python} [configuration](#sphinx/config-options)
+allows for a `title` key to be present in the [document front matter](#syntax/frontmatter).
+
+This will then be used as the document's header (parsed as Markdown).
+For example:
+
+```md
+---
+title: My Title with *emphasis*
+---
+```
+
+would be equivalent to:
+
+```md
+# My Title with *emphasis*
+```
+
+:::::
+
+(organising-content/include)=
+## Inserting other documents directly into the current document
+
+The `include` directive allows you to insert the contents of another document directly into the flow of the current document.
+
+:::{seealso}
+The [`literalinclude` directive](#syntax/literalinclude), for including source code from files.
+:::
+
+:::{myst-example}
+```{literalinclude} example.txt
+```
+
+```{include} example.txt
+```
+:::
+
+The following options allow you to include only part of a document:
+
+:start-line: Only the content starting from this line number will be included (numbering starts at 1, and negative count from the end)
+:end-line: Only the content up to (but excluding) this line will be included.
+:start-after: Only the content after the first occurrence of the specified text will be included.
+:end-before: Only the content before the first occurrence of the specified text (but after any after text) will be included.
+
+:::{myst-example}
+```{literalinclude} example.txt
+```
+
+```{include} example.txt
+:start-line: 1
+:end-line: 2
+```
+
+```{include} example.txt
+:start-after: Hallo
+:end-before: you!
+```
+:::
+
+The following options allow you to modify the content of the included document,
+to make it relative to the location that it is being inserted:
+
+:heading-offset: Offset all the heading levels by this positive integer, e.g. changing `#` to `####`
+:relative-docs: Make Markdown file references, relative to the current document, if they start with a certain prefix
+:relative-images: Make Markdown image references, relative to the current document
+
+:::{myst-example}
+```{literalinclude} examples/example_relative_include.txt
+```
+
+```{include} examples/example_relative_include.txt
+:heading-offset: 3
+:relative-docs: ..
+:relative-images:
+```
+:::
+
+Additional options:
+:encoding: The text encoding of the external file
+
+::::{admonition} Including to/from reStructuredText files
+:class: tip dropdown
+
+As explained in [this section](#syntax/directives/parsing), all MyST directives will parse their content as Markdown.
+So to include rST, we must first "wrap" the directive in the [eval-rst directive](#syntax/directives/parsing):
+
+:::{myst-example}
+```{eval-rst}
+.. include:: ../faq/snippets/include-rst.rst
+```
+:::
+
+To include a MyST file within a ReStructuredText file, we can use the `parser` option of the `include` directive:
+
+```rst
+.. include:: include.md
+   :parser: myst_parser.sphinx_
+```
+
+:::{important}
+The `parser` option requires `docutils>=0.17`
+:::
+
+::::
+
+(syntax/toctree)=
+## Using `toctree` to include other documents as children
+
+To structure a project, with multiple documents, the [toctree directive](inv:sphinx:*:directive#toctree) is utilised.
+
+The designate documents as children of the current document,
+building up a nested hierarchy of documents starting from a [`root_doc`](inv:sphinx:*:confval#root_doc).
+
+:::{myst-example}
+```{toctree}
+examples/content_child1.md
+examples/content_child2.md
+```
+:::
+
+The `toctree` has options:
+
+:glob: Indicates that all entries are then matched against the list of available documents,
+    and matches are inserted into the list alphabetically
+
+The following options to control how it is displayed within the document:
+
+:caption: A title for this toctree
+:hidden: Do not show within the document
+:includehidden: Included child hidden `toctree` entries
+:maxdepth: The depth of document sub-headings shown
+:titlesonly: Only show the first top-level heading
+:reversed: Reverse the order of the entries in the list
+
+Additional options:
+
+:name: Allow the `toctree` to be referenced
+:numbered: Number all headings in children. If an integer is specified, then this is the depth to number down to
+
+:::{tip}
+Sub-toctrees are automatically numbered, so don’t give the `:numbered:` flag to those
+:::
diff --git a/docs/syntax/reference.md b/docs/syntax/reference.md
index 1e53b43..a4961ad 100644
--- a/docs/syntax/reference.md
+++ b/docs/syntax/reference.md
@@ -4,7 +4,7 @@
 This page serves as a reference for the syntax that makes of MyST Markdown.
 
 :::{seealso}
-For more description and explanation of MyST syntax, see the [syntax guide](syntax.md).
+For more description and explanation of MyST syntax, see the [syntax guide](typography.md).
 :::
 
 ## Block (Multi-line) Tokens
diff --git a/docs/syntax/roles-and-directives.md b/docs/syntax/roles-and-directives.md
index df76067..7c0fea8 100644
--- a/docs/syntax/roles-and-directives.md
+++ b/docs/syntax/roles-and-directives.md
@@ -30,10 +30,9 @@ header-rows: 1
   - reStructuredText
 * - ````md
     ```{directivename} arguments
-    ---
-    key1: val1
-    key2: val2
-    ---
+    :key1: val1
+    :key2: val2
+
     This is
     directive content
     ```
@@ -48,19 +47,13 @@ header-rows: 1
     ```
 `````
 
-For example, the following code:
-
-````md
-```{admonition} This is my admonition
-This is my note
-```
-````
-
-Will generate this admonition:
+For example:
 
+:::{myst-example}
 ```{admonition} This is my admonition
 This is my note
 ```
+:::
 
 #### Parameterizing directives
 
@@ -68,26 +61,28 @@ For directives that take parameters as input, there are two ways to parameterize
 In each case, the options themselves are given as `key: value` pairs. An example of
 each is shown below:
 
-**Using YAML frontmatter**. A block of YAML front-matter just after the
-first line of the directive will be parsed as options for the directive. 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:
+**Short-hand options with `:` characters**. If you only need one or two options for your
+directive and wish to save lines, you may also specify directive options as a collection
+of lines just after the first line of the directive, each preceding with `:`. Then the
+leading `:` is removed from each line, and the rest is parsed as YAML.
 
-````md
+:::{myst-example}
 ```{code-block} python
----
-lineno-start: 10
-emphasize-lines: 1, 3
-caption: |
-    This is my
-    multi-line caption. It is *pretty nifty* ;-)
----
+:lineno-start: 10
+:emphasize-lines: 1, 3
+
 a = 2
 print('my 1st line')
 print(f'my {a}nd line')
 ```
-````
+:::
+
+**Using YAML frontmatter**. A block of YAML front-matter just after the
+first line of the directive will be parsed as options for the directive. 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:
 
+:::{myst-example}
 ```{code-block} python
 ---
 lineno-start: 10
@@ -100,24 +95,7 @@ a = 2
 print('my 1st line')
 print(f'my {a}nd line')
 ```
-
-**Short-hand options with `:` characters**. If you only need one or two options for your
-directive and wish to save lines, you may also specify directive options as a collection
-of lines just after the first line of the directive, each preceding with `:`. Then the
-leading `:` is removed from each line, and the rest is parsed as YAML.
-
-For example:
-
-````md
-```{code-block} python
-:lineno-start: 10
-:emphasize-lines: 1, 3
-
-a = 2
-print('my 1st line')
-print(f'my {a}nd line')
-```
-````
+:::
 
 (syntax/directives/parsing)=
 
@@ -128,44 +106,24 @@ MyST parses this content **as Markdown**.
 
 This means that MyST markdown can be written in the content areas of any directives written in MyST markdown. For example:
 
-````md
-```{admonition} My markdown link
-Here is [markdown link syntax](https://jupyter.org)
-```
-````
-
+:::{myst-example}
 ```{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 parameter options are used (see below),
 you may start the content directly after the directive name.
 
-````md
-```{note} Notes require **no** arguments, so content can start here.
-```
-````
-
+:::{myst-example}
 ```{note} Notes require **no** arguments, so content can start here.
 ```
+:::
 
 For special cases, MySt also offers the `eval-rst` directive.
 This will parse the content **as ReStructuredText**:
 
-````md
-```{eval-rst}
-.. figure:: img/fun-fish.png
-  :width: 100px
-  :name: rst-fun-fish
-
-  Party time!
-
-A reference from inside: :ref:`rst-fun-fish`
-
-A reference from outside: :ref:`syntax/directives/parsing`
-```
-````
-
+:::{myst-example}
 ```{eval-rst}
 .. figure:: img/fun-fish.png
   :width: 100px
@@ -177,6 +135,7 @@ A reference from inside: :ref:`rst-fun-fish`
 
 A reference from outside: :ref:`syntax/directives/parsing`
 ```
+:::
 
 Note how the text is integrated into the rest of the document, so we can also reference [party fish](rst-fun-fish) anywhere else in the documentation.
 
@@ -186,43 +145,19 @@ You can nest directives by ensuring that the tick-lines corresponding to the
 outermost directive are longer than the tick-lines for the inner directives.
 For example, nest a warning inside a note block like so:
 
-`````md
-````{note}
-The next info should be nested
-```{warning}
-Here's my warning
-```
-````
-`````
-
-Here's how it looks rendered:
-
+:::{myst-example}
 ````{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:
 
-`````md
-````{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...
-    ```
-````
-`````
-
+:::{myst-example}
 ````{note}
 The warning block will be properly-parsed
 
@@ -236,9 +171,11 @@ But the next block will be parsed as raw text
     Here's my raw text warning that isn't parsed...
     ```
 ````
+:::
 
 This can really be abused if you'd like ;-)
 
+:::{myst-example}
 ``````{note}
 The next info should be nested
 `````{warning}
@@ -251,21 +188,18 @@ print('yep!')
 ````
 `````
 ``````
+:::
 
 #### Markdown-friendly directives
 
 Want to use syntax that renders correctly in standard Markdown editors?
 See [the extended syntax option](syntax/colon_fence).
 
-```md
-:::{note}
-This text is **standard** *Markdown*
-:::
-```
-
+::::{myst-example}
 :::{note}
 This text is **standard** *Markdown*
 :::
+::::
 
 (syntax/roles)=
 
@@ -288,37 +222,23 @@ header-rows: 1
     ```
 ````
 
-For example, the following code:
-
-```md
-Since Pythagoras, we know that {math}`a^2 + b^2 = c^2`
-```
-
-Becomes:
+For example:
 
+:::{myst-example}
 Since Pythagoras, we know that {math}`a^2 + b^2 = c^2`
+:::
 
 You can use roles to do things like reference equations and other items in
 your book. For example:
 
-````md
+:::{myst-example}
 ```{math} e^{i\pi} + 1 = 0
----
-label: euler
----
+:label: euler
 ```
 
 Euler's identity, equation {math:numref}`euler`, was elected one of the
 most beautiful mathematical formulas.
-````
-
-Becomes:
-
-```{math} e^{i\pi} + 1 = 0
----
-label: euler
----
-```
+:::
 
 Euler's identity, equation {math:numref}`euler`, was elected one of the
 most beautiful mathematical formulas.
@@ -337,75 +257,13 @@ For example, following the `ref` example above, if you pass a string like this:
 
 How roles parse this content depends on the author that created the role.
 
-## Common roles and directives
-
-:::{admonition} {material-regular}`engineering;1.5rem;sd-mr-1` Currently Under Construction
-:class: no-icon
-Check back for more...
-:::
-
-### ToC Trees
-
-```{doc-directive} contents
-Insert a table of contents tree of the documents headings.
-```
-
-```{doc-directive} toctree
-Inserts a Sphinx "Table of Contents" tree, containing a list of (relative) child document paths.
-```
-
-### Admonitions
-
-```{doc-directive} admonition
-Create a generic "callout" box, containing the content.
-```
-
-```{doc-directive} note
-Create a "callout" box, specific to notes, containing the content.
-```
-
-Other admonitions (same structure as `note`): `attention`, `caution`, `danger`, `error`, `hint`, `important`, `tip`, `warning`.
-
-Sphinx only: `deprecated`, `versionadded`, `versionchanged`.
-
-### Images and Figures
-
-```{doc-directive} image
-Insert an image, from a (relative) path or URL.
-```
-
-```{doc-directive} figure
-Insert an image, from a (relative) path or URL,
-with a caption (first paragraph), and optional legend (subsequent content).
-```
-
-```{doc-directive} table
-Insert a (MyST) table with a caption.
-```
-
-### Tables
-
-```{doc-directive} list-table
-Create a table from data in a uniform two-level bullet list.
-```
-
-```{doc-directive} csv-table
-Create a table from CSV (comma-separated values) data.
-```
-
-### Code
-
-```{doc-directive} code-block
-Syntax highlight a block of code, according to the language.
-```
-
 (syntax/roles/special)=
 
-### MyST only
+## MyST only roles
 
 This section contains information about special roles and directives that come bundled with the MyST Parser Sphinx extension.
 
-#### Insert the date and reading time
+### Insert the date and reading time
 
 ```{versionadded} 0.14.0
 The `sub-ref` role and word counting.
@@ -415,11 +273,9 @@ You may insert the "last updated" date and estimated reading time into your docu
 
 For example:
 
-```markdown
-> {sub-ref}`today` | {sub-ref}`wordcount-words` words | {sub-ref}`wordcount-minutes` min read
-```
-
+:::{myst-example}
 > {sub-ref}`today` | {sub-ref}`wordcount-words` words | {sub-ref}`wordcount-minutes` min read
+:::
 
 `today` is replaced by either the date on which the document is parsed, with the format set by <inv:sphinx#today_fmt>, or the `today` variable if set in the configuration file.
 
diff --git a/docs/syntax/syntax.md b/docs/syntax/syntax.md
deleted file mode 100644
index 2248a02..0000000
--- a/docs/syntax/syntax.md
+++ /dev/null
@@ -1,665 +0,0 @@
-(syntax/core)=
-
-# Core Syntax
-
-## Introduction
-
-MyST is a strict superset of the [CommonMark syntax specification](https://spec.commonmark.org/).
-It adds features focussed on scientific and technical documentation authoring, as detailed below.
-
-In addition, the roles and directives syntax provide inline/block-level extension points for plugins.
-This is detailed further in the [Roles and Directives](roles-directives) section.
-
-:::{seealso}
-The [syntax token reference tables](syntax-tokens)
-:::
-
-(syntax/commonmark)=
-
-## CommonMark
-
-The [CommonMark syntax specification](https://spec.commonmark.org/) details the full set of syntax rules.
-Here we provide a summary of most features:
-
-Element         | Syntax
---------------- | -------------------------------------------
-Heading         | `# H1` to `###### H6`
-Bold            | `**bold**`
-Italic          | `*italic*`
-Inline Code     | `` `code` ``
-Autolink        | `<https://www.example.com>`
-URL Link        | `[title](https://www.example.com)`
-Image           | `![alt](https://www.example.com/image.png)`
-Reference Link  | `[title][link]`
-Link Definition | `[link]: https://www.example.com`
-Thematic break  | `---`
-Blockquote      | `> quote`
-Ordered List    | `1. item`
-Unordered List  | `- item`
-Code Fence      | opening ```` ```lang ```` to closing ```` ``` ````
-
-:::{tip}
-The {ref}`attribute extensions <syntax/attributes>` allow you to enrich these syntaxes with additional information.
-:::
-
-(syntax/frontmatter)=
-
-## Front Matter
-
-This is a [YAML](https://en.wikipedia.org/wiki/YAML) block at the start of the document, as used for example in [jekyll](https://jekyllrb.com/docs/front-matter/).
-The document should start with three or more `---` markers, and YAML is parsed until a closing `---` marker is found:
-
-```yaml
----
-key1: value
-key2: [value1, value2]
-key3:
-  subkey1: value
----
-```
-
-:::{seealso}
-Top-matter is also used for the [substitution syntax extension](syntax/substitutions),
-and can be used to store information for blog posting (see [ablog's myst-parser support](https://ablog.readthedocs.io/en/latest/manual/markdown/)).
-:::
-
-### Setting a title
-
-```{versionadded} 0.17.0
-```
-
-If `myst_title_to_header` is set to `True`, and a `title` key is present in the front matter,
-then the title will be used as the document's header (parsed as Markdown).
-For example:
-
-```md
----
-title: My Title with *emphasis*
----
-```
-
-would be equivalent to:
-
-```md
-# My Title with *emphasis*
-```
-
-(syntax/html_meta)=
-
-### Setting HTML Metadata
-
-The front-matter can contain the special key `html_meta`; a dict with data to add to the generated HTML as [`<meta>` elements](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta).
-This is equivalent to using the [meta directive](inv:sphinx#html-meta).
-
-HTML metadata can also be added globally in the `conf.py` *via* the `myst_html_meta` variable, in which case it will be added to all MyST documents.
-For each document, the `myst_html_meta` dict will be updated by the document level front-matter `html_meta`, with the front-matter taking precedence.
-
-::::{tab-set}
-:::{tab-item} Sphinx Configuration
-
-```python
-language = "en"
-myst_html_meta = {
-    "description lang=en": "metadata description",
-    "description lang=fr": "description des métadonnées",
-    "keywords": "Sphinx, MyST",
-    "property=og:locale":  "en_US"
-}
-```
-
-:::
-
-:::{tab-item} MyST Front-Matter
-
-```yaml
----
-myst:
-  html_meta:
-    "description lang=en": "metadata description"
-    "description lang=fr": "description des métadonnées"
-    "keywords": "Sphinx, MyST"
-    "property=og:locale": "en_US"
----
-```
-
-:::
-
-:::{tab-item} RestructuredText
-
-```restructuredtext
-.. meta::
-   :description lang=en: metadata description
-   :description lang=fr: description des métadonnées
-   :keywords: Sphinx, MyST
-   :property=og:locale: en_US
-```
-
-:::
-
-:::{tab-item} HTML Output
-
-```html
-<html lang="en">
-  <head>
-    <meta content="metadata description" lang="en" name="description" xml:lang="en" />
-    <meta content="description des métadonnées" lang="fr" name="description" xml:lang="fr" />
-    <meta name="keywords" content="Sphinx, MyST">
-    <meta content="en_US" property="og:locale" />
-```
-
-:::
-::::
-
-(syntax/comments)=
-
-## 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 won't be parsed into the document:
-
-:::{myst-example}
-% my comment
-:::
-
-````{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
-% a comment
-another line
-````
-
-:::{tip}
-Comments are equivalent to the RST syntax: `.. my comment`.
-:::
-
-(syntax/blockbreaks)=
-
-## 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](https://jupyter.org/),
-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 won't be parsed into the document:
-
-```{myst-example}
-+++ some text
-```
-
-(syntax/referencing)=
-
-## Markdown Links and Referencing
-
-### CommonMark link format
-
-CommonMark links come in three forms ([see the spec](https://spec.commonmark.org/0.30/#links)):
-
-*Autolinks* are [URIs][uri] surrounded by `<` and `>`, which must always have a scheme:
-
-```md
-<scheme:path?query#fragment>
-```
-
-*Inline links* allow for optional explicit text and titles (in HTML titles are rendered as tooltips):
-
-```md
-[Explicit *Markdown* text](destination "optional explicit title")
-```
-
-or, if the destination contains spaces,
-
-```md
-[Explicit *Markdown* text](<a destination> "optional explicit title")
-```
-
-*Reference links* define the destination separately in the document, and can be used multiple times:
-
-```md
-[Explicit *Markdown* text][label]
-[Another link][label]
-
-[label]: destination "optional explicit title"
-```
-
-[uri]: https://en.wikipedia.org/wiki/Uniform_Resource_Identifier
-[url]: https://en.wikipedia.org/wiki/URL
-
-### Default destination resolution
-
-The destination of a link can resolve to either an **external** target, such as a [URL] to another website,
-or an **internal** target, such as a file, heading or figure within the same project.
-
-By default, MyST will resolve link destinations according to the following rules:
-
-1. All autolinks will be treated as external [URL] links.
-
-2. Destinations beginning with  `http:`, `https:`, `ftp:`, or `mailto:` will be treated as external [URL] links.
-
-3. Destinations which point to a local file path are treated as links to that file.
-   - The path must be relative and in [POSIX format](https://en.wikipedia.org/wiki/Path_(computing)#POSIX_and_Unix_paths) (i.e. `/` separators).
-   - If the path is to another source file in the project (e.g. a `.md` or `.rst` file),
-    then the link will be to the initial heading in that file or,
-    if the path is appended by a `#target`, to the heading "slug" in that file.
-   - If the path is to a non-source file (e.g. a `.png` or `.pdf` file),
-    then the link will be to the file itself, e.g. to download it.
-
-4. Destinations beginning with `#` will be treated as a link to a heading "slug" in the same file.
-   - This requires the `myst_heading_anchors` configuration be set.
-   - For more details see [](syntax/header-anchors).
-
-5. All other destinations are treated as internal references, which can link to any type of target within the project (see [](syntax/targets)).
-
-Here are some examples:
-
-:::{list-table}
-:header-rows: 1
-
-* - Type
-  - Syntax
-  - Rendered
-
-* - Autolink
-  - `<https://example.com>`
-  - <https://example.com>
-
-* - External URL
-  - `[example.com](https://example.com)`
-  - [example.com](https://example.com)
-
-* - Internal source file
-  - `[Source file](syntax.md)`
-  - [Source file](syntax.md)
-
-* - Internal non-source file
-  - `[Non-source file](example.txt)`
-  - [Non-source file](example.txt)
-
-* - Local heading
-  - `[Heading](#markdown-links-and-referencing)`
-  - [Heading](#markdown-links-and-referencing)
-
-* - Heading in another file
-  - `[Heading](optional.md#auto-generated-header-anchors)`
-  - [Heading](optional.md#auto-generated-header-anchors)
-
-:::
-
-### Customising external URL resolution
-
-:::{versionadded} 0.19
-`myst_url_schemes` now allows for customising how the links are converted to URLs,
-and the `attrs_inline` extension can be used to specify certain links as external.
-:::
-
-By default, all links which begin with `http:`, `https:`, `ftp:`, or `mailto:` will be treated as external [URL] links.
-You can customise this behaviour in a number of ways using [configuration options](../configuration.md).
-
-Most simply, by setting the `myst_all_links_external` configuration option to `True`,
-all links will be treated as external [URL] links.
-
-To apply selectively to specific links, you can enable the [attrs_inline](syntax/attributes/inline) extension,
-then add an `external` class to the link.\
-For example, `[my-external-link](my-external-link){.external}` becomes [my-external-link](my-external-link){.external}.
-
-To specify a custom list of URL schemes, you can set the `myst_url_schemes` configuration option.
-By default this is set to `["http", "https", "ftp", "mailto"]`.
-
-As well as being a list of strings, `myst_url_schemes` can also be a dictionary,
-where the keys are the URL schemes, and the values define how the links are converted to URLs.
-This allows you to customise the conversion of links to URLs for specific schemes, for example:
-
-```python
-myst_url_schemes = {
-    "http": None,
-    "https": None,
-    "wiki": "https://en.wikipedia.org/wiki/{{path}}#{{fragment}}",
-    "doi": "https://doi.org/{{path}}",
-    "gh-issue": {
-        "url": "https://github.com/executablebooks/MyST-Parser/issue/{{path}}#{{fragment}}",
-        "title": "Issue #{{path}}",
-        "classes": ["github"],
-    },
-}
-```
-
-Allows for links such as:
-
-- `[URI](wiki:Uniform_Resource_Identifier#URI_references)` is converted to [URI](wiki:Uniform_Resource_Identifier#URI_references)
-- `<doi:10.1186/gm483>` is converted to <doi:10.1186/gm483>
-- `<gh-issue:639>` is converted to <gh-issue:639>
-
-:::{tip}
-You can also use the [sphinx-tippy](https://sphinx-tippy.readthedocs.io) extension to add rich "hover" tooltips to links.
-
-Adding the `github` class above integrates well the [pydata-sphinx-theme's GitHub link formatting](https://pydata-sphinx-theme.readthedocs.io/en/stable/user_guide/theme-elements.html#link-shortening-for-git-repository-services)
-:::
-
-The value of each scheme can be:
-
-- `None`: the link is converted directly to an external URL.
-- A string: the link is converted to an external URL using the string as a template.
-- A dictionary: the link is converted to an external URL using the dictionary’s `url` key as a template.
-  - The (optional) `title` key is a template for the link’s implicit title, i.e. it is used if the link has no explicit title.
-  - The (optional) `classes` key is a list of classes to add to the link.
-
-The templates for `url` and `title` can use variables (enclosed by `{{ }}`), which are substituted for the corresponding parts of the link `<scheme>://<netloc>/<path>;<params>?<query>#<fragment>` (or the full link using `uri`).
-For example:
-
-- `scheme`: the URL scheme, e.g. `wiki`.
-- `path`: the path part of the URL, e.g. `Uniform_Resource_Identifier`.
-- `fragment`: the fragment part of the URL, e.g. `URI_references`.
-
-(syntax/inv_links)=
-### Cross-project (inventory) links
-
-:::{versionadded} 0.19
-This functionality is currently in *beta*.
-It is intended that eventually it will be part of the core syntax.
-:::
-
-Each Sphinx HTML build creates a file named `objects.inv` that contains a mapping from referenceable objects to [URIs][uri] relative to the HTML set’s root.
-Each object is uniquely identified by a `domain`, `type`, and `name`.
-As well as the relative location, the object can also include implicit `text` for the reference (like the text for a heading).
-
-You can use the `myst-inv` command line tool (installed with `myst_parser`) to visualise and filter any remote URL or local file path to this inventory file (or its parent):
-
-```yaml
-# $ myst-inv https://www.sphinx-doc.org/en/master -n index
-name: Sphinx
-version: 6.2.0
-base_url: https://www.sphinx-doc.org/en/master
-objects:
-  rst:
-    role:
-      index:
-        loc: usage/restructuredtext/directives.html#role-index
-        text: null
-  std:
-    doc:
-      index:
-        loc: index.html
-        text: Welcome
-```
-
-To load external inventories into your Sphinx project, you must load the [`sphinx.ext.intersphinx` extension](inv:sphinx#usage/*/intersphinx), and set the `intersphinx_mapping` configuration option.
-Then also enable the `inv_link` MyST extension e.g.:
-
-```python
-extensions = ["myst_parser", "sphinx.ext.intersphinx"]
-intersphinx_mapping = {
-    "sphinx": ("https://www.sphinx-doc.org/en/master", None),
-}
-myst_enable_extensions = ["inv_link"]
-```
-
-:::{dropdown} Docutils configuration
-
-Use the `docutils.conf` configuration file, for more details see [](myst-docutils).
-
-```ini
-[general]
-myst-inventories:
-  sphinx: ["https://www.sphinx-doc.org/en/master", null]
-myst-enable-extensions: inv_link
-```
-
-:::
-
-you can then reference inventory objects by prefixing the `inv` schema to the destination [URI]: `inv:key:domain:type#name`.
-
-`key`, `domain` and `type` are optional, e.g. for `inv:#name`, all inventories, domains and types will be searched, with a [warning emitted](myst-warnings) if multiple matches are found.
-
-Additionally, `*` is a wildcard which matches zero or characters, e.g. `inv:*:std:doc#a*` will match all `std:doc` objects in all inventories, with a `name` beginning with `a`.
-Note, to match to a literal `*` use `\*`.
-
-Here are some examples:
-
-:::{list-table}
-:header-rows: 1
-
-* - Type
-  - Syntax
-  - Rendered
-
-* - Autolink, full
-  - `<inv:sphinx:std:doc#index>`
-  - <inv:sphinx:std:doc#index>
-
-* - Link, full
-  - `[Sphinx](inv:sphinx:std:doc#index)`
-  - [Sphinx](inv:sphinx:std:doc#index)
-
-* - Autolink, no type
-  - `<inv:sphinx:std#index>`
-  - <inv:sphinx:std#index>
-
-* - Autolink, no domain
-  - `<inv:sphinx:*:doc#index>`
-  - <inv:sphinx:*:doc#index>
-
-* - Autolink, only name
-  - `<inv:#*.Sphinx>`
-  - <inv:#*.Sphinx>
-
-:::
-
-(syntax/targets)=
-
-## 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 [](syntax/header-anchors) section of extended syntaxes.
-
-:::
-
-Target headers are defined with this syntax:
-
-```md
-(header_target)=
-```
-
-They can then be referred to with the
-[`ref` inline role](inv:sphinx#ref-role):
-
-```md
-{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:
-
-```md
-{ref}`my text <header_target>`
-```
-
-For example, see this ref: {ref}`syntax/targets`, and here's a ref back to the top of this page: {ref}`my text <syntax/core>`.
-
-Alternatively using the markdown syntax:
-
-```md
-[my text](header_target)
-```
-
-is equivalent to using the [`any` inline role](inv:sphinx#any-role):
-
-```md
-{any}`my text <header_target>`
-```
-
-but can also accept "nested" syntax (like bold text) and will recognise document paths that include extensions (e.g. `syntax/syntax` or `syntax/syntax.md`)
-
-Using the same example, see this ref: [](syntax/targets), here is a reference back to the top of
-this page: [my text with **nested** $\alpha$ syntax](syntax/core), and here is a reference to another page (`[](../intro.md)`): [](../intro.md).
-
-```{note}
-If you wish to have the target's title inserted into your text, you can
-leave the "text" section of the markdown link empty. For example, this
-markdown: `[](syntax.md)` will result in: [](syntax.md).
-```
-
-(syntax/code-blocks)=
-## Code syntax highlighting
-
-Code blocks contain a language identifier, which is used to determine the language of the code.
-This language is used to determine the syntax highlighting, using an available [pygments lexer](https://pygments.org/docs/lexers/).
-
-
-:::{myst-example}
-```python
-from a import b
-c = "string"
-```
-:::
-
-You can create and register your own lexer, using the [`pygments.lexers` entry point](https://pygments.org/docs/plugins/#register-plugins),
-or within a sphinx extension, with the [`app.add_lexer` method](inv:sphinx#*.Sphinx.add_lexer).
-
-Using the `myst_number_code_blocks` configuration option, you can also control whether code blocks are numbered by line.
-For example, using `myst_number_code_blocks = ["typescript"]`:
-
-:::{myst-example}
-```typescript
-type MyBool = true | false;
-
-interface User {
-  name: string;
-  id: number;
-}
-```
-:::
-
-### Show backticks inside raw markdown blocks
-
-If you'd like to show backticks inside of your markdown, you can do so by nesting them
-in backticks of a greater length. Markdown will treat the outer-most backticks as the
-edges of the "raw" block and everything inside will show up. For example:
-
-:::{myst-example}
-`` `hi` ``
-
-````
-```
-hi
-```
-````
-:::
-
-## Tables
-
-Tables can be written using the standard [Github Flavoured Markdown syntax](https://github.github.com/gfm/#tables-extension-):
-
-:::{myst-example}
-```md
-| foo | bar |
-| --- | --- |
-| baz | bim |
-```
-:::
-
-Cells in a column can be aligned using the `:` character:
-
-:::{myst-example}
-```md
-| left | center | right |
-| :--- | :----: | ----: |
-| a    | b      | c     |
-```
-:::
-
-:::{note}
-
-Text is aligned by assigning `text-left`, `text-center`, or `text-right` to the cell.
-It is then necessary for the theme you are using to include the appropriate css styling.
-
-```html
-<table class="colwidths-auto table">
-  <thead>
-    <tr><th class="text-left head"><p>left</p></th></tr>
-  </thead>
-  <tbody>
-    <tr><td class="text-left"><p>a</p></td></tr>
-  </tbody>
-</table>
-```
-
-:::
-
-## Images
-
-MyST provides a few different syntaxes for including images in your documentation.
-
-The standard Markdown syntax is:
-
-:::{myst-example}
-![fishy](img/fun-fish.png)
-:::
-
-But you can also enable extended image syntaxes, to control attributes like width and captions.
-See the [extended image syntax guide](syntax/images).
-
-(syntax/footnotes)=
-## Footnotes
-
-Footnotes use the [pandoc specification](https://pandoc.org/MANUAL.html#footnotes).
-Their labels **start with `^`** and can then be any alphanumeric string (no spaces), which is case-insensitive.
-
-- If the label is an integer, then it will always use that integer for the rendered label (i.e. they are manually numbered).
-- For any other labels, they will be auto-numbered in the order which they are referenced, skipping any manually numbered labels.
-
-All footnote definitions are collected, and displayed at the bottom of the page (in the order they are referenced).
-Note that un-referenced footnote definitions will not be displayed.
-
-:::{myst-example}
-- This is a manually-numbered footnote reference.[^3]
-- This is an auto-numbered footnote reference.[^myref]
-
-[^myref]: This is an auto-numbered footnote definition.
-[^3]: This is a manually-numbered footnote definition.
-:::
-
-Any preceding text after a footnote definitions, which is
-indented by four or more spaces, will also be included in the footnote definition, and the text is rendered as MyST Markdown, e.g.
-
-:::{myst-example}
-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.
-:::
-
-````{important}
-Although footnote references can be used just fine within directives, e.g.[^myref],
-it is recommended that footnote definitions are not set within directives,
-unless they will only be referenced within that same directive:
-
-This is because, they may not be available to reference in text outside that particular directive.
-````
-
-By default, a transition line (with a `footnotes` class) will be placed before any footnotes.
-This can be turned off by adding `myst_footnote_transition = False` to the config file.
diff --git a/docs/syntax/tables.md b/docs/syntax/tables.md
new file mode 100644
index 0000000..3802111
--- /dev/null
+++ b/docs/syntax/tables.md
@@ -0,0 +1,200 @@
+# Tables
+
+## Markdown syntax
+
+Tables can be written using the standard [Github Flavoured Markdown syntax](https://github.github.com/gfm/#tables-extension-):
+
+:::{myst-example}
+| foo | bar |
+| --- | --- |
+| baz | bim |
+:::
+
+Cells in a column can be aligned using the `:` character:
+
+:::{myst-example}
+| left | center | right |
+| :--- | :----: | ----: |
+| a    | b      | c     |
+:::
+
+:::{admonition} Aligning cells in Sphinx HTML themes
+:class: tip dropdown
+
+Text is aligned by assigning `text-left`, `text-center`, or `text-right` to the cell.
+It is then necessary for the theme you are using to include the appropriate css styling.
+
+```html
+<table class="colwidths-auto table">
+  <thead>
+    <tr><th class="text-left head"><p>left</p></th></tr>
+  </thead>
+  <tbody>
+    <tr><td class="text-left"><p>a</p></td></tr>
+  </tbody>
+</table>
+```
+
+:::
+
+## Table with captions
+
+The `table` directive can be used to create a table with a caption:
+
+::::{myst-example}
+:::{table} Table caption
+:widths: auto
+:align: center
+
+| foo | bar |
+| --- | --- |
+| baz | bim |
+:::
+::::
+
+The following options are recognized:
+
+:::{admonition} List table options
+:class: hint
+
+`align` : "left", "center", or "right"
+: The horizontal alignment of the table.
+
+`width` : [length](units/length) or [percentage](units/percentage)
+: Sets the width of the table to the specified length or percentage of the line width.
+: If omitted, the renderer determines the width of the table based on its contents or the column widths.
+
+`widths` : "auto", "grid", or a list of integers
+: Explicitly set column widths. Specifies relative widths if used with the width option.
+: "auto" delegates the determination of column widths to the backend renderer.
+: "grid" determines column widths from the widths of the input columns (in characters).
+
+:::
+
+## List tables
+
+The `list-table` directive is used to create a table from data in a uniform two-level bullet list.
+"Uniform" means that each sublist (second-level list) must contain the same number of list items.
+
+::::{myst-example}
+:::{list-table} Frozen Delights!
+:widths: 15 10 30
+:header-rows: 1
+
+*   - Treat
+    - Quantity
+    - Description
+*   - Albatross
+    - 2.99
+    - On a stick!
+*   - Crunchy Frog
+    - 1.49
+    - If we took the bones out, it wouldn't be
+ crunchy, now would it?
+*   - Gannet Ripple
+    - 1.99
+    - On a stick!
+:::
+::::
+
+The following options are recognized:
+
+
+:::{admonition} List table options
+:class: hint
+
+`align` : "left", "center", or "right"
+: The horizontal alignment of the table.
+
+`header-rows` : integer
+: The number of rows of list data to use in the table header. Defaults to 0.
+
+`stub-columns` : integer
+: The number of table columns to use as stubs (row titles, on the left). Defaults to 0.
+
+`width` : [length](units/length) or [percentage](units/percentage)
+: Sets the width of the table to the specified length or percentage of the line width.
+: If omitted, the renderer determines the width of the table based on its contents or the column widths.
+
+`widths` : integer `[integer...]` or "auto"
+: A list of relative column widths. The default is equal-width columns (100%/#columns).
+: "auto" delegates the determination of column widths to the output builder.
+
+``class``
+: A space-separated list of CSS classes to add to the image.
+
+``name``
+: A reference target for the admonition (see [cross-referencing](#syntax/referencing)).
+
+:::
+
+## CSV tables
+
+The `csv-table` directive is used to create a table from Comma-Separated-Values data.
+
+:::{myst-example}
+```{csv-table} Frozen Delights!
+:header: >
+:    "Treat", "Quantity", "Description"
+:widths: 15, 10, 30
+
+"Albatross", 2.99, "On a stick!"
+"Crunchy Frog", 1.49, "If we took the bones out, it wouldn't be crunchy, now would it?"
+"Gannet Ripple", 1.99, "On a stick!"
+```
+:::
+
+The following options are recognized:
+
+:::{admonition} CSV table options
+:class: hint
+
+`align` : "left", "center", or "right"
+: The horizontal alignment of the table.
+
+`delim` : char | "tab" | "space"
+: A one-character string used to separate fields. Defaults to , (comma).
+  May be specified as a Unicode code point; see the unicode directive for syntax details.
+
+`encoding` : string
+: The text encoding of the external CSV data (file or URL).
+  Defaults to the document's input_encoding.
+
+`escape` : char
+: A one-character string used to escape the delimiter or quote characters. May be specified as a Unicode code point; see the unicode directive for syntax details. Used when the delimiter is used in an unquoted field, or when quote characters are used within a field. The default is to double-up the character, e.g. "He said, ""Hi!"""
+
+`file` : string (newlines removed)
+: The local filesystem path to a CSV data file.
+
+`header` : CSV data
+: Supplemental data for the table header, added independently of and before any header-rows from the main CSV data. Must use the same CSV format as the main CSV data.
+
+`header-rows` : integer
+: The number of rows of CSV data to use in the table header. Defaults to 0.
+
+`keepspace` : flag
+: Treat whitespace immediately following the delimiter as significant. The default is to ignore such whitespace.
+
+`quote` : char
+: A one-character string used to quote elements containing the delimiter or which start with the quote character. Defaults to " (quote). May be specified as a Unicode code point; see the unicode directive for syntax details.
+
+`stub-columns` : integer
+: The number of table columns to use as stubs (row titles, on the left). Defaults to 0.
+
+`url` : string (whitespace removed)
+: An Internet URL reference to a CSV data file.
+
+`widths` : integer, `[integer...]` or "auto"
+: A list of relative column widths. The default is equal-width columns (100%/#columns).
+: "auto" delegates the determination of column widths to the backend renderer.
+
+`width` : [length](units/length) or [percentage](units/percentage)
+: Sets the width of the table to the specified length or percentage of the line width. If omitted, the renderer determines the width of the table based on its contents or the column widths.
+
+``class``
+: A space-separated list of CSS classes to add to the image.
+
+``name``
+: A reference target for the admonition (see [cross-referencing](#syntax/referencing)).
+
+:::
diff --git a/docs/syntax/typography.md b/docs/syntax/typography.md
new file mode 100644
index 0000000..c6dbf8d
--- /dev/null
+++ b/docs/syntax/typography.md
@@ -0,0 +1,294 @@
+(syntax/core)=
+
+# Typography
+
+MyST is a strict superset of the [CommonMark syntax specification](https://spec.commonmark.org/).
+It adds features focussed on scientific and technical documentation authoring, as detailed below.
+
+## Headings
+
+Markdown syntax denotes headers starting with between 1 to 6 #.
+
+:::{myst-example}
+### Heading Level 3
+:::
+
+Note, that headings that are not at the root level of the document
+will not be included in the table of contents.
+Using the [attrs_block](#syntax/attributes/block) extension,
+you can also add classes to headings
+
+:::{myst-example}
+> {.bg-primary}
+> ### Paragraph heading
+:::
+
+:::{seealso}
+To structure single and multiple documents into table of contents, see the [organising content section](#organising-content).
+
+To reference a heading in your text, see the [cross-referencing section](#syntax/referencing).
+:::
+
+## Paragraphs
+
+Paragraphs are block of text separated by a blank line.
+
+Using the [attrs_block](#syntax/attributes/block) extension,
+you can also add classes to paragraphs:
+
+:::{myst-example}
+{.bg-primary}
+Here is a paragraph with a class to control its formatting.
+:::
+
+(syntax/blockbreaks)=
+
+## Thematic breaks
+
+You can create a thematic break, to break content between themes, using three or more `*`, `-`, or `_` characters on a line by themselves.
+
+:::{myst-example}
+:alt-output: <hr class="docutils">
+* * *
+:::
+
+## Inline Text Formatting
+
+Standard inline formatting including bold, italic, code, as well as escaped symbols and line breaks:
+
+:::{myst-example}
+**strong**, _emphasis_, `literal text`, \*escaped symbols\*
+:::
+
+The [strikethrough](syntax/strikethrough) extension allows you to add strike-through text:
+
+:::{myst-example}
+~~strikethrough with *emphasis*~~
+:::
+
+The [smartquotes](syntax/smartquotes) and [replacements](syntax/replacements) extensions can improve the typography of common symbols:
+
+
+:::{myst-example}
+Smart-quotes 'single quotes' and "double quotes".
+
++-, --, ---, ... and other replacements.
+:::
+
+Using the [attrs_inline](syntax/attributes/inline) extension,
+you can also add classes to inline text spans:
+
+:::{myst-example}
+A paragraph with a span of [text with attributes]{.bg-warning}
+:::
+
+## Line Breaks
+
+To put a line break, without a paragraph, use a `\` followed by a new line. This corresponds to a `<br>` in HTML and `\\` in LaTeX.
+
+:::{myst-example}
+Fleas \
+Adam \
+Had 'em.
+:::
+
+## Bullet points and numbered lists
+
+You can use bullet points and numbered lists as you would in standard Markdown.
+Starting a line with either a `-` or `*` for a bullet point, and `1.` for numbered lists.
+These lists can be nested using two spaces at the start of the line.
+
+:::{myst-example}
+- Lists can start with `-` or `*`
+  * My other, nested
+  * bullet point list!
+
+1. My numbered list
+2. has two points
+:::
+
+For numbered lists, you can start following lines with any number, meaning they don't have to be in numerical order, and this will not change the rendered output.
+The exception is the first number, which if it is not `1.` this will change the start number of the list.
+
+::::{admonition} Alternate numbering styles
+:class: tip dropdown
+
+Using the [attrs_block](#syntax/attributes/block) extension,
+you can also specify a alternative numbering styles:
+
+:::{myst-example}
+{style=lower-alpha}
+1. a
+2. b
+
+{style=upper-alpha}
+1. a
+2. b
+
+{style=lower-roman}
+1. a
+2. b
+
+{style=upper-roman}
+1. a
+2. b
+:::
+
+::::
+
+Using the [tasklist](syntax/tasklists) extension,
+you can also create task lists:
+
+:::{myst-example}
+- [ ] An item that needs doing
+- [x] An item that is complete
+:::
+
+## Subscript & Superscript
+
+For inline typography for subscript and superscript formatting,
+the `sub` and `sup` {{role}}, can be used respectively.
+
+:::{myst-example}
+H{sub}`2`O, and 4{sup}`th` of July
+:::
+
+
+## Quotations
+
+Quotations are controlled with standard Markdown syntax, by inserting a caret (>) symbol in front of one or more lines of text.
+
+:::{myst-example}
+> We know what we are, but know not what we may be.
+:::
+
+Using the [attrs_block](#syntax/attributes/block) extension,
+you can also add an `attribution` attribute to a block quote:
+
+:::{myst-example}
+{attribution="Hamlet act 4, Scene 5"}
+> We know what we are, but know not what we may be.
+:::
+
+(syntax/glossaries)=
+## Definition lists and glossaries
+
+Using the [definition lists](syntax/definition-lists) extension,
+you can define terms in your documentation, using the syntax:
+
+:::{myst-example}
+Term 1
+: Definition
+
+Term 2
+: Longer definition
+
+  With multiple paragraphs
+
+  - And bullet points
+
+:::
+
+Using the [attrs_block](#syntax/attributes/block) extension,
+you can also add a `glossary` class to a definition list, that will allow you to reference terms in your text using the [`term` role](syntax/roles):
+
+:::{myst-example}
+{.glossary}
+my term
+: Definition of the term
+
+{term}`my term`
+:::
+
+## Field lists
+
+Using the [field lists](syntax/fieldlists) extension,
+you can create field lists, which are useful in source code documentation (see [Sphinx docstrings](inv:sphinx#info-field-lists)):
+
+:::{myst-example}
+
+:param arg1: A description of arg1
+:param arg2: A longer description,
+    with multiple lines.
+
+    - And bullet points
+:return: A description of the return value
+
+:::
+
+(syntax/comments)=
+
+## 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 won't be parsed into the document:
+
+:::{myst-example}
+% my comment
+:::
+
+::::{admonition} Comments split paragraphs
+:class: warning dropdown
+
+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:
+
+:::{myst-example}
+a line
+% a comment
+another line
+:::
+
+::::
+
+(syntax/footnotes)=
+## Footnotes
+
+Footnotes use the [pandoc specification](https://pandoc.org/MANUAL.html#footnotes).
+Their labels **start with `^`** and can then be any alphanumeric string (no spaces), which is case-insensitive.
+
+- If the label is an integer, then it will always use that integer for the rendered label (i.e. they are manually numbered).
+- For any other labels, they will be auto-numbered in the order which they are referenced, skipping any manually numbered labels.
+
+All footnote definitions are collected, and displayed at the bottom of the page (in the order they are referenced).
+Note that un-referenced footnote definitions will not be displayed.
+
+:::{myst-example}
+- This is a manually-numbered footnote reference.[^3]
+- This is an auto-numbered footnote reference.[^myref]
+
+[^myref]: This is an auto-numbered footnote definition.
+[^3]: This is a manually-numbered footnote definition.
+:::
+
+Any preceding text after a footnote definitions, which is
+indented by four or more spaces, will also be included in the footnote definition, and the text is rendered as MyST Markdown, e.g.
+
+:::{myst-example}
+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.
+:::
+
+````{important}
+Although footnote references can be used just fine within directives, e.g.[^myref],
+it is recommended that footnote definitions are not set within directives,
+unless they will only be referenced within that same directive:
+
+This is because, they may not be available to reference in text outside that particular directive.
+````
+
+By default, a transition line (with a `footnotes` class) will be placed before any footnotes.
+This can be turned off by adding `myst_footnote_transition = False` to the config file.
diff --git a/myst_parser/__init__.py b/myst_parser/__init__.py
index 56dd460..ef35016 100644
--- a/myst_parser/__init__.py
+++ b/myst_parser/__init__.py
@@ -1,9 +1,12 @@
-"""An extended commonmark compliant parser, with bridges to docutils & sphinx."""
-__version__ = "0.18.1"
+"""An extended [CommonMark](https://spec.commonmark.org/) compliant parser,
+with bridges to [docutils](https://docutils.sourceforge.io/)
+and [Sphinx](https://github.com/sphinx-doc/sphinx).
+"""
+__version__ = "0.19.0"
 
 
 def setup(app):
-    """Initialize the Sphinx extension."""
+    """Initialize the [Sphinx](https://github.com/sphinx-doc/sphinx) extension."""
     from myst_parser.sphinx_ext.main import setup_sphinx
 
     setup_sphinx(app, load_parser=True)
diff --git a/myst_parser/_docs.py b/myst_parser/_docs.py
index 86544fd..7a39244 100644
--- a/myst_parser/_docs.py
+++ b/myst_parser/_docs.py
@@ -8,9 +8,11 @@ from docutils import nodes
 from docutils.frontend import OptionParser
 from docutils.parsers.rst import directives
 from sphinx.directives import other
+from sphinx.transforms.post_transforms import SphinxPostTransform
 from sphinx.util import logging
 from sphinx.util.docutils import SphinxDirective
 
+from myst_parser.parsers.docutils_ import to_html5_demo
 from ._compat import get_args, get_origin
 from .config.main import MdParserConfig
 from .parsers.docutils_ import Parser as DocutilsParser
@@ -19,6 +21,53 @@ from .warnings_ import MystWarnings
 LOGGER = logging.getLogger(__name__)
 
 
+class StripUnsupportedLatex(SphinxPostTransform):
+    """Remove unsupported nodes from the doctree."""
+
+    default_priority = 900
+
+    def run(self):
+        if self.app.builder.format != "latex":
+            return
+        from docutils import nodes
+
+        for node in self.document.findall():
+            if node.tagname == "image" and node["uri"].endswith(".svg"):
+                node.parent.replace(node, nodes.inline("", "Removed SVG image"))
+            if node.tagname == "mermaid":
+                node.parent.replace(node, nodes.inline("", "Removed Mermaid diagram"))
+
+
+class NumberSections(SphinxPostTransform):
+    """Number sections (html only)"""
+
+    default_priority = 710  # same as docutils.SectNum
+    formats = ("html",)
+
+    def run(self):
+        min_heading_level = 2
+        max_heading_level = 3
+        stack: list[tuple[list[int], nodes.Element]] = [([], self.document)]
+        while stack:
+            path, node = stack.pop()
+            if len(path) >= min_heading_level:
+                title = node[0]
+                text = (
+                    ".".join(str(i) for i in path[min_heading_level - 1 :])
+                    + "."
+                    + ("&nbsp;" * 2)
+                )
+                # docutils SectNum transform
+                title.insert(0, nodes.raw("", text, format="html"))
+                title["auto"] = 1
+            if len(path) < max_heading_level:
+                i = 0
+                for child in node.children:
+                    if isinstance(child, nodes.section):
+                        i += 1
+                        stack.append((path + [i], child))
+
+
 class _ConfigBase(SphinxDirective):
     """Directive to automate rendering of the configuration."""
 
@@ -58,7 +107,6 @@ class _ConfigBase(SphinxDirective):
 
 
 class MystConfigDirective(_ConfigBase):
-
     option_spec = {
         "sphinx": directives.flag,
         "extensions": directives.flag,
@@ -71,7 +119,6 @@ class MystConfigDirective(_ConfigBase):
         text = self.table_header()
         count = 0
         for name, value, field in config.as_triple():
-
             if field.metadata.get("deprecated"):
                 continue
 
@@ -227,16 +274,20 @@ class MystWarningsDirective(SphinxDirective):
 
 
 class MystExampleDirective(SphinxDirective):
-    """Directive to print an example."""
+    """Directive to create an example, showing the source and output."""
 
     has_content = True
     option_spec = {
-        "html": directives.flag,
+        "alt-output": directives.unchanged,
+        "highlight": directives.unchanged,
+        # "html": directives.flag,
     }
 
     def run(self):
         """Run the directive."""
         content_str = "\n".join(self.content)
+        output_str = self.options.get("alt-output", content_str)
+        highlight = self.options.get("highlight", "myst")
         backticks = "```"
         while backticks in content_str:
             backticks += "`"
@@ -244,15 +295,151 @@ class MystExampleDirective(SphinxDirective):
 {backticks}``{{div}} myst-example
 
 {backticks}`{{div}} myst-example-source
-{backticks}markdown
+{backticks}{highlight}
 {content_str}
 {backticks}
 {backticks}`
 {backticks}`{{div}} myst-example-render
-{content_str}
+
+{output_str}
 {backticks}`
 {backticks}``
 """
         node_ = nodes.Element()
         self.state.nested_parse(content.splitlines(), self.content_offset, node_)
         return node_.children
+
+
+class MystAdmonitionDirective(SphinxDirective):
+    """Directive to show a set of admonitions, in a tab set."""
+
+    required_arguments = 1
+    final_argument_whitespace = True
+
+    def run(self):
+        """Run the directive."""
+        types = [t.strip() for t in self.arguments[0].split(",")]
+        content = "::::{tab-set}"
+        for type_ in types:
+            content += f"""
+:::{{tab-item}} {type_}
+```{{{type_}}}
+This is a {type_}
+```
+:::
+"""
+        content += "::::"
+        node_ = nodes.Element()
+        self.state.nested_parse(content.splitlines(), self.content_offset, node_)
+        return node_.children
+
+
+class MystToHTMLDirective(SphinxDirective):
+    """Directive to convert MyST to HTML."""
+
+    has_content = True
+    optional_arguments = 1
+    final_argument_whitespace = True
+    option_spec = {
+        "extensions": directives.unchanged,
+    }
+
+    def run(self):
+        """Run the directive."""
+        content_str = "\n".join(self.content)
+        kwargs = {}
+        cli_opt = ""
+        if "extensions" in self.options:
+            ext = self.options["extensions"].split(",")
+            kwargs["myst_enable_extensions"] = ext
+            cli_opt += f"--myst-enable-extensions={self.options['extensions']}"
+        html = to_html5_demo(content_str, **kwargs)
+        content = f"""\
+::::myst-example
+```bash
+myst-docutils-demo example.md {cli_opt}
+```
+```myst
+{content_str}
+```
+```html
+{html}
+```
+::::
+"""
+        node_ = nodes.Element()
+        self.state.nested_parse(content.splitlines(), self.content_offset, node_)
+        return node_.children
+
+
+### MyST Lexer ###
+# TODO when some more work and testing, this should be made available publicly
+
+from pygments import token  # noqa: E402
+from pygments.lexer import bygroups, inherit, this, using  # noqa: E402
+from pygments.lexers.markup import MarkdownLexer  # noqa: E402
+
+
+class MystLexer(MarkdownLexer):
+    """A custom lexer for MyST Markdown."""
+
+    name = "MyST"
+    aliases = ["myst"]
+    filenames = ["*.myst"]
+    mimetypes = ["text/x-myst"]
+
+    tokens = {
+        "root": [
+            # (target)=
+            (
+                r"^(\()([^\n]+)(\)=)(\n)",
+                bygroups(
+                    token.Punctuation, token.Name.Label, token.Punctuation, token.Text
+                ),
+            ),
+            # :::
+            (r"^([\:]{3,})(\n)", bygroups(token.Punctuation, token.Text)),
+            # :::name other
+            # TODO this seems to "eat" the next line
+            # (r"^([\:]{3,})([^\s\n]+)(\s+)([^\n]+)(\n)",
+            # bygroups(token.Punctuation, token.Name.Tag, token.Whitespace, token.Text,token.Text)),
+            # :::name
+            (
+                r"^([\:]{3,})([^\n]+)(\n)",
+                bygroups(token.Punctuation, token.Name.Tag, token.Text),
+            ),
+            # :name: value
+            (
+                r"^(\:)([^\n\:]+)(\:)([^\n]+)(\n)",
+                bygroups(
+                    token.Punctuation,
+                    token.Generic.Strong,
+                    token.Punctuation,
+                    using(this, state="inline"),
+                    token.Text,
+                ),
+            ),
+            inherit,
+        ],
+        "inline": [
+            # escape (we have to copy this from the parent class)
+            (r"\\.", token.Text),
+            # {name}
+            (
+                r"(\{)([a-zA-Z0-9+:-]+)(\})",
+                bygroups(token.Punctuation, token.Operator.Word, token.Punctuation),
+            ),
+            # <http:example.com>
+            (
+                r"(<)(http|https|mailto|project|path|inv)(\:)([^\s>]+)(>)",
+                bygroups(
+                    token.Punctuation,
+                    token.String.Other,
+                    token.String.Other,
+                    token.Name.Label,
+                    token.Punctuation,
+                ),
+            ),
+            inherit,
+        ],
+    }
diff --git a/myst_parser/config/main.py b/myst_parser/config/main.py
index e1bec56..387131c 100644
--- a/myst_parser/config/main.py
+++ b/myst_parser/config/main.py
@@ -44,7 +44,6 @@ def check_extensions(inst: "MdParserConfig", field: dc.Field, value: Any) -> Non
             "fieldlist",
             "html_admonition",
             "html_image",
-            "inv_link",
             "linkify",
             "replacements",
             "smartquotes",
@@ -263,7 +262,7 @@ class MdParserConfig:
         default=False,
         metadata={
             "validator": instance_of(bool),
-            "help": "Convert a `title` field in the top-matter to a H1 header",
+            "help": "Convert a `title` field in the front-matter to a H1 header",
         },
     )
 
diff --git a/myst_parser/mdit_to_docutils/base.py b/myst_parser/mdit_to_docutils/base.py
index 9ec3e11..5b893cb 100644
--- a/myst_parser/mdit_to_docutils/base.py
+++ b/myst_parser/mdit_to_docutils/base.py
@@ -118,6 +118,7 @@ class DocutilsRenderer(RendererProtocol):
             "current_node",
             "reporter",
             "language_module_rst",
+            "_heading_offset",
             "_level_to_section",
         ):
             raise AttributeError(
@@ -142,6 +143,7 @@ class DocutilsRenderer(RendererProtocol):
         self.language_module_rst: ModuleType = get_language_rst(
             self.document.settings.language_code
         )
+        self._heading_offset: int = 0
         # a mapping of heading levels to its currently associated node
         self._level_to_section: dict[int, nodes.document | nodes.section] = {
             0: self.document
@@ -324,6 +326,7 @@ class DocutilsRenderer(RendererProtocol):
         lineno: int,
         inline: bool = False,
         temp_root_node: None | nodes.Element = None,
+        heading_offset: int = 0,
     ) -> None:
         """Render unparsed text (appending to the current node).
 
@@ -331,6 +334,7 @@ class DocutilsRenderer(RendererProtocol):
         :param lineno: the starting line number of the text, within the full source
         :param inline: whether the text is inline or block
         :param temp_root_node: If set, allow sections to be created as children of this node
+        :param heading_offset: offset heading levels by this amount
         """
         tokens = (
             self.md.parseInline(text, self.md_env)
@@ -347,22 +351,27 @@ class DocutilsRenderer(RendererProtocol):
             if token.map:
                 token.map = [token.map[0] + lineno, token.map[1] + lineno]
 
-        if temp_root_node is None:
-            self._render_tokens(tokens)
-        else:
-            # we need to temporarily set the root node,
-            # and we also want to restore the level_to_section mapping at the end
-            current_level_to_section = {
-                i: node for i, node in self._level_to_section.items()
-            }
-            current_root_node = self.md_env.get("temp_root_node", None)
-            try:
+        @contextmanager
+        def _restore():
+            current_heading_offset = self._heading_offset
+            self._heading_offset = heading_offset
+            if temp_root_node is not None:
+                # we need to temporarily set the root node,
+                # and we also want to restore the level_to_section mapping at the end
+                current_level_to_section = {
+                    i: node for i, node in self._level_to_section.items()
+                }
+                current_root_node = self.md_env.get("temp_root_node", None)
                 self.md_env["temp_root_node"] = temp_root_node
-                self._render_tokens(tokens)
-            finally:
+            yield
+            self._heading_offset = current_heading_offset
+            if temp_root_node is not None:
                 self.md_env["temp_root_node"] = current_root_node
                 self._level_to_section = current_level_to_section
 
+        with _restore():
+            self._render_tokens(tokens)
+
     @contextmanager
     def current_node_context(
         self, node: nodes.Element, append: bool = False
@@ -826,7 +835,7 @@ class DocutilsRenderer(RendererProtocol):
     def render_heading(self, token: SyntaxTreeNode) -> None:
         """Render a heading, e.g. `# Heading`."""
 
-        level = int(token.tag[1])
+        level = int(token.tag[1]) + self._heading_offset
 
         # sections are only allowed as a parent of a document or another section
         # the only exception to this, is if a directive has called a nested parse,
@@ -878,46 +887,49 @@ class DocutilsRenderer(RendererProtocol):
     def render_link(self, token: SyntaxTreeNode) -> None:
         """Parse `<http://link.com>` or `[text](link "title")` syntax to docutils AST:
 
-        - If `myst_all_links_external` is True, forward to `render_external_url`
+        - If `myst_all_links_external` is True, forward to `render_link_url`
         - If the link token has a class attribute containing `external`,
-            forward to `render_external_url`
-        - If the link is an id link (e.g. `#id`), forward to `render_id_link`
+            forward to `render_link_url`
+        - If the link is an id link (e.g. `#id`), forward to `render_link_anchor`
         - If the link has a schema, and the schema is in `url_schemes` (e.g. `http:`),
-          forward to `render_external_url`
-        - If the link has an `inv:` schema, and `inv_link` is enabled,
-          forward to `render_inventory_link`
-        - If the link is an autolink/linkify type link, forward to `render_external_url`
-        - Otherwise, forward to `render_internal_link`
+          forward to `render_link_url`
+        - If the link has an `inv:` schema, forward to `render_link_inventory`
+        - If the link is an autolink/linkify type link, forward to `render_link_url`
+        - Otherwise, forward to `render_link_internal`
         """
         if (
             self.md_config.commonmark_only
             or self.md_config.gfm_only
             or self.md_config.all_links_external
         ):
-            return self.render_external_url(token)
+            return self.render_link_url(token)
 
         if "class" in token.attrs and "external" in str(token.attrs["class"]).split():
-            return self.render_external_url(token)
+            return self.render_link_url(token)
 
         href = cast(str, token.attrGet("href") or "")
         if href.startswith("#"):
-            return self.render_id_link(token)
+            return self.render_link_anchor(token, href)
 
         scheme_match = REGEX_SCHEME.match(href)
         scheme = None if scheme_match is None else scheme_match.group(1)
         if scheme in self.md_config.url_schemes:
-            return self.render_external_url(token, self.md_config.url_schemes[scheme])
+            return self.render_link_url(token, self.md_config.url_schemes[scheme])
 
-        if scheme == "inv" and "inv_link" in self.md_config.enable_extensions:
-            return self.render_inventory_link(token)
+        if scheme == "inv":
+            return self.render_link_inventory(token)
+        if scheme == "path":
+            return self.render_link_path(token)
+        if scheme == "project":
+            return self.render_link_project(token)
 
         if token.info == "auto":
-            # handles both autolink and linkify, these are currently never internal
-            return self.render_external_url(token)
+            # handles both autolink and linkify
+            return self.render_link_url(token)
 
-        return self.render_internal_link(token)
+        return self.render_link_unknown(token)
 
-    def render_external_url(
+    def render_link_url(
         self, token: SyntaxTreeNode, conversion: None | UrlSchemeType = None
     ) -> None:
         """Render link token (including autolink and linkify),
@@ -977,21 +989,49 @@ class DocutilsRenderer(RendererProtocol):
             with self.current_node_context(ref_node, append=True):
                 self.render_children(token)
 
-    def render_id_link(self, token: SyntaxTreeNode) -> None:
-        """Render link token like `[text](#id)`, to a local target."""
+    def render_link_path(self, token: SyntaxTreeNode) -> None:
+        """Render a link token like `<path:...>`."""
+        self.create_warning(
+            "`path:` scheme not yet supported in docutils",
+            MystWarnings.NOT_SUPPORTED,
+            line=token_line(token, 0),
+            append_to=self.current_node,
+        )
+        return self.render_link_url(token)
+
+    def render_link_project(self, token: SyntaxTreeNode) -> None:
+        """Render a link token like `<project:...>`."""
+        destination = cast(str, token.attrGet("href") or "")
+        if destination.startswith("project:"):
+            destination = destination[8:]
+        if destination.startswith("#"):
+            return self.render_link_anchor(token, destination)
+        self.create_warning(
+            "`project:` scheme for file paths not yet supported in docutils",
+            MystWarnings.NOT_SUPPORTED,
+            line=token_line(token, 0),
+            append_to=self.current_node,
+        )
+        return self.render_link_url(token)
+
+    def render_link_anchor(self, token: SyntaxTreeNode, target: str) -> None:
+        """Render link token like `[text](#target)`, to a local target.
+
+        :target: the target id, e.g. `#target`
+        """
         ref_node = nodes.reference()
         self.add_line_and_source_path(ref_node, token)
         ref_node["id_link"] = True
-        ref_node["refuri"] = self.md.normalizeLinkText(str(token.attrGet("href") or ""))
+        ref_node["refuri"] = self.md.normalizeLinkText(target)
         self.copy_attributes(
             token, ref_node, ("class", "id", "reftitle"), aliases={"title": "reftitle"}
         )
         self.current_node.append(ref_node)
-        if token.info != "auto" and not is_ellipsis(token):
+        if token.info != "auto":
             with self.current_node_context(ref_node):
                 self.render_children(token)
 
-    def render_internal_link(self, token: SyntaxTreeNode) -> None:
+    def render_link_unknown(self, token: SyntaxTreeNode) -> None:
         """Render link token `[text](link "title")`,
         where the link has not been identified as an external URL::
 
@@ -1012,7 +1052,7 @@ class DocutilsRenderer(RendererProtocol):
         with self.current_node_context(ref_node, append=True):
             self.render_children(token)
 
-    def render_inventory_link(self, token: SyntaxTreeNode) -> None:
+    def render_link_inventory(self, token: SyntaxTreeNode) -> None:
         r"""Create a link to an inventory object.
 
         This assumes the href is of the form `<scheme>:<path>#<target>`.
@@ -1028,9 +1068,7 @@ class DocutilsRenderer(RendererProtocol):
         href = self.md.normalizeLinkText(cast(str, token.attrGet("href") or ""))
 
         # note if the link had explicit text or not (autolinks are always implicit)
-        explicit = (
-            (token.info != "auto") and bool(token.children) and not is_ellipsis(token)
-        )
+        explicit = (token.info != "auto") and bool(token.children)
 
         # split the href up into parts
         uri_parts = urlparse(href)
@@ -1098,7 +1136,7 @@ class DocutilsRenderer(RendererProtocol):
         elif match.text:
             ref_node.append(nodes.Text(match.text))
         else:
-            ref_node.append(nodes.Text(match.name))
+            ref_node.append(nodes.literal(match.name, match.name))
 
     def get_inventory_matches(
         self,
@@ -1667,6 +1705,7 @@ class DocutilsRenderer(RendererProtocol):
             # to allow for altering relative image reference links
             directive_class.option_spec["relative-images"] = directives.flag
             directive_class.option_spec["relative-docs"] = directives.path
+            directive_class.option_spec["heading-offset"] = directives.nonnegative_int
 
         try:
             parsed = parse_directive_text(directive_class, first_line, content)
@@ -1928,12 +1967,3 @@ def compute_unique_slug(
         slug = f"{slug}-{i}"
         i += 1
     return slug
-
-
-def is_ellipsis(token: SyntaxTreeNode) -> bool:
-    """Check if a token content only contains an ellipsis."""
-    return (
-        len(token.children) == 1
-        and token.children[0].type == "text"
-        and token.children[0].content in ("...", "…")
-    )
diff --git a/myst_parser/mdit_to_docutils/sphinx_.py b/myst_parser/mdit_to_docutils/sphinx_.py
index 4e7aee1..71942af 100644
--- a/myst_parser/mdit_to_docutils/sphinx_.py
+++ b/myst_parser/mdit_to_docutils/sphinx_.py
@@ -4,7 +4,6 @@ from __future__ import annotations
 import os
 from pathlib import Path
 from typing import cast
-from urllib.parse import unquote
 from uuid import uuid4
 
 from docutils import nodes
@@ -16,7 +15,8 @@ from sphinx.ext.intersphinx import InventoryAdapter
 from sphinx.util import logging
 
 from myst_parser import inventory
-from myst_parser.mdit_to_docutils.base import DocutilsRenderer, is_ellipsis
+from myst_parser.mdit_to_docutils.base import DocutilsRenderer, token_line
+from myst_parser.warnings_ import MystWarnings
 
 LOGGER = logging.getLogger(__name__)
 
@@ -32,21 +32,103 @@ class SphinxRenderer(DocutilsRenderer):
     def sphinx_env(self) -> BuildEnvironment:
         return self.document.settings.env
 
-    def render_internal_link(self, token: SyntaxTreeNode) -> None:
-        """Render link token `[text](link "title")`,
-        where the link has not been identified as an external URL.
-        """
-        destination = unquote(cast(str, token.attrGet("href") or ""))
+    def _process_wrap_node(
+        self,
+        wrap_node: nodes.Element,
+        token: SyntaxTreeNode,
+        explicit: bool,
+        classes: list[str],
+        path_dest: str,
+    ):
+        """Process a wrap node, which is a node that wraps a link."""
+        self.add_line_and_source_path(wrap_node, token)
+        self.copy_attributes(token, wrap_node, ("class", "id", "title"))
+        self.current_node.append(wrap_node)
 
-        # make the path relative to an "including" document
-        # this is set when using the `relative-docs` option of the MyST `include` directive
+        if explicit:
+            inner_node = nodes.inline("", "", classes=classes)
+            with self.current_node_context(inner_node):
+                self.render_children(token)
+        elif isinstance(wrap_node, addnodes.download_reference):
+            inner_node = nodes.literal(path_dest, path_dest, classes=classes)
+        else:
+            inner_node = nodes.inline("", "", classes=classes)
+
+        wrap_node.append(inner_node)
+
+    def _handle_relative_docs(self, destination: str) -> str:
+        """Make the path relative to an "including" document
+
+        This is set when using the `relative-docs` option of the MyST `include` directive
+        """
         relative_include = self.md_env.get("relative-docs", None)
         if relative_include is not None and destination.startswith(relative_include[0]):
             source_dir, include_dir = relative_include[1:]
             destination = os.path.relpath(
                 os.path.join(include_dir, os.path.normpath(destination)), source_dir
             )
-        explicit = len(token.children or []) > 0 and not is_ellipsis(token)
+        return destination
+
+    def render_link_project(self, token: SyntaxTreeNode) -> None:
+        destination = cast(str, token.attrGet("href") or "")
+        if destination.startswith("project:"):
+            destination = destination[8:]
+        if destination.startswith("#"):
+            return self.render_link_anchor(token, destination)
+
+        if not self.sphinx_env.srcdir:  # not set in some test situations
+            return self.render_link_url(token)
+
+        destination = self.md.normalizeLinkText(destination)
+        destination = self._handle_relative_docs(destination)
+        path_dest, *_path_ids = destination.split("#", maxsplit=1)
+        path_id = _path_ids[0] if _path_ids else None
+        explicit = (token.info != "auto") and (len(token.children or []) > 0)
+        _, abs_path = self.sphinx_env.relfn2path(path_dest, self.sphinx_env.docname)
+        docname = self.sphinx_env.path2doc(abs_path)
+        if not docname:
+            self.create_warning(
+                f"Could not find document: {abs_path}",
+                MystWarnings.XREF_MISSING,
+                line=token_line(token, 0),
+                append_to=self.current_node,
+            )
+            return self.render_link_url(token)
+        wrap_node = addnodes.pending_xref(
+            refdomain="doc",
+            reftarget=docname,
+            reftargetid=path_id,
+            refdoc=self.sphinx_env.docname,
+            reftype="myst",
+            refexplicit=explicit,
+        )
+        classes = ["xref", "myst"]
+        self._process_wrap_node(wrap_node, token, explicit, classes, destination)
+
+    def render_link_path(self, token: SyntaxTreeNode) -> None:
+        destination = self.md.normalizeLinkText(cast(str, token.attrGet("href") or ""))
+        if destination.startswith("path:"):
+            destination = destination[5:]
+        destination = self._handle_relative_docs(destination)
+        explicit = (token.info != "auto") and (len(token.children or []) > 0)
+        wrap_node = addnodes.download_reference(
+            refdomain=None,
+            reftarget=destination,
+            refdoc=self.sphinx_env.docname,
+            reftype="myst",
+            refexplicit=explicit,
+        )
+        classes = ["xref", "download", "myst"]
+        self._process_wrap_node(wrap_node, token, explicit, classes, destination)
+
+    def render_link_unknown(self, token: SyntaxTreeNode) -> None:
+        """Render link token `[text](link "title")`,
+        where the link has not been identified as an external URL.
+        """
+        destination = self.md.normalizeLinkText(cast(str, token.attrGet("href") or ""))
+        destination = self._handle_relative_docs(destination)
+
+        explicit = (token.info != "auto") and (len(token.children or []) > 0)
         kwargs = {
             "refdoc": self.sphinx_env.docname,
             "reftype": "myst",
@@ -55,24 +137,11 @@ class SphinxRenderer(DocutilsRenderer):
         path_dest, *_path_ids = destination.split("#", maxsplit=1)
         path_id = _path_ids[0] if _path_ids else None
 
-        potential_path: None | Path
-        if path_dest.startswith("/"):
-            # here we are referencing a file relative to the source directory
-            potential_path = Path(self.sphinx_env.srcdir) / path_dest[1:]
-        elif path_dest == "./":
-            # this is a special case, where we want to reference the current document
-            potential_path = (
-                Path(self.sphinx_env.doc2path(self.sphinx_env.docname))
-                if self.sphinx_env.srcdir
-                else None
-            )
-        else:
-            potential_path = (
-                Path(self.sphinx_env.doc2path(self.sphinx_env.docname)).parent
-                / path_dest
-                if self.sphinx_env.srcdir  # not set in some test situations
-                else None
-            )
+        potential_path: None | Path = None
+        if self.sphinx_env.srcdir:  # not set in some test situations
+            _, path_str = self.sphinx_env.relfn2path(path_dest, self.sphinx_env.docname)
+            potential_path = Path(path_str)
+
         if potential_path and potential_path.is_file():
             docname = self.sphinx_env.path2doc(str(potential_path))
             if docname:
@@ -80,29 +149,18 @@ class SphinxRenderer(DocutilsRenderer):
                     refdomain="doc", reftarget=docname, reftargetid=path_id, **kwargs
                 )
                 classes = ["xref", "myst"]
-                text = ""
             else:
                 wrap_node = addnodes.download_reference(
                     refdomain=None, reftarget=path_dest, **kwargs
                 )
                 classes = ["xref", "download", "myst"]
-                text = destination if not token.children else ""
         else:
             wrap_node = addnodes.pending_xref(
                 refdomain=None, reftarget=destination, **kwargs
             )
             classes = ["xref", "myst"]
-            text = ""
-
-        self.add_line_and_source_path(wrap_node, token)
-        self.copy_attributes(token, wrap_node, ("class", "id", "title"))
-        self.current_node.append(wrap_node)
 
-        inner_node = nodes.inline("", text, classes=classes)
-        wrap_node.append(inner_node)
-        if explicit:
-            with self.current_node_context(inner_node):
-                self.render_children(token)
+        self._process_wrap_node(wrap_node, token, explicit, classes, path_dest)
 
     def get_inventory_matches(
         self,
diff --git a/myst_parser/mocking.py b/myst_parser/mocking.py
index 9c8848b..d91b9c5 100644
--- a/myst_parser/mocking.py
+++ b/myst_parser/mocking.py
@@ -469,7 +469,11 @@ class MockIncludeDirective:
                     source_dir,
                     path.parent,
                 )
-            self.renderer.nested_render_text(file_content, startline + 1)
+            self.renderer.nested_render_text(
+                file_content,
+                startline + 1,
+                heading_offset=self.options.get("heading-offset", 0),
+            )
         finally:
             self.renderer.document["source"] = source
             self.renderer.reporter.source = rsource
diff --git a/myst_parser/parsers/docutils_.py b/myst_parser/parsers/docutils_.py
index 472f947..dfce785 100644
--- a/myst_parser/parsers/docutils_.py
+++ b/myst_parser/parsers/docutils_.py
@@ -15,8 +15,10 @@ from typing import (
 
 import yaml
 from docutils import frontend, nodes
-from docutils.core import default_description, publish_cmdline
+from docutils.core import default_description, publish_cmdline, publish_string
+from docutils.frontend import filter_settings_spec
 from docutils.parsers.rst import Parser as RstParser
+from docutils.writers.html5_polyglot import HTMLTranslator, Writer
 
 from myst_parser._compat import Literal, get_args, get_origin
 from myst_parser.config.main import (
@@ -321,6 +323,27 @@ class Parser(RstParser):
         self.finish_parse()
 
 
+class SimpleTranslator(HTMLTranslator):
+    def stylesheet_call(self, *args, **kwargs):
+        return ""
+
+
+class SimpleWriter(Writer):
+
+    settings_spec = filter_settings_spec(
+        Writer.settings_spec,
+        "template",
+    )
+
+    def apply_template(self):
+        subs = self.interpolation_dict()
+        return "%(body)s\n" % subs
+
+    def __init__(self):
+        self.parts = {}
+        self.translator_class = SimpleTranslator
+
+
 def _run_cli(writer_name: str, writer_description: str, argv: Optional[List[str]]):
     """Run the command line interface for a particular writer."""
     publish_cmdline(
@@ -343,6 +366,44 @@ def cli_html5(argv: Optional[List[str]] = None):
     _run_cli("html5", "HTML5 documents", argv)
 
 
+def cli_html5_demo(argv: Optional[List[str]] = None):
+    """Cmdline entrypoint for converting MyST to simple HTML5 demonstrations.
+
+    This is a special case of the HTML5 writer,
+    that only outputs the body of the document.
+    """
+    publish_cmdline(
+        parser=Parser(),
+        writer=SimpleWriter(),
+        description=(
+            f"Generates body HTML5 from standalone MyST sources.\n{default_description}"
+        ),
+        settings_overrides={
+            "doctitle_xform": False,
+            "sectsubtitle_xform": False,
+            "initial_header_level": 1,
+        },
+        argv=argv,
+    )
+
+
+def to_html5_demo(inputstring: str, **kwargs) -> str:
+    """Convert a MyST string to HTML5."""
+    overrides = {
+        "doctitle_xform": False,
+        "sectsubtitle_xform": False,
+        "initial_header_level": 1,
+        "output_encoding": "unicode",
+    }
+    overrides.update(kwargs)
+    return publish_string(
+        inputstring,
+        parser=Parser(),
+        writer=SimpleWriter(),
+        settings_overrides=overrides,
+    )
+
+
 def cli_latex(argv: Optional[List[str]] = None):
     """Cmdline entrypoint for converting MyST to LaTeX."""
     _run_cli("latex", "LaTeX documents", argv)
diff --git a/myst_parser/sphinx_ext/main.py b/myst_parser/sphinx_ext/main.py
index 01c30d9..809056e 100644
--- a/myst_parser/sphinx_ext/main.py
+++ b/myst_parser/sphinx_ext/main.py
@@ -13,8 +13,12 @@ from myst_parser.parsers.docutils_ import (
 from myst_parser.warnings_ import MystWarnings
 
 
-def setup_sphinx(app: Sphinx, load_parser=False):
-    """Initialize all settings and transforms in Sphinx."""
+def setup_sphinx(app: Sphinx, load_parser: bool = False) -> None:
+    """Initialize all settings and transforms in Sphinx.
+
+    :param app: The Sphinx application object.
+    :param load_parser: Whether to load the parser.
+    """
     # we do this separately to setup,
     # so that it can be called by external packages like myst_nb
     from myst_parser.config.main import MdParserConfig
@@ -59,6 +63,7 @@ def setup_sphinx(app: Sphinx, load_parser=False):
 
 
 def create_myst_config(app):
+    """Create the myst config object and add it to the sphinx environment."""
     from sphinx.util import logging
 
     # Ignore type checkers because the attribute is dynamically assigned
diff --git a/myst_parser/sphinx_ext/myst_refs.py b/myst_parser/sphinx_ext/myst_refs.py
index e00afc4..8a4dc20 100644
--- a/myst_parser/sphinx_ext/myst_refs.py
+++ b/myst_parser/sphinx_ext/myst_refs.py
@@ -392,7 +392,7 @@ class MystReferenceResolver(ReferencesResolver):
             )
         else:
             newnode.append(
-                contnode.__class__(match.name, match.name, classes=["iref", "myst"])
+                nodes.literal(match.name, match.name, classes=["iref", "myst"])
             )
 
         return newnode
diff --git a/myst_parser/warnings_.py b/myst_parser/warnings_.py
index 3bac946..fc54024 100644
--- a/myst_parser/warnings_.py
+++ b/myst_parser/warnings_.py
@@ -12,12 +12,14 @@ class MystWarnings(Enum):
 
     DEPRECATED = "deprecated"
     """Deprecated usage."""
+    NOT_SUPPORTED = "not_supported"
+    """Functionality that is not yet supported in docutils."""
 
     RENDER_METHOD = "render"
     """The render method is not implemented."""
 
     MD_TOPMATTER = "topmatter"
-    """Issue reading top-matter."""
+    """Issue reading front-matter."""
     MD_DEF_DUPE = "duplicate_def"
     """Duplicate Markdown reference definition."""
     MD_FOOTNOTE_DUPE = "footnote"
diff --git a/pyproject.toml b/pyproject.toml
index d9d5b12..8f6de6d 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -54,16 +54,18 @@ linkify = ["linkify-it-py~=1.0"]
 # Note: This is only required for internal use
 rtd = [
     "ipython",
-    # currently required to get sphinx v5
-    "sphinx-book-theme==0.4.0rc1",
-    "sphinx-design",
+    "sphinx-book-theme==1.0.0rc2",
+    "pydata-sphinx-theme==v0.13.0rc4",
+    "sphinx-design2",
     "sphinx-copybutton",
     "sphinxext-rediraffe~=0.2.7",
-    "sphinxcontrib.mermaid~=0.7.1",
+    # TODO this can uncommented once https://github.com/mgaitan/sphinxcontrib-mermaid/issues/109 is fixed
+    # "sphinxcontrib.mermaid~=0.7.1",
     "sphinxext-opengraph~=0.7.5",
     "sphinx-pyscript",
     "sphinx-tippy>=0.3.1",
-    "sphinx-autodoc2>=0.3.0"
+    "sphinx-autodoc2~=0.4.2",
+    "sphinx-togglebutton",
 ]
 testing = [
     "beautifulsoup4",
@@ -85,6 +87,7 @@ myst-anchors = "myst_parser.cli:print_anchors"
 myst-inv = "myst_parser.inventory:inventory_cli"
 myst-docutils-html = "myst_parser.parsers.docutils_:cli_html"
 myst-docutils-html5 = "myst_parser.parsers.docutils_:cli_html5"
+myst-docutils-demo = "myst_parser.parsers.docutils_:cli_html5_demo"
 myst-docutils-latex = "myst_parser.parsers.docutils_:cli_latex"
 myst-docutils-xml = "myst_parser.parsers.docutils_:cli_xml"
 myst-docutils-pseudoxml = "myst_parser.parsers.docutils_:cli_pseudoxml"
@@ -117,7 +120,7 @@ no_implicit_optional = true
 warn_unused_ignores = true
 
 [[tool.mypy.overrides]]
-module = ["docutils.*", "yaml.*"]
+module = ["docutils.*", "yaml.*", "pygments.*"]
 ignore_missing_imports = true
 
 [tool.pytest.ini_options]


Test patch:
diff --git a/tests/test_docutils.py b/tests/test_docutils.py
index f603ee5..e4fc4c2 100644
--- a/tests/test_docutils.py
+++ b/tests/test_docutils.py
@@ -12,9 +12,11 @@ from myst_parser.parsers.docutils_ import (
     attr_to_optparse_option,
     cli_html,
     cli_html5,
+    cli_html5_demo,
     cli_latex,
     cli_pseudoxml,
     cli_xml,
+    to_html5_demo,
 )
 
 
@@ -54,6 +56,18 @@ def test_cli_html5(monkeypatch, capsys):
     assert "text" in captured.out
 
 
+def test_cli_html5_demo(monkeypatch, capsys):
+    monkeypatch.setattr("sys.stdin", io.TextIOWrapper(io.BytesIO(b"text")))
+    cli_html5_demo([])
+    captured = capsys.readouterr()
+    assert not captured.err
+    assert "text" in captured.out
+
+
+def test_to_html5_demo():
+    assert to_html5_demo("text").strip() == "<p>text</p>"
+
+
 def test_cli_latex(monkeypatch, capsys):
     monkeypatch.setattr("sys.stdin", io.TextIOWrapper(io.BytesIO(b"text")))
     cli_latex([])
diff --git a/tests/test_renderers/fixtures/docutil_link_resolution.md b/tests/test_renderers/fixtures/docutil_link_resolution.md
index f5e39e7..e686e17 100644
--- a/tests/test_renderers/fixtures/docutil_link_resolution.md
+++ b/tests/test_renderers/fixtures/docutil_link_resolution.md
@@ -18,7 +18,7 @@
 [missing] 
 .
 [](#test)
-[...](#test)
+<project:#test>
 [explicit](#test)
 [](<#name with spaces>)
 .
@@ -59,7 +59,7 @@
 ## Non-anchor heading
 
 [](#title)
-[...](#longer-title-with-nested-syntax)
+<project:#longer-title-with-nested-syntax>
 [explicit](#title)
 .
 <document source="<src>/index.md">
@@ -94,7 +94,7 @@
 # Test
 
 [](#target)
-[...](#target)
+<project:#target>
 [explicit](#target)
 .
 <document ids="test target" names="test target" source="<src>/index.md" title="Test">
@@ -165,7 +165,7 @@ c  | d
 ```
 
 [](#table)
-[...](#table)
+<project:#table>
 [explicit](#table)
 .
 <document source="<src>/index.md">
diff --git a/tests/test_renderers/fixtures/myst-config.txt b/tests/test_renderers/fixtures/myst-config.txt
index f20ac08..62226c9 100644
--- a/tests/test_renderers/fixtures/myst-config.txt
+++ b/tests/test_renderers/fixtures/myst-config.txt
@@ -360,7 +360,7 @@ My paragraph
             Chris Sewell
 .
 
-[inv_link] --myst-enable-extensions=inv_link
+[inv_link]
 .
 <inv:#index>
 [](inv:#index)
@@ -411,7 +411,7 @@ My paragraph
             Title
 .
 
-[inv_link_error] --myst-enable-extensions=inv_link
+[inv_link_error]
 .
 <inv:#other>
 
diff --git a/tests/test_renderers/fixtures/sphinx_link_resolution.md b/tests/test_renderers/fixtures/sphinx_link_resolution.md
index 8512076..e624b97 100644
--- a/tests/test_renderers/fixtures/sphinx_link_resolution.md
+++ b/tests/test_renderers/fixtures/sphinx_link_resolution.md
@@ -18,7 +18,7 @@
 [missing] 
 .
 [](#test)
-[...](#test)
+<project:#test>
 [explicit](#test)
 .
 <document source="<src>/index.md">
@@ -41,7 +41,7 @@
 ## Non-anchor heading
 
 [](#title)
-[...](#longer-title-with-nested-syntax)
+<project:#longer-title-with-nested-syntax>
 [explicit](#title)
 .
 <document source="<src>/index.md">
@@ -76,7 +76,7 @@
 # Test
 
 [](#target)
-[...](#target)
+<project:#target>
 [explicit](#target)
 [](<#name with spaces>)
 .
@@ -151,7 +151,7 @@ c  | d
 ```
 
 [](#table)
-[...](#table)
+<project:#table>
 [explicit](#table)
 .
 <document source="<src>/index.md">
@@ -193,17 +193,18 @@ c  | d
 [external-file] 
 .
 [](test.txt)
-[...](./test.txt)
+<path:./test.txt>
 [relative to source dir](/test.txt)
 .
 <document source="<src>/index.md">
     <paragraph>
         <download_reference filename="dd18bf3a8e0a2a3e53e2661c7fb53534/test.txt" refdoc="index" refdomain="True" refexplicit="False" reftarget="test.txt" reftype="myst">
-            <inline classes="xref download myst">
+            <literal classes="xref download myst">
                 test.txt
 
         <download_reference filename="dd18bf3a8e0a2a3e53e2661c7fb53534/test.txt" refdoc="index" refdomain="True" refexplicit="False" reftarget="./test.txt" reftype="myst">
-            <inline classes="xref download myst">
+            <literal classes="xref download myst">
+                ./test.txt
 
         <download_reference filename="dd18bf3a8e0a2a3e53e2661c7fb53534/test.txt" refdoc="index" refdomain="True" refexplicit="True" reftarget="/test.txt" reftype="myst">
             <inline classes="xref download myst">
@@ -213,7 +214,7 @@ c  | d
 [source-file] 
 .
 [](other.rst)
-[...](./other.rst)
+<project:other.rst>
 [relative to source dir](/other.rst)
 .
 <document source="<src>/index.md">
diff --git a/tests/test_sphinx/sourcedirs/references/index.md b/tests/test_sphinx/sourcedirs/references/index.md
index ac1f0de..74d0fd6 100644
--- a/tests/test_sphinx/sourcedirs/references/index.md
+++ b/tests/test_sphinx/sourcedirs/references/index.md
@@ -45,7 +45,7 @@ subfolder/other2.md
 
 [](#title-anchors)
 
-[](./#title-anchors)
+<project:#title-anchors>
 
 [](./other.md#title-anchors)
 
diff --git a/tests/test_sphinx/test_sphinx_builds/test_references.html b/tests/test_sphinx/test_sphinx_builds/test_references.html
index 666196d..55b13a7 100644
--- a/tests/test_sphinx/test_sphinx_builds/test_references.html
+++ b/tests/test_sphinx/test_sphinx_builds/test_references.html
@@ -93,9 +93,11 @@
     </p>
     <p>
      <a class="reference download internal" download="" href="_downloads/1952147a8403903cb78cecf56f049085/file_link2.txt">
-      <span class="xref download myst">
-       subfolder/file_link2.txt
-      </span>
+      <code class="xref download myst docutils literal notranslate">
+       <span class="pre">
+        subfolder/file_link2.txt
+       </span>
+      </code>
      </a>
     </p>
     <p id="insidecodeblock">
@@ -225,9 +227,11 @@
     <p>
      Known no title
      <a class="reference external" href="https://example.com/index.html#paragraph-target" title="Example 0.0.1">
-      <span class="iref myst">
-       paragraph-target
-      </span>
+      <code class="iref myst docutils literal notranslate">
+       <span class="pre">
+        paragraph-target
+       </span>
+      </code>
      </a>
     </p>
     <p>
@@ -251,9 +255,11 @@
     <p>
      Ambiguous
      <a class="reference external" href="https://example.com/index.html#module-duplicate" title="Example 0.0.1">
-      <span class="iref myst">
-       duplicate
-      </span>
+      <code class="iref myst docutils literal notranslate">
+       <span class="pre">
+        duplicate
+       </span>
+      </code>
      </a>
     </p>
    </section>
diff --git a/tests/test_sphinx/test_sphinx_builds/test_references.resolved.xml b/tests/test_sphinx/test_sphinx_builds/test_references.resolved.xml
index b539bf3..58d7354 100644
--- a/tests/test_sphinx/test_sphinx_builds/test_references.resolved.xml
+++ b/tests/test_sphinx/test_sphinx_builds/test_references.resolved.xml
@@ -54,7 +54,7 @@
                         link
         <paragraph>
             <download_reference filename="1952147a8403903cb78cecf56f049085/file_link2.txt" refdoc="index" refdomain="True" refexplicit="False" reftarget="subfolder/file_link2.txt" reftype="myst">
-                <inline classes="xref download myst">
+                <literal classes="xref download myst">
                     subfolder/file_link2.txt
         <target refid="insidecodeblock">
         <paragraph ids="insidecodeblock" names="insidecodeblock">
@@ -98,7 +98,7 @@
                     <inline classes="std std-ref">
                         Title anchors
             <paragraph>
-                <reference internal="True" refid="title-anchors">
+                <reference id_link="True" refid="title-anchors">
                     <inline classes="std std-ref">
                         Title anchors
             <paragraph>
@@ -132,7 +132,7 @@
         <paragraph>
             Known no title 
             <reference internal="False" reftitle="Example 0.0.1" refuri="https://example.com/index.html#paragraph-target">
-                <inline classes="iref myst">
+                <literal classes="iref myst">
                     paragraph-target
         <paragraph>
             Known explicit 
@@ -148,5 +148,5 @@
         <paragraph>
             Ambiguous 
             <reference internal="False" reftitle="Example 0.0.1" refuri="https://example.com/index.html#module-duplicate">
-                <inline classes="iref myst">
+                <literal classes="iref myst">
                     duplicate
diff --git a/tests/test_sphinx/test_sphinx_builds/test_references.xml b/tests/test_sphinx/test_sphinx_builds/test_references.xml
index b6fcdc9..5069ace 100644
--- a/tests/test_sphinx/test_sphinx_builds/test_references.xml
+++ b/tests/test_sphinx/test_sphinx_builds/test_references.xml
@@ -52,7 +52,7 @@
                         link
         <paragraph>
             <download_reference filename="1952147a8403903cb78cecf56f049085/file_link2.txt" refdoc="index" refdomain="True" refexplicit="False" reftarget="subfolder/file_link2.txt" reftype="myst">
-                <inline classes="xref download myst">
+                <literal classes="xref download myst">
                     subfolder/file_link2.txt
         <target refid="insidecodeblock">
         <paragraph ids="insidecodeblock" names="insidecodeblock">
@@ -83,8 +83,9 @@
                     <inline classes="std std-ref">
                         Title anchors
             <paragraph>
-                <pending_xref refdoc="index" refdomain="doc" refexplicit="False" reftarget="index" reftargetid="title-anchors" reftype="myst">
-                    <inline classes="xref myst">
+                <reference id_link="True" refid="title-anchors">
+                    <inline classes="std std-ref">
+                        Title anchors
             <paragraph>
                 <pending_xref refdoc="index" refdomain="doc" refexplicit="False" reftarget="other" reftargetid="title-anchors" reftype="myst">
                     <inline classes="xref myst">