I have a plugin which adds a node decoration to every node that contains text (in the example it’s just putting a border around each node). This works completely fine, except when the decoration is within a list element and you press delete at the begging of the list item. Doing that will throw the error: RangeError: Position -1 outside of fragment
Is there something I’m doing wrong with the decorations? Or could this be a bug? I’m using the latest version of ProseMirror. The code only decorates the paragraph tags, including the paragraph tag within the list item. It doesn’t add the decoration to the list item itself.
Example of the error being triggered:
Simplified plugin code:
function shouldDecorateNode(node) {
return node.isTextblock
}
function decorateNodes(nodes) {
return nodes.map(item => {
return Decoration.node(item.pos, item.pos + item.node.nodeSize, { class: 'test-decoration' })
})
}
function findBlockNodes(doc) {
const results = [];
doc.descendants((child, pos) => {
results.push({ node: child, pos });
})
return results.filter(child => child.node.isBlock);
}
function createPlugin() {
return new Plugin({
state: {
init: (config, state) => {
// Decorate matching nodes on init
const matching = findBlockNodes(state.doc).filter(item => shouldDecorateNode(item.node))
return DecorationSet.create(state.doc, decorateNodes(matching))
},
apply: (tr, decorationSet) => {
const { doc } = tr
// If the document hasn't changed, there's nothing to do
if (!tr.docChanged) {
return decorationSet
}
// This is where the error happens:
let mappedSet = decorationSet.map(tr.mapping, doc)
const blockNodes = findBlockNodes(doc)
const matching = blockNodes.filter(item => shouldDecorateNode(item.node))
const otherNodes = blockNodes.filter(item => !matching.includes(item))
// Remove decorations that are not within the correct nodes anymore
let decorationsOld = otherNodes.map(item => mappedSet.find(item.pos, item.pos + item.node.nodeSize)).flat()
mappedSet = mappedSet.remove(decorationsOld)
// Decorate the matching nodes
mappedSet = mappedSet.add(doc, decorateNodes(matching))
return mappedSet
},
},
props: {
decorations(state) { return this.getState(state) },
}
})
}