tiptap
tiptap copied to clipboard
NodeViewContent is empty by inserted with nodeInputRule
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. 💖
Have you tried giving the <node-view-content>
a min width with css?
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>
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.
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;
}
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
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