mirror of
https://github.com/ueberdosis/tiptap.git
synced 2024-12-01 17:39:03 +08:00
Merge branch 'main' of https://github.com/ueberdosis/tiptap-next into main
This commit is contained in:
commit
dd840703d9
@ -18,30 +18,21 @@ export default {
|
|||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
documentName: 'tiptap-collaboration-extension',
|
|
||||||
ydoc: null,
|
|
||||||
provider: null,
|
|
||||||
type: null,
|
|
||||||
editor: null,
|
editor: null,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.ydoc = new Y.Doc()
|
const ydoc = new Y.Doc()
|
||||||
this.provider = new WebrtcProvider(this.documentName, this.ydoc)
|
const provider = new WebrtcProvider('tiptap-collaboration-extension', ydoc)
|
||||||
this.type = this.ydoc.getXmlFragment('prosemirror')
|
|
||||||
|
|
||||||
this.editor = new Editor({
|
this.editor = new Editor({
|
||||||
// TODO: This is added by every new user.
|
|
||||||
// content: `
|
|
||||||
// <p>Example Text</p>
|
|
||||||
// `,
|
|
||||||
extensions: [
|
extensions: [
|
||||||
Document,
|
Document,
|
||||||
Paragraph,
|
Paragraph,
|
||||||
Text,
|
Text,
|
||||||
Collaboration.configure({
|
Collaboration.configure({
|
||||||
type: this.type,
|
provider,
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
@ -49,7 +40,6 @@ export default {
|
|||||||
|
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
this.editor.destroy()
|
this.editor.destroy()
|
||||||
this.provider.destroy()
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -19,35 +19,28 @@ export default {
|
|||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
documentName: 'tiptap-collaboration-cursor-extension',
|
|
||||||
ydoc: null,
|
|
||||||
provider: null,
|
|
||||||
type: null,
|
|
||||||
editor: null,
|
editor: null,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.ydoc = new Y.Doc()
|
const ydoc = new Y.Doc()
|
||||||
this.provider = new WebrtcProvider(this.documentName, this.ydoc)
|
const provider = new WebrtcProvider('tiptap-collaboration-cursor-extension', ydoc)
|
||||||
this.type = this.ydoc.getXmlFragment('prosemirror')
|
|
||||||
|
|
||||||
this.editor = new Editor({
|
this.editor = new Editor({
|
||||||
// TODO: This is added by every new user.
|
|
||||||
// content: `
|
|
||||||
// <p>Example Text</p>
|
|
||||||
// `,
|
|
||||||
extensions: [
|
extensions: [
|
||||||
Document,
|
Document,
|
||||||
Paragraph,
|
Paragraph,
|
||||||
Text,
|
Text,
|
||||||
Collaboration.configure({
|
Collaboration.configure({
|
||||||
type: this.type,
|
provider,
|
||||||
}),
|
}),
|
||||||
CollaborationCursor.configure({
|
CollaborationCursor.configure({
|
||||||
provider: this.provider,
|
provider,
|
||||||
|
user: {
|
||||||
name: 'Cyndi Lauper',
|
name: 'Cyndi Lauper',
|
||||||
color: '#f783ac',
|
color: '#f783ac',
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
@ -55,7 +48,6 @@ export default {
|
|||||||
|
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
this.editor.destroy()
|
this.editor.destroy()
|
||||||
this.provider.destroy()
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
## toc
|
## toc
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
The editor fires a few different events that you can hook into. There are two ways to register event listeners:
|
The editor fires a few different events that you can hook into. There are three ways to register event listeners:
|
||||||
|
|
||||||
## Option 1: Right-away
|
## Option 1: Configuration
|
||||||
You can define your event listeners on a new editor instance right-away:
|
You can define your event listeners on a new editor instance right-away:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@ -29,12 +29,12 @@ const editor = new Editor({
|
|||||||
// The editor isn’t focused anymore.
|
// The editor isn’t focused anymore.
|
||||||
},
|
},
|
||||||
onDestroy() {
|
onDestroy() {
|
||||||
// The editor is destroyed.
|
// The editor is being destroyed.
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
## Option 2: Later
|
## Option 2: Binding
|
||||||
Or you can register your event listeners on a running editor instance:
|
Or you can register your event listeners on a running editor instance:
|
||||||
|
|
||||||
### Bind event listeners
|
### Bind event listeners
|
||||||
@ -64,7 +64,7 @@ editor.on('blur', ({ event }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
editor.on('destroy', () => {
|
editor.on('destroy', () => {
|
||||||
// The editor is destroyed.
|
// The editor is being destroyed.
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -82,3 +82,34 @@ editor.on('update', onUpdate)
|
|||||||
// … and unbind.
|
// … and unbind.
|
||||||
editor.off('update', onUpdate)
|
editor.off('update', onUpdate)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Option 3: Extensions
|
||||||
|
Moving your event listeners to custom extensions (or nodes, or marks) is also possible. Here’s how that would look like:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { Extension } from '@tiptap/core'
|
||||||
|
|
||||||
|
const CustomExtension = Extension.create({
|
||||||
|
onCreate() {
|
||||||
|
// The editor is ready.
|
||||||
|
},
|
||||||
|
onUpdate() {
|
||||||
|
// The content has changed.
|
||||||
|
},
|
||||||
|
onSelection() {
|
||||||
|
// The selection has changed.
|
||||||
|
},
|
||||||
|
onTransaction({ transaction }) {
|
||||||
|
// The editor state has changed.
|
||||||
|
},
|
||||||
|
onFocus({ event }) {
|
||||||
|
// The editor is focused.
|
||||||
|
},
|
||||||
|
onBlur({ event }) {
|
||||||
|
// The editor isn’t focused anymore.
|
||||||
|
},
|
||||||
|
onDestroy() {
|
||||||
|
// The editor is being destroyed.
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
@ -4,6 +4,12 @@
|
|||||||
Using collaborative editing in production? Do the right thing and [sponsor our work](/sponsor)!
|
Using collaborative editing in production? Do the right thing and [sponsor our work](/sponsor)!
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
<!--
|
||||||
|
TODO:
|
||||||
|
- Pass auth token to the provider
|
||||||
|
-
|
||||||
|
-->
|
||||||
|
|
||||||
## toc
|
## toc
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
@ -27,7 +33,7 @@ npm install @tiptap/extension-collaboration yjs y-webrtc
|
|||||||
yarn add @tiptap/extension-collaboration yjs y-webrtc
|
yarn add @tiptap/extension-collaboration yjs y-webrtc
|
||||||
```
|
```
|
||||||
|
|
||||||
And create a new Y document, and register it with tiptap:
|
Now, create a new Y document, and register it with tiptap:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import { Editor } from '@tiptap/core'
|
import { Editor } from '@tiptap/core'
|
||||||
@ -39,15 +45,13 @@ import { WebrtcProvider } from 'y-webrtc'
|
|||||||
const ydoc = new Y.Doc()
|
const ydoc = new Y.Doc()
|
||||||
// Registered with a WebRTC provider
|
// Registered with a WebRTC provider
|
||||||
const provider = new WebrtcProvider('example-document', ydoc)
|
const provider = new WebrtcProvider('example-document', ydoc)
|
||||||
// Point to the ProseMirror schema
|
|
||||||
const type = ydoc.getXmlFragment('prosemirror')
|
|
||||||
|
|
||||||
const editor = new Editor({
|
const editor = new Editor({
|
||||||
extensions: [
|
extensions: [
|
||||||
// …
|
// …
|
||||||
// Register the document with tiptap
|
// Register the document with tiptap
|
||||||
Collaboration.configure({
|
Collaboration.configure({
|
||||||
type: type,
|
provider
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
@ -86,15 +90,13 @@ import { WebsocketProvider } from 'y-websocket'
|
|||||||
const ydoc = new Y.Doc()
|
const ydoc = new Y.Doc()
|
||||||
// Registered with a WebSocket provider
|
// Registered with a WebSocket provider
|
||||||
const provider = new WebsocketProvider('ws://127.0.0.1:1234', 'example-document', ydoc)
|
const provider = new WebsocketProvider('ws://127.0.0.1:1234', 'example-document', ydoc)
|
||||||
// Point to the ProseMirror schema
|
|
||||||
const type = ydoc.getXmlFragment('prosemirror')
|
|
||||||
|
|
||||||
const editor = new Editor({
|
const editor = new Editor({
|
||||||
extensions: [
|
extensions: [
|
||||||
// …
|
// …
|
||||||
// Register the document with tiptap
|
// Register the document with tiptap
|
||||||
Collaboration.configure({
|
Collaboration.configure({
|
||||||
type: type,
|
provider
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
@ -144,13 +146,12 @@ import { WebsocketProvider } from 'y-websocket'
|
|||||||
|
|
||||||
const ydoc = new Y.Doc()
|
const ydoc = new Y.Doc()
|
||||||
const provider = new WebsocketProvider('ws://127.0.0.1:1234', 'example-document', ydoc)
|
const provider = new WebsocketProvider('ws://127.0.0.1:1234', 'example-document', ydoc)
|
||||||
const type = ydoc.getXmlFragment('prosemirror')
|
|
||||||
|
|
||||||
const editor = new Editor({
|
const editor = new Editor({
|
||||||
extensions: [
|
extensions: [
|
||||||
// …
|
// …
|
||||||
Collaboration.configure({
|
Collaboration.configure({
|
||||||
type: type,
|
provider
|
||||||
}),
|
}),
|
||||||
// Register the collaboration cursor extension
|
// Register the collaboration cursor extension
|
||||||
CollaborationCursor.configure({
|
CollaborationCursor.configure({
|
||||||
@ -162,7 +163,7 @@ const editor = new Editor({
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
As you can see, you can pass a name and color for every user. Look at the [collaborative editing example](/exmplaes/collaborative-editing), to see a more advanced example.
|
As you can see, you can pass a name and color for every user. Look at the [collaborative editing example](/examples/collaborative-editing), to see a more advanced example.
|
||||||
|
|
||||||
### Offline support
|
### Offline support
|
||||||
Adding offline support to your collaborative editor is basically a one-liner, thanks to the fantastic [Y IndexedDB adapter](https://github.com/yjs/y-indexeddb). Install it:
|
Adding offline support to your collaborative editor is basically a one-liner, thanks to the fantastic [Y IndexedDB adapter](https://github.com/yjs/y-indexeddb). Install it:
|
||||||
@ -184,7 +185,6 @@ import * as Y from 'yjs'
|
|||||||
import { IndexeddbPersistence } from 'y-indexeddb'
|
import { IndexeddbPersistence } from 'y-indexeddb'
|
||||||
|
|
||||||
const ydoc = new Y.Doc()
|
const ydoc = new Y.Doc()
|
||||||
const type = ydoc.getXmlFragment('prosemirror')
|
|
||||||
// Store the Y document in the browser
|
// Store the Y document in the browser
|
||||||
const indexdb = new IndexeddbPersistence('example-document', ydoc)
|
const indexdb = new IndexeddbPersistence('example-document', ydoc)
|
||||||
|
|
||||||
@ -192,7 +192,7 @@ const editor = new Editor({
|
|||||||
extensions: [
|
extensions: [
|
||||||
// …
|
// …
|
||||||
Collaboration.configure({
|
Collaboration.configure({
|
||||||
type: type,
|
provider
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
@ -213,9 +213,7 @@ import { Server } from '@hocuspocus/server'
|
|||||||
|
|
||||||
const server = Server.configure({
|
const server = Server.configure({
|
||||||
onJoinDocument(data, resolve, reject) {
|
onJoinDocument(data, resolve, reject) {
|
||||||
const {
|
const { documentName, clientID, requestHeaders, clientsCount, document } = data
|
||||||
documentName, clientID, requestHeaders, clientsCount, document,
|
|
||||||
} = data
|
|
||||||
// Your code here, for example a request to an API
|
// Your code here, for example a request to an API
|
||||||
|
|
||||||
// If the user is authorized …
|
// If the user is authorized …
|
||||||
@ -260,9 +258,7 @@ const server = Server.configure({
|
|||||||
|
|
||||||
// executed when the document is changed
|
// executed when the document is changed
|
||||||
onChange(data) {
|
onChange(data) {
|
||||||
const {
|
const { documentName, clientID, requestHeaders, clientsCount, document } = data
|
||||||
documentName, clientID, requestHeaders, clientsCount, document,
|
|
||||||
} = data
|
|
||||||
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user