The current approach will work fine as long as you don’t use too many decorations. Replacing sounds bad, but as I explained before, ProseMirror will only apply the diff to the DOM. The replacement is efficient because y-prosemirror preserves the identity of the nodes.
However, working with decorations and y-prosemirror has been one of the biggest pain points. It’s particularly hard to share decorations between collaborators. Not that it’s impossible, it just requires working directly with Yjs based relative positions that rever to the Yjs model and sync them to the ProseMirror state. I feel we need better abstractions.
The y-prosemirror binding is one of the most used editor bindings for Yjs. This was my first implementation and I think there is a lot of room for improvement. Especially the change-tracking / versioning extension is just an ugly hack that I made possible for the FOSDEM demo.
I’d like to create a rewrite this year with the feedback that I accumulated. A big focus will be to enable offline-editing scenarios. This will include:
- A cleaner codebase.
- Applying minimal diffs to ProseMirror without losing decorations.
- A better abstraction around tracking shared positions that will replace the too complex relative position API.
- An extension to track shared decorations that are synced between collaborators (e.g. for implementing comments).
- A rewrite of the snapshots API to create a nice abstraction for implementing change tracking.
- Potentially using the new move API to handle split-node scenarios better. Explanation: When splitting a paragraph into two separate paragraphs, we are removing the remainder of the first paragraph and creating a new node with the copied content from the first paragraph. Concurrent changes that are synced to the remainder of the first paragraph are still synced to the first paragraph. Yjs now supports moving of ranges of content. With the new Move-API (still WIP) we can “move” the remainder of the first paragraph to the new paragraph and retain concurrent edits. This is especially relevant for offline editing (changes that are only synced after a long time).
I talked to another editor project and we thought about creating a common abstraction around editor bindings. There are a lot of similarities between editor projects and how they represent editor state. The “editor abstraction” will handle representing editor state efficiently using Yjs’ types and provide a common abstraction for editor projects.
Looking for funding
Together with the creators of the TipTap editor @hanspagel & @philippkuehn I created an Open Collective (y-collective) for funding collaborative technologies. Basically, approved projects can charge up to $100/h for working on their projects. So far we made some really awesome things happen through the open-collective like Yrs (the Rust port of Yjs) and Hocuspocus. If we receive at least $30k in funding for the y-prosemirror rewrite, I will start development. Please direct your contributions to the y-prosemirror sub-project - which is part of the y-collective. Thank you!
If you want to fund a significant portion of the requested funds, feel free to ping me first so we can talk about expectations.
Cheers all, and thanks for all the feedback.