/* eslint-disable no-useless-escape */ import { KEYBOARD_ALLOW_DEFAULT, KEYBOARD_PREVENT_DEFAULT, } from '@blockeditor/inline'; import type { InlineMarkdownMatch } from '../inline-manager.js'; import type { AffineTextAttributes } from './affine-inline-specs.js'; // inline markdown match rules: // covert: ***test*** + space // covert: ***t est*** + space // not convert: *** test*** + space // not convert: ***test *** + space // not convert: *** test *** + space export const affineInlineMarkdownMatches: InlineMarkdownMatch[] = [ { name: 'bolditalic', pattern: /(?:\*\*\*)([^\s\*](?:[^*]*?[^\s\*])?)(?:\*\*\*)$/g, action: ({ inlineEditor, prefixText, inlineRange, pattern, undoManager, }) => { const match = pattern.exec(prefixText); if (!match) { return KEYBOARD_ALLOW_DEFAULT; } const annotatedText = match[0]; const startIndex = inlineRange.index - annotatedText.length; inlineEditor.insertText( { index: startIndex + annotatedText.length, length: 0, }, ' ' ); inlineEditor.setInlineRange({ index: startIndex + annotatedText.length + 1, length: 0, }); undoManager.stopCapturing(); inlineEditor.formatText( { index: startIndex, length: annotatedText.length, }, { bold: true, italic: true, } ); inlineEditor.deleteText({ index: startIndex + annotatedText.length, length: 1, }); inlineEditor.deleteText({ index: startIndex + annotatedText.length - 3, length: 3, }); inlineEditor.deleteText({ index: startIndex, length: 3, }); inlineEditor.setInlineRange({ index: startIndex + annotatedText.length - 6, length: 0, }); return KEYBOARD_PREVENT_DEFAULT; }, }, { name: 'bold', pattern: /(?:\*\*)([^\s\*](?:[^*]*?[^\s\*])?)(?:\*\*)$/g, action: ({ inlineEditor, prefixText, inlineRange, pattern, undoManager, }) => { const match = pattern.exec(prefixText); if (!match) { return KEYBOARD_ALLOW_DEFAULT; } const annotatedText = match[0]; const startIndex = inlineRange.index - annotatedText.length; inlineEditor.insertText( { index: startIndex + annotatedText.length, length: 0, }, ' ' ); inlineEditor.setInlineRange({ index: startIndex + annotatedText.length + 1, length: 0, }); undoManager.stopCapturing(); inlineEditor.formatText( { index: startIndex, length: annotatedText.length, }, { bold: true, } ); inlineEditor.deleteText({ index: startIndex + annotatedText.length, length: 1, }); inlineEditor.deleteText({ index: startIndex + annotatedText.length - 2, length: 2, }); inlineEditor.deleteText({ index: startIndex, length: 2, }); inlineEditor.setInlineRange({ index: startIndex + annotatedText.length - 4, length: 0, }); return KEYBOARD_PREVENT_DEFAULT; }, }, { name: 'italic', pattern: /(?:\*)([^\s\*](?:[^*]*?[^\s\*])?)(?:\*)$/g, action: ({ inlineEditor, prefixText, inlineRange, pattern, undoManager, }) => { const match = pattern.exec(prefixText); if (!match) { return KEYBOARD_ALLOW_DEFAULT; } const annotatedText = match[0]; const startIndex = inlineRange.index - annotatedText.length; inlineEditor.insertText( { index: startIndex + annotatedText.length, length: 0, }, ' ' ); inlineEditor.setInlineRange({ index: startIndex + annotatedText.length + 1, length: 0, }); undoManager.stopCapturing(); inlineEditor.formatText( { index: startIndex, length: annotatedText.length, }, { italic: true, } ); inlineEditor.deleteText({ index: startIndex + annotatedText.length, length: 1, }); inlineEditor.deleteText({ index: startIndex + annotatedText.length - 1, length: 1, }); inlineEditor.deleteText({ index: startIndex, length: 1, }); inlineEditor.setInlineRange({ index: startIndex + annotatedText.length - 2, length: 0, }); return KEYBOARD_PREVENT_DEFAULT; }, }, { name: 'strikethrough', pattern: /(?:~~)([^\s~](?:[^~]*?[^\s~])?)(?:~~)$/g, action: ({ inlineEditor, prefixText, inlineRange, pattern, undoManager, }) => { const match = pattern.exec(prefixText); if (!match) { return KEYBOARD_ALLOW_DEFAULT; } const annotatedText = match[0]; const startIndex = inlineRange.index - annotatedText.length; inlineEditor.insertText( { index: startIndex + annotatedText.length, length: 0, }, ' ' ); inlineEditor.setInlineRange({ index: startIndex + annotatedText.length + 1, length: 0, }); undoManager.stopCapturing(); inlineEditor.formatText( { index: startIndex, length: annotatedText.length, }, { strike: true, } ); inlineEditor.deleteText({ index: startIndex + annotatedText.length, length: 1, }); inlineEditor.deleteText({ index: startIndex + annotatedText.length - 2, length: 2, }); inlineEditor.deleteText({ index: startIndex, length: 2, }); inlineEditor.setInlineRange({ index: startIndex + annotatedText.length - 4, length: 0, }); return KEYBOARD_PREVENT_DEFAULT; }, }, { name: 'underthrough', pattern: /(?:~)([^\s~](?:[^~]*?[^\s~])?)(?:~)$/g, action: ({ inlineEditor, prefixText, inlineRange, pattern, undoManager, }) => { const match = pattern.exec(prefixText); if (!match) { return KEYBOARD_ALLOW_DEFAULT; } const annotatedText = match[0]; const startIndex = inlineRange.index - annotatedText.length; inlineEditor.insertText( { index: startIndex + annotatedText.length, length: 0, }, ' ' ); inlineEditor.setInlineRange({ index: startIndex + annotatedText.length + 1, length: 0, }); undoManager.stopCapturing(); inlineEditor.formatText( { index: startIndex, length: annotatedText.length, }, { underline: true, } ); inlineEditor.deleteText({ index: startIndex + annotatedText.length, length: 1, }); inlineEditor.deleteText({ index: inlineRange.index - 1, length: 1, }); inlineEditor.deleteText({ index: startIndex, length: 1, }); inlineEditor.setInlineRange({ index: startIndex + annotatedText.length - 2, length: 0, }); return KEYBOARD_PREVENT_DEFAULT; }, }, { name: 'code', pattern: /(?:`)([^\s`](?:[^`]*?[^\s`])?)(?:`)$/g, action: ({ inlineEditor, prefixText, inlineRange, pattern, undoManager, }) => { const match = pattern.exec(prefixText); if (!match) { return KEYBOARD_ALLOW_DEFAULT; } const annotatedText = match[0]; const startIndex = inlineRange.index - annotatedText.length; if (prefixText.match(/^([* \n]+)$/g)) { return KEYBOARD_ALLOW_DEFAULT; } inlineEditor.insertText( { index: startIndex + annotatedText.length, length: 0, }, ' ' ); inlineEditor.setInlineRange({ index: startIndex + annotatedText.length + 1, length: 0, }); undoManager.stopCapturing(); inlineEditor.formatText( { index: startIndex, length: annotatedText.length, }, { code: true, } ); inlineEditor.deleteText({ index: startIndex + annotatedText.length, length: 1, }); inlineEditor.deleteText({ index: startIndex + annotatedText.length - 1, length: 1, }); inlineEditor.deleteText({ index: startIndex, length: 1, }); inlineEditor.setInlineRange({ index: startIndex + annotatedText.length - 2, length: 0, }); return KEYBOARD_PREVENT_DEFAULT; }, }, { name: 'link', pattern: /(?:\[(.+?)\])(?:\((.+?)\))$/g, action: ({ inlineEditor, prefixText, inlineRange, pattern, undoManager, }) => { const startIndex = prefixText.search(pattern); const matchedText = prefixText.match(pattern)?.[0]; const hrefText = prefixText.match(/(?:\[(.*?)\])/g)?.[0]; const hrefLink = prefixText.match(/(?:\((.*?)\))/g)?.[0]; if (startIndex === -1 || !matchedText || !hrefText || !hrefLink) { return KEYBOARD_ALLOW_DEFAULT; } const start = inlineRange.index - matchedText.length; inlineEditor.insertText( { index: inlineRange.index, length: 0, }, ' ' ); inlineEditor.setInlineRange({ index: inlineRange.index + 1, length: 0, }); undoManager.stopCapturing(); inlineEditor.formatText( { index: start, length: hrefText.length, }, { link: hrefLink.slice(1, hrefLink.length - 1), } ); inlineEditor.deleteText({ index: inlineRange.index + matchedText.length, length: 1, }); inlineEditor.deleteText({ index: inlineRange.index - hrefLink.length - 1, length: hrefLink.length + 1, }); inlineEditor.deleteText({ index: start, length: 1, }); inlineEditor.setInlineRange({ index: start + hrefText.length - 1, length: 0, }); return KEYBOARD_PREVENT_DEFAULT; }, }, ];