docs/plans/2026-04-10-math-delimiter-trigger-implementation-plan.md
Executed for the default rich-mode slice.
Closed result:
$...$$$ + Enter block promotionWhy the deferred branch stayed deferred:
$ and $$ already share one symbol family in the rich editor$ selection-wrap as a default rich-mode branch increases collision
and ambiguity pressure instead of reducing itImplement the deferred math delimiter trigger lane for Plate's markdown-first profile:
$ selection-wrap over an existing selection$...$ rich-mode conversion on explicit closing delimiter$$ block trigger / block detection$$ plus Enter promotionPlate already supports math in three separate ways:
remark-mathinsertInlineEquation and
insertEquationWhat it does not support is markdown-sensitive typing triggers for $ and
$$.
That gap now has real law and protocol rows, so leaving it as “later” is no longer honest. The implementation work is also cross-cutting enough that it needs one full plan instead of another roadmap placeholder.
EDIT-PROFILE-MATH-TRIGGER-001EDIT-PROFILE-MATH-TRIGGER-002EDIT-PROFILE-MATH-TRIGGER-003EDIT-PROFILE-MATH-TRIGGER-001EDIT-PROFILE-MATH-TRIGGER-002EDIT-PROFILE-MATH-TRIGGER-003remark-math:
$$ plus Enter ownership decision explicit instead of burying it
in vague future work.$ selection-wrap typing behavior.@platejs/autoformat input rulesReason:
insertText and insertBreak, not a math-only pluginMathKit compose with the
existing autoformat engine instead of carrying another editor overrideRecommended file additions:
packages/autoformat/src/lib/rules/math/ for pure
trigger parsing / matching logic$
$
$...$ run on the closing delimiter in default rich
mode$$ block trigger
$$ trigger and $$ plus Enter promotion as
separate branches even if they share helpersReason:
deviation, not a previously shipped Plate
contract$Default posture:
$$ plus Enter as a second implementation slice inside the same laneReason:
insertBreak / block-owner behavior, not just insertText$ surfacesThat means:
$...$ rich-mode conversionAll slices stay inside the same lane and plan. Slice C is optional until the selection-wrap branch is explicitly approved.
Add tests that prove the current absence of trigger behavior and the current fallback insertion semantics before changing runtime.
Primary files:
packages/math/src/lib/apps/www/src/__tests__/package-integration/math/Create pure helpers for:
$$...$$$Recommended new files:
packages/math/src/lib/triggers/shouldWrapMathSelection.tspackages/math/src/lib/triggers/shouldPairInlineMath.tspackages/math/src/lib/triggers/shouldPromoteBlockMath.tspackages/math/src/lib/triggers/index.tsAdd one shared autoformat-owned input-rule path that handles both insertText
and insertBreak for the math-trigger surface.
Primary files:
packages/autoformat/src/lib/AutoformatPlugin.tspackages/autoformat/src/lib/types.tspackages/autoformat/src/lib/rules/math/autoformatMathInput.tspackages/autoformat/src/lib/rules/math/index.tsResponsibilities:
$ and $$ trigger handlingWire the shared trigger plugin into the app kits that should expose the markdown-first math-trigger surface.
Primary files:
Decision to encode:
Update math docs so typing triggers are described as a real optional surface, separate from explicit insert buttons and parser support.
Primary files:
Add:
packages/autoformat/src/lib/rules/math/autoformatMathInput.spec.tsxScenarios:
$ creates one inline equation node with the selected
text as texExpression$ leaves text literal when the trigger surface is
disabled$...$ converts on the closing delimiter when enabled$ stays literal instead of committing on the opening delimiter$$ line-shaped trigger detection does not fire inside existing code or
incompatible contexts$$ plus Enter promotion only fires in the allowed branch$ text in plain typing pathsAdd:
apps/www/src/__tests__/package-integration/math/math-delimiter-trigger.slow.tsxScenarios:
$ still stays
deferred by default$...$ converts on the closing
delimiter$$ then Enter promotes to block math
if Slice B shipsVerify on the real docs/demo surface with browser-use:
$$ plus EnterIf the trigger plugin is too broad, $ starts acting like a normal quote pair
everywhere.
Mitigation:
$$ promotion fights normal block ownershipThe Enter path is structurally different from insertText.
Mitigation:
Inline equation nodes can open editing UI or shift focus unexpectedly.
Mitigation:
EDIT-PROFILE-MATH-TRIGGER-002 and 003 are implemented and tested for the
default rich mode.EDIT-PROFILE-MATH-TRIGGER-001 remains explicitly approval-gated instead of
being silently assumed.