typescriptvue.jsprose-mirroryjsmilkdown

Why is my setup for 'Collaborative Editing' for milkdown plain working and not for Crepe (Vue 3)?


I've got the editor working with the vanilla setup and following milkdowns guide: milkdown setup with collab-plugin api: collab-plugin.

Collaborative Editing Guide Collaborative Editing.

Using: Vue 3, milkdown/vue, milkdown/crepe, milkdown/plugin-collab, yjs, y-websocket, milkdown/core, milkdown/preset-commonmark

Following setup for milkdown vanilla works:

Editor.vue (component):

<template>
  <div class="editor-wrapper">
    <div ref="editorRoot" class="milkdown" />
  </div>
</template>
<script lang="ts" setup>
import { ref, onMounted } from "vue";
import { collab, collabServiceCtx } from "@milkdown/plugin-collab";
import { Editor, rootCtx } from "@milkdown/core";
import { commonmark } from "@milkdown/preset-commonmark";
import { Doc } from "yjs";
import { WebsocketProvider } from "y-websocket";
import { nord } from "@milkdown/theme-nord";

const props = defineProps<{
  documentId: string;
}>();

const editorRoot = ref<HTMLDivElement | null>(null);

onMounted(async () => {
  if (!editorRoot.value) return;

  const doc = new Doc();
  const provider = new WebsocketProvider(
    "ws://localhost:1234",
    props.documentId,
    doc
  );

  const editor = await Editor.make()
    .config((ctx) => {
      nord(ctx);
      ctx.set(rootCtx, editorRoot.value!);
    })
    .use(commonmark)
    .use(collab)
    .create();

  editor.action((ctx) => {
    const collabService = ctx.get(collabServiceCtx);
    collabService.bindDoc(doc).setAwareness(provider.awareness).connect();
  });
});
</script>

Page.vue:

...
    <Editor :documentId="props.id" />
...

Following setup for milkdown with Crepe does not work:

The editor is displaying nicely, however the collaboration feature is not working. Any idea to what I'm missing or doing wrong?

Editor.vue (component):

<script setup lang="ts">
import { Milkdown, useEditor } from "@milkdown/vue";
import { Crepe } from "@milkdown/crepe";
import { collab, collabServiceCtx } from "@milkdown/plugin-collab";
import { Doc } from "yjs";
import { WebsocketProvider } from "y-websocket";

const props = defineProps<{
  documentId: string;
}>();

/*
const markdown = `# Milkdown Vue Crepe

> You're scared of a world where you're needed.

This is a demo for using Crepe with **Vue**.`;
*/
const doc = new Doc();
const provider = new WebsocketProvider(
  "ws://localhost:1234",
  props.documentId,
  doc
);

useEditor((root) => {
  const crepe = new Crepe({
    root,
  });

  crepe.editor.use(collab);

  crepe.editor.create().then(() => {
    crepe.editor?.action((ctx) => {
      const collabService = ctx.get(collabServiceCtx);
      collabService.bindDoc(doc).setAwareness(provider.awareness).connect();
    });
  });

  return crepe;
});
</script>

<template>
  <Milkdown />
</template>

Page.vue:


import { MilkdownProvider } from "@milkdown/vue";
...
  <MilkdownProvider>
    <Editor :documentId="props.id" />
  </MilkdownProvider>
...

Solution

  • Found the issue: Needed to check for sync first:

    useEditor((root) => {
      const crepe = new Crepe({
        root,
      });
    
      crepe.editor.config((ctx) => {
        ctx.set(defaultValueCtx, markdown);
      });
    
      crepe.editor.use(collab);
    
      crepe.editor.create().then(() => {
        crepe.editor?.action((ctx) => {
          const collabService = ctx.get(collabServiceCtx);
    
          provider.once("sync", async (isSynced: boolean) => {
            if (isSynced) {
              collabService.bindDoc(doc).setAwareness(provider.awareness).connect();
            }
          });
        });
      });
    
      return crepe;
    });