3

I am trying to get basics to work with lexicaljs, like hashtags, mentions etc.

What does one need to do to get hashtag to work? Identical to how it works on Twitter for example, not through a button but triggered as one types #something.

Modified basic example, but nothing happens as one types #...

Any ideas?

import * as React from "react";
import { useRef } from "react";
import debounce from 'lodash.debounce';


import ExampleTheme from "./theme";
import { LexicalComposer } from "@lexical/react/LexicalComposer";
import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
import { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin'
import { ContentEditable } from "@lexical/react/LexicalContentEditable";
import { HistoryPlugin } from "@lexical/react/LexicalHistoryPlugin";
import { AutoFocusPlugin } from "@lexical/react/LexicalAutoFocusPlugin";
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 { HashtagNode } from "@lexical/hashtag";

import LexicalErrorBoundary from "@lexical/react/LexicalErrorBoundary";
import TreeViewPlugin from "./plugins/TreeViewPlugin";
import ToolbarPlugin from "./plugins/ToolbarPlugin";
import ListMaxIndentLevelPlugin from "./plugins/ListMaxIndentLevelPlugin";
import CodeHighlightPlugin from "./plugins/CodeHighlightPlugin";
import AutoLinkPlugin from "./plugins/AutoLinkPlugin";

import "./styles.css";

function Placeholder() {
    return <div className="editor-placeholder">Enter some rich text...</div>;
}

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,
        HashtagNode,
    ]
};

export default function Editor(props) {

    function onChange(editorState) {
        if(props.onChange){
            props.onChange(editorState, JSON.stringify(editorState));
        }
    }

    const delayedOnChangeHandler = useRef(debounce((editorState) => {
        onChange(editorState)
    }, 1000)).current;

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

Update: It appears that the class (style) is not being applied to the hashtag node, despite it being correctly recognized in the tree:

 root
  └ (1) paragraph  
    ├ (9) hashtag  "#hashtag"
    ├ (10) text  " "
>   └ (14) text  "bold" { format: bold }
>                 ^^^^
<p class="editor-paragraph ltr" dir="ltr">
    <span data-lexical-text="true">#hashtag</span>
    <span data-lexical-text="true"></span>
    <strong class="editor-text-bold" data-lexical-text="true">bold</strong>
</p>

What could be the problem?

enko
  • 615
  • 6
  • 20

2 Answers2

3

Checked out your example code - the hashtag key in EditorTheme should be a top-level key, not nested under the text property.

ace
  • 180
  • 6
0

Popping another answer on here - as clickable hashtags (especially when readonly) is a common question. I've made some progress with Node Overrides, but frustratingly it's not actually doing the expected replacement. Ideas welcome... I'll update this if I figure it out. https://codesandbox.io/s/vigorous-jepsen-3i9ydu?file=/src/Editor.js

Peter Ehrlich
  • 6,969
  • 4
  • 49
  • 65
  • 1
    Don't pass the key to the constructor of your custom node. This prevent Lexical from actually adding the new node to the internal nodeMap, as it assumes it's already there. – ace May 08 '23 at 14:01