#!/usr/bin/env node import fs from 'node:fs/promises' import path from 'node:path' import sharp from 'sharp' const ROOT = path.resolve(process.cwd(), 'public/images/figma') const QUALITY = 82 const MIN_BYTES = 200_000 const manifest = { deletedDuplicates: [], encoded: [], skipped: [] } const all = await fs.readdir(ROOT) const byBase = new Map() for (const f of all) { const ext = path.extname(f) const base = ext ? path.basename(f, ext) : f if (!byBase.has(base)) byBase.set(base, []) byBase.get(base).push(f) } // 1) Delete extensionless duplicates that have a webp/png/jpg sibling for (const [, variants] of byBase) { const extensionless = variants.find((v) => path.extname(v) === '') const hasSibling = variants.some((v) => /\.(webp|png|jpg|jpeg)$/i.test(v)) if (extensionless && hasSibling) { const p = path.join(ROOT, extensionless) await fs.unlink(p) manifest.deletedDuplicates.push(path.basename(p)) } } // 2) Re-encode large png/jpg to webp (skip if webp already exists and is newer) for (const [base, variants] of byBase) { const heavy = variants.find((v) => /\.(png|jpg|jpeg)$/i.test(v)) if (!heavy) continue const srcPath = path.join(ROOT, heavy) const stat = await fs.stat(srcPath).catch(() => null) if (!stat || stat.size < MIN_BYTES) { manifest.skipped.push(path.basename(srcPath)) continue } const outPath = path.join(ROOT, `${base}.webp`) const outStat = await fs.stat(outPath).catch(() => null) if (outStat && outStat.mtimeMs > stat.mtimeMs) { manifest.skipped.push(path.basename(srcPath) + ' (webp newer)') continue } await sharp(srcPath).webp({ quality: QUALITY }).toFile(outPath) manifest.encoded.push({ src: path.basename(srcPath), out: `${base}.webp`, before: stat.size }) } const manifestPath = path.join(process.cwd(), 'scripts/optimize-images.manifest.json') await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2)) console.log( `Deleted ${manifest.deletedDuplicates.length} duplicates, encoded ${manifest.encoded.length} files, skipped ${manifest.skipped.length}.` ) console.log('Manifest:', manifestPath)