Skip to content

Commit

Permalink
[lexical-html] Feature: support pasting empty block nodes (#6392)
Browse files Browse the repository at this point in the history
  • Loading branch information
potatowagon authored Jul 12, 2024
1 parent 1ecef21 commit 2e26b74
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 22 deletions.
23 changes: 20 additions & 3 deletions packages/lexical-html/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
$isTextNode,
ArtificialNode__DO_NOT_USE,
ElementNode,
isInlineDomNode,
} from 'lexical';

/**
Expand Down Expand Up @@ -294,9 +295,16 @@ function $createNodesFromDOM(
}

if (currentLexicalNode == null) {
// If it hasn't been converted to a LexicalNode, we hoist its children
// up to the same level as it.
lexicalNodes = lexicalNodes.concat(childLexicalNodes);
if (childLexicalNodes.length > 0) {
// If it hasn't been converted to a LexicalNode, we hoist its children
// up to the same level as it.
lexicalNodes = lexicalNodes.concat(childLexicalNodes);
} else {
if (isBlockDomNode(node) && isDomNodeBetweenTwoInlineNodes(node)) {
// Empty block dom node that hasnt been converted, we replace it with a linebreak if its between inline nodes
lexicalNodes = lexicalNodes.concat($createLineBreakNode());
}
}
} else {
if ($isElementNode(currentLexicalNode)) {
// If the current node is a ElementNode after conversion,
Expand Down Expand Up @@ -359,3 +367,12 @@ function $unwrapArtificalNodes(
node.remove();
}
}

function isDomNodeBetweenTwoInlineNodes(node: Node): boolean {
if (node.nextSibling == null || node.previousSibling == null) {
return false;
}
return (
isInlineDomNode(node.nextSibling) && isInlineDomNode(node.previousSibling)
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,42 @@ describe('LexicalEventHelpers', () => {
],
name: 'two lines and br in spans',
},
{
expectedHTML:
'<ol class="editor-list-ol"><li value="1" class="editor-listitem"><span data-lexical-text="true">1</span><br><span data-lexical-text="true">2</span></li><li value="2" class="editor-listitem"><br></li><li value="3" class="editor-listitem"><span data-lexical-text="true">3</span></li></ol>',
inputs: [
pasteHTML('<ol><li>1<div></div>2</li><li></li><li>3</li></ol>'),
],
name: 'empty block node in li behaves like a line break',
},
{
expectedHTML:
'<p class="editor-paragraph"><span data-lexical-text="true">1</span><br><span data-lexical-text="true">2</span></p>',
inputs: [pasteHTML('<div>1<div></div>2</div>')],
name: 'empty block node in div behaves like a line break',
},
{
expectedHTML:
'<p class="editor-paragraph"><span data-lexical-text="true">12</span></p>',
inputs: [pasteHTML('<div>1<text></text>2</div>')],
name: 'empty inline node does not behave like a line break',
},
{
expectedHTML:
'<p class="editor-paragraph"><span data-lexical-text="true">1</span></p><p class="editor-paragraph"><span data-lexical-text="true">2</span></p>',
inputs: [pasteHTML('<div><div>1</div><div></div><div>2</div></div>')],
name: 'empty block node between non inline siblings does not behave like a line break',
},
{
expectedHTML:
'<p class="editor-paragraph" dir="ltr"><span data-lexical-text="true">a</span></p><p class="editor-paragraph" dir="ltr"><span data-lexical-text="true">b b</span></p><p class="editor-paragraph" dir="ltr"><span data-lexical-text="true">c</span></p><p class="editor-paragraph" dir="ltr"><span data-lexical-text="true">z</span></p><p class="editor-paragraph" dir="ltr"><span data-lexical-text="true">d e</span></p><p class="editor-paragraph" dir="ltr"><span data-lexical-text="true">fg</span></p>',
inputs: [
pasteHTML(
`<div>a<div>b b<div>c<div><div></div>z</div></div>d e</div>fg</div>`,
),
],
name: 'nested divs',
},
];

suite.forEach((testUnit, i) => {
Expand Down
19 changes: 0 additions & 19 deletions packages/lexical/src/__tests__/unit/HTMLCopyAndPaste.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,25 +51,6 @@ describe('HTMLCopyAndPaste tests', () => {
456
</div>`,
},
{
expectedHTML: `<p dir="ltr"><span data-lexical-text="true">a</span></p><p dir="ltr"><span data-lexical-text="true">b b</span></p><p dir="ltr"><span data-lexical-text="true">c</span></p><p dir="ltr"><span data-lexical-text="true">z </span></p><p dir="ltr"><span data-lexical-text="true">d e </span></p><p dir="ltr"><span data-lexical-text="true">fg</span></p>`,
name: 'nested divs',
pastedHTML: `<div>
a
<div>
b b
<div>
c
<div>
<div></div>
z
</div>
</div>
d e
</div>
fg
</div>`,
},
{
expectedHTML: `<p dir="ltr"><span data-lexical-text="true">a b c d e</span></p><p dir="ltr"><span data-lexical-text="true">f g h</span></p>`,
name: 'multiple nested spans and divs',
Expand Down

0 comments on commit 2e26b74

Please sign in to comment.