Skip to content

Commit 7d64404

Browse files
committed
fix(files): render mermaid diagrams in markdown preview using design tokens
Streamdown intercepts fenced code blocks before components.code is called, so the previous mermaid branch in the code renderer was dead code. Add a remarkMermaid plugin that transforms mermaid code nodes at the MDAST stage via data.hName/hProperties so remark-rehype emits a <mermaid-diagram> element that our MermaidDiagram component handles. This avoids Streamdown's built-in mermaid renderer which uses mismatched Tailwind semantic classes.
1 parent 1ce4143 commit 7d64404

1 file changed

Lines changed: 32 additions & 5 deletions

File tree

apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-panel.tsx

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,33 @@ export const PreviewPanel = memo(function PreviewPanel({
9696

9797
const CALLOUT_TYPES = new Set(['NOTE', 'TIP', 'WARNING', 'IMPORTANT', 'CAUTION'])
9898

99+
function remarkMermaid() {
100+
return (tree: { type: string; children?: unknown[] }) => {
101+
function processNode(node: {
102+
type: string
103+
children?: unknown[]
104+
lang?: string
105+
value?: string
106+
data?: Record<string, unknown>
107+
}) {
108+
if (!node.children) return
109+
for (const child of node.children) {
110+
const c = child as typeof node
111+
if (c.type === 'code' && c.lang === 'mermaid') {
112+
c.data = {
113+
hName: 'mermaid-diagram',
114+
hProperties: { definition: c.value ?? '' },
115+
hChildren: [],
116+
}
117+
} else {
118+
processNode(c)
119+
}
120+
}
121+
}
122+
processNode(tree)
123+
}
124+
}
125+
99126
function remarkCallouts() {
100127
return (tree: { type: string; children?: unknown[] }) => {
101128
function processNode(node: { type: string; children?: unknown[] }) {
@@ -140,7 +167,7 @@ function remarkCallouts() {
140167
}
141168
}
142169

143-
const REMARK_PLUGINS = [remarkGfm, remarkBreaks, remarkCallouts]
170+
const REMARK_PLUGINS = [remarkGfm, remarkBreaks, remarkMermaid, remarkCallouts]
144171
const REHYPE_PLUGINS = [rehypeSlug]
145172

146173
/**
@@ -320,6 +347,9 @@ function resolveSimFileUrl(src: string | undefined): string | undefined {
320347

321348
const STATIC_MARKDOWN_COMPONENTS = {
322349
pre: ({ children }: { children?: React.ReactNode }) => <>{children}</>,
350+
'mermaid-diagram': ({ definition }: { definition?: string }) => (
351+
<MermaidDiagram definition={definition ?? ''} />
352+
),
323353
p: ({ children }: { children?: React.ReactNode }) => (
324354
<p className='mb-3 break-words text-[14px] text-[var(--text-primary)] leading-[1.6] last:mb-0'>
325355
{children}
@@ -392,10 +422,6 @@ const STATIC_MARKDOWN_COMPONENTS = {
392422
const langRaw = langMatch?.[1] ?? ''
393423
const codeString = extractTextContent(children)
394424

395-
if (langRaw === 'mermaid') {
396-
return <MermaidDiagram definition={codeString} />
397-
}
398-
399425
if (!codeString) {
400426
return (
401427
<code className='whitespace-normal rounded bg-[var(--surface-5)] px-1.5 py-0.5 font-mono text-[var(--caution)]'>
@@ -728,6 +754,7 @@ const MarkdownPreview = memo(function MarkdownPreview({
728754
remarkPlugins={REMARK_PLUGINS}
729755
rehypePlugins={REHYPE_PLUGINS}
730756
components={MARKDOWN_COMPONENTS}
757+
allowedTags={{ 'mermaid-diagram': ['definition'] }}
731758
>
732759
{markdownContent}
733760
</Streamdown>

0 commit comments

Comments
 (0)