feat(markdown): render Mermaid across chat + preview surfaces (#50)#195
Open
MarkSiqiZhang wants to merge 4 commits intofix/issue-50-latex-bracketsfrom
Open
feat(markdown): render Mermaid across chat + preview surfaces (#50)#195MarkSiqiZhang wants to merge 4 commits intofix/issue-50-latex-bracketsfrom
MarkSiqiZhang wants to merge 4 commits intofix/issue-50-latex-bracketsfrom
Conversation
Add a MermaidBlock component that renders ```mermaid fences inline as SVG via a lazy-loaded mermaid@11 import. The chat Markdown CodeBlock short-circuits to MermaidBlock when language === 'mermaid', bypassing syntax highlighting. Streaming partial sources are debounced 150ms and fall back to a <pre> of the raw source on parse errors, so users never see a flashing error during a live stream. Theme is driven by useTheme() so diagrams repaint live on dark-mode toggle without remount. Also tighten formatFileTreeInContent so it no longer mis-wraps non-tree content in ```text fences — the likely cause of the "fence marker / text label leak" symptom in issue #50. Two guardrails: 1. Skip detection inside fenced code blocks (insideFence toggle). 2. Only commit the wrap when the collected block contains at least one strong signal (├── or └──); lone-│ clusters (ASCII pipelines, Mermaid-ish art) pass through unwrapped. i18n: add codeBlock.rendering / codeBlock.renderError in en/zh-CN/ko; reuse existing codeBlock.copy / codeBlock.copied for the diagram copy button. Scope: chat surface only, mirroring PR #191. ChatContextFilePreview, ResearchLab, and CodeEditor are deferred to a follow-up. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…urfaces. Extract a shared MarkdownRenderer that owns mermaid routing + LaTeX normalization + plugin defaults, and migrate three surfaces to it: CodeEditor markdown preview, ChatContextFilePreview, and ResearchLab IdeaCard + FileViewer.
Collaborator
|
我这边本地把这条 PR 看完了,也跑了 另外我用浏览器把这次 PR 改到的几条 Mermaid / Markdown 渲染链路单独挂出来测了一轮:
这几条链路里:
不过我抓到一个建议尽快补掉的 follow-up:
我本地能稳定看到 React 的 建议这里把 除了这个点之外,我这边暂时没有看到别的明显 blocker。 |
…down v10 react-markdown@10 removed the `inline` prop and now passes HAST nodes (`node.type === 'element'`) instead of MDAST (`node.type === 'inlineCode'`), so `inlineDetected` was always false — every inline `<code>` in a paragraph fell through to the block renderer and produced `<p><div>...</div></p>` DOM, tripping validateDOMNesting warnings. Add a newline-based fallback: markdown forbids newlines in inline code and block children always carry a trailing \n, so `!/[\r\n]/.test(raw)` reliably distinguishes the two. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Collaborator
Author
|
感谢 review,这里现在修复了。
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes Issue #50: render
```mermaidfences as SVG diagrams in every markdown surface, not just chat. Stacked on #191 (LaTeX bracket delimiters); base will auto-retarget tomainonce #191 merges.Changes
Chat surface —
7794e44MermaidBlockcomponent — lazy-loadsmermaid@11via dynamic import, 150 ms debounce so streaming partials don't flash a parse error, graceful<pre>fallback on invalid syntax, copy-source button.useTheme()drives the diagram theme so dark-mode toggles repaint live.CodeBlockvia a 3-line short-circuit whenlanguage === 'mermaid'.formatFileTreeInContent: skip detection inside fenced code blocks; only wrap when the block contains at least one├──or└──. Lone-│clusters (ASCII pipelines, Mermaid-ish art) now pass through unwrapped.Preview surfaces —
c06f69asrc/components/shared/MarkdownRenderer.tsx— owns mermaid routing,normalizeLatexDelimiters, plugin defaults (remarkGfm,remarkMath,rehypeKatex), and code-block rendering. Two code-block variants:codeBlockStyle="syntax"— lazy-loadedreact-syntax-highlighter+ copy button (used by CodeEditor + ChatContextFilePreview).codeBlockStyle="plain"— language banner +<pre>, matching ResearchLab's pre-existing look.CodeEditor.jsxmarkdown preview tab — the bug in the screenshot.chat/view/subcomponents/ChatContextFilePreview.tsx— was bare<ReactMarkdown>with nocomponentsprop.ResearchLab.jsxIdeaCard body + FileViewer markdown preview.Scope decisions
chat/view/subcomponents/Markdown.tsxintentionally deferred. It already renders mermaid correctly (per7794e44) and has streaming highlighting +onFileOpenlink rewriting + insight callouts that need to be lifted into props before consolidation. Migrating it in this PR would add regression risk without fixing any user-visible bug. Tracked as a follow-up.OVERVIEW_MARKDOWN_COMPONENTSunchanged — small inline blurbs with intentionally minimal styling. Mermaid is unlikely to appear there.i18n
No new keys. Reuses
chat:codeBlock.{copy,copied,rendering,renderError}(already present in en/zh-CN/ko from7794e44).Bundle
mermaid.core-*.js+ per-diagram chunks).react-syntax-highlighteris nowReact.lazy()-loaded insideMarkdownRenderer, so surfaces usingcodeBlockStyle="plain"(ResearchLab) don't pull it.Test plan
npm run typecheckandnpm run buildmust pass. Thennpm run devand exercise the fixture below in each surface.Fixture (any
.mdfile):Per surface:
<pre>with amber error..md, click preview toggle; SVG renders; python keeps syntax highlighting; KaTeX renders; broken block → fallback..mdas chat context, expand preview; same checks as CodeEditor.<pre>(no syntax highlighter — verifies thecodeBlockStyle="plain"opt-out path).│) is no longer auto-wrapped in```text; a real file tree (├──,└──) still wraps.\[ r_t(\theta) = ... \]still renders via KaTeX; no\thetacorruption.