From 434d77a66461c5e5608ce0443f3b3542a7c49f7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Ku=CC=88hn?= Date: Thu, 2 Apr 2020 12:41:52 +0200 Subject: [PATCH] add verbal expressions --- packages/core/package.json | 3 +- packages/core/src/pasteRules/markPasteRule.ts | 15 ++-- packages/extension-bold/index.ts | 67 ++++++++++++++++-- packages/extension-italic/index.ts | 69 ++++++++++++++++--- yarn.lock | 5 ++ 5 files changed, 138 insertions(+), 21 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index 66a9f78d..1a685ee7 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -24,6 +24,7 @@ "prosemirror-state": "^1.3.3", "prosemirror-tables": "^1.0.0", "prosemirror-utils": "^0.9.6", - "prosemirror-view": "^1.14.6" + "prosemirror-view": "^1.14.6", + "verbal-expressions": "^1.0.2" } } diff --git a/packages/core/src/pasteRules/markPasteRule.ts b/packages/core/src/pasteRules/markPasteRule.ts index 61a63726..0fe2fd49 100644 --- a/packages/core/src/pasteRules/markPasteRule.ts +++ b/packages/core/src/pasteRules/markPasteRule.ts @@ -14,16 +14,19 @@ export default function (regexp: RegExp, type: MarkType, getAttrs?: Function) { // eslint-disable-next-line while ((match = regexp.exec(text)) !== null) { + const m = match.length - 1 + if (parent.type.allowsMarkType(type) && match[1]) { const start = match.index - const end = start + match[0].length - const textStart = start + match[0].indexOf(match[1]) - const textEnd = textStart + match[1].length + const matchStart = start + match[0].indexOf(match[m - 1]) + const matchEnd = matchStart + match[m - 1].length // TODO: why is there no -1 + const textStart = matchStart + match[m - 1].lastIndexOf(match[m]) + const textEnd = textStart + match[m].length const attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs // adding text before markdown to nodes - if (start > 0) { - nodes.push(child.cut(pos, start)) + if (matchStart > 0) { + nodes.push(child.cut(pos, matchStart)) } // adding the markdown part to nodes @@ -32,7 +35,7 @@ export default function (regexp: RegExp, type: MarkType, getAttrs?: Function) { // @ts-ignore .mark(type.create(attrs).addToSet(child.marks))) - pos = end + pos = matchEnd } } diff --git a/packages/extension-bold/index.ts b/packages/extension-bold/index.ts index a49fec37..d66b7479 100644 --- a/packages/extension-bold/index.ts +++ b/packages/extension-bold/index.ts @@ -1,6 +1,7 @@ import { Mark, markInputRule, markPasteRule } from '@tiptap/core' import { toggleMark } from 'prosemirror-commands' import { MarkSpec } from 'prosemirror-model' +import VerEx from 'verbal-expressions' declare module '@tiptap/core/src/Editor' { interface Editor { @@ -45,15 +46,69 @@ export default class Bold extends Mark { } inputRules() { - return [ - markInputRule(/(?:\*\*|__)([^*_]+)(?:\*\*|__)$/, this.schemaType), - ] + return ['**', '__'].map(character => ([ + // match start of line + markInputRule( + VerEx() + .startOfLine() + .beginCapture() + .find(character) + .beginCapture() + .somethingBut(character) + .endCapture() + .find(character) + .endCapture() + .endOfLine(), + this.schemaType, + ), + // match before whitespace + markInputRule( + VerEx() + .whitespace() + .beginCapture() + .find(character) + .beginCapture() + .somethingBut(character) + .endCapture() + .find(character) + .endCapture() + .endOfLine(), + this.schemaType, + ), + ])) + .flat(1) } pasteRules() { - return [ - markPasteRule(/(?:\*\*|__)([^*_]+)(?:\*\*|__)/g, this.schemaType), - ] + return ['**', '__'].map(character => ([ + // match start of line + markPasteRule( + VerEx() + .startOfLine() + .beginCapture() + .find(character) + .beginCapture() + .somethingBut(character) + .endCapture() + .find(character) + .endCapture(), + this.schemaType, + ), + // match before whitespace + markPasteRule( + VerEx() + .whitespace() + .beginCapture() + .find(character) + .beginCapture() + .somethingBut(character) + .endCapture() + .find(character) + .endCapture(), + this.schemaType, + ), + ])) + .flat(1) } } \ No newline at end of file diff --git a/packages/extension-italic/index.ts b/packages/extension-italic/index.ts index 14a905d7..2e76bb28 100644 --- a/packages/extension-italic/index.ts +++ b/packages/extension-italic/index.ts @@ -1,6 +1,7 @@ import { Mark, markInputRule, markPasteRule } from '@tiptap/core' import { toggleMark } from 'prosemirror-commands' import { MarkSpec } from 'prosemirror-model' +import VerEx from 'verbal-expressions' declare module '@tiptap/core/src/Editor' { interface Editor { @@ -37,17 +38,69 @@ export default class Italic extends Mark { } inputRules() { - return [ - markInputRule(/(?:^|[^_])(_([^_]+)_)$/, this.schemaType), - // markInputRule(/(?:^|[^*])(\*([^*]+)\*)$/, this.schemaType), - ] + return ['*', '_'].map(character => ([ + // match start of line + markInputRule( + VerEx() + .startOfLine() + .beginCapture() + .find(character) + .beginCapture() + .somethingBut(character) + .endCapture() + .find(character) + .endCapture() + .endOfLine(), + this.schemaType, + ), + // match before whitespace + markInputRule( + VerEx() + .whitespace() + .beginCapture() + .find(character) + .beginCapture() + .somethingBut(character) + .endCapture() + .find(character) + .endCapture() + .endOfLine(), + this.schemaType, + ), + ])) + .flat(1) } pasteRules() { - return [ - markPasteRule(/_([^_]+)_/g, this.schemaType), - // markPasteRule(/\*([^*]+)\*/g, this.schemaType), - ] + return ['*', '_'].map(character => ([ + // match start of line + markPasteRule( + VerEx() + .startOfLine() + .beginCapture() + .find(character) + .beginCapture() + .somethingBut(character) + .endCapture() + .find(character) + .endCapture(), + this.schemaType, + ), + // match before whitespace + markPasteRule( + VerEx() + .whitespace() + .beginCapture() + .find(character) + .beginCapture() + .somethingBut(character) + .endCapture() + .find(character) + .endCapture(), + this.schemaType, + ), + ])) + .flat(1) } } \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index adbb67ad..06ab1c8f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14282,6 +14282,11 @@ vendors@^1.0.0: resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.4.tgz#e2b800a53e7a29b93506c3cf41100d16c4c4ad8e" integrity sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w== +verbal-expressions@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/verbal-expressions/-/verbal-expressions-1.0.2.tgz#1f2d28fdcf7169be270777ff5fadcdb2b3b905c5" + integrity sha512-LV8eG4ckcg1iIhGjOF+j1jb0b58m1DgGywce+2U8kbRrB5wZnGe4XCyUyOujZR9D/+rJGXTmxnL30o3zAgmC4w== + verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"