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
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" />
...
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>
...
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;
});