@lexical/html 0.44.1-nightly.20260519.0 → 0.45.1-dev.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.
Files changed (66) hide show
  1. package/{DOMRenderExtension.d.ts → dist/DOMRenderExtension.d.ts} +12 -1
  2. package/dist/DOMRenderRuntime.d.ts +51 -0
  3. package/dist/LexicalHtml.dev.js +3289 -0
  4. package/dist/LexicalHtml.dev.mjs +3242 -0
  5. package/{LexicalHtml.js.flow → dist/LexicalHtml.js.flow} +16 -16
  6. package/dist/LexicalHtml.mjs +57 -0
  7. package/dist/LexicalHtml.node.mjs +55 -0
  8. package/dist/LexicalHtml.prod.js +9 -0
  9. package/dist/LexicalHtml.prod.mjs +9 -0
  10. package/dist/RenderContext.d.ts +68 -0
  11. package/{compileDOMRenderConfigOverrides.d.ts → dist/compileDOMRenderConfigOverrides.d.ts} +1 -1
  12. package/{constants.d.ts → dist/constants.d.ts} +2 -0
  13. package/dist/domOverride.d.ts +23 -0
  14. package/dist/import/CoreImportExtension.d.ts +11 -0
  15. package/dist/import/DOMImportExtension.d.ts +82 -0
  16. package/dist/import/HorizontalRuleImportExtension.d.ts +28 -0
  17. package/dist/import/ImportContext.d.ts +208 -0
  18. package/dist/import/compileImportRules.d.ts +50 -0
  19. package/dist/import/coreImportRules.d.ts +25 -0
  20. package/dist/import/defineImportRule.d.ts +32 -0
  21. package/dist/import/defineOverlayRules.d.ts +66 -0
  22. package/dist/import/index.d.ts +38 -0
  23. package/dist/import/inlineStylesFromStyleSheets.d.ts +28 -0
  24. package/dist/import/parseCss.d.ts +18 -0
  25. package/dist/import/runImport.d.ts +19 -0
  26. package/dist/import/schemas.d.ts +106 -0
  27. package/dist/import/sel.d.ts +74 -0
  28. package/dist/import/types.d.ts +394 -0
  29. package/dist/index.d.ts +44 -0
  30. package/{types.d.ts → dist/types.d.ts} +96 -8
  31. package/package.json +33 -18
  32. package/src/ContextRecord.ts +243 -0
  33. package/src/DOMRenderExtension.ts +96 -0
  34. package/src/DOMRenderRuntime.ts +265 -0
  35. package/src/RenderContext.ts +168 -0
  36. package/src/compileDOMRenderConfigOverrides.ts +416 -0
  37. package/src/constants.ts +18 -0
  38. package/src/domOverride.ts +46 -0
  39. package/src/import/CoreImportExtension.ts +26 -0
  40. package/src/import/DOMImportExtension.ts +221 -0
  41. package/src/import/HorizontalRuleImportExtension.ts +52 -0
  42. package/src/import/ImportContext.ts +339 -0
  43. package/src/import/compileImportRules.ts +178 -0
  44. package/src/import/coreImportRules.ts +545 -0
  45. package/src/import/defineImportRule.ts +40 -0
  46. package/src/import/defineOverlayRules.ts +105 -0
  47. package/src/import/index.ts +97 -0
  48. package/src/import/inlineStylesFromStyleSheets.ts +104 -0
  49. package/src/import/parseCss.ts +219 -0
  50. package/src/import/runImport.ts +245 -0
  51. package/src/import/schemas.ts +280 -0
  52. package/src/import/sel.ts +314 -0
  53. package/src/import/types.ts +471 -0
  54. package/src/index.ts +561 -0
  55. package/src/types.ts +470 -0
  56. package/LexicalHtml.dev.js +0 -914
  57. package/LexicalHtml.dev.mjs +0 -900
  58. package/LexicalHtml.mjs +0 -24
  59. package/LexicalHtml.node.mjs +0 -22
  60. package/LexicalHtml.prod.js +0 -9
  61. package/LexicalHtml.prod.mjs +0 -9
  62. package/RenderContext.d.ts +0 -32
  63. package/domOverride.d.ts +0 -18
  64. package/index.d.ts +0 -32
  65. /package/{ContextRecord.d.ts → dist/ContextRecord.d.ts} +0 -0
  66. /package/{LexicalHtml.js → dist/LexicalHtml.js} +0 -0
@@ -1,914 +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 lexical = require('lexical');
13
- var extension = require('@lexical/extension');
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
- // Do not require this module directly! Use normal `invariant` calls.
24
-
25
- function formatDevErrorMessage(message) {
26
- throw new Error(message);
27
- }
28
-
29
- /**
30
- * Copyright (c) Meta Platforms, Inc. and affiliates.
31
- *
32
- * This source code is licensed under the MIT license found in the
33
- * LICENSE file in the root directory of this source tree.
34
- *
35
- */
36
-
37
- let activeContext;
38
-
39
- /**
40
- * @experimental
41
- *
42
- * The LexicalEditor with context
43
- */
44
-
45
- /**
46
- * @experimental
47
- *
48
- * @param contextRecord The ContextRecord
49
- * @param cfg The configuration
50
- * @returns The value or defaultValue of cfg
51
- */
52
- function getContextValue(contextRecord, cfg) {
53
- const {
54
- key
55
- } = cfg;
56
- return contextRecord && key in contextRecord ? contextRecord[key] : cfg.defaultValue;
57
- }
58
- function getEditorContext(editor) {
59
- return activeContext && activeContext.editor === editor ? activeContext : undefined;
60
- }
61
-
62
- /**
63
- * @experimental
64
- *
65
- * @param sym The symbol for this ContextRecord (e.g. DOMRenderContextSymbol)
66
- * @param editor The editor
67
- * @returns The current context or undefined
68
- */
69
- function getContextRecord(sym, editor) {
70
- const editorContext = getEditorContext(editor);
71
- return editorContext && editorContext[sym];
72
- }
73
- function toPair(contextRecord, pairOrUpdater) {
74
- if ('cfg' in pairOrUpdater) {
75
- const {
76
- cfg,
77
- updater
78
- } = pairOrUpdater;
79
- return [cfg, updater(getContextValue(contextRecord, cfg))];
80
- }
81
- return pairOrUpdater;
82
- }
83
-
84
- /**
85
- * Construct a new context from a parent context and pairs
86
- *
87
- * @param pairs The pairs and updaters to build the context from
88
- * @param parent The parent context
89
- * @returns The new context
90
- */
91
- function contextFromPairs(pairs, parent) {
92
- let rval = parent;
93
- for (const pairOrUpdater of pairs) {
94
- const [k, v] = toPair(rval, pairOrUpdater);
95
- const key = k.key;
96
- if (rval === parent && getContextValue(rval, k) === v) {
97
- continue;
98
- }
99
- const ctx = rval || createChildContext(parent);
100
- ctx[key] = v;
101
- rval = ctx;
102
- }
103
- return rval;
104
- }
105
- function createChildContext(parent) {
106
- return Object.create(parent || null);
107
- }
108
-
109
- /**
110
- * Create a context config pair that sets a value in the render context.
111
- * @experimental
112
- */
113
- function contextValue(cfg, value) {
114
- return [cfg, value];
115
- }
116
-
117
- /**
118
- * Create a context config updater that transforms a value in the render context.
119
- * @experimental
120
- */
121
- function contextUpdater(cfg, updater) {
122
- return {
123
- cfg,
124
- updater
125
- };
126
- }
127
-
128
- /**
129
- * @internal
130
- * @experimental
131
- * @__NO_SIDE_EFFECTS__
132
- */
133
- function $withFullContext(sym, contextRecord, f, editor = lexical.$getEditor()) {
134
- const prevDOMContext = activeContext;
135
- const parentEditorContext = getEditorContext(editor);
136
- try {
137
- activeContext = {
138
- ...parentEditorContext,
139
- editor,
140
- [sym]: contextRecord
141
- };
142
- return f();
143
- } finally {
144
- activeContext = prevDOMContext;
145
- }
146
- }
147
-
148
- /**
149
- * @internal
150
- * @experimental
151
- * @__NO_SIDE_EFFECTS__
152
- */
153
- function $withContext(sym, $defaults = () => undefined) {
154
- return (cfg, editor = lexical.$getEditor()) => {
155
- return f => {
156
- const parentEditorContext = getEditorContext(editor);
157
- const parentContextRecord = parentEditorContext && parentEditorContext[sym];
158
- const contextRecord = contextFromPairs(cfg, parentContextRecord || $defaults(editor));
159
- if (!contextRecord || contextRecord === parentContextRecord) {
160
- return f();
161
- }
162
- return $withFullContext(sym, contextRecord, f, editor);
163
- };
164
- };
165
- }
166
-
167
- /**
168
- * @experimental
169
- * @internal
170
- * @__NO_SIDE_EFFECTS__
171
- */
172
- function createContextState(tag, name, getDefaultValue, isEqual) {
173
- return Object.assign(lexical.createState(Symbol(name), {
174
- isEqual,
175
- parse: getDefaultValue
176
- }), {
177
- [tag]: true
178
- });
179
- }
180
-
181
- /**
182
- * Copyright (c) Meta Platforms, Inc. and affiliates.
183
- *
184
- * This source code is licensed under the MIT license found in the
185
- * LICENSE file in the root directory of this source tree.
186
- *
187
- */
188
- const DOMRenderExtensionName = '@lexical/html/DOM';
189
- const DOMRenderContextSymbol = Symbol.for('@lexical/html/DOMExportContext');
190
- const ALWAYS_TRUE = () => true;
191
-
192
- /**
193
- * Copyright (c) Meta Platforms, Inc. and affiliates.
194
- *
195
- * This source code is licensed under the MIT license found in the
196
- * LICENSE file in the root directory of this source tree.
197
- *
198
- */
199
- /**
200
- * Create a context state to be used during render.
201
- *
202
- * Note that to support the ValueOrUpdater pattern you can not use a
203
- * function for V (but you may wrap it in an array or object).
204
- *
205
- * @experimental
206
- * @__NO_SIDE_EFFECTS__
207
- */
208
- function createRenderState(name, getDefaultValue, isEqual) {
209
- return createContextState(DOMRenderContextSymbol, name, getDefaultValue, isEqual);
210
- }
211
-
212
- /**
213
- * Render context state that is true if the export was initiated from the root of the document.
214
- * @experimental
215
- */
216
- const RenderContextRoot = createRenderState('root', Boolean);
217
-
218
- /**
219
- * Render context state that is true if this is an export operation ($generateHtmlFromNodes).
220
- * @experimental
221
- */
222
- const RenderContextExport = createRenderState('isExport', Boolean);
223
- function getDefaultRenderContext(editor) {
224
- const dep = extension.getPeerDependencyFromEditor(editor, DOMRenderExtensionName);
225
- return dep ? dep.output.defaults : undefined;
226
- }
227
- function getRenderContext(editor) {
228
- return getContextRecord(DOMRenderContextSymbol, editor) || getDefaultRenderContext(editor);
229
- }
230
-
231
- /**
232
- * Get a render context value during a DOM render or export operation.
233
- * @experimental
234
- */
235
- function $getRenderContextValue(cfg, editor = lexical.$getEditor()) {
236
- return getContextValue(getRenderContext(editor), cfg);
237
- }
238
-
239
- /**
240
- * Execute a callback within a render context with the given config pairs.
241
- * @experimental
242
- */
243
- const $withRenderContext = $withContext(DOMRenderContextSymbol, getDefaultRenderContext);
244
-
245
- /**
246
- * Copyright (c) Meta Platforms, Inc. and affiliates.
247
- *
248
- * This source code is licensed under the MIT license found in the
249
- * LICENSE file in the root directory of this source tree.
250
- *
251
- */
252
-
253
- /**
254
- * A convenience function for type inference when constructing DOM overrides for
255
- * use with {@link DOMRenderExtension}.
256
- *
257
- * @experimental
258
- * @__NO_SIDE_EFFECTS__
259
- */
260
-
261
- function domOverride(nodes, config) {
262
- return {
263
- ...config,
264
- nodes
265
- };
266
- }
267
-
268
- function buildTypeTree(editorConfig) {
269
- const t = {};
270
- const {
271
- nodes
272
- } = extension.getKnownTypesAndNodes(editorConfig);
273
- for (const klass of nodes) {
274
- const type = klass.getType();
275
- t[type] = {
276
- klass,
277
- types: {}
278
- };
279
- }
280
- for (const baseRec of Object.values(t)) {
281
- if (baseRec) {
282
- const baseType = baseRec.klass.getType();
283
- for (let {
284
- klass
285
- } = baseRec; lexical.$isLexicalNode(klass.prototype); klass = Object.getPrototypeOf(klass)) {
286
- const {
287
- ownNodeType
288
- } = lexical.getStaticNodeConfig(klass);
289
- const superRec = ownNodeType && t[ownNodeType];
290
- if (superRec) {
291
- superRec.types[baseType] = true;
292
- }
293
- }
294
- }
295
- }
296
- return t;
297
- }
298
- function buildNodePredicate(klass) {
299
- return node => node instanceof klass;
300
- }
301
- function getPredicate(typeTree, {
302
- nodes
303
- }) {
304
- if (nodes === '*') {
305
- return ALWAYS_TRUE;
306
- }
307
- let types = {};
308
- const predicates = [];
309
- for (const klassOrPredicate of nodes) {
310
- if ('getType' in klassOrPredicate) {
311
- const type = klassOrPredicate.getType();
312
- if (types) {
313
- const tree = typeTree[type];
314
- if (!(tree !== undefined)) {
315
- formatDevErrorMessage(`Node class ${klassOrPredicate.name} with type ${type} not registered in editor`);
316
- }
317
- types = Object.assign(types, tree.types);
318
- }
319
- predicates.push(buildNodePredicate(klassOrPredicate));
320
- } else {
321
- types = undefined;
322
- predicates.push(klassOrPredicate);
323
- }
324
- }
325
- if (types) {
326
- return types;
327
- } else if (predicates.length === 1) {
328
- return predicates[0];
329
- }
330
- return node => {
331
- for (const predicate of predicates) {
332
- if (predicate(node)) {
333
- return true;
334
- }
335
- }
336
- return false;
337
- };
338
- }
339
- function makePrerender() {
340
- return {
341
- $createDOM: [],
342
- $decorateDOM: [],
343
- $exportDOM: [],
344
- $extractWithChild: [],
345
- $getDOMSlot: [],
346
- $shouldExclude: [],
347
- $shouldInclude: [],
348
- $updateDOM: []
349
- };
350
- }
351
-
352
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
353
-
354
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
355
-
356
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
357
-
358
- function ignoreNext2(acc) {
359
- return (node, _$next, editor) => acc(node, editor);
360
- }
361
- function ignoreNext3(acc) {
362
- return (node, a, _$next, editor) => acc(node, a, editor);
363
- }
364
- function ignoreNext4(acc) {
365
- return (node, a, b, _$next, editor) => acc(node, a, b, editor);
366
- }
367
- function ignoreNext5(acc) {
368
- return (node, a, b, c, _$next, editor) => acc(node, a, b, c, editor);
369
- }
370
- function merge2($acc, $getOverride) {
371
- return (node, editor) => {
372
- const $next = () => $acc(node, editor);
373
- const $override = $getOverride(node);
374
- return $override ? $override(node, $next, editor) : $next();
375
- };
376
- }
377
- function merge3(acc, $getOverride) {
378
- return (node, a, editor) => {
379
- const $next = () => acc(node, a, editor);
380
- const $override = $getOverride(node);
381
- return $override ? $override(node, a, $next, editor) : $next();
382
- };
383
- }
384
- function merge4($acc, $getOverride) {
385
- return (node, a, b, editor) => {
386
- const $next = () => $acc(node, a, b, editor);
387
- const $override = $getOverride(node);
388
- return $override ? $override(node, a, b, $next, editor) : $next();
389
- };
390
- }
391
- function merge5(acc, $getOverride) {
392
- return (node, a, b, c, editor) => {
393
- const $next = () => acc(node, a, b, c, editor);
394
- const $override = $getOverride(node);
395
- return $override ? $override(node, a, b, c, $next, editor) : $next();
396
- };
397
- }
398
- function sequence4($acc, $getOverride) {
399
- return (node, a, b, editor) => {
400
- $acc(node, a, b, editor);
401
- const $override = $getOverride(node);
402
- if ($override) {
403
- $override(node, a, b, editor);
404
- }
405
- };
406
- }
407
- function compilePrerenderKey(prerender, k, defaults, mergeFunction, ignoreNextFunction) {
408
- let acc = defaults[k];
409
- for (const pair of prerender[k]) {
410
- if (typeof pair[0] === 'function') {
411
- const [$predicate, $override] = pair;
412
- acc = mergeFunction(acc, node => $predicate(node) && $override || undefined);
413
- } else {
414
- const typeOverrides = pair[1];
415
- const compiled = {};
416
- for (const type in typeOverrides) {
417
- const arr = typeOverrides[type];
418
- if (arr) {
419
- compiled[type] = arr.reduce(($acc, $override) => mergeFunction($acc, () => $override), acc);
420
- }
421
- }
422
- acc = mergeFunction(acc, node => {
423
- const f = compiled[node.getType()];
424
- return f && ignoreNextFunction(f);
425
- });
426
- }
427
- }
428
- defaults[k] = acc;
429
- }
430
- function addOverride(prerender, k, predicateOrTypes, override) {
431
- if (!override) {
432
- return;
433
- }
434
- const arr = prerender[k];
435
- if (typeof predicateOrTypes === 'function') {
436
- arr.push([predicateOrTypes, override]);
437
- } else {
438
- const last = arr[arr.length - 1];
439
- let types;
440
- if (last && last[0] === 'types') {
441
- types = last[1];
442
- } else {
443
- types = {};
444
- arr.push(['types', types]);
445
- }
446
- for (const type in predicateOrTypes) {
447
- const typeArr = types[type] || [];
448
- types[type] = typeArr;
449
- typeArr.push(override);
450
- }
451
- }
452
- }
453
- function isWildcard(override) {
454
- return override.nodes === '*';
455
- }
456
- function sortedOverrides(overrides) {
457
- const byWildcard = [];
458
- const byPredicate = [];
459
- const byNode = [];
460
- for (const override of overrides) {
461
- if (isWildcard(override)) {
462
- byWildcard.push(override);
463
- } else if (Array.isArray(override.nodes)) {
464
- for (const klassOrPredicate of override.nodes) {
465
- if (lexical.$isLexicalNode(klassOrPredicate.prototype)) {
466
- byNode.push(override.nodes.length === 1 ? override : {
467
- ...override,
468
- nodes: [klassOrPredicate]
469
- });
470
- } else {
471
- byPredicate.push(override.nodes.length === 1 ? override : {
472
- ...override,
473
- nodes: [klassOrPredicate]
474
- });
475
- }
476
- }
477
- }
478
- }
479
- const depths = new Map();
480
- const depthOf = klass => {
481
- let depth = depths.get(klass);
482
- if (depth === undefined) {
483
- depth = 0;
484
- for (let k = klass; lexical.$isLexicalNode(k.prototype); k = Object.getPrototypeOf(k)) {
485
- depth++;
486
- }
487
- depths.set(klass, depth);
488
- }
489
- return depth;
490
- };
491
- byNode.sort((a, b) => depthOf(a.nodes[0]) - depthOf(b.nodes[0]));
492
- return [...byNode, ...byPredicate, ...byWildcard];
493
- }
494
- function precompileDOMRenderConfigOverrides(editorConfig, overrides) {
495
- const typeTree = buildTypeTree(editorConfig);
496
- const prerender = makePrerender();
497
- for (const override of sortedOverrides(overrides)) {
498
- const predicateOrTypes = getPredicate(typeTree, override);
499
- for (const k_ in prerender) {
500
- const k = k_;
501
- addOverride(prerender, k, predicateOrTypes, override[k]);
502
- }
503
- }
504
- return prerender;
505
- }
506
- function identity(v) {
507
- return v;
508
- }
509
- function compileDOMRenderConfigOverrides(editorConfig, {
510
- overrides
511
- }) {
512
- const prerender = precompileDOMRenderConfigOverrides(editorConfig, overrides);
513
- const dom = {
514
- ...lexical.DEFAULT_EDITOR_DOM_CONFIG,
515
- ...editorConfig.dom
516
- };
517
- compilePrerenderKey(prerender, '$createDOM', dom, merge2, ignoreNext2);
518
- compilePrerenderKey(prerender, '$exportDOM', dom, merge2, ignoreNext2);
519
- compilePrerenderKey(prerender, '$extractWithChild', dom, merge5, ignoreNext5);
520
- compilePrerenderKey(prerender, '$getDOMSlot', dom, merge3, ignoreNext3);
521
- compilePrerenderKey(prerender, '$shouldExclude', dom, merge3, ignoreNext3);
522
- compilePrerenderKey(prerender, '$shouldInclude', dom, merge3, ignoreNext3);
523
- compilePrerenderKey(prerender, '$updateDOM', dom, merge4, ignoreNext4);
524
- compilePrerenderKey(prerender, '$decorateDOM', dom, sequence4, identity);
525
- return dom;
526
- }
527
-
528
- /**
529
- * Copyright (c) Meta Platforms, Inc. and affiliates.
530
- *
531
- * This source code is licensed under the MIT license found in the
532
- * LICENSE file in the root directory of this source tree.
533
- *
534
- */
535
-
536
-
537
- /**
538
- * @experimental
539
- *
540
- * An extension that allows overriding the render and export behavior for an
541
- * editor. This is highly experimental and subject to change from one version
542
- * to the next.
543
- **/
544
- const DOMRenderExtension = lexical.defineExtension({
545
- build(editor, config, state) {
546
- return {
547
- defaults: contextFromPairs(config.contextDefaults, undefined)
548
- };
549
- },
550
- config: {
551
- contextDefaults: [],
552
- overrides: []
553
- },
554
- html: {
555
- // Define a RootNode export for $generateDOMFromRoot
556
- export: new Map([[lexical.RootNode, () => {
557
- const element = document.createElement('div');
558
- element.role = 'textbox';
559
- return {
560
- element
561
- };
562
- }]])
563
- },
564
- init(editorConfig, config) {
565
- editorConfig.dom = compileDOMRenderConfigOverrides(editorConfig, config);
566
- },
567
- mergeConfig(config, partial) {
568
- const merged = lexical.shallowMergeConfig(config, partial);
569
- for (const k of ['overrides', 'contextDefaults']) {
570
- if (partial[k]) {
571
- merged[k] = [...config[k], ...partial[k]];
572
- }
573
- }
574
- return merged;
575
- },
576
- name: DOMRenderExtensionName
577
- });
578
-
579
- function isStyleRule(rule) {
580
- return rule.constructor.name === CSSStyleRule.name;
581
- }
582
-
583
- /**
584
- * Inlines CSS rules from <style> tags onto matching elements as inline styles.
585
- * This is needed because apps like Excel generate HTML where styles live in
586
- * class-based <style> rules (e.g. `.xl65 { background: #FFFF00; color: blue; }`)
587
- * rather than inline styles. Since Lexical's import converters read inline styles,
588
- * we resolve stylesheet rules into inline styles before conversion.
589
- *
590
- * Mutates the DOM in-place. Original inline styles always take precedence over
591
- * stylesheet rules (matching CSS specificity behavior).
592
- */
593
- function inlineStylesFromStyleSheets(doc) {
594
- if (doc.querySelector('style') === null) {
595
- return;
596
- }
597
- const originalInlineStyles = new Map();
598
- function getOriginalInlineProps(el) {
599
- let props = originalInlineStyles.get(el);
600
- if (props === undefined) {
601
- props = new Set();
602
- for (let i = 0; i < el.style.length; i++) {
603
- props.add(el.style[i]);
604
- }
605
- originalInlineStyles.set(el, props);
606
- }
607
- return props;
608
- }
609
- try {
610
- for (const sheet of Array.from(doc.styleSheets)) {
611
- let rules;
612
- try {
613
- rules = sheet.cssRules;
614
- } catch (_unused) {
615
- continue;
616
- }
617
- for (const rule of Array.from(rules)) {
618
- if (!isStyleRule(rule)) {
619
- continue;
620
- }
621
- let elements;
622
- try {
623
- elements = doc.querySelectorAll(rule.selectorText);
624
- } catch (_unused2) {
625
- continue;
626
- }
627
- for (const el of Array.from(elements)) {
628
- if (!lexical.isHTMLElement(el)) {
629
- continue;
630
- }
631
- const originalProps = getOriginalInlineProps(el);
632
- for (let i = 0; i < rule.style.length; i++) {
633
- const prop = rule.style[i];
634
- if (!originalProps.has(prop)) {
635
- el.style.setProperty(prop, rule.style.getPropertyValue(prop), rule.style.getPropertyPriority(prop));
636
- }
637
- }
638
- }
639
- }
640
- }
641
- } catch (_unused3) {
642
- // styleSheets API not supported in this environment
643
- }
644
- }
645
- const IGNORE_TAGS = new Set(['STYLE', 'SCRIPT']);
646
-
647
- /**
648
- * How you parse your html string to get a document is left up to you. In the browser you can use the native
649
- * DOMParser API to generate a document (see clipboard.ts), but to use in a headless environment you can use JSDom
650
- * or an equivalent library and pass in the document here.
651
- */
652
- function $generateNodesFromDOM(editor, dom) {
653
- if (lexical.isDOMDocumentNode(dom)) {
654
- inlineStylesFromStyleSheets(dom);
655
- }
656
- const elements = lexical.isDOMDocumentNode(dom) ? dom.body.childNodes : dom.childNodes;
657
- const lexicalNodes = [];
658
- const allArtificialNodes = [];
659
- for (const element of elements) {
660
- if (!IGNORE_TAGS.has(element.nodeName)) {
661
- const lexicalNode = $createNodesFromDOM(element, editor, allArtificialNodes, false);
662
- if (lexicalNode !== null) {
663
- for (const node of lexicalNode) {
664
- lexicalNodes.push(node);
665
- }
666
- }
667
- }
668
- }
669
- $unwrapArtificialNodes(allArtificialNodes);
670
- return lexicalNodes;
671
- }
672
-
673
- /**
674
- * Generate DOM nodes from the editor state into the given container element,
675
- * using the editor's {@link EditorDOMRenderConfig}.
676
- * @experimental
677
- */
678
- function $generateDOMFromNodes(container, selection = null, editor = lexical.$getEditor()) {
679
- return $withRenderContext([contextValue(RenderContextExport, true)], editor)(() => {
680
- const root = lexical.$getRoot();
681
- const domConfig = lexical.$getEditorDOMRenderConfig(editor);
682
- const parentElementAppend = container.append.bind(container);
683
- for (const topLevelNode of root.getChildren()) {
684
- $appendNodesToHTML(editor, topLevelNode, parentElementAppend, selection, domConfig);
685
- }
686
- return container;
687
- });
688
- }
689
-
690
- /**
691
- * Generate DOM nodes from a root node into the given container element,
692
- * including the root node itself. Uses the editor's {@link EditorDOMRenderConfig}.
693
- * @experimental
694
- */
695
- function $generateDOMFromRoot(container, root = lexical.$getRoot()) {
696
- const editor = lexical.$getEditor();
697
- return $withRenderContext([contextValue(RenderContextExport, true), contextValue(RenderContextRoot, true)], editor)(() => {
698
- const selection = null;
699
- const domConfig = lexical.$getEditorDOMRenderConfig(editor);
700
- const parentElementAppend = container.append.bind(container);
701
- $appendNodesToHTML(editor, root, parentElementAppend, selection, domConfig);
702
- return container;
703
- });
704
- }
705
- function $generateHtmlFromNodes(editor, selection = null) {
706
- if (typeof document === 'undefined' || typeof window === 'undefined' && typeof global.window === 'undefined') {
707
- {
708
- formatDevErrorMessage(`To use $generateHtmlFromNodes in headless mode please initialize a headless browser implementation such as JSDom or use withDOM from @lexical/headless/dom before calling this function.`);
709
- }
710
- }
711
- return $generateDOMFromNodes(document.createElement('div'), selection, editor).innerHTML;
712
- }
713
- function $appendNodesToHTML(editor, currentNode, parentElementAppend, selection$1 = null, domConfig = lexical.$getEditorDOMRenderConfig(editor)) {
714
- let shouldInclude = domConfig.$shouldInclude(currentNode, selection$1, editor);
715
- const shouldExclude = domConfig.$shouldExclude(currentNode, selection$1, editor);
716
- let target = currentNode;
717
- if (selection$1 !== null && lexical.$isTextNode(currentNode)) {
718
- target = selection.$sliceSelectedTextNodeContent(selection$1, currentNode, 'clone');
719
- }
720
- const exportProps = domConfig.$exportDOM(target, editor);
721
- const {
722
- element,
723
- after,
724
- append,
725
- $getChildNodes
726
- } = exportProps;
727
- if (!element) {
728
- return false;
729
- }
730
- const fragment = document.createDocumentFragment();
731
- const children = $getChildNodes ? $getChildNodes() : lexical.$isElementNode(target) ? target.getChildren() : [];
732
- const fragmentAppend = fragment.append.bind(fragment);
733
- for (const childNode of children) {
734
- const shouldIncludeChild = $appendNodesToHTML(editor, childNode, fragmentAppend, selection$1, domConfig);
735
- if (!shouldInclude && shouldIncludeChild && domConfig.$extractWithChild(currentNode, childNode, selection$1, 'html', editor)) {
736
- shouldInclude = true;
737
- }
738
- }
739
- if (shouldInclude && !shouldExclude) {
740
- if (lexical.isHTMLElement(element) || lexical.isDocumentFragment(element)) {
741
- if (append) {
742
- append(fragment);
743
- } else {
744
- element.append(fragment);
745
- }
746
- }
747
- parentElementAppend(element);
748
- if (after) {
749
- const newElement = after.call(target, element);
750
- if (newElement) {
751
- if (lexical.isDocumentFragment(element)) {
752
- element.replaceChildren(newElement);
753
- } else {
754
- element.replaceWith(newElement);
755
- }
756
- }
757
- }
758
- } else {
759
- parentElementAppend(fragment);
760
- }
761
- return shouldInclude;
762
- }
763
- function getConversionFunction(domNode, editor) {
764
- const {
765
- nodeName
766
- } = domNode;
767
- const cachedConversions = editor._htmlConversions.get(nodeName.toLowerCase());
768
- let currentConversion = null;
769
- if (cachedConversions !== undefined) {
770
- for (const cachedConversion of cachedConversions) {
771
- const domConversion = cachedConversion(domNode);
772
- if (domConversion !== null && (currentConversion === null ||
773
- // Given equal priority, prefer the last registered importer
774
- // which is typically an application custom node or HTMLConfig['import']
775
- (currentConversion.priority || 0) <= (domConversion.priority || 0))) {
776
- currentConversion = domConversion;
777
- }
778
- }
779
- }
780
- return currentConversion !== null ? currentConversion.conversion : null;
781
- }
782
- function $createNodesFromDOM(node, editor, allArtificialNodes, hasBlockAncestorLexicalNode, forChildMap = new Map(), parentLexicalNode) {
783
- const lexicalNodes = [];
784
- if (IGNORE_TAGS.has(node.nodeName)) {
785
- return lexicalNodes;
786
- }
787
- let currentLexicalNode = null;
788
- const transformFunction = getConversionFunction(node, editor);
789
- const transformOutput = transformFunction ? transformFunction(node) : null;
790
- let postTransform = null;
791
- if (transformOutput !== null) {
792
- postTransform = transformOutput.after;
793
- const transformNodes = transformOutput.node;
794
- currentLexicalNode = Array.isArray(transformNodes) ? transformNodes[transformNodes.length - 1] : transformNodes;
795
- if (currentLexicalNode !== null) {
796
- for (const [, forChildFunction] of forChildMap) {
797
- currentLexicalNode = forChildFunction(currentLexicalNode, parentLexicalNode);
798
- if (!currentLexicalNode) {
799
- break;
800
- }
801
- }
802
- if (currentLexicalNode) {
803
- lexicalNodes.push(...(Array.isArray(transformNodes) ? transformNodes : [currentLexicalNode]));
804
- }
805
- }
806
- if (transformOutput.forChild != null) {
807
- forChildMap.set(node.nodeName, transformOutput.forChild);
808
- }
809
- }
810
-
811
- // If the DOM node doesn't have a transformer, we don't know what
812
- // to do with it but we still need to process any childNodes.
813
- const children = node.childNodes;
814
- let childLexicalNodes = [];
815
- const hasBlockAncestorLexicalNodeForChildren = currentLexicalNode != null && lexical.$isRootOrShadowRoot(currentLexicalNode) ? false : currentLexicalNode != null && lexical.$isBlockElementNode(currentLexicalNode) || hasBlockAncestorLexicalNode;
816
- for (let i = 0; i < children.length; i++) {
817
- childLexicalNodes.push(...$createNodesFromDOM(children[i], editor, allArtificialNodes, hasBlockAncestorLexicalNodeForChildren, new Map(forChildMap), currentLexicalNode));
818
- }
819
- if (postTransform != null) {
820
- childLexicalNodes = postTransform(childLexicalNodes);
821
- }
822
- if (lexical.isBlockDomNode(node)) {
823
- if (!hasBlockAncestorLexicalNodeForChildren) {
824
- childLexicalNodes = wrapContinuousInlines(node, childLexicalNodes, lexical.$createParagraphNode);
825
- } else {
826
- childLexicalNodes = wrapContinuousInlines(node, childLexicalNodes, () => {
827
- const artificialNode = new lexical.ArtificialNode__DO_NOT_USE();
828
- allArtificialNodes.push(artificialNode);
829
- return artificialNode;
830
- });
831
- }
832
- }
833
- if (currentLexicalNode == null) {
834
- if (childLexicalNodes.length > 0) {
835
- // If it hasn't been converted to a LexicalNode, we hoist its children
836
- // up to the same level as it.
837
- for (const childNode of childLexicalNodes) {
838
- lexicalNodes.push(childNode);
839
- }
840
- } else {
841
- if (lexical.isBlockDomNode(node) && isDomNodeBetweenTwoInlineNodes(node)) {
842
- // Empty block dom node that hasnt been converted, we replace it with a linebreak if its between inline nodes
843
- lexicalNodes.push(lexical.$createLineBreakNode());
844
- }
845
- }
846
- } else {
847
- if (lexical.$isElementNode(currentLexicalNode)) {
848
- // If the current node is a ElementNode after conversion,
849
- // we can append all the children to it.
850
- currentLexicalNode.append(...childLexicalNodes);
851
- }
852
- }
853
- return lexicalNodes;
854
- }
855
- function wrapContinuousInlines(domNode, nodes, createWrapperFn) {
856
- const textAlign = domNode.style.textAlign;
857
- const out = [];
858
- let continuousInlines = [];
859
- // wrap contiguous inline child nodes in para
860
- for (let i = 0; i < nodes.length; i++) {
861
- const node = nodes[i];
862
- if (lexical.$isBlockElementNode(node)) {
863
- if (textAlign && !node.getFormat()) {
864
- node.setFormat(textAlign);
865
- }
866
- out.push(node);
867
- } else {
868
- continuousInlines.push(node);
869
- if (i === nodes.length - 1 || i < nodes.length - 1 && lexical.$isBlockElementNode(nodes[i + 1])) {
870
- const wrapper = createWrapperFn();
871
- wrapper.setFormat(textAlign);
872
- wrapper.append(...continuousInlines);
873
- out.push(wrapper);
874
- continuousInlines = [];
875
- }
876
- }
877
- }
878
- return out;
879
- }
880
- function $unwrapArtificialNodes(allArtificialNodes) {
881
- // Replace artificial node with its children, inserting a linebreak
882
- // between adjacent artificial nodes
883
- for (const node of allArtificialNodes) {
884
- if (node.getParent() && node.getNextSibling() instanceof lexical.ArtificialNode__DO_NOT_USE) {
885
- node.insertAfter(lexical.$createLineBreakNode());
886
- }
887
- }
888
- for (const node of allArtificialNodes) {
889
- const parent = node.getParent();
890
- if (parent) {
891
- parent.splice(node.getIndexWithinParent(), 1, node.getChildren());
892
- }
893
- }
894
- }
895
- function isDomNodeBetweenTwoInlineNodes(node) {
896
- if (node.nextSibling == null || node.previousSibling == null) {
897
- return false;
898
- }
899
- return lexical.isInlineDomNode(node.nextSibling) && lexical.isInlineDomNode(node.previousSibling);
900
- }
901
-
902
- exports.$generateDOMFromNodes = $generateDOMFromNodes;
903
- exports.$generateDOMFromRoot = $generateDOMFromRoot;
904
- exports.$generateHtmlFromNodes = $generateHtmlFromNodes;
905
- exports.$generateNodesFromDOM = $generateNodesFromDOM;
906
- exports.$getRenderContextValue = $getRenderContextValue;
907
- exports.$withRenderContext = $withRenderContext;
908
- exports.DOMRenderExtension = DOMRenderExtension;
909
- exports.RenderContextExport = RenderContextExport;
910
- exports.RenderContextRoot = RenderContextRoot;
911
- exports.contextUpdater = contextUpdater;
912
- exports.contextValue = contextValue;
913
- exports.createRenderState = createRenderState;
914
- exports.domOverride = domOverride;