- Add 26 documentation files including test reports, deployment guides, and troubleshooting documentation - Include 3 CSV data files for trainer imports and user registration tracking - Add 43 JavaScript test files covering mobile optimization, Safari compatibility, and E2E testing - Include 18 PHP utility files for debugging, geocoding, and data analysis - Add 12 shell scripts for deployment verification, user management, and database operations - Update .gitignore with whitelist patterns for development files, documentation, and CSV data 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
		
			
				
	
	
		
			421 lines
		
	
	
		
			No EOL
		
	
	
		
			13 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			421 lines
		
	
	
		
			No EOL
		
	
	
		
			13 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| #!/usr/bin/env node
 | |
| 
 | |
| /**
 | |
|  * HVAC Community Events CSS Vendor Prefix Fixes
 | |
|  * 
 | |
|  * This script adds vendor prefixes for cross-browser compatibility
 | |
|  * using Autoprefixer patterns to ensure support across all modern browsers.
 | |
|  */
 | |
| 
 | |
| const fs = require('fs');
 | |
| const path = require('path');
 | |
| 
 | |
| const CSS_DIR = './assets/css';
 | |
| const prefixRules = [];
 | |
| 
 | |
| // Vendor prefix patterns - following Autoprefixer standards
 | |
| const VENDOR_PREFIXES = {
 | |
|     // Flexbox properties
 | |
|     flexbox: {
 | |
|         'display: flex': [
 | |
|             'display: -webkit-box',
 | |
|             'display: -ms-flexbox', 
 | |
|             'display: flex'
 | |
|         ],
 | |
|         'flex-direction: column': [
 | |
|             '-webkit-box-orient: vertical',
 | |
|             '-webkit-box-direction: normal',
 | |
|             '-ms-flex-direction: column',
 | |
|             'flex-direction: column'
 | |
|         ],
 | |
|         'flex-direction: row': [
 | |
|             '-webkit-box-orient: horizontal',
 | |
|             '-webkit-box-direction: normal', 
 | |
|             '-ms-flex-direction: row',
 | |
|             'flex-direction: row'
 | |
|         ],
 | |
|         'justify-content: space-between': [
 | |
|             '-webkit-box-pack: justify',
 | |
|             '-ms-flex-pack: justify',
 | |
|             'justify-content: space-between'
 | |
|         ],
 | |
|         'justify-content: center': [
 | |
|             '-webkit-box-pack: center',
 | |
|             '-ms-flex-pack: center',
 | |
|             'justify-content: center'
 | |
|         ],
 | |
|         'justify-content: flex-start': [
 | |
|             '-webkit-box-pack: start',
 | |
|             '-ms-flex-pack: start',
 | |
|             'justify-content: flex-start'
 | |
|         ],
 | |
|         'justify-content: flex-end': [
 | |
|             '-webkit-box-pack: end',
 | |
|             '-ms-flex-pack: end',
 | |
|             'justify-content: flex-end'
 | |
|         ],
 | |
|         'align-items: center': [
 | |
|             '-webkit-box-align: center',
 | |
|             '-ms-flex-align: center',
 | |
|             'align-items: center'
 | |
|         ],
 | |
|         'align-items: flex-start': [
 | |
|             '-webkit-box-align: start',
 | |
|             '-ms-flex-align: start',
 | |
|             'align-items: flex-start'
 | |
|         ],
 | |
|         'align-items: flex-end': [
 | |
|             '-webkit-box-align: end',
 | |
|             '-ms-flex-align: end',
 | |
|             'align-items: flex-end'
 | |
|         ],
 | |
|         'align-items: stretch': [
 | |
|             '-webkit-box-align: stretch',
 | |
|             '-ms-flex-align: stretch',
 | |
|             'align-items: stretch'
 | |
|         ],
 | |
|         'flex: 1': [
 | |
|             '-webkit-box-flex: 1',
 | |
|             '-ms-flex: 1',
 | |
|             'flex: 1'
 | |
|         ],
 | |
|         'flex-wrap: wrap': [
 | |
|             '-ms-flex-wrap: wrap',
 | |
|             'flex-wrap: wrap'
 | |
|         ]
 | |
|     },
 | |
|     
 | |
|     // CSS Grid properties  
 | |
|     grid: {
 | |
|         'display: grid': [
 | |
|             'display: -ms-grid',
 | |
|             'display: grid'
 | |
|         ],
 | |
|         'grid-template-columns': {
 | |
|             pattern: /grid-template-columns:\s*([^;]+)/g,
 | |
|             replacement: (match, value) => [
 | |
|                 `-ms-grid-columns: ${value}`,
 | |
|                 `grid-template-columns: ${value}`
 | |
|             ]
 | |
|         },
 | |
|         'grid-template-rows': {
 | |
|             pattern: /grid-template-rows:\s*([^;]+)/g,
 | |
|             replacement: (match, value) => [
 | |
|                 `-ms-grid-rows: ${value}`,
 | |
|                 `grid-template-rows: ${value}`
 | |
|             ]
 | |
|         },
 | |
|         'gap': {
 | |
|             pattern: /gap:\s*([^;]+)/g,
 | |
|             replacement: (match, value) => [
 | |
|                 `grid-gap: ${value}`,
 | |
|                 `gap: ${value}`
 | |
|             ]
 | |
|         }
 | |
|     },
 | |
|     
 | |
|     // Transform properties
 | |
|     transform: {
 | |
|         pattern: /transform:\s*([^;]+)/g,
 | |
|         replacement: (match, value) => [
 | |
|             `-webkit-transform: ${value}`,
 | |
|             `-ms-transform: ${value}`,
 | |
|             `transform: ${value}`
 | |
|         ]
 | |
|     },
 | |
|     
 | |
|     // Transition properties
 | |
|     transition: {
 | |
|         pattern: /transition:\s*([^;]+)/g,
 | |
|         replacement: (match, value) => [
 | |
|             `-webkit-transition: ${value}`,
 | |
|             `transition: ${value}`
 | |
|         ]
 | |
|     },
 | |
|     
 | |
|     // Animation properties
 | |
|     animation: {
 | |
|         pattern: /animation:\s*([^;]+)/g,
 | |
|         replacement: (match, value) => [
 | |
|             `-webkit-animation: ${value}`,
 | |
|             `animation: ${value}`
 | |
|         ]
 | |
|     },
 | |
|     
 | |
|     // Box-shadow property
 | |
|     boxShadow: {
 | |
|         pattern: /box-shadow:\s*([^;]+)/g,
 | |
|         replacement: (match, value) => [
 | |
|             `-webkit-box-shadow: ${value}`,
 | |
|             `box-shadow: ${value}`
 | |
|         ]
 | |
|     },
 | |
|     
 | |
|     // Border-radius property
 | |
|     borderRadius: {
 | |
|         pattern: /border-radius:\s*([^;]+)/g,
 | |
|         replacement: (match, value) => [
 | |
|             `-webkit-border-radius: ${value}`,
 | |
|             `border-radius: ${value}`
 | |
|         ]
 | |
|     },
 | |
|     
 | |
|     // Appearance property
 | |
|     appearance: {
 | |
|         pattern: /appearance:\s*([^;]+)/g,
 | |
|         replacement: (match, value) => [
 | |
|             `-webkit-appearance: ${value}`,
 | |
|             `-moz-appearance: ${value}`,
 | |
|             `appearance: ${value}`
 | |
|         ]
 | |
|     },
 | |
|     
 | |
|     // User-select property
 | |
|     userSelect: {
 | |
|         pattern: /user-select:\s*([^;]+)/g,
 | |
|         replacement: (match, value) => [
 | |
|             `-webkit-user-select: ${value}`,
 | |
|             `-moz-user-select: ${value}`,
 | |
|             `-ms-user-select: ${value}`,
 | |
|             `user-select: ${value}`
 | |
|         ]
 | |
|     },
 | |
|     
 | |
|     // Background-size property
 | |
|     backgroundSize: {
 | |
|         pattern: /background-size:\s*([^;]+)/g,
 | |
|         replacement: (match, value) => [
 | |
|             `-webkit-background-size: ${value}`,
 | |
|             `background-size: ${value}`
 | |
|         ]
 | |
|     }
 | |
| };
 | |
| 
 | |
| function addVendorPrefixesToFile(filePath) {
 | |
|     try {
 | |
|         let content = fs.readFileSync(filePath, 'utf8');
 | |
|         let modifications = 0;
 | |
|         const fileName = path.basename(filePath);
 | |
|         
 | |
|         console.log(`\nProcessing: ${fileName}`);
 | |
|         
 | |
|         // Skip files that already have vendor prefixes
 | |
|         if (content.includes('/* Vendor Prefixes Added */')) {
 | |
|             console.log('  ✓ Vendor prefixes already exist, skipping');
 | |
|             return 0;
 | |
|         }
 | |
|         
 | |
|         // Process flexbox properties
 | |
|         Object.entries(VENDOR_PREFIXES.flexbox).forEach(([property, prefixes]) => {
 | |
|             const regex = new RegExp(`${property.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')}(?=\\s*;)`, 'g');
 | |
|             const matches = content.match(regex);
 | |
|             
 | |
|             if (matches && matches.length > 0) {
 | |
|                 content = content.replace(regex, prefixes.join(';\n    ') + ';');
 | |
|                 modifications += matches.length;
 | |
|                 console.log(`  ✓ Added ${matches.length} flexbox prefixes for: ${property}`);
 | |
|             }
 | |
|         });
 | |
|         
 | |
|         // Process other properties with regex patterns
 | |
|         Object.entries(VENDOR_PREFIXES).forEach(([category, config]) => {
 | |
|             if (category === 'flexbox') return; // Already processed above
 | |
|             
 | |
|             if (config.pattern && config.replacement) {
 | |
|                 const matches = [...content.matchAll(config.pattern)];
 | |
|                 
 | |
|                 if (matches.length > 0) {
 | |
|                     matches.forEach(match => {
 | |
|                         const replacements = typeof config.replacement === 'function' 
 | |
|                             ? config.replacement(match[0], match[1])
 | |
|                             : config.replacement;
 | |
|                         
 | |
|                         content = content.replace(match[0], replacements.join(';\n    ') + ';');
 | |
|                     });
 | |
|                     
 | |
|                     modifications += matches.length;
 | |
|                     console.log(`  ✓ Added ${matches.length} ${category} prefixes`);
 | |
|                 }
 | |
|             }
 | |
|         });
 | |
|         
 | |
|         // Add special handling for CSS Grid fallbacks
 | |
|         if (content.includes('display: grid')) {
 | |
|             const gridFallbacks = `
 | |
| /* CSS Grid Fallbacks for IE */
 | |
| .hvac-stats-row,
 | |
| .hvac-dashboard-stats,
 | |
| .hvac-certificate-stats {
 | |
|     display: -ms-grid;
 | |
|     -ms-grid-columns: repeat(auto-fit, minmax(200px, 1fr));
 | |
| }
 | |
| 
 | |
| /* Progressive enhancement for modern browsers */
 | |
| @supports (display: grid) {
 | |
|     .hvac-stats-row,
 | |
|     .hvac-dashboard-stats,
 | |
|     .hvac-certificate-stats {
 | |
|         display: grid;
 | |
|     }
 | |
| }`;
 | |
| 
 | |
|             if (!content.includes('/* CSS Grid Fallbacks for IE */')) {
 | |
|                 content += gridFallbacks;
 | |
|                 modifications += 3;
 | |
|                 console.log('  ✓ Added CSS Grid IE fallbacks');
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         // Add feature detection support
 | |
|         const featureDetection = `
 | |
| /* Feature Detection Support */
 | |
| @supports not (display: flex) {
 | |
|     .hvac-content [class*="flex"] {
 | |
|         display: table-cell;
 | |
|         vertical-align: middle;
 | |
|     }
 | |
| }
 | |
| 
 | |
| @supports not (display: grid) {
 | |
|     .hvac-content [class*="grid"] {
 | |
|         display: block;
 | |
|         overflow: hidden;
 | |
|     }
 | |
|     
 | |
|     .hvac-content [class*="grid"] > * {
 | |
|         float: left;
 | |
|         width: 50%;
 | |
|     }
 | |
| }`;
 | |
| 
 | |
|         if (!content.includes('/* Feature Detection Support */') && modifications > 0) {
 | |
|             content += featureDetection;
 | |
|             modifications += 2;
 | |
|             console.log('  ✓ Added feature detection fallbacks');
 | |
|         }
 | |
|         
 | |
|         // Add vendor prefix marker
 | |
|         if (modifications > 0) {
 | |
|             content = `/* Vendor Prefixes Added - ${new Date().toISOString().split('T')[0]} */\n${content}`;
 | |
|         }
 | |
|         
 | |
|         // Write the updated content
 | |
|         fs.writeFileSync(filePath, content, 'utf8');
 | |
|         
 | |
|         if (modifications > 0) {
 | |
|             console.log(`  ✅ Added ${modifications} vendor prefixes total`);
 | |
|             prefixRules.push({
 | |
|                 file: fileName,
 | |
|                 modifications: modifications
 | |
|             });
 | |
|         } else {
 | |
|             console.log('  • No vendor prefixes needed');
 | |
|         }
 | |
|         
 | |
|         return modifications;
 | |
|         
 | |
|     } catch (error) {
 | |
|         console.error(`Error processing ${filePath}:`, error.message);
 | |
|         return 0;
 | |
|     }
 | |
| }
 | |
| 
 | |
| function createAutoprefixerConfig() {
 | |
|     const configPath = './autoprefixer.config.js';
 | |
|     const configContent = `module.exports = {
 | |
|     browsers: [
 | |
|         '> 1%',
 | |
|         'last 2 versions',
 | |
|         'Firefox ESR',
 | |
|         'not dead',
 | |
|         'IE 11'
 | |
|     ],
 | |
|     grid: 'autoplace',
 | |
|     flexbox: 'no-2009'
 | |
| };`;
 | |
| 
 | |
|     if (!fs.existsSync(configPath)) {
 | |
|         fs.writeFileSync(configPath, configContent, 'utf8');
 | |
|         console.log('✓ Created autoprefixer.config.js for future builds');
 | |
|     }
 | |
| }
 | |
| 
 | |
| function main() {
 | |
|     console.log('HVAC Community Events - CSS Vendor Prefix Fixes');
 | |
|     console.log('='.repeat(60));
 | |
|     
 | |
|     if (!fs.existsSync(CSS_DIR)) {
 | |
|         console.error(`CSS directory not found: ${CSS_DIR}`);
 | |
|         process.exit(1);
 | |
|     }
 | |
|     
 | |
|     // Focus on the main HVAC plugin CSS files
 | |
|     const hvacFiles = [
 | |
|         '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 = hvacFiles.filter(filePath => fs.existsSync(filePath));
 | |
|     
 | |
|     let totalModifications = 0;
 | |
|     
 | |
|     // Process each CSS file
 | |
|     existingFiles.forEach(filePath => {
 | |
|         totalModifications += addVendorPrefixesToFile(filePath);
 | |
|     });
 | |
|     
 | |
|     // Create autoprefixer config for future builds
 | |
|     createAutoprefixerConfig();
 | |
|     
 | |
|     console.log('\n' + '='.repeat(60));
 | |
|     console.log('VENDOR PREFIX FIX SUMMARY');
 | |
|     console.log('='.repeat(60));
 | |
|     
 | |
|     if (prefixRules.length > 0) {
 | |
|         prefixRules.forEach(rule => {
 | |
|             console.log(`${rule.file}: ${rule.modifications} prefixes added`);
 | |
|         });
 | |
|     }
 | |
|     
 | |
|     console.log(`\nTotal files processed: ${existingFiles.length}`);
 | |
|     console.log(`Total vendor prefixes added: ${totalModifications}`);
 | |
|     
 | |
|     if (totalModifications > 0) {
 | |
|         console.log('\n✅ Vendor prefix fixes applied successfully!');
 | |
|         console.log('\nKey improvements:');
 | |
|         console.log('• Added -webkit- prefixes for Safari/Chrome');
 | |
|         console.log('• Added -ms- prefixes for IE/Edge');
 | |
|         console.log('• Added -moz- prefixes for Firefox');
 | |
|         console.log('• Added CSS Grid IE fallbacks');
 | |
|         console.log('• Added @supports feature detection');
 | |
|         console.log('• Created autoprefixer.config.js for builds');
 | |
|         
 | |
|         console.log('\n📋 Browser Support:');
 | |
|         console.log('• Chrome/Safari: All modern features');
 | |
|         console.log('• Firefox: All modern features');
 | |
|         console.log('• Edge: All modern features');
 | |
|         console.log('• IE 11: Graceful fallbacks provided');
 | |
|         
 | |
|         console.log('\n💡 Next Steps:');
 | |
|         console.log('• Test in IE 11 to verify fallbacks');
 | |
|         console.log('• Consider adding PostCSS/Autoprefixer to build process');
 | |
|         console.log('• Validate with BrowserStack or similar tools');
 | |
|     } else {
 | |
|         console.log('\n✅ All CSS files already have vendor prefixes');
 | |
|     }
 | |
| }
 | |
| 
 | |
| if (require.main === module) {
 | |
|     main();
 | |
| }
 | |
| 
 | |
| module.exports = { addVendorPrefixesToFile, VENDOR_PREFIXES }; |