{"version":3,"sources":["../src/components/LatexRenderer/LatexRenderer.tsx"],"sourcesContent":["import { CSSProperties, ReactNode } from 'react';\nimport 'katex/dist/katex.min.css';\nimport { KatexMath } from '../HtmlMathRenderer/KatexMath';\nimport DOMPurify from 'dompurify';\nimport parse, {\n  DOMNode,\n  Element,\n  HTMLReactParserOptions,\n} from 'html-react-parser';\nimport { cn } from '../../utils/utils';\n\n/**\n * Props for the LatexRenderer component\n */\nexport interface LatexRendererProps {\n  /** HTML content containing LaTeX expressions to render */\n  content: string;\n  /** Additional CSS classes to apply */\n  className?: string;\n  /** Inline styles to apply */\n  style?: CSSProperties;\n  /** Custom error renderer for invalid LaTeX expressions */\n  onError?: (latex: string) => ReactNode;\n}\n\n/**\n * Helper function to sanitize HTML content to prevent XSS attacks\n */\nconst sanitizeHtml = (value: string): string => {\n  return DOMPurify.sanitize(value, {\n    ADD_ATTR: ['data-latex', 'data-display-mode', 'data-math', 'data-math-id'],\n  });\n};\n\n/**\n * Helper function to decode HTML entities\n * Converts entities like &amp;, &lt;, &gt; back to their actual characters\n */\nconst decodeHtmlEntities = (str: string): string => {\n  const textarea = document.createElement('textarea');\n  textarea.innerHTML = str;\n  return textarea.value;\n};\n\n/**\n * Helper function to clean latex from invisible characters\n */\nconst cleanLatex = (str: string): string => {\n  // Remove zero-width characters, invisible characters, and other problematic Unicode\n  return str.replaceAll(/[\\u200B-\\u200D\\uFEFF]/g, '').trim();\n};\n\n/**\n * Type for math parts used in rendering\n */\ninterface MathPart {\n  id: number;\n  type: 'inline' | 'block';\n  latex: string;\n}\n\n/**\n * Creates a replace function for html-react-parser that replaces math placeholders\n * with KaTeX components\n */\nconst createMathReplacer = (\n  mathParts: MathPart[],\n  errorRenderer: (latex: string) => ReactNode\n) => {\n  return (domNode: DOMNode) => {\n    if (\n      domNode instanceof Element &&\n      domNode.name === 'span' &&\n      domNode.attribs['data-math-id']\n    ) {\n      const mathId = Number.parseInt(domNode.attribs['data-math-id'], 10);\n      const mathPart = mathParts[mathId];\n\n      if (!mathPart) return domNode;\n\n      if (mathPart.type === 'inline') {\n        return (\n          <KatexMath\n            key={`math-${mathId}`}\n            math={mathPart.latex}\n            renderError={() => errorRenderer(mathPart.latex)}\n          />\n        );\n      } else {\n        return (\n          <div key={`math-${mathId}`} className=\"my-2.5 text-center\">\n            <KatexMath\n              math={mathPart.latex}\n              displayMode\n              renderError={() => errorRenderer(mathPart.latex)}\n            />\n          </div>\n        );\n      }\n    }\n    return domNode;\n  };\n};\n\n/**\n * LatexRenderer component for Analytica Ensino platforms\n *\n * Renders HTML content with embedded LaTeX/KaTeX mathematical expressions.\n * Supports multiple LaTeX formats:\n * - Inline math: `$...$` or `<latex>...</latex>`\n * - Block math: `$$...$$`\n * - LaTeX environments: `\\begin{equation}...\\end{equation}`, etc.\n * - Editor format: `<span class=\"math-formula\" data-latex=\"...\">...</span>`\n *\n * @param content - HTML content with LaTeX expressions\n * @param className - Additional CSS classes\n * @param style - Inline styles\n * @param onError - Custom error renderer\n * @returns Rendered content with mathematical expressions\n *\n * @example\n * ```tsx\n * <LatexRenderer content=\"The formula is $E = mc^2$\" />\n *\n * <LatexRenderer\n *   content=\"Block equation: $$\\sum_{i=1}^{n} x_i$$\"\n *   className=\"my-custom-class\"\n * />\n *\n * <LatexRenderer\n *   content=\"<p>Matrix: \\begin{pmatrix} a & b \\\\ c & d \\end{pmatrix}</p>\"\n *   onError={(latex) => <span>Invalid: {latex}</span>}\n * />\n * ```\n */\nconst LatexRenderer = ({\n  content,\n  className,\n  style,\n  onError,\n}: LatexRendererProps) => {\n  const renderContentWithMath = (htmlContent: string) => {\n    if (!htmlContent) return null;\n\n    let processedContent = htmlContent;\n    const mathParts: MathPart[] = [];\n\n    // Step 1: Handle math-formula spans (from the editor)\n    const mathFormulaPattern =\n      /<span[^>]*class=\"math-formula\"[^>]*data-latex=\"([^\"]*)\"[^>]*>[\\s\\S]*?<\\/span>/g;\n    processedContent = processedContent.replaceAll(\n      mathFormulaPattern,\n      (match, latex) => {\n        const isDisplayMode = match.includes('data-display-mode=\"true\"');\n        const id = mathParts.length;\n        mathParts.push({\n          id,\n          type: isDisplayMode ? 'block' : 'inline',\n          latex: cleanLatex(decodeHtmlEntities(latex)),\n        });\n        return `<span data-math-id=\"${id}\"></span>`;\n      }\n    );\n\n    // Step 2: Handle wrapped math expressions (from math modal - legacy)\n    const wrappedMathPattern =\n      /<span[^>]*class=\"math-expression\"[^>]*data-math=\"([^\"]*)\"[^>]*>.*?<\\/span>/g;\n    processedContent = processedContent.replaceAll(\n      wrappedMathPattern,\n      (match, latex) => {\n        const id = mathParts.length;\n        mathParts.push({\n          id,\n          type: 'inline',\n          latex: cleanLatex(decodeHtmlEntities(latex)),\n        });\n        return `<span data-math-id=\"${id}\"></span>`;\n      }\n    );\n\n    // Step 3: Handle raw $$...$$ expressions (manual input or saved content) - BEFORE single $\n    const doubleDollarPattern = /(?<!\\\\)\\$\\$([\\s\\S]+?)\\$\\$/g;\n    processedContent = processedContent.replaceAll(\n      doubleDollarPattern,\n      (match, latex) => {\n        const id = mathParts.length;\n        mathParts.push({\n          id,\n          type: 'block',\n          latex: cleanLatex(latex),\n        });\n        return `<span data-math-id=\"${id}\"></span>`;\n      }\n    );\n\n    // Step 4: Handle single $...$ expressions for inline math\n    const singleDollarPattern = /(?<!\\\\)\\$([\\s\\S]+?)\\$/g;\n    processedContent = processedContent.replaceAll(\n      singleDollarPattern,\n      (match, latex) => {\n        const id = mathParts.length;\n        mathParts.push({\n          id,\n          type: 'inline',\n          latex: cleanLatex(latex),\n        });\n        return `<span data-math-id=\"${id}\"></span>`;\n      }\n    );\n\n    // Step 5: Handle <latex>...</latex> tags for inline math\n    const latexTagPattern =\n      /(?:<latex>|&lt;latex&gt;)([\\s\\S]*?)(?:<\\/latex>|&lt;\\/latex&gt;)/g;\n    processedContent = processedContent.replaceAll(\n      latexTagPattern,\n      (match, latex) => {\n        const id = mathParts.length;\n        mathParts.push({\n          id,\n          type: 'inline',\n          latex: cleanLatex(latex),\n        });\n        return `<span data-math-id=\"${id}\"></span>`;\n      }\n    );\n\n    // Step 6: Handle standalone LaTeX environments (align, equation, pmatrix, etc.) for block math\n    const latexEnvPattern = /\\\\begin\\{([^}]+)\\}([\\s\\S]*?)\\\\end\\{\\1\\}/g;\n    processedContent = processedContent.replaceAll(latexEnvPattern, (match) => {\n      const id = mathParts.length;\n      mathParts.push({\n        id,\n        type: 'block',\n        latex: cleanLatex(match),\n      });\n      return `<span data-math-id=\"${id}\"></span>`;\n    });\n\n    // Sanitize the HTML with placeholders\n    const sanitizedContent = sanitizeHtml(processedContent);\n\n    // Default error renderer\n    const defaultErrorRenderer = (latex: string) => (\n      <span className=\"text-red-600\">Math Error: {latex}</span>\n    );\n\n    const errorRenderer = onError || defaultErrorRenderer;\n\n    // Parse HTML and replace math placeholders with React components\n    const options: HTMLReactParserOptions = {\n      replace: createMathReplacer(mathParts, errorRenderer),\n    };\n\n    return <>{parse(sanitizedContent, options)}</>;\n  };\n\n  return (\n    <div\n      className={cn('whitespace-pre-wrap leading-relaxed', className)}\n      style={style}\n    >\n      {renderContentWithMath(content)}\n    </div>\n  );\n};\n\nexport default LatexRenderer;\n"],"mappings":"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","names":[]}