@webiny/lexical-converter 6.3.0 → 6.4.0-beta.1
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/createHtmlToLexicalParser.js +27 -42
- package/createHtmlToLexicalParser.js.map +1 -1
- package/createLexicalStateTransformer.js +49 -46
- package/createLexicalStateTransformer.js.map +1 -1
- package/index.js +0 -3
- package/package.json +5 -5
- package/postProcessHtml.js +7 -8
- package/postProcessHtml.js.map +1 -1
- package/types.js +0 -3
- package/index.js.map +0 -1
- package/types.js.map +0 -1
|
@@ -2,47 +2,32 @@ import { createHeadlessEditor } from "@lexical/headless";
|
|
|
2
2
|
import { $generateNodesFromDOM } from "@lexical/html";
|
|
3
3
|
import { $getRoot, $getSelection } from "lexical";
|
|
4
4
|
import { allNodes } from "@webiny/lexical-nodes";
|
|
5
|
-
const passthroughMapper = node
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
},
|
|
35
|
-
/**
|
|
36
|
-
* Prevents this update from being batched, forcing it to run synchronously.
|
|
37
|
-
*/
|
|
38
|
-
{
|
|
39
|
-
discrete: true
|
|
40
|
-
});
|
|
41
|
-
if (parsingError) {
|
|
42
|
-
throw parsingError;
|
|
43
|
-
}
|
|
44
|
-
return editor.getEditorState().toJSON();
|
|
45
|
-
};
|
|
46
|
-
};
|
|
5
|
+
const passthroughMapper = (node)=>node;
|
|
6
|
+
const createHtmlToLexicalParser = (config = {})=>(domDocument)=>{
|
|
7
|
+
const customNodeMapper = config.nodeMapper ?? passthroughMapper;
|
|
8
|
+
const editor = createHeadlessEditor({
|
|
9
|
+
...config.editorConfig,
|
|
10
|
+
nodes: [
|
|
11
|
+
...allNodes,
|
|
12
|
+
...config.editorConfig?.nodes || []
|
|
13
|
+
]
|
|
14
|
+
});
|
|
15
|
+
let parsingError;
|
|
16
|
+
editor.update(()=>{
|
|
17
|
+
const lexicalNodes = $generateNodesFromDOM(editor, domDocument).map(customNodeMapper);
|
|
18
|
+
$getRoot().select();
|
|
19
|
+
const selection = $getSelection();
|
|
20
|
+
if (selection) try {
|
|
21
|
+
selection.insertNodes(lexicalNodes);
|
|
22
|
+
} catch (err) {
|
|
23
|
+
parsingError = err;
|
|
24
|
+
}
|
|
25
|
+
}, {
|
|
26
|
+
discrete: true
|
|
27
|
+
});
|
|
28
|
+
if (parsingError) throw parsingError;
|
|
29
|
+
return editor.getEditorState().toJSON();
|
|
30
|
+
};
|
|
31
|
+
export { createHtmlToLexicalParser };
|
|
47
32
|
|
|
48
33
|
//# sourceMappingURL=createHtmlToLexicalParser.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"file":"createHtmlToLexicalParser.js","sources":["../src/createHtmlToLexicalParser.ts"],"sourcesContent":["import { createHeadlessEditor } from \"@lexical/headless\";\nimport { $generateNodesFromDOM } from \"@lexical/html\";\nimport { $getRoot, $getSelection } from \"lexical\";\nimport { allNodes } from \"@webiny/lexical-nodes\";\nimport type { NodeMapper, ParserConfigurationOptions } from \"~/types.js\";\n\nconst passthroughMapper: NodeMapper = node => node;\n\n/**\n * Parse html string to lexical JSON object.\n */\nexport const createHtmlToLexicalParser = (config: ParserConfigurationOptions = {}) => {\n return (domDocument: Document): Record<string, any> | null => {\n const customNodeMapper: NodeMapper = config.nodeMapper ?? passthroughMapper;\n\n const editor = createHeadlessEditor({\n ...config.editorConfig,\n nodes: [...allNodes, ...(config.editorConfig?.nodes || [])]\n });\n\n let parsingError;\n\n editor.update(\n () => {\n // Convert to lexical node objects that can be stored in db.\n const lexicalNodes = $generateNodesFromDOM(editor, domDocument).map(\n customNodeMapper\n );\n\n // Select the root\n $getRoot().select();\n\n // Insert the nodes at a selection.\n const selection = $getSelection();\n if (selection) {\n try {\n selection.insertNodes(lexicalNodes);\n } catch (err) {\n parsingError = err;\n }\n }\n },\n /**\n * Prevents this update from being batched, forcing it to run synchronously.\n */\n { discrete: true }\n );\n\n if (parsingError) {\n throw parsingError;\n }\n\n return editor.getEditorState().toJSON();\n };\n};\n"],"names":["passthroughMapper","node","createHtmlToLexicalParser","config","domDocument","customNodeMapper","editor","createHeadlessEditor","allNodes","parsingError","lexicalNodes","$generateNodesFromDOM","$getRoot","selection","$getSelection","err"],"mappings":";;;;AAMA,MAAMA,oBAAgCC,CAAAA,OAAQA;AAKvC,MAAMC,4BAA4B,CAACC,SAAqC,CAAC,CAAC,GACtE,CAACC;QACJ,MAAMC,mBAA+BF,OAAO,UAAU,IAAIH;QAE1D,MAAMM,SAASC,qBAAqB;YAChC,GAAGJ,OAAO,YAAY;YACtB,OAAO;mBAAIK;mBAAcL,OAAO,YAAY,EAAE,SAAS,EAAE;aAAE;QAC/D;QAEA,IAAIM;QAEJH,OAAO,MAAM,CACT;YAEI,MAAMI,eAAeC,sBAAsBL,QAAQF,aAAa,GAAG,CAC/DC;YAIJO,WAAW,MAAM;YAGjB,MAAMC,YAAYC;YAClB,IAAID,WACA,IAAI;gBACAA,UAAU,WAAW,CAACH;YAC1B,EAAE,OAAOK,KAAK;gBACVN,eAAeM;YACnB;QAER,GAIA;YAAE,UAAU;QAAK;QAGrB,IAAIN,cACA,MAAMA;QAGV,OAAOH,OAAO,cAAc,GAAG,MAAM;IACzC"}
|
|
@@ -1,56 +1,59 @@
|
|
|
1
|
-
import { $
|
|
1
|
+
import { $createNodeSelection, $getRoot, $isElementNode } from "lexical";
|
|
2
2
|
import { $generateHtmlFromNodes } from "@lexical/html";
|
|
3
3
|
import { createHeadlessEditor } from "@lexical/headless";
|
|
4
4
|
import { allNodes, prepareLexicalState } from "@webiny/lexical-nodes";
|
|
5
5
|
import { postProcessHtml } from "./postProcessHtml.js";
|
|
6
6
|
class LexicalStateTransformer {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const editorState = this.editor.parseEditorState(prepareLexicalState(state));
|
|
15
|
-
this.editor.setEditorState(editorState);
|
|
16
|
-
let flattenedNodes = [];
|
|
17
|
-
this.editor.update(() => {
|
|
18
|
-
const children = $getRoot().getChildren();
|
|
19
|
-
flattenedNodes = children.map(childNode => {
|
|
20
|
-
const selection = $createNodeSelection();
|
|
21
|
-
selection.add(childNode.getKey());
|
|
22
|
-
this.getNodeDescendants(childNode).forEach(node => {
|
|
23
|
-
selection.add(node.getKey());
|
|
7
|
+
constructor(config = {}){
|
|
8
|
+
this.editor = createHeadlessEditor({
|
|
9
|
+
...config.editorConfig,
|
|
10
|
+
nodes: [
|
|
11
|
+
...allNodes,
|
|
12
|
+
...config.editorConfig?.nodes || []
|
|
13
|
+
]
|
|
24
14
|
});
|
|
25
|
-
const html = $generateHtmlFromNodes(this.editor, selection);
|
|
26
|
-
return {
|
|
27
|
-
node: childNode,
|
|
28
|
-
html: postProcessHtml(html)
|
|
29
|
-
};
|
|
30
|
-
});
|
|
31
|
-
});
|
|
32
|
-
return flattenedNodes;
|
|
33
|
-
}
|
|
34
|
-
toHtml(state) {
|
|
35
|
-
const preparedState = prepareLexicalState(state);
|
|
36
|
-
const editorState = this.editor.parseEditorState(preparedState);
|
|
37
|
-
this.editor.setEditorState(editorState);
|
|
38
|
-
let html = "";
|
|
39
|
-
this.editor.update(() => {
|
|
40
|
-
html = $generateHtmlFromNodes(this.editor);
|
|
41
|
-
});
|
|
42
|
-
return postProcessHtml(html);
|
|
43
|
-
}
|
|
44
|
-
getNodeDescendants(node) {
|
|
45
|
-
if (!$isElementNode(node)) {
|
|
46
|
-
return [];
|
|
47
15
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
16
|
+
flatten(state) {
|
|
17
|
+
const editorState = this.editor.parseEditorState(prepareLexicalState(state));
|
|
18
|
+
this.editor.setEditorState(editorState);
|
|
19
|
+
let flattenedNodes = [];
|
|
20
|
+
this.editor.update(()=>{
|
|
21
|
+
const children = $getRoot().getChildren();
|
|
22
|
+
flattenedNodes = children.map((childNode)=>{
|
|
23
|
+
const selection = $createNodeSelection();
|
|
24
|
+
selection.add(childNode.getKey());
|
|
25
|
+
this.getNodeDescendants(childNode).forEach((node)=>{
|
|
26
|
+
selection.add(node.getKey());
|
|
27
|
+
});
|
|
28
|
+
const html = $generateHtmlFromNodes(this.editor, selection);
|
|
29
|
+
return {
|
|
30
|
+
node: childNode,
|
|
31
|
+
html: postProcessHtml(html)
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
return flattenedNodes;
|
|
36
|
+
}
|
|
37
|
+
toHtml(state) {
|
|
38
|
+
const preparedState = prepareLexicalState(state);
|
|
39
|
+
const editorState = this.editor.parseEditorState(preparedState);
|
|
40
|
+
this.editor.setEditorState(editorState);
|
|
41
|
+
let html = "";
|
|
42
|
+
this.editor.update(()=>{
|
|
43
|
+
html = $generateHtmlFromNodes(this.editor);
|
|
44
|
+
});
|
|
45
|
+
return postProcessHtml(html);
|
|
46
|
+
}
|
|
47
|
+
getNodeDescendants(node) {
|
|
48
|
+
if (!$isElementNode(node)) return [];
|
|
49
|
+
const children = node.getChildren();
|
|
50
|
+
return [
|
|
51
|
+
...children,
|
|
52
|
+
...children.map((child)=>this.getNodeDescendants(child)).flat()
|
|
53
|
+
];
|
|
54
|
+
}
|
|
51
55
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
};
|
|
56
|
+
const createLexicalStateTransformer = (config)=>new LexicalStateTransformer(config);
|
|
57
|
+
export { createLexicalStateTransformer };
|
|
55
58
|
|
|
56
59
|
//# sourceMappingURL=createLexicalStateTransformer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"file":"createLexicalStateTransformer.js","sources":["../src/createLexicalStateTransformer.ts"],"sourcesContent":["import type { CreateEditorArgs, LexicalEditor, SerializedEditorState, LexicalNode } from \"lexical\";\nimport { $getRoot, $createNodeSelection, $isElementNode } from \"lexical\";\nimport { $generateHtmlFromNodes } from \"@lexical/html\";\nimport { createHeadlessEditor } from \"@lexical/headless\";\nimport { allNodes, prepareLexicalState } from \"@webiny/lexical-nodes\";\nimport { postProcessHtml } from \"./postProcessHtml.js\";\n\ninterface LexicalStateTransformerConfig {\n editorConfig?: Pick<CreateEditorArgs, \"nodes\" | \"theme\">;\n}\n\nexport type FlatStateWithHTML = Array<{ node: LexicalNode; html: string }>;\n\nclass LexicalStateTransformer {\n private readonly editor: LexicalEditor;\n\n constructor(config: LexicalStateTransformerConfig = {}) {\n this.editor = createHeadlessEditor({\n ...config.editorConfig,\n nodes: [...allNodes, ...(config.editorConfig?.nodes || [])]\n });\n }\n\n public flatten(state: string | SerializedEditorState) {\n const editorState = this.editor.parseEditorState(prepareLexicalState(state));\n this.editor.setEditorState(editorState);\n\n let flattenedNodes: FlatStateWithHTML = [];\n\n this.editor.update(() => {\n const children = $getRoot().getChildren();\n\n flattenedNodes = children.map(childNode => {\n const selection = $createNodeSelection();\n selection.add(childNode.getKey());\n\n this.getNodeDescendants(childNode).forEach(node => {\n selection.add(node.getKey());\n });\n\n const html = $generateHtmlFromNodes(this.editor, selection);\n\n return {\n node: childNode,\n html: postProcessHtml(html)\n };\n });\n });\n\n return flattenedNodes;\n }\n\n public toHtml(state: string | SerializedEditorState) {\n const preparedState = prepareLexicalState(state);\n const editorState = this.editor.parseEditorState(preparedState);\n this.editor.setEditorState(editorState);\n\n let html = \"\";\n\n this.editor.update(() => {\n html = $generateHtmlFromNodes(this.editor);\n });\n\n return postProcessHtml(html);\n }\n\n private getNodeDescendants(node: LexicalNode): LexicalNode[] {\n if (!$isElementNode(node)) {\n return [];\n }\n const children = node.getChildren();\n return [...children, ...children.map(child => this.getNodeDescendants(child)).flat()];\n }\n}\n\nexport const createLexicalStateTransformer = (config?: LexicalStateTransformerConfig) => {\n return new LexicalStateTransformer(config);\n};\n"],"names":["LexicalStateTransformer","config","createHeadlessEditor","allNodes","state","editorState","prepareLexicalState","flattenedNodes","children","$getRoot","childNode","selection","$createNodeSelection","node","html","$generateHtmlFromNodes","postProcessHtml","preparedState","$isElementNode","child","createLexicalStateTransformer"],"mappings":";;;;;AAaA,MAAMA;IAGF,YAAYC,SAAwC,CAAC,CAAC,CAAE;QACpD,IAAI,CAAC,MAAM,GAAGC,qBAAqB;YAC/B,GAAGD,OAAO,YAAY;YACtB,OAAO;mBAAIE;mBAAcF,OAAO,YAAY,EAAE,SAAS,EAAE;aAAE;QAC/D;IACJ;IAEO,QAAQG,KAAqC,EAAE;QAClD,MAAMC,cAAc,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAACC,oBAAoBF;QACrE,IAAI,CAAC,MAAM,CAAC,cAAc,CAACC;QAE3B,IAAIE,iBAAoC,EAAE;QAE1C,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;YACf,MAAMC,WAAWC,WAAW,WAAW;YAEvCF,iBAAiBC,SAAS,GAAG,CAACE,CAAAA;gBAC1B,MAAMC,YAAYC;gBAClBD,UAAU,GAAG,CAACD,UAAU,MAAM;gBAE9B,IAAI,CAAC,kBAAkB,CAACA,WAAW,OAAO,CAACG,CAAAA;oBACvCF,UAAU,GAAG,CAACE,KAAK,MAAM;gBAC7B;gBAEA,MAAMC,OAAOC,uBAAuB,IAAI,CAAC,MAAM,EAAEJ;gBAEjD,OAAO;oBACH,MAAMD;oBACN,MAAMM,gBAAgBF;gBAC1B;YACJ;QACJ;QAEA,OAAOP;IACX;IAEO,OAAOH,KAAqC,EAAE;QACjD,MAAMa,gBAAgBX,oBAAoBF;QAC1C,MAAMC,cAAc,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAACY;QACjD,IAAI,CAAC,MAAM,CAAC,cAAc,CAACZ;QAE3B,IAAIS,OAAO;QAEX,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;YACfA,OAAOC,uBAAuB,IAAI,CAAC,MAAM;QAC7C;QAEA,OAAOC,gBAAgBF;IAC3B;IAEQ,mBAAmBD,IAAiB,EAAiB;QACzD,IAAI,CAACK,eAAeL,OAChB,OAAO,EAAE;QAEb,MAAML,WAAWK,KAAK,WAAW;QACjC,OAAO;eAAIL;eAAaA,SAAS,GAAG,CAACW,CAAAA,QAAS,IAAI,CAAC,kBAAkB,CAACA,QAAQ,IAAI;SAAG;IACzF;AACJ;AAEO,MAAMC,gCAAgC,CAACnB,SACnC,IAAID,wBAAwBC"}
|
package/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webiny/lexical-converter",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.4.0-beta.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./index.js",
|
|
@@ -9,18 +9,18 @@
|
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"@lexical/headless": "0.44.0",
|
|
11
11
|
"@lexical/html": "0.44.0",
|
|
12
|
-
"@webiny/lexical-nodes": "6.
|
|
12
|
+
"@webiny/lexical-nodes": "6.4.0-beta.1",
|
|
13
13
|
"cheerio": "1.2.0",
|
|
14
14
|
"lexical": "0.44.0"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
17
|
-
"@webiny/build-tools": "6.
|
|
17
|
+
"@webiny/build-tools": "6.4.0-beta.1",
|
|
18
18
|
"jsdom": "29.1.1",
|
|
19
|
-
"vitest": "4.1.
|
|
19
|
+
"vitest": "4.1.6"
|
|
20
20
|
},
|
|
21
21
|
"publishConfig": {
|
|
22
22
|
"access": "public",
|
|
23
23
|
"directory": "dist"
|
|
24
24
|
},
|
|
25
|
-
"gitHead": "
|
|
25
|
+
"gitHead": "73237b8243693038c072bae1c0b783387448cbbe"
|
|
26
26
|
}
|
package/postProcessHtml.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { load } from "cheerio";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
$(
|
|
8
|
-
});
|
|
9
|
-
return $("body").html() ?? html;
|
|
2
|
+
const postProcessHtml = (html)=>{
|
|
3
|
+
const $ = load(html);
|
|
4
|
+
$("b").each((_, el)=>{
|
|
5
|
+
$(el).replaceWith($(el).html() ?? "");
|
|
6
|
+
});
|
|
7
|
+
return $("body").html() ?? html;
|
|
10
8
|
};
|
|
9
|
+
export { postProcessHtml };
|
|
11
10
|
|
|
12
11
|
//# sourceMappingURL=postProcessHtml.js.map
|
package/postProcessHtml.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"file":"postProcessHtml.js","sources":["../src/postProcessHtml.ts"],"sourcesContent":["import { load } from \"cheerio\";\n\nexport const postProcessHtml = (html: string) => {\n const $ = load(html);\n\n // Replace <b> elements with their text content (unwrap them)\n $(\"b\").each((_, el) => {\n $(el).replaceWith($(el).html() ?? \"\");\n });\n\n return $(\"body\").html() ?? html;\n};\n"],"names":["postProcessHtml","html","$","load","_","el"],"mappings":";AAEO,MAAMA,kBAAkB,CAACC;IAC5B,MAAMC,IAAIC,KAAKF;IAGfC,EAAE,KAAK,IAAI,CAAC,CAACE,GAAGC;QACZH,EAAEG,IAAI,WAAW,CAACH,EAAEG,IAAI,IAAI,MAAM;IACtC;IAEA,OAAOH,EAAE,QAAQ,IAAI,MAAMD;AAC/B"}
|
package/types.js
CHANGED
package/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["index.ts"],"sourcesContent":["export type { SerializedEditorState } from \"lexical\";\nexport * from \"./createHtmlToLexicalParser.js\";\nexport * from \"./createLexicalStateTransformer.js\";\n"],"mappings":"AACA;AACA;AAAmD","ignoreList":[]}
|
package/types.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["types.ts"],"sourcesContent":["import type { CreateEditorArgs, LexicalNode } from \"lexical\";\n\nexport type NodeMapper = (node: LexicalNode) => LexicalNode;\n\nexport interface ParserConfigurationOptions {\n editorConfig?: Pick<CreateEditorArgs, \"nodes\" | \"theme\">;\n nodeMapper?: NodeMapper;\n}\n"],"mappings":"","ignoreList":[]}
|