From 9f5564565508511cb772762d2af087478563d234 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Sun, 10 Mar 2024 08:59:15 -0600 Subject: [PATCH] fix: Backtick shortcut not applied correctly with composition (#6659) * fix: Backtick shortcut not applied correctly with composition * docs --- shared/editor/lib/markInputRule.ts | 39 ++++++++++++++++++------------ shared/editor/marks/Code.ts | 6 ++++- 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/shared/editor/lib/markInputRule.ts b/shared/editor/lib/markInputRule.ts index 4c67b978e..2fe14dd17 100644 --- a/shared/editor/lib/markInputRule.ts +++ b/shared/editor/lib/markInputRule.ts @@ -19,7 +19,16 @@ function getMarksBetween(start: number, end: number, state: EditorState) { return marks; } -export default function ( +/** + * A factory function for creating Prosemirror plugins that automatically apply a mark to text + * that matches a given regular expression. + * + * @param regexp The regular expression to match + * @param markType The mark type to apply + * @param getAttrs A function that returns the attributes to apply to the mark + * @returns The input rule + */ +export default function markInputRule( regexp: RegExp, markType: MarkType, getAttrs?: (match: string[]) => Record @@ -29,15 +38,14 @@ export default function ( (state: EditorState, match: string[], start: number, end: number) => { const attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs; const { tr } = state; - const m = match.length - 1; - let markEnd = end; - let markStart = start; + const captureGroup = match[match.length - 1]; + const fullMatch = match[0]; + const startSpaces = fullMatch.search(/\S/); - 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 (captureGroup) { + const matchStart = start + fullMatch.indexOf(captureGroup); + const textStart = start + fullMatch.lastIndexOf(captureGroup); + const textEnd = textStart + captureGroup.length; const excludedMarks = getMarksBetween(start, end, state) .filter((item) => item.mark.type.excludes(markType)) @@ -47,17 +55,16 @@ export default function ( return null; } - if (textEnd < matchEnd) { - tr.delete(textEnd, matchEnd); + if (textEnd < end) { + tr.delete(textEnd, end); } - if (textStart > matchStart) { - tr.delete(matchStart, textStart); + if (textStart > start) { + tr.delete(start + startSpaces, textStart); } - markStart = matchStart; - markEnd = markStart + match[m].length; + end = start + startSpaces + captureGroup.length; } - tr.addMark(markStart, markEnd, markType.create(attrs)); + tr.addMark(start + startSpaces, end, markType.create(attrs)); tr.removeStoredMark(markType); return tr; } diff --git a/shared/editor/marks/Code.ts b/shared/editor/marks/Code.ts index 7a3782d23..62706b6b9 100644 --- a/shared/editor/marks/Code.ts +++ b/shared/editor/marks/Code.ts @@ -61,8 +61,12 @@ export default class Code extends Mark { } get plugins() { + const codeCursorPlugin = codemark({ + markType: this.editor.schema.marks.code_inline, + })[0]; + return [ - ...codemark({ markType: this.editor.schema.marks.code_inline }), + codeCursorPlugin, new Plugin({ props: { // Typing a character inside of two backticks will wrap the character