71 lines
2.7 KiB
JavaScript
71 lines
2.7 KiB
JavaScript
import mermaid from "mermaid";
|
|
import { MERMAID_CONFIG } from "./constants.js";
|
|
import { encodeEntities } from "./utils.js";
|
|
import { parseMermaidFlowChartDiagram } from "./parser/flowchart.js";
|
|
import { parseMermaidSequenceDiagram } from "./parser/sequence.js";
|
|
import { parseMermaidClassDiagram } from "./parser/class.js";
|
|
// Fallback to Svg
|
|
const convertSvgToGraphImage = (svgContainer) => {
|
|
// Extract SVG width and height
|
|
// TODO: make width and height change dynamically based on user's screen dimension
|
|
const svgEl = svgContainer.querySelector("svg");
|
|
if (!svgEl) {
|
|
throw new Error("SVG element not found");
|
|
}
|
|
const rect = svgEl.getBoundingClientRect();
|
|
const width = rect.width;
|
|
const height = rect.height;
|
|
// Set width and height explictly since in firefox it gets set to 0
|
|
// if the width and height are not expilcitly set
|
|
// eg in some cases like er Diagram, gnatt, width and height is set as 100%
|
|
// which sets the dimensions as 0 in firefox and thus the diagram isn't rendered
|
|
svgEl.setAttribute("width", `${width}`);
|
|
svgEl.setAttribute("height", `${height}`);
|
|
// Convert SVG to image
|
|
const mimeType = "image/svg+xml";
|
|
const decoded = unescape(encodeURIComponent(svgEl.outerHTML));
|
|
const base64 = btoa(decoded);
|
|
const dataURL = `data:image/svg+xml;base64,${base64}`;
|
|
const graphImage = {
|
|
type: "graphImage",
|
|
mimeType,
|
|
dataURL,
|
|
width,
|
|
height,
|
|
};
|
|
return graphImage;
|
|
};
|
|
export const parseMermaid = async (definition, config = MERMAID_CONFIG) => {
|
|
mermaid.initialize({ ...MERMAID_CONFIG, ...config });
|
|
// Parse the diagram
|
|
const diagram = await mermaid.mermaidAPI.getDiagramFromText(encodeEntities(definition));
|
|
// Render the SVG diagram
|
|
const { svg } = await mermaid.render("mermaid-to-excalidraw", definition);
|
|
// Append Svg to DOM
|
|
const svgContainer = document.createElement("div");
|
|
svgContainer.setAttribute("style", `opacity: 0; position: relative; z-index: -1;`);
|
|
svgContainer.innerHTML = svg;
|
|
svgContainer.id = "mermaid-diagram";
|
|
document.body.appendChild(svgContainer);
|
|
let data;
|
|
switch (diagram.type) {
|
|
case "flowchart-v2": {
|
|
data = parseMermaidFlowChartDiagram(diagram, svgContainer);
|
|
break;
|
|
}
|
|
case "sequence": {
|
|
data = parseMermaidSequenceDiagram(diagram, svgContainer);
|
|
break;
|
|
}
|
|
case "classDiagram": {
|
|
data = parseMermaidClassDiagram(diagram, svgContainer);
|
|
break;
|
|
}
|
|
// fallback to image if diagram type not-supported
|
|
default: {
|
|
data = convertSvgToGraphImage(svgContainer);
|
|
}
|
|
}
|
|
svgContainer.remove();
|
|
return data;
|
|
};
|