Repository navigation
Markdown: render mermaid / mmd fences as diagrams in the Web chat #3346
yishu-ziyu
started this conversation in
Ideas
Replies: 1 comment
中文摘要请在 Web 对话里,把 现在( 动态 Cordis 插件做不到「自然嵌在正文里」:Slot 碰不到单条 markdown 围栏;整页注入 mermaid.js + MutationObserver 会和 React 打架,还容易把页面卡死。所以这应该是 建议:
最小改动点: 如果方向认可,我可以跟进 PR(仓库目前暂不收外部 PR 的话,就当需求投票)。 |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Summary
Please render fenced
mermaid/mmdblocks as diagrams inside the assistant message, the same wayMarkdownTextalready special-casesmathfences and KaTeX.Today those fences only get Shiki highlighting via
CodeBlock. Agents emit Mermaid constantly (flowcharts, sequence diagrams, architecture). In the Web UI they stay as source, so users copy them out to mermaid.live.Current behavior (0.1.0-rc.6)
MarkdownText→renderCodealways ends inCodeBlockexcept forlang === "math":CodeBlockis a highlighted source surface (banner + copy). There is no diagram path formermaid/mmd.This is inconsistent with the rest of the markdown family: GFM + KaTeX already treat some fences as presentation, not source.
Why a dynamic / Cordis plugin is the wrong layer
I tried to do this from a session-scoped dynamic plugin first. It cannot look native:
conversation.chat.node,conversation.chat.turnTail,conversation.input.dock,tool.view.cordis, …) never reach an individual markdown fence.conversation.chat.node/assistant-stepwould shadow the shipped message renderer.MutationObserverover.md-code-blockcan draw a chart, but it fights React reconciliation, can infinite-loop on its own inserts, and blows up layout (huge SVGs, UI freeze).So “a card under the composer” or “a DOM patch” is a demo, not a product feature. Native rendering belongs in
ui-primitives, next to KaTeX.Proposed behavior
mermaid,mmd(infostring first token, same/^[\w-]+/split as today).streaming === true, keep the current sourceCodeBlock(no highlight / no mermaid), matching KaTeX (“highlighting and KaTeX land on the finalize swap”).CodeBlockplus a short error line. Never blank the message.securityLevel: "strict"(or equivalent). NodangerouslySetInnerHTMLof model HTML; only mermaid-produced SVG. No click/js callbacks from diagrams.max-width: 100%, bounded height + scroll (e.g. ~360px). A 20-node graph must not take the viewport or lock the main thread.neutral/dark, or CSS variables already used by markdown).Example that should become a chart after the turn settles
graph TD A[Start] --> B{Done?} B -->|Yes| C[Ship] B -->|No| D[Fix] D --> BSuggested implementation
Smallest change, same shape as the
mathbranch:packages/client/ui-primitives—src/markdown/render.tsx(renderCode)MermaidBlocknext toCodeBlock.tsxmermaid(or a slim renderer). Keepui-primitiveszero-cordis.import('mermaid')so the boot chunk does not pay for it until a settled mermaid fence appears (same spirit as lazy Shiki grammars).Pseudo-API (illustrative):
MermaidBlockwould:mermaid.initialize({ startOnLoad: false, securityLevel: 'strict', theme })mermaid.render(stableId, code)→ SVG<CodeBlock code={code} lang="mermaid" />No Slot, no Host RPC, no
tapIndex, no page-wide observer.Acceptance criteria
```mermaid/```mmdrenders a diagram in the message body.MessageTextunchanged (literal), unless you explicitly want mermaid there too — I only need assistant markdown.Out of scope
Environment
@deepseek-ai/dsh0.1.0-rc.6(dsh web)@deepseek-ai/dsh-client-ui-primitivesHappy to send a PR against
packages/client/ui-primitivesif this direction is acceptable.All reactions