Merge branch 'master' into issue-232
This commit is contained in:
78
packages/tiptap-extensions/src/extensions/Collaboration.js
Normal file
78
packages/tiptap-extensions/src/extensions/Collaboration.js
Normal file
@@ -0,0 +1,78 @@
|
||||
import { Extension } from 'tiptap'
|
||||
import { Step } from 'prosemirror-transform'
|
||||
import {
|
||||
collab,
|
||||
sendableSteps,
|
||||
getVersion,
|
||||
receiveTransaction,
|
||||
} from 'prosemirror-collab'
|
||||
|
||||
export default class Collaboration extends Extension {
|
||||
|
||||
get name() {
|
||||
return 'collaboration'
|
||||
}
|
||||
|
||||
init() {
|
||||
this.getSendableSteps = this.debounce(state => {
|
||||
const sendable = sendableSteps(state)
|
||||
|
||||
if (sendable) {
|
||||
this.options.onSendable({
|
||||
version: sendable.version,
|
||||
steps: sendable.steps.map(step => step.toJSON()),
|
||||
clientID: sendable.clientID,
|
||||
})
|
||||
}
|
||||
}, this.options.debounce)
|
||||
|
||||
this.editor.on('update', ({ state }) => {
|
||||
this.getSendableSteps(state)
|
||||
})
|
||||
}
|
||||
|
||||
get defaultOptions() {
|
||||
return {
|
||||
version: 0,
|
||||
clientID: Math.floor(Math.random() * 0xFFFFFFFF),
|
||||
debounce: 250,
|
||||
onSendable: () => {},
|
||||
update: ({ steps, version }) => {
|
||||
const { state, view, schema } = this.editor
|
||||
|
||||
if (getVersion(state) > version) {
|
||||
return
|
||||
}
|
||||
|
||||
view.dispatch(receiveTransaction(
|
||||
state,
|
||||
steps.map(item => Step.fromJSON(schema, item.step)),
|
||||
steps.map(item => item.clientID),
|
||||
))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
get plugins() {
|
||||
return [
|
||||
collab({
|
||||
version: this.options.version,
|
||||
clientID: this.options.clientID,
|
||||
}),
|
||||
]
|
||||
}
|
||||
|
||||
debounce(fn, delay) {
|
||||
let timeout
|
||||
return function (...args) {
|
||||
if (timeout) {
|
||||
clearTimeout(timeout)
|
||||
}
|
||||
timeout = setTimeout(() => {
|
||||
fn(...args)
|
||||
timeout = null
|
||||
}, delay)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,6 +23,7 @@ export { default as Link } from './marks/Link'
|
||||
export { default as Strike } from './marks/Strike'
|
||||
export { default as Underline } from './marks/Underline'
|
||||
|
||||
export { default as Collaboration } from './extensions/Collaboration'
|
||||
export { default as History } from './extensions/History'
|
||||
export { default as Placeholder } from './extensions/Placeholder'
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ export default class Link extends Mark {
|
||||
pasteRules({ type }) {
|
||||
return [
|
||||
pasteRule(
|
||||
/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_+.~#?&//=]*)/g,
|
||||
/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{2,256}\.[a-zA-Z]{2,}\b([-a-zA-Z0-9@:%_+.~#?&//=]*)/g,
|
||||
type,
|
||||
url => ({ href: url }),
|
||||
),
|
||||
@@ -59,7 +59,7 @@ export default class Link extends Mark {
|
||||
const { schema } = view.state
|
||||
const attrs = getMarkAttrs(view.state, schema.marks.link)
|
||||
|
||||
if (attrs.href) {
|
||||
if (attrs.href && event.target instanceof HTMLAnchorElement) {
|
||||
event.stopPropagation()
|
||||
window.open(attrs.href)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user