mirror of
https://github.com/ueberdosis/tiptap.git
synced 2025-01-05 09:37:48 +08:00
61 lines
1.7 KiB
TypeScript
61 lines
1.7 KiB
TypeScript
|
import { InputRule } from 'prosemirror-inputrules'
|
||
|
import { EditorState } from 'prosemirror-state'
|
||
|
import { MarkType } from 'prosemirror-model'
|
||
|
|
||
|
function getMarksBetween(start: number, end: number, state: EditorState) {
|
||
|
let marks: any[] = []
|
||
|
|
||
|
state.doc.nodesBetween(start, end, (node, pos) => {
|
||
|
marks = [...marks, ...node.marks.map(mark => ({
|
||
|
start: pos,
|
||
|
end: pos + node.nodeSize,
|
||
|
mark,
|
||
|
}))]
|
||
|
})
|
||
|
|
||
|
return marks
|
||
|
}
|
||
|
|
||
|
export default function (regexp: RegExp, markType: MarkType, getAttrs?: Function) {
|
||
|
return new InputRule(regexp, (state, match, start, end) => {
|
||
|
const attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs
|
||
|
const { tr } = state
|
||
|
const m = match.length - 1
|
||
|
let markEnd = end
|
||
|
let markStart = start
|
||
|
|
||
|
if (match[m]) {
|
||
|
const matchStart = start + match[0].indexOf(match[m - 1])
|
||
|
const matchEnd = matchStart + match[m - 1].length - 1
|
||
|
const textStart = matchStart + match[m - 1].lastIndexOf(match[m])
|
||
|
const textEnd = textStart + match[m].length
|
||
|
|
||
|
const excludedMarks = getMarksBetween(start, end, state)
|
||
|
.filter(item => {
|
||
|
const { excluded } = item.mark.type
|
||
|
return excluded.find((type: MarkType) => type.name === markType.name)
|
||
|
})
|
||
|
.filter(item => item.end > matchStart)
|
||
|
|
||
|
if (excludedMarks.length) {
|
||
|
return null
|
||
|
}
|
||
|
|
||
|
if (textEnd < matchEnd) {
|
||
|
tr.delete(textEnd, matchEnd)
|
||
|
}
|
||
|
|
||
|
if (textStart > matchStart) {
|
||
|
tr.delete(matchStart, textStart)
|
||
|
}
|
||
|
|
||
|
markStart = matchStart
|
||
|
markEnd = markStart + match[m].length
|
||
|
}
|
||
|
|
||
|
tr.addMark(markStart, markEnd, markType.create(attrs))
|
||
|
tr.removeStoredMark(markType)
|
||
|
return tr
|
||
|
})
|
||
|
}
|