@lexical/html 0.43.0 → 0.43.1-nightly.20260413.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.dev.js +66 -0
- package/LexicalHtml.dev.mjs +66 -0
- package/LexicalHtml.prod.js +1 -1
- package/LexicalHtml.prod.mjs +1 -1
- package/package.json +4 -4
package/LexicalHtml.dev.js
CHANGED
|
@@ -21,12 +21,78 @@ var lexical = require('lexical');
|
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
23
|
|
|
24
|
+
/**
|
|
25
|
+
* Inlines CSS rules from <style> tags onto matching elements as inline styles.
|
|
26
|
+
* This is needed because apps like Excel generate HTML where styles live in
|
|
27
|
+
* class-based <style> rules (e.g. `.xl65 { background: #FFFF00; color: blue; }`)
|
|
28
|
+
* rather than inline styles. Since Lexical's import converters read inline styles,
|
|
29
|
+
* we resolve stylesheet rules into inline styles before conversion.
|
|
30
|
+
*
|
|
31
|
+
* Mutates the DOM in-place. Original inline styles always take precedence over
|
|
32
|
+
* stylesheet rules (matching CSS specificity behavior).
|
|
33
|
+
*/
|
|
34
|
+
function inlineStylesFromStyleSheets(doc) {
|
|
35
|
+
if (doc.querySelector('style') === null) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const originalInlineStyles = new Map();
|
|
39
|
+
function getOriginalInlineProps(el) {
|
|
40
|
+
let props = originalInlineStyles.get(el);
|
|
41
|
+
if (props === undefined) {
|
|
42
|
+
props = new Set();
|
|
43
|
+
for (let i = 0; i < el.style.length; i++) {
|
|
44
|
+
props.add(el.style[i]);
|
|
45
|
+
}
|
|
46
|
+
originalInlineStyles.set(el, props);
|
|
47
|
+
}
|
|
48
|
+
return props;
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
for (const sheet of Array.from(doc.styleSheets)) {
|
|
52
|
+
let rules;
|
|
53
|
+
try {
|
|
54
|
+
rules = sheet.cssRules;
|
|
55
|
+
} catch (_unused) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
for (const rule of Array.from(rules)) {
|
|
59
|
+
if (!(rule instanceof CSSStyleRule)) {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
let elements;
|
|
63
|
+
try {
|
|
64
|
+
elements = doc.querySelectorAll(rule.selectorText);
|
|
65
|
+
} catch (_unused2) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
for (const el of Array.from(elements)) {
|
|
69
|
+
if (!(el instanceof HTMLElement)) {
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
const originalProps = getOriginalInlineProps(el);
|
|
73
|
+
for (let i = 0; i < rule.style.length; i++) {
|
|
74
|
+
const prop = rule.style[i];
|
|
75
|
+
if (!originalProps.has(prop)) {
|
|
76
|
+
el.style.setProperty(prop, rule.style.getPropertyValue(prop), rule.style.getPropertyPriority(prop));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
} catch (_unused3) {
|
|
83
|
+
// styleSheets API not supported in this environment
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
24
87
|
/**
|
|
25
88
|
* How you parse your html string to get a document is left up to you. In the browser you can use the native
|
|
26
89
|
* DOMParser API to generate a document (see clipboard.ts), but to use in a headless environment you can use JSDom
|
|
27
90
|
* or an equivalent library and pass in the document here.
|
|
28
91
|
*/
|
|
29
92
|
function $generateNodesFromDOM(editor, dom) {
|
|
93
|
+
if (lexical.isDOMDocumentNode(dom)) {
|
|
94
|
+
inlineStylesFromStyleSheets(dom);
|
|
95
|
+
}
|
|
30
96
|
const elements = lexical.isDOMDocumentNode(dom) ? dom.body.childNodes : dom.childNodes;
|
|
31
97
|
let lexicalNodes = [];
|
|
32
98
|
const allArtificialNodes = [];
|
package/LexicalHtml.dev.mjs
CHANGED
|
@@ -19,12 +19,78 @@ import { isDOMDocumentNode, $getRoot, $isElementNode, $isTextNode, getRegistered
|
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Inlines CSS rules from <style> tags onto matching elements as inline styles.
|
|
24
|
+
* This is needed because apps like Excel generate HTML where styles live in
|
|
25
|
+
* class-based <style> rules (e.g. `.xl65 { background: #FFFF00; color: blue; }`)
|
|
26
|
+
* rather than inline styles. Since Lexical's import converters read inline styles,
|
|
27
|
+
* we resolve stylesheet rules into inline styles before conversion.
|
|
28
|
+
*
|
|
29
|
+
* Mutates the DOM in-place. Original inline styles always take precedence over
|
|
30
|
+
* stylesheet rules (matching CSS specificity behavior).
|
|
31
|
+
*/
|
|
32
|
+
function inlineStylesFromStyleSheets(doc) {
|
|
33
|
+
if (doc.querySelector('style') === null) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const originalInlineStyles = new Map();
|
|
37
|
+
function getOriginalInlineProps(el) {
|
|
38
|
+
let props = originalInlineStyles.get(el);
|
|
39
|
+
if (props === undefined) {
|
|
40
|
+
props = new Set();
|
|
41
|
+
for (let i = 0; i < el.style.length; i++) {
|
|
42
|
+
props.add(el.style[i]);
|
|
43
|
+
}
|
|
44
|
+
originalInlineStyles.set(el, props);
|
|
45
|
+
}
|
|
46
|
+
return props;
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
for (const sheet of Array.from(doc.styleSheets)) {
|
|
50
|
+
let rules;
|
|
51
|
+
try {
|
|
52
|
+
rules = sheet.cssRules;
|
|
53
|
+
} catch (_unused) {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
for (const rule of Array.from(rules)) {
|
|
57
|
+
if (!(rule instanceof CSSStyleRule)) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
let elements;
|
|
61
|
+
try {
|
|
62
|
+
elements = doc.querySelectorAll(rule.selectorText);
|
|
63
|
+
} catch (_unused2) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
for (const el of Array.from(elements)) {
|
|
67
|
+
if (!(el instanceof HTMLElement)) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const originalProps = getOriginalInlineProps(el);
|
|
71
|
+
for (let i = 0; i < rule.style.length; i++) {
|
|
72
|
+
const prop = rule.style[i];
|
|
73
|
+
if (!originalProps.has(prop)) {
|
|
74
|
+
el.style.setProperty(prop, rule.style.getPropertyValue(prop), rule.style.getPropertyPriority(prop));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
} catch (_unused3) {
|
|
81
|
+
// styleSheets API not supported in this environment
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
22
85
|
/**
|
|
23
86
|
* How you parse your html string to get a document is left up to you. In the browser you can use the native
|
|
24
87
|
* DOMParser API to generate a document (see clipboard.ts), but to use in a headless environment you can use JSDom
|
|
25
88
|
* or an equivalent library and pass in the document here.
|
|
26
89
|
*/
|
|
27
90
|
function $generateNodesFromDOM(editor, dom) {
|
|
91
|
+
if (isDOMDocumentNode(dom)) {
|
|
92
|
+
inlineStylesFromStyleSheets(dom);
|
|
93
|
+
}
|
|
28
94
|
const elements = isDOMDocumentNode(dom) ? dom.body.childNodes : dom.childNodes;
|
|
29
95
|
let lexicalNodes = [];
|
|
30
96
|
const allArtificialNodes = [];
|
package/LexicalHtml.prod.js
CHANGED
|
@@ -6,4 +6,4 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
"use strict";var e=require("@lexical/selection"),
|
|
9
|
+
"use strict";var e=require("@lexical/selection"),t=require("@lexical/utils"),n=require("lexical");function o(l,r,i,s=null){let c=null===s||r.isSelected(s);const u=n.$isElementNode(r)&&r.excludeFromCopy("html");let a=r;null!==s&&n.$isTextNode(r)&&(a=e.$sliceSelectedTextNodeContent(s,r,"clone"));const d=n.$isElementNode(a)?a.getChildren():[],f=n.getRegisteredNode(l,a.getType());let m;m=f&&void 0!==f.exportDOM?f.exportDOM(l,a):a.exportDOM(l);const{element:h,after:p}=m;if(!h)return!1;const g=document.createDocumentFragment();for(let e=0;e<d.length;e++){const t=d[e],i=o(l,t,g,s);!c&&n.$isElementNode(r)&&i&&r.extractWithChild(t,s,"html")&&(c=!0)}if(c&&!u){if((t.isHTMLElement(h)||n.isDocumentFragment(h))&&h.append(g),i.append(h),p){const e=p.call(a,h);e&&(n.isDocumentFragment(h)?h.replaceChildren(e):h.replaceWith(e))}}else i.append(g);return c}const l=new Set(["STYLE","SCRIPT"]);function r(e,o,s,c,u=new Map,a){let d=[];if(l.has(e.nodeName))return d;let f=null;const m=function(e,t){const{nodeName:n}=e,o=t._htmlConversions.get(n.toLowerCase());let l=null;if(void 0!==o)for(const t of o){const n=t(e);null!==n&&(null===l||(l.priority||0)<=(n.priority||0))&&(l=n)}return null!==l?l.conversion:null}(e,o),h=m?m(e):null;let p=null;if(null!==h){p=h.after;const t=h.node;if(f=Array.isArray(t)?t[t.length-1]:t,null!==f){for(const[,e]of u)if(f=e(f,a),!f)break;f&&d.push(...Array.isArray(t)?t:[f])}null!=h.forChild&&u.set(e.nodeName,h.forChild)}const g=e.childNodes;let y=[];const N=(null==f||!n.$isRootOrShadowRoot(f))&&(null!=f&&n.$isBlockElementNode(f)||c);for(let e=0;e<g.length;e++)y.push(...r(g[e],o,s,N,new Map(u),f));return null!=p&&(y=p(y)),t.isBlockDomNode(e)&&(y=i(e,y,N?()=>{const e=new n.ArtificialNode__DO_NOT_USE;return s.push(e),e}:n.$createParagraphNode)),null==f?y.length>0?d=d.concat(y):t.isBlockDomNode(e)&&function(e){if(null==e.nextSibling||null==e.previousSibling)return!1;return n.isInlineDomNode(e.nextSibling)&&n.isInlineDomNode(e.previousSibling)}(e)&&(d=d.concat(n.$createLineBreakNode())):n.$isElementNode(f)&&f.append(...y),d}function i(e,t,o){const l=e.style.textAlign,r=[];let i=[];for(let e=0;e<t.length;e++){const s=t[e];if(n.$isBlockElementNode(s))l&&!s.getFormat()&&s.setFormat(l),r.push(s);else if(i.push(s),e===t.length-1||e<t.length-1&&n.$isBlockElementNode(t[e+1])){const e=o();e.setFormat(l),e.append(...i),r.push(e),i=[]}}return r}exports.$generateHtmlFromNodes=function(e,t){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"),r=n.$getRoot().getChildren();for(let n=0;n<r.length;n++){o(e,r[n],l,t)}return l.innerHTML},exports.$generateNodesFromDOM=function(e,t){n.isDOMDocumentNode(t)&&function(e){if(null===e.querySelector("style"))return;const t=new Map;function n(e){let n=t.get(e);if(void 0===n){n=new Set;for(let t=0;t<e.style.length;t++)n.add(e.style[t]);t.set(e,n)}return n}try{for(const t of Array.from(e.styleSheets)){let o;try{o=t.cssRules}catch(e){continue}for(const t of Array.from(o)){if(!(t instanceof CSSStyleRule))continue;let o;try{o=e.querySelectorAll(t.selectorText)}catch(e){continue}for(const e of Array.from(o)){if(!(e instanceof HTMLElement))continue;const o=n(e);for(let n=0;n<t.style.length;n++){const l=t.style[n];o.has(l)||e.style.setProperty(l,t.style.getPropertyValue(l),t.style.getPropertyPriority(l))}}}}}catch(e){}}(t);const o=n.isDOMDocumentNode(t)?t.body.childNodes:t.childNodes;let i=[];const s=[];for(const t of o)if(!l.has(t.nodeName)){const n=r(t,e,s,!1);null!==n&&(i=i.concat(n))}return function(e){for(const t of e)t.getNextSibling()instanceof n.ArtificialNode__DO_NOT_USE&&t.insertAfter(n.$createLineBreakNode());for(const t of e){const e=t.getChildren();for(const n of e)t.insertBefore(n);t.remove()}}(s),i};
|
package/LexicalHtml.prod.mjs
CHANGED
|
@@ -6,4 +6,4 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import{$sliceSelectedTextNodeContent as e}from"@lexical/selection";import{isHTMLElement as
|
|
9
|
+
import{$sliceSelectedTextNodeContent as e}from"@lexical/selection";import{isHTMLElement as t,isBlockDomNode as n}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 h,$createParagraphNode as p}from"lexical";function m(e,t){o(t)&&function(e){if(null===e.querySelector("style"))return;const t=new Map;function n(e){let n=t.get(e);if(void 0===n){n=new Set;for(let t=0;t<e.style.length;t++)n.add(e.style[t]);t.set(e,n)}return n}try{for(const t of Array.from(e.styleSheets)){let o;try{o=t.cssRules}catch(e){continue}for(const t of Array.from(o)){if(!(t instanceof CSSStyleRule))continue;let o;try{o=e.querySelectorAll(t.selectorText)}catch(e){continue}for(const e of Array.from(o)){if(!(e instanceof HTMLElement))continue;const o=n(e);for(let n=0;n<t.style.length;n++){const l=t.style[n];o.has(l)||e.style.setProperty(l,t.style.getPropertyValue(l),t.style.getPropertyPriority(l))}}}}}catch(e){}}(t);const n=o(t)?t.body.childNodes:t.childNodes;let l=[];const r=[];for(const t of n)if(!S.has(t.nodeName)){const n=w(t,e,r,!1);null!==n&&(l=l.concat(n))}return function(e){for(const t of e)t.getNextSibling()instanceof d&&t.insertAfter(a());for(const t of e){const e=t.getChildren();for(const n of e)t.insertBefore(n);t.remove()}}(r),l}function y(e,t){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 n=document.createElement("div"),o=l().getChildren();for(let l=0;l<o.length;l++){g(e,o[l],n,t)}return n.innerHTML}function g(n,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 h=r(d)?d.getChildren():[],p=s(n,d.getType());let m;m=p&&void 0!==p.exportDOM?p.exportDOM(n,d):d.exportDOM(n);const{element:y,after:S}=m;if(!y)return!1;const w=document.createDocumentFragment();for(let e=0;e<h.length;e++){const t=h[e],l=g(n,t,w,u);!f&&r(o)&&l&&o.extractWithChild(t,u,"html")&&(f=!0)}if(f&&!a){if((t(y)||c(y))&&y.append(w),l.append(y),S){const e=S.call(d,y);e&&(c(y)?y.replaceChildren(e):y.replaceWith(e))}}else l.append(w);return f}const S=new Set(["STYLE","SCRIPT"]);function w(e,t,o,l,i=new Map,s){let c=[];if(S.has(e.nodeName))return c;let m=null;const y=function(e,t){const{nodeName:n}=e,o=t._htmlConversions.get(n.toLowerCase());let l=null;if(void 0!==o)for(const t of o){const n=t(e);null!==n&&(null===l||(l.priority||0)<=(n.priority||0))&&(l=n)}return null!==l?l.conversion:null}(e,t),g=y?y(e):null;let C=null;if(null!==g){C=g.after;const t=g.node;if(m=Array.isArray(t)?t[t.length-1]:t,null!==m){for(const[,e]of i)if(m=e(m,s),!m)break;m&&c.push(...Array.isArray(t)?t:[m])}null!=g.forChild&&i.set(e.nodeName,g.forChild)}const b=e.childNodes;let v=[];const A=(null==m||!u(m))&&(null!=m&&f(m)||l);for(let e=0;e<b.length;e++)v.push(...w(b[e],t,o,A,new Map(i),m));return null!=C&&(v=C(v)),n(e)&&(v=x(e,v,A?()=>{const e=new d;return o.push(e),e}:p)),null==m?v.length>0?c=c.concat(v):n(e)&&function(e){if(null==e.nextSibling||null==e.previousSibling)return!1;return h(e.nextSibling)&&h(e.previousSibling)}(e)&&(c=c.concat(a())):r(m)&&m.append(...v),c}function x(e,t,n){const o=e.style.textAlign,l=[];let r=[];for(let e=0;e<t.length;e++){const i=t[e];if(f(i))o&&!i.getFormat()&&i.setFormat(o),l.push(i);else if(r.push(i),e===t.length-1||e<t.length-1&&f(t[e+1])){const e=n();e.setFormat(o),e.append(...r),l.push(e),r=[]}}return l}export{y as $generateHtmlFromNodes,m as $generateNodesFromDOM};
|
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"html"
|
|
9
9
|
],
|
|
10
10
|
"license": "MIT",
|
|
11
|
-
"version": "0.43.0",
|
|
11
|
+
"version": "0.43.1-nightly.20260413.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.43.0",
|
|
21
|
-
"@lexical/utils": "0.43.0",
|
|
22
|
-
"lexical": "0.43.0"
|
|
20
|
+
"@lexical/selection": "0.43.1-nightly.20260413.0",
|
|
21
|
+
"@lexical/utils": "0.43.1-nightly.20260413.0",
|
|
22
|
+
"lexical": "0.43.1-nightly.20260413.0"
|
|
23
23
|
},
|
|
24
24
|
"module": "LexicalHtml.mjs",
|
|
25
25
|
"sideEffects": false,
|