tiptap icon indicating copy to clipboard operation
tiptap copied to clipboard

NodeViewContent is empty by inserted with nodeInputRule

Open aleversn opened this issue 2 years ago • 4 comments

What’s the bug you are facing?

When inserting a Vue component with <node-view-content>, the element's content is empty, even though I have defined the content to be 'paragraph+' or 'block+'. And then the cursor can't select the <node-view-content>, and I can not make any changes inside it.

Which browser was this experienced in? Are any special extensions installed?

Chrome or Edge latest version.

How can we reproduce the bug on our side?

Define a Vue component with NodeViewContent, and insert it by inputRule.

Can you provide a CodeSandbox?

No response

What did you expect to happen?

Provide a function to initialize the content in NodeViewContent or fix the issue in inserting by inputRule.

Anything to add? (optional)

No response

Did you update your dependencies?

  • [X] Yes, I’ve updated my dependencies to use the latest version of all packages.

Are you sponsoring us?

  • [ ] Yes, I’m a sponsor. 💖

aleversn avatar Jul 10 '22 04:07 aleversn

Have you tried giving the <node-view-content> a min width with css?

sereneinserenade avatar Jul 10 '22 15:07 sereneinserenade

Yes, here is the css:

.power-editor-task-item-content {
        min-width: 20px;
        min-height: 30px;
        margin-left: 5px;
        border: black thin dotted;
        white-space: nowrap;
    }

If I insert it by inputRule, you can see the cursor jump to the next line, I can only select the <node-view-content> by clicking down the mouse and typing some text,

https://user-images.githubusercontent.com/30100324/178176738-085ef204-b1e5-4bc0-b335-168af65f1a32.mp4

the content here is not wrapped by any tag, when I type Enter, the splitItem function doesn't work, the cursor just jumps into the next line.

<div data-node-view-content="" class="power-editor-task-item-content" style="white-space: pre-wrap;"></div>

If I insert by insertContent, I can define the content with a paragraph, and you can see the component works well:

https://user-images.githubusercontent.com/30100324/178184272-9ed26e19-2525-4ebe-87ca-df709624737e.mp4

<div data-node-view-content="" class="power-editor-task-item-content" style="white-space: pre-wrap;">
<p><br class="ProseMirror-trailingBreak"></p>
</div>

aleversn avatar Jul 11 '22 03:07 aleversn

Hey, I'm facing the same issue. Even their official code-block example has this issue - if you try typing ``` you can see that the cursor jumps to the next line.

amirhhashemi avatar Jul 19 '22 05:07 amirhhashemi

A solution here is to rewrite the nodeInputRule function for specific node.

import { callOrReturn, findParentNode, getAttributes, InputRule } from '@tiptap/core';
import { TextSelection } from 'prosemirror-state';

export function nodeInputWithContentRule({ find, type, getAttributes, content, overlapIgnore = [] }) {
    return new InputRule({
        find,
        handler: ({ state, range, match }) => {
            const attributes = callOrReturn(getAttributes, undefined, match) || {};
            let { tr } = state;
            const start = range.from;
            let end = range.to;

            if (overlapIgnore.length > 0) {
                if (
                    matchIgnore({
                        state,
                        overlapIgnore,
                    })
                ) {
                    return;
                }
            }

            if (match[1]) {
                const offset = match[0].lastIndexOf(match[1]);
                const matchStart = start + offset;

                if (matchStart > end) {
                    matchStart = end;
                } else {
                    end = matchStart + match[1].length;
                }
                // insert last typed character
                const lastChar = match[0][match[0].length - 1];

                tr.insertText(lastChar, start + match[0].length - 1);
                let itemNode = undefined;
                if (content != null) {
                    // insert node from input rule
                    const textNode = state.schema.nodeFromJSON(content);
                    itemNode = type.create(attributes, textNode);
                } else {
                    itemNode = type.create(attributes);
                }
                tr = tr.replaceWith(matchStart, end, itemNode);
                const selection = TextSelection.near(tr.doc.resolve(matchStart + itemNode.nodeSize - 1));
                tr.setSelection(selection);
            } else if (match[0]) {
                let itemNode = undefined;
                if (content != null) {
                    // insert node from input rule
                    const textNode = state.schema.nodeFromJSON(content);
                    itemNode = type.create(attributes, textNode);
                } else {
                    itemNode = type.create(attributes);
                }
                tr = tr.replaceWith(start, end, itemNode);
                const selection = TextSelection.near(tr.doc.resolve(start + itemNode.nodeSize - 1));
                tr.setSelection(selection);
            }
        },
    });
}

function matchIgnore({ state, overlapIgnore }) {
    let selection = state.selection;
    let path = selection.$anchor.path;
    let ignore = false;
    for (let p of path) {
        if (!p.type) continue;
        let name = p.type.name;
        if (overlapIgnore.includes(name)) {
            ignore = true;
            break;
        }
    }
    return ignore;
}

aleversn avatar Sep 20 '22 03:09 aleversn

This issue is stale because it has been open 45 days with no activity. Remove stale label or comment or this will be closed in 7 days

github-actions[bot] avatar Feb 11 '23 00:02 github-actions[bot]

This issue is stale because it has been open 45 days with no activity. Remove stale label or comment or this will be closed in 7 days

github-actions[bot] avatar May 21 '23 00:05 github-actions[bot]