Hello all,
I’ve been working on a “CRDT-inspired” adaptation of prosemirror-collab, which you can find here, with the interesting code in prosemirror_wrapper.ts. It is just a prototype for now, but I wanted to share it and would be happy to hear any feedback.
The architecture is almost the same as prosemirror-collab, with a central server that totally orders all changes to the document. The difference is in how it rebases on top of concurrent changes: instead of mapping ProseMirror positions through the concurrent changes (OT-style), it annotates the original steps with immutable IDs (CRDT-style), then looks up where those IDs belong in the current document. The IDs (confusingly also called “Positions”) come from my list-positions library.
Relative to prosemirror-collab, this eliminates the need for clients to resubmit changes to the server: the server can append changes to the log as-is, and the IDs will still “make sense”, even if there were intervening concurrent changes.
Relative to y-prosemirror, the server’s authoritative log makes it easy to reject/modify changes on the server. Additionally, clients always apply remote changes using native ProseMirror steps, which can be useful for plugins/decorations (cf y-prosemirror issue 113).
I also found implementing this a lot easier than trying to figure out a “ProseMirror CRDT” that somehow makes all concurrent updates commute.