0

I wanted to build an autocorrect plugin. So, I started out building a simple node transform. So, I just setup a custom autocorrect node and hardcoded two values which if the editor encounters, it should replace it with another set of hardcoded words. Now, the problem I am facing is that the identification of the hardcoded words isn't consistent. 

Only if the first word I type is one of the words I want to be transformed, then it works. If I type those words anywhere else, it's not identifying. So, it's basically not able to identify unless it's the only word I type. So, if you could help me with this anyway possible, that would be really helpful for me.Here is the code for the Custom node and the Plugin:

import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
import { LexicalEditor, TextNode } from "lexical";
import { useEffect } from "react";
import {
    $createAutocorrectNode,
    AutocorrectNode,
} from "./Nodes/AutocorrectNode";

function autocorrectTransform(node: TextNode) {
    const textContent = node.getTextContent();
    let replacedNode;
    if (textContent === "bikes") {
        replacedNode = node.replace($createAutocorrectNode("shumi"));
    } else if (textContent === "cars") {
        replacedNode = node.replace($createAutocorrectNode("karthik"));
    }
    replacedNode?.select();
}

function useAutocorrect(editor: LexicalEditor) {
    useEffect(() => {
        if (!editor.hasNodes([AutocorrectNode])) {
            throw new Error(
                "AutocorrectNode: AutocorrectNode not registered on editor"
            );
        }
    }, [editor]);

    useEffect(() => {
        const removeTransform = editor.registerNodeTransform(
            TextNode,
            autocorrectTransform
        );

        return () => {
            removeTransform();
        };
    }, [editor]);
}

export default function DictionaryOnHoverPlugin() {
    const [editor] = useLexicalComposerContext();
    useAutocorrect(editor);

    return null;
}

Here is the code of the custom node:

import type { Spread } from "lexical";

import {
    type DOMConversionMap,
    type DOMConversionOutput,
    type DOMExportOutput,
    type EditorConfig,
    type LexicalNode,
    type NodeKey,
    type SerializedTextNode,
    $applyNodeReplacement,
    TextNode,
} from "lexical";

export type SerializedMentionNode = Spread<
    {
        value: string;
    },
    SerializedTextNode
>;

function convertAutocorrectElement(
    domNode: HTMLElement
): DOMConversionOutput | null {
    const textContent = domNode.textContent;
    if (textContent !== null) {
        const node = $createAutocorrectNode(textContent);
        return {
            node,
        };
    }

    return null;
}

export class AutocorrectNode extends TextNode {
    __value: string;

    static getType(): string {
        return "autocorrect";
    }

    static clone(node: AutocorrectNode): AutocorrectNode {
        return new AutocorrectNode(node.__value, node.__text, node.__key);
    }
    static importJSON(serializedNode: SerializedMentionNode): AutocorrectNode {
        const node = $createAutocorrectNode(serializedNode.value);
        node.setTextContent(serializedNode.text);
        node.setFormat(serializedNode.format);
        node.setDetail(serializedNode.detail);
        node.setMode(serializedNode.mode);
        node.setStyle(serializedNode.style);
        return node;
    }

    constructor(value: string, text?: string, key?: NodeKey) {
        super(text ?? value, key);
        this.__value = value;
    }

    exportJSON(): SerializedMentionNode {
        return {
            ...super.exportJSON(),
            value: this.__value,
            type: "autocorrect",
            version: 1,
        };
    }

    createDOM(config: EditorConfig): HTMLElement {
        const dom = super.createDOM(config);
        dom.className = config.theme.incorrect;
        return dom;
    }

    exportDOM(): DOMExportOutput {
        const element = document.createElement("span");
        element.setAttribute("data-lexical-autocorrect", "true");
        element.textContent = this.__text;
        return { element };
    }

    static importDOM(): DOMConversionMap | null {
        return {
            span: (domNode: HTMLElement) => {
                if (!domNode.hasAttribute("data-lexical-autocorrect")) {
                    return null;
                }
                return {
                    conversion: convertAutocorrectElement,
                    priority: 1,
                };
            },
        };
    }

    isTextEntity(): true {
        return true;
    }

    canInsertTextBefore(): boolean {
        return false;
    }
}

export function $createAutocorrectNode(correctedVal: string): AutocorrectNode {
    const autocorrectNode = new AutocorrectNode(correctedVal);
    autocorrectNode.setMode("segmented").toggleDirectionless();
    return $applyNodeReplacement(autocorrectNode);
}

export function $isAutocorrectNode(
    node: LexicalNode | null | undefined
): node is AutocorrectNode {
    return node instanceof AutocorrectNode;
}

Basically, I want the transform to be working everytime it encounters the hardcoded value. But, it is only recognizing it if and only if the hardcoded value is the only text in the editor.

0 Answers0