#!/usr/bin/env node
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const ROOT = path.resolve(__dirname, "..");
const TSX_FILES = [];
function walkDir(dir) {
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
const full = path.join(dir, entry.name);
if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
walkDir(full);
} else if (entry.name.endsWith(".tsx")) {
TSX_FILES.push(full);
}
}
}
walkDir(path.join(ROOT, "components"));
let totalReplaced = 0;
for (const file of TSX_FILES) {
let content = fs.readFileSync(file, "utf8");
let changed = false;
// Replace
with
// Match self-closing img tags
content = content.replace(/
]*?)\s*\/>/g, (match, attrs) => {
const srcMatch = attrs.match(/src="([^"]*)"/);
if (!srcMatch) return match;
const src = srcMatch[1];
// Skip SVG inline and external URLs
if (src.startsWith("http://") || src.startsWith("https://")) return match;
if (src.startsWith("data:")) return match;
const widthMatch = attrs.match(/width=\{(\d+)\}/);
const heightMatch = attrs.match(/height=\{(\d+)\}/);
const altMatch = attrs.match(/alt="([^"]*)"/);
const classMatch = attrs.match(/className="([^"]*)"/);
const loadingMatch = attrs.match(/loading="([^"]*)"/);
const sizesMatch = attrs.match(/sizes="([^"]*)"/);
// Remove srcSet from attrs (next/image handles it)
let cleanAttrs = attrs
.replace(/srcSet="[^"]*"/g, "")
.replace(/loading="[^"]*"/g, "")
.replace(/\s+/g, " ")
.trim();
// Ensure width and height exist
const width = widthMatch ? widthMatch[1] : "0";
const height = heightMatch ? heightMatch[1] : "0";
// If no width/height, use fill mode
if (width === "0" || height === "0") {
// Remove width/height attrs
cleanAttrs = cleanAttrs
.replace(/width=\{\d+\}/g, "")
.replace(/height=\{\d+\}/g, "")
.replace(/\s+/g, " ")
.trim();
changed = true;
totalReplaced++;
return ``;
}
changed = true;
totalReplaced++;
return ``;
});
if (changed) {
// Add Image import if not present
if (!content.includes('import Image from "next/image"') && !content.includes("import Image from 'next/image'")) {
// Add after existing imports or at top
const firstImport = content.indexOf("import ");
if (firstImport !== -1) {
const lineEnd = content.indexOf("\n", firstImport);
content = content.slice(0, lineEnd + 1) + 'import Image from "next/image"\n' + content.slice(lineEnd + 1);
} else {
content = 'import Image from "next/image"\n\n' + content;
}
}
fs.writeFileSync(file, content, "utf8");
console.log(`Updated: ${path.relative(ROOT, file)}`);
}
}
console.log(`\nTotal
→ : ${totalReplaced}`);