X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/111a313d5125bd890d7df46929802f4621388c95..refs/pull/5676/head:/resources/js/wysiwyg/utils/nodes.ts diff --git a/resources/js/wysiwyg/utils/nodes.ts b/resources/js/wysiwyg/utils/nodes.ts index e33cfda7c..116a3f4e5 100644 --- a/resources/js/wysiwyg/utils/nodes.ts +++ b/resources/js/wysiwyg/utils/nodes.ts @@ -1,14 +1,23 @@ -import {$getRoot, $isElementNode, $isTextNode, ElementNode, LexicalEditor, LexicalNode} from "lexical"; +import { + $createParagraphNode, + $getRoot, + $isDecoratorNode, + $isElementNode, $isRootNode, + $isTextNode, + ElementNode, + LexicalEditor, + 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; } @@ -73,6 +82,62 @@ export function $getNearestBlockNodeForCoords(editor: LexicalEditor, x: number, return null; } +export function $getNearestNodeBlockParent(node: LexicalNode): LexicalNode|null { + const isBlockNode = (node: LexicalNode): boolean => { + return ($isElementNode(node) || $isDecoratorNode(node)) && !node.isInline() && !$isRootNode(node); + }; + + if (isBlockNode(node)) { + return node; + } + + 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