Lexical - Underline TextNode based on cursor position

842 Views Asked by At

I want to achieve a following functionality:

lexical playground example with one of the words being underlined

(notice that "are" is underlined while other words are normal). The cursor position decides what TextNode should be underlined.

I tried to use editor.registerNodeTransform to split single TextNode into multiple TextNodes (splitting by space " " character) and editor.registerCommand(SELECTION_CHANGE_COMMAND) to style it as underlined but i'm having issues with lexical infinitely updating itself.

Here is a gist:

import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
import { useEffect } from "react";
import { TextNode } from "lexical";
import {
  $getSelection,
  SELECTION_CHANGE_COMMAND,
  COMMAND_PRIORITY_NORMAL
} from "lexical";

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

  useEffect(() => {
    editor.registerNodeTransform(TextNode, (textNode) => {
      const textContent = textNode.getTextContent();

      const whiteSpaceIndices = [];
      for (let i = 0; i < textContent.length; i++) {
        if (textContent[i] === " ") {
          whiteSpaceIndices.push(i);
          whiteSpaceIndices.push(i + 1);
        }
      }

      editor.update(() => {
        textNode.splitText(...whiteSpaceIndices);
      });
    });
  }, []);

  useEffect(() => {
    return editor.registerCommand(
      SELECTION_CHANGE_COMMAND,
      () => {
        const selection = $getSelection();

        const [node] = selection.getNodes();

        // node.setFormat("underline"); // <- causes lexical to indefinitely update
      },
      COMMAND_PRIORITY_NORMAL
    );
  }, []);

  return null;
}

DEMO

what am I doing wrong?

0

There are 0 best solutions below