Skip to content

Live mermaid preview while editing + handle alignment fix#26

Merged
ptheofan merged 22 commits into
mainfrom
feat/mermaid-live-preview
May 20, 2026
Merged

Live mermaid preview while editing + handle alignment fix#26
ptheofan merged 22 commits into
mainfrom
feat/mermaid-live-preview

Conversation

@ptheofan
Copy link
Copy Markdown
Owner

Summary

Two things in this branch:

  1. Live mermaid preview while editing — clicking a ```mermaid``` block in edit mode now opens a preview-above-source surface. The rendered diagram stays visible at the top; a textarea sits below; the diagram re-renders ~250ms after each keystroke. Invalid mermaid syntax keeps the last good preview visible and surfaces the error in an inline chip between preview and textarea. `Esc` commits, click-away commits, race conditions are handled by per-call scratch containers and monotonic request IDs.

  2. Slice handle alignment for mermaid blocks — `slice-code:has(.mermaid-container)` override sets `--slice-handle-top: 0px` since mermaid blocks render as `<div.mermaid-container>` rather than `

    `, and the 13px offset tuned for `
    `'s padding was wrong.

Architecture (generalised)

The live preview is built on a new optional plugin capability — `PreviewablePlugin` — so any plugin that owns a fenced code block and can render to visual content can opt into the same editing surface. Mermaid is the first implementer; future plugins (math, graphviz, embedded HTML, etc.) get live preview for free by implementing four methods.

Component Role
`PreviewablePlugin` interface Optional capability: `matchesSlice`, `extractSource`, `renderPreview`, `applySourceToRaw`
`PluginManager.getPreviewablePlugins()` Returns enabled plugins implementing the capability
`MermaidPlugin` Implements the contract — opens ```mermaid``` and `~~~mermaid``` fences with info-string preservation
`PreviewableSourceEditor` (new) Drives one editing session: layout, debounced re-render, race control, error chip, idempotent commit
`EditModeController` New routing branch in `startEdit` opens the previewable editor for matching slices; shared `applyRawCommit` helper factored out so both the slim textarea and the previewable editor follow the same re-render path

Stats

  • 9 files changed (3 added)
  • 38 new tests; total suite 598 passing
  • 22 commits, written task-by-task via TDD with subagent-driven implementation + two-stage review per task

Spec and plan

  • Design: `docs/superpowers/specs/2026-05-19-mermaid-live-preview-design.md`
  • Plan: `docs/superpowers/plans/2026-05-19-mermaid-live-preview.md`

Test plan

  • `pnpm typecheck` clean
  • `pnpm test` — 598 passing across 30 files (38 new)
  • `pnpm lint` clean
  • Manual: open a file with a mermaid diagram → enter edit mode (`Cmd+E`) → click the mermaid block → confirm preview-above-textarea surface
  • Manual: edit the diagram source → preview updates ~250ms after typing pauses
  • Manual: type invalid syntax → last good preview stays + red error chip appears with the mermaid error message
  • Manual: fix the syntax → error chip disappears, preview updates
  • Manual: `Esc` commits, slice re-renders with the new source
  • Manual: click a non-mermaid code block (```js```) → opens regular raw textarea (no preview area)
  • Manual: click a paragraph → still opens WYSIWYG inline editor
  • Manual: hover any slice → handle dot grid sits aligned with the first text line for all block types

🤖 Generated with Claude Code

ptheofan and others added 22 commits May 19, 2026 19:53
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mermaid blocks share the 'code' slice type with regular code fences but
render as <div.mermaid-container> rather than <pre><code>. The 13px
handle offset tuned for <pre>'s 16px top padding plus 85% font lines
was pushing the handle down into the diagram. Override to 0px for
mermaid via :has(.mermaid-container) so the handle sits at the
slice's top edge — aligned with the diagram's bounding box.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Move preview imports to the top of the file, nest describe('getPreviewablePlugins')
inside the main describe('PluginManager'), and add a negative-case test that confirms
registered-but-not-enabled previewable plugins are excluded from the result.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…urce

- Add test: raw with no fences round-trips unchanged
- Add test: raw with opening fence but no closing fence strips only the opener
- Change trim() → trimEnd() on the closing-fence check to match the
  trimStart() used on the opening-fence check (symmetry fix)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ring

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ling

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Wire previewable plugin detection into EditModeController.startEdit so
mermaid (and any future PreviewablePlugin) slices open with live preview
above source. Factor the post-update re-render logic from commitRawEdit
into a shared applyRawCommit helper used by both paths. Non-previewable
code slices now also fall back to raw editing instead of WYSIWYG.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ptheofan ptheofan merged commit 8369e49 into main May 20, 2026
4 checks passed
@ptheofan ptheofan deleted the feat/mermaid-live-preview branch May 20, 2026 06:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant