/**
* Génère le favicon et les icônes à partir du logo (spirale dorée), jamais
* d'icône générique. Usage : pnpm icons
*/
import { writeFileSync, mkdirSync } from "node:fs";
import sharp from "sharp";
import { buildSpiral } from "../src/lib/spiral.ts";
const { squares, path, bbox } = buildSpiral(8);
const pad = 1.2;
const vb = `${bbox.x - pad} ${bbox.y - pad} ${bbox.w + pad * 2} ${bbox.h + pad * 2}`;
const gold = "#c7a075";
const ivory = "#f5eee4";
function svg({ background, size }: { background: boolean; size?: number }) {
const rects = squares
.map(
(s) =>
``,
)
.join("");
const dim = size ? ` width="${size}" height="${size}"` : "";
// Le rectangle d'or est 34×21 : on le centre dans un carré pour l'icône.
const side = Math.max(bbox.w, bbox.h) + pad * 2;
const sq = `${bbox.x + bbox.w / 2 - side / 2} ${bbox.y + bbox.h / 2 - side / 2} ${side} ${side}`;
return ``;
}
mkdirSync("src/app", { recursive: true });
mkdirSync("public", { recursive: true });
writeFileSync("src/app/icon.svg", svg({ background: true }));
writeFileSync("public/logo-mark.svg", svg({ background: false }));
const png = (s: number) => sharp(Buffer.from(svg({ background: true, size: s }))).png();
await png(180).toFile("src/app/apple-icon.png");
await png(512).toFile("public/icon-512.png");
await png(192).toFile("public/icon-192.png");
// favicon.ico : PNG 48 px encapsulé (format accepté par les navigateurs modernes)
const p48 = await png(48).toBuffer();
const ico = Buffer.alloc(6 + 16);
ico.writeUInt16LE(0, 0);
ico.writeUInt16LE(1, 2);
ico.writeUInt16LE(1, 4);
ico.writeUInt8(48, 6);
ico.writeUInt8(48, 7);
ico.writeUInt8(0, 8);
ico.writeUInt8(0, 9);
ico.writeUInt16LE(1, 10);
ico.writeUInt16LE(32, 12);
ico.writeUInt32LE(p48.length, 14);
ico.writeUInt32LE(22, 18);
writeFileSync("src/app/favicon.ico", Buffer.concat([ico, p48]));
console.log(
"Icônes générées : src/app/icon.svg, favicon.ico, apple-icon.png, public/icon-*.png, public/logo-mark.svg",
);