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]: Updating the node and its highlight #5155

Open
1 task done
VadimYefim opened this issue May 15, 2024 · 0 comments
Open
1 task done

[Bug]: Updating the node and its highlight #5155

VadimYefim opened this issue May 15, 2024 · 0 comments
Labels
Category: Open Source The issue or pull reuqest is related to the open source packages of Tiptap. Type: Bug The issue or pullrequest is related to a bug

Comments

@VadimYefim
Copy link

VadimYefim commented May 15, 2024

Affected Packages

"@tiptap/extension-bullet-list": "^2.3.0", "@tiptap/extension-color": "^2.3.0", "@tiptap/extension-document": "^2.3.0", "@tiptap/extension-heading": "^2.3.0", "@tiptap/extension-highlight": "^2.3.0", "@tiptap/extension-image": "^2.3.0", "@tiptap/extension-link": "^2.3.0", "@tiptap/extension-list-item": "^2.3.0", "@tiptap/extension-ordered-list": "^2.3.0", "@tiptap/extension-paragraph": "^2.3.0", "@tiptap/extension-placeholder": "^2.3.0", "@tiptap/extension-text": "^2.3.0", "@tiptap/extension-text-align": "^2.3.0", "@tiptap/extension-text-style": "^2.3.0", "@tiptap/extension-underline": "^2.3.0", "@tiptap/pm": "^2.3.0", "@tiptap/react": "^2.3.0", "@tiptap/starter-kit": "^2.3.0",

Version(s)

2.3.0

Bug Description

I have my editor as a component. And to the right of it is a list of words (This is a separate component from the editor, not a child).
And when I click on a word from the list, I want to see it highlighted. When I click on another word, it's another.

That is, every time the selectedKeyword changes, the function that makes the decorations should be triggered.

import React from 'react';
import { useSelector } from 'react-redux';

import { Extension } from '@tiptap/core';
import { Decoration, DecorationSet } from '@tiptap/pm/view';
import { EditorProvider } from '@tiptap/react';
import { debounce } from 'lodash';

import useUpdateEditorContent from './hooks/useUpdateEditorContent';

import TipTapEditorSettings from './TipTapEditorSettings';
import EditorToolbar from './toolbar/EditorToolbar';
import EditLinkContent from './toolbar/buttons/content/EditLinkContent';

import { tiptapEditorExtensions } from './extentions/tiptapEditorExtentions';

import { Plugin } from '@tiptap/pm/state';
import { selectSelectedKeyword } from '../../pages/contentOptimizer/contentPage/store/contentOptimizerContent.selectors';
import './TipTapEditor.scss';

const TipTapEditor = () => {
    const [handleUpdateEditor] = useUpdateEditorContent();

    const handleEditorChange = debounce((editorOnChangeData) => {
        const { editor } = editorOnChangeData;
        const updatedEditorData = editor?.getHTML();
        const updatedEditorText = editor?.getText();

        handleUpdateEditor(updatedEditorData, updatedEditorText);
    }, 1000);

    const selectedKeyword = useSelector(selectSelectedKeyword);

    const getHighlightedKeywords = (doc) => {
        const decorations = [];

        doc.descendants((node, position) => {
            if (!node.text) {
                return;
            }

            if (selectedKeyword) {
                const matchedKeywordKey = selectedKeyword?.regex
                    ? selectedKeyword?.regex
                    : selectedKeyword?.keyword;

                Array.from(
                    node.text.toLowerCase().matchAll(matchedKeywordKey)
                ).forEach((match) => {
                    const word = match[0];
                    const index = match.index || 0;
                    const from = position + index;
                    const to = from + word.length;
                    const decoration = Decoration.inline(from, to, {
                        class: `highlight-keyword selected-keyword`,
                    });

                    decorations.push(decoration);
                });
            }
        });

        return DecorationSet.create(doc, decorations);
    };

    const getHighlightKeywordsExtension = (getHighlightedKeywords) => {
        if (!getHighlightedKeywords) return null;

        return Extension.create({
            name: 'colorHighlighter',

            addProseMirrorPlugins() {
                return [
                    new Plugin({
                        state: {
                            init(_, { doc }) {
                                return getHighlightedKeywords(doc);
                            },
                            apply(transaction, oldState) {
                                return transaction.docChanged
                                    ? getHighlightedKeywords(transaction.doc)
                                    : oldState;
                            },
                        },
                        props: {
                            decorations(state) {
                                return this.getState(state);
                            },
                        },
                    }),
                ];
            },
        });
    };

    return (
        <EditorProvider
            slotBefore={<EditorToolbar />}
            extensions={[
                ...tiptapEditorExtensions,
                getHighlightKeywordsExtension(getHighlightedKeywords),
            ]}
            onUpdate={handleEditorChange}
        >
            <TipTapEditorSettings />
            <EditLinkContent />
        </EditorProvider>
    );
};

export default TipTapEditor;

Browser Used

Chrome

Code Example URL

https://codesandbox.io/p/sandbox/romantic-butterfly-r9v92m?file=%2Fsrc%2FApp.js%3A14%2C26&layout=%257B%2522sidebarPanel%2522%253A%2522EXPLORER%2522%252C%2522rootPanelGroup%2522%253A%257B%2522direction%2522%253A%2522horizontal%2522%252C%2522contentType%2522%253A%2522UNKNOWN%2522%252C%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522id%2522%253A%2522ROOT_LAYOUT%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522UNKNOWN%2522%252C%2522direction%2522%253A%2522vertical%2522%252C%2522id%2522%253A%2522clw7qnqr20006356nkbdmkgf3%2522%252C%2522sizes%2522%253A%255B100%252C0%255D%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522EDITOR%2522%252C%2522direction%2522%253A%2522horizontal%2522%252C%2522id%2522%253A%2522EDITOR%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522EDITOR%2522%252C%2522id%2522%253A%2522clw7qnqr20002356noy51o85r%2522%257D%255D%257D%252C%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522SHELLS%2522%252C%2522direction%2522%253A%2522horizontal%2522%252C%2522id%2522%253A%2522SHELLS%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522SHELLS%2522%252C%2522id%2522%253A%2522clw7qnqr20003356n57oxv5q1%2522%257D%255D%252C%2522sizes%2522%253A%255B100%255D%257D%255D%257D%252C%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522DEVTOOLS%2522%252C%2522direction%2522%253A%2522vertical%2522%252C%2522id%2522%253A%2522DEVTOOLS%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522DEVTOOLS%2522%252C%2522id%2522%253A%2522clw7qnqr20005356nnto9lfux%2522%257D%255D%252C%2522sizes%2522%253A%255B100%255D%257D%255D%252C%2522sizes%2522%253A%255B50%252C50%255D%257D%252C%2522tabbedPanels%2522%253A%257B%2522clw7qnqr20002356noy51o85r%2522%253A%257B%2522tabs%2522%253A%255B%257B%2522id%2522%253A%2522clw7qnqr20001356n2o757nk1%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522type%2522%253A%2522FILE%2522%252C%2522filepath%2522%253A%2522%252Fsrc%252Findex.js%2522%252C%2522state%2522%253A%2522IDLE%2522%257D%252C%257B%2522id%2522%253A%2522clw7rq4y70002356ss5y03162%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522type%2522%253A%2522FILE%2522%252C%2522initialSelections%2522%253A%255B%257B%2522startLineNumber%2522%253A14%252C%2522startColumn%2522%253A26%252C%2522endLineNumber%2522%253A14%252C%2522endColumn%2522%253A26%257D%255D%252C%2522filepath%2522%253A%2522%252Fsrc%252FApp.js%2522%252C%2522state%2522%253A%2522IDLE%2522%257D%255D%252C%2522id%2522%253A%2522clw7qnqr20002356noy51o85r%2522%252C%2522activeTabId%2522%253A%2522clw7rq4y70002356ss5y03162%2522%257D%252C%2522clw7qnqr20005356nnto9lfux%2522%253A%257B%2522tabs%2522%253A%255B%257B%2522id%2522%253A%2522clw7qnqr20004356n2zio9u1e%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522type%2522%253A%2522UNASSIGNED_PORT%2522%252C%2522port%2522%253A0%252C%2522path%2522%253A%2522%252F%2522%257D%255D%252C%2522id%2522%253A%2522clw7qnqr20005356nnto9lfux%2522%252C%2522activeTabId%2522%253A%2522clw7qnqr20004356n2zio9u1e%2522%257D%252C%2522clw7qnqr20003356n57oxv5q1%2522%253A%257B%2522tabs%2522%253A%255B%255D%252C%2522id%2522%253A%2522clw7qnqr20003356n57oxv5q1%2522%257D%257D%252C%2522showDevtools%2522%253Atrue%252C%2522showShells%2522%253Afalse%252C%2522showSidebar%2522%253Atrue%252C%2522sidebarPanelSize%2522%253A15%257D

Expected Behavior

Actual result:
<p>First Edition</p>

Expected result
<p><span class="highlight-keyword selected-keyword">First Edition</span></p>

Additional Context (Optional)

No response

Dependency Updates

  • Yes, I've updated all my dependencies.
@VadimYefim VadimYefim added Category: Open Source The issue or pull reuqest is related to the open source packages of Tiptap. Type: Bug The issue or pullrequest is related to a bug labels May 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Category: Open Source The issue or pull reuqest is related to the open source packages of Tiptap. Type: Bug The issue or pullrequest is related to a bug
Projects
Status: Triage open
Development

No branches or pull requests

1 participant