Repository navigation
fix: keep a backslash in a code span from hiding emphasis - #4117
Conversation
The em/strong mask replaced every backslash escape before it masked code spans, but a backslash inside a code span is literal. A code span ending in `\` therefore lost its closing backtick in the mask, so the next backtick paired with it and the emphasis between them was masked out and rendered as literal `_` or `*`. Mask escapes only outside code spans.
|
@breken-ai is attempting to deploy a commit to the MarkedJS Team on Vercel. A member of the Team first needs to authorize it. |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
styfle
left a comment
There was a problem hiding this comment.
Looks good though we deviate a bit from commonmark. Here's an example:
https://spec.commonmark.org/dingus/?text=_%60%60%5C%60_%60%60
|
@styfle thanks for the example. It was a regression from this PR. Here is why. Before this PR, masking Fixed in 7d5c8c9. Inside a code span that the escape mask matches, the inner backticks are now masked to _``\`_``
_`` a`_ ``These now render as |
## [18.1.1](v18.1.0...v18.1.1) (2026-10-12) ### Bug Fixes * **cli:** honor an explicitly empty string input ([#4113](#4113)) ([ec3a4e5](ec3a4e5)) * end blockquote before a lazy line after a heading, hr or html block ([#4115](#4115)) ([9e64a6a](9e64a6a)) * keep a backslash in a code span from hiding emphasis ([#4117](#4117)) ([6a57018](6a57018)) * keep a decoded character reference from forming a new one ([#4111](#4111)) ([6bbac0c](6bbac0c)), closes [#38](#38) [#112](#112) * let indented and type 3-5 html blocks interrupt a paragraph ([#4124](#4124)) ([eaa1fff](eaa1fff)) * make walkTokens linear by appending values in place ([#4121](#4121)) ([627d9ae](627d9ae)), closes [#4120](#4120) * match pre, script, style and textarea as whole tag names ([#4114](#4114)) ([0db74cb](0db74cb)) * preserve enclosing link state after parsing images ([#4123](#4123)) ([cc07bb9](cc07bb9)) * respect tab stops in list continuation indentation ([#4119](#4119)) ([4bd2528](4bd2528)) ### Performance Improvements * avoid repeated raw string copies in nested lists ([#4082](#4082)) ([7e8754d](7e8754d))
Marked version: 18.0.14 (
masterat 4ee44f7)Markdown flavor: CommonMark (also GitHub Flavored Markdown)
Description
No existing issue that I could find.
Expectation
A code span that ends in a backslash does not affect emphasis later in the paragraph. This line from the minimatch README:
should render
<em>will</em>, as it does in the CommonMark reference implementation, markdown-it and on GitHub.Result
The underscores come through as literal text. The same happens with
**bold**in the glob README (`\` characters to `/` in pattern strings, **thus making it impossible...**) and with any Windows path in code, e.g.Use `C:\Users\` for **home** and `D:\` for data.Minimal case:`a\` *b* `c`.What was attempted
In
#inlineTokensInner, the em/strong mask replaces every backslash escape (anyPunctuation) beforeblockSkipmasks code spans. A backslash is literal inside a code span, but the mask still turned\`into++. That removed the closing backtick of`\`, soblockSkippaired the opening backtick with the next code span's backtick and masked everything in between, including the emphasis delimiters. This ordering dates from #2838.The fix adds
anyPunctuationOutsideCode. It matches a code span (same shape asinline.code) or an unmatched backtick run whole and leaves it unchanged, and masks only the escapes outside code spans. Escaped backticks outside code still work:\`*escaped tick*\`keeps its emphasis.anyPunctuationitself is unchanged because the tokenizer also uses it to unescape hrefs, titles and info strings.Test:
test/specs/new/codespan_backslash_emphasis.md. It fails onmasterand passes with the fix.npm run test:specs(1865/1865),test:unit,test:cjs,test:umd,test:typesandtest:lintall pass. As a further check, I compared this branch withmasteron 300k generated inputs mixing backticks, backslashes and delimiters. Every output that changed now matches commonmark.js (or markdown-it withgfm: true), and none moved away from it.This change was prepared with the help of an AI coding assistant, and I reviewed and tested it.
Contributor
Committer
In most cases, this should be a different person than the contributor.