X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/e2409a5fab3e38e1753adb51ff432b6104c7572b..refs/pull/5280/head:/resources/js/wysiwyg/nodes/index.ts diff --git a/resources/js/wysiwyg/nodes/index.ts b/resources/js/wysiwyg/nodes/index.ts index 03fcd33a5..b5483c500 100644 --- a/resources/js/wysiwyg/nodes/index.ts +++ b/resources/js/wysiwyg/nodes/index.ts @@ -1,34 +1,128 @@ import {HeadingNode, QuoteNode} from '@lexical/rich-text'; import {CalloutNode} from './callout'; -import {ElementNode, KlassConstructor, LexicalNode, LexicalNodeReplacement, ParagraphNode} from "lexical"; +import { + ElementNode, + KlassConstructor, + LexicalNode, + LexicalNodeReplacement, NodeMutation, + ParagraphNode +} from "lexical"; import {CustomParagraphNode} from "./custom-paragraph"; import {LinkNode} from "@lexical/link"; import {ImageNode} from "./image"; import {DetailsNode, SummaryNode} from "./details"; import {ListItemNode, ListNode} from "@lexical/list"; +import {TableCellNode, TableNode, TableRowNode} from "@lexical/table"; +import {CustomTableNode} from "./custom-table"; +import {HorizontalRuleNode} from "./horizontal-rule"; +import {CodeBlockNode} from "./code-block"; +import {DiagramNode} from "./diagram"; +import {EditorUiContext} from "../ui/framework/core"; +import {MediaNode} from "./media"; +import {CustomListItemNode} from "./custom-list-item"; +import {CustomTableCellNode} from "./custom-table-cell"; +import {CustomTableRowNode} from "./custom-table-row"; +import {CustomHeadingNode} from "./custom-heading"; +import {CustomQuoteNode} from "./custom-quote"; +import {CustomListNode} from "./custom-list"; /** * Load the nodes for lexical. */ export function getNodesForPageEditor(): (KlassConstructor | LexicalNodeReplacement)[] { return [ - CalloutNode, // Todo - Create custom - HeadingNode, // Todo - Create custom - QuoteNode, // Todo - Create custom - ListNode, // Todo - Create custom - ListItemNode, - ImageNode, + CalloutNode, + CustomHeadingNode, + CustomQuoteNode, + CustomListNode, + CustomListItemNode, // TODO - Alignment? + CustomTableNode, + CustomTableRowNode, + CustomTableCellNode, + ImageNode, // TODO - Alignment + HorizontalRuleNode, DetailsNode, SummaryNode, + CodeBlockNode, + DiagramNode, + MediaNode, // TODO - Alignment CustomParagraphNode, + LinkNode, { replace: ParagraphNode, with: (node: ParagraphNode) => { return new CustomParagraphNode(); } }, - LinkNode, + { + replace: HeadingNode, + with: (node: HeadingNode) => { + return new CustomHeadingNode(node.__tag); + } + }, + { + replace: QuoteNode, + with: (node: QuoteNode) => { + return new CustomQuoteNode(); + } + }, + { + replace: ListNode, + with: (node: ListNode) => { + return new CustomListNode(node.getListType(), node.getStart()); + } + }, + { + replace: ListItemNode, + with: (node: ListItemNode) => { + return new CustomListItemNode(node.__value, node.__checked); + } + }, + { + replace: TableNode, + with(node: TableNode) { + return new CustomTableNode(); + } + }, + { + replace: TableRowNode, + with(node: TableRowNode) { + return new CustomTableRowNode(); + } + }, + { + replace: TableCellNode, + with: (node: TableCellNode) => { + const cell = new CustomTableCellNode( + node.__headerState, + node.__colSpan, + node.__width, + ); + cell.__rowSpan = node.__rowSpan; + return cell; + } + }, ]; } +export function registerCommonNodeMutationListeners(context: EditorUiContext): void { + const decorated = [ImageNode, CodeBlockNode, DiagramNode]; + + const decorationDestroyListener = (mutations: Map): void => { + for (let [nodeKey, mutation] of mutations) { + if (mutation === "destroyed") { + const decorator = context.manager.getDecoratorByNodeKey(nodeKey); + if (decorator) { + decorator.destroy(context); + } + } + } + }; + + for (let decoratedNode of decorated) { + // Have to pass a unique function here since they are stored by lexical keyed on listener function. + context.editor.registerMutationListener(decoratedNode, (mutations) => decorationDestroyListener(mutations)); + } +} + export type LexicalNodeMatcher = (node: LexicalNode|null|undefined) => boolean; export type LexicalElementNodeCreator = () => ElementNode; \ No newline at end of file