Repository navigation
Conversation
… inline without the line break caret regression OverflowNode.isInline() now returns true (meta#6027, reverted in meta#6535). The revert was caused by a trailing LineBreakNode inside the now inline OverflowNode: the browser can't put the caret after a <br> that ends an inline element, so the next character landed before the line break. - The reconciler gives a block the managed trailing <br> when its last child is an inline element that itself ends with a LineBreakNode. - $wrapOverflowedNodes moves a caret left at the end of an OverflowNode ending with a line break to the same spot just after the OverflowNode. Closes meta#9454 Signed-off-by: Ved Thakar <111605341+Vedthakar@users.noreply.github.com> Co-authored-by: Ved Thakar <111605341+Vedthakar@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Vedthakar
requested review from
acywatson,
etrepum,
fantactuka,
ivailop7,
potatowagon and
zurfyx
as code owners
October 25, 2026 01:07
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
lexical
@lexical/a11y
@lexical/clipboard
@lexical/code
@lexical/code-core
@lexical/code-prism
@lexical/code-shiki
@lexical/compiler
@lexical/devtools-core
@lexical/dragon
@lexical/eslint-plugin
@lexical/extension
@lexical/fast-check
@lexical/file
@lexical/hashtag
@lexical/headless
@lexical/history
@lexical/html
@lexical/internal
@lexical/link
@lexical/list
@lexical/mark
@lexical/markdown
@lexical/mdast
@lexical/offset
@lexical/overflow
@lexical/plain-text
@lexical/react
@lexical/rich-text
@lexical/selection
@lexical/table
@lexical/tailwind
@lexical/text
@lexical/utils
@lexical/yjs
commit: |
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
This solves issue #9454.
OverflowNodeis now inline (isInline()returnstrue), as #6027 first tried. #6535 reverted #6027 because, in plain-text mode or with Shift+Enter in rich text, a line break typed at the end of the overflow left the caret before the trailingLineBreakNode.Root cause. Once
OverflowNodeis inline, a<br>ends up as the last thing inside an inline<span>at the end of a paragraph. Two things then go wrong:<br>only when a block's direct last child is aLineBreakNode. Here the paragraph's last child is theOverflowNode, so no managed<br>is added and the new empty line has no caret position.OverflowNode, past its<br>. The browser can't put the caret there and moves it to before the overflow, so the next character goes in front of the6. The test saw76instead of6<br>7.Changes
lexical-overflow:OverflowNode.isInline()returnstrue.lexical(reconciler):$isLastChildLineBreakOrDecoratoralso counts aLineBreakNodereached through trailing inline elements, so that block gets the managed<br>. This also fixes the same layout for other inline elements, such as aLinkNodeending with a line break. Decorators are unchanged.lexical-react(useCharacterLimit): after wrapping and merging, a selection point at the end of anOverflowNodewhose last child is aLineBreakNodemoves to the same position just after theOverflowNodein its parent.NodeStructureExtension.test.ts: the [lexical][lexical-code-core][lexical-devtools][lexical-extension][lexical-link][lexical-list][lexical-mark][lexical-mdast][lexical-rich-text][lexical-table][lexical-website] Feature: Experimental node structure in $config (inline, children, mergeAdjacent, derived) and an opt-in NodeStructureExtension #9452 assertion now expectsoverflow.isInline()to betrue. Follow-up for maintainers: theisOverflowClass/isOverflowNodeexemptions inLexicalStructure.tscould probably be removed now; this PR leaves them alone.Closes #9454
Test plan
Before
isInline()alone (the Fix OverflowNode configuration #6027 configuration),packages/lexical-playground/src/__tests__/browser/CharacterLimit.test.ts(vitest browser, chromium): 6 failed | 10 passed (16). This is the Revert "Fix OverflowNode configuration" #6535 regression: the caret lands before the line break in plain text, and thedelete text in frontcases fail.packages/lexical-react/src/__tests__/unit/useLexicalCharacterLimit.test.tsagainstmain: 3 failed | 7 passed (10).packages/lexical/src/__tests__/unit/LexicalReconciler.test.ts(a paragraph ending in aLinkNodewhose last child is aLineBreakNode) againstmain: 1 failed. No managed<br>is rendered after the<a>.After
On current
main(tested together with my other open fixes):useLexicalCharacterLimit.test.ts,LexicalReconciler.test.tsandNodeStructureExtension.test.ts: 131 passed (5 fail onmain).CharacterLimit.test.ts(browser, Chromium): 20 passed.CharacterLimit.spec.mjs,Links.spec.mjs,Selection.spec.mjsandregression/1113-link-newline-at-end.spec.mjspass.pnpm run test-unit: all 10,080 tests passtsc,pnpm run flow(0 errors), and eslint/prettier on the changed files: cleanAuthor: Ved Thakar (@Vedthakar)
🤖 Generated with Claude Code