1import {HeadingNode} from '@lexical/rich-text'; 2 3export class CustomHeadingNode extends HeadingNode { 4 __className; 5 constructor(tag = 'h1', className = '', key) { 6 super(tag, key); 7 this.__className = className; 8 } 9 10 // Use the same type, so this replaces the default HeadingNode when registered. 11 static getType() { 12 return 'heading'; 13 } 14 15 static clone(node) { 16 return new CustomHeadingNode(node.__tag, node.__className, node.__key); 17 } 18 19 // Persist the className in the node JSON 20 exportJSON() { 21 const json = super.exportJSON(); 22 json.className = this.__className || ''; 23 return json; 24 } 25 26 static importJSON(serialized) { 27 return new CustomHeadingNode(serialized.tag, serialized.className); 28 } 29 30 static importDOM() { 31 // noinspection JSValidateTypes 32 return { 33 h1: () => ({ 34 conversion: $convertHeadingElement, 35 priority: 1, 36 }), 37 h2: () => ({ 38 conversion: $convertHeadingElement, 39 priority: 1, 40 }), 41 h3: () => ({ 42 conversion: $convertHeadingElement, 43 priority: 1, 44 }), 45 h4: () => ({ 46 conversion: $convertHeadingElement, 47 priority: 1, 48 }), 49 h5: () => ({ 50 conversion: $convertHeadingElement, 51 priority: 1, 52 }), 53 h6: () => ({ 54 conversion: $convertHeadingElement, 55 priority: 1, 56 }), 57 }; 58 } 59 60 // When Lexical renders the DOM, attach the class 61 /** 62 * @returns {HTMLElement} 63 **/ 64 createDOM(config) { 65 // noinspection JSVoidFunctionReturnValueUsed,JSValidateTypes 66 /** 67 * @type {HTMLElement} 68 **/ 69 const dom = super.createDOM(config); 70 if (this.__className) { 71 dom.className = this.__className; 72 } 73 return dom; 74 } 75 76 updateDOM(prevNode, dom, config) { 77 const shouldUpdate = super.updateDOM(prevNode, dom, config); 78 79 // Keep class in sync if it changed 80 if (prevNode.__className !== this.__className) { 81 dom.className = this.__className || ''; 82 return true; 83 } 84 85 return shouldUpdate; 86 } 87 88 // Optional: used when exporting nodes to HTML (e.g., with @lexical/html) 89 exportDOM() { 90 const element = document.createElement(this.__tag); 91 if (this.__className) element.className = this.__className; 92 return { type: 'element', element }; 93 } 94 95 // Convenience API 96 setClass(className) { 97 const writable = this.getWritable(); 98 writable.__className = className; 99 } 100 101 // noinspection JSUnusedGlobalSymbols 102 getClass() { 103 return this.__className; 104 } 105} 106 107function $convertHeadingElement(element) { 108 const node = $createCustomHeadingNode(element.nodeName.toLowerCase(), element.className); 109 return {node}; 110} 111 112// Factory and type check helpers 113export function $createCustomHeadingNode(tag = 'h1', className = '') { 114 return new CustomHeadingNode(tag, className); 115} 116 117export function $isCustomHeadingNode(node) { 118 return node instanceof CustomHeadingNode; 119}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.