/** * BlockRenderer - Renders structured message blocks * NO hardcoded parsing - only handles proper JSON blocks from backend */ import { useMemo } from 'react' import { BlockMath, InlineMath } from 'react-katex' import 'katex/dist/katex.min.css' /** * Render a TextBlock - plain text */ const TextBlock = ({ content }) => { if (!content) return null return

{content}

} /** * Render a MathBlock - KaTeX for math expressions * Accepts either 'latex' or 'content' prop for compatibility */ const MathBlockRenderer = ({ latex, content, display = 'block' }) => { // Support both 'latex' and 'content' field names const mathContent = latex || content if (!mathContent) return null try { if (display === 'inline') { return } return (
) } catch (error) { console.error('KaTeX render error:', error) return {mathContent} } } /** * Render a ListBlock - ordered or unordered list */ const ListBlockRenderer = ({ items, ordered = false }) => { if (!items || !items.length) return null const ListTag = ordered ? 'ol' : 'ul' return ( {items.map((item, idx) => (
  • {item}
  • ))}
    ) } /** * Render a CodeBlock - syntax highlighted code */ const CodeBlockRenderer = ({ content, language = 'python' }) => { if (!content) return null return (
                {content}
            
    ) } /** * Render a StepBlock - solution step with nested blocks */ const StepBlockRenderer = ({ index, title, blocks }) => { return (
    {index} {title}
    {blocks && blocks.map((block, idx) => ( ))}
    ) } /** * Main BlockRenderer - dispatches to appropriate renderer based on block type */ const BlockRenderer = ({ block }) => { if (!block || !block.type) return null switch (block.type) { case 'text': return case 'math': // Support both 'latex' and 'content' fields return case 'list': return case 'code': return case 'step': return default: console.warn('Unknown block type:', block.type) return

    {JSON.stringify(block)}

    } } /** * MessageBlocks - Renders an array of blocks for a message * Only parses JSON - no hardcoded fallback parsing */ export const MessageBlocks = ({ content }) => { const blocks = useMemo(() => { if (!content) return [] try { // Parse JSON blocks from backend const parsed = typeof content === 'string' ? JSON.parse(content) : content if (parsed.blocks && Array.isArray(parsed.blocks)) { return parsed.blocks } // If no blocks array, wrap as single text block return [{ type: 'text', content: String(content) }] } catch { // JSON parse failed - backend didn't return proper format // Show as plain text (no regex processing) return [{ type: 'text', content: String(content) }] } }, [content]) if (!blocks.length) return null return (
    {blocks.map((block, idx) => ( ))}
    ) } export default BlockRenderer