]> BookStack Code Mirror - bookstack/blob - resources/js/wysiwyg/nodes/custom-paragraph.ts
Lexical: Added custom alignment handling for blocks
[bookstack] / resources / js / wysiwyg / nodes / custom-paragraph.ts
1 import {
2     DOMConversion,
3     DOMConversionMap,
4     DOMConversionOutput,
5     LexicalNode,
6     ParagraphNode, SerializedParagraphNode, Spread,
7 } from "lexical";
8 import {EditorConfig} from "lexical/LexicalEditor";
9 import {
10     CommonBlockAlignment, commonPropertiesDifferent,
11     SerializedCommonBlockNode,
12     setCommonBlockPropsFromElement,
13     updateElementWithCommonBlockProps
14 } from "./_common";
15
16 export type SerializedCustomParagraphNode = Spread<SerializedCommonBlockNode, SerializedParagraphNode>
17
18 export class CustomParagraphNode extends ParagraphNode {
19     __id: string = '';
20     __alignment: CommonBlockAlignment = '';
21
22     static getType() {
23         return 'custom-paragraph';
24     }
25
26     setId(id: string) {
27         const self = this.getWritable();
28         self.__id = id;
29     }
30
31     getId(): string {
32         const self = this.getLatest();
33         return self.__id;
34     }
35
36     setAlignment(alignment: CommonBlockAlignment) {
37         const self = this.getWritable();
38         self.__alignment = alignment;
39     }
40
41     getAlignment(): CommonBlockAlignment {
42         const self = this.getLatest();
43         return self.__alignment;
44     }
45
46     static clone(node: CustomParagraphNode): CustomParagraphNode {
47         const newNode = new CustomParagraphNode(node.__key);
48         newNode.__id = node.__id;
49         newNode.__alignment = node.__alignment;
50         return newNode;
51     }
52
53     createDOM(config: EditorConfig): HTMLElement {
54         const dom = super.createDOM(config);
55         updateElementWithCommonBlockProps(dom, this);
56         return dom;
57     }
58
59     updateDOM(prevNode: CustomParagraphNode, dom: HTMLElement, config: EditorConfig): boolean {
60         return super.updateDOM(prevNode, dom, config)
61             || commonPropertiesDifferent(prevNode, this);
62     }
63
64     exportJSON(): SerializedCustomParagraphNode {
65         return {
66             ...super.exportJSON(),
67             type: 'custom-paragraph',
68             version: 1,
69             id: this.__id,
70             alignment: this.__alignment,
71         };
72     }
73
74     static importJSON(serializedNode: SerializedCustomParagraphNode): CustomParagraphNode {
75         const node = $createCustomParagraphNode();
76         node.setId(serializedNode.id);
77         node.setAlignment(serializedNode.alignment);
78         return node;
79     }
80
81     static importDOM(): DOMConversionMap|null {
82         return {
83             p(node: HTMLElement): DOMConversion|null {
84                 return {
85                     conversion: (element: HTMLElement): DOMConversionOutput|null => {
86                         const node = $createCustomParagraphNode();
87                         if (element.style.textIndent) {
88                             const indent = parseInt(element.style.textIndent, 10) / 20;
89                             if (indent > 0) {
90                                 node.setIndent(indent);
91                             }
92                         }
93
94                         setCommonBlockPropsFromElement(element, node);
95
96                         return {node};
97                     },
98                     priority: 1,
99                 };
100             },
101         };
102     }
103 }
104
105 export function $createCustomParagraphNode(): CustomParagraphNode {
106     return new CustomParagraphNode();
107 }
108
109 export function $isCustomParagraphNode(node: LexicalNode | null | undefined): node is CustomParagraphNode {
110     return node instanceof CustomParagraphNode;
111 }