🐛 Fix button-ref target whitespace and nested content#281
Merged
Conversation
7f2dc96 to
eb913e7
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #281 +/- ##
==========================================
+ Coverage 90.41% 90.72% +0.30%
==========================================
Files 13 13
Lines 1158 1207 +49
==========================================
+ Hits 1047 1095 +48
- Misses 111 112 +1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
eb913e7 to
c6137fa
Compare
button-ref now normalises its target like Sphinx's XRefRole (collapsing whitespace) instead of stripping it via directives.uri, so multi-word autosectionlabel labels resolve (#110). A stash/graft post-transform pair (around the resolvers, using only stable Sphinx/docutils APIs) preserves rich inline content (emphasis, icons) on resolved button-ref nodes, matching button-link output rather than flattening to text (#228).
c6137fa to
926cc8b
Compare
This was referenced Jul 14, 2026
chrisjsewell
added a commit
that referenced
this pull request
Jul 14, 2026
Both `card` (cards.py) and `grid-item-card` (grids.py, via its own option_spec) ran the `:link:` option through `directives.uri`, which deletes all whitespace. For `link-type: ref`, a multi-word target such as an `autosectionlabel` label (e.g. `my section name`) became `mysectionname`, producing an `undefined label` warning. The `link` option is now captured verbatim (`unchanged_required`) and normalised inside `CardDirective.create_card`, where `link-type` is known: `url` keeps the `directives.uri` behaviour (byte-identical for URLs), `ref` collapses whitespace runs and lowercases (matching the `:ref:` role, `XRefRole(lowercase=True)`), and `doc`/`any` collapse whitespace but preserve case. Completes the fix for #110 (the `button-ref` path was fixed in #281).
chrisjsewell
added a commit
that referenced
this pull request
Jul 14, 2026
Badge roles now accept a trailing `; tooltip` suffix, rendered as a native HTML `title` attribute (closes #81). The suffix is split on the last unescaped `;` (a literal `;` is written `\;`), mirroring the icon roles' string grammar via the new `split_tooltip` helper. Since `;` is a legal character in URLs and reference targets, the `bdg-link-*`/`bdg-ref-*` families only accept the suffix after a complete explicit `title <target>` form (the `;` must follow the closing `>`); a bare target is never split, so existing targets containing `;` render byte-identically to before. The `\;` escape is resolved uniformly for both parsers (docutils NUL-encodes escapes, MyST forwards backslashes verbatim). - plain badges use a new `sd_badge` node (a `nodes.inline` whose HTML visitor emits `title` when set, with explicit passthrough visitors for latex/text/man/texinfo); output without a tooltip is byte-identical to before (only the doctree node name changes, hence the badge-basic fixture regeneration) - `bdg-link-*` set `reftitle` on the reference (native `title`) - `bdg-ref-*` carry the tooltip across cross-reference resolution using the #281 marker-class + document-stash pattern (an arbitrary attribute does not survive resolution), applied as `reftitle` by a post-transform that runs after the resolver; no marker/attribute leaks into output Also removes a stale `TODO escape HTML` on the button `:tooltip:` option (the HTML writer already escapes attribute values) and the dead commented-out `reftitle` code in the link badge role.
chrisjsewell
added a commit
that referenced
this pull request
Jul 14, 2026
Badge roles now accept a trailing `; tooltip` suffix, rendered as a native HTML `title` attribute (closes #81). The suffix is split on the last unescaped `;` (a literal `;` is written `\;`), mirroring the icon roles' string grammar via the new `split_tooltip` helper. Since `;` is a legal character in URLs and reference targets, the `bdg-link-*`/`bdg-ref-*` families only accept the suffix after a complete explicit `title <target>` form (the `;` must follow the closing `>`); a bare target is never split, so existing targets containing `;` render byte-identically to before. The `\;` escape is resolved uniformly for both parsers (docutils NUL-encodes escapes, MyST forwards backslashes verbatim). - plain badges use a new `sd_badge` node (a `nodes.inline` whose HTML visitor emits `title` when set, with explicit passthrough visitors for latex/text/man/texinfo); output without a tooltip is byte-identical to before (only the doctree node name changes, hence the badge-basic fixture regeneration) - `bdg-link-*` set `reftitle` on the reference (native `title`) - `bdg-ref-*` carry the tooltip across cross-reference resolution using the #281 marker-class + document-stash pattern (an arbitrary attribute does not survive resolution), applied as `reftitle` by a post-transform that runs after the resolver; no marker/attribute leaks into output Also removes a stale `TODO escape HTML` on the button `:tooltip:` option (the HTML writer already escapes attribute values) and the dead commented-out `reftitle` code in the link badge role.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two
button-refbugs, plus a parity improvement:Changes
directives.uri, which deletes all whitespace — correct forbutton-linkURLs, but it turned multi-word ref targets (exactly whatautosectionlabelgenerates, e.g.my article section) intomyarticlesection→undefined label. Each directive now normalizes its own argument:button-linkkeepsdirectives.uri;button-refcollapses whitespace runs like Sphinx'sXRefRoledoes. Additionally,ref-type: reftargets are lowercased to match the:ref:role (XRefRole(lowercase=True)— std labels are stored lowercased), so the visible Title-Case heading text can be pasted verbatim;doc/mysttargets stay case-sensitive.astext(), flattening nested inline markup (emphasis, icons rendered as escaped text). Fixed with a stash/graft pair of post-transforms using only stable APIs: content is stashed and thepending_xreftagged with a transient marker class before any resolver runs (priority 8 — below myst-parser's resolver at 9 and the built-in at 10), then grafted back onto the resolved reference (priority 11). Buttons whose content itself contains a cross-reference role are deliberately left on the old flatten path — regrafting would re-insert an unresolvedpending_xrefand crash the writer (and a link inside a button link is invalid HTML anyway).button-refs keep the resolver-generated section title (guarded byrefexplicit).button-refs degrade to a standardundefined labelwarning with unlinked content — no traceback (locking in the hardening from 🐛 Keep buttons intact under gettext translation #270). Docs updated: the "bold text will be rendered without bold" caveat is gone (it now renders), and targets may contain spaces.Verification
tests/test_buttons.py(11 tests, rst + myst): multi-word target resolution (verified red on the old code:undefined label: 'myarticlesection'), Title-Case +ref-type: ref, nested-content parity withbutton-link, nested-xref-in-content build safety (verified red — reproduced the writer crash pre-fix), content-less title rendering, unresolved warning path, and marker-leak assertions (HTML + doctree) on every path.sd-btnclass output byte-identical to main outside the intended fixes, nitpicky-mode parity.Closes #110
Closes #228