From fa40f0b203507b07bcd14a91b8723fbf46582a64 Mon Sep 17 00:00:00 2001 From: Chris Sewell Date: Tue, 10 Nov 2026 15:47:25 +0100 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=9A=80=20RELEASE:=20v5.2.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bump the version to 5.2.0 and add the 5.2.0 changelog entry, with upgrade notes for the changes that can alter existing output. --- CHANGELOG.md | 112 ++++++++++++++++++++++++++++++++++++++++ myst_parser/__init__.py | 2 +- 2 files changed, 113 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ff2d904f..37e4a18c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,117 @@ # Changelog +## 5.2.0 - 2026-11-10 + +Heading anchors are now stable and documented: +one shared slug implementation with `"github"`, `"gitlab"` and `"docutils"` presets, +slugs emitted as real HTML ids, explicit `(target)=` ids taking priority, and a versioned anchor contract. +Warnings and other tools now get accurate source lines (also inside `{include}`d files), +docutils 0.23 is supported, inputs that used to abort the build now warn instead, +and many fixes land for references, images, front matter, substitutions and directives. + +Nothing is dropped: Python `>=3.11`, Sphinx `>=8,<10` and the markdown-it-py and mdit-py-plugins requirements are unchanged, +and the docutils range is widened to `>=0.20,<0.24`. +Some of these changes can still alter the output of a project that built before, so please read the upgrade notes. + +### ‼️ Upgrade notes + +- **Heading anchors** (, ), see [](syntax/header-anchors): + - Duplicate heading slugs now get fixed-base suffixes, `x`, `x-1`, `x-2`, as on GitHub; + the third and later duplicates used to get `x-1-2`, `x-1-2-3`, ... + **So a link to the third or later duplicate of a heading changes URL**; the first two keep theirs. + - Slugs are also emitted as secondary HTML `id`s on the rendered headings, so `#slug` links work in the published HTML. + The docutils id stays the primary (first) id, so existing fragment links keep working. + Set `myst_heading_anchors_html_ids = False` to emit only the docutils id. + - An explicit `(target)=` placed before a heading becomes the section's primary id, + which tocs, permalinks and `objects.inv` use; the implicit heading id is kept as a secondary anchor. + - A heading whose slug is empty (a punctuation-only title, or any non-Latin title with the `"docutils"` preset) gets no anchor, + and an empty fragment, `[](#)`, now warns as unresolved. + - Links that used to warn now resolve when the anchor exists: + same-document links to implicit ids (such as headings deeper than `myst_heading_anchors`; under Sphinx only as a last resort), + and cross-document links to section and label ids. + `[](doc.md#label)` takes the target's title as its text (). + - These rules (slug presets, deduplication, empty slugs, explicit-id priority and HTML ids) are now a documented contract, + pinned by a versioned, language-agnostic corpus (`tests/fixtures/slugs.json`). + `myst_parser.mdit_to_docutils.base.default_slugify` is deprecated in favour of `myst_parser.slugs.github_slugify`. +- **Directive option warnings** (): each warning now points at the offending option's line, + and unknown options are reported one per warning, as `Unknown option key: 'x' (allowed: [...])`, + instead of one aggregate `Unknown option keys: [...]`. + The `myst.directive_option` subtype is unchanged, so `suppress_warnings` keeps working, + but tests that match the old message need updating. +- **Directive API** (): directives now receive the full fenced text as `block_text`, as in reStructuredText, + so errors that echo it show the whole fence; + and `content_offset` is `-1` when the body starts on the opening line. +- **Source lines** (, , ): lines in warnings and nodes change where they were wrong. + Text nodes no longer take the line of the most recent directive (so gettext `.pot` locations change), + lines inside `{include}`d files are no longer one late, + and the body of a directive with options and a trailing blank line is no longer one line off. +- **Front matter** (): options that can only be set globally + (`heading_slug_func`, `update_mathjax`, `mathjax_classes`, `suppress_warnings`, `inventories`) + now warn (`myst.topmatter`) and are ignored in a document's front matter. + This removes the undocumented per-document effect of `inventories` (docutils) and `update_mathjax` (Sphinx). +- **Rendered output**: + - `parsed-literal` keeps each line's indentation, and two trailing spaces no longer make a hard line break (); + - `$$` math blocks lose the blank lines at the start and end of their content, which broke LaTeX output (); + - `myst_links_external_new_tab` writes `rel="noreferrer"` (it was misspelt `noreferer`), + and no longer overwrites an authored `target` or `rel` (); + - image alt text keeps backslash escapes and entities (), + an HTML `` keeps its alt text exactly, and a valueless `alt` is now empty rather than `None` (); + - link titles are kept on links that go through cross-reference resolution (); + - a footnote whose label equals a heading's name is now kept, rather than dropped with a warning (). +- **Packaging** (): the distributions are now built with `python -m build`, + so the sdists hold only the package, `pyproject.toml`, `README.md` and `LICENSE` + (no longer `CHANGELOG.md`, `tox.ini` or `.github/`); the wheels are unaffected. + +### ✨ New Features + +- ✨ Stable heading anchors: one shared slug module (`myst_parser.slugs`), named presets for `myst_heading_slug_func` (`"github"`, `"gitlab"`), slugs emitted as HTML ids (`myst_heading_anchors_html_ids`), explicit-id priority, fewer false warnings for working links, and `myst-anchors --slug-func`, by in +- ✨ Add the `"docutils"` heading slug preset (byte-identical to `docutils.nodes.make_id`) and a versioned anchor contract, see [](syntax/header-anchors), by in + +### 👌 Improvements + +- 👌 Report accurate source lines: directive option warnings point at their option, unknown options warn per key, first-line directive content is no longer one line off, text nodes get their own lines (), directives receive the full `block_text` (superseding , thanks to ), and an `include` with `:literal:` gets its true line, by in +- 👌 Allow a `{table}` caption to wrap onto the following lines, by in +- 👌 Make a document's own front matter available to its substitutions, as `env.metadata[env.docname]`, by in + +### 🐛 Bug Fixes + +- 🐛 Warn instead of aborting the build on hostile input (deeply nested HTML, malformed or hostile YAML front matter, YAML alias bombs), and keep a footnote whose label equals a heading's name, by in +- 🐛 Fix small docutils renderer bugs: field bodies get source lines, a definition without a term no longer crashes, and `linkify` without `linkify-it-py` installed is disabled with a `myst.linkify` warning instead of crashing, by in +- 🐛 Use the target's title for `[](doc.md#label)` links, which rendered as invisible empty links, by in +- 🐛 Keep link titles through cross-reference resolution, by in +- 🐛 Report exact source lines in `{include}`d files (also with `:start-after:` and a negative `:start-line:`), by , , and in +- 🐛 Keep validated front matter config values (`enable_extensions`, `fence_as_directive`, `url_schemes`), and reject `global_only` options in front matter, by in +- 🐛 Fix a directive's body offset when its body ends in blank lines, by in +- 🐛 Don't crash on nested YAML dates in front matter, by in +- 🐛 Fix sorting of mixed manual and auto-numbered footnotes, by in +- 🐛 Keep backslash escapes and entities in image alt text, by in +- 🐛 Keep the literal alt text of HTML images (`html_image`), so a newline in an attribute can no longer inject a directive option, by in +- 🐛 Preserve line indentation in `parsed-literal` directives, by in +- 🐛 Allow substitution keys that are not Jinja2 identifiers, such as `{{foo-bar}}`, by in +- 🐛 attrs: warn instead of raising on an invalid aliased image attribute (`{w=…}`) or a duplicate heading `{#id}`, and fix the new-tab link attributes, by in +- 🐛 Strip blank boundary lines from `$$` math blocks, which broke LaTeX output, by in +- 🐛 Send a User-Agent when fetching remote inventories, which Read the Docs rejected with HTTP 403, by in +- 🐛 Allow `setup_sphinx` to run twice, so `myst_parser` and `myst_nb` can both be listed in `extensions`, by in + +### ⬆️ Dependency Upgrades + +- ⬆️ Allow docutils 0.23 (`docutils>=0.20,<0.24`), reported by in , by in +- ⬆️ Update the `testing` extra's pygments requirement from `<2.21` to `<2.22` in +- ⬆️ Allow flit_core 4 as the build backend (`flit_core>=3.4,<5`) in + +### 📚 Documentation + +- 📚 Document percent-encoding spaces in inventory object names, by in +- 📚 Drop the unsupported `\[...\]` and `\(...\)` math delimiters from the syntax reference, by in +- 📚 Link to `auto_mode` in sphinx-autodoc2, by in (from ) +- 📚 Render the docs' syntax examples with `sphinx-syntax-example`, by in + +### 🔧 Internal / Maintenance + +- 🔧 Publish to PyPI with trusted publishing, by in , from distributions built and checked in CI, by in + +**Full Changelog**: [v5.1.0...v5.2.0](https://github.com/executablebooks/MyST-Parser/compare/v5.1.0...v5.2.0) + ## 5.1.0 - 2026-05-13 ### ✨ New Features diff --git a/myst_parser/__init__.py b/myst_parser/__init__.py index 6e33baeb..4d93431b 100644 --- a/myst_parser/__init__.py +++ b/myst_parser/__init__.py @@ -3,7 +3,7 @@ and [Sphinx](https://github.com/sphinx-doc/sphinx). """ -__version__ = "5.1.0" +__version__ = "5.2.0" def setup(app): From 8f05b9f17a622624976820b04972493ac8358e2c Mon Sep 17 00:00:00 2001 From: Chris Sewell Date: Tue, 10 Nov 2026 16:08:01 +0100 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=93=9A=20RELEASE:=20v5.2.0=20changelo?= =?UTF-8?q?g=20wording=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Correct three lines of the 5.2.0 entry: a third or later duplicate heading keeps its HTML ids, but links that use its old slug must be rewritten; cross-document links resolve to label ids and to the implicit ids of headings within the anchor depth; and the #1207 line describes the 5.1.0 behaviour it fixes (issue #1151). --- CHANGELOG.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 37e4a18c..b2195905 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,9 @@ Some of these changes can still alter the output of a project that built before, - **Heading anchors** (, ), see [](syntax/header-anchors): - Duplicate heading slugs now get fixed-base suffixes, `x`, `x-1`, `x-2`, as on GitHub; the third and later duplicates used to get `x-1-2`, `x-1-2-3`, ... - **So a link to the third or later duplicate of a heading changes URL**; the first two keep theirs. + **So a link that uses the old slug of a third or later duplicate, such as `[](#x-1-2)`, no longer resolves + and warns (`myst.xref_missing`, which fails a `-W` build): change it to `[](#x-2)`.** + Links to the first two duplicates are unchanged, and every HTML id a heading had before is kept. - Slugs are also emitted as secondary HTML `id`s on the rendered headings, so `#slug` links work in the published HTML. The docutils id stays the primary (first) id, so existing fragment links keep working. Set `myst_heading_anchors_html_ids = False` to emit only the docutils id. @@ -28,7 +30,7 @@ Some of these changes can still alter the output of a project that built before, and an empty fragment, `[](#)`, now warns as unresolved. - Links that used to warn now resolve when the anchor exists: same-document links to implicit ids (such as headings deeper than `myst_heading_anchors`; under Sphinx only as a last resort), - and cross-document links to section and label ids. + and cross-document links to label ids and to the implicit ids of headings within the `myst_heading_anchors` depth. `[](doc.md#label)` takes the target's title as its text (). - These rules (slug presets, deduplication, empty slugs, explicit-id priority and HTML ids) are now a documented contract, pinned by a versioned, language-agnostic corpus (`tests/fixtures/slugs.json`). @@ -77,7 +79,7 @@ Some of these changes can still alter the output of a project that built before, - 🐛 Warn instead of aborting the build on hostile input (deeply nested HTML, malformed or hostile YAML front matter, YAML alias bombs), and keep a footnote whose label equals a heading's name, by in - 🐛 Fix small docutils renderer bugs: field bodies get source lines, a definition without a term no longer crashes, and `linkify` without `linkify-it-py` installed is disabled with a `myst.linkify` warning instead of crashing, by in -- 🐛 Use the target's title for `[](doc.md#label)` links, which rendered as invisible empty links, by in +- 🐛 Resolve `[](doc.md#label)` links to explicit targets in other documents without a false `myst.xref_missing` warning (, reported by ), using the target's title as the link text, by in - 🐛 Keep link titles through cross-reference resolution, by in - 🐛 Report exact source lines in `{include}`d files (also with `:start-after:` and a negative `:start-line:`), by , , and in - 🐛 Keep validated front matter config values (`enable_extensions`, `fence_as_directive`, `url_schemes`), and reject `global_only` options in front matter, by in From 03f9bc4040aa65e4c7a5e58ebb31c881f10b1d83 Mon Sep 17 00:00:00 2001 From: Chris Sewell Date: Tue, 10 Nov 2026 19:01:22 +0100 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=93=9A=20DOCS:=205.2.0=20changelog:?= =?UTF-8?q?=20the=20section=5Fref=20extension=20and=20the=20mdit-py-plugin?= =?UTF-8?q?s=200.7=20requirement=20(#1170)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b2195905..d79c7010 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,9 +7,11 @@ one shared slug implementation with `"github"`, `"gitlab"` and `"docutils"` pres slugs emitted as real HTML ids, explicit `(target)=` ids taking priority, and a versioned anchor contract. Warnings and other tools now get accurate source lines (also inside `{include}`d files), docutils 0.23 is supported, inputs that used to abort the build now warn instead, -and many fixes land for references, images, front matter, substitutions and directives. +and many fixes land for references, images, front matter, substitutions and directives; +a new `section_ref` extension links `§1.1`-style references to numbered headings. -Nothing is dropped: Python `>=3.11`, Sphinx `>=8,<10` and the markdown-it-py and mdit-py-plugins requirements are unchanged, +Nothing is dropped: Python `>=3.11`, Sphinx `>=8,<10` and the markdown-it-py requirement are unchanged, +mdit-py-plugins is raised to `~=0.7` (it was `~=0.6,>=0.6.1`), and the docutils range is widened to `>=0.20,<0.24`. Some of these changes can still alter the output of a project that built before, so please read the upgrade notes. @@ -63,11 +65,13 @@ Some of these changes can still alter the output of a project that built before, - **Packaging** (): the distributions are now built with `python -m build`, so the sdists hold only the package, `pyproject.toml`, `README.md` and `LICENSE` (no longer `CHANGELOG.md`, `tox.ini` or `.github/`); the wheels are unaffected. +- **mdit-py-plugins 0.7** (): myst-parser and myst-docutils now require `mdit-py-plugins>=0.7,<1`. ### ✨ New Features - ✨ Stable heading anchors: one shared slug module (`myst_parser.slugs`), named presets for `myst_heading_slug_func` (`"github"`, `"gitlab"`), slugs emitted as HTML ids (`myst_heading_anchors_html_ids`), explicit-id priority, fewer false warnings for working links, and `myst-anchors --slug-func`, by in - ✨ Add the `"docutils"` heading slug preset (byte-identical to `docutils.nodes.make_id`) and a versioned anchor contract, see [](syntax/header-anchors), by in +- ✨ Add the `"section_ref"` syntax extension: section-sign references such as `§1`, `§1.1` and `§2.3.4` link to the correspondingly numbered heading of the current document (numbered the same in docutils and Sphinx), with a suppressible `myst.section_ref` warning when no heading matches, see [](syntax/section-ref), by in ### 👌 Improvements @@ -97,6 +101,7 @@ Some of these changes can still alter the output of a project that built before, ### ⬆️ Dependency Upgrades +- ⬆️ Require `mdit-py-plugins~=0.7`, for its `section_ref` plugin, by in - ⬆️ Allow docutils 0.23 (`docutils>=0.20,<0.24`), reported by in , by in - ⬆️ Update the `testing` extra's pygments requirement from `<2.21` to `<2.22` in - ⬆️ Allow flit_core 4 as the build backend (`flit_core>=3.4,<5`) in