diff --git a/web/src/components/MemoContent/CodeBlock.tsx b/web/src/components/MemoContent/CodeBlock.tsx index e22272590..5c53440e3 100644 --- a/web/src/components/MemoContent/CodeBlock.tsx +++ b/web/src/components/MemoContent/CodeBlock.tsx @@ -1,6 +1,7 @@ import { CheckIcon, CopyIcon } from "lucide-react"; import { useState } from "react"; import { cn } from "@/lib/utils"; +import { MermaidBlock } from "./MermaidBlock"; interface PreProps { children?: React.ReactNode; @@ -19,6 +20,15 @@ export const CodeBlock = ({ children, className, ...props }: PreProps) => { const match = /language-(\w+)/.exec(codeClassName); const language = match ? match[1] : ""; + // If it's a mermaid block, render with MermaidBlock component + if (language === "mermaid") { + return ( + + {children} + + ); + } + const handleCopy = async () => { try { await navigator.clipboard.writeText(codeContent); diff --git a/web/src/components/MemoContent/MermaidBlock.tsx b/web/src/components/MemoContent/MermaidBlock.tsx new file mode 100644 index 000000000..ca3bb575a --- /dev/null +++ b/web/src/components/MemoContent/MermaidBlock.tsx @@ -0,0 +1,69 @@ +import mermaid from "mermaid"; +import { useEffect, useRef, useState } from "react"; +import { cn } from "@/lib/utils"; + +interface MermaidBlockProps { + children?: React.ReactNode; + className?: string; +} + +// Initialize mermaid with default configuration +mermaid.initialize({ + startOnLoad: false, + theme: "default", + securityLevel: "strict", + fontFamily: "inherit", +}); + +export const MermaidBlock = ({ children, className }: MermaidBlockProps) => { + const containerRef = useRef(null); + const [svg, setSvg] = useState(""); + const [error, setError] = useState(""); + + // Extract the code element and its content + const codeElement = children as React.ReactElement; + const codeContent = String(codeElement?.props?.children || "").replace(/\n$/, ""); + + useEffect(() => { + const renderDiagram = async () => { + if (!codeContent || !containerRef.current) { + return; + } + + try { + // Generate a unique ID for this diagram + const id = `mermaid-${Math.random().toString(36).substring(7)}`; + + // Render the mermaid diagram + const { svg: renderedSvg } = await mermaid.render(id, codeContent); + setSvg(renderedSvg); + setError(""); + } catch (err) { + console.error("Failed to render mermaid diagram:", err); + setError(err instanceof Error ? err.message : "Failed to render diagram"); + } + }; + + renderDiagram(); + }, [codeContent]); + + // If there's an error, fall back to showing the code + if (error) { + return ( +
+
Mermaid Error: {error}
+
+          {codeContent}
+        
+
+ ); + } + + return ( +
+ ); +};