Replicating Replace decoration functionality from CodeMirror 6

I’m building a plugin which I’d like to replace certain strings such as {custom-tag} with a DOM element in the editor.

I’ve done this in CodeMirror 6 using the replace decoration and PluginField.atomicRanges, which perfectly covers my usecase.

In ProseMirror, I’m attempting this with a combination of:

  • A widget decoration which displays my DOM element and will have click handlers
  • An inline inline decoration which hides the {custom-tag} itself

When part of the {custom-tag} is deleted, the widget and the inline decorations are disappearing fine. But I’m struggling to find the right way to remove the rest of the tag. e.g. when the closing } is deleted, I want the rest of the {custom-tag to be removed also.

What would be the best way to achieve this? And any plans to introduce a Replace-style decoration to Prosemirror?

Thanks again!


Monitor transactions in an appendTransaction hook and make the necessary changes, I think.

Thank you @marijn!

For anyone else trying to achieve the same, as suggested I did a reconciliation in appendTransaction:

  1. I found the {custom-tag}s in the previous state and recorded their to and from positions
  2. Mapped the positions through each transaction to get their positions in the new state
  3. Used doc.textBetween with the new positions in the new state to find what the updated tag string looked like
  4. Tested it to see if it was still a valid tag. If not, I appended a transaction to get rid of it with replaceRangeWith(newFrom, newTo, '')

I don’t know if this is good practice but it seems to be working for me.