Pointers on optimizing "lint" example

In the lint example (https://prosemirror.net/examples/lint/), we have the following text:

Recomputing the whole set of problems, and recreating the set of decorations, on every change isn’t very efficient, so for production code you might want to consider an approach that can incrementally update these. That’d be quite a bit more complex, but definitely doable—the transaction can give you the information you need to figure out what part of the document changed.

I’d really appreciate any pointers on how to solve for this — to me if it’s not obvious how to do this. Is it enough to just look at the transaction’s selection and update the nodes inside of the selection? To me, that sounds very naïve and unclear if it would work (I can think of a copy-paste would break this attempt).

No, you should go through the step maps and run forEach on each to get the ranges they change, and then map those ranges forward to the current document to get the actual area that was touched.

(Though that still doesn’t tell you about changed marks, which don’t actually replace pieces of the document. To be safe, including the selection in the set of changed ranges when there are any steps in the transaction might be a good idea.)

Thanks for the reply @marijn!

I realised that the example I’m working on is more close to the tooltip example (https://prosemirror.net/examples/tooltip/), in the sense that I have a plugin view. The problem is that I create a tooltip for every word in the editor, and this grows very slow for large documents. In the update(), I then iterate through the words and create a tooltip.

When I try to apply the principle you suggest with the transactions steps, I can see that the view.state.tr.steps is empty in the update function.

One alternative way I can think of is to use a decoration plugin, but that would make the positioning of the tooltip very difficult I think, but also that it’s not possible to add a data attribute for an inline decoration.

Sorry for the bump here @marijn — but can you think of any way of seeing a transactions steps in a plugin view? I can see in the tooltip example linked above that the view.state.tr.steps is empty in the update function as well.

You can’t, so probably the best way to implement something like this is to maintain the lint state in a state field, and read it in a plugin view.