'use client' import { memo, useMemo } from 'react' import ReactMarkdown from 'react-markdown' import remarkGfm from 'remark-gfm' import remarkMath from 'remark-math' import rehypeKatex from 'rehype-katex' import rehypeRaw from 'rehype-raw' import 'katex/dist/katex.min.css' import { NoteChartFromCode } from './note-chart' // Memoized wrapper to prevent infinite re-renders const ChartWrapper = memo(function ChartWrapper({ code }: { code: string }) { return }) interface MarkdownContentProps { content: string className?: string } export const MarkdownContent = memo(function MarkdownContent({ content, className }: MarkdownContentProps) { // Strip ... and ... blocks produced by reasoning models // (MiniMax, DeepSeek R1, etc.) before passing to ReactMarkdown — rehypeRaw would otherwise // try to render them as HTML elements causing React warnings. // Also handles partial/unclosed blocks during streaming (e.g. without yet). const safeContent = useMemo( () => content .replace(/[\s\S]*?<\/think>/gi, '') // complete think blocks .replace(/[\s\S]*/i, '') // unclosed think block (still streaming) .replace(/[\s\S]*?<\/thinking>/gi, '') // complete thinking blocks .replace(/[\s\S]*/i, '') // unclosed thinking block .trim(), [content] ) return ( ) })