Files
endorphin-tabularium-docs/apps/docs/scripts/build-doc-images.mjs
codex-bot d57e9b77d7
Verify database-backed documents / verify (pull_request) Failing after 6m6s
feat: make the site database authoritative for documents and catalog
2026-10-30 16:23:54 +08:00

50 lines
2.3 KiB
JavaScript

import { mkdir, readFile, readdir, writeFile } from "node:fs/promises";
import path from "node:path";
import { fileURLToPath } from "node:url";
import sharp from "sharp";
const root = fileURLToPath(new URL("../../../", import.meta.url));
const sources = path.join(root, "tools/figures/assets");
const output = path.join(root, "apps/docs/public/figures");
const check = process.argv.includes("--check");
const policy = JSON.parse(await readFile(path.join(root, "content/image-policy.json"), "utf8"));
async function files(directory) {
const entries = await readdir(directory, { withFileTypes: true });
return (await Promise.all(entries.map((entry) => {
const name = path.join(directory, entry.name);
return entry.isDirectory() ? files(name) : [name];
}))).flat().sort();
}
// Originals stay outside public; both inline and lightbox images use the WebP.
for (const name of await files(path.join(root, "apps/docs/public"))) {
if (/\.(?:png|jpe?g|tiff?|bmp)$/i.test(name)) {
throw new Error(`Original raster exposed in public: ${path.relative(root, name)}. Move it to tools/figures/assets and run images.`);
}
}
await mkdir(output, { recursive: true });
for (const source of await files(sources)) {
if (!/\.(?:png|jpe?g|tiff?|bmp)$/i.test(source)) continue;
const relative = path.relative(sources, source).replace(/\.[^.]+$/, ".webp");
const destination = path.join(output, relative);
const original = await readFile(source);
const encoded = await sharp(original)
.rotate()
.resize({ width: policy.maxWidth, withoutEnlargement: true })
.webp({ quality: policy.quality, effort: 6 })
.toBuffer();
if (encoded.length > policy.maxBytes) {
throw new Error(`${relative}: ${encoded.length} bytes exceeds the ${policy.maxBytes}-byte image budget.`);
}
if (check) {
const generated = await readFile(destination);
if (!encoded.equals(generated)) throw new Error(`${relative} is stale. Regenerate browser images on the confirmed remote runner.`);
} else {
await mkdir(path.dirname(destination), { recursive: true });
await writeFile(destination, encoded);
}
console.log(`${check ? "Verified" : "Generated"} ${relative}: ${original.length} → ${encoded.length} bytes (${(100 * (1 - encoded.length / original.length)).toFixed(1)}% smaller)`);
}