Merge branch 'main' of github.com:ueberdosis/tiptap-next into main
This commit is contained in:
@@ -47,10 +47,10 @@ export default {
|
||||
isActive: () => this.editor.isActive('code'),
|
||||
},
|
||||
{
|
||||
icon: 'paragraph',
|
||||
title: 'Paragraph',
|
||||
action: () => this.editor.chain().focus().setParagraph().run(),
|
||||
isActive: () => this.editor.isActive('paragraph'),
|
||||
icon: 'mark-pen-line',
|
||||
title: 'Highlight',
|
||||
action: () => this.editor.chain().focus().toggleHighlight().run(),
|
||||
isActive: () => this.editor.isActive('highlight'),
|
||||
},
|
||||
{
|
||||
icon: 'h-1',
|
||||
@@ -65,28 +65,10 @@ export default {
|
||||
isActive: () => this.editor.isActive('heading', { level: 2 }),
|
||||
},
|
||||
{
|
||||
icon: 'h-3',
|
||||
title: 'Heading 3',
|
||||
action: () => this.editor.chain().focus().toggleHeading({ level: 3 }).run(),
|
||||
isActive: () => this.editor.isActive('heading', { level: 3 }),
|
||||
},
|
||||
{
|
||||
icon: 'h-4',
|
||||
title: 'Heading 4',
|
||||
action: () => this.editor.chain().focus().toggleHeading({ level: 4 }).run(),
|
||||
isActive: () => this.editor.isActive('heading', { level: 4 }),
|
||||
},
|
||||
{
|
||||
icon: 'h-5',
|
||||
title: 'Heading 5',
|
||||
action: () => this.editor.chain().focus().toggleHeading({ level: 5 }).run(),
|
||||
isActive: () => this.editor.isActive('heading', { level: 5 }),
|
||||
},
|
||||
{
|
||||
icon: 'h-6',
|
||||
title: 'Heading 6',
|
||||
action: () => this.editor.chain().focus().toggleHeading({ level: 6 }).run(),
|
||||
isActive: () => this.editor.isActive('heading', { level: 6 }),
|
||||
icon: 'paragraph',
|
||||
title: 'Paragraph',
|
||||
action: () => this.editor.chain().focus().setParagraph().run(),
|
||||
isActive: () => this.editor.isActive('paragraph'),
|
||||
},
|
||||
{
|
||||
icon: 'list-unordered',
|
||||
@@ -100,6 +82,12 @@ export default {
|
||||
action: () => this.editor.chain().focus().toggleOrderedList().run(),
|
||||
isActive: () => this.editor.isActive('orderedList'),
|
||||
},
|
||||
{
|
||||
icon: 'list-check-2',
|
||||
title: 'Task List',
|
||||
action: () => this.editor.chain().focus().toggleTaskList().run(),
|
||||
isActive: () => this.editor.isActive('taskList'),
|
||||
},
|
||||
{
|
||||
icon: 'code-box-line',
|
||||
title: 'Code Block',
|
||||
|
||||
@@ -41,6 +41,9 @@
|
||||
import { Editor, EditorContent, defaultExtensions } from '@tiptap/vue-starter-kit'
|
||||
import Collaboration from '@tiptap/extension-collaboration'
|
||||
import CollaborationCursor from '@tiptap/extension-collaboration-cursor'
|
||||
import TaskList from '@tiptap/extension-task-list'
|
||||
import TaskItem from '@tiptap/extension-task-item'
|
||||
import Highlight from '@tiptap/extension-highlight'
|
||||
import * as Y from 'yjs'
|
||||
import { WebsocketProvider } from 'y-websocket'
|
||||
import { IndexeddbPersistence } from 'y-indexeddb'
|
||||
@@ -81,6 +84,9 @@ export default {
|
||||
this.editor = new Editor({
|
||||
extensions: [
|
||||
...defaultExtensions().filter(extension => extension.config.name !== 'history'),
|
||||
Highlight,
|
||||
TaskList,
|
||||
TaskItem,
|
||||
Collaboration.configure({
|
||||
provider,
|
||||
}),
|
||||
|
||||
@@ -205,17 +205,55 @@ Yes, it’s magic. As already mentioned, that is all based on the fantastic Y.js
|
||||
## Store the content
|
||||
Our collaborative editing backend is ready to handle advanced use cases, like authorization, persistence and scaling. Let’s go through a few common use cases here!
|
||||
|
||||
### Authentication
|
||||
With the `onConnect` hook you can write a custom Promise to check if a client is authenticated. That can be a request to an API, to a microservice, a database query, or whatever is needed, as long as it’s executing `resolve()` at some point. You can also pass contextual data to the `resolve()` method which will be accessible in other hooks.
|
||||
|
||||
```js
|
||||
import { Server } from '@hocuspocus/server'
|
||||
|
||||
const server = Server.configure({
|
||||
onConnect(data, resolve, reject) {
|
||||
const { requestHeaders } = data
|
||||
// Your code here, for example a request to an API
|
||||
|
||||
// If the user is not authorized …
|
||||
if (requestHeaders.access_token !== 'super-secret-token') {
|
||||
return reject()
|
||||
}
|
||||
|
||||
// Set contextual data
|
||||
const context = {
|
||||
user_id: 1234,
|
||||
}
|
||||
|
||||
// If the user is authorized …
|
||||
resolve(context)
|
||||
},
|
||||
})
|
||||
|
||||
server.listen()
|
||||
```
|
||||
|
||||
### Authorization
|
||||
With the `onJoinDocument` hook you can write a custom Promise to check if a client is authorized. That can be a request to an API, to a microservice, a database query, or whatever is needed, as long as it’s executing `resolve()` at some point.
|
||||
With the `onJoinDocument` hook you can check if a user is authorized to edit the current document. This works in the same way the [Authentication](#authentication) works.
|
||||
|
||||
```js
|
||||
import { Server } from '@hocuspocus/server'
|
||||
|
||||
const server = Server.configure({
|
||||
onJoinDocument(data, resolve, reject) {
|
||||
const { documentName, clientID, requestHeaders, clientsCount, document } = data
|
||||
const {
|
||||
clientsCount,
|
||||
context,
|
||||
document,
|
||||
documentName,
|
||||
requestHeaders,
|
||||
} = data
|
||||
// Your code here, for example a request to an API
|
||||
|
||||
// Access the contextual data from the onConnect hook, in this example this will print { user_id: 1234 }
|
||||
console.log(context)
|
||||
|
||||
// If the user is authorized …
|
||||
resolve()
|
||||
|
||||
@@ -258,8 +296,14 @@ const server = Server.configure({
|
||||
|
||||
// executed when the document is changed
|
||||
onChange(data) {
|
||||
const { documentName, clientID, requestHeaders, clientsCount, document } = data
|
||||
const {
|
||||
clientsCount,
|
||||
document,
|
||||
documentName,
|
||||
requestHeaders,
|
||||
} = data
|
||||
|
||||
// Your code here, for example a request to an API
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ export default function isMarkActive(
|
||||
let markRanges: MarkRange[] = []
|
||||
|
||||
state.doc.nodesBetween(from, to, (node, pos) => {
|
||||
if (node.isInline) {
|
||||
if (node.isText) {
|
||||
const relativeFrom = Math.max(from, pos)
|
||||
const relativeTo = Math.min(to, pos + node.nodeSize)
|
||||
const range = relativeTo - relativeFrom
|
||||
@@ -51,6 +51,10 @@ export default function isMarkActive(
|
||||
}
|
||||
})
|
||||
|
||||
if (selectionRange === 0) {
|
||||
return false
|
||||
}
|
||||
|
||||
const range = markRanges
|
||||
.filter(markRange => {
|
||||
if (!type) {
|
||||
|
||||
Reference in New Issue
Block a user