docs/solutions/logic-errors/2026-04-17-markdown-link-automd-must-move-selection-after-inserted-link.md
Markdown link completion inserted the right link node but left selection in the wrong place.
The visible repro was /blocks/link-demo: finish the link with ) and the
caret stays before the link instead of after it.
LinkRules.markdown inserted the link at the matched range, but unlike bare
URL autolink it never ran the shared post-insert selection handoff.
So the transform stopped after upsertLink(...), leaving the collapsed
selection in the leading empty text node.
Make markdown link completion use the same post-insert selection move as the other autolink flows:
const inserted = upsertLink(context.editor, {
insertNodesOptions: {
at: match.range,
select: true,
},
skipValidation: true,
text: match.text,
url: match.url,
});
if (inserted) {
moveSelectionAfterLink(context.editor);
return true;
}
File:
moveSelectionAfterLink(...) already knew how to place the caret in the text
node after a completed link.
The markdown rule simply never called it. Once it does, markdown-link completion matches the expected editing flow:
bun test packages/link/src/lib/internal/inputRules.spec.tsx
bun test packages/link/src/lib/withLink.spec.tsx
bun test ./apps/www/src/__tests__/package-integration/link/link-automd.slow.tsx
bun test ./apps/www/src/__tests__/package-integration/playground/playground-rules.slow.tsx
Browser proof:
http://localhost:3001/blocks/link-demo[link](http://google.com)[0, 2], offset 0, after the inserted link