import { useState } from 'react'; import { Download, Code2, Check, Copy } from 'lucide-react'; import ReactMarkdown from 'react-markdown'; import remarkMath from 'remark-math'; import rehypeKatex from 'rehype-katex'; import 'katex/dist/katex.min.css'; import { RecognitionResult } from '../types'; import ExportSidebar from './ExportSidebar'; interface ResultPanelProps { result: RecognitionResult | null; fileStatus?: 'pending' | 'processing' | 'completed' | 'failed'; } /** * Preprocess LaTeX content to fix common formatting issues * that may cause KaTeX rendering to fail */ function preprocessLatex(content: string): string { if (!content) return ''; let processed = content; // Fix mixed display math delimiters: $$\[...\]$$ -> $$...$$ // This handles cases where \[ \] are incorrectly nested inside $$ $$ // Note: In JS replace(), $$ means "insert one $", so we need $$$$ to insert $$ processed = processed.replace(/\$\$\s*\\\[/g, '$$$$'); processed = processed.replace(/\\\]\s*\$\$/g, '$$$$'); // Also fix standalone \[ and \] that should be $$ for remark-math compatibility // Replace \[ with $$ at the start of display math (not inside other math) processed = processed.replace(/(? $$\n\begin processed = processed.replace(/\$\$([^\n$])/g, '$$$$\n$1'); // Ensure content followed by $$ has a newline: content$$ -> content\n$$ processed = processed.replace(/([^\n$])\$\$/g, '$1\n$$$$'); // Fix: \left \{ -> \left\{ (remove space between \left and delimiter) processed = processed.replace(/\\left\s+\\/g, '\\left\\'); processed = processed.replace(/\\left\s+\{/g, '\\left\\{'); processed = processed.replace(/\\left\s+\[/g, '\\left['); processed = processed.replace(/\\left\s+\(/g, '\\left('); // Fix: \right \} -> \right\} (remove space between \right and delimiter) processed = processed.replace(/\\right\s+\\/g, '\\right\\'); processed = processed.replace(/\\right\s+\}/g, '\\right\\}'); processed = processed.replace(/\\right\s+\]/g, '\\right]'); processed = processed.replace(/\\right\s+\)/g, '\\right)'); // Fix: \begin{matrix} with mismatched \left/\right -> use \begin{array} // This is a more complex issue that requires proper \left/\right pairing // For now, we'll try to convert problematic patterns // Replace \left( ... \right. text \right) pattern with ( ... \right. text ) // This fixes the common mispairing issue processed = processed.replace(/\\left\(([^)]*?)\\right\.\s*(\\text\{[^}]*\})\s*\\right\)/g, '($1\\right. $2)'); return processed; } export default function ResultPanel({ result, fileStatus }: ResultPanelProps) { const [isExportSidebarOpen, setIsExportSidebarOpen] = useState(false); const [copied, setCopied] = useState(false); const handleCopy = async () => { if (result?.markdown_content) { await navigator.clipboard.writeText(result.markdown_content); setCopied(true); setTimeout(() => setCopied(false), 2000); } }; if (!result) { if (fileStatus === 'processing' || fileStatus === 'pending') { return (

{fileStatus === 'pending' ? 'Waiting in queue...' : 'Analyzing...'}

{fileStatus === 'pending' ? 'Your file is in the queue, please wait.' : 'Texpixel is processing your file, this may take a moment.'}

); } return (

Waiting for recognition result

After uploading the file, Texpixel will automatically recognize and display the result here

); } return (
{/* Top Header */}

Markdown

{/* Content Area - Rendered Markdown */} {
{preprocessLatex(result.markdown_content || '')}
} setIsExportSidebarOpen(false)} result={result} />
); }