]> BookStack Code Mirror - bookstack/blob - resources/js/wysiwyg/nodes/custom-table-row.ts
effaaa50d014893d6f92893302b314a54afb5de9
[bookstack] / resources / js / wysiwyg / nodes / custom-table-row.ts
1 import {
2     $createParagraphNode,
3     $isElementNode,
4     $isLineBreakNode,
5     $isTextNode,
6     DOMConversionMap,
7     DOMConversionOutput,
8     EditorConfig,
9     LexicalNode,
10     Spread
11 } from "lexical";
12
13 import {
14     $createTableCellNode,
15     $isTableCellNode,
16     SerializedTableRowNode,
17     TableCellHeaderStates,
18     TableRowNode
19 } from "@lexical/table";
20 import {createStyleMapFromDomStyles, StyleMap} from "../utils/styles";
21 import {NodeKey} from "lexical/LexicalNode";
22
23 export type SerializedCustomTableRowNode = Spread<{
24     styles: Record<string, string>,
25 }, SerializedTableRowNode>
26
27 export class CustomTableRowNode extends TableRowNode {
28     __styles: StyleMap = new Map();
29
30     constructor(key?: NodeKey) {
31         super(0, key);
32     }
33
34     static getType(): string {
35         return 'custom-table-row';
36     }
37
38     static clone(node: CustomTableRowNode): CustomTableRowNode {
39         const cellNode = new CustomTableRowNode(node.__key);
40
41         cellNode.__styles = new Map(node.__styles);
42         return cellNode;
43     }
44
45     getStyles(): StyleMap {
46         const self = this.getLatest();
47         return new Map(self.__styles);
48     }
49
50     setStyles(styles: StyleMap): void {
51         const self = this.getWritable();
52         self.__styles = new Map(styles);
53     }
54
55     createDOM(config: EditorConfig): HTMLElement {
56         const element = super.createDOM(config);
57
58         for (const [name, value] of this.__styles.entries()) {
59             element.style.setProperty(name, value);
60         }
61
62         return element;
63     }
64
65     updateDOM(prevNode: CustomTableRowNode): boolean {
66         return super.updateDOM(prevNode)
67             || this.__styles !== prevNode.__styles;
68     }
69
70     static importDOM(): DOMConversionMap | null {
71         return {
72             tr: (node: Node) => ({
73                 conversion: $convertTableRowElement,
74                 priority: 0,
75             }),
76         };
77     }
78
79     static importJSON(serializedNode: SerializedCustomTableRowNode): CustomTableRowNode {
80         const node = $createCustomTableRowNode();
81
82         node.setStyles(new Map(Object.entries(serializedNode.styles)));
83
84         return node;
85     }
86
87     exportJSON(): SerializedCustomTableRowNode {
88         return {
89             ...super.exportJSON(),
90             height: 0,
91             type: 'custom-table-row',
92             styles: Object.fromEntries(this.__styles),
93         };
94     }
95 }
96
97 export function $convertTableRowElement(domNode: Node): DOMConversionOutput {
98     const rowNode = $createCustomTableRowNode();
99
100     if (domNode instanceof HTMLElement) {
101         rowNode.setStyles(createStyleMapFromDomStyles(domNode.style));
102     }
103
104     return {node: rowNode};
105 }
106
107 export function $createCustomTableRowNode(): CustomTableRowNode {
108     return new CustomTableRowNode();
109 }
110
111 export function $isCustomTableRowNode(node: LexicalNode | null | undefined): node is CustomTableRowNode {
112     return node instanceof CustomTableRowNode;
113 }