Tiptap Collaboration 扩展可以使一个文档同时多个进行实时协作,实时协作基于 Y.js 实现,本文演示的是webrtc实现协作,webrtc 并不会把数据发送到服务器,而是浏览器间直接进行通讯,如果想了解原理请自行学习一下Y.js 和 y-webrtc。也可以查阅详细的说明>>
// 直接运行安装命令可能会出错,请按照错误提示安装对应版本的库
npm install @tiptap/extension-collaboration yjs y-websocket y-prosemirror
document An initialized Y.js document.
Collaboration.configure({
document: new Y.Doc(),
})
field Name of a Y.js fragment, can be changed to sync multiple fields with one Y.js document.
Collaboration.configure({
document: new Y.Doc(),
field: 'title',
})
fragment A raw Y.js fragment, can be used instead of document and field.
Collaboration.configure({
fragment: new Y.Doc().getXmlFragment('body'),
})
undo Undo the last change.
editor.commands.undo()
redo Redo the last change.
editor.commands.redo()
Command | Windows/Linux | macOS |
---|---|---|
undo() | Control Z | Cmd Z |
redo | Shift Control Z Control Y | Shift Cmd Z Cmd Y |
Vue 例子
React 例子
<template>
<editor-content :editor="editor" />
</template>
<script>
import Collaboration from '@tiptap/extension-collaboration'
import Document from '@tiptap/extension-document'
import Paragraph from '@tiptap/extension-paragraph'
import Placeholder from '@tiptap/extension-placeholder'
import Text from '@tiptap/extension-text'
import { Editor, EditorContent } from '@tiptap/vue-3'
import { WebrtcProvider } from 'y-webrtc'
import * as Y from 'yjs'
export default {
components: {
EditorContent,
},
data() {
return {
editor: null,
provider: null,
}
},
mounted() {
const ydoc = new Y.Doc()
this.provider = new WebrtcProvider('tiptap-collaboration-extension', ydoc)
this.editor = new Editor({
extensions: [
Document,
Paragraph,
Text,
Collaboration.configure({
document: ydoc,
}),
Placeholder.configure({
placeholder: 'Write something … It’ll be shared with everyone else looking at this example.',
}),
],
})
},
beforeUnmount() {
this.editor.destroy()
this.provider.destroy()
},
}
</script>
<style>
/* Basic editor styles */
.ProseMirror {
> * + * {
margin-top: 0.75em;
}
}
/* Placeholder (at the top) */
.ProseMirror p.is-editor-empty:first-child::before {
content: attr(data-placeholder);
float: left;
color: #adb5bd;
pointer-events: none;
height: 0;
}
</style>
import Collaboration from '@tiptap/extension-collaboration'
import Document from '@tiptap/extension-document'
import Paragraph from '@tiptap/extension-paragraph'
import Placeholder from '@tiptap/extension-placeholder'
import Text from '@tiptap/extension-text'
import { EditorContent, useEditor } from '@tiptap/react'
import React from 'react'
import { WebrtcProvider } from 'y-webrtc'
import * as Y from 'yjs'
const ydoc = new Y.Doc()
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const provider = new WebrtcProvider('tiptap-collaboration-extension', ydoc)
export default () => {
const editor = useEditor({
extensions: [
Document,
Paragraph,
Text,
Collaboration.configure({
document: ydoc,
}),
Placeholder.configure({
placeholder:
'Write something … It’ll be shared with everyone else looking at this example.',
}),
],
})
return <EditorContent editor={editor} />
}