Skip to content

[lexical-code][lexical-playground] Bug Fix: Prevent formatting on TabNode inside code blocks#8752

Merged
etrepum merged 1 commit into
facebook:mainfrom
mayrang:fix/8749-tab-format-in-code-block
Jun 26, 2026
Merged

[lexical-code][lexical-playground] Bug Fix: Prevent formatting on TabNode inside code blocks#8752
etrepum merged 1 commit into
facebook:mainfrom
mayrang:fix/8749-tab-format-in-code-block

Conversation

@mayrang

@mayrang mayrang commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Description

The floating text format toolbar shows when selecting a TabNode inside a code block, and formatting (bold, highlight, etc.) sticks. CodeHighlightNode already blocks this via a no-op setFormat(), but TabNode inherits from TextNode and has no such guard.

Fix

CodeExtension now registers a registerNodeTransform(TabNode, ...) that strips format back to 0 when the parent is a CodeNode. A global TabNode.setFormat() override was not used because TabNode legitimately inherits format in normal paragraphs (the existing INSERT_TAB_COMMAND test verifies this).

The FloatingTextFormatToolbarPlugin guard is simplified from checking both $isCodeHighlightNode(anchor) and $isCodeNode(anchor.getParent()) to just $isCodeNode(anchor.getParent()) — the latter is a superset since CodeHighlightNode always has a CodeNode parent.

Closes #8749

Test plan

  • pnpm vitest run --project unit -t "CodeExtension" — 5 pass (including new "should strip format from TabNode inside CodeNode").
  • pnpm vitest run --project unit -t "TabNode" — 23 pass, no regression.
  • pnpm tsc --noEmit clean.
  • Manual playground:
    • Tab inside code block → select → no floating toolbar.
    • Tab in normal paragraph → formatting still works as before.

@vercel

vercel Bot commented Jun 26, 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 Jun 26, 2026 3:36pm
lexical-playground Ready Ready Preview Jun 26, 2026 3:36pm

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 26, 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 ✅ — Clean, targeted fix with good test coverage.

What this PR does

Prevents text formatting (bold, italic, etc.) from being applied to TabNode elements inside code blocks, and fixes the floating text format toolbar to correctly suppress itself when the selection is inside a code block.

What I checked

  1. Logic correctness:

    • The registerNodeTransform(TabNode, ...) approach is correct — it reactively strips formatting (setFormat(0)) whenever a TabNode inside a CodeNode has non-zero format. This covers all mutation paths (user applying format, paste, collaboration sync).
    • The parent check $isCodeNode(node.getParent()) is the right level — TabNodes are direct children of CodeNode, not nested deeper.
    • The toolbar fix changes from $isCodeHighlightNode(selection.anchor.getNode()) to $isCodeNode(selection.anchor.getNode().getParent()). This is more robust — the old check only caught CodeHighlightNode but missed TabNode (which is also a direct child of CodeNode). The new check catches ANY node whose parent is CodeNode.
  2. Edge cases:

    • node.getParent() could return null if the node is detached, but $isCodeNode(null) safely returns false — no crash risk.
    • The transform only fires when node.getFormat() !== 0, avoiding unnecessary writes/re-triggers.
    • mergeRegister correctly composes the existing KEY_ENTER_COMMAND handler with the new node transform — cleanup is properly handled.
  3. Test coverage:

    • New unit test should strip format from TabNode inside CodeNode properly exercises the transform: creates a tab inside code, applies format, then verifies it gets stripped back to 0. Uses {discrete: true} for synchronous verification.
  4. No regressions:

    • The toolbar change is playground-only (not library code), and the logic is strictly more correct (suppresses toolbar for all code-block children, not just CodeHighlightNode).
    • Unit tests pass on Node 22.x and 24.x. Browser tests pass. CLA signed. Vercel deploys pass.
  5. www compat:

    • No removed/renamed exports. $isCodeNode was already exported. mergeRegister and TabNode already exported from lexical. No breaking changes to public API.

CI status: Core unit + browser tests all green. Integrity check and one e2e canary still pending — recommend waiting for those to finish before merging, but no red flags.

Ready to approve once remaining CI checks complete.

Comment thread packages/lexical-code-core/src/CodeExtension.ts Outdated
…Node inside code blocks

TabNode inside a code block accepted text formatting (bold, highlight, etc.)
because it inherits TextNode.setFormat() — unlike CodeHighlightNode which
overrides setFormat() as a no-op. The floating toolbar also appeared when
selecting a TabNode inside a code block.

Register a TabNode transform in CodeExtension that strips format when the
tab is inside a CodeNode. Also add a $isCodeNode(parent) guard to the
floating toolbar so it hides for any node inside a code block, not just
CodeHighlightNode.

Closes facebook#8749
@mayrang mayrang force-pushed the fix/8749-tab-format-in-code-block branch from 2b4d827 to 5d9ae0f Compare June 26, 2026 15:35
@etrepum etrepum added this pull request to the merge queue Jun 26, 2026
Merged via the queue into facebook:main with commit daf6679 Jun 26, 2026
45 checks passed
@etrepum etrepum mentioned this pull request Jul 9, 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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: The toolbar is displayed above the TabNode inside the code block

3 participants