[lexical-markdown] Bug Fix: Inline code spans containing backticks#8723
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
potatowagon
left a comment
There was a problem hiding this comment.
Reviewed by Navi (Tater Thoughts Bobblehead) on behalf of @potatowagon.
Assessment: LGTM ✅
This PR fixes inline code span export/import to properly handle backtick-containing content per the CommonMark spec (https://spec.commonmark.org/#code-spans).
What I checked:
-
Algorithm correctness —
getCodeSpanDelimiter()computes the longest backtick run in content and useslongestRun + 1backticks as the fence. This is the correct CommonMark algorithm. Padding with spaces is correctly applied when content contains backticks OR starts/ends with whitespace (per spec rule 2). -
Import-side
scanCodeSpans()— Correctly implements CommonMark opener/closer matching (same-length runs). TheisEscaped()helper properly counts preceding backslashes (odd = escaped). Content stripping of single-space padding correctly checks for non-space content to avoid stripping all-space spans. -
Integration with
exportTextFormat()— TheisCodebranch skips the character escaping (correct — code spans are literal), computes the fence, and setstrimmedOutputto the fully-fenced content. Thecontinuestatement forformat === 'code'prevents double-wrapping with the static backtick tag. Other format tags (bold, italic) correctly wrap around the code span fence. -
Edge cases covered by tests — Single backtick in content (
a\b→ `` `` a\b), double backtick (a\`b→ ``` ``` a\`b), leading backtick (\`x→`x), bold+code combination, redundant fence normalization on re-export. Round-trip tests confirm lossless transformation. -
No regressions — Existing code span behavior unchanged (backtick-free content still gets single backtick fence). The
excludeRangesmechanism still works — it now usesscanCodeSpansoutput instead of the regex, but produces equivalent ranges. All existing tests pass. -
www compat —
getCodeSpanDelimiteris newly exported but additive only. No removed/renamed exports. No API surface changes to existing functions. Safe for www consumers of @lexical/markdown.
Minor note: The needsPadding condition includes content.length === 0 — an empty code span would produce ` ` (space between single backticks). This is technically correct per CommonMark (empty code spans resolve to empty string), though unusual. Not a concern.
All CI green (unit 22.x+24.x, browser, integrity, e2e canary chromium, CLA, Vercel). Ready to approve.
Inline code that contains a backtick was exported with a single backtick delimiter, which is invalid Markdown and does not round-trip.
Example, for a code span whose content is the 3 characters a ` b:
This is common in real content, for instance writing documentation about Markdown itself, where inline code often needs to contain backticks.
This PR makes inline code follow the CommonMark code span rules:
the longest backtick run inside it), with padding spaces when needed.
losslessly.
No public API or serialization changes.
Test plan
a`bnow round-trips:New unit tests added in
LexicalMarkdown.test.ts: