(codeTheme: string, size: MarkdownSize, styles: typeof sizeStyles.md, isStreaming: boolean = false)
| 248 | |
| 249 | // Custom code component that uses our theme system |
| 250 | function createCodeComponent(codeTheme: string, size: MarkdownSize, styles: typeof sizeStyles.md, isStreaming: boolean = false) { |
| 251 | return function CodeComponent({ className, children, node, ...props }: any) { |
| 252 | const match = /language-(\w+)/.exec(className || "") |
| 253 | const language = match ? match[1] : undefined |
| 254 | const codeContent = String(children) |
| 255 | |
| 256 | // Check if this is a code block (has language) or inline code |
| 257 | // Streamdown wraps code blocks in <pre><code>, inline code is just <code> |
| 258 | const isCodeBlock = language || (codeContent.includes("\n") && codeContent.length > 100) |
| 259 | |
| 260 | if (isCodeBlock) { |
| 261 | // Route mermaid blocks to MermaidBlock component |
| 262 | if (language === "mermaid") { |
| 263 | // Pass isStreaming to MermaidBlock |
| 264 | // When streaming, MermaidBlock shows a placeholder instead of trying to render |
| 265 | return <MermaidBlock code={codeContent.replace(/\n$/, "")} size={size} isStreaming={isStreaming} /> |
| 266 | } |
| 267 | |
| 268 | return ( |
| 269 | <CodeBlock |
| 270 | language={language} |
| 271 | themeId={codeTheme} |
| 272 | size={size} |
| 273 | > |
| 274 | {codeContent.replace(/\n$/, "")} |
| 275 | </CodeBlock> |
| 276 | ) |
| 277 | } |
| 278 | |
| 279 | // Inline code |
| 280 | return <span className={styles.inlineCode}>{children}</span> |
| 281 | } |
| 282 | } |
| 283 | |
| 284 | export const ChatMarkdownRenderer = memo(function ChatMarkdownRenderer({ |
| 285 | content, |
no outgoing calls
no test coverage detected