I'm working with Facebook's Lexical editor in Typescript and need to preserve class attributes on text nodes fx. on a h4 tag, when importing them to the editor through the $generateHtmlFromNodes method. I need the classes to persist in the editor, so that I can manipulate the html string after exporting it from the Lexical editor, but I'm a bit confused about the implementation of the importDOM method especially on what to return and how to make it preserve attributes. Can anyone help create a simple class that extends the TextNode class to allow for preserving the class attribute?
I understand that I need to update the importDOM & exportDOM methods, but everything I have tried does not seem to work...
Any help is greatly appreciated!!
Current implementation:
This is what I've been able to implement with the importDOM method, which I'm having trouble understanding what it should return and how I can manipulate it to preserve the classes on import (So sorry if it seems weird, but I've been trying different stuff without luck):
import {
TextNode,
EditorConfig,
LexicalEditor,
DOMExportOutput,
DOMConversionMap,
DOMConversionOutput,
NodeKey
} from "lexical"
export class ClassNode extends TextNode {
private tagName: string
private __class: string
/**
* Constructor for creating an instance of ClassNode.
* @param {string} classAttribute - The class attribute for the node.
*/
constructor(tagName: string, classAttribute: string, text?: string, key?: NodeKey) {
super(text || "", key)
this.tagName = tagName
this.__class = classAttribute
}
static getType(): string {
return "class-node"
}
static convertClassNodeElement(domNode: HTMLElement): DOMConversionOutput | null {
const hasClass = domNode.classList.length > 0
if (!hasClass) return null
console.log("domNode: ", domNode)
return {node: new ClassNode("h4", domNode.className)}
}
/**
* Clones an instance of CustomNode.
* @param {CustomNode} node - The node instance to clone.
* @returns {CustomNode} The cloned node instance.
*/
static clone(node: ClassNode): ClassNode {
return new ClassNode(node.tagName, node.__class, node.__text, node.__key)
}
/**
* Creates the DOM representation of the node.
* @param {Object} config - Configuration object passed by the editor.
* @returns {HTMLElement} The DOM element representing this node.
*/
createDOM(config: EditorConfig): HTMLElement {
const element = document.createElement(this.tagName)
element.className = this.__class
return element
}
/**
* Updates the DOM when the node has changed.
* @returns {boolean} True if the DOM should be updated, false otherwise.
*/
updateDOM() {
return false
}
static importDOM(): DOMConversionMap | null {
return {
h4: (domNode: HTMLElement) => {
return {
conversion: ClassNode.convertClassNodeElement,
priority: 4
}
}
}
}
/**
* Defines how the node is exported to an external DOM.
* @returns {Object} The export configuration for the node.
*/
exportDOM(editor: LexicalEditor): DOMExportOutput {
const element = document.createElement(this.tagName)
element.className = this.__class
return {element}
}
}