Add inline `[[/` autocomplete to BlockEditor

Add inline [[/ autocomplete to BlockEditor

#4 in Riparion/riparion-editor — merged 2026-06-02

What

Type the literal [[/ in a block's textarea to open an inline popup of host-supplied candidates, filtered by the query typed after [[/. ↑/↓ select, Enter/Tab splice the chosen snippet at the caret (forced onto its own line so it reads as a standalone embed), Esc dismisses.

The crate stays app-agnostic: the new autocomplete module provides the mechanics; the host injects candidates via the optional complete callback (query -> Vec<CompletionItem>) and themes the menu via the completion_*_class props. complete: None (the default) disables autocomplete entirely — fully back-compatible.

How

  • Pure, unit-tested logic (no web feature): find_trigger detects [[/, captures the [A-Za-z0-9_-]* query, and bails on a space/]/newline; apply_completion splices at the caret and forces the snippet onto its own line. 9 new tests (incl. multibyte).
  • use_autocomplete hook — the single behavior source, reused by BlockEditor (Live mode) and usable by any host textarea (e.g. a raw source view). Reads the caret on oninput, drives the popup on onkeydown, and on accept performs the DOM splice + caret move, returning the new value via KeyOutcome::Accepted { value } for the caller to commit to its own source signal. Off web it's inert, so server/SSR builds compile and render nothing.
  • CompletionPopup — themeless markup positioned by the caller (inside a position:relative wrapper) and styled via class props; items fire on mousedown (prevent_default) so picking one doesn't blur the textarea before the splice lands.
  • Key precedence: the autocomplete keydown gets first refusal on ↑/↓/Enter/Tab/Esc, so an open popup never also triggers block split / cross-block nav / deactivate.
  • Example (examples/markdown.rs): wires [[/ autocomplete with a small fixed catalog.

Verification

  • cargo fmt --check clean.
  • cargo test --no-default-features: 20 passed (11 existing + 9 new).
  • clippy -D warnings on both CI targets: --no-default-features --all-targets (non-web) and --features web --target wasm32-unknown-unknown (wasm). The example also compiles on wasm.

Consumed by riparion-cms next (a follow-up PR there bumps the pin and wires MarkdownPane's Live + Raw textareas to this hook).

🤖 Generated with Claude Code

Last updated 2026-06-03