"use client"; import ReactMarkdown from "react-markdown"; import remarkGfm from "remark-gfm"; import remarkMath from "remark-math"; import rehypeKatex from "rehype-katex"; import "katex/dist/katex.min.css"; import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; import { oneLight } from "react-syntax-highlighter/dist/esm/styles/prism"; interface Props { content: string; } /** * Pre-process content to normalize LaTeX delimiters for remark-math. * Fallback: converts \[...\] → $$...$$ and \(...\) → $...$ * System prompt already instructs model to use $...$ and $$...$$. */ function preprocessLaTeX(content: string): string { // Step 1: Convert \[...\] to $$...$$ (block math) let result = content.replace( /\\\[([\s\S]*?)\\\]/g, (_match, inner) => `$$${inner}$$` ); // Step 2: Convert \(...\) to $...$ (inline math) result = result.replace( /\\\(([\s\S]*?)\\\)/g, (_match, inner) => `$${inner}$` ); return result; } export function MarkdownRenderer({ content }: Props) { const processed = preprocessLaTeX(content); return (
{language}
{codeStr} ) : ( {children} ); }, p({ children }) { return

{children}

; }, ul({ children }) { return ; }, ol({ children }) { return
    {children}
; }, h1({ children }) { return

{children}

; }, h2({ children }) { return

{children}

; }, h3({ children }) { return

{children}

; }, table({ children }) { return (
{children}
); }, th({ children }) { return ( {children} ); }, td({ children }) { return ( {children} ); }, img({ src, alt, ...props }) { // Skip rendering if src is empty — prevents browser error if (!src) return null; // eslint-disable-next-line @next/next/no-img-element return {alt; }, blockquote({ children }) { return (
{children}
); }, }} > {processed}
); }