]> BookStack Code Mirror - bookstack/blobdiff - resources/js/wysiwyg/utils/nodes.ts
Opensearch: Fixed XML declaration when php short tags enabled
[bookstack] / resources / js / wysiwyg / utils / nodes.ts
index b8bb8de9a2de6ee88bc1fe2625de7811472aae0e..116a3f4e5c01e0a39ee0ed0b564dd325a226b99d 100644 (file)
@@ -1,23 +1,23 @@
 import {
+    $createParagraphNode,
     $getRoot,
     $isDecoratorNode,
-    $isElementNode,
+    $isElementNode, $isRootNode,
     $isTextNode,
     ElementNode,
     LexicalEditor,
-    LexicalNode
+    LexicalNode, RangeSelection
 } from "lexical";
 import {LexicalNodeMatcher} from "../nodes";
-import {$createCustomParagraphNode} from "../nodes/custom-paragraph";
 import {$generateNodesFromDOM} from "@lexical/html";
 import {htmlToDom} from "./dom";
-import {NodeHasAlignment} from "../nodes/_common";
+import {NodeHasAlignment, NodeHasInset} from "lexical/nodes/common";
 import {$findMatchingParent} from "@lexical/utils";
 
 function wrapTextNodes(nodes: LexicalNode[]): LexicalNode[] {
     return nodes.map(node => {
         if ($isTextNode(node)) {
-            const paragraph = $createCustomParagraphNode();
+            const paragraph = $createParagraphNode();
             paragraph.append(node);
             return paragraph;
         }
@@ -84,7 +84,7 @@ export function $getNearestBlockNodeForCoords(editor: LexicalEditor, x: number,
 
 export function $getNearestNodeBlockParent(node: LexicalNode): LexicalNode|null {
     const isBlockNode = (node: LexicalNode): boolean => {
-        return ($isElementNode(node) || $isDecoratorNode(node)) && !node.isInline();
+        return ($isElementNode(node) || $isDecoratorNode(node)) && !node.isInline() && !$isRootNode(node);
     };
 
     if (isBlockNode(node)) {
@@ -94,6 +94,50 @@ export function $getNearestNodeBlockParent(node: LexicalNode): LexicalNode|null
     return $findMatchingParent(node, isBlockNode);
 }
 
+export function $sortNodes(nodes: LexicalNode[]): LexicalNode[] {
+    const idChain: string[] = [];
+    const addIds = (n: ElementNode) => {
+        for (const child of n.getChildren()) {
+            idChain.push(child.getKey())
+            if ($isElementNode(child)) {
+                addIds(child)
+            }
+        }
+    };
+
+    const root = $getRoot();
+    addIds(root);
+
+    const sorted = Array.from(nodes);
+    sorted.sort((a, b) => {
+        const aIndex = idChain.indexOf(a.getKey());
+        const bIndex = idChain.indexOf(b.getKey());
+        return aIndex - bIndex;
+    });
+
+    return sorted;
+}
+
+export function $selectOrCreateAdjacent(node: LexicalNode, after: boolean): RangeSelection {
+    const nearestBlock = $getNearestNodeBlockParent(node) || node;
+    let target = after ? nearestBlock.getNextSibling() : nearestBlock.getPreviousSibling()
+
+    if (!target) {
+        target = $createParagraphNode();
+        if (after) {
+            nearestBlock.insertAfter(target)
+        } else {
+            nearestBlock.insertBefore(target);
+        }
+    }
+
+    return after ? target.selectStart() : target.selectEnd();
+}
+
 export function nodeHasAlignment(node: object): node is NodeHasAlignment {
     return '__alignment' in node;
+}
+
+export function nodeHasInset(node: object): node is NodeHasInset {
+    return '__inset' in node;
 }
\ No newline at end of file