From 43a7647a9c4c3e616d4d69e407f585a8de2a713f Mon Sep 17 00:00:00 2001 From: Yandrik Date: Wed, 9 Jul 2025 13:59:21 +0200 Subject: [PATCH] feat: add mermaid diagram support --- App.tsx | 73 ++- make-practiceapp-deployready.md | 142 +++++ package.json | 1 + pnpm-lock.yaml | 1001 +++++++++++++++++++++++++++++++ 4 files changed, 1215 insertions(+), 2 deletions(-) diff --git a/App.tsx b/App.tsx index ab4ea8d..b1909a5 100644 --- a/App.tsx +++ b/App.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useCallback, useMemo } from 'react'; +import React, { useState, useEffect, useCallback, useMemo, useRef } from 'react'; import { Dialog } from "@headlessui/react"; import { Cog6ToothIcon } from "@heroicons/react/24/outline"; import { Exercise, CheckResult, ExercisePartType } from './types'; @@ -18,6 +18,7 @@ import Editor from 'react-simple-code-editor'; import Prism from 'prismjs/components/prism-core'; import 'prismjs/components/prism-clike'; import 'prismjs/components/prism-c'; +import mermaid from 'mermaid'; // --- GEMINI API SETUP & HELPERS --- @@ -167,6 +168,68 @@ const TextAreaEditor: React.FC<{ ) }; +const MermaidDiagram: React.FC<{ value: string; onChange: (value: string) => void; placeholder?: string }> = ({ value, onChange, placeholder }) => { + const [diagramHtml, setDiagramHtml] = useState(''); + const [error, setError] = useState(''); + const renderCountRef = useRef(0); + + useEffect(() => { + mermaid.initialize({ + startOnLoad: false, + theme: 'default', + securityLevel: 'loose' + }); + }, []); + + useEffect(() => { + if (value.trim()) { + const renderDiagram = async () => { + try { + setError(''); + renderCountRef.current += 1; + const uniqueId = `mermaid-diagram-${renderCountRef.current}`; + const { svg } = await mermaid.render(uniqueId, value); + setDiagramHtml(svg); + } catch (err) { + setError(err instanceof Error ? err.message : 'Mermaid diagram rendering failed'); + setDiagramHtml(''); + } + }; + renderDiagram(); + } else { + setDiagramHtml(''); + setError(''); + } + }, [value]); + + return ( +
+