fix(preview): pin SVG to intrinsic size for all diagram types
The previous fix only disabled useMaxWidth for flowcharts, so sequence (and other) diagrams still rendered responsively and fit shrank them to a tiny speck. Normalise every rendered SVG to its viewBox pixel size (stripping width:100% / max-width) in the render path, so fit/zoom is exact regardless of diagram type. Drops the now-redundant per-type flowchart flag.
This commit is contained in:
@@ -15,10 +15,37 @@ function configure(theme: string) {
|
||||
theme: theme as any,
|
||||
securityLevel: 'loose',
|
||||
fontFamily: 'inherit',
|
||||
// Render at the diagram's intrinsic pixel size (not responsive 100% width)
|
||||
// so the preview's own zoom/fit maths stay exact — otherwise a large
|
||||
// flowchart is scaled down by the SVG *and* again by fit, ending up tiny.
|
||||
flowchart: { useMaxWidth: false, htmlLabels: true },
|
||||
flowchart: { htmlLabels: true },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Force an SVG to its intrinsic pixel size (from the viewBox), stripping the
|
||||
* responsive `width:100%` / `max-width` that Mermaid emits by default.
|
||||
*
|
||||
* Mermaid's `useMaxWidth` makes diagrams shrink to their container, but the
|
||||
* preview applies its own zoom/fit transform — so a responsive SVG ends up
|
||||
* scaled down twice and renders tiny. Pinning the laid-out size to the viewBox
|
||||
* keeps fit/zoom exact for *every* diagram type (sequence, class, …), which
|
||||
* per-type `useMaxWidth` flags can't guarantee uniformly.
|
||||
*/
|
||||
function pinSize(svg: string): string {
|
||||
const vb = svg.match(/viewBox="([\d.\s-]+)"/);
|
||||
if (!vb) return svg;
|
||||
const p = vb[1].trim().split(/\s+/).map(Number);
|
||||
if (p.length !== 4 || p.some(Number.isNaN)) return svg;
|
||||
const [, , w, h] = p;
|
||||
return svg.replace(/<svg\b[^>]*>/, (tag) => {
|
||||
let t = tag.replace(/\s(?:width|height)="[^"]*"/g, '');
|
||||
t = t.replace(/\sstyle="([^"]*)"/, (_m, s: string) => {
|
||||
const cleaned = s
|
||||
.split(';')
|
||||
.map((d) => d.trim())
|
||||
.filter((d) => d && !/^(?:max-width|width)\s*:/i.test(d))
|
||||
.join('; ');
|
||||
return cleaned ? ` style="${cleaned}"` : '';
|
||||
});
|
||||
return t.replace(/<svg\b/, `<svg width="${w}" height="${h}"`);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -33,7 +60,7 @@ export async function renderMermaid(code: string, theme: string): Promise<Render
|
||||
const id = `mmx-render-${++renderSeq}`;
|
||||
try {
|
||||
const { svg } = await mermaid.render(id, code);
|
||||
return { svg };
|
||||
return { svg: pinSize(svg) };
|
||||
} catch (e) {
|
||||
return { error: e instanceof Error ? e.message : String(e) };
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user