aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/packages/docs/app/components/mermaid.tsx
diff options
context:
space:
mode:
authorNtskwK <natsukawa247@outlook.com>2026-03-26 10:08:23 +0800
committerNtskwK <natsukawa247@outlook.com>2026-03-26 10:08:23 +0800
commit14832b994f2ad504c70f5e101ddfa96018e657d6 (patch)
tree4ece6bc8421ff58915a0a17a4d981a9a30a43a68 /packages/docs/app/components/mermaid.tsx
parent8f2f72a857083122bce14277089ebccd64312061 (diff)
downloadDropOut-14832b994f2ad504c70f5e101ddfa96018e657d6.tar.gz
DropOut-14832b994f2ad504c70f5e101ddfa96018e657d6.zip
chore(docs): refactor Mermaid component to render charts asynchronously and improve security
Diffstat (limited to 'packages/docs/app/components/mermaid.tsx')
-rw-r--r--packages/docs/app/components/mermaid.tsx29
1 files changed, 20 insertions, 9 deletions
diff --git a/packages/docs/app/components/mermaid.tsx b/packages/docs/app/components/mermaid.tsx
index d408aad..04d89d9 100644
--- a/packages/docs/app/components/mermaid.tsx
+++ b/packages/docs/app/components/mermaid.tsx
@@ -6,25 +6,36 @@ import { useEffect, useRef } from "react";
mermaid.initialize({
startOnLoad: false,
theme: "default",
+ securityLevel: "strict",
});
export function Mermaid({ chart }: { chart: string }) {
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
- if (ref.current) {
- ref.current.innerHTML = chart;
- mermaid.run({
- nodes: [ref.current],
- });
- }
+ const renderChart = async () => {
+ if (!ref.current) return;
+
+ try {
+ const id = `mermaid-${Math.random().toString(36).slice(2, 9)}`;
+ const { svg } = await mermaid.render(id, chart);
+ // Use innerHTML with sanitized SVG from mermaid.render
+ // biome-disable-next-line security/noInnerHtml
+ ref.current.innerHTML = svg;
+ } catch {
+ // Invalid chart definition, render nothing
+ if (ref.current) {
+ ref.current.innerHTML = "";
+ }
+ }
+ };
+
+ renderChart();
}, [chart]);
return (
<div className="not-prose my-6">
- <div ref={ref} className="mermaid">
- {chart}
- </div>
+ <div ref={ref} className="mermaid" />
</div>
);
}