Skip to content

Commit

Permalink
Allow exporting a document fragment from the exportDOM function (#6641)
Browse files Browse the repository at this point in the history
Co-authored-by: Tomáš Kubát <tomas.kubat@omnetic.com>
  • Loading branch information
skopz356 and Tomáš Kubát authored Sep 18, 2024
1 parent 8fb96f9 commit fc8cf09
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 7 deletions.
55 changes: 52 additions & 3 deletions packages/lexical-html/src/__tests__/unit/LexicalHtml.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@
*
*/

//@ts-ignore-next-line
import type {RangeSelection} from 'lexical';

import {CodeNode} from '@lexical/code';
import {createHeadlessEditor} from '@lexical/headless';
import {$generateHtmlFromNodes, $generateNodesFromDOM} from '@lexical/html';
Expand All @@ -20,6 +17,8 @@ import {
$createRangeSelection,
$createTextNode,
$getRoot,
ParagraphNode,
RangeSelection,
} from 'lexical';

describe('HTML', () => {
Expand Down Expand Up @@ -212,4 +211,54 @@ describe('HTML', () => {
'<p style="text-align: center;"><span style="white-space: pre-wrap;">Hello world!</span></p>',
);
});

test('It should output correctly nodes whose export is DocumentFragment', () => {
const editor = createHeadlessEditor({
html: {
export: new Map([
[
ParagraphNode,
() => {
const element = document.createDocumentFragment();
return {
element,
};
},
],
]),
},
nodes: [],
});

editor.update(
() => {
const root = $getRoot();
const p1 = $createParagraphNode();
const text1 = $createTextNode('Hello');
p1.append(text1);
const p2 = $createParagraphNode();
const text2 = $createTextNode('World');
p2.append(text2);
root.append(p1).append(p2);
// Root
// - ParagraphNode
// -- TextNode "Hello"
// - ParagraphNode
// -- TextNode "World"
},
{
discrete: true,
},
);

let html = '';

editor.update(() => {
html = $generateHtmlFromNodes(editor);
});

expect(html).toBe(
'<span style="white-space: pre-wrap;">Hello</span><span style="white-space: pre-wrap;">World</span>',
);
});
});
9 changes: 7 additions & 2 deletions packages/lexical-html/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
$isTextNode,
ArtificialNode__DO_NOT_USE,
ElementNode,
isDocumentFragment,
isInlineDomNode,
} from 'lexical';

Expand Down Expand Up @@ -147,15 +148,19 @@ function $appendNodesToHTML(
}

if (shouldInclude && !shouldExclude) {
if (isHTMLElement(element)) {
if (isHTMLElement(element) || isDocumentFragment(element)) {
element.append(fragment);
}
parentElement.append(element);

if (after) {
const newElement = after.call(target, element);
if (newElement) {
element.replaceWith(newElement);
if (isDocumentFragment(element)) {
element.replaceChildren(newElement);
} else {
element.replaceWith(newElement);
}
}
}
} else {
Expand Down
4 changes: 2 additions & 2 deletions packages/lexical/src/LexicalNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,9 @@ export type DOMExportOutputMap = Map<

export type DOMExportOutput = {
after?: (
generatedElement: HTMLElement | Text | null | undefined,
generatedElement: HTMLElement | DocumentFragment | Text | null | undefined,
) => HTMLElement | Text | null | undefined;
element: HTMLElement | Text | null;
element: HTMLElement | DocumentFragment | Text | null;
};

export type NodeKey = string;
Expand Down
11 changes: 11 additions & 0 deletions packages/lexical/src/LexicalUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1668,6 +1668,17 @@ export function isHTMLElement(x: Node | EventTarget): x is HTMLElement {
return x.nodeType === 1;
}

/**
* @param x - The element being testing
* @returns Returns true if x is a document fragment, false otherwise.
*/
export function isDocumentFragment(
x: Node | EventTarget,
): x is DocumentFragment {
// @ts-ignore-next-line - strict check on nodeType here should filter out non-Element EventTarget implementors
return x.nodeType === 11;
}

/**
*
* @param node - the Dom Node to check
Expand Down
1 change: 1 addition & 0 deletions packages/lexical/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ export {
getEditorPropertyFromDOMNode,
getNearestEditorFromDOMNode,
isBlockDomNode,
isDocumentFragment,
isHTMLAnchorElement,
isHTMLElement,
isInlineDomNode,
Expand Down

0 comments on commit fc8cf09

Please sign in to comment.