Skip to content

Commit

Permalink
Use provided selection when serializing to HTML (#4392)
Browse files Browse the repository at this point in the history
  • Loading branch information
acywatson committed Apr 24, 2023
1 parent ffb2f69 commit 66741ef
Show file tree
Hide file tree
Showing 2 changed files with 155 additions and 1 deletion.
153 changes: 153 additions & 0 deletions packages/lexical-html/src/__tests__/unit/LexicalHtml.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/

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

import {CodeNode} from '@lexical/code';
import {createHeadlessEditor} from '@lexical/headless';
import {$generateHtmlFromNodes} from '@lexical/html';
import {LinkNode} from '@lexical/link';
import {ListItemNode, ListNode} from '@lexical/list';
import {HeadingNode, QuoteNode} from '@lexical/rich-text';
import {
$createParagraphNode,
$createRangeSelection,
$createTextNode,
$getRoot,
} from 'lexical';

describe('HTML', () => {
type Input = Array<{
name: string;
html: string;
initializeEditorState: () => void;
}>;

const HTML_SERIALIZE: Input = [
{
html: '<p><br></p>',
initializeEditorState: () => {
$getRoot().append($createParagraphNode());
},
name: 'Empty editor state',
},
];
for (const {name, html, initializeEditorState} of HTML_SERIALIZE) {
test(`[Lexical -> HTML]: ${name}`, () => {
const editor = createHeadlessEditor({
nodes: [
HeadingNode,
ListNode,
ListItemNode,
QuoteNode,
CodeNode,
LinkNode,
],
});

editor.update(initializeEditorState, {
discrete: true,
});

expect(
editor.getEditorState().read(() => $generateHtmlFromNodes(editor)),
).toBe(html);
});
}

test(`[Lexical -> HTML]: Use provided selection`, () => {
const editor = createHeadlessEditor({
nodes: [
HeadingNode,
ListNode,
ListItemNode,
QuoteNode,
CodeNode,
LinkNode,
],
});

let selection: RangeSelection | null = null;

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"
p1.select(0, text1.getTextContentSize());
selection = $createRangeSelection();
selection.setTextNodeRange(text2, 0, text2, text2.getTextContentSize());
},
{
discrete: true,
},
);

let html = '';

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

expect(html).toBe('<span>World</span>');
});

test(`[Lexical -> HTML]: Default selection (undefined) should serialize entire editor state`, () => {
const editor = createHeadlessEditor({
nodes: [
HeadingNode,
ListNode,
ListItemNode,
QuoteNode,
CodeNode,
LinkNode,
],
});

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"
p1.select(0, text1.getTextContentSize());
},
{
discrete: true,
},
);

let html = '';

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

expect(html).toBe('<p><span>Hello</span></p><p><span>World</span></p>');
});
});
3 changes: 2 additions & 1 deletion packages/lexical-html/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ function $appendNodesToHTML(
parentElement: HTMLElement | DocumentFragment,
selection: RangeSelection | NodeSelection | GridSelection | null = null,
): boolean {
let shouldInclude = selection != null ? currentNode.isSelected() : true;
let shouldInclude =
selection != null ? currentNode.isSelected(selection) : true;
const shouldExclude =
$isElementNode(currentNode) && currentNode.excludeFromCopy('html');
let target = currentNode;
Expand Down

2 comments on commit 66741ef

@vercel
Copy link

@vercel vercel bot commented on 66741ef Apr 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

lexical – ./packages/lexical-website

lexical-fbopensource.vercel.app
lexicaljs.org
lexical.dev
lexical-git-main-fbopensource.vercel.app
lexicaljs.com
www.lexical.dev

@vercel
Copy link

@vercel vercel bot commented on 66741ef Apr 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

lexical-playground – ./packages/lexical-playground

playground.lexical.dev
lexical-playground-git-main-fbopensource.vercel.app
lexical-playground-fbopensource.vercel.app
lexical-playground.vercel.app

Please sign in to comment.