/** * 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{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 (
{content}
)
}
/**
* Render a StepBlock - solution step with nested blocks
*/
const StepBlockRenderer = ({ index, title, blocks }) => {
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 (