Hello fellow prosemirror developers
I am attempting to build a plugin to handle simple comment functionality. Ideally, something approaching how Microsoft Word or Google docs handle comments in their text editors. But Iām having great difficulty figuring out how the schema should be constructed. Hoping someone can point me in the right direction.
What I have so far are block nodes highlighting a selection and decorations to render comment copy in a sidebar. The problem with this approach is that the entire paragraph node gets wrapped (for example). Ideally only the text selection should be highlighted for a comment with a single decoration render to the sidebar.
Visually my comment looks like this:
I thought marks would be perfect for solving the limitations. And that does allow highlighting of selected text relatively easily BUT this approach breaks my decorations. For example, adding bold on a selection of text will split my comment mark into 3 and then it becomes tricky to render a comment with a decoration in the sidebar. I donāt want to render 3 identical comment decorations. A carriage return will also create a new paragraph and split the comments mark.
Iām unsure if am approaching the problem correctly. Maybe I am doing this entirely wrong? Iāve looked through the documentation and other examples but really struggling to get this working Any advice is much appreciated.
The code for my comment node schema looks like this:
getNodes() {
const user = this.user;
return {
comment: {
isolating: true,
group: "block",
content: "block*",
toDOM() { return ["comment", 0] },
parseDOM: [
{tag: "comment",
getAttrs(dom) {
return {
copy: dom.getAttribute("data-copy"),
type: dom.getAttribute("data-type"),
user: dom.getAttribute("data-user"),
timestamp: dom.getAttribute("data-timestamp")
};
}
}
],
attrs: {
copy: {
default: '',
hasDefault: false
},
type: {
default: '',
hasDefault: true
},
user: {
default: user,
hasDefault: true
},
timestamp: {
default: undefined,
hasDefault: true
}
}
}
}
}
And my alternative mark based solution looks like this:
getMarks() {
return {
comment2: {
attrs: {
copy: {
default: ' 123 ',
hasDefault: true
},
type: {
default: 'bar',
hasDefault: true
},
user: {
default: 'Joe Bloggs',
hasDefault: true
}
},
parseDOM: [{
tag: "span.comment",
getAttrs(dom) {
return {
copy: dom.getAttribute("data-copy"),
type: dom.getAttribute("data-type"),
user: dom.getAttribute("data-user")
};
}
}],
toDOM(node) {
return [
"span",
{
"class": "comment",
"data-copy": node.attrs.copy,
"data-type": node.attrs.type,
"data-user": node.attrs.user,
"title": `Created by: ${node.attrs.user}`}
]
}
}
}
}
Many Thanks. Any advice much appreciated.