Advice on interleaving documents?

I’d like to build an app where users are able to add notes to documents they don’t have edit access to. Essentially they are taking their own collaborative notes on someone else’s (potentially live edited) notes.

It seems prosemirror supports nested instances of the editor via custom view nodes. How plausible is the following strategy:

  1. UserA’s client has read access, but not write access to Doc1 so we use ProseMirror editable: false
  2. UserA’s client can, however, specify a position to insert a new block node to Doc1. This node has a custom node view that embeds a prosemirror instance (we’ll call this node NestedDocView).
  3. Since UserA doesn’t have write access these changes aren’t propagated to other clients or stored, its in UserA’s client side memory only.
  4. Create a Y.RelativePosition on Doc1 where the NestedDocView is inserted, then store an encoded version of it as a property on Doc2.
  5. A new Y.Doc (or Y.xmlFragment) Doc2 is created and and is bound to the new NestedDocView via the syncPlugin, UserA has write access.
  6. When UserA loads Doc1 later, we can rehydrate the previous state by resolving an absolute position from the encoded Y.RelativePosition from step 4 then inserting a NestedDocView in that position. Any remote updates to Doc1 won’t mess with consistent positioning of Doc2 within Doc1
  7. Similarly UserB may have access to Doc2 and Doc1 will be able to see Doc2 embedded in the correct spot within Doc1 because of that stored Y.RelativePosition.

Assumptions:

  • Remote changes to Doc1 can be applied to UserA’s modified version, and the NestedDocView will keep its relative position.
  • After changes to Doc1 between sessions, the encoded Y.RelativePosition in Doc2 will always give a valid absolute position index

Questions

  • What happens if the characters referenced by the encoded Y.RelativePosition reference are deleted? whats a sensible strategy to resolve this? just append to end of Doc1, or can we do something smarter?
  • If the owner of Doc1 (Admin) can also view Doc2, can I add the NestedDocView node to Doc1 but not propagate that specific change to other clients / server.
  • I think undo/redo for Admin would be fine, just don’t record the NestedDocView insertion on hydration?
  • Any other obvious edge cases that will need some workaround?

Doing a few tests and reading through Y.RelativePosition, discovered this only became plausible last week: Inconsistency in absolute position index across clients after an undo operation · Issue #638 · yjs/yjs · GitHub.

In conclusion it does seem possible to embed a second editor instance bound to a second document at a specific point in a document, and have that rendered consistently across clients, without storing that information in the original document. Instead we store a relative position in the second document.

Plan on making a simple demo.

1 Like