fix(insights): notes markdown + equations LaTeX rendues correctement
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:
@@ -29,6 +29,8 @@ import { getNoteById } from '@/app/actions/notes'
|
|||||||
import type { Note as NoteFull } from '@/lib/types'
|
import type { Note as NoteFull } from '@/lib/types'
|
||||||
import { X, Maximize2 } from 'lucide-react'
|
import { X, Maximize2 } from 'lucide-react'
|
||||||
import DOMPurify from 'dompurify'
|
import DOMPurify from 'dompurify'
|
||||||
|
import { MarkdownContent } from '@/components/markdown-content'
|
||||||
|
import 'katex/dist/katex.min.css'
|
||||||
|
|
||||||
const NetworkGraph = dynamic(
|
const NetworkGraph = dynamic(
|
||||||
() => import('@/components/network-graph').then(m => ({ default: m.NetworkGraph })),
|
() => import('@/components/network-graph').then(m => ({ default: m.NetworkGraph })),
|
||||||
@@ -277,6 +279,22 @@ export default function InsightsPage() {
|
|||||||
|
|
||||||
const closePeek = () => setPeekNote(null)
|
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 = () => {
|
const openPeekFully = () => {
|
||||||
if (!peekNote) return
|
if (!peekNote) return
|
||||||
router.push(`/home?openNote=${peekNote.id}`)
|
router.push(`/home?openNote=${peekNote.id}`)
|
||||||
@@ -932,7 +950,11 @@ export default function InsightsPage() {
|
|||||||
{peekNote.title || t('insightsView.unknownNote')}
|
{peekNote.title || t('insightsView.unknownNote')}
|
||||||
</h2>
|
</h2>
|
||||||
{peekNote.content ? (
|
{peekNote.content ? (
|
||||||
|
peekNote.isMarkdown ? (
|
||||||
|
<MarkdownContent content={peekNote.content} className="prose-lg" />
|
||||||
|
) : (
|
||||||
<div
|
<div
|
||||||
|
id="insights-peek-content"
|
||||||
dir="auto"
|
dir="auto"
|
||||||
className="editor-body prose prose-lg dark:prose-invert max-w-none leading-relaxed text-ink dark:text-dark-ink
|
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
|
[&_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
|
[&_hr]:border-border [&_hr]:my-6
|
||||||
[&_[data-callout-type]]:p-4 [&_[data-callout-type]]:rounded-lg [&_[data-callout-type]]:my-4
|
[&_[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']]: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
|
[&_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"
|
|
||||||
dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(peekNote.content) }}
|
dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(peekNote.content) }}
|
||||||
/>
|
/>
|
||||||
|
)
|
||||||
) : (
|
) : (
|
||||||
<p className="text-sm text-concrete italic">—</p>
|
<p className="text-sm text-concrete italic">—</p>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user