Y-prosemirror - yDocToProsemirrorJSON root node type is always 'doc'

Our prosemirror schema uses a root node type of 'root' and then a single child 'document' (helps us with our Tiptap editor when storing document level attributes).

When calling yDocToProsemirrorJSON on our document, the root node type returned is hardcoded to 'doc'. (https://github.com/yjs/y-prosemirror/blob/master/src/lib.js#L304-L307)

Is this intentional?

Or could this simply be updated to:

return {
  type: item.type,
  content: items.map(serialize)

From a prosemirror perspective, that does seem like a bug since the topNode can be something else than "doc". Unsure if item.type works though because item isn’t defined in that context.

Edit: Looks like to resolve this issue, y-prosemirror/lib would have to be modified to use Y.XmlElement instead of Y.XmlFragment since Y.XmlElement defines a nodeName (and allows for top level attrs) and Y.XmlFragment does not.

1 Like

Wait what. This is hard-coded? Most definitely a bug as nothing forces you to use ‘doc’ as the topNode in PM.

I assume @jamis0n fixed this by adding a pmDoc.type = 'root' after yDocToProsemirrorJSON. Which works but definitely not a clean solution as the type could change depending on the document.

And was it that also attrs of the topNode are not persisted by yjs? So adding the topNode type as metadata would have to be done outside the document.

You can supply a Y.XmlFragment in the TipTap binding. By default, a lot of people seem to store their content in a root-level attribute. So there was a contribution ydocToProsemirrorJSON which I accepted. Instead, it should have converted types to a prosemirror-json.

The existing function also accepts parameters to use a different root-level name: y-prosemirror/lib.js at 984175f7fd7960b1478f10370829659f001ccd3b · yjs/y-prosemirror · GitHub

There is also a PR (which I haven’t been able to review completely yet) that implements typeToProsemirrorJSON.

Could it be possible to just add a new child node to the XMLFragment which would correspond to the PM topNode? I don’t know what’s happening now internally but since XMLFragment does not seem to map to how topNodes actually are, using an additional XMLElement seems necessary.

This may not be compatible with how it works now as the old docs would need to have a new topNode inserted. But I assume you could add some clever handling of missing topNodes and keep the new API separate to avoid most developer errors.

EDIT: changing the API to yXmlFragmentToProsemirrorJSON would definitely be the right call as it has completely flown past me that by default the PM doc is persisted to "prosemirror" xmlFragment inside yDoc.