]> BookStack Code Mirror - bookstack/blob - resources/js/wysiwyg/nodes/custom-table.ts
Lexical: Finished off core cell properties functionality
[bookstack] / resources / js / wysiwyg / nodes / custom-table.ts
1 import {SerializedTableNode, TableNode} from "@lexical/table";
2 import {DOMConversion, DOMConversionMap, DOMConversionOutput, LexicalNode, Spread} from "lexical";
3 import {EditorConfig} from "lexical/LexicalEditor";
4
5 import {el} from "../utils/dom";
6 import {getTableColumnWidths} from "../utils/tables";
7
8 export type SerializedCustomTableNode = Spread<{
9     id: string;
10     colWidths: string[];
11 }, SerializedTableNode>
12
13 export class CustomTableNode extends TableNode {
14     __id: string = '';
15     __colWidths: string[] = [];
16
17     static getType() {
18         return 'custom-table';
19     }
20
21     setId(id: string) {
22         const self = this.getWritable();
23         self.__id = id;
24     }
25
26     getId(): string {
27         const self = this.getLatest();
28         return self.__id;
29     }
30
31     setColWidths(widths: string[]) {
32         const self = this.getWritable();
33         self.__colWidths = widths;
34     }
35
36     getColWidths(): string[] {
37         const self = this.getLatest();
38         return self.__colWidths;
39     }
40
41     static clone(node: CustomTableNode) {
42         const newNode = new CustomTableNode(node.__key);
43         newNode.__id = node.__id;
44         newNode.__colWidths = node.__colWidths;
45         return newNode;
46     }
47
48     createDOM(config: EditorConfig): HTMLElement {
49         const dom = super.createDOM(config);
50         const id = this.getId();
51         if (id) {
52             dom.setAttribute('id', id);
53         }
54
55         const colWidths = this.getColWidths();
56         if (colWidths.length > 0) {
57             const colgroup = el('colgroup');
58             for (const width of colWidths) {
59                 const col = el('col');
60                 if (width) {
61                     col.style.width = width;
62                 }
63                 colgroup.append(col);
64             }
65             dom.append(colgroup);
66         }
67
68         return dom;
69     }
70
71     updateDOM(): boolean {
72         return true;
73     }
74
75     exportJSON(): SerializedCustomTableNode {
76         return {
77             ...super.exportJSON(),
78             type: 'custom-table',
79             version: 1,
80             id: this.__id,
81             colWidths: this.__colWidths,
82         };
83     }
84
85     static importJSON(serializedNode: SerializedCustomTableNode): CustomTableNode {
86         const node = $createCustomTableNode();
87         node.setId(serializedNode.id);
88         node.setColWidths(serializedNode.colWidths);
89         return node;
90     }
91
92     static importDOM(): DOMConversionMap|null {
93         return {
94             table(node: HTMLElement): DOMConversion|null {
95                 return {
96                     conversion: (element: HTMLElement): DOMConversionOutput|null => {
97                         const node = $createCustomTableNode();
98
99                         if (element.id) {
100                             node.setId(element.id);
101                         }
102
103                         const colWidths = getTableColumnWidths(element as HTMLTableElement);
104                         node.setColWidths(colWidths);
105
106                         return {node};
107                     },
108                     priority: 1,
109                 };
110             },
111         };
112     }
113 }
114
115 export function $createCustomTableNode(): CustomTableNode {
116     return new CustomTableNode();
117 }
118
119 export function $isCustomTableNode(node: LexicalNode | null | undefined): node is CustomTableNode {
120     return node instanceof CustomTableNode;
121 }