feat: complete MDX migration for blog, fix diagram fidelity and refactor styling architecture
This commit is contained in:
@@ -5,22 +5,67 @@ import mermaid from "mermaid";
|
||||
import { DiagramShareButton } from "./DiagramShareButton";
|
||||
|
||||
interface MermaidProps {
|
||||
graph: string;
|
||||
graph?: string;
|
||||
children?: React.ReactNode;
|
||||
id?: string;
|
||||
title?: string;
|
||||
showShare?: boolean;
|
||||
fontSize?: string;
|
||||
nodeFontSize?: string;
|
||||
labelFontSize?: string;
|
||||
actorFontSize?: string;
|
||||
messageFontSize?: string;
|
||||
noteFontSize?: string;
|
||||
titleFontSize?: string;
|
||||
sectionFontSize?: string;
|
||||
legendFontSize?: string;
|
||||
}
|
||||
|
||||
export const Mermaid: React.FC<MermaidProps> = ({
|
||||
graph,
|
||||
children,
|
||||
id: providedId,
|
||||
title,
|
||||
showShare = false,
|
||||
fontSize = "16px",
|
||||
nodeFontSize,
|
||||
labelFontSize,
|
||||
actorFontSize,
|
||||
messageFontSize,
|
||||
noteFontSize,
|
||||
titleFontSize,
|
||||
sectionFontSize,
|
||||
legendFontSize,
|
||||
}) => {
|
||||
const [id, setId] = useState<string | null>(null);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const [svgContent, setSvgContent] = useState<string>("");
|
||||
|
||||
// Extract text from React children nodes (MDX parses multi-line content as React nodes)
|
||||
const extractTextFromChildren = (node: React.ReactNode): string => {
|
||||
if (typeof node === 'string') return node;
|
||||
if (typeof node === 'number') return String(node);
|
||||
if (Array.isArray(node)) return node.map(extractTextFromChildren).join('\n');
|
||||
if (React.isValidElement(node)) {
|
||||
const props = node.props as { children?: React.ReactNode };
|
||||
if (props.children) {
|
||||
return extractTextFromChildren(props.children);
|
||||
}
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
const rawGraph = graph || extractTextFromChildren(children) || "";
|
||||
|
||||
// MDXRemote double-escapes \n in plain string props (e.g., "graph TD\\nA-->B" becomes "graph TD\\\\nA-->B")
|
||||
// We need to unescape these back to real newlines for Mermaid to parse
|
||||
const sanitizedGraph = rawGraph
|
||||
.trim()
|
||||
.replace(/^`+|`+$/g, '')
|
||||
.replace(/\\n/g, '\n')
|
||||
.replace(/\\"/g, '"')
|
||||
.replace(/\\'/g, "'");
|
||||
|
||||
useEffect(() => {
|
||||
setId(
|
||||
providedId || `mermaid-${Math.random().toString(36).substring(2, 11)}`,
|
||||
@@ -63,7 +108,15 @@ export const Mermaid: React.FC<MermaidProps> = ({
|
||||
|
||||
// Font
|
||||
fontFamily: "Inter, system-ui, sans-serif",
|
||||
fontSize: "14px",
|
||||
fontSize: fontSize,
|
||||
nodeFontSize: nodeFontSize || fontSize,
|
||||
labelFontSize: labelFontSize || fontSize,
|
||||
actorFontSize: actorFontSize || fontSize,
|
||||
messageFontSize: messageFontSize || fontSize,
|
||||
noteFontSize: noteFontSize || fontSize,
|
||||
titleFontSize: titleFontSize || "20px",
|
||||
sectionFontSize: sectionFontSize || fontSize,
|
||||
legendFontSize: legendFontSize || fontSize,
|
||||
|
||||
// Pie Chart Colors - High Contrast Industrial Palette
|
||||
pie1: "#0f172a", // Deep Navy
|
||||
@@ -84,14 +137,21 @@ export const Mermaid: React.FC<MermaidProps> = ({
|
||||
|
||||
const render = async () => {
|
||||
if (containerRef.current && id) {
|
||||
if (!sanitizedGraph || sanitizedGraph.trim() === "") {
|
||||
console.warn("Mermaid: Empty or invalid graph provided, skipping render.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const { svg } = await mermaid.render(`${id}-svg`, graph);
|
||||
const { svg } = await mermaid.render(`${id}-svg`, sanitizedGraph);
|
||||
containerRef.current.innerHTML = svg;
|
||||
setSvgContent(svg);
|
||||
setIsRendered(true);
|
||||
} catch (err) {
|
||||
console.error("Mermaid rendering failed:", err);
|
||||
setError("Failed to render diagram. Please check the syntax.");
|
||||
console.error("Graph that failed:", sanitizedGraph);
|
||||
const errorMessage = err instanceof Error ? err.message : String(err);
|
||||
setError(`Failed to render diagram: ${errorMessage}`);
|
||||
setIsRendered(true);
|
||||
}
|
||||
}
|
||||
@@ -100,7 +160,7 @@ export const Mermaid: React.FC<MermaidProps> = ({
|
||||
if (id) {
|
||||
render();
|
||||
}
|
||||
}, [graph, id]);
|
||||
}, [sanitizedGraph, id]);
|
||||
|
||||
if (!id) return null;
|
||||
|
||||
@@ -127,7 +187,7 @@ export const Mermaid: React.FC<MermaidProps> = ({
|
||||
{error}
|
||||
</div>
|
||||
) : (
|
||||
graph
|
||||
sanitizedGraph
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user