@lexical/html 0.37.1-nightly.20251027.0 → 0.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LexicalHtml.js CHANGED
@@ -6,6 +6,6 @@
6
6
  *
7
7
  */
8
8
 
9
- 'use strict'
10
- const LexicalHtml = process.env.NODE_ENV !== 'production' ? require('./LexicalHtml.dev.js') : require('./LexicalHtml.prod.js');
11
- module.exports = LexicalHtml;
9
+ 'use strict';
10
+
11
+ module.exports = require('./dist/LexicalHtml.js');
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "html"
9
9
  ],
10
10
  "license": "MIT",
11
- "version": "0.37.1-nightly.20251027.0",
11
+ "version": "0.38.0",
12
12
  "main": "LexicalHtml.js",
13
13
  "types": "index.d.ts",
14
14
  "repository": {
@@ -17,9 +17,9 @@
17
17
  "directory": "packages/lexical-html"
18
18
  },
19
19
  "dependencies": {
20
- "@lexical/selection": "0.37.1-nightly.20251027.0",
21
- "@lexical/utils": "0.37.1-nightly.20251027.0",
22
- "lexical": "0.37.1-nightly.20251027.0"
20
+ "@lexical/selection": "0.38.0",
21
+ "@lexical/utils": "0.38.0",
22
+ "lexical": "0.38.0"
23
23
  },
24
24
  "module": "LexicalHtml.mjs",
25
25
  "sideEffects": false,
@@ -0,0 +1,265 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import {CodeNode} from '@lexical/code';
10
+ import {createHeadlessEditor} from '@lexical/headless';
11
+ import {$generateHtmlFromNodes, $generateNodesFromDOM} from '@lexical/html';
12
+ import {LinkNode} from '@lexical/link';
13
+ import {ListItemNode, ListNode} from '@lexical/list';
14
+ import {HeadingNode, QuoteNode} from '@lexical/rich-text';
15
+ import {
16
+ $createParagraphNode,
17
+ $createRangeSelection,
18
+ $createTextNode,
19
+ $getRoot,
20
+ ParagraphNode,
21
+ RangeSelection,
22
+ } from 'lexical';
23
+ import {describe, expect, test} from 'vitest';
24
+
25
+ describe('HTML', () => {
26
+ type Input = Array<{
27
+ name: string;
28
+ html: string;
29
+ initializeEditorState: () => void;
30
+ }>;
31
+
32
+ const HTML_SERIALIZE: Input = [
33
+ {
34
+ html: '<p><br></p>',
35
+ initializeEditorState: () => {
36
+ $getRoot().append($createParagraphNode());
37
+ },
38
+ name: 'Empty editor state',
39
+ },
40
+ ];
41
+ for (const {name, html, initializeEditorState} of HTML_SERIALIZE) {
42
+ test(`[Lexical -> HTML]: ${name}`, () => {
43
+ const editor = createHeadlessEditor({
44
+ nodes: [
45
+ HeadingNode,
46
+ ListNode,
47
+ ListItemNode,
48
+ QuoteNode,
49
+ CodeNode,
50
+ LinkNode,
51
+ ],
52
+ });
53
+
54
+ editor.update(initializeEditorState, {
55
+ discrete: true,
56
+ });
57
+
58
+ expect(
59
+ editor.getEditorState().read(() => $generateHtmlFromNodes(editor)),
60
+ ).toBe(html);
61
+ });
62
+ }
63
+
64
+ test(`[Lexical -> HTML]: Use provided selection`, () => {
65
+ const editor = createHeadlessEditor({
66
+ nodes: [
67
+ HeadingNode,
68
+ ListNode,
69
+ ListItemNode,
70
+ QuoteNode,
71
+ CodeNode,
72
+ LinkNode,
73
+ ],
74
+ });
75
+
76
+ let selection: RangeSelection | null = null;
77
+
78
+ editor.update(
79
+ () => {
80
+ const root = $getRoot();
81
+ const p1 = $createParagraphNode();
82
+ const text1 = $createTextNode('Hello');
83
+ p1.append(text1);
84
+ const p2 = $createParagraphNode();
85
+ const text2 = $createTextNode('World');
86
+ p2.append(text2);
87
+ root.append(p1).append(p2);
88
+ // Root
89
+ // - ParagraphNode
90
+ // -- TextNode "Hello"
91
+ // - ParagraphNode
92
+ // -- TextNode "World"
93
+ p1.select(0, text1.getTextContentSize());
94
+ selection = $createRangeSelection();
95
+ selection.setTextNodeRange(text2, 0, text2, text2.getTextContentSize());
96
+ },
97
+ {
98
+ discrete: true,
99
+ },
100
+ );
101
+
102
+ let html = '';
103
+
104
+ editor.update(() => {
105
+ html = $generateHtmlFromNodes(editor, selection);
106
+ });
107
+
108
+ expect(html).toBe('<span style="white-space: pre-wrap;">World</span>');
109
+ });
110
+
111
+ test(`[Lexical -> HTML]: Default selection (undefined) should serialize entire editor state`, () => {
112
+ const editor = createHeadlessEditor({
113
+ nodes: [
114
+ HeadingNode,
115
+ ListNode,
116
+ ListItemNode,
117
+ QuoteNode,
118
+ CodeNode,
119
+ LinkNode,
120
+ ],
121
+ });
122
+
123
+ editor.update(
124
+ () => {
125
+ const root = $getRoot();
126
+ const p1 = $createParagraphNode();
127
+ const text1 = $createTextNode('Hello');
128
+ p1.append(text1);
129
+ const p2 = $createParagraphNode();
130
+ const text2 = $createTextNode('World');
131
+ p2.append(text2);
132
+ root.append(p1).append(p2);
133
+ // Root
134
+ // - ParagraphNode
135
+ // -- TextNode "Hello"
136
+ // - ParagraphNode
137
+ // -- TextNode "World"
138
+ p1.select(0, text1.getTextContentSize());
139
+ },
140
+ {
141
+ discrete: true,
142
+ },
143
+ );
144
+
145
+ let html = '';
146
+
147
+ editor.update(() => {
148
+ html = $generateHtmlFromNodes(editor);
149
+ });
150
+
151
+ expect(html).toBe(
152
+ '<p><span style="white-space: pre-wrap;">Hello</span></p><p><span style="white-space: pre-wrap;">World</span></p>',
153
+ );
154
+ });
155
+
156
+ test(`If alignment is set on the paragraph, don't overwrite from parent empty format`, () => {
157
+ const editor = createHeadlessEditor();
158
+ const parser = new DOMParser();
159
+ const rightAlignedParagraphInDiv =
160
+ '<div><p style="text-align: center;">Hello world!</p></div>';
161
+
162
+ editor.update(
163
+ () => {
164
+ const root = $getRoot();
165
+ const dom = parser.parseFromString(
166
+ rightAlignedParagraphInDiv,
167
+ 'text/html',
168
+ );
169
+ const nodes = $generateNodesFromDOM(editor, dom);
170
+ root.append(...nodes);
171
+ },
172
+ {discrete: true},
173
+ );
174
+
175
+ let html = '';
176
+
177
+ editor.update(() => {
178
+ html = $generateHtmlFromNodes(editor);
179
+ });
180
+
181
+ expect(html).toBe(
182
+ '<p style="text-align: center;"><span style="white-space: pre-wrap;">Hello world!</span></p>',
183
+ );
184
+ });
185
+
186
+ test(`If alignment is set on the paragraph, it should take precedence over its parent block alignment`, () => {
187
+ const editor = createHeadlessEditor();
188
+ const parser = new DOMParser();
189
+ const rightAlignedParagraphInDiv =
190
+ '<div style="text-align: right;"><p style="text-align: center;">Hello world!</p></div>';
191
+
192
+ editor.update(
193
+ () => {
194
+ const root = $getRoot();
195
+ const dom = parser.parseFromString(
196
+ rightAlignedParagraphInDiv,
197
+ 'text/html',
198
+ );
199
+ const nodes = $generateNodesFromDOM(editor, dom);
200
+ root.append(...nodes);
201
+ },
202
+ {discrete: true},
203
+ );
204
+
205
+ let html = '';
206
+
207
+ editor.update(() => {
208
+ html = $generateHtmlFromNodes(editor);
209
+ });
210
+
211
+ expect(html).toBe(
212
+ '<p style="text-align: center;"><span style="white-space: pre-wrap;">Hello world!</span></p>',
213
+ );
214
+ });
215
+
216
+ test('It should output correctly nodes whose export is DocumentFragment', () => {
217
+ const editor = createHeadlessEditor({
218
+ html: {
219
+ export: new Map([
220
+ [
221
+ ParagraphNode,
222
+ () => {
223
+ const element = document.createDocumentFragment();
224
+ return {
225
+ element,
226
+ };
227
+ },
228
+ ],
229
+ ]),
230
+ },
231
+ nodes: [],
232
+ });
233
+
234
+ editor.update(
235
+ () => {
236
+ const root = $getRoot();
237
+ const p1 = $createParagraphNode();
238
+ const text1 = $createTextNode('Hello');
239
+ p1.append(text1);
240
+ const p2 = $createParagraphNode();
241
+ const text2 = $createTextNode('World');
242
+ p2.append(text2);
243
+ root.append(p1).append(p2);
244
+ // Root
245
+ // - ParagraphNode
246
+ // -- TextNode "Hello"
247
+ // - ParagraphNode
248
+ // -- TextNode "World"
249
+ },
250
+ {
251
+ discrete: true,
252
+ },
253
+ );
254
+
255
+ let html = '';
256
+
257
+ editor.update(() => {
258
+ html = $generateHtmlFromNodes(editor);
259
+ });
260
+
261
+ expect(html).toBe(
262
+ '<span style="white-space: pre-wrap;">Hello</span><span style="white-space: pre-wrap;">World</span>',
263
+ );
264
+ });
265
+ });
@@ -6,56 +6,103 @@
6
6
  *
7
7
  */
8
8
 
9
- import { $sliceSelectedTextNodeContent } from '@lexical/selection';
10
- import { isHTMLElement, isBlockDomNode } from '@lexical/utils';
11
- import { isDOMDocumentNode, $getRoot, $isElementNode, $isTextNode, getRegisteredNode, isDocumentFragment, $isRootOrShadowRoot, $isBlockElementNode, $createLineBreakNode, ArtificialNode__DO_NOT_USE, isInlineDomNode, $createParagraphNode } from 'lexical';
12
-
13
- /**
14
- * Copyright (c) Meta Platforms, Inc. and affiliates.
15
- *
16
- * This source code is licensed under the MIT license found in the
17
- * LICENSE file in the root directory of this source tree.
18
- *
19
- */
9
+ import type {
10
+ BaseSelection,
11
+ DOMChildConversion,
12
+ DOMConversion,
13
+ DOMConversionFn,
14
+ ElementFormatType,
15
+ LexicalEditor,
16
+ LexicalNode,
17
+ } from 'lexical';
20
18
 
19
+ import {$sliceSelectedTextNodeContent} from '@lexical/selection';
20
+ import {isBlockDomNode, isHTMLElement} from '@lexical/utils';
21
+ import {
22
+ $createLineBreakNode,
23
+ $createParagraphNode,
24
+ $getRoot,
25
+ $isBlockElementNode,
26
+ $isElementNode,
27
+ $isRootOrShadowRoot,
28
+ $isTextNode,
29
+ ArtificialNode__DO_NOT_USE,
30
+ ElementNode,
31
+ getRegisteredNode,
32
+ isDocumentFragment,
33
+ isDOMDocumentNode,
34
+ isInlineDomNode,
35
+ } from 'lexical';
21
36
 
22
37
  /**
23
38
  * How you parse your html string to get a document is left up to you. In the browser you can use the native
24
39
  * DOMParser API to generate a document (see clipboard.ts), but to use in a headless environment you can use JSDom
25
40
  * or an equivalent library and pass in the document here.
26
41
  */
27
- function $generateNodesFromDOM(editor, dom) {
28
- const elements = isDOMDocumentNode(dom) ? dom.body.childNodes : dom.childNodes;
29
- let lexicalNodes = [];
30
- const allArtificialNodes = [];
42
+ export function $generateNodesFromDOM(
43
+ editor: LexicalEditor,
44
+ dom: Document | ParentNode,
45
+ ): Array<LexicalNode> {
46
+ const elements = isDOMDocumentNode(dom)
47
+ ? dom.body.childNodes
48
+ : dom.childNodes;
49
+ let lexicalNodes: Array<LexicalNode> = [];
50
+ const allArtificialNodes: Array<ArtificialNode__DO_NOT_USE> = [];
31
51
  for (const element of elements) {
32
52
  if (!IGNORE_TAGS.has(element.nodeName)) {
33
- const lexicalNode = $createNodesFromDOM(element, editor, allArtificialNodes, false);
53
+ const lexicalNode = $createNodesFromDOM(
54
+ element,
55
+ editor,
56
+ allArtificialNodes,
57
+ false,
58
+ );
34
59
  if (lexicalNode !== null) {
35
60
  lexicalNodes = lexicalNodes.concat(lexicalNode);
36
61
  }
37
62
  }
38
63
  }
39
64
  $unwrapArtificialNodes(allArtificialNodes);
65
+
40
66
  return lexicalNodes;
41
67
  }
42
- function $generateHtmlFromNodes(editor, selection) {
43
- if (typeof document === 'undefined' || typeof window === 'undefined' && typeof global.window === 'undefined') {
44
- throw new Error('To use $generateHtmlFromNodes in headless mode please initialize a headless browser implementation such as JSDom before calling this function.');
68
+
69
+ export function $generateHtmlFromNodes(
70
+ editor: LexicalEditor,
71
+ selection?: BaseSelection | null,
72
+ ): string {
73
+ if (
74
+ typeof document === 'undefined' ||
75
+ (typeof window === 'undefined' && typeof global.window === 'undefined')
76
+ ) {
77
+ throw new Error(
78
+ 'To use $generateHtmlFromNodes in headless mode please initialize a headless browser implementation such as JSDom before calling this function.',
79
+ );
45
80
  }
81
+
46
82
  const container = document.createElement('div');
47
83
  const root = $getRoot();
48
84
  const topLevelChildren = root.getChildren();
85
+
49
86
  for (let i = 0; i < topLevelChildren.length; i++) {
50
87
  const topLevelNode = topLevelChildren[i];
51
88
  $appendNodesToHTML(editor, topLevelNode, container, selection);
52
89
  }
90
+
53
91
  return container.innerHTML;
54
92
  }
55
- function $appendNodesToHTML(editor, currentNode, parentElement, selection = null) {
56
- let shouldInclude = selection !== null ? currentNode.isSelected(selection) : true;
57
- const shouldExclude = $isElementNode(currentNode) && currentNode.excludeFromCopy('html');
93
+
94
+ function $appendNodesToHTML(
95
+ editor: LexicalEditor,
96
+ currentNode: LexicalNode,
97
+ parentElement: HTMLElement | DocumentFragment,
98
+ selection: BaseSelection | null = null,
99
+ ): boolean {
100
+ let shouldInclude =
101
+ selection !== null ? currentNode.isSelected(selection) : true;
102
+ const shouldExclude =
103
+ $isElementNode(currentNode) && currentNode.excludeFromCopy('html');
58
104
  let target = currentNode;
105
+
59
106
  if (selection !== null && $isTextNode(currentNode)) {
60
107
  target = $sliceSelectedTextNodeContent(selection, currentNode, 'clone');
61
108
  }
@@ -69,26 +116,40 @@ function $appendNodesToHTML(editor, currentNode, parentElement, selection = null
69
116
  } else {
70
117
  exportOutput = target.exportDOM(editor);
71
118
  }
72
- const {
73
- element,
74
- after
75
- } = exportOutput;
119
+
120
+ const {element, after} = exportOutput;
121
+
76
122
  if (!element) {
77
123
  return false;
78
124
  }
125
+
79
126
  const fragment = document.createDocumentFragment();
127
+
80
128
  for (let i = 0; i < children.length; i++) {
81
129
  const childNode = children[i];
82
- const shouldIncludeChild = $appendNodesToHTML(editor, childNode, fragment, selection);
83
- if (!shouldInclude && $isElementNode(currentNode) && shouldIncludeChild && currentNode.extractWithChild(childNode, selection, 'html')) {
130
+ const shouldIncludeChild = $appendNodesToHTML(
131
+ editor,
132
+ childNode,
133
+ fragment,
134
+ selection,
135
+ );
136
+
137
+ if (
138
+ !shouldInclude &&
139
+ $isElementNode(currentNode) &&
140
+ shouldIncludeChild &&
141
+ currentNode.extractWithChild(childNode, selection, 'html')
142
+ ) {
84
143
  shouldInclude = true;
85
144
  }
86
145
  }
146
+
87
147
  if (shouldInclude && !shouldExclude) {
88
148
  if (isHTMLElement(element) || isDocumentFragment(element)) {
89
149
  element.append(fragment);
90
150
  }
91
151
  parentElement.append(element);
152
+
92
153
  if (after) {
93
154
  const newElement = after.call(target, element);
94
155
  if (newElement) {
@@ -102,52 +163,89 @@ function $appendNodesToHTML(editor, currentNode, parentElement, selection = null
102
163
  } else {
103
164
  parentElement.append(fragment);
104
165
  }
166
+
105
167
  return shouldInclude;
106
168
  }
107
- function getConversionFunction(domNode, editor) {
108
- const {
109
- nodeName
110
- } = domNode;
169
+
170
+ function getConversionFunction(
171
+ domNode: Node,
172
+ editor: LexicalEditor,
173
+ ): DOMConversionFn | null {
174
+ const {nodeName} = domNode;
175
+
111
176
  const cachedConversions = editor._htmlConversions.get(nodeName.toLowerCase());
112
- let currentConversion = null;
177
+
178
+ let currentConversion: DOMConversion | null = null;
179
+
113
180
  if (cachedConversions !== undefined) {
114
181
  for (const cachedConversion of cachedConversions) {
115
182
  const domConversion = cachedConversion(domNode);
116
- if (domConversion !== null && (currentConversion === null ||
117
- // Given equal priority, prefer the last registered importer
118
- // which is typically an application custom node or HTMLConfig['import']
119
- (currentConversion.priority || 0) <= (domConversion.priority || 0))) {
183
+ if (
184
+ domConversion !== null &&
185
+ (currentConversion === null ||
186
+ // Given equal priority, prefer the last registered importer
187
+ // which is typically an application custom node or HTMLConfig['import']
188
+ (currentConversion.priority || 0) <= (domConversion.priority || 0))
189
+ ) {
120
190
  currentConversion = domConversion;
121
191
  }
122
192
  }
123
193
  }
194
+
124
195
  return currentConversion !== null ? currentConversion.conversion : null;
125
196
  }
197
+
126
198
  const IGNORE_TAGS = new Set(['STYLE', 'SCRIPT']);
127
- function $createNodesFromDOM(node, editor, allArtificialNodes, hasBlockAncestorLexicalNode, forChildMap = new Map(), parentLexicalNode) {
128
- let lexicalNodes = [];
199
+
200
+ function $createNodesFromDOM(
201
+ node: Node,
202
+ editor: LexicalEditor,
203
+ allArtificialNodes: Array<ArtificialNode__DO_NOT_USE>,
204
+ hasBlockAncestorLexicalNode: boolean,
205
+ forChildMap: Map<string, DOMChildConversion> = new Map(),
206
+ parentLexicalNode?: LexicalNode | null | undefined,
207
+ ): Array<LexicalNode> {
208
+ let lexicalNodes: Array<LexicalNode> = [];
209
+
129
210
  if (IGNORE_TAGS.has(node.nodeName)) {
130
211
  return lexicalNodes;
131
212
  }
213
+
132
214
  let currentLexicalNode = null;
133
215
  const transformFunction = getConversionFunction(node, editor);
134
- const transformOutput = transformFunction ? transformFunction(node) : null;
216
+ const transformOutput = transformFunction
217
+ ? transformFunction(node as HTMLElement)
218
+ : null;
135
219
  let postTransform = null;
220
+
136
221
  if (transformOutput !== null) {
137
222
  postTransform = transformOutput.after;
138
223
  const transformNodes = transformOutput.node;
139
- currentLexicalNode = Array.isArray(transformNodes) ? transformNodes[transformNodes.length - 1] : transformNodes;
224
+ currentLexicalNode = Array.isArray(transformNodes)
225
+ ? transformNodes[transformNodes.length - 1]
226
+ : transformNodes;
227
+
140
228
  if (currentLexicalNode !== null) {
141
229
  for (const [, forChildFunction] of forChildMap) {
142
- currentLexicalNode = forChildFunction(currentLexicalNode, parentLexicalNode);
230
+ currentLexicalNode = forChildFunction(
231
+ currentLexicalNode,
232
+ parentLexicalNode,
233
+ );
234
+
143
235
  if (!currentLexicalNode) {
144
236
  break;
145
237
  }
146
238
  }
239
+
147
240
  if (currentLexicalNode) {
148
- lexicalNodes.push(...(Array.isArray(transformNodes) ? transformNodes : [currentLexicalNode]));
241
+ lexicalNodes.push(
242
+ ...(Array.isArray(transformNodes)
243
+ ? transformNodes
244
+ : [currentLexicalNode]),
245
+ );
149
246
  }
150
247
  }
248
+
151
249
  if (transformOutput.forChild != null) {
152
250
  forChildMap.set(node.nodeName, transformOutput.forChild);
153
251
  }
@@ -157,16 +255,38 @@ function $createNodesFromDOM(node, editor, allArtificialNodes, hasBlockAncestorL
157
255
  // to do with it but we still need to process any childNodes.
158
256
  const children = node.childNodes;
159
257
  let childLexicalNodes = [];
160
- const hasBlockAncestorLexicalNodeForChildren = currentLexicalNode != null && $isRootOrShadowRoot(currentLexicalNode) ? false : currentLexicalNode != null && $isBlockElementNode(currentLexicalNode) || hasBlockAncestorLexicalNode;
258
+
259
+ const hasBlockAncestorLexicalNodeForChildren =
260
+ currentLexicalNode != null && $isRootOrShadowRoot(currentLexicalNode)
261
+ ? false
262
+ : (currentLexicalNode != null &&
263
+ $isBlockElementNode(currentLexicalNode)) ||
264
+ hasBlockAncestorLexicalNode;
265
+
161
266
  for (let i = 0; i < children.length; i++) {
162
- childLexicalNodes.push(...$createNodesFromDOM(children[i], editor, allArtificialNodes, hasBlockAncestorLexicalNodeForChildren, new Map(forChildMap), currentLexicalNode));
267
+ childLexicalNodes.push(
268
+ ...$createNodesFromDOM(
269
+ children[i],
270
+ editor,
271
+ allArtificialNodes,
272
+ hasBlockAncestorLexicalNodeForChildren,
273
+ new Map(forChildMap),
274
+ currentLexicalNode,
275
+ ),
276
+ );
163
277
  }
278
+
164
279
  if (postTransform != null) {
165
280
  childLexicalNodes = postTransform(childLexicalNodes);
166
281
  }
282
+
167
283
  if (isBlockDomNode(node)) {
168
284
  if (!hasBlockAncestorLexicalNodeForChildren) {
169
- childLexicalNodes = wrapContinuousInlines(node, childLexicalNodes, $createParagraphNode);
285
+ childLexicalNodes = wrapContinuousInlines(
286
+ node,
287
+ childLexicalNodes,
288
+ $createParagraphNode,
289
+ );
170
290
  } else {
171
291
  childLexicalNodes = wrapContinuousInlines(node, childLexicalNodes, () => {
172
292
  const artificialNode = new ArtificialNode__DO_NOT_USE();
@@ -175,6 +295,7 @@ function $createNodesFromDOM(node, editor, allArtificialNodes, hasBlockAncestorL
175
295
  });
176
296
  }
177
297
  }
298
+
178
299
  if (currentLexicalNode == null) {
179
300
  if (childLexicalNodes.length > 0) {
180
301
  // If it hasn't been converted to a LexicalNode, we hoist its children
@@ -193,12 +314,19 @@ function $createNodesFromDOM(node, editor, allArtificialNodes, hasBlockAncestorL
193
314
  currentLexicalNode.append(...childLexicalNodes);
194
315
  }
195
316
  }
317
+
196
318
  return lexicalNodes;
197
319
  }
198
- function wrapContinuousInlines(domNode, nodes, createWrapperFn) {
199
- const textAlign = domNode.style.textAlign;
200
- const out = [];
201
- let continuousInlines = [];
320
+
321
+ function wrapContinuousInlines(
322
+ domNode: Node,
323
+ nodes: Array<LexicalNode>,
324
+ createWrapperFn: () => ElementNode,
325
+ ): Array<LexicalNode> {
326
+ const textAlign = (domNode as HTMLElement).style
327
+ .textAlign as ElementFormatType;
328
+ const out: Array<LexicalNode> = [];
329
+ let continuousInlines: Array<LexicalNode> = [];
202
330
  // wrap contiguous inline child nodes in para
203
331
  for (let i = 0; i < nodes.length; i++) {
204
332
  const node = nodes[i];
@@ -209,7 +337,10 @@ function wrapContinuousInlines(domNode, nodes, createWrapperFn) {
209
337
  out.push(node);
210
338
  } else {
211
339
  continuousInlines.push(node);
212
- if (i === nodes.length - 1 || i < nodes.length - 1 && $isBlockElementNode(nodes[i + 1])) {
340
+ if (
341
+ i === nodes.length - 1 ||
342
+ (i < nodes.length - 1 && $isBlockElementNode(nodes[i + 1]))
343
+ ) {
213
344
  const wrapper = createWrapperFn();
214
345
  wrapper.setFormat(textAlign);
215
346
  wrapper.append(...continuousInlines);
@@ -220,7 +351,10 @@ function wrapContinuousInlines(domNode, nodes, createWrapperFn) {
220
351
  }
221
352
  return out;
222
353
  }
223
- function $unwrapArtificialNodes(allArtificialNodes) {
354
+
355
+ function $unwrapArtificialNodes(
356
+ allArtificialNodes: Array<ArtificialNode__DO_NOT_USE>,
357
+ ) {
224
358
  for (const node of allArtificialNodes) {
225
359
  if (node.getNextSibling() instanceof ArtificialNode__DO_NOT_USE) {
226
360
  node.insertAfter($createLineBreakNode());
@@ -235,11 +369,12 @@ function $unwrapArtificialNodes(allArtificialNodes) {
235
369
  node.remove();
236
370
  }
237
371
  }
238
- function isDomNodeBetweenTwoInlineNodes(node) {
372
+
373
+ function isDomNodeBetweenTwoInlineNodes(node: Node): boolean {
239
374
  if (node.nextSibling == null || node.previousSibling == null) {
240
375
  return false;
241
376
  }
242
- return isInlineDomNode(node.nextSibling) && isInlineDomNode(node.previousSibling);
377
+ return (
378
+ isInlineDomNode(node.nextSibling) && isInlineDomNode(node.previousSibling)
379
+ );
243
380
  }
244
-
245
- export { $generateHtmlFromNodes, $generateNodesFromDOM };
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) Meta Platforms, Inc. and affiliates.
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
@@ -1,248 +0,0 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- */
8
-
9
- 'use strict';
10
-
11
- var selection = require('@lexical/selection');
12
- var utils = require('@lexical/utils');
13
- var lexical = require('lexical');
14
-
15
- /**
16
- * Copyright (c) Meta Platforms, Inc. and affiliates.
17
- *
18
- * This source code is licensed under the MIT license found in the
19
- * LICENSE file in the root directory of this source tree.
20
- *
21
- */
22
-
23
-
24
- /**
25
- * How you parse your html string to get a document is left up to you. In the browser you can use the native
26
- * DOMParser API to generate a document (see clipboard.ts), but to use in a headless environment you can use JSDom
27
- * or an equivalent library and pass in the document here.
28
- */
29
- function $generateNodesFromDOM(editor, dom) {
30
- const elements = lexical.isDOMDocumentNode(dom) ? dom.body.childNodes : dom.childNodes;
31
- let lexicalNodes = [];
32
- const allArtificialNodes = [];
33
- for (const element of elements) {
34
- if (!IGNORE_TAGS.has(element.nodeName)) {
35
- const lexicalNode = $createNodesFromDOM(element, editor, allArtificialNodes, false);
36
- if (lexicalNode !== null) {
37
- lexicalNodes = lexicalNodes.concat(lexicalNode);
38
- }
39
- }
40
- }
41
- $unwrapArtificialNodes(allArtificialNodes);
42
- return lexicalNodes;
43
- }
44
- function $generateHtmlFromNodes(editor, selection) {
45
- if (typeof document === 'undefined' || typeof window === 'undefined' && typeof global.window === 'undefined') {
46
- throw new Error('To use $generateHtmlFromNodes in headless mode please initialize a headless browser implementation such as JSDom before calling this function.');
47
- }
48
- const container = document.createElement('div');
49
- const root = lexical.$getRoot();
50
- const topLevelChildren = root.getChildren();
51
- for (let i = 0; i < topLevelChildren.length; i++) {
52
- const topLevelNode = topLevelChildren[i];
53
- $appendNodesToHTML(editor, topLevelNode, container, selection);
54
- }
55
- return container.innerHTML;
56
- }
57
- function $appendNodesToHTML(editor, currentNode, parentElement, selection$1 = null) {
58
- let shouldInclude = selection$1 !== null ? currentNode.isSelected(selection$1) : true;
59
- const shouldExclude = lexical.$isElementNode(currentNode) && currentNode.excludeFromCopy('html');
60
- let target = currentNode;
61
- if (selection$1 !== null && lexical.$isTextNode(currentNode)) {
62
- target = selection.$sliceSelectedTextNodeContent(selection$1, currentNode, 'clone');
63
- }
64
- const children = lexical.$isElementNode(target) ? target.getChildren() : [];
65
- const registeredNode = lexical.getRegisteredNode(editor, target.getType());
66
- let exportOutput;
67
-
68
- // Use HTMLConfig overrides, if available.
69
- if (registeredNode && registeredNode.exportDOM !== undefined) {
70
- exportOutput = registeredNode.exportDOM(editor, target);
71
- } else {
72
- exportOutput = target.exportDOM(editor);
73
- }
74
- const {
75
- element,
76
- after
77
- } = exportOutput;
78
- if (!element) {
79
- return false;
80
- }
81
- const fragment = document.createDocumentFragment();
82
- for (let i = 0; i < children.length; i++) {
83
- const childNode = children[i];
84
- const shouldIncludeChild = $appendNodesToHTML(editor, childNode, fragment, selection$1);
85
- if (!shouldInclude && lexical.$isElementNode(currentNode) && shouldIncludeChild && currentNode.extractWithChild(childNode, selection$1, 'html')) {
86
- shouldInclude = true;
87
- }
88
- }
89
- if (shouldInclude && !shouldExclude) {
90
- if (utils.isHTMLElement(element) || lexical.isDocumentFragment(element)) {
91
- element.append(fragment);
92
- }
93
- parentElement.append(element);
94
- if (after) {
95
- const newElement = after.call(target, element);
96
- if (newElement) {
97
- if (lexical.isDocumentFragment(element)) {
98
- element.replaceChildren(newElement);
99
- } else {
100
- element.replaceWith(newElement);
101
- }
102
- }
103
- }
104
- } else {
105
- parentElement.append(fragment);
106
- }
107
- return shouldInclude;
108
- }
109
- function getConversionFunction(domNode, editor) {
110
- const {
111
- nodeName
112
- } = domNode;
113
- const cachedConversions = editor._htmlConversions.get(nodeName.toLowerCase());
114
- let currentConversion = null;
115
- if (cachedConversions !== undefined) {
116
- for (const cachedConversion of cachedConversions) {
117
- const domConversion = cachedConversion(domNode);
118
- if (domConversion !== null && (currentConversion === null ||
119
- // Given equal priority, prefer the last registered importer
120
- // which is typically an application custom node or HTMLConfig['import']
121
- (currentConversion.priority || 0) <= (domConversion.priority || 0))) {
122
- currentConversion = domConversion;
123
- }
124
- }
125
- }
126
- return currentConversion !== null ? currentConversion.conversion : null;
127
- }
128
- const IGNORE_TAGS = new Set(['STYLE', 'SCRIPT']);
129
- function $createNodesFromDOM(node, editor, allArtificialNodes, hasBlockAncestorLexicalNode, forChildMap = new Map(), parentLexicalNode) {
130
- let lexicalNodes = [];
131
- if (IGNORE_TAGS.has(node.nodeName)) {
132
- return lexicalNodes;
133
- }
134
- let currentLexicalNode = null;
135
- const transformFunction = getConversionFunction(node, editor);
136
- const transformOutput = transformFunction ? transformFunction(node) : null;
137
- let postTransform = null;
138
- if (transformOutput !== null) {
139
- postTransform = transformOutput.after;
140
- const transformNodes = transformOutput.node;
141
- currentLexicalNode = Array.isArray(transformNodes) ? transformNodes[transformNodes.length - 1] : transformNodes;
142
- if (currentLexicalNode !== null) {
143
- for (const [, forChildFunction] of forChildMap) {
144
- currentLexicalNode = forChildFunction(currentLexicalNode, parentLexicalNode);
145
- if (!currentLexicalNode) {
146
- break;
147
- }
148
- }
149
- if (currentLexicalNode) {
150
- lexicalNodes.push(...(Array.isArray(transformNodes) ? transformNodes : [currentLexicalNode]));
151
- }
152
- }
153
- if (transformOutput.forChild != null) {
154
- forChildMap.set(node.nodeName, transformOutput.forChild);
155
- }
156
- }
157
-
158
- // If the DOM node doesn't have a transformer, we don't know what
159
- // to do with it but we still need to process any childNodes.
160
- const children = node.childNodes;
161
- let childLexicalNodes = [];
162
- const hasBlockAncestorLexicalNodeForChildren = currentLexicalNode != null && lexical.$isRootOrShadowRoot(currentLexicalNode) ? false : currentLexicalNode != null && lexical.$isBlockElementNode(currentLexicalNode) || hasBlockAncestorLexicalNode;
163
- for (let i = 0; i < children.length; i++) {
164
- childLexicalNodes.push(...$createNodesFromDOM(children[i], editor, allArtificialNodes, hasBlockAncestorLexicalNodeForChildren, new Map(forChildMap), currentLexicalNode));
165
- }
166
- if (postTransform != null) {
167
- childLexicalNodes = postTransform(childLexicalNodes);
168
- }
169
- if (utils.isBlockDomNode(node)) {
170
- if (!hasBlockAncestorLexicalNodeForChildren) {
171
- childLexicalNodes = wrapContinuousInlines(node, childLexicalNodes, lexical.$createParagraphNode);
172
- } else {
173
- childLexicalNodes = wrapContinuousInlines(node, childLexicalNodes, () => {
174
- const artificialNode = new lexical.ArtificialNode__DO_NOT_USE();
175
- allArtificialNodes.push(artificialNode);
176
- return artificialNode;
177
- });
178
- }
179
- }
180
- if (currentLexicalNode == null) {
181
- if (childLexicalNodes.length > 0) {
182
- // If it hasn't been converted to a LexicalNode, we hoist its children
183
- // up to the same level as it.
184
- lexicalNodes = lexicalNodes.concat(childLexicalNodes);
185
- } else {
186
- if (utils.isBlockDomNode(node) && isDomNodeBetweenTwoInlineNodes(node)) {
187
- // Empty block dom node that hasnt been converted, we replace it with a linebreak if its between inline nodes
188
- lexicalNodes = lexicalNodes.concat(lexical.$createLineBreakNode());
189
- }
190
- }
191
- } else {
192
- if (lexical.$isElementNode(currentLexicalNode)) {
193
- // If the current node is a ElementNode after conversion,
194
- // we can append all the children to it.
195
- currentLexicalNode.append(...childLexicalNodes);
196
- }
197
- }
198
- return lexicalNodes;
199
- }
200
- function wrapContinuousInlines(domNode, nodes, createWrapperFn) {
201
- const textAlign = domNode.style.textAlign;
202
- const out = [];
203
- let continuousInlines = [];
204
- // wrap contiguous inline child nodes in para
205
- for (let i = 0; i < nodes.length; i++) {
206
- const node = nodes[i];
207
- if (lexical.$isBlockElementNode(node)) {
208
- if (textAlign && !node.getFormat()) {
209
- node.setFormat(textAlign);
210
- }
211
- out.push(node);
212
- } else {
213
- continuousInlines.push(node);
214
- if (i === nodes.length - 1 || i < nodes.length - 1 && lexical.$isBlockElementNode(nodes[i + 1])) {
215
- const wrapper = createWrapperFn();
216
- wrapper.setFormat(textAlign);
217
- wrapper.append(...continuousInlines);
218
- out.push(wrapper);
219
- continuousInlines = [];
220
- }
221
- }
222
- }
223
- return out;
224
- }
225
- function $unwrapArtificialNodes(allArtificialNodes) {
226
- for (const node of allArtificialNodes) {
227
- if (node.getNextSibling() instanceof lexical.ArtificialNode__DO_NOT_USE) {
228
- node.insertAfter(lexical.$createLineBreakNode());
229
- }
230
- }
231
- // Replace artificial node with it's children
232
- for (const node of allArtificialNodes) {
233
- const children = node.getChildren();
234
- for (const child of children) {
235
- node.insertBefore(child);
236
- }
237
- node.remove();
238
- }
239
- }
240
- function isDomNodeBetweenTwoInlineNodes(node) {
241
- if (node.nextSibling == null || node.previousSibling == null) {
242
- return false;
243
- }
244
- return lexical.isInlineDomNode(node.nextSibling) && lexical.isInlineDomNode(node.previousSibling);
245
- }
246
-
247
- exports.$generateHtmlFromNodes = $generateHtmlFromNodes;
248
- exports.$generateNodesFromDOM = $generateNodesFromDOM;
package/LexicalHtml.mjs DELETED
@@ -1,13 +0,0 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- */
8
-
9
- import * as modDev from './LexicalHtml.dev.mjs';
10
- import * as modProd from './LexicalHtml.prod.mjs';
11
- const mod = process.env.NODE_ENV !== 'production' ? modDev : modProd;
12
- export const $generateHtmlFromNodes = mod.$generateHtmlFromNodes;
13
- export const $generateNodesFromDOM = mod.$generateNodesFromDOM;
@@ -1,11 +0,0 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- */
8
-
9
- const mod = await (process.env.NODE_ENV !== 'production' ? import('./LexicalHtml.dev.mjs') : import('./LexicalHtml.prod.mjs'));
10
- export const $generateHtmlFromNodes = mod.$generateHtmlFromNodes;
11
- export const $generateNodesFromDOM = mod.$generateNodesFromDOM;
@@ -1,9 +0,0 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- */
8
-
9
- "use strict";var e=require("@lexical/selection"),n=require("@lexical/utils"),t=require("lexical");function o(l,i,r,s=null){let c=null===s||i.isSelected(s);const d=t.$isElementNode(i)&&i.excludeFromCopy("html");let u=i;null!==s&&t.$isTextNode(i)&&(u=e.$sliceSelectedTextNodeContent(s,i,"clone"));const a=t.$isElementNode(u)?u.getChildren():[],f=t.getRegisteredNode(l,u.getType());let m;m=f&&void 0!==f.exportDOM?f.exportDOM(l,u):u.exportDOM(l);const{element:h,after:p}=m;if(!h)return!1;const g=document.createDocumentFragment();for(let e=0;e<a.length;e++){const n=a[e],r=o(l,n,g,s);!c&&t.$isElementNode(i)&&r&&i.extractWithChild(n,s,"html")&&(c=!0)}if(c&&!d){if((n.isHTMLElement(h)||t.isDocumentFragment(h))&&h.append(g),r.append(h),p){const e=p.call(u,h);e&&(t.isDocumentFragment(h)?h.replaceChildren(e):h.replaceWith(e))}}else r.append(g);return c}const l=new Set(["STYLE","SCRIPT"]);function i(e,o,s,c,d=new Map,u){let a=[];if(l.has(e.nodeName))return a;let f=null;const m=function(e,n){const{nodeName:t}=e,o=n._htmlConversions.get(t.toLowerCase());let l=null;if(void 0!==o)for(const n of o){const t=n(e);null!==t&&(null===l||(l.priority||0)<=(t.priority||0))&&(l=t)}return null!==l?l.conversion:null}(e,o),h=m?m(e):null;let p=null;if(null!==h){p=h.after;const n=h.node;if(f=Array.isArray(n)?n[n.length-1]:n,null!==f){for(const[,e]of d)if(f=e(f,u),!f)break;f&&a.push(...Array.isArray(n)?n:[f])}null!=h.forChild&&d.set(e.nodeName,h.forChild)}const g=e.childNodes;let N=[];const $=(null==f||!t.$isRootOrShadowRoot(f))&&(null!=f&&t.$isBlockElementNode(f)||c);for(let e=0;e<g.length;e++)N.push(...i(g[e],o,s,$,new Map(d),f));return null!=p&&(N=p(N)),n.isBlockDomNode(e)&&(N=r(e,N,$?()=>{const e=new t.ArtificialNode__DO_NOT_USE;return s.push(e),e}:t.$createParagraphNode)),null==f?N.length>0?a=a.concat(N):n.isBlockDomNode(e)&&function(e){if(null==e.nextSibling||null==e.previousSibling)return!1;return t.isInlineDomNode(e.nextSibling)&&t.isInlineDomNode(e.previousSibling)}(e)&&(a=a.concat(t.$createLineBreakNode())):t.$isElementNode(f)&&f.append(...N),a}function r(e,n,o){const l=e.style.textAlign,i=[];let r=[];for(let e=0;e<n.length;e++){const s=n[e];if(t.$isBlockElementNode(s))l&&!s.getFormat()&&s.setFormat(l),i.push(s);else if(r.push(s),e===n.length-1||e<n.length-1&&t.$isBlockElementNode(n[e+1])){const e=o();e.setFormat(l),e.append(...r),i.push(e),r=[]}}return i}exports.$generateHtmlFromNodes=function(e,n){if("undefined"==typeof document||"undefined"==typeof window&&void 0===global.window)throw new Error("To use $generateHtmlFromNodes in headless mode please initialize a headless browser implementation such as JSDom before calling this function.");const l=document.createElement("div"),i=t.$getRoot().getChildren();for(let t=0;t<i.length;t++){o(e,i[t],l,n)}return l.innerHTML},exports.$generateNodesFromDOM=function(e,n){const o=t.isDOMDocumentNode(n)?n.body.childNodes:n.childNodes;let r=[];const s=[];for(const n of o)if(!l.has(n.nodeName)){const t=i(n,e,s,!1);null!==t&&(r=r.concat(t))}return function(e){for(const n of e)n.getNextSibling()instanceof t.ArtificialNode__DO_NOT_USE&&n.insertAfter(t.$createLineBreakNode());for(const n of e){const e=n.getChildren();for(const t of e)n.insertBefore(t);n.remove()}}(s),r};
@@ -1,9 +0,0 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- */
8
-
9
- import{$sliceSelectedTextNodeContent as e}from"@lexical/selection";import{isHTMLElement as n,isBlockDomNode as t}from"@lexical/utils";import{isDOMDocumentNode as o,$getRoot as l,$isElementNode as r,$isTextNode as i,getRegisteredNode as s,isDocumentFragment as c,$isRootOrShadowRoot as u,$isBlockElementNode as f,$createLineBreakNode as a,ArtificialNode__DO_NOT_USE as d,isInlineDomNode as p,$createParagraphNode as h}from"lexical";function m(e,n){const t=o(n)?n.body.childNodes:n.childNodes;let l=[];const r=[];for(const n of t)if(!w.has(n.nodeName)){const t=y(n,e,r,!1);null!==t&&(l=l.concat(t))}return function(e){for(const n of e)n.getNextSibling()instanceof d&&n.insertAfter(a());for(const n of e){const e=n.getChildren();for(const t of e)n.insertBefore(t);n.remove()}}(r),l}function g(e,n){if("undefined"==typeof document||"undefined"==typeof window&&void 0===global.window)throw new Error("To use $generateHtmlFromNodes in headless mode please initialize a headless browser implementation such as JSDom before calling this function.");const t=document.createElement("div"),o=l().getChildren();for(let l=0;l<o.length;l++){x(e,o[l],t,n)}return t.innerHTML}function x(t,o,l,u=null){let f=null===u||o.isSelected(u);const a=r(o)&&o.excludeFromCopy("html");let d=o;null!==u&&i(o)&&(d=e(u,o,"clone"));const p=r(d)?d.getChildren():[],h=s(t,d.getType());let m;m=h&&void 0!==h.exportDOM?h.exportDOM(t,d):d.exportDOM(t);const{element:g,after:w}=m;if(!g)return!1;const y=document.createDocumentFragment();for(let e=0;e<p.length;e++){const n=p[e],l=x(t,n,y,u);!f&&r(o)&&l&&o.extractWithChild(n,u,"html")&&(f=!0)}if(f&&!a){if((n(g)||c(g))&&g.append(y),l.append(g),w){const e=w.call(d,g);e&&(c(g)?g.replaceChildren(e):g.replaceWith(e))}}else l.append(y);return f}const w=new Set(["STYLE","SCRIPT"]);function y(e,n,o,l,i=new Map,s){let c=[];if(w.has(e.nodeName))return c;let m=null;const g=function(e,n){const{nodeName:t}=e,o=n._htmlConversions.get(t.toLowerCase());let l=null;if(void 0!==o)for(const n of o){const t=n(e);null!==t&&(null===l||(l.priority||0)<=(t.priority||0))&&(l=t)}return null!==l?l.conversion:null}(e,n),x=g?g(e):null;let b=null;if(null!==x){b=x.after;const n=x.node;if(m=Array.isArray(n)?n[n.length-1]:n,null!==m){for(const[,e]of i)if(m=e(m,s),!m)break;m&&c.push(...Array.isArray(n)?n:[m])}null!=x.forChild&&i.set(e.nodeName,x.forChild)}const S=e.childNodes;let v=[];const N=(null==m||!u(m))&&(null!=m&&f(m)||l);for(let e=0;e<S.length;e++)v.push(...y(S[e],n,o,N,new Map(i),m));return null!=b&&(v=b(v)),t(e)&&(v=C(e,v,N?()=>{const e=new d;return o.push(e),e}:h)),null==m?v.length>0?c=c.concat(v):t(e)&&function(e){if(null==e.nextSibling||null==e.previousSibling)return!1;return p(e.nextSibling)&&p(e.previousSibling)}(e)&&(c=c.concat(a())):r(m)&&m.append(...v),c}function C(e,n,t){const o=e.style.textAlign,l=[];let r=[];for(let e=0;e<n.length;e++){const i=n[e];if(f(i))o&&!i.getFormat()&&i.setFormat(o),l.push(i);else if(r.push(i),e===n.length-1||e<n.length-1&&f(n[e+1])){const e=t();e.setFormat(o),e.append(...r),l.push(e),r=[]}}return l}export{g as $generateHtmlFromNodes,m as $generateNodesFromDOM};
package/index.d.ts DELETED
@@ -1,15 +0,0 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- */
8
- import type { BaseSelection, LexicalEditor, LexicalNode } from 'lexical';
9
- /**
10
- * How you parse your html string to get a document is left up to you. In the browser you can use the native
11
- * DOMParser API to generate a document (see clipboard.ts), but to use in a headless environment you can use JSDom
12
- * or an equivalent library and pass in the document here.
13
- */
14
- export declare function $generateNodesFromDOM(editor: LexicalEditor, dom: Document | ParentNode): Array<LexicalNode>;
15
- export declare function $generateHtmlFromNodes(editor: LexicalEditor, selection?: BaseSelection | null): string;