Tr.mapping.map(pos) in Plugin.apply returns the end of the document on change

I’m trying to keep track of the position for a decoration as the document changes.

apply: (tr, prevState, oldEditorState, newEditorState) => {
  const newPos = tr.mapping.map(prevState.pos)

For some reason, if another user types a single character into the document, the newPos value is always the end of the document instead of simply +1 (if the change was before it) or the same (if the change was after it).

Am I misunderstanding how position mapping works?

Thanks! Were a new sponsor FYI (gamma.app) :slight_smile: Loving Prosemirror so far!

This would happen if you replace the entire document with a new document. How does your collaborative editing work, and what kind of steps are present in the transaction (tr.steps.toJSON()) when this occurs?

@jamis0n This is probably because you are using y.js which is replacing the doc on every incoming change. Some helper methods to map decorations are possible but it’s not done yet (in y.js or tiptap).

Ah, thanks for pointing that out @philippkuehn ! I suspect you’re exactly right.

Any ideas for workarounds at the moment? This plugin is just adding decorations with a class for a particular node.

If the original pointer was position 10, we just need to know if a change was made that should update that pointer to 11 (or whatever the corresponding new location is)

OH I should also mention were storing the prosemirror node in the plugin state as well, so another approach could be to “find this same node, if it still exists”

Does the DecorationSet.map not suffice for this usecase? What’s the reason for needing to keep a state of decoration positions outside of DecorationSet (e.g. asynchronous decorations, decoration cache-ing)?