Offline, Peer-to-Peer, Collaborative Editing using Yjs

Yes, there is. I gave an outline here: ProseMirror + CRDT's? - #8 by dmonad . The idea is to compute the steps based on the diff of the new and the old state of the document.

From my personal experience computing “minimal diffs” is a bit expensive and unnecessary for my use-cases. I’m still a bit indifferent about this feature. And here is why:

  • y-prosemirror does not simply emit a new state object when the document changes. It preserves object identity, and so far, ProseMirror has been handling this very well. This also works well together with node-views - they won’t be rerendered. ProseMirror automatically figures out what needs to change. There is no performance loss.
  • It is necessary to replace ProseMirrors Position Mapping with a Yjs based position mapping. Yjs position mapping (relative positions) are markers on the Yjs data model and guarantee that every client will eventually end up with the same position mapping. In peer-to-peer scenarios clients receive document updates in arbitrary order and there are cases when clients would end up with different results if you would use ProseMirrors native position mapping. As you mentioned, I already use Yjs maps to compute selections. In a different project I use Yjs mappings to represent comments. Relative positions are not as nice to use as ProseMirror mappings. Eventually, I would like to provide an API that works similarly well.
  • As far as I understand, transaction steps are primarily used for calculating position mappings. As I explained, Yjs’s relative positions are better suited in p2p scenarios.

I have still on my radar that I want to make good-effort transaction steps. But again: From a p2p point of view, transactions (especially the order in which transactions are applied) are not as expressive as the Yjs document changes combined with relative positions. Still, I’m looking for ways to combine these two worlds in a way that makes sense.

I’m not denying that it will break some ProseMirror plugins (i.e. plugins that render using decorations and ProseMirror mappings). But I have tested y-prosemirror successfully in Atlaskit and TipTap. For the reasons mentioned above I also needed to replace ProseMirrors history plugin with Yjs-based history plugin (y-undo-plugin).

3 Likes