Document List With Remirror + Yjs

Hello guys, I know my issue is related to Remirror. However I couldn’t found a way to achieve what I am looking for.
Basically this is what I am trying to build, but with Remirror + Yjs.

I did ask the Remirror community about a solution but no feedback until now.

I really appreciate if you guys have a look at my problem.

As you mentioned in the ticket, for an application like this it is necessary to supply a (nested) type to the editor binding. The TipTap editor binding also accepts a Yjs document and uses a default namespace to create a Y.XmlFragment. However, it also accepts a Yjs type instead of a Yjs document. I think this would be a good approach for Remirror as well.

I suggest that you open another ticket where you describe what you want to do. Then you can create a PR with the suggested changes. Happy to review it once you are done.


document.getXmlFragment(page.name)

I generally discourage this. It will be impossible for you to delete the document. Instead, you should supply the document xmlFragment = yarray.get(index).


Another approach is to have a separate Yjs document for each page.

1 Like

@dmonad Thanks for your reply, it made me think about my situation.
To be honest, things are a bit confusing for me. I am not sure whether it is a Remirror issue or a Yjs one. After investigating I noticed that YjsExtension which is implemented by Remirror team does not support multi doc, because of the below line that they create an xmlFragment with a fixed name prosemirror. It introduces two problems, first it is xmlFragment which does not let me add subdocuments to it. Second the name is fixed I can’t change it from outside.

2022-04-17_15-09

However I managed to fix this by creating a different xmlFragment each time page changes and pass it to YjsExtension. I also rewrite the YjsExtension. Basically it worked. But I faced more issues. Since I was updating ySyncPlugin when page changes, I didn’t find a way to let yUndoPluing know that ySyncPluginKey is changed as well. It was trying to capture history on previous document. In fact, I was trying to undo my work on second page, it was restoring history of first page.
I am not sure but I guess this test reveals the intention.

I also tried your solution about providing a separate Yjs document for each page. But there is also a few issues I can’t fix.

I am interested in fixing this by making PRs however I am not sure where to start. It would be great If you can elaborate on this to show me the starting point.

Thanks in advance.

To Add to my previous comment. here is how it works.

From YjsExtension:

createExternalPlugins() {
    const {
      // pageName,
      cursorBuilder,
      cursorStateField,
      getSelection,
      protectedNodes = new Set([]),
      trackedOrigins = [],
      extraAttributes,
    } = this.options;

    // instead of an xmlFragment manage to create a map that I can add more than one xmlFragment to it
    const type = this.provider.doc.getMap('prosemirror');

    const { pageName } = extraAttributes;

    // while prosemirror map is empty or pageName is not present, extenralPlugins should not initialize
    if (type.size === 0 || !pageName) return [];

    // get desired page document ( which is an xmlFragment) from top level map
    const page = type.get(pageName);

    // create UndoManager based on the current xmlFragment
    const undoManager = new UndoManager(page, {
      trackedOrigins: new Set([ySyncPluginKey, ...trackedOrigins]),
      deleteFilter: (item) => defaultDeleteFilter(item, protectedNodes),
    });

    return [ySyncPlugin(page), yUndoPlugin({ undoManager })];
  }

With the above changes ySyncPlugin works, but as I discussed yUndoPlugin does not function as expected. I guess it is because of changing xmlFragment dynamically. I guess I will face more issues regarding other collaboration extensions such as Annotation.

What is not working for you in the UndoManager?