import sharp from 'sharp'; import fs from 'fs'; import path from 'path'; import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); async function generateFavicon() { const sourceIcon = path.join(__dirname, '..', 'static', 'icon-source.png'); const outputIcon = path.join(__dirname, '..', 'static', 'favicon.png'); console.log('Generating favicon.png from icon-source.png...'); // Verify source file exists if (!fs.existsSync(sourceIcon)) { console.error('Error: icon-source.png not found at', sourceIcon); process.exit(1); } // Resize to 192x192 with transparent background await sharp(sourceIcon) .resize(192, 192, { fit: 'contain', background: { r: 0, g: 0, b: 0, alpha: 0 } }) .ensureAlpha() .png() .toFile(outputIcon); // Verify output file const metadata = await sharp(outputIcon).metadata(); const stats = fs.statSync(outputIcon); console.log(`✓ favicon.png generated successfully`); console.log(` Dimensions: ${metadata.width}x${metadata.height}`); console.log(` Format: ${metadata.format}`); console.log(` Size: ${(stats.size / 1024).toFixed(1)}KB`); // Validate success criteria if (metadata.width !== 192 || metadata.height !== 192) { console.error('Error: Invalid dimensions'); process.exit(1); } if (metadata.format !== 'png') { console.error('Error: Invalid format'); process.exit(1); } if (stats.size > 100 * 1024) { console.error('Error: File size exceeds 100KB'); process.exit(1); } console.log('✓ All validation checks passed'); } generateFavicon().catch((err) => { console.error('Error generating favicon:', err); process.exit(1); });