/* eslint-disable no-underscore-dangle -- Lexical nodes use protected __ fields by convention. */ import { $isTextNode, TextNode } from "lexical" import type { DOMConversionMap, DOMConversionOutput, DOMConversionProp, SerializedTextNode, } from "lexical" function patchTextStyleConversion( originalDOMConverter?: DOMConversionProp ) { return (node: HTMLElement): DOMConversionOutput | null => { const original = originalDOMConverter?.(node) const output = original?.conversion(node) if (!output) return null const color = node.style.color const backgroundColor = node.style.backgroundColor const textDecoration = node.style.textDecoration const style = [ color ? `color: ${color}` : null, backgroundColor ? `background-color: ${backgroundColor}` : null, textDecoration ? `text-decoration: ${textDecoration}` : null, ] .filter(Boolean) .join("; ") return { ...output, forChild: (lexicalNode, parent) => { const converted = output.forChild ? output.forChild(lexicalNode, parent) : lexicalNode if ($isTextNode(converted) && style) converted.setStyle(style) return converted }, } } } export class LexicalTextNode extends TextNode { static getType(): string { return "lexical-text" } static clone(node: LexicalTextNode): LexicalTextNode { return new LexicalTextNode(node.__text, node.__key) } static importJSON(node: SerializedTextNode): LexicalTextNode { return new LexicalTextNode().updateFromJSON(node) } static importDOM(): DOMConversionMap | null { const importers = TextNode.importDOM() return { ...importers, code: () => ({ conversion: patchTextStyleConversion(importers?.code), priority: 1, }), em: () => ({ conversion: patchTextStyleConversion(importers?.em), priority: 1, }), span: () => ({ conversion: patchTextStyleConversion(importers?.span), priority: 1, }), strong: () => ({ conversion: patchTextStyleConversion(importers?.strong), priority: 1, }), } } isSimpleText(): boolean { return this.__type === "lexical-text" && this.__mode === 0 } }