import { useEffect } from 'react'; import hljs from 'highlight.js'; import katex from 'katex'; import 'katex/dist/katex.min.css'; function renderMath(element: HTMLElement) { const delimiters = [ { left: '$$', right: '$$', display: true }, { left: '$', right: '$', display: false }, { left: '\\(', right: '\\)', display: false }, { left: '\\[', right: '\\]', display: true }, ]; const walk = (node: Node) => { if (node.nodeType === Node.ELEMENT_NODE) { const el = node as HTMLElement; if (el.tagName === 'CODE' || el.tagName === 'PRE') return; for (const child of Array.from(el.childNodes)) walk(child); } else if (node.nodeType === Node.TEXT_NODE) { const text = node.textContent || ''; for (const { left, right, display } of delimiters) { const idx = text.indexOf(left); if (idx === -1) continue; const end = text.indexOf(right, idx + left.length); if (end === -1) continue; const tex = text.slice(idx + left.length, end); try { const rendered = katex.renderToString(tex, { displayMode: display, throwOnError: false }); const span = document.createElement('span'); span.innerHTML = rendered; const range = document.createRange(); range.setStart(node, idx); range.setEnd(node, end + right.length); range.deleteContents(); range.insertNode(span); } catch { /* skip invalid tex */ } return; } } }; for (let i = 0; i < 3; i++) walk(element); } interface Props { containerId: string; } export default function PostEnhancer({ containerId }: Props) { useEffect(() => { const el = document.getElementById(containerId); if (!el) return; renderMath(el); el.querySelectorAll('pre code').forEach((block) => { hljs.highlightElement(block); }); }, [containerId]); return null; }