51 lines
1.5 KiB
TypeScript
51 lines
1.5 KiB
TypeScript
import { InputRule } from 'prosemirror-inputrules'
|
|
import { MarkType } from 'prosemirror-model'
|
|
import getMarksBetween from '../helpers/getMarksBetween'
|
|
|
|
export default function (regexp: RegExp, markType: MarkType, getAttributes?: Function): InputRule {
|
|
return new InputRule(regexp, (state, match, start, end) => {
|
|
const attributes = getAttributes instanceof Function
|
|
? getAttributes(match)
|
|
: getAttributes
|
|
const { tr } = state
|
|
const captureGroup = match[match.length - 1]
|
|
const fullMatch = match[0]
|
|
let markEnd = end
|
|
|
|
if (captureGroup) {
|
|
const startSpaces = fullMatch.search(/\S/)
|
|
const textStart = start + fullMatch.indexOf(captureGroup)
|
|
const textEnd = textStart + captureGroup.length
|
|
|
|
const excludedMarks = getMarksBetween(start, end, state)
|
|
.filter(item => {
|
|
// TODO: PR to add excluded to MarkType
|
|
// @ts-ignore
|
|
const { excluded } = item.mark.type
|
|
return excluded.find((type: MarkType) => type.name === markType.name)
|
|
})
|
|
.filter(item => item.to > textStart)
|
|
|
|
if (excludedMarks.length) {
|
|
return null
|
|
}
|
|
|
|
if (textEnd < end) {
|
|
tr.delete(textEnd, end)
|
|
}
|
|
|
|
if (textStart > start) {
|
|
tr.delete(start + startSpaces, textStart)
|
|
}
|
|
|
|
markEnd = start + startSpaces + captureGroup.length
|
|
|
|
tr.addMark(start + startSpaces, markEnd, markType.create(attributes))
|
|
|
|
tr.removeStoredMark(markType)
|
|
}
|
|
|
|
return tr
|
|
})
|
|
}
|