[Breaking Change][lexical] Fix: Preserve the first linebreak when passing inline nodes to insertNodes#8615
[Breaking Change][lexical] Fix: Preserve the first linebreak when passing inline nodes to insertNodes#8615levensta wants to merge 6 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
There are two We can either settle for a small refactoring of wrapInlineNodes or try to solve this issue #3980 |
| return [parent, node.getIndexWithinParent() + 1]; | ||
| } | ||
|
|
||
| function $wrapInlineNodes(nodes: LexicalNode[]) { |
There was a problem hiding this comment.
I'm also thinking about how we could export a common function to normalize inline elements for shadow root elements.
If we use this function as is, its use in a transformation would look like this:
const children = node.getChildren();
if (
node.isEmpty() ||
children.some(
child =>
$isLineBreakNode(child) ||
$isInlineElementOrDecoratorNode(child) ||
$isTextNode(child) ||
child.isParentRequired(),
)
) {
node.append(...$wrapInlineNodes(children).getChildren());
}Which doesn't look effective
Review (automated — Navi for @potatowagon)Status: Not ready to approve — CI still failing What changed (latest commit
|
potatowagon
left a comment
There was a problem hiding this comment.
Review — Preserve First Linebreak in insertNodes
Assessment: Has concerns
What I verified:
-
Logic correctness: The change to
$wrapInlineNodessimplifies the wrapping logic — it now unconditionally appends LineBreakNodes intocurrentBlockrather than skipping them (the old code created a parent block but thencontinued, effectively dropping the LineBreak from the block's children). The refactored code is cleaner: it uses$isInlineElementOrDecoratorNodeand always appends tocurrentBlock. -
Breaking change assessment: This is marked as a breaking change. The behavior change is: previously, a leading LineBreakNode before inline content would result in an empty paragraph; now it's preserved inside the wrapping paragraph. This is arguably more correct behavior (issue #4295), but it may affect existing consumers who rely on the current
insertNodesbehavior. -
Test coverage: Tests that were previously commented out (referencing issue #4295) are now enabled. A new regression test (
$wrapInlineNodes regression) explicitly verifies LineBreakNode is preserved in the wrapping paragraph.
Concerns:
CI is failing: Unit tests on Node 22.x and 24.x are red. This needs to be addressed before merge. The e2e tests pass, but the core unit tests do not — which likely means the test expectations or the logic has a mismatch that needs investigation.
The fix should be verified once CI is green. The conceptual change is sound, but cannot recommend landing with failing tests.
— via Navi on behalf of potatowagon
|
I just corrected the test, in general it already reflects the correct behavior: 1 |
|
Maybe we should set something on the DOM on the managed line breaks like |
|
I've thought about this, but it doesn't seem to serve much purpose. Maybe just as additional information that this is a special Or perhaps we should instead set the |
|
data-lexical-managed-linebreak might be a better name for the attribute. I don't think setting data-lexical-linebreak on all LineBreakNode is worthwhile. The value here is mostly to help people with debugging and to be an easy target to unambiguously normalize them away (e.g. on import or on a serialization style html export) |
b119d43 to
514cfe6
Compare
|
Done, now all managed linebreaks have the attribute |
Description
RangeSelection.insertNodesmethod. The first linebreak is always preservedattribute data-lexical-managed-linebreak="true"has been added to managed line break. This is done to make debugging and reading tests easier, where you need to distinguish where<br>is inserted from LineBreakNode, and where a managed line break is used to display an empty line.For example, this is what a paragraph containing a single line break would look like in the DOM
Closes #3980
Test plan
Before
For example, if when calling
$insertNodes()there are inline nodes, at least one block element, and the first node is a LineBreakNodeThen the linebreak is removed, and the remaining inlines are wrapped in a paragraph
After
Now the first linebreak is preserved