Skip to content

[lexical-markdown] Bug Fix: Fix nested fenced code blocks parsing and export#8116

Merged
etrepum merged 7 commits intofacebook:mainfrom
abdulalim110:fix/markdown-nested-code-blocks
Feb 8, 2026
Merged

[lexical-markdown] Bug Fix: Fix nested fenced code blocks parsing and export#8116
etrepum merged 7 commits intofacebook:mainfrom
abdulalim110:fix/markdown-nested-code-blocks

Conversation

@abdulalim110
Copy link
Copy Markdown
Contributor

[lexical-markdown] Bug Fix: Fix nested fenced code blocks parsing and export

Description

Current behavior:

Nested fenced code blocks (e.g., using 4 backticks to wrap 3 backticks) are corrupted during the Markdown round-trip. The parser prematurely closes the code block at the first encounter of a 3-backtick sequence, causing the remaining content and the original closing fence to leak into the editor as plain text.

Changes added by this PR:

  1. State Preservation: Introduced codeFenceState using createState to store the specific fence length (3, 4, 5+ backticks) used during import, ensuring the same length is used during export.

  2. Dynamic Fence Detection: Implemented handleImportAfterStartMatch with a dynamic Regex to ensure a code block only closes when it finds a fence with a length matching the opening fence.

  3. Edge Case Fixes:

    • Improved single-line code block detection to prevent content (like in ```Single line```) from being incorrectly parsed as a language attribute.

    • Added EOF (End of File) handling for unclosed code blocks to ensure they are correctly captured as code nodes instead of standard paragraphs.

    • Refined the CODE transformer Regex to properly separate the fence and language capture groups.

Closes #8109

Test plan

Before

Markdown content with nested fences would be rendered incorrectly in the Lexical editor. For example, a 4-backtick block would "break" at the inner 3-backtick block, leading to malformed output and extra escaped backticks ( \```` ) on export.

After

Automated Tests:

Added new unit tests in LexicalMarkdown.test.ts:

  • can round-trip nested fenced code blocks (4 backticks wrapping 3 backticks)

  • can round-trip deeply nested fenced code blocks (5 backticks wrapping 4 backticks)

  • Verified that single-line blocks and incomplete/unclosed tags still pass and render correctly as per CommonMark expectations.

Manual Verification:

Tested in the playground by switching between Markdown and Rich Text views with nested code examples. The structure and backtick count are now perfectly preserved.

@vercel
Copy link
Copy Markdown

vercel bot commented Feb 5, 2026

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

Project Deployment Actions Updated (UTC)
lexical Ready Ready Preview, Comment Feb 8, 2026 4:45pm
lexical-playground Ready Ready Preview, Comment Feb 8, 2026 4:45pm

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 Feb 5, 2026
Copy link
Copy Markdown
Collaborator

@etrepum etrepum left a comment

Choose a reason for hiding this comment

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

Overall this looks like a good direction but I think it can handle a few more edge cases

Comment on lines +226 to +228
if (typeof val === 'string' && val.startsWith('`')) {
return val;
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Might as well guarantee that it's a valid fence

Suggested change
if (typeof val === 'string' && val.startsWith('`')) {
return val;
}
if (typeof val === 'string' && /^`{3,}$/.test(val) {
return val;
}

Copy link
Copy Markdown
Collaborator

@etrepum etrepum left a comment

Choose a reason for hiding this comment

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

The only thing left here is to test that the computed fence works

@etrepum etrepum added the extended-tests Run extended e2e tests on a PR label Feb 6, 2026
@etrepum etrepum changed the title fix(markdown): fix nested fenced code blocks parsing and export [lexical-markdown] Bug Fix: Fix nested fenced code blocks parsing and export Feb 6, 2026
Copy link
Copy Markdown
Collaborator

@etrepum etrepum left a comment

Choose a reason for hiding this comment

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

There should be a test that the computed fence works. Right now it is only testing round-trips where the fence is not computed.

@abdulalim110
Copy link
Copy Markdown
Contributor Author

@etrepum I've added the test case (computes fence dynamically...) as requested.

this PR now addresses all feedback (redundant fallback removed + new test).

@etrepum etrepum added this pull request to the merge queue Feb 8, 2026
Merged via the queue into facebook:main with commit 70c1d23 Feb 8, 2026
39 checks passed
@etrepum etrepum mentioned this pull request Feb 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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: Nested fenced code blocks (4 backticks) are corrupted

2 participants