-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
/
Copy pathmarkPasteRule.ts
72 lines (59 loc) · 2.13 KB
/
markPasteRule.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import { MarkType } from '@tiptap/pm/model'
import { getMarksBetween } from '../helpers/getMarksBetween.js'
import { PasteRule, PasteRuleFinder } from '../PasteRule.js'
import { ExtendedRegExpMatchArray } from '../types.js'
import { callOrReturn } from '../utilities/callOrReturn.js'
/**
* Build an paste rule that adds a mark when the
* matched text is pasted into it.
* @see https://tiptap.dev/docs/editor/extensions/custom-extensions/extend-existing#paste-rules
*/
export function markPasteRule(config: {
find: PasteRuleFinder
type: MarkType
getAttributes?:
| Record<string, any>
| ((match: ExtendedRegExpMatchArray, event: ClipboardEvent) => Record<string, any>)
| false
| null
}) {
return new PasteRule({
find: config.find,
handler: ({
state, range, match, pasteEvent,
}) => {
const attributes = callOrReturn(config.getAttributes, undefined, match, pasteEvent)
if (attributes === false || attributes === null) {
return null
}
const { tr } = state
const captureGroup = match[match.length - 1]
const fullMatch = match[0]
let markEnd = range.to
if (captureGroup) {
const startSpaces = fullMatch.search(/\S/)
const textStart = range.from + fullMatch.indexOf(captureGroup)
const textEnd = textStart + captureGroup.length
const excludedMarks = getMarksBetween(range.from, range.to, state.doc)
.filter(item => {
// @ts-ignore
const excluded = item.mark.type.excluded as MarkType[]
return excluded.find(type => type === config.type && type !== item.mark.type)
})
.filter(item => item.to > textStart)
if (excludedMarks.length) {
return null
}
if (textEnd < range.to) {
tr.delete(textEnd, range.to)
}
if (textStart > range.from) {
tr.delete(range.from + startSpaces, textStart)
}
markEnd = range.from + startSpaces + captureGroup.length
tr.addMark(range.from + startSpaces, markEnd, config.type.create(attributes || {}))
tr.removeStoredMark(config.type)
}
},
})
}