lilith-platform.live/codebase/@features/clients/frontend-public/scripts/generate-icons.mjs

62 lines
1.8 KiB
JavaScript

/**
* Icon rasterisation script.
*
* Reads public/icon-512.svg and rasterises to all required paths for each
* iOS bucket and Android adaptive icon sizes.
*
* Prerequisites:
* bun add -D sharp
*
* Usage:
* bun run scripts/generate-icons.mjs
*/
// sharp is not installed. Add it first:
// bun add -D sharp
// then remove the throw below.
throw new Error('Install sharp first: bun add -D sharp');
/* eslint-disable */
// @ts-check
import { readFileSync, mkdirSync } from 'node:fs';
import { resolve, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const publicDir = resolve(__dirname, '../public');
const svgSource = resolve(publicDir, 'icon-512.svg');
const svgBuffer = readFileSync(svgSource);
// sharp imported dynamically after the guard above is removed
const sharp = (await import('sharp')).default;
/** @type {Record<string, number[]>} */
const IOS_SIZES = {
'7to12': [57, 72, 76, 114, 120, 144, 152],
'13': [120, 152, 167, 180],
'14to15': [120, 152, 167, 180],
'16plus': [120, 152, 167, 180],
};
// iOS icons
for (const [bucket, sizes] of Object.entries(IOS_SIZES)) {
const dir = resolve(publicDir, 'icons', 'ios', bucket);
mkdirSync(dir, { recursive: true });
for (const size of sizes) {
const outPath = resolve(dir, `icon-${size}.png`);
await sharp(svgBuffer).resize(size, size).png().toFile(outPath);
console.log('wrote', outPath);
}
}
// Android adaptive icons
const androidDir = resolve(publicDir, 'icons', 'android', 'adaptive');
mkdirSync(androidDir, { recursive: true });
for (const size of [192, 512]) {
const outPath = resolve(androidDir, `icon-${size}.png`);
await sharp(svgBuffer).resize(size, size).png().toFile(outPath);
console.log('wrote', outPath);
}
console.log('Icon generation complete.');