--- type: ADR id: "0137" title: "Shared rich-editor input transforms" status: active date: 2026-06-07 --- ## Context Tolaria has several Markdown-style conveniences in the rich BlockNote editor: typed arrows become ligatures, completed inline math becomes a math node, and completed `==highlight==` syntax becomes the durable highlight mark. These features were added incrementally as separate `beforeinput` extensions. Each extension repeated the same lifecycle work: reading the live ProseMirror view, skipping IME composition, guarding stale views, dispatching transactions, preventing native input only after a successful transform, and recovering known BlockNote/ProseMirror transform failures. The syntax matchers differed, but the execution shell was parallel enough that each new Markdown affordance risked a slightly different edge-case policy. ## Decision **Tolaria routes rich-editor Markdown input transforms through one shared `beforeinput` execution path.** `src/components/richEditorInputTransform.ts` owns the common lifecycle, dispatch, and recoverable-error behavior. Feature files such as `arrowLigaturesExtension.ts`, `mathInputExtension.ts`, and `markdownHighlightInputExtension.ts` expose small transform objects that only decide whether the current input event should produce a transaction. `src/components/richEditorInputTransformExtension.ts` composes the Markdown transform set used by the main editor and hidden editor probe. ## Options Considered - **Shared transform primitive with feature-owned matchers** (chosen): removes duplicate listener, dispatch, composition, and recovery code while keeping each syntax rule local and testable. - **One monolithic Markdown input extension**: reduces listener count, but mixes unrelated syntax rules in one file and makes each future input affordance harder to test independently. - **Keep one extension per feature**: preserves local ownership, but keeps the repeated edge-case shell and invites divergence as more transforms are added. ## Consequences - `Editor` mounts one Markdown input-transform extension rather than separate arrow, math, and highlight `beforeinput` listeners. - Feature-specific files remain responsible for their syntax matching and transaction construction only. - Recoverable transform errors use the same telemetry event and fallback policy across Markdown input transforms. - New rich-editor Markdown input affordances should plug into the shared transform primitive instead of adding another capture-phase `beforeinput` extension.