It’s pretty common to represent @mentions and #tags as atomic tokens with autocomplete in ProseMirror, and I want to compose these same primitives to build a higher-level structured editor that can support calling functions with arguments.
Let’s consider the simplest example of a unary function: call(Sam)
.
Suppose we have some atomic inline tokens for both the function name and the mention. Something like this:
// A typical atomic token
const func: NodeSpec = {
group: "inline",
inline: true,
atom: true,
attrs: { func: { default: "" } },
selectable: false,
draggable: false,
toDOM: (node) => {
const span = document.createElement("span")
span.setAttribute("data-func", node.attrs.func)
span.innerText = node.attrs.func
return span
},
parseDOM: [
{
tag: `span[data-func]`,
getAttrs: (dom) => {
if (dom instanceof HTMLElement) {
var value = dom.getAttribute("data-func")
return { func: value }
}
},
},
],
}
Now the question is: how do we compose all of this together into something that can display the wrapping parentheses all as one token.
My plan is to create another inline token that composes these together into another inline token.
// This is how I want to compose them together:
const pair: NodeSpec = {
content: "func (text|mention)*",
inline: true,
selectable: false,
draggable: false,
toDOM: () => {
return ["span", { class: "pair" }, 0]
},
parseDOM: [{ tag: "span.pair" }],
}
This way, the function and the arguments are grouped together. In theory, I just have to wrap the func node in a pair node and I can edit inside the arguments section by moving my cursor around:
Ideally that red cursor location would not be allowed, but we can coerce the selection to make that happen.
What do you think of this approach? Any suggestions on how to implement something like this?