I came up with this:
function markInputRule(regexp, markType, getAttrs, skipStart) {
return new InputRule(regexp, (state, match, start, end) => {
let attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs
let tr = state.tr
if (match[1]) {
let skipMatch;
let skipLen = 0;
if (skipMatch = skipStart && match[0].match(skipStart)) {
console.log(skipMatch)
skipLen = skipMatch[0].length;
start += skipLen;
}
let textStart = start + match[0].indexOf(match[1]) - skipLen
let textEnd = textStart + match[1].length
if (textEnd < end) tr.delete(textEnd, end)
if (textStart > start) tr.delete(start, textStart)
end = start + match[1].length
}
tr.addMark(start, end, markType.create(attrs))
tr.removeStoredMark(markType)
return tr
})
}
(skipStart
is a hack for emphasis because some browsers don’t yet support lookbehinds in Regex.)
And, here are the rules I used:
// strong (** AND __)
markInputRule(/(?:\*\*)([^\*]+)(?:\*\*)$/, marks.strong),
markInputRule(/(?:\s__)([^_]+)(?:__)$/, marks.strong),
// em (* and _)
markInputRule(/(?:^|[^\*])(?:\*)([^\*]+)(?:\*)$/, marks.em, {}, /^[^\*]/),
markInputRule(/(?:^|[^_])(?:_)([^_]+)(?:_)$/, marks.em, {}, /^[^_]/),
// links
markInputRule(/(?:\[([^\]]+)\])(\([^\)]+\))$/, marks.link, function(match) {
return {href: match[2]}
}),
// code (prosemirror-codemark adds this)
markInputRule(/(?:`)([^`]+)(?:`)$/, marks.code),
// strikethrough
markInputRule(/(?:~~)([^~]+)(?:~~)$/, marks.s),
// sup & sub
markInputRule(/(?:\^)([^\^]+)(?:\^)$/, marks.sup),
markInputRule(/(?:~)([^~]+)(?:~)$/, marks.sub),
// mark
markInputRule(/(?:==)([^=]+)(?:==)/, marks.mark),
Instead of the code inputrule, I let prosemirror-codemark handle that (with better cursors).