import type { NodeType, Schema } from 'prosemirror-model'; import { inputRules, wrappingInputRule, smartQuotes, emDash, ellipsis, InputRule, } from 'prosemirror-inputrules'; const blockQuoteRule = (nodeType: NodeType) => wrappingInputRule(/^\s*>\s$/, nodeType); const orderedListRule = (nodeType: NodeType) => wrappingInputRule( /^(\d+)\.\s$/, nodeType, (match) => ({ order: +match[1] }), (match, node) => node.childCount + node.attrs.order === +match[1], ); const bulletListRule = (nodeType: NodeType) => wrappingInputRule(/^\s*([-+*])\s$/, nodeType); const codeRule = () => { const inputRegex = /(?:^|\s)((?:`)((?:[^`]+))(?:`))$/; return new InputRule(inputRegex, (state, match, start, end) => { const { schema } = state; const tr = state.tr.insertText(`${match[2]} `, start, end); const mark = schema.marks.code.create(); return tr.addMark(start, start + match[2].length, mark); }); }; const linkRule = () => { const urlRegEx = /(?:https?:\/\/)?[\w-]+(?:\.[\w-]+)+\.?(?:\d+)?(?:\/\S*)?$/; return new InputRule(urlRegEx, (state, match, start, end) => { const { schema } = state; const tr = state.tr.insertText(match[0], start, end); const mark = schema.marks.link.create({ href: match[0], title: match[0] }); return tr.addMark(start, start + match[0].length, mark); }); }; export const buildInputRules = (schema: Schema) => { const rules = [...smartQuotes, ellipsis, emDash]; rules.push(blockQuoteRule(schema.nodes.blockquote)); rules.push(orderedListRule(schema.nodes.ordered_list)); rules.push(bulletListRule(schema.nodes.bullet_list)); rules.push(codeRule()); rules.push(linkRule()); return inputRules({ rules }); };