- demo iframe: scrolling=no (the bridge auto-sizes; a scrollable iframe trapped the wheel) + content-box so the bridge height is the viewport - figures: svgNaturalWidth hug + center (w-fit max-w-full mx-auto), full-width fallback for viewBox-only svgs - fullscreen: MermaidOverlay figure mode (raw svg, white stage, invert carried); openFigure context; figureFocus rides the mermaid Esc layer - downloads: figure.svg + <slug>.html (raw pre-bridge), shared download.ts - invert: manual ContrastIcon toggle on both cards — invert(1) hue-rotate(180deg) on the white-bearing element, default off, no detection, no theme wiring (owner rulings 2026-10-07) 1433 tests green; live smoke passed (hug/center measured, filters verified, downloads fired, Esc closed; wheel-chaining structurally sound)
33 lines
1.1 KiB
TypeScript
33 lines
1.1 KiB
TypeScript
/**
|
|
* Artifact download helpers (release polish, 2026-10-07): the tiny
|
|
* save-a-blob seam shared by the demo + figure cards, plus the filename
|
|
* slug. The slug is pure (test-pinned); downloadFile touches the DOM and
|
|
* only runs on click.
|
|
*/
|
|
|
|
/** Slugify a demo title into a filename stem — lowercase, accents folded,
|
|
* runs of non-alphanumerics collapsed to "-", trimmed, capped at 64
|
|
* chars. Empty/fully-symbolic titles fall back to "demo". */
|
|
export function slugFilename(title: string): string {
|
|
const slug = title
|
|
.toLowerCase()
|
|
.normalize("NFKD")
|
|
.replace(/[\u0300-\u036f]/g, "")
|
|
.replace(/[^a-z0-9]+/g, "-")
|
|
.replace(/^-+|-+$/g, "")
|
|
.slice(0, 64);
|
|
return slug || "demo";
|
|
}
|
|
|
|
/** Save text as a downloaded file. The blob URL is revoked right after the
|
|
* click — Chromium keeps the download alive past the revoke. */
|
|
export function downloadFile(name: string, text: string, mime: string): void {
|
|
const blob = new Blob([text], { type: mime });
|
|
const url = URL.createObjectURL(blob);
|
|
const a = document.createElement("a");
|
|
a.href = url;
|
|
a.download = name;
|
|
a.click();
|
|
URL.revokeObjectURL(url);
|
|
}
|