import { DIAGRAM_STYLESHEET, diagramLocation } from "#assets/diagram.assets"; import { createElement } from "#core/factories/element.factory"; import { diagramDigest } from "#core/analyzers/diagram.analyzer"; import { isVector } from "#core/predicates/resource.predicate"; const STYLESHEET_REL = "stylesheet"; const LOAD_EVENT = "load"; const ERROR_EVENT = "error"; const held = new Map>(); let styled: Promise | null = null; const fetchMarkup = async function fetchMarkup(source: string): Promise { try { const response = await fetch(diagramLocation(await diagramDigest(source))); return isVector(response) ? await response.text() : null; } catch { return null; } }; const attachStylesheet = async function attachStylesheet(): Promise { return new Promise((settle) => { const link = createElement("link", { attributes: { href: DIAGRAM_STYLESHEET, rel: STYLESHEET_REL } }); link.addEventListener(LOAD_EVENT, () => { settle(); }); link.addEventListener(ERROR_EVENT, () => { settle(); }); document.head.append(link); }); }; const styledMarkup = async function styledMarkup(source: string): Promise { const markup = await fetchMarkup(source); if (markup === null) { return null; } styled ??= attachStylesheet(); await styled; return markup; }; export const loadDiagram = async function loadDiagram(source: string): Promise { const pending = held.get(source); if (pending !== undefined) { return pending; } const loading = styledMarkup(source).then((markup) => { if (markup === null) { held.delete(source); } return markup; }); held.set(source, loading); return loading; };