Y-prosemirror usage

I’m looking for some clarification using y-prosemirror. I have a YDoc which contains a YMap and each YMap entry is a Prosemirror JSON doc. The user can then select a doc to view/edit which I get from the YMap and instantiate an editor.

If I call ySyncPlugin( ydoc.getXmlFragment() ) where ydoc is the top level YDoc, sync works except when I populate Prosemirror with an empty doc retrieved from a YMap item. Prosemirror then renders content from the previous YMap item that has content.

I have tried prosemirrorJSONToYDoc( schema, content ).getXmlFragment() and passing this to ySyncPlugin() however sync doesn’t work at all then.

Do I need to change the YMap items to be YDoc’s that contain the Prosemirror content and pass this YDoc when I create an editor instance?

I am using TipTap and it’s Collaboration extension however this is just a simple wrapper around y-prosemirror functions. I also posted on the TipTap discord with a bit more detail.

Thanks for any help.

Hi @clibu,

The ySyncPlugin(yXmlFragment) accepts a shared type. The TipTap people - for some reason - advertise that you should create one Yjs doc for every ProseMirror/TipTap document. However, you can easily nest documents as you suggested. Basically you do ydoc.getMap().set('docname', new Y.XmlFragment()) to populate and ySyncPlugin(ydoc.getMap().get('docname')) to bind.

There is also an example to build what you are asking for in our documentation: Shared Types - Yjs Docs (see the last section).

In the future please only post your question once. Now you might have two answers (tiptap or here is fine), but it really adds unnecessary overhead to voluntary work…

Hi @dmonad Thanks for the prompt reply. In hindsight I should have just posted here.

My YMap item is an object with various properties, one of which is the Prosemirror doc in JSON format.

From your example I’m unsure how I init my Prosmirror content. Do I somehow add this to the new Y.XmlFragment() or do I just set the Prosemirror content with my json doc or …?

I’ve read the doc’s you referred to and looked at the Quill example, however this doesn’t use Y.XmlFragment(). I’ve also scoured the forum.

@dmonad Ok, so simple in the end. Your y-prosemirror code populates the Prosemirror instance and updates the providers when editor content changes. So there is nothing I need to do.

Now that I no longer store the Prosemirror JSON I now have to refactor other code. I’ll go back to the doc’s and samples and hopefully work this out.

Specifically I need to convert the Y.XmlFragment() back to a JSON Prosemirror doc so I can parse it to extract plain text content. Any pointers welcome.

Thanks again for your help and great work with YJS.

1 Like

Hi all, I’ve followed along with all of this, thank you so much for your work @dmonad. I have the same use case but for y-prosemirror. I’m trying to reproduce a simple Quill Nested example (so I can eventually do a full file tree based on Y.Map), but it’s not working for me.

This was working for me:

// inside EditorState.create
ySyncPlugin(ydoc.getXmlFragment(myFilename))

However, when I tried to change that into a map, multi-window editing stopped working:

const ymap = ydoc.getMap('map');
const yxml = new Y.XmlFragment();
ymap.set('nested', yxml);

// Later on, this doesn't let my ydocs sync
ySyncPlugin(ymap.get(myFilename));

// Neither did this
ySyncPlugin(yxml);

Is there something I’m obviously doing wrong? I can set up a repro if helpful.

Is it a bad idea to just have all my files as top-level XmlFragment instances in the ydoc? 'Cause that’s what seems to be working right now, over putting it all in a Y.Map.

Hi all, I solved my problem after a few days. Setting and getting on a map won’t work immediately. I’m not entirely sure how it works, but you have to wait a bit for the map to instantiate/sync/??. If your ydoc is already populated with a YMap (e.g. persisted somewhere like in Liveblocks), what I did and what dmonad specified should work.