How to set marks for both block leaf nodes and inline text nodes?


We use marks for comments and we want marks both on text and on block level leaf nodes, such as figures. The following functions seems to be working to achieve that

addMark(tr, from, to, mark) {
    // add to inline nodes
    tr.addMark(from, to, mark)
    // add to leaf nodes
    tr.doc.nodesBetween(from, to, (node, pos, parent) => {
        if (!node.isLeaf) {
        let marks = node.marks
        if (!mark.isInSet(marks) && parent.type.allowsMarkType(mark.type)) {
            let newMarks = mark.addToSet(marks)
            tr.setNodeMarkup(pos, null, node.attrs, newMarks)
    if (!tr.steps.length) {
    return tr

However, there is no good way to filter for this on the server. On the server we just need a quick check whether the user is doing something they are allowed to do. Users who only have comment rights should not be modying anything else than comment marks. We can easily check for that on the server. But commenting on leaf nodes creates a replace-step type that contains all the data of the leaf node and it’s not immediately clear what exactly has changed.

So my question here: Has anyone else solved this? It seems to me that the easiest would probably be to create a custom step type for adding and removing comments on any kind of node. But I don’t know how much work that would be. Other ideas?