Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: generateHtmlFromNodes ignores selection argument #3705

Closed
SeanBrodyWP opened this issue Jan 11, 2023 · 2 comments · Fixed by #4392
Closed

Bug: generateHtmlFromNodes ignores selection argument #3705

SeanBrodyWP opened this issue Jan 11, 2023 · 2 comments · Fixed by #4392

Comments

@SeanBrodyWP
Copy link

SeanBrodyWP commented Jan 11, 2023

When I call $generateHtmlFromNodes with both an editor and a selection, it only returns the HTML for nodes/text in both the editorState's selection (what the user selected) and the selection object I pass to the call. For example, if I pass a node selection with nodes A,B,C, and the user has only selected B, then it only exports the HTML for B.

Lexical version:

Steps To Reproduce

  1. Register an update listener
    1. Get all nodes of a certain type
    2. For each node
      1. Create a node selection and add that node's key
      2. Run $generateHtmlFromNodes using that selection
  2. Create a few lines/nodes, and change the selection

When you have multiple nodes, it will always output the currently selected node (or wherever the cursor currently is)

To replicate, replace MyCustomAutoFocusPlugin.js in the example codesandbox, with this:

import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
import { $nodesOfType, $createNodeSelection, TextNode } from "lexical";
import { useEffect } from "react";
import { $generateHtmlFromNodes } from "@lexical/html";

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

  useEffect(() => {
    return editor.registerUpdateListener(() => {
      editor.update(() => {
        const nodes = $nodesOfType(TextNode);
        for (const tNode of nodes) {
          const nodeSelection = $createNodeSelection();
          const key = tNode.getKey();
          nodeSelection.add(key);
          const html = $generateHtmlFromNodes(editor, nodeSelection);
          console.log("html", key, html);
        }
      });
    });
  }, [editor]);

  return null;
}

The current behavior

It always returns the HTML for the user-selected node, not the "selection" passed into the function.
image

The expected behavior

It returns the HTML for the selection I pass into the function, and the user's selection has no effect.

@thegreatercurve
Copy link
Contributor

Node selections are exclusively for decorator nodes. Do you have this same issue if you apply a range selection to the stated array of nodes?

@SeanBrodyWP
Copy link
Author

SeanBrodyWP commented Feb 2, 2023

Thank you for your response. I was not aware that node selection were exclusivly for decorator nodes. The documentation says that NodeSelections are "selection[s] of multiple arbitrary nodes", so I assumed I could use them for any nodes. In my code, I'm using them to select a custom ElementNode subclass (and its children), but for my example code it was easier to work with text nodes.

I still have the issue if I use a range selection instead of a node selection. When I modify MyCustomAutoFocusPlugin.js to the following, $generateHtmlFromNodes returns the html for the user-selected string, not the RangeSelection I pass to it.

import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
import { $nodesOfType, $createRangeSelection, TextNode } from "lexical";
import { useEffect } from "react";
import { $generateHtmlFromNodes } from "@lexical/html";

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

  useEffect(() => {
    return editor.registerUpdateListener(() => {
      editor.update(() => {
        const nodes = $nodesOfType(TextNode);
        for (const tNode of nodes) {
         const rangeSelection = $createRangeSelection()
         const key = tNode.getKey();
         rangeSelection.setTextNodeRange(tNode, 0, tNode, tNode.__text.length)
         const html = $generateHtmlFromNodes(editor, rangeSelection);
         console.log("html", key, html);
        }
      });
    });
  }, [editor]);

  return null;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants