LexicalJS文本编辑器:如何允许用户按按钮添加文本

huangapple go评论57阅读模式
英文:

LexicalJS text editor : how can I allow users to add text pressing buttons

问题

我正在尝试理解 Lexical,但文档实在不太好(尽管项目看起来非常不错)。我正在尝试通过让我的用户按一些按钮或一些包含内容的 div 来自动将内容添加到编辑器中。

我不知道如何使其工作,有人能提供一些灵感吗?

以下是一些代码:

import {$getRoot, $getSelection} from 'lexical';
import {useEffect} from 'react';
import { LexicalComposer } from "@lexical/react/LexicalComposer";
import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
import { ContentEditable } from "@lexical/react/LexicalContentEditable";
import { HistoryPlugin } from "@lexical/react/LexicalHistoryPlugin";
import { AutoFocusPlugin } from "@lexical/react/LexicalAutoFocusPlugin";
import LexicalErrorBoundary from "@lexical/react/LexicalErrorBoundary";
import TreeViewPlugin from "./editor/TreeViewPlugin";
import ToolbarPlugin from "./editor/ToolbarPlugin";
import { HeadingNode, QuoteNode } from "@lexical/rich-text";
import { TableCellNode, TableNode, TableRowNode } from "@lexical/table";
import { ListItemNode, ListNode } from "@lexical/list";
import { CodeHighlightNode, CodeNode } from "@lexical/code";
import { AutoLinkNode, LinkNode } from "@lexical/link";
import { LinkPlugin } from "@lexical/react/LexicalLinkPlugin";
import { ListPlugin } from "@lexical/react/LexicalListPlugin";
import { MarkdownShortcutPlugin } from "@lexical/react/LexicalMarkdownShortcutPlugin";
import { TRANSFORMERS } from "@lexical/markdown";
import {OnChangePlugin} from '@lexical/react/LexicalOnChangePlugin';

import ListMaxIndentLevelPlugin from "./editor/ListMaxIndentLevelPlugin";
import CodeHighlightPlugin from "./editor/CodeHighlightPlugin";
import AutoLinkPlugin from "./editor/AutoLinkPlugin";
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';

const editorConfig = {
    // 编辑器主题
    // theme: ExampleTheme,
    // 在更新过程中处理错误
    onError(error) {
      throw error;
    },
    // 自定义节点在这里添加
    nodes: [
      HeadingNode,
      ListNode,
      ListItemNode,
      QuoteNode,
      CodeNode,
      CodeHighlightNode,
      TableNode,
      TableCellNode,
      TableRowNode,
      AutoLinkNode,
      LinkNode
    ]
};

function onChange(editorState) {
    editorState.read(() => {
      // 在这里读取 EditorState 的内容
      const root = $getRoot();
      const selection = $getSelection();

      // console.log(root, selection);
      console.log(root.getTextContent());
    });
}

const MyEditor = () => {

    // const [editor] = useLexicalComposerContext();

    const initialConfig = {
        namespace: 'MyEditor',
        theme: {
            paragraph: 'mb-1', // tailwind 类可以使用!
        },
        onError(error) {
            throw error;
        },
    };

    function Placeholder() {
        return <div className="editor-placeholder">输入您的文本...</div>;
    }

    const addStuff = () => {

        editor.update(() => {
            // // 获取编辑器中当前的选择
            // const selection = $getSelection();

            // // 在当前选择位置插入文本
            // if (selection) {
            //     selection.insertText("test added");
            // }

            const root = $getRoot();

            // 从 EditorState 获取选择
            const selection = $getSelection();

            // 创建新的 ParagraphNode
            const paragraphNode = $createParagraphNode();

            // 创建新的 TextNode
            const textNode = $createTextNode('Hello world');

            // 将文本节点附加到段落中
            paragraphNode.append(textNode);

            // 最后,将段落附加到根节点
            root.append(paragraphNode);
        });
    }

    return (
        <>
            <div onClick={addStuff}>点击我添加内容</div>

            <LexicalComposer initialConfig={editorConfig}>
                <div className="editor-container">
                    <ToolbarPlugin />
                    <div className="editor-inner">
                        <RichTextPlugin
                            contentEditable={<ContentEditable className="editor-input" />}
                            placeholder={<Placeholder />}
                            ErrorBoundary={LexicalErrorBoundary}
                        />
                        <HistoryPlugin />
                        <TreeViewPlugin />
                        <AutoFocusPlugin />
                        <CodeHighlightPlugin />
                        <ListPlugin />
                        <LinkPlugin />
                        <AutoLinkPlugin />
                        <ListMaxIndentLevelPlugin maxDepth={7} />
                        <MarkdownShortcutPlugin transformers={TRANSFORMERS} />
                        <OnChangePlugin onChange={onChange} />
                    </div>
                </div>
            </LexicalComposer>
        </>
    );

}

export default MyEditor;

希望这可以帮助你添加内容到 Lexical 编辑器中。

英文:

I'm trying to figure out Lexical but the docs are not great at all (despite the project looking very nice). I'm trying to add content into the editor automatically by getting my users to press some buttons, or some divs with content inside.

I have no idea how to make that work, anyone some inspiration ?

Here's some code :

    import {$getRoot, $getSelection} from &#39;lexical&#39;;
import {useEffect} from &#39;react&#39;;
import { LexicalComposer } from &quot;@lexical/react/LexicalComposer&quot;;
import { RichTextPlugin } from &quot;@lexical/react/LexicalRichTextPlugin&quot;;
import { ContentEditable } from &quot;@lexical/react/LexicalContentEditable&quot;;
import { HistoryPlugin } from &quot;@lexical/react/LexicalHistoryPlugin&quot;;
import { AutoFocusPlugin } from &quot;@lexical/react/LexicalAutoFocusPlugin&quot;;
import LexicalErrorBoundary from &quot;@lexical/react/LexicalErrorBoundary&quot;;
import TreeViewPlugin from &quot;./editor/TreeViewPlugin&quot;;
import ToolbarPlugin from &quot;./editor/ToolbarPlugin&quot;;
import { HeadingNode, QuoteNode } from &quot;@lexical/rich-text&quot;;
import { TableCellNode, TableNode, TableRowNode } from &quot;@lexical/table&quot;;
import { ListItemNode, ListNode } from &quot;@lexical/list&quot;;
import { CodeHighlightNode, CodeNode } from &quot;@lexical/code&quot;;
import { AutoLinkNode, LinkNode } from &quot;@lexical/link&quot;;
import { LinkPlugin } from &quot;@lexical/react/LexicalLinkPlugin&quot;;
import { ListPlugin } from &quot;@lexical/react/LexicalListPlugin&quot;;
import { MarkdownShortcutPlugin } from &quot;@lexical/react/LexicalMarkdownShortcutPlugin&quot;;
import { TRANSFORMERS } from &quot;@lexical/markdown&quot;;
import {OnChangePlugin} from &#39;@lexical/react/LexicalOnChangePlugin&#39;;
import ListMaxIndentLevelPlugin from &quot;./editor/ListMaxIndentLevelPlugin&quot;;
import CodeHighlightPlugin from &quot;./editor/CodeHighlightPlugin&quot;;
import AutoLinkPlugin from &quot;./editor/AutoLinkPlugin&quot;;
import { useLexicalComposerContext } from &#39;@lexical/react/LexicalComposerContext&#39;;
const editorConfig = {
// The editor theme
//theme: ExampleTheme,
// Handling of errors during update
onError(error) {
throw error;
},
// Any custom nodes go here
nodes: [
HeadingNode,
ListNode,
ListItemNode,
QuoteNode,
CodeNode,
CodeHighlightNode,
TableNode,
TableCellNode,
TableRowNode,
AutoLinkNode,
LinkNode
]
};
function onChange(editorState) {
editorState.read(() =&gt; {
// Read the contents of the EditorState here.
const root = $getRoot();
const selection = $getSelection();
// console.log(root, selection);
console.log(root.getTextContent());
});
}
const MyEditor = () =&gt; {
// const [editor] = useLexicalComposerContext();
const initialConfig = {
namespace: &#39;MyEditor&#39;,
theme: {
paragraph: &#39;mb-1&#39;, // tailwind classes work!
},
onError(error) {
throw error;
},
};
function Placeholder() {
return &lt;div className=&quot;editor-placeholder&quot;&gt;Enter your text...&lt;/div&gt;;
}
const addStuff = () =&gt; {
editor.update(() =&gt; {
// // Get the current selection in the editor
// const selection = $getSelection();
// // Insert the text at the current selection
// if (selection) {
//     selection.insertText(&quot;test added&quot;);
// }
const root = $getRoot();
// Get the selection from the EditorState
const selection = $getSelection();
// Create a new ParagraphNode
const paragraphNode = $createParagraphNode();
// Create a new TextNode
const textNode = $createTextNode(&#39;Hello world&#39;);
// Append the text node to the paragraph
paragraphNode.append(textNode);
// Finally, append the paragraph to the root
root.append(paragraphNode);
});
}
return (
&lt;&gt;
&lt;div onClick={addStuff} &gt;Click me to add stuff&lt;/div&gt;
&lt;LexicalComposer initialConfig={editorConfig}&gt;
&lt;div className=&quot;editor-container&quot;&gt;
&lt;ToolbarPlugin /&gt;
&lt;div className=&quot;editor-inner&quot;&gt;
&lt;RichTextPlugin
contentEditable={&lt;ContentEditable className=&quot;editor-input&quot; /&gt;}
placeholder={&lt;Placeholder /&gt;}
ErrorBoundary={LexicalErrorBoundary}
/&gt;
&lt;HistoryPlugin /&gt;
&lt;TreeViewPlugin /&gt;
&lt;AutoFocusPlugin /&gt;
&lt;CodeHighlightPlugin /&gt;
&lt;ListPlugin /&gt;
&lt;LinkPlugin /&gt;
&lt;AutoLinkPlugin /&gt;
&lt;ListMaxIndentLevelPlugin maxDepth={7} /&gt;
&lt;MarkdownShortcutPlugin transformers={TRANSFORMERS} /&gt;
&lt;OnChangePlugin onChange={onChange} /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/LexicalComposer&gt;
&lt;/&gt;
);
}
export default MyEditor;

答案1

得分: 1

以下是翻译好的部分:

我处理这个的方式是:

  • 注册一个自定义命令 INSERT_CUSTOM_TEXT
  • 确保导入以下内容:
    • @lexical/utils 导入 $insertNodeToNearestRoot
    • lexical 导入 $insertNodes
const INSERT_CUSTOM_TEXT: LexicalCommand<string> = createCommand();

editor.registerCommand(
  INSERT_CUSTOM_TEXT,
  () => {
          const paragraphNode = $createParagraphNode();
          const textNode = $createTextNode('Hello world');
          $insertNodes(textNode)
          paragraphNode.append(textNode);
          $insertNodeToNearestRoot(paragraphNode);
  },
  COMMAND_PRIORITY_NORMAL,
);
  • 创建一个名为 AddContentLinkPlugin 的插件
  • 使插件返回带有 onClick 附加的链接
  • 在 onClick 中调用 editor.dispatchCommand 以触发 INSERT_CUSTOM_TEXT 命令
function AddContentLinkPlugin() {
  const [editor] = useLexicalComposerContext();
  return (<div onClick={(e) => { editor.dispatchCommand(INSERT_CUSTOM_TEXT, e); }}>
            向编辑器添加文本
          </div>)
}

然后,您可以直接将此插件添加到您的 LexicalComposer 定义中。例如:

<LexicalComposer initialConfig={editorConfig}>
//...
  <AddContentLinkPlugin />
//...
</LexicalComposer>
英文:

The way I would approach this is:

  • register a custom command INSERT_CUSTOM_TEXT
  • Make sure to import
    • $insertNodeToNearestRoot from @lexical/utils
    • $insertNodes from lexical
const INSERT_CUSTOM_TEXT: LexicalCommand&lt;string&gt; = createCommand();
editor.registerCommand(
INSERT_CUSTOM_TEXT,
() =&gt; {
const paragraphNode = $createParagraphNode();
const textNode = $createTextNode(&#39;Hello world&#39;);
$insertNodes(textNode)
paragraphNode.append(textNode);
$insertNodeToNearestRoot(paragraphNode);
},
COMMAND_PRIORITY_NORMAL,
);
  • Create a Plugin called AddContentLinkPlugin
  • Have the Plugin return your link with an onClick attached
  • In the onClick call editor.dispatchCommand to fire INSERT_CUSTOM_TEXT command
function AddContentLinkPlugin() {
const [editor] = useLexicalComposerContext();
return (&lt;div onClick={(e) =&gt; { editor.dispatchCommand(INSERT_CUSTOM_TEXT, e); }}&gt;
Add text to editor
&lt;/div&gt;)
}

You can then add this plugin directly in your LexicalComposer definition. For example:

&lt;LexicalComposer initialConfig={editorConfig}&gt;
//...
&lt;AddContentLinkPlugin /&gt;
//...
&lt;/LexicalComposer&gt;

huangapple
  • 本文由 发表于 2023年6月1日 23:23:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/76383467.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定