Skip to content

feat(ui): add Mermaid diagram visualization in markdown#21497

Open
callmeYe wants to merge 8 commits intoanomalyco:devfrom
callmeYe:feat/mermaid-upstream
Open

feat(ui): add Mermaid diagram visualization in markdown#21497
callmeYe wants to merge 8 commits intoanomalyco:devfrom
callmeYe:feat/mermaid-upstream

Conversation

@callmeYe
Copy link
Copy Markdown

@callmeYe callmeYe commented Apr 8, 2026

Issue for this PR

Closes #

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Adds interactive Mermaid diagram visualization for ```mermaid code blocks in the markdown renderer, inspired by Vercel's @streamdown/mermaid.

Currently, mermaid code blocks are rendered as plain text (Shiki doesn't recognize the mermaid language and falls back to text). This PR intercepts mermaid code blocks in both markedShiki highlight and highlightCodeBlocks (native parser path), outputs a placeholder <div data-component="mermaid-diagram">, then asynchronously renders them as interactive SVG diagrams after morphdom DOM updates.

The mermaid library (~3MB) is lazy-loaded on first use to avoid impacting initial bundle size.

Interactive features:

  • Zoom: Scroll wheel + button controls (0.5x–3x range, 0.1 step)
  • Pan: Pointer drag with setPointerCapture for reliable tracking
  • Fullscreen: Appends a fixed overlay to document.body, re-renders SVG via mermaid.render() with a fresh ID to avoid DOM ID/CSS selector conflicts with the inline copy. Closes via Escape key or X button.
  • Download: Dropdown with SVG, PNG (5x canvas for high-res), and .mmd source export
  • Copy source: Clipboard write with 2-second visual feedback
  • Error handling: Failed renders show an error bar above the preserved source code

Streaming compatibility: markdown-stream.ts already splits incomplete code fences, so incomplete mermaid blocks display as raw code until the fence closes, then auto-render. Rendered diagrams are preserved across morphdom updates via onBeforeElUpdated returning false for data-mermaid-rendered elements.

Key fix: Mermaid outputs width="100%" on SVGs, which collapses to 0px in a pure flex layout (the fullscreen viewport). fixSvgSizing() replaces percentage width with the actual viewBox dimensions and constrains with max-width: 90vw / max-height: 85vh.

How did you verify your code works?

  • Tested locally with multiple mermaid diagram types (flowchart, sequence, ER, state, pie, gantt)
  • Verified streaming behavior: incomplete code fences show raw code, completed fences auto-render
  • Tested all interactive controls: zoom in/out/reset, drag pan, fullscreen open/close (Escape + X button + backdrop click), download SVG/PNG/MMD, copy source
  • Verified fullscreen renders correctly (no black rectangles or blank SVGs) by re-rendering with a fresh mermaid ID
  • Confirmed regular code blocks are unaffected
  • Typecheck passes (bun run typecheck in packages/ui)

Screenshots / recordings

N/A — this is best tested interactively. Send any message containing a ```mermaid code block to see the rendered diagram with hover controls.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

🤖 Generated with Claude Code

@github-actions github-actions bot added the needs:compliance This means the issue will auto-close after 2 hours. label Apr 8, 2026
Add interactive Mermaid diagram rendering for ```mermaid code blocks,
inspired by Vercel's @streamdown/mermaid package.

Features:
- Lazy-load mermaid library (~3MB) on first use
- Auto-detect dark/light theme for diagram rendering
- Interactive controls: zoom (0.5x-3x), pan (drag), fullscreen,
  download (SVG/PNG/source), copy source
- Fullscreen mode re-renders SVG to avoid DOM ID conflicts
- Fix SVG width="100%" collapse in flex layouts via viewBox sizing
- Streaming-compatible: incomplete code fences show raw code
- Error handling with source fallback display

Integration:
- Intercept mermaid language in markedShiki highlight and
  highlightCodeBlocks (native parser path)
- Skip mermaid blocks in ensureCodeWrapper (decorate)
- Preserve rendered diagrams across morphdom updates
- Async post-processing after morphdom

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@callmeYe callmeYe force-pushed the feat/mermaid-upstream branch from 533e0c6 to 10e6c50 Compare April 8, 2026 09:57
@github-actions github-actions bot removed the needs:compliance This means the issue will auto-close after 2 hours. label Apr 8, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 8, 2026

Thanks for updating your PR! It now meets our contributing guidelines. 👍

callmeYe and others added 2 commits April 9, 2026 14:06
Merged latest dev into feat/mermaid-upstream and regenerated bun.lock
via `bun install` to resolve the lockfile conflict.
@callmeYe
Copy link
Copy Markdown
Author

callmeYe commented Apr 9, 2026

/review

callmeYe and others added 5 commits April 9, 2026 15:29
The previous bun install runs on this branch picked up a local
~/.npmrc that points to the Alibaba intranet mirror
(registry.anpm.alibaba-inc.com), which baked private registry URLs
into ~3257 package entries in bun.lock. That makes the lockfile
unreproducible for anyone outside the corp network and breaks
upstream CI.

Reset bun.lock to github/dev's baseline and re-ran
`BUN_CONFIG_REGISTRY=https://registry.npmjs.org/ bun install` so
the new mermaid dependency tree is added against the public
registry. The only remaining diff vs dev is the mermaid packages
plus the version bumps brought in by the merge from dev.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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