1

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}
  }
}

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.