From 8d8c111a6a77eec1378f99f28b88d94db633f4fd Mon Sep 17 00:00:00 2001 From: Vladimir Urushev Date: Sun, 21 Jun 2026 19:51:57 +0200 Subject: [PATCH] fix: polyfill global CSSStyleSheet for mermaid rendering --- src/acemir-cssom.d.ts | 3 +++ src/mermaid/render.ts | 17 +++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 src/acemir-cssom.d.ts diff --git a/src/acemir-cssom.d.ts b/src/acemir-cssom.d.ts new file mode 100644 index 0000000..e846a74 --- /dev/null +++ b/src/acemir-cssom.d.ts @@ -0,0 +1,3 @@ +// @acemir/cssom is a transitive dependency (via jsdom) and ships no types. +// We touch it only to borrow its real CSSStyleSheet class for a global polyfill (see mermaid/render.ts). +declare module '@acemir/cssom' diff --git a/src/mermaid/render.ts b/src/mermaid/render.ts index e904a57..8fb06f0 100644 --- a/src/mermaid/render.ts +++ b/src/mermaid/render.ts @@ -32,6 +32,22 @@ async function loadMermaid() { const mod = await import('isomorphic-mermaid') mermaid = mod.default + // @acemir/cssom (jsdom's CSS engine, pulled in by isomorphic-mermaid) reads a *bare global* + // `CSSStyleSheet` while rendering. isomorphic-mermaid swaps `window` for svgdom's, which never + // defines it, so depending on platform/timing the global is missing -> intermittent + // `ReferenceError: CSSStyleSheet is not defined` (flaky in CI, rarely local). Define it once, + // up front, from the same cssom jsdom uses; fall back to a stub if that package ever moves. + // biome-ignore lint/suspicious/noExplicitAny: patching globals for the svgdom render env + const g = globalThis as any + if (typeof g.CSSStyleSheet === 'undefined') { + try { + const cssom = await import('@acemir/cssom') + g.CSSStyleSheet = cssom.CSSStyleSheet ?? cssom.default?.CSSStyleSheet ?? class CSSStyleSheet {} + } catch { + g.CSSStyleSheet = class CSSStyleSheet {} + } + } + // Patch window with everything elkjs needs (GWT compatibility) // isomorphic-mermaid sets window = svgWindow which lacks these // biome-ignore lint/suspicious/noExplicitAny: patching global window for GWT @@ -49,6 +65,7 @@ async function loadMermaid() { win.setInterval = setInterval win.clearInterval = clearInterval win.console = console + win.CSSStyleSheet = g.CSSStyleSheet } // Load and register ELK layout engine