const fs = require('fs'); const path = require('path'); const sharp = require('sharp'); const appSvgPath = path.resolve(__dirname, '../client/public/favicon.svg'); const traySvgPath = path.resolve(__dirname, '../client/public/tray-icon.svg'); const iconsDir = path.resolve(__dirname, '../client/public/icons'); const buildDir = path.resolve(__dirname, '../client/build'); const docsDir = path.resolve(__dirname, '../docs'); const iconSizes = [16, 24, 32, 48, 64, 128, 256, 512]; const trayIcons = [ { name: 'tray-icon.png', size: 32 }, { name: 'tray-icon@2x.png', size: 64 }, ]; async function renderPng(sourceBuffer, targetPath, size) { await sharp(sourceBuffer) .resize(size, size, { fit: 'contain', kernel: sharp.kernel.lanczos3, }) .png({ compressionLevel: 9, adaptiveFiltering: true, palette: size <= 64, }) .toFile(targetPath); } async function generate() { if (!fs.existsSync(appSvgPath)) { throw new Error(`App icon SVG not found: ${appSvgPath}`); } if (!fs.existsSync(traySvgPath)) { throw new Error(`Tray icon SVG not found: ${traySvgPath}`); } fs.mkdirSync(iconsDir, { recursive: true }); fs.mkdirSync(buildDir, { recursive: true }); fs.mkdirSync(docsDir, { recursive: true }); const appSvg = fs.readFileSync(appSvgPath); const traySvg = fs.readFileSync(traySvgPath); for (const size of iconSizes) { await renderPng(appSvg, path.join(iconsDir, `icon-${size}.png`), size); console.log(`generated icon-${size}.png`); } for (const tray of trayIcons) { await renderPng(traySvg, path.join(iconsDir, tray.name), tray.size); console.log(`generated ${tray.name}`); } const logoPath = path.join(iconsDir, 'logo.png'); await renderPng(appSvg, logoPath, 512); fs.copyFileSync(path.join(iconsDir, 'icon-256.png'), path.join(buildDir, 'icon.png')); fs.copyFileSync(logoPath, path.join(docsDir, 'logo.png')); console.log(`icon generation complete: ${iconsDir}`); } generate().catch((error) => { console.error(error); process.exit(1); });