'use client'; import { useEditor, EditorContent } from '@tiptap/react'; import StarterKit from '@tiptap/starter-kit'; import Underline from '@tiptap/extension-underline'; import Link from '@tiptap/extension-link'; import Image from '@tiptap/extension-image'; import mermaid from 'mermaid'; import { useEffect, useRef } from 'react'; import { cn } from '@/lib/utils'; mermaid.initialize({ startOnLoad: false, theme: 'neutral' }); const emptyDoc = { type: 'doc', content: [] }; interface LessonContentViewerProps { content: Record | null; className?: string; } export function LessonContentViewer({ content, className }: LessonContentViewerProps) { const containerRef = useRef(null); const editor = useEditor({ extensions: [ StarterKit.configure({ heading: { levels: [1, 2, 3] }, codeBlock: { HTMLAttributes: (node: { attrs: { language?: string } }) => node.attrs.language === 'mermaid' ? { class: 'mermaid rounded-lg p-4 bg-muted min-h-[80px]', 'data-language': 'mermaid' } : { class: 'rounded-xl bg-muted p-5 font-mono text-sm border', 'data-language': node.attrs.language || '' }, }, }), Underline, Link.configure({ openOnClick: true, HTMLAttributes: { class: 'text-primary underline underline-offset-2 hover:text-primary/80 transition-colors' }, }), Image.configure({ HTMLAttributes: { class: 'rounded-xl max-w-full h-auto shadow-sm my-6' } }), ], content: content ?? emptyDoc, editable: false, editorProps: { attributes: { class: 'outline-none text-foreground', }, }, }); useEffect(() => { if (editor && content) { editor.commands.setContent(content); } }, [content, editor]); useEffect(() => { if (!containerRef.current || !content) return; const mermaidNodes = containerRef.current.querySelectorAll('pre[data-language="mermaid"]'); if (mermaidNodes.length === 0) return; mermaid.run({ nodes: Array.from(mermaidNodes) as HTMLElement[], suppressErrors: true }).catch(() => {}); }, [content]); if (!editor) return null; return (
); }