We’re using the y-prosemirror library to provide our prosemirror-based editor with collaborative editing functionality. Full disclosure: As we’re using remirror, we use the remirror-extension-yjs, which essentially links up the
undo-plugin into remirrors extension/plugin architecture.
This mostly works well, but one problem I had to fight with over the last couple of days was how undo is handled. The assumption of y-prosemirror seems to be that “undo” happens on the level of the yjs document, which essentially means any change done by any client becomes undo-able. From a user point-of-view this is quite odd: When I think about “undo”, I think about undo-ing my changes only. If there are other people editing the document in other places, that’s fine, but I don’t want my undo-ing touch their content. A secondary problem we found is that while the
UndoManager is able to capture the changes in “high fidelity” (to the level of “a character was added here”), the
sync-plugin will always dispatch a “replace the complete document” transaction into prosemirror’s model. This “destroys” things like annotations and other things that are attached to specific positions in the document – replacing the document means those positions are gone, too. That very similar content seems to be added afterwards doesn’t mean we can move the annotation to point into the new content.
Our conclusion at the end was therefore to try to disable any undo-support from the
y-prosemirror library, and instead rely on
prosemirror-history to provide undo on the level of the editor model. This works considerably better for us.
For a editor-level undo we do need some help from y-prosemirror though: It needs to indicate that the transactions it produces aren’t relevant for the prosemirror-history plugin. The plugin also documents how to do that, and hints that that is relevant for collaborative editing: Set the
"addToHistory" transaction meta to