- Move the TypeScript project under scripts/ (src, tsconfig, package.json, pnpm lockfile/workspace, canonical .gitignore); drop the npm package-lock - Add scripts/Taskfile.yml aggregator plus .scripts modules (loggers, base, cli) with build, run, and validate tasks - Move the six SKILL-*.md docs into references/ with kebab names and extract the connector-routing sections from SKILL.md into references/routing-best-practices.md (SKILL.md 666 -> ~310 lines) - Add license/metadata/compatibility frontmatter, an Available scripts section, and update all CLI paths in README and references skill-manager validate: 13/13 passed, 0 warnings. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
73 lines
2.8 KiB
TypeScript
73 lines
2.8 KiB
TypeScript
/**
|
|
* dom-polyfill.ts
|
|
*
|
|
* Sets up (or extends) the global DOM environment required by @maxgraph/core
|
|
* when running in Node.js. Safe to import multiple times — idempotent.
|
|
*
|
|
* The parser (drawio-parser/parser.ts) already sets up a partial DOM polyfill
|
|
* for the basic maxGraph model/serializer classes. This module extends it with
|
|
* the additional globals needed by Graph+GraphView (rendering pipeline):
|
|
* - location
|
|
* - SVGElement, MouseEvent, KeyboardEvent, TouchEvent
|
|
* - requestAnimationFrame / cancelAnimationFrame
|
|
*
|
|
* Must be imported before any maxGraph Graph/GraphView usage.
|
|
*/
|
|
|
|
import { JSDOM } from "jsdom";
|
|
|
|
// Use the same DOM that may already be set up by parser.ts, or create a new one.
|
|
// We detect by checking whether global.document already exists.
|
|
let win: Record<string, unknown>;
|
|
|
|
if ((globalThis as Record<string, unknown>)["document"]) {
|
|
// Parser already set up a DOM — re-use the existing window
|
|
win = (globalThis as Record<string, unknown>)["window"] as Record<string, unknown>;
|
|
} else {
|
|
const dom = new JSDOM(
|
|
'<!DOCTYPE html><html><body></body></html>',
|
|
{ pretendToBeVisual: true }
|
|
);
|
|
win = dom.window as unknown as Record<string, unknown>;
|
|
(globalThis as Record<string, unknown>)["document"] = win["document"];
|
|
(globalThis as Record<string, unknown>)["window"] = win;
|
|
(globalThis as Record<string, unknown>)["DOMParser"] = win["DOMParser"];
|
|
(globalThis as Record<string, unknown>)["XMLSerializer"] = win["XMLSerializer"];
|
|
(globalThis as Record<string, unknown>)["HTMLElement"] = win["HTMLElement"];
|
|
(globalThis as Record<string, unknown>)["Element"] = win["Element"];
|
|
(globalThis as Record<string, unknown>)["Node"] = win["Node"];
|
|
(globalThis as Record<string, unknown>)["Event"] = win["Event"];
|
|
try {
|
|
Object.defineProperty(globalThis, "navigator", {
|
|
value: win["navigator"],
|
|
writable: true,
|
|
configurable: true,
|
|
});
|
|
} catch { /* already defined */ }
|
|
}
|
|
|
|
// Add/overwrite globals needed specifically for Graph+GraphView rendering
|
|
const g = globalThis as Record<string, unknown>;
|
|
|
|
if (!g["SVGElement"]) g["SVGElement"] = win["SVGElement"] ?? class SVGElement {};
|
|
if (!g["MouseEvent"]) g["MouseEvent"] = win["MouseEvent"] ?? class MouseEvent {};
|
|
if (!g["KeyboardEvent"]) g["KeyboardEvent"] = win["KeyboardEvent"] ?? class KeyboardEvent {};
|
|
if (!g["TouchEvent"]) g["TouchEvent"] = win["TouchEvent"] ?? class TouchEvent {};
|
|
if (!g["requestAnimationFrame"]) {
|
|
g["requestAnimationFrame"] = (fn: () => void) => setTimeout(fn, 0);
|
|
}
|
|
if (!g["cancelAnimationFrame"]) {
|
|
g["cancelAnimationFrame"] = clearTimeout;
|
|
}
|
|
// location is needed by UrlConverter (used when rendering image shapes)
|
|
if (!g["location"]) {
|
|
g["location"] = {
|
|
protocol: "http:",
|
|
host: "localhost",
|
|
href: "http://localhost/",
|
|
pathname: "/",
|
|
};
|
|
}
|
|
|
|
export {};
|