Skip to content

[lexical-markdown] Bug Fix: Inline code spans containing backticks#8723

Merged
etrepum merged 1 commit into
facebook:mainfrom
baptistejamin:fix/inline-code-fence
Jun 19, 2026
Merged

[lexical-markdown] Bug Fix: Inline code spans containing backticks#8723
etrepum merged 1 commit into
facebook:mainfrom
baptistejamin:fix/inline-code-fence

Conversation

@baptistejamin

@baptistejamin baptistejamin commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

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:

Before:  `a`b`        (corrupted, invalid Markdown)
After:   `` a`b ``    (valid CommonMark)

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:

  • Export: the fence is now computed from the content (one more backtick than
    the longest backtick run inside it), with padding spaces when needed.
  • Import: now parses multi-backtick code spans, so the content round-trips
    losslessly.

No public API or serialization changes.

Test plan

a`b now round-trips:

$convertToMarkdownString(TRANSFORMERS);
// Before: Here: `a`b`     (corrupted)
// After:  Here: `` a`b `` (valid CommonMark)

New unit tests added in LexicalMarkdown.test.ts:

@vercel

vercel Bot commented Jun 19, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
lexical Ready Ready Preview, Comment Jun 19, 2026 11:46am
lexical-playground Ready Ready Preview, Comment Jun 19, 2026 11:46am

Request Review

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Jun 19, 2026

@potatowagon potatowagon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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:

  1. Algorithm correctnessgetCodeSpanDelimiter() computes the longest backtick run in content and uses longestRun + 1 backticks 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).

  2. Import-side scanCodeSpans() — Correctly implements CommonMark opener/closer matching (same-length runs). The isEscaped() 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.

  3. Integration with exportTextFormat() — The isCode branch skips the character escaping (correct — code spans are literal), computes the fence, and sets trimmedOutput to the fully-fenced content. The continue statement for format === 'code' prevents double-wrapping with the static backtick tag. Other format tags (bold, italic) correctly wrap around the code span fence.

  4. 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.

  5. No regressions — Existing code span behavior unchanged (backtick-free content still gets single backtick fence). The excludeRanges mechanism still works — it now uses scanCodeSpans output instead of the regex, but produces equivalent ranges. All existing tests pass.

  6. www compatgetCodeSpanDelimiter is 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.

@etrepum etrepum added the extended-tests Run extended e2e tests on a PR label Jun 19, 2026
@etrepum etrepum added this pull request to the merge queue Jun 19, 2026
Merged via the queue into facebook:main with commit f8bb9da Jun 19, 2026
54 checks passed
@etrepum etrepum mentioned this pull request Jun 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. extended-tests Run extended e2e tests on a PR

3 participants