chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:58:18 +08:00
commit 6d5d58c1a9
18293 changed files with 3502153 additions and 0 deletions
+36
View File
@@ -0,0 +1,36 @@
/**
* A single shared headless Chromium for local chart/diagram rendering.
*
* The rendering happens entirely in-process (our own browser) — only the
* charting *library* is fetched from a CDN; the user's data never leaves the
* host. Reuse one browser across renders so we don't pay a launch per call;
* `closeBrowser()` is wired into the bridge's shutdown.
*
* Requires a Chromium binary: `npx playwright install chromium`.
*/
import { chromium, type Browser } from "playwright";
let browserPromise: Promise<Browser> | undefined;
let closing = false;
export function getBrowser(): Promise<Browser> {
if (closing) {
return Promise.reject(new Error("renderer is shutting down"));
}
if (!browserPromise) {
browserPromise = chromium.launch({ args: ["--no-sandbox"] });
}
return browserPromise;
}
export async function closeBrowser(): Promise<void> {
if (!browserPromise) return;
// Claim shutdown and detach the promise BEFORE awaiting, so a concurrent
// getBrowser() rejects cleanly instead of handing back a browser we're
// about to close out from under it.
closing = true;
const pending = browserPromise;
browserPromise = undefined;
const b = await pending.catch(() => undefined);
await b?.close().catch(() => {});
}
+53
View File
@@ -0,0 +1,53 @@
/**
* Render a Chart.js config to a PNG, locally, in headless Chromium.
* The agent produces the Chart.js config (type + data + options); we draw it
* to a canvas and screenshot it. Chart.js is loaded from a CDN into our own
* browser — the chart *data* never leaves the host.
*/
import { getBrowser } from "./browser.js";
const CHART_JS_CDN =
process.env["CHART_JS_URL"] ??
"https://cdn.jsdelivr.net/npm/chart.js@4.4.3/dist/chart.umd.js";
export async function renderChart(
spec: Record<string, unknown>,
opts: { width?: number; height?: number } = {},
): Promise<Buffer> {
const width = opts.width ?? 720;
const height = opts.height ?? 440;
const browser = await getBrowser();
const page = await browser.newPage({
viewport: { width, height },
deviceScaleFactor: 2,
});
try {
await page.setContent(
`<!doctype html><html><body style="margin:0;background:#ffffff">` +
`<canvas id="c" width="${width}" height="${height}"></canvas></body></html>`,
);
await page.addScriptTag({ url: CHART_JS_CDN });
const err = await page.evaluate((spec) => {
const el = document.getElementById("c") as HTMLCanvasElement | null;
if (!el) return "no canvas";
const s = spec as { options?: Record<string, unknown> };
s.options = { ...(s.options ?? {}), animation: false, responsive: false };
try {
// @ts-expect-error Chart is injected by the CDN script
new Chart(el.getContext("2d"), s);
return null;
} catch (e) {
return String((e as Error)?.message ?? e);
}
}, spec);
if (err) throw new Error(`Chart.js render failed: ${err}`);
// Chart.js with animation disabled paints synchronously; a tiny settle
// guards against font/layout reflow.
await page.waitForTimeout(120);
const canvas = await page.$("#c");
if (!canvas) throw new Error("canvas disappeared");
return (await canvas.screenshot({ type: "png" })) as Buffer;
} finally {
await page.close();
}
}
+67
View File
@@ -0,0 +1,67 @@
/**
* Render Mermaid diagram source to a PNG, locally, in headless Chromium.
* Mermaid is loaded from a CDN into our own browser; the diagram source
* never leaves the host. Invalid Mermaid throws with the parser message so
* the tool can hand the agent a clear error to repair.
*
* Two-stage to keep AI-authored content from executing scripts:
* 1. A "render" page loads Mermaid and turns the DSL into a sanitized SVG
* *string* (securityLevel "strict"); Mermaid only parses its own DSL
* here, never arbitrary HTML.
* 2. A "shot" page displays that SVG with a `script-src 'none'` CSP, so
* even a crafted SVG can't run a script, then we screenshot it.
*/
import { getBrowser } from "./browser.js";
const MERMAID_CDN =
process.env["MERMAID_URL"] ??
"https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js";
export async function renderDiagram(code: string): Promise<Buffer> {
const browser = await getBrowser();
// ── Stage 1: DSL → sanitized SVG string ─────────────────────────────
const renderPage = await browser.newPage();
let svg: string;
try {
await renderPage.setContent("<!doctype html><html><body></body></html>");
await renderPage.addScriptTag({ url: MERMAID_CDN });
const result = await renderPage.evaluate(async (code) => {
// @ts-expect-error mermaid is injected by the CDN script
mermaid.initialize({ startOnLoad: false, securityLevel: "strict" });
try {
// @ts-expect-error mermaid global
const out = await mermaid.render("graph", code);
return { svg: out.svg as string };
} catch (e) {
return { error: String((e as Error)?.message ?? e) };
}
}, code);
if ("error" in result) {
throw new Error(`Mermaid render failed: ${result.error}`);
}
svg = result.svg;
} finally {
await renderPage.close();
}
// ── Stage 2: display under a no-script CSP and screenshot ────────────
const shotPage = await browser.newPage({
viewport: { width: 1000, height: 800 },
deviceScaleFactor: 2,
});
try {
await shotPage.setContent(
`<!doctype html><html><head>` +
`<meta http-equiv="Content-Security-Policy" content="script-src 'none'; object-src 'none'">` +
`</head><body style="margin:0;padding:16px;background:#ffffff">` +
`<div id="out">${svg}</div></body></html>`,
{ waitUntil: "load" },
);
const el = await shotPage.$("#out svg");
if (!el) throw new Error("Mermaid produced no SVG");
return (await el.screenshot({ type: "png" })) as Buffer;
} finally {
await shotPage.close();
}
}