import { DOMConversionMap, DOMConversionOutput, LexicalNode, Spread } from "lexical"; import {EditorConfig} from "lexical/LexicalEditor"; import {HeadingNode, HeadingTagType, SerializedHeadingNode} from "@lexical/rich-text"; import { CommonBlockAlignment, commonPropertiesDifferent, SerializedCommonBlockNode, setCommonBlockPropsFromElement, updateElementWithCommonBlockProps } from "./_common"; export type SerializedCustomHeadingNode = Spread export class CustomHeadingNode extends HeadingNode { __id: string = ''; __alignment: CommonBlockAlignment = ''; static getType() { return 'custom-heading'; } setId(id: string) { const self = this.getWritable(); self.__id = id; } getId(): string { const self = this.getLatest(); return self.__id; } setAlignment(alignment: CommonBlockAlignment) { const self = this.getWritable(); self.__alignment = alignment; } getAlignment(): CommonBlockAlignment { const self = this.getLatest(); return self.__alignment; } static clone(node: CustomHeadingNode) { const newNode = new CustomHeadingNode(node.__tag, node.__key); newNode.__alignment = node.__alignment; return newNode; } createDOM(config: EditorConfig): HTMLElement { const dom = super.createDOM(config); updateElementWithCommonBlockProps(dom, this); return dom; } updateDOM(prevNode: CustomHeadingNode, dom: HTMLElement): boolean { return super.updateDOM(prevNode, dom) || commonPropertiesDifferent(prevNode, this); } exportJSON(): SerializedCustomHeadingNode { return { ...super.exportJSON(), type: 'custom-heading', version: 1, id: this.__id, alignment: this.__alignment, }; } static importJSON(serializedNode: SerializedCustomHeadingNode): CustomHeadingNode { const node = $createCustomHeadingNode(serializedNode.tag); node.setId(serializedNode.id); node.setAlignment(serializedNode.alignment); return node; } static importDOM(): DOMConversionMap | null { return { h1: (node: Node) => ({ conversion: $convertHeadingElement, priority: 0, }), h2: (node: Node) => ({ conversion: $convertHeadingElement, priority: 0, }), h3: (node: Node) => ({ conversion: $convertHeadingElement, priority: 0, }), h4: (node: Node) => ({ conversion: $convertHeadingElement, priority: 0, }), h5: (node: Node) => ({ conversion: $convertHeadingElement, priority: 0, }), h6: (node: Node) => ({ conversion: $convertHeadingElement, priority: 0, }), }; } } function $convertHeadingElement(element: HTMLElement): DOMConversionOutput { const nodeName = element.nodeName.toLowerCase(); let node = null; if ( nodeName === 'h1' || nodeName === 'h2' || nodeName === 'h3' || nodeName === 'h4' || nodeName === 'h5' || nodeName === 'h6' ) { node = $createCustomHeadingNode(nodeName); setCommonBlockPropsFromElement(element, node); } return {node}; } export function $createCustomHeadingNode(tag: HeadingTagType) { return new CustomHeadingNode(tag); } export function $isCustomHeadingNode(node: LexicalNode | null | undefined): node is CustomHeadingNode { return node instanceof CustomHeadingNode; }