From d6bbf0d2a2bc2406407cc1f25f60a08bf572346a Mon Sep 17 00:00:00 2001 From: Jinwoo-H Date: Fri, 1 May 2026 02:09:12 -0400 Subject: [PATCH] feat: convert [[target]] to doc link node as user types in rich editor Add an input rule that fires when the user types the closing ]] of a doc link, replacing the plain text with the styled atomic node. This means users no longer need to switch to source mode and back to see doc links rendered. Co-authored-by: Orca --- .../editor/rich-markdown-doc-link.ts | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/renderer/src/components/editor/rich-markdown-doc-link.ts b/src/renderer/src/components/editor/rich-markdown-doc-link.ts index 765b6e6176b..0f064788c38 100644 --- a/src/renderer/src/components/editor/rich-markdown-doc-link.ts +++ b/src/renderer/src/components/editor/rich-markdown-doc-link.ts @@ -1,4 +1,5 @@ -import { Node, mergeAttributes } from '@tiptap/core' +import { Node, mergeAttributes, InputRule } from '@tiptap/core' +import { getMarkdownDocLinkTarget } from './markdown-doc-links' const DOC_LINK_PLACEHOLDER_PREFIX = '[[ORCA_DOC_LINK:' const DOC_LINK_PLACEHOLDER_SUFFIX = ']]' @@ -57,6 +58,25 @@ export const MarkdownDocLink = Node.create({ renderMarkdown: (node) => `[[${typeof node.attrs?.target === 'string' ? node.attrs.target : ''}]]`, + addInputRules() { + return [ + new InputRule({ + // Why: matches [[target]] at the end of input. The regex captures the + // target text between [[ and ]] so the input rule fires when the user + // types the closing ]]. + find: /\[\[([^[\]\r\n|]+)\]\]$/, + handler: ({ state, range, match }) => { + const target = getMarkdownDocLinkTarget(match[1]) + if (!target) { + return + } + const node = state.schema.nodes.markdownDocLink.create({ target }) + state.tr.replaceWith(range.from, range.to, node) + } + }) + ] + }, + parseHTML() { return [{ tag: 'span[data-doc-link-target]' }] },