const fs = require('fs'); const path = require('path'); // Find all HTML files that need optimization const findHtmlFiles = (dir) => { const files = []; const items = fs.readdirSync(dir); for (const item of items) { const fullPath = path.join(dir, item); const stat = fs.statSync(fullPath); if (stat.isDirectory() && !item.startsWith('.') && item !== 'node_modules') { files.push(...findHtmlFiles(fullPath)); } else if (item.endsWith('.html') && !item.includes('test') && !item.includes('performance') && !item.includes('optimized')) { files.push(fullPath); } } return files; }; // Apply global optimizations const optimizeFile = (filePath) => { let content = fs.readFileSync(filePath, 'utf8'); let modified = false; // 1. Replace main.css with main.min.css (if not already minified) if (content.includes('href="/css/main.css"') || content.includes('href="css/main.css"')) { content = content.replace(/href="(\/?)css\/main\.css"/g, 'href="$1css/main.min.css"'); modified = true; } // 2. Add preconnect hints if missing (only in head section) if (!content.includes('preconnect') && content.includes('')) { const preconnectHints = ` `; content = content.replace(//, `${preconnectHints}`); modified = true; } // 3. Update component scripts to use minified versions if (content.includes('src="/components/') || content.includes('src="components/')) { content = content.replace(/src="(\/?)components\/([^"]+)\.js"/g, (match, slash, name) => { // Only update if .min.js exists const minPath = path.join(__dirname, 'components', `${name}.min.js`); if (fs.existsSync(minPath)) { return `src="${slash}components/${name}.min.js"`; } return match; }); content = content.replace(/src="(\/?)js\/([^"]+)\.js"/g, (match, slash, name) => { // Only update if .min.js exists const minPath = path.join(__dirname, 'js', `${name}.min.js`); if (fs.existsSync(minPath)) { return `src="${slash}js/${name}.min.js"`; } return match; }); modified = true; } // 4. Add async loading for D3.js if it's loaded directly if (content.includes('d3.v7.min.js') && !content.includes('async')) { content = content.replace( /' ); modified = true; } // Write back if modified if (modified) { fs.writeFileSync(filePath, content); console.log(`āœ“ Optimized: ${path.relative(__dirname, filePath)}`); return true; } return false; }; // Main execution console.log('šŸš€ Starting global performance optimization...\n'); const htmlFiles = findHtmlFiles(__dirname); let optimizedCount = 0; for (const file of htmlFiles) { try { if (optimizeFile(file)) { optimizedCount++; } } catch (error) { console.error(`āŒ Error optimizing ${file}:`, error.message); } } console.log(`\nšŸŽÆ Optimization complete!`); console.log(`šŸ“Š Optimized ${optimizedCount} out of ${htmlFiles.length} files`); console.log(`\nšŸ’” Optimizations applied:`); console.log(` āœ… Switched to minified CSS (main.min.css)`); console.log(` āœ… Added preconnect hints for faster loading`); console.log(` āœ… Updated to minified component scripts`); console.log(` āœ… Optimized D3.js loading`); console.log(`\nšŸ”’ All D3.js visuals preserved - no content changes!`);