2 * Copyright (c) Meta Platforms, Inc. and affiliates.
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
10 import type {RangeSelection} from 'lexical';
12 import {createHeadlessEditor} from '@lexical/headless';
13 import {$generateHtmlFromNodes, $generateNodesFromDOM} from '@lexical/html';
14 import {LinkNode} from '@lexical/link';
15 import {ListItemNode, ListNode} from '@lexical/list';
16 import {HeadingNode, QuoteNode} from '@lexical/rich-text';
19 $createRangeSelection,
24 describe('HTML', () => {
28 initializeEditorState: () => void;
31 const HTML_SERIALIZE: Input = [
34 initializeEditorState: () => {
35 $getRoot().append($createParagraphNode());
37 name: 'Empty editor state',
40 for (const {name, html, initializeEditorState} of HTML_SERIALIZE) {
41 test(`[Lexical -> HTML]: ${name}`, () => {
42 const editor = createHeadlessEditor({
52 editor.update(initializeEditorState, {
57 editor.getEditorState().read(() => $generateHtmlFromNodes(editor)),
62 test(`[Lexical -> HTML]: Use provided selection`, () => {
63 const editor = createHeadlessEditor({
73 let selection: RangeSelection | null = null;
77 const root = $getRoot();
78 const p1 = $createParagraphNode();
79 const text1 = $createTextNode('Hello');
81 const p2 = $createParagraphNode();
82 const text2 = $createTextNode('World');
84 root.append(p1).append(p2);
87 // -- TextNode "Hello"
89 // -- TextNode "World"
90 p1.select(0, text1.getTextContentSize());
91 selection = $createRangeSelection();
92 selection.setTextNodeRange(text2, 0, text2, text2.getTextContentSize());
101 editor.update(() => {
102 html = $generateHtmlFromNodes(editor, selection);
105 expect(html).toBe('<span style="white-space: pre-wrap;">World</span>');
108 test(`[Lexical -> HTML]: Default selection (undefined) should serialize entire editor state`, () => {
109 const editor = createHeadlessEditor({
121 const root = $getRoot();
122 const p1 = $createParagraphNode();
123 const text1 = $createTextNode('Hello');
125 const p2 = $createParagraphNode();
126 const text2 = $createTextNode('World');
128 root.append(p1).append(p2);
131 // -- TextNode "Hello"
133 // -- TextNode "World"
134 p1.select(0, text1.getTextContentSize());
143 editor.update(() => {
144 html = $generateHtmlFromNodes(editor);
148 '<p><span style="white-space: pre-wrap;">Hello</span></p><p><span style="white-space: pre-wrap;">World</span></p>',
152 test(`If alignment is set on the paragraph, don't overwrite from parent empty format`, () => {
153 const editor = createHeadlessEditor();
154 const parser = new DOMParser();
155 const rightAlignedParagraphInDiv =
156 '<div><p style="text-align: center;">Hello world!</p></div>';
160 const root = $getRoot();
161 const dom = parser.parseFromString(
162 rightAlignedParagraphInDiv,
165 const nodes = $generateNodesFromDOM(editor, dom);
166 root.append(...nodes);
173 editor.update(() => {
174 html = $generateHtmlFromNodes(editor);
178 '<p style="text-align: center;"><span style="white-space: pre-wrap;">Hello world!</span></p>',
182 test(`If alignment is set on the paragraph, it should take precedence over its parent block alignment`, () => {
183 const editor = createHeadlessEditor();
184 const parser = new DOMParser();
185 const rightAlignedParagraphInDiv =
186 '<div style="text-align: right;"><p style="text-align: center;">Hello world!</p></div>';
190 const root = $getRoot();
191 const dom = parser.parseFromString(
192 rightAlignedParagraphInDiv,
195 const nodes = $generateNodesFromDOM(editor, dom);
196 root.append(...nodes);
203 editor.update(() => {
204 html = $generateHtmlFromNodes(editor);
208 '<p style="text-align: center;"><span style="white-space: pre-wrap;">Hello world!</span></p>',