docs/solutions/logic-errors/2026-04-11-link-paste-autolink-must-stay-literal-inside-markdown-source-entry.md
The link plugin autolinked pasted URLs too eagerly.
That was fine for plain rich-text paste, but wrong inside markdown source entry
like [text](...), where the user is clearly building literal markdown rather
than asking for a rich link node.
https://google.com after [Example]( produced a link node in the
middle of literal markdown source.insertData implementation that was not always present.insertData(data),
which does not guarantee plain-text insertion in the bare editor test setup.Add a default paste guard for markdown link source entry and insert the raw text when a valid URL paste is intentionally kept literal.
const MARKDOWN_LINK_SOURCE_RE = /!?\[[^\]\n]*]\([^)\n]*$/;
const shouldAutoLinkPasteByDefault = (editor, { textBefore }) => {
if (editor.api.some({ match: { type: [editor.getType(KEYS.codeBlock)] } })) {
return false;
}
if (!editor.api.isCollapsed()) return true;
return !MARKDOWN_LINK_SOURCE_RE.test(textBefore);
};
Then, for valid URL candidates:
if (isValidPasteUrl) {
if (canAutoLinkPaste) {
return upsertLink(...);
}
editor.tf.insertText(text);
return;
}
This keeps default rich-text paste behavior, but preserves literal markdown source entry when the local context makes that intent obvious.
The fix separates two decisions that were previously conflated:
Markdown source entry is a real editing context, not noise around the URL.
Once the plugin sees [... ]( before the cursor, the right behavior is to keep
the URL literal. And when it does that, it must insert the plain text itself
instead of assuming another paste handler will always finish the job.
withLink.spec.tsx, not only through
URL validation tests.