]> BookStack Code Mirror - bookstack/blob - resources/js/wysiwyg/services/node-clipboard.ts
7d880db98895ce187bf0f4e23a3139b5f88d15cb
[bookstack] / resources / js / wysiwyg / services / node-clipboard.ts
1 import {$isElementNode, LexicalEditor, LexicalNode, SerializedLexicalNode} from "lexical";
2
3 type SerializedLexicalNodeWithChildren = {
4     node: SerializedLexicalNode,
5     children: SerializedLexicalNodeWithChildren[],
6 };
7
8 function serializeNodeRecursive(node: LexicalNode): SerializedLexicalNodeWithChildren {
9     const childNodes = $isElementNode(node) ? node.getChildren() : [];
10     return {
11         node: node.exportJSON(),
12         children: childNodes.map(n => serializeNodeRecursive(n)),
13     };
14 }
15
16 function unserializeNodeRecursive(editor: LexicalEditor, {node, children}: SerializedLexicalNodeWithChildren): LexicalNode|null {
17     const instance = editor._nodes.get(node.type)?.klass.importJSON(node);
18     if (!instance) {
19         return null;
20     }
21
22     const childNodes = children.map(child => unserializeNodeRecursive(editor, child));
23     for (const child of childNodes) {
24         if (child && $isElementNode(instance)) {
25             instance.append(child);
26         }
27     }
28
29     return instance;
30 }
31
32 export class NodeClipboard<T extends LexicalNode> {
33     nodeClass: {importJSON: (s: SerializedLexicalNode) => T};
34     protected store: SerializedLexicalNodeWithChildren[] = [];
35
36     constructor(nodeClass: {importJSON: (s: any) => T}) {
37         this.nodeClass = nodeClass;
38     }
39
40     set(...nodes: LexicalNode[]): void {
41         this.store.splice(0, this.store.length);
42         for (const node of nodes) {
43             this.store.push(serializeNodeRecursive(node));
44         }
45     }
46
47     get(editor: LexicalEditor): LexicalNode[] {
48         return this.store.map(json => unserializeNodeRecursive(editor, json)).filter((node) => {
49             return node !== null;
50         });
51     }
52
53     size(): number {
54         return this.store.length;
55     }
56 }