]> BookStack Code Mirror - bookstack/blob - resources/js/wysiwyg/utils/nodes.ts
8e6c666109b82c2143bf1008e5b3c7ed7808940e
[bookstack] / resources / js / wysiwyg / utils / nodes.ts
1 import {$getRoot, $isTextNode, LexicalEditor, LexicalNode} from "lexical";
2 import {LexicalNodeMatcher} from "../nodes";
3 import {$createCustomParagraphNode} from "../nodes/custom-paragraph";
4 import {$generateNodesFromDOM} from "@lexical/html";
5 import {htmlToDom} from "./dom";
6
7 function wrapTextNodes(nodes: LexicalNode[]): LexicalNode[] {
8     return nodes.map(node => {
9         if ($isTextNode(node)) {
10             const paragraph = $createCustomParagraphNode();
11             paragraph.append(node);
12             return paragraph;
13         }
14         return node;
15     });
16 }
17
18 export function $htmlToBlockNodes(editor: LexicalEditor, html: string): LexicalNode[] {
19     const dom = htmlToDom(html);
20     const nodes = $generateNodesFromDOM(editor, dom);
21     return wrapTextNodes(nodes);
22 }
23
24 export function $getParentOfType(node: LexicalNode, matcher: LexicalNodeMatcher): LexicalNode | null {
25     for (const parent of node.getParents()) {
26         if (matcher(parent)) {
27             return parent;
28         }
29     }
30
31     return null;
32 }
33
34 /**
35  * Get the nearest root/block level node for the given position.
36  */
37 export function $getNearestBlockNodeForCoords(editor: LexicalEditor, x: number, y: number): LexicalNode | null {
38     // TODO - Take into account x for floated blocks?
39     const rootNodes = $getRoot().getChildren();
40     for (const node of rootNodes) {
41         const nodeDom = editor.getElementByKey(node.__key);
42         if (!nodeDom) {
43             continue;
44         }
45
46         const bounds = nodeDom.getBoundingClientRect();
47         if (y <= bounds.bottom) {
48             return node;
49         }
50     }
51
52     return null;
53 }