import { promises as fs } from 'node:fs'; import path from 'node:path'; // Build map: relative path that ORIGINALLY existed but now only has .webp // Walk /public for .webp files, compute their candidate original ext (.jpg/.png/.gif) // If the candidate no longer exists on disk, that's a swap target. const PUBLIC_ROOT = path.resolve('public'); const SRC_ROOT = path.resolve('src'); async function walk(dir, out) { const entries = await fs.readdir(dir, { withFileTypes: true }); for (const e of entries) { const p = path.join(dir, e.name); if (e.isDirectory()) await walk(p, out); else out.push(p); } } // 1. Find .webp files and detect which original ext is missing const all = []; await walk(PUBLIC_ROOT, all); const webps = all.filter((p) => p.toLowerCase().endsWith('.webp')); const existing = new Set(all.map((p) => p.toLowerCase())); const swaps = []; // { from: /images/foo.jpg, to: /images/foo.webp } for (const wp of webps) { const base = wp.slice(0, -5); // strip .webp for (const ext of ['.jpg', '.jpeg', '.png', '.gif']) { const candidate = base + ext; if (!existing.has(candidate.toLowerCase())) { // Candidate gone => it was converted const rel = '/' + path.relative(PUBLIC_ROOT, candidate).split(path.sep).join('/'); const relWebp = '/' + path.relative(PUBLIC_ROOT, wp).split(path.sep).join('/'); swaps.push({ from: rel, to: relWebp }); } } } console.log(`detected ${swaps.length} swap pairs`); // 2. Walk /src for ts/tsx/js/jsx/json/md/css and apply replacements const srcExts = new Set(['.ts', '.tsx', '.js', '.jsx', '.json', '.md', '.css', '.html', '.mjs']); const srcFiles = []; await walk(SRC_ROOT, srcFiles); const targets = srcFiles.filter((p) => srcExts.has(path.extname(p).toLowerCase())); let totalReplacements = 0; let touchedFiles = 0; for (const file of targets) { let text = await fs.readFile(file, 'utf8'); let count = 0; for (const s of swaps) { if (text.includes(s.from)) { const before = text; text = text.split(s.from).join(s.to); const occurrences = (before.length - text.length) / (s.from.length - s.to.length); count += occurrences; } } if (count > 0) { await fs.writeFile(file, text, 'utf8'); totalReplacements += count; touchedFiles++; const rel = path.relative(process.cwd(), file).split(path.sep).join('/'); console.log(`UPDATE ${rel} (${count} swaps)`); } } console.log('---'); console.log(`replaced ${totalReplacements} references across ${touchedFiles} files`);