docs/plans/2026-04-11-link-automd-autoformat-plan.md
Executed.
The narrow first slice is now shipped.
Closed result:
[text](url converts on the explicit closing )AutoformatPlugin.insertTextRules@platejs/linkImplement EDIT-INTERACT-LINK-AUTOMD-001 as a real typed conversion lane for
Plate:
[text](url)The user requirement for this plan is explicit:
AutoformatPlugin lane if that is the
best architectureCurrent law already says:
Authoritative docs:
That means this plan does not need a new law family first. The law already exists. The work is implementation plus queue promotion.
Plate already proves the mechanic is possible in a package test:
But that proof is not shippable architecture:
AutoformatRule@platejs/autoformat and
@platejs/linkSo the real work is to turn that proof into a durable lane with:
Use shared AutoformatPlugin input-rule hosting with link-owned feature
semantics.
Concretely:
@platejs/autoformat
owns the dispatch lane:
insertTextRules)@platejs/link
owns the feature semantics:
[text](urlThe runtime can stay on the current hot path:
) inputThis is the fastest plausible shape for live typed conversion.
The spec already says link automd is a link interaction lane, not generic autoformat.
So:
@platejs/autoformat@platejs/linkThat keeps URL validation, link node shape, and future link-specific options from being duplicated in autoformat.
Future consumers should be able to reason about this as:
Not:
AutoformatRule hackReject.
Why:
@platejs/autoformatReject.
Why:
@platejs/autoformat to know link payload semantics@platejs/link URL validation policy@platejs/link with its own editor overrideReject.
Why:
AutoformatPlugininsertTextRules hostThe first shipped slice should support only:
[text](url)text and urlDo not inflate the first slice to cover:
If a richer markdown-link grammar is wanted later, that becomes a follow-up, not an excuse to bloat the first runtime slice.
Add a small pure helper under @platejs/link that:
[text](url shapeSuggested shape:
type LinkAutomdMatch = {
range: TRange;
text: string;
url: string;
};
matchLinkAutomdInput(editor): LinkAutomdMatch | undefined
The helper should work off the current text flow, not whole-editor markdown.
The automd path must call the existing link URL validation:
Do not create a second URL-policy branch in autoformat.
The insertion path should reuse link package helpers where possible:
If insertLink(..., { at: range }) is sufficient and covered, use it.
If range replacement semantics are too implicit, add one tiny link-owned helper
for replacing the markdown source range with the link node in one obvious call.
Use insertTextRules with:
trigger: ')'resolve returning LinkAutomdMatch | undefinedformat replacing the source range with the link nodeThis should not go through the plain rules table.
Likely files:
packages/link/src/lib/automd/ or packages/link/src/lib/utils/packages/link/src/lib/transforms/Likely files:
insertTextRules contract needs a small extensionpackages/autoformat/src/lib/rules/link/
only if we decide the rule artifact itself belongs in autoformat rather
than being provided by @platejs/linkLikely files:
Decision to encode:
Recommendation:
Add focused tests for:
[Example](https://example.com + ) converts to one link nodejavascript: or invalid heading-like # heading)Primary files:
@platejs/linkAdd package-integration coverage for the shipped kit surface:
[Example](https://example.com) in the current editor kit converts
into a link[Example](not a url) stays literalLikely path:
apps/www/src/__tests__/package-integration/link/link-automd.slow.tsxIf the rule ships in the current app kits, verify in the real editor:
/blocks/playgroundIf the rule logic fully lives in @platejs/autoformat, link semantics will
drift from @platejs/link.
Mitigation:
Trying to support nested markdown-link grammar immediately will slow the path down and create edge-case debt.
Mitigation:
Automd could fight with floating-link edit / insert behavior.
Mitigation:
Even a correct runtime can be too aggressive for the default kit.
Mitigation:
pnpm installbun test for the new link automd package specspnpm turbo build --filter=./packages/link --filter=./packages/autoformat --filter=./apps/wwwpnpm turbo typecheck --filter=./packages/link --filter=./packages/autoformat --filter=./apps/wwwpnpm lint:fixEDIT-INTERACT-LINK-AUTOMD-001 has an explicit implementation plan with a
clear permanent architecture.AutoformatPlugin as the typed-input host, not the
plain rules table.@platejs/link.If this plan is approved, the next execution move is:
insertTextRules host path