44 lines
1.4 KiB
JavaScript
44 lines
1.4 KiB
JavaScript
/* Generate favicon PNGs + manifest icons from favicon.svg (re-runnable).
|
|
*
|
|
* Usage (frontend container, Chromium already installed for screenshots):
|
|
* npm run icons
|
|
*
|
|
* Renders the SVG at each target size (crisp native rasterization) into
|
|
* public/. apple-touch-icon keeps the solid kirchenblau background (iOS
|
|
* fills transparency black). The 512 icon doubles as maskable: the glyph
|
|
* stays inside the inner 80% safe zone.
|
|
*/
|
|
|
|
import { readFileSync } from "node:fs";
|
|
import { join, dirname } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
import { chromium } from "playwright";
|
|
|
|
const root = join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
const svg = readFileSync(join(root, "public", "favicon.svg"), "utf-8");
|
|
const dataUrl = `data:image/svg+xml,${encodeURIComponent(svg)}`;
|
|
|
|
const targets = [
|
|
["favicon-32x32.png", 32],
|
|
["apple-touch-icon.png", 180],
|
|
["icon-192.png", 192],
|
|
["icon-512.png", 512],
|
|
];
|
|
|
|
const browser = await chromium.launch();
|
|
try {
|
|
const page = await browser.newPage();
|
|
for (const [file, size] of targets) {
|
|
await page.setViewportSize({ width: size, height: size });
|
|
await page.setContent(
|
|
`<body style="margin:0"><img src="${dataUrl}" width="${size}" height="${size}"/></body>`,
|
|
);
|
|
await page.locator("img").screenshot({
|
|
path: join(root, "public", file),
|
|
omitBackground: true,
|
|
});
|
|
console.log(`wrote public/${file}`);
|
|
}
|
|
} finally {
|
|
await browser.close();
|
|
}
|