From b0c28da3c125c7ce376605477691264216101579 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Mon, 6 May 2019 04:25:58 +0200 Subject: [PATCH 1/3] fix pasteRules for italic mark fixes #284 --- packages/tiptap-extensions/src/marks/Italic.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/tiptap-extensions/src/marks/Italic.js b/packages/tiptap-extensions/src/marks/Italic.js index e3d79e75..17eaf3c9 100644 --- a/packages/tiptap-extensions/src/marks/Italic.js +++ b/packages/tiptap-extensions/src/marks/Italic.js @@ -36,7 +36,8 @@ export default class Italic extends Mark { pasteRules({ type }) { return [ - markPasteRule(/(?:^|[^*_])(?:\*|_)([^*_]+)(?:\*|_)/g, type), + markPasteRule(/_([^_]+)_/g, type), + markPasteRule(/\*([^*]+)\*/g, type), ] } From 98cf0e425a73e6a8d94688d50403422a55fe4387 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Tue, 7 May 2019 18:50:04 +0200 Subject: [PATCH 2/3] fix markInputRules for italics mark add another layer of matching by introducing support for second match group since javascript (at least in current browsers) still lacks lookbehind in regex so now supports /nomatch(markstart(text)markend)nomatch/ and still supports the /markstart(text)markend/ syntax all `nomatch` will be kept as is so kindof simulating lookbehinds --- .../src/commands/markInputRule.js | 29 +++++++++++-------- .../tiptap-extensions/src/marks/Italic.js | 3 +- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/packages/tiptap-commands/src/commands/markInputRule.js b/packages/tiptap-commands/src/commands/markInputRule.js index 066760e6..d37d29c4 100644 --- a/packages/tiptap-commands/src/commands/markInputRule.js +++ b/packages/tiptap-commands/src/commands/markInputRule.js @@ -3,23 +3,28 @@ import { InputRule } from 'prosemirror-inputrules' export default function (regexp, markType, getAttrs) { return new InputRule(regexp, (state, match, start, end) => { const attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs - const { tr } = state - let markEnd = end + const { tr } = state + const m = match.length - 1 + let markEnd = end + let markStart = start - if (match[1]) { - const startSpaces = match[0].search(/\S/) - const textStart = start + match[0].indexOf(match[1]) - const textEnd = textStart + match[1].length - if (textEnd < end) { - tr.delete(textEnd, end) + 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 + + if (textEnd < matchEnd) { + tr.delete(textEnd, matchEnd) } - if (textStart > start) { - tr.delete(start + startSpaces, textStart) + if (textStart > matchStart) { + tr.delete(matchStart, textStart) } - markEnd = start + startSpaces + match[1].length + markStart = matchStart + markEnd = markStart + match[m].length } - tr.addMark(start, markEnd, markType.create(attrs)) + tr.addMark(markStart, markEnd, markType.create(attrs)) tr.removeStoredMark(markType) // Do not continue with mark. return tr }) diff --git a/packages/tiptap-extensions/src/marks/Italic.js b/packages/tiptap-extensions/src/marks/Italic.js index 17eaf3c9..30f68621 100644 --- a/packages/tiptap-extensions/src/marks/Italic.js +++ b/packages/tiptap-extensions/src/marks/Italic.js @@ -30,7 +30,8 @@ export default class Italic extends Mark { inputRules({ type }) { return [ - markInputRule(/(?:^|[^*_])(?:\*|_)([^*_]+)(?:\*|_)$/, type), + markInputRule(/(?:^|[^_])(_([^_]+)_)$/, type), + markInputRule(/(?:^|[^*])(\*([^*]+)\*)$/, type), ] } From 5bac4a1e332973ba270a523e838e4de43a52182a Mon Sep 17 00:00:00 2001 From: Marius Tolzmann Date: Tue, 7 May 2019 23:58:53 +0200 Subject: [PATCH 3/3] add comment clarifying why match index hast to be length -1 i verified that the actual transaction does not contain the last matching char tr.doc.textBetween(start, end+1) will miss the triggering char at the end --- packages/tiptap-commands/src/commands/markInputRule.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/tiptap-commands/src/commands/markInputRule.js b/packages/tiptap-commands/src/commands/markInputRule.js index d37d29c4..f9ad91c2 100644 --- a/packages/tiptap-commands/src/commands/markInputRule.js +++ b/packages/tiptap-commands/src/commands/markInputRule.js @@ -10,6 +10,8 @@ export default function (regexp, markType, getAttrs) { if (match[m]) { const matchStart = start + match[0].indexOf(match[m - 1]) + // matchEnd index is -1 because the last matching char is not yet member of transaction + // and actually never will be because it triggered the inputrule and vanishes ;) const matchEnd = matchStart + match[m - 1].length - 1 const textStart = matchStart + match[m - 1].lastIndexOf(match[m]) const textEnd = textStart + match[m].length