🐛 FIX: myst_role backslash-guard misparse at inline start#145
Merged
Conversation
The guard checking the char before the role read state.src[state.pos - 1],
which at pos 0 wraps to the last char of the inline source (negative
indexing; the IndexError branch never fires), wrongly rejecting a role at
the start of inline content whenever the content ends with a backslash.
The guard is removed entirely: \{ is already consumed by the core escape
rule before this rule runs (so the guard was dead for its intended case),
and for an escaped backslash (\\{name}`x`) it wrongly suppressed a live
role.
Closes #62
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #145 +/- ##
==========================================
+ Coverage 92.80% 92.90% +0.10%
==========================================
Files 31 40 +9
Lines 1835 2284 +449
==========================================
+ Hits 1703 2122 +419
- Misses 132 162 +30
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:
|
Merged
chrisjsewell
added a commit
that referenced
this pull request
Jul 19, 2026
Bumps the version to 0.7.0 and dates the changelog for release. ## 0.7.0 - 2026-07-19 - ✨ NEW: Add section reference plugin (`section_ref`) (#144) - 🐛 FIX: `myst_role` no longer mis-rejects a role at the start of inline content when the content ends with a backslash (#62, #145) Also included since 0.6.1: the switch to PyPI trusted publishing (#142) — this will be the first release through the OIDC publish job. After merge, tagging `v0.7.0` on master triggers the publish job. --- _Generated by [Claude Code](https://claude.ai/code/session_01LwRkZLzpbHdb3pgmctmn6H)_ Co-authored-by: Claude <noreply@anthropic.com>
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.
What
Fixes #62:
myst_rolemisparsed inline content that starts with a role and ends with a backslash:Why
The "starting backslash escape" guard read
state.src[state.pos - 1]. Atstate.pos == 0that is Python negative indexing — it reads the last character of the inline source (theexcept IndexErrornever fires), so a role at the start of the inline was rejected whenever the content ended with\.The guard is removed entirely rather than bounds-checked, because it was wrong in both remaining respects too:
\{foo}x``) it was dead code:{is CommonMark-escapable, so the core `escape` rule (which runs before this rule) consumes `{` wholesale — `myst_role` is never invoked there. Verified unchanged before/after.\\{foo}x``) it wrongly suppressed a live role; it now renders a literal\followed by the parsed role, matching the CommonMark analogy (`\a` → `<em>a`). This is the "edge case `\{`" the guard's own comment flagged as broken.This mirrors the analysis done for the
section_refplugin in #144, where the same guard pattern was dropped.Testing
\{foo}x(still escaped, via the core rule), and `\\{foo}`x(now a live role).zero-preset config without the coreescaperule,\{foo}x`` now parses the role (previously suppressed-but-still-literal-backslash). No realistic consumer runsmyst_rolewithout the escape rule; a code comment now documents the assumption.Note: the same latent
state.src[state.pos - 1]wraparound exists indollarmath(only reachable with the non-defaultallow_digits=False) — left for a separate PR.Generated by Claude Code