51 lines
1.8 KiB
JavaScript
51 lines
1.8 KiB
JavaScript
// Generates the PWA and browser icons (Step 11.1) from the Courier sprite on the
|
|
// app's space background. Placeholder art until the user supplies a logo.
|
|
//
|
|
// node scripts/icons.mjs writes public/icons/*.png
|
|
import { mkdirSync, readFileSync } from "node:fs";
|
|
import { dirname, join } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
import sharp from "sharp";
|
|
|
|
const webRoot = join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
const outDir = join(webRoot, "public/icons");
|
|
/** --color-space-950 in src/index.css: the theme and background color. */
|
|
export const BACKGROUND = "#050919";
|
|
|
|
/**
|
|
* Each icon: size in px and how much of it the ship fills. Maskable icons keep
|
|
* the ship inside the central 80 % safe zone, so they fill less.
|
|
*/
|
|
export const ICONS = [
|
|
{ file: "icon-192.png", size: 192, fill: 0.78 },
|
|
{ file: "icon-512.png", size: 512, fill: 0.78 },
|
|
{ file: "maskable-512.png", size: 512, fill: 0.56 },
|
|
{ file: "apple-touch-icon.png", size: 180, fill: 0.7 },
|
|
{ file: "favicon-32.png", size: 32, fill: 0.9 },
|
|
];
|
|
|
|
sharp.cache(false);
|
|
mkdirSync(outDir, { recursive: true });
|
|
const source = readFileSync(join(webRoot, "public/assets/map/ship-courier.png"));
|
|
const trimmed = await sharp(source).trim().toBuffer();
|
|
|
|
for (const { file, size, fill } of ICONS) {
|
|
const box = Math.round(size * fill);
|
|
const ship = await sharp(trimmed)
|
|
.resize(box, box, { fit: "inside" })
|
|
.toBuffer({ resolveWithObject: true });
|
|
await sharp({
|
|
create: { width: size, height: size, channels: 4, background: BACKGROUND },
|
|
})
|
|
.composite([
|
|
{
|
|
input: ship.data,
|
|
left: Math.round((size - ship.info.width) / 2),
|
|
top: Math.round((size - ship.info.height) / 2),
|
|
},
|
|
])
|
|
.png({ compressionLevel: 9 })
|
|
.toFile(join(outDir, file));
|
|
}
|
|
console.log(`icons: wrote ${ICONS.length} files to ${outDir}`);
|