Add mermaid suport
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
"@radix-ui/react-tabs": "^1.1.13",
|
||||
"clsx": "^2.1.1",
|
||||
"cmdk": "^1.1.1",
|
||||
"mermaid": "^11.13.0",
|
||||
"react-dropzone": "^14.3.8",
|
||||
"react-intersection-observer": "^9.16.0",
|
||||
"react-markdown": "^10.1.0",
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { isValidElement } from "react";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import rehypeRaw from "rehype-raw";
|
||||
import remarkGfm from "remark-gfm";
|
||||
|
||||
import { MermaidDiagram } from "./MermaidDiagram";
|
||||
|
||||
type Props = {
|
||||
content: string;
|
||||
};
|
||||
@@ -23,19 +26,31 @@ export function Markdown({ content }: Props) {
|
||||
{children}
|
||||
</a>
|
||||
),
|
||||
pre: ({ children, ...props }) => (
|
||||
<pre
|
||||
className="border border-border-solid rounded p-4 bg-transparent font-mono text-sm overflow-x-auto text-inherit"
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</pre>
|
||||
),
|
||||
code: ({ children, ...props }) => (
|
||||
<code className="font-mono text-sm text-inherit" {...props}>
|
||||
{children}
|
||||
</code>
|
||||
),
|
||||
pre: ({ children, ...props }) => {
|
||||
const child = isValidElement<{
|
||||
className?: string;
|
||||
children?: string;
|
||||
}>(children)
|
||||
? children
|
||||
: null;
|
||||
|
||||
if (
|
||||
child?.type === "code"
|
||||
&& child.props.className === "language-mermaid"
|
||||
&& typeof child.props.children === "string"
|
||||
) {
|
||||
return <MermaidDiagram chart={child.props.children} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<pre
|
||||
className="border border-border-solid rounded p-4 bg-transparent font-mono text-sm overflow-x-auto text-inherit"
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</pre>
|
||||
);
|
||||
},
|
||||
}}
|
||||
>
|
||||
{content}
|
||||
|
||||
51
packages/ui/src/Atoms/Markdown/MermaidDiagram.tsx
Normal file
51
packages/ui/src/Atoms/Markdown/MermaidDiagram.tsx
Normal file
@@ -0,0 +1,51 @@
|
||||
import mermaid from "mermaid";
|
||||
import { useEffect, useId, useState } from "react";
|
||||
|
||||
type Props = {
|
||||
chart: string;
|
||||
};
|
||||
|
||||
export function MermaidDiagram({ chart }: Props) {
|
||||
const id = useId().replace(/:/g, "");
|
||||
const [svg, setSvg] = useState<string | null>(null);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
|
||||
mermaid.initialize({ startOnLoad: false, theme: "neutral" });
|
||||
|
||||
mermaid
|
||||
.render(`mermaid-${id}`, chart.trim())
|
||||
.then((result) => {
|
||||
if (!cancelled) {
|
||||
setSvg(result.svg);
|
||||
setError(null);
|
||||
}
|
||||
})
|
||||
.catch((err: unknown) => {
|
||||
if (!cancelled) {
|
||||
setError(err instanceof Error ? err.message : String(err));
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [chart, id]);
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<pre className="border border-border-solid rounded p-4 bg-transparent font-mono text-sm overflow-x-auto text-inherit">
|
||||
<code>{chart}</code>
|
||||
</pre>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className="flex justify-center my-4"
|
||||
dangerouslySetInnerHTML={svg ? { __html: svg } : undefined}
|
||||
/>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user