core/adapters/diagram.adapter.ts
core/adapters/diagram.adapter.ts is a file in GovLab Docs. 58 lines of code and 16 definitions.
import { JSDOM } from "jsdom";
import type { Mermaid } from "mermaid";
import type { MermaidParser } from "#types/diagram.types";
const GLOBAL_KEYS: readonly string[] = ["DOMParser", "Node", "SVGElement", "HTMLElement", "getComputedStyle"];
const BLANK_PAGE = "<!DOCTYPE html><html><body></body></html>";
const LINE_BREAK = "\n";
const loaded: { mermaid?: Promise<Mermaid> } = {};
const noop = function noop(): null {
return null;
};
const installGlobals = function installGlobals(dom: JSDOM): void {
const view = dom.window;
Reflect.set(globalThis, "window", view);
Reflect.set(globalThis, "document", Reflect.get(view, "document"));
for (const key of GLOBAL_KEYS) {
Reflect.set(globalThis, key, Reflect.get(view, key));
}
if (!Reflect.has(globalThis, "navigator")) {
Object.defineProperty(globalThis, "navigator", { configurable: true, value: Reflect.get(view, "navigator") });
}
if (!Reflect.has(view, "matchMedia")) {
Reflect.set(view, "matchMedia", () => ({ addListener: noop, matches: false, removeListener: noop }));
}
};
const loadParser = async function loadParser(): Promise<Mermaid> {
installGlobals(new JSDOM(BLANK_PAGE, { pretendToBeVisual: true }));
const { default: mermaid } = await import("mermaid");
const { default: elkLayouts } = await import("@mermaid-js/layout-elk");
mermaid.registerLayoutLoaders(elkLayouts);
mermaid.initialize({ securityLevel: "strict", startOnLoad: false });
return mermaid;
};
const firstLine = function firstLine(message: string): string {
const lineBreak = message.indexOf(LINE_BREAK);
return lineBreak === -1 ? message.trim() : message.slice(0, lineBreak).trim();
};
const messageOf = function messageOf(error: unknown): string {
return error instanceof Error ? error.message : String(error);
};
export const createMermaidParser = async function createMermaidParser(): Promise<MermaidParser> {
try {
loaded.mermaid ??= loadParser();
const mermaid = await loaded.mermaid;
return {
available: true,
async parse(code: string): Promise<string | null> {
try {
await mermaid.parse(code);
return null;
} catch (error) {
return firstLine(messageOf(error));
}
},
};
} catch (error) {
return { available: false, reason: messageOf(error) };
}
};