fix(insights): notes markdown + equations LaTeX rendues correctement
All checks were successful
CI / Lint, Unit Tests & Build (push) Successful in 5m27s
CI / Deploy production (on server) (push) Successful in 24s

Markdown notes:
- peekNote.isMarkdown → MarkdownContent (react-markdown + remarkMath + rehypeKatex)
- GFM tables, code blocks, etc. supportés nativement

Rich text notes:
- KaTeX CSS importé (katex.min.css)
- useEffect rend les equations data-latex via katex.renderToString
- math-equation-block → display mode
- inline-math → inline mode

KaTeX lazy-loadé (await import('katex')) — pas dans le bundle initial
This commit is contained in:
Antigravity
2026-07-04 23:16:53 +00:00
parent ee9d6650a2
commit 6536180e91

View File

@@ -29,6 +29,8 @@ import { getNoteById } from '@/app/actions/notes'
import type { Note as NoteFull } from '@/lib/types'
import { X, Maximize2 } from 'lucide-react'
import DOMPurify from 'dompurify'
import { MarkdownContent } from '@/components/markdown-content'
import 'katex/dist/katex.min.css'
const NetworkGraph = dynamic(
() => import('@/components/network-graph').then(m => ({ default: m.NetworkGraph })),
@@ -277,6 +279,22 @@ export default function InsightsPage() {
const closePeek = () => setPeekNote(null)
// Rendu KaTeX pour les notes richtext (data-latex)
useEffect(() => {
if (!peekNote || peekNote.isMarkdown) return
const timer = setTimeout(async () => {
const container = document.getElementById('insights-peek-content')
if (!container) return
const katex = (await import('katex')).default
container.querySelectorAll('.math-equation-block[data-latex], .inline-math[data-latex]').forEach(el => {
const latex = el.getAttribute('data-latex') || ''
const isDisplay = el.classList.contains('math-equation-block')
try { el.innerHTML = katex.renderToString(latex, { displayMode: isDisplay, throwOnError: false }) } catch {}
})
}, 100)
return () => clearTimeout(timer)
}, [peekNote])
const openPeekFully = () => {
if (!peekNote) return
router.push(`/home?openNote=${peekNote.id}`)
@@ -932,7 +950,11 @@ export default function InsightsPage() {
{peekNote.title || t('insightsView.unknownNote')}
</h2>
{peekNote.content ? (
peekNote.isMarkdown ? (
<MarkdownContent content={peekNote.content} className="prose-lg" />
) : (
<div
id="insights-peek-content"
dir="auto"
className="editor-body prose prose-lg dark:prose-invert max-w-none leading-relaxed text-ink dark:text-dark-ink
[&_h1]:text-2xl [&_h1]:font-serif [&_h1]:font-semibold [&_h1]:mt-8 [&_h1]:mb-4
@@ -953,10 +975,10 @@ export default function InsightsPage() {
[&_hr]:border-border [&_hr]:my-6
[&_[data-callout-type]]:p-4 [&_[data-callout-type]]:rounded-lg [&_[data-callout-type]]:my-4
[&_div[data-type='toggle-block']]:my-3
[&_div[data-type='toggle-block']_details]:rounded-lg [&_div[data-type='toggle-block']_details]:border [&_div[data-type='toggle-block']_details]:border-border
[&_[data-math]]:my-4 [&_[data-math]]:text-center"
[&_div[data-type='toggle-block']_details]:rounded-lg [&_div[data-type='toggle-block']_details]:border [&_div[data-type='toggle-block']_details]:border-border"
dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(peekNote.content) }}
/>
)
) : (
<p className="text-sm text-concrete italic"></p>
)}