feat(markdown): mermaid diagram rendering (LC-550) #520
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/LC-550-mermaid-diagrams"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
LC-550: Mermaid diagram rendering (Round 4, Vein C - content, quick win)
Render ```mermaid fenced code blocks as inline diagrams (flowcharts, sequence diagrams, etc.), the way LaTeX math already renders. Progressive enhancement: server emits a container, a vendored self-hosted mermaid bundle swaps in an SVG on the client. No CDN, no framework.
How it works
views/markdown.rs: a mermaid branch in the fenced-code path (next to the highlighter). A ```mermaid fence emits<div class="lc-mermaid" data-lc-mermaid><pre class="lc-mermaid-src">ESCAPED SOURCE</pre></div>instead of highlighted code. The info string is matched case-insensitively and tolerates trailing attributes.assets/mermaid.js: a small framework-free loader that finds the containers and renders them. The ~3.5MB vendored bundle (assets/vendor/mermaid.min.js, mermaid 11.16.0) is fetched LAZILY, only once a page actually contains a diagram, so diagram-free pages pay nothing. New messages arriving over HTMX are re-scanned onhtmx:afterSwap.Safety and fallback
securityLevel: 'strict'(labels sanitized, click/HTML disabled).<pre>stays visible as a readable fallback.data-theme(dark/light). The existing CSP already permits a same-origin script plus mermaid's inline styles/eval, so no CSP change.Caching / i18n
The container is deterministic from the source and carries no localized text, so it caches like any other rendered block (the content-keyed markdown cache stays correct across locales).
Tests
Unit (CI/lib): container shape, source escaping, case/attribute info-string variants, and that non-mermaid fences still highlight.
Notes
Gates:
just check, fulljust test,just test-saasall green.🤖 Generated with Claude Code
https://claude.ai/code/session_01S5obszLoUgUi8qaF7Hi5qz