Supress selection transactions until mouse is released

I have a CodeMirror 6 editor that uses the official lang-markdown mode. This mode styles the markdown code using decorations unless the text is selected, in which case the styling is removed, similar to HyperMD or Obsidian. This behavior can cause a feedback loop: selecting text causes it to lose styling, which shifts the content and changes the selection, causing the text to be re-rendered, and the cycle repeats.
I want to avoid these visual glitches by delaying rendering until the mouse button is released, as Obsidian does. I’m unsure how to achieve this. I thought about using a transactionFilter, but there’s no transaction emitted when the mouse is released, leading me to think that buffering transactions might be necessary. Are there other options or guidance someone could provide?

Edit: Custom Statefields, which I have implemented, style the markdown with decorations, not lang-markdown. The Statefields re-compute the decorations on every update by iterating over the syntaxTree.

This is not accurate? @codemirror/lang-markdown does nothing like that.

Sorry, that was badly phrased. I hope the edit makes it clear.

Oh, I see what you mean now. A decent workaround would be to just map the existing decorations on regular transactions, and have a debounce in a view plugin that fires a special transaction causing an actual recompute of the decorations in the field, after doc/selection changes have stopped for a moment.

1 Like

Ok, after some testing and playing around I think I found a way that’s reliable and snappy. I’m ignoring any transaction.isUserEvent("select.pointer") in my Statefields and dispatch a transaction, on any mouseup event, like this

window.addEventListener("mouseup", (_) => {
  setTimeout(() => {
    client.editorView.dispatch(/* speical transaction */);
  })
});

This is pretty hacky, but it works ayyy