yjs / y-prosemirror

ProseMirror editor binding for Yjs
https://demos.yjs.dev/prosemirror/prosemirror.html
MIT License
345 stars 120 forks source link

Enhance Y.XMLFragment to/from JSON serialization #53

Open SamDuvall opened 3 years ago

SamDuvall commented 3 years ago

If the y-prosemirror utility functions were called from a Y.XMLElement perspective, instead of a Y.Doc with a xmlFragment key perspective, developers could re-use the utility functions to perform Y.XMLElement updates on the server. This would give developers another tool to build documents on a server before they are served to clients.

export const appendNodes = (
  yXmlFragment: Y.XmlFragment,
  jsonNodes: XmlNode[],
  schema: Schema
) => {
  // Create the initial state
  const json = yXmlFragmentToProsemirrorJSON(yXmlFragment)
  const doc = Node.fromJSON(schema, json)
  const state = EditorState.create({ doc, schema })

  // Create the new state
  const nodes = jsonNodes.map(node => Node.fromJSON(schema, node))
  const endPosition = state.doc.content.size
  const tr = state.tr.insert(endPosition, nodes)
  const newState = state.apply(tr)

  // Update the yDoc
  updateYXmlFragmentFromProsemirror(type, newState.doc)
}
SamDuvall commented 3 years ago

I've had a slight change of heart from my initial comment. I really only needed updateYFragment export from the sync-plugin.

However, I do think the signature for yDocToProsemirrorJSON isn't quite right, because I have a use case where my Y.XmlFragment is not hanging off of the Y.Doc, which I think is a valid use case. I exported another function yXmlFragmentToProsemirrorJSON which converts a Y.XmlFragment to JSON and then had yDocToProsemirrorJSON use yXmlFragmentToProsemirrorJSON to preserve backward-compatibility and not add any duplication.