]> BookStack Code Mirror - bookstack/blob - resources/js/wysiwyg/lexical/core/nodes/common.ts
eac9c82959573ee8d74b5f7d1ee17e18cae05492
[bookstack] / resources / js / wysiwyg / lexical / core / nodes / common.ts
1 import {sizeToPixels} from "../../../utils/dom";
2 import {SerializedCommonBlockNode} from "lexical/nodes/CommonBlockNode";
3
4 export type CommonBlockAlignment = 'left' | 'right' | 'center' | 'justify' | '';
5 const validAlignments: CommonBlockAlignment[] = ['left', 'right', 'center', 'justify'];
6
7 type EditorNodeDirection = 'ltr' | 'rtl' | null;
8
9 export interface NodeHasAlignment {
10     readonly __alignment: CommonBlockAlignment;
11     setAlignment(alignment: CommonBlockAlignment): void;
12     getAlignment(): CommonBlockAlignment;
13 }
14
15 export interface NodeHasId {
16     readonly __id: string;
17     setId(id: string): void;
18     getId(): string;
19 }
20
21 export interface NodeHasInset {
22     readonly __inset: number;
23     setInset(inset: number): void;
24     getInset(): number;
25 }
26
27 export interface NodeHasDirection {
28     readonly __dir: EditorNodeDirection;
29     setDirection(direction: EditorNodeDirection): void;
30     getDirection(): EditorNodeDirection;
31 }
32
33 export interface CommonBlockInterface extends NodeHasId, NodeHasAlignment, NodeHasInset, NodeHasDirection {}
34
35 export function extractAlignmentFromElement(element: HTMLElement): CommonBlockAlignment {
36     const textAlignStyle: string = element.style.textAlign || '';
37     if (validAlignments.includes(textAlignStyle as CommonBlockAlignment)) {
38         return textAlignStyle as CommonBlockAlignment;
39     }
40
41     if (element.classList.contains('align-left')) {
42         return 'left';
43     } else if (element.classList.contains('align-right')) {
44         return 'right'
45     } else if (element.classList.contains('align-center')) {
46         return 'center'
47     } else if (element.classList.contains('align-justify')) {
48         return 'justify'
49     }
50
51     return '';
52 }
53
54 export function extractInsetFromElement(element: HTMLElement): number {
55     const elemPadding: string = element.style.paddingLeft || '0';
56     return sizeToPixels(elemPadding);
57 }
58
59 export function extractDirectionFromElement(element: HTMLElement): EditorNodeDirection {
60     const elemDir = (element.dir || '').toLowerCase();
61     if (elemDir === 'rtl' || elemDir === 'ltr') {
62         return elemDir;
63     }
64
65     return null;
66 }
67
68 export function setCommonBlockPropsFromElement(element: HTMLElement, node: CommonBlockInterface): void {
69     if (element.id) {
70         node.setId(element.id);
71     }
72
73     node.setAlignment(extractAlignmentFromElement(element));
74     node.setInset(extractInsetFromElement(element));
75     node.setDirection(extractDirectionFromElement(element));
76 }
77
78 export function commonPropertiesDifferent(nodeA: CommonBlockInterface, nodeB: CommonBlockInterface): boolean {
79     return nodeA.__id !== nodeB.__id ||
80         nodeA.__alignment !== nodeB.__alignment ||
81         nodeA.__inset !== nodeB.__inset ||
82         nodeA.__dir !== nodeB.__dir;
83 }
84
85 export function updateElementWithCommonBlockProps(element: HTMLElement, node: CommonBlockInterface): void {
86     if (node.__id) {
87         element.setAttribute('id', node.__id);
88     }
89
90     if (node.__alignment) {
91         element.classList.add('align-' + node.__alignment);
92     }
93
94     if (node.__inset) {
95         element.style.paddingLeft = `${node.__inset}px`;
96     }
97
98     if (node.__dir) {
99         element.dir = node.__dir;
100     }
101 }
102
103 export function deserializeCommonBlockNode(serializedNode: SerializedCommonBlockNode, node: CommonBlockInterface): void {
104     node.setId(serializedNode.id);
105     node.setAlignment(serializedNode.alignment);
106     node.setInset(serializedNode.inset);
107     node.setDirection(serializedNode.direction);
108 }
109
110 export interface NodeHasSize {
111     setHeight(height: number): void;
112     setWidth(width: number): void;
113     getHeight(): number;
114     getWidth(): number;
115 }