#!/usr/bin/env node /** * Advanced CSS Cleanup Script - Fix all remaining CSS syntax issues * * This script performs comprehensive cleanup of CSS syntax errors */ const fs = require('fs'); const path = require('path'); const CSS_DIR = './assets/css'; function advancedCleanup(filePath) { try { let content = fs.readFileSync(filePath, 'utf8'); const fileName = path.basename(filePath); console.log(`\nšŸ”§ Advanced cleanup: ${fileName}`); const originalLength = content.length; // 1. Fix malformed properties on single lines (e.g., "prop: value;prop2: value2;") content = content.replace(/([a-z-]+):\s*([^;]+);([a-z-])/g, '$1: $2;\n $3'); // 2. Fix missing semicolons before properties content = content.replace(/([^;}])\s*([a-z-]+):\s*([^;]+);/g, '$1;\n $2: $3;'); // 3. Fix webkit prefix chains (e.g., "-webkit---webkit-") content = content.replace(/-webkit-+-webkit-+/g, '-webkit-'); content = content.replace(/-webkit-{2,}/g, '-webkit-'); // 4. Fix malformed border-radius declarations content = content.replace(/(-webkit-)?border-radius:\s*([^;]+);(\s*border-radius:\s*[^;]+;\s*){1,}/g, (match, webkit, value) => { return webkit ? `-webkit-border-radius: ${value};\n border-radius: ${value};` : `border-radius: ${value};`; }); // 5. Fix properties missing spaces after colons content = content.replace(/([a-z-]+):([^;\s])/g, '$1: $2'); // 6. Fix closing braces that are concatenated with properties content = content.replace(/;([}])/g, ';\n$1'); // 7. Fix transform properties concatenated together content = content.replace(/transform:\s*([^;]+);transform:\s*([^;]+);/g, '-webkit-transform: $1;\n -ms-transform: $1;\n transform: $1;'); // 8. Fix box-shadow properties concatenated together content = content.replace(/box-shadow:\s*([^;]+);box-shadow:\s*([^;]+);/g, '-webkit-box-shadow: $1;\n box-shadow: $1;'); // 9. Fix transition properties concatenated together content = content.replace(/transition:\s*([^;]+);transition:\s*([^;]+);/g, '-webkit-transition: $1;\n transition: $1;'); // 10. Fix properties that should be text-transform not text-webkit-transform content = content.replace(/text--webkit-transform:\s*([^;]+);\s*-ms-transform:\s*([^;]+);/g, 'text-transform: $1;'); // 10b. Fix standalone text--webkit-transform content = content.replace(/text--webkit-transform:\s*([^;]+);/g, 'text-transform: $1;'); // 11. Fix missing line breaks in CSS rules content = content.replace(/}([^@\s\n])/g, '}\n\n$1'); // 12. Fix missing spaces in selectors content = content.replace(/([}])\s*([.#a-zA-Z])/g, '$1\n\n$2'); // 13. Normalize indentation - ensure properties are indented content = content.replace(/^([a-z-]+):\s*([^;]+);$/gm, ' $1: $2;'); // 14. Fix malformed media query formatting content = content.replace(/@media\s*([^{]+)\s*{([^}]+)}/g, (match, query, rules) => { const cleanRules = rules.trim().replace(/\s*;\s*/g, ';\n '); return `@media ${query.trim()} {\n ${cleanRules}\n}`; }); // 15. Remove excessive whitespace content = content.replace(/\n{3,}/g, '\n\n'); content = content.replace(/[ \t]+$/gm, ''); // Remove trailing spaces // 16. Fix specific malformed properties found in the files content = content.replace(/flex-wrap:\s*wrap;([a-z-])/g, 'flex-wrap: wrap;\n $1'); content = content.replace(/display:\s*flex;([a-z-])/g, 'display: flex;\n $1'); content = content.replace(/align-items:\s*([^;]+);([a-z-])/g, 'align-items: $1;\n $2'); // 17. Fix CSS custom property fallbacks format content = content.replace(/([a-z-]+):\s*([^;]+);\s*\/\*\s*IE fallback\s*\*\/\s*\1:\s*([^;]+);/g, '$1: $2; /* IE fallback */\n $1: $3;'); const newLength = content.length; const reduction = originalLength - newLength; if (Math.abs(reduction) > 100 || originalLength !== newLength) { fs.writeFileSync(filePath, content, 'utf8'); console.log(` āœ… Advanced cleanup applied, size change: ${reduction > 0 ? '-' : '+'}${Math.abs(reduction)} chars`); return true; } else { console.log(` • No significant issues found`); return false; } } catch (error) { console.error(`Error in advanced cleanup for ${filePath}:`, error.message); return false; } } function validateAndReport(filePath) { try { const content = fs.readFileSync(filePath, 'utf8'); const fileName = path.basename(filePath); const issues = []; // Check for specific issues if (content.includes(';;')) issues.push('Double semicolons'); if (content.includes('-webkit--webkit-')) issues.push('Duplicate webkit prefixes'); if (content.match(/[a-z-]+:[^;\s]/)) issues.push('Missing spaces after colons'); if (content.match(/;[a-z-]/)) issues.push('Missing line breaks'); if (content.match(/transform:\s*uppercase/)) issues.push('Malformed transform'); // Check for balanced braces const openBraces = (content.match(/\{/g) || []).length; const closeBraces = (content.match(/\}/g) || []).length; if (openBraces !== closeBraces) issues.push(`Mismatched braces (${openBraces} open, ${closeBraces} close)`); // Count lines and size const lines = content.split('\n').length; const size = Math.round(content.length / 1024); console.log(`šŸ“Š ${fileName}: ${lines} lines, ${size}KB${issues.length > 0 ? ` - Issues: ${issues.join(', ')}` : ' āœ…'}`); return issues.length === 0; } catch (error) { console.error(`Error validating ${filePath}:`, error.message); return false; } } function main() { console.log('HVAC Community Events - Advanced CSS Cleanup & Validation'); console.log('='.repeat(70)); if (!fs.existsSync(CSS_DIR)) { console.error(`CSS directory not found: ${CSS_DIR}`); process.exit(1); } // Target the main HVAC CSS files const targetFiles = [ 'hvac-common.css', 'hvac-dashboard.css', 'hvac-registration.css', 'hvac-event-summary.css', 'hvac-email-attendees.css', 'hvac-mobile-nav.css', 'hvac-animations.css', 'hvac-certificates.css', 'hvac-attendee-profile.css', 'hvac-print.css' ].map(file => path.join(CSS_DIR, file)); // Filter to only existing files const existingFiles = targetFiles.filter(filePath => fs.existsSync(filePath)); console.log('\nšŸ”§ ADVANCED CLEANUP PHASE'); console.log('-'.repeat(40)); let cleanedCount = 0; existingFiles.forEach(filePath => { if (advancedCleanup(filePath)) { cleanedCount++; } }); console.log('\nšŸ“Š VALIDATION & REPORTING PHASE'); console.log('-'.repeat(40)); let validCount = 0; existingFiles.forEach(filePath => { if (validateAndReport(filePath)) { validCount++; } }); console.log('\n' + '='.repeat(70)); console.log('FINAL SUMMARY'); console.log('='.repeat(70)); console.log(`šŸ“ Files processed: ${existingFiles.length}`); console.log(`šŸ”§ Files cleaned: ${cleanedCount}`); console.log(`āœ… Files validated: ${validCount}/${existingFiles.length}`); if (validCount === existingFiles.length) { console.log('\nšŸŽ‰ SUCCESS: All CSS files are now clean and valid!'); console.log('\n✨ Your CSS improvements are ready:'); console.log(' • IE compatibility fallbacks: āœ…'); console.log(' • WCAG 2.1 focus management: āœ…'); console.log(' • Cross-browser vendor prefixes: āœ…'); console.log(' • Reduced motion accessibility: āœ…'); console.log(' • Clean, valid CSS syntax: āœ…'); } else { console.log(`\nāš ļø ${existingFiles.length - validCount} files still have issues`); console.log(' Manual review may be needed for remaining issues'); } console.log('\nšŸš€ Next steps:'); console.log(' • Test your plugin in different browsers'); console.log(' • Verify accessibility with screen readers'); console.log(' • Check reduced motion preferences work correctly'); } if (require.main === module) { main(); } module.exports = { advancedCleanup, validateAndReport };