({ code }: MermaidBlockProps)
| 88 | } |
| 89 | |
| 90 | export default function MermaidBlock({ code }: MermaidBlockProps) { |
| 91 | const containerRef = useRef<HTMLDivElement>(null) |
| 92 | const [isLoading, setIsLoading] = useState(false) |
| 93 | const [error, setError] = useState<string | null>(null) |
| 94 | const [isErrorExpanded, setIsErrorExpanded] = useState(false) |
| 95 | const { showCopyFeedback, copyWithFeedback } = useCopyToClipboard() |
| 96 | const { t } = useAppTranslation() |
| 97 | |
| 98 | // 1) Whenever `code` changes, mark that we need to re-render a new chart |
| 99 | useEffect(() => { |
| 100 | setIsLoading(true) |
| 101 | setError(null) |
| 102 | }, [code]) |
| 103 | |
| 104 | // 2) Debounce the actual parse/render |
| 105 | useDebounceEffect( |
| 106 | () => { |
| 107 | if (containerRef.current) { |
| 108 | containerRef.current.innerHTML = "" |
| 109 | } |
| 110 | |
| 111 | mermaid |
| 112 | .parse(code) |
| 113 | .then(() => { |
| 114 | const id = `mermaid-${Math.random().toString(36).substring(2)}` |
| 115 | return mermaid.render(id, code) |
| 116 | }) |
| 117 | .then(({ svg }) => { |
| 118 | if (containerRef.current) { |
| 119 | containerRef.current.innerHTML = svg |
| 120 | } |
| 121 | }) |
| 122 | .catch((err) => { |
| 123 | console.warn("Mermaid parse/render failed:", err) |
| 124 | setError(err.message || "Failed to render Mermaid diagram") |
| 125 | }) |
| 126 | .finally(() => { |
| 127 | setIsLoading(false) |
| 128 | }) |
| 129 | }, |
| 130 | 500, // Delay 500ms |
| 131 | [code], // Dependencies for scheduling |
| 132 | ) |
| 133 | |
| 134 | /** |
| 135 | * Called when user clicks the rendered diagram. |
| 136 | * Converts the <svg> to a PNG and sends it to the extension. |
| 137 | */ |
| 138 | const handleClick = async () => { |
| 139 | if (!containerRef.current) return |
| 140 | const svgEl = containerRef.current.querySelector("svg") |
| 141 | if (!svgEl) return |
| 142 | |
| 143 | try { |
| 144 | const pngDataUrl = await svgToPng(svgEl) |
| 145 | vscode.postMessage({ |
| 146 | type: "openImage", |
| 147 | text: pngDataUrl, |
nothing calls this directly
no test coverage detected