|
| 1 | +#!/usr/bin/env node |
| 2 | + |
| 3 | +/** |
| 4 | + * Script to validate CSS variables consistency between repositories |
| 5 | + * This script extracts CSS variable names from the TypeScript interface |
| 6 | + * and compares them with the implementation in another repository |
| 7 | + */ |
| 8 | + |
| 9 | +const fs = require('fs'); |
| 10 | +const path = require('path'); |
| 11 | + |
| 12 | +/** |
| 13 | + * Extract CSS variable names from the TypeScript interface |
| 14 | + * @param {string} filePath - Path to the css-variables.ts file |
| 15 | + * @returns {string[]} Array of CSS variable names |
| 16 | + */ |
| 17 | +function extractVariablesFromInterface(filePath) { |
| 18 | + try { |
| 19 | + const content = fs.readFileSync(filePath, 'utf8'); |
| 20 | + |
| 21 | + // Extract variable names using regex |
| 22 | + const variableRegex = /'--ts-var-[^']+'/g; |
| 23 | + const matches = content.match(variableRegex); |
| 24 | + |
| 25 | + if (!matches) { |
| 26 | + console.error('No CSS variables found in the interface file'); |
| 27 | + return []; |
| 28 | + } |
| 29 | + |
| 30 | + // Remove quotes and sort for consistent comparison |
| 31 | + return matches.map(match => match.replace(/'/g, '')).sort(); |
| 32 | + } catch (error) { |
| 33 | + console.error(`Error reading interface file: ${error.message}`); |
| 34 | + return []; |
| 35 | + } |
| 36 | +} |
| 37 | + |
| 38 | +/** |
| 39 | + * Extract CSS variable names from the implementation object |
| 40 | + * @param {string} content - Content of the implementation file |
| 41 | + * @returns {string[]} Array of CSS variable names |
| 42 | + */ |
| 43 | +function extractVariablesFromImplementation(content) { |
| 44 | + try { |
| 45 | + // Extract variable names from object keys |
| 46 | + const variableRegex = /'--ts-var-[^']+':/g; |
| 47 | + const matches = content.match(variableRegex); |
| 48 | + |
| 49 | + if (!matches) { |
| 50 | + console.error('No CSS variables found in the implementation'); |
| 51 | + return []; |
| 52 | + } |
| 53 | + |
| 54 | + // Remove quotes and colon, then sort for consistent comparison |
| 55 | + return matches.map(match => match.replace(/[':]/g, '')).sort(); |
| 56 | + } catch (error) { |
| 57 | + console.error(`Error parsing implementation: ${error.message}`); |
| 58 | + return []; |
| 59 | + } |
| 60 | +} |
| 61 | + |
| 62 | +/** |
| 63 | + * Compare two arrays of CSS variables and report differences |
| 64 | + * @param {string[]} interfaceVars - Variables from TypeScript interface |
| 65 | + * @param {string[]} implementationVars - Variables from implementation |
| 66 | + * @returns {object} Comparison result |
| 67 | + */ |
| 68 | +function compareVariables(interfaceVars, implementationVars) { |
| 69 | + const missingInImplementation = interfaceVars.filter(varName => !implementationVars.includes(varName)); |
| 70 | + const extraInImplementation = implementationVars.filter(varName => !interfaceVars.includes(varName)); |
| 71 | + |
| 72 | + return { |
| 73 | + interfaceCount: interfaceVars.length, |
| 74 | + implementationCount: implementationVars.length, |
| 75 | + missingInImplementation, |
| 76 | + extraInImplementation, |
| 77 | + isConsistent: missingInImplementation.length === 0 && extraInImplementation.length === 0 |
| 78 | + }; |
| 79 | +} |
| 80 | + |
| 81 | +/** |
| 82 | + * Main validation function |
| 83 | + */ |
| 84 | +function validateCSSVariables() { |
| 85 | + console.log('🔍 Validating CSS variables consistency...\n'); |
| 86 | + |
| 87 | + // Path to the interface file |
| 88 | + const interfacePath = path.join(__dirname, '..', 'src', 'css-variables.ts'); |
| 89 | + |
| 90 | + // Check if interface file exists |
| 91 | + if (!fs.existsSync(interfacePath)) { |
| 92 | + console.error(`❌ Interface file not found: ${interfacePath}`); |
| 93 | + process.exit(1); |
| 94 | + } |
| 95 | + |
| 96 | + // Extract variables from interface |
| 97 | + const interfaceVars = extractVariablesFromInterface(interfacePath); |
| 98 | + console.log(`📋 Found ${interfaceVars.length} variables in TypeScript interface`); |
| 99 | + |
| 100 | + // Get implementation content from command line argument or environment |
| 101 | + const implementationContent = process.argv[2] || process.env.CSS_VARS_IMPLEMENTATION; |
| 102 | + |
| 103 | + if (!implementationContent) { |
| 104 | + console.log('⚠️ No implementation content provided. Use:'); |
| 105 | + console.log(' node validate-css-variables.js "implementation content"'); |
| 106 | + console.log(' or set CSS_VARS_IMPLEMENTATION environment variable'); |
| 107 | + console.log('\n📋 Variables in interface:'); |
| 108 | + interfaceVars.forEach(varName => console.log(` - ${varName}`)); |
| 109 | + return; |
| 110 | + } |
| 111 | + |
| 112 | + // Extract variables from implementation |
| 113 | + const implementationVars = extractVariablesFromImplementation(implementationContent); |
| 114 | + console.log(`🔧 Found ${implementationVars.length} variables in implementation`); |
| 115 | + |
| 116 | + // Compare variables |
| 117 | + const comparison = compareVariables(interfaceVars, implementationVars); |
| 118 | + |
| 119 | + console.log('\n📊 Comparison Results:'); |
| 120 | + console.log(` Interface variables: ${comparison.interfaceCount}`); |
| 121 | + console.log(` Implementation variables: ${comparison.implementationCount}`); |
| 122 | + |
| 123 | + if (comparison.isConsistent) { |
| 124 | + console.log('\n✅ CSS variables are consistent between repositories!'); |
| 125 | + process.exit(0); |
| 126 | + } else { |
| 127 | + console.log('\n❌ CSS variables are NOT consistent:'); |
| 128 | + |
| 129 | + if (comparison.missingInImplementation.length > 0) { |
| 130 | + console.log('\n🔴 Missing in implementation:'); |
| 131 | + comparison.missingInImplementation.forEach(varName => { |
| 132 | + console.log(` - ${varName}`); |
| 133 | + }); |
| 134 | + } |
| 135 | + |
| 136 | + if (comparison.extraInImplementation.length > 0) { |
| 137 | + console.log('\n🟡 Extra in implementation:'); |
| 138 | + comparison.extraInImplementation.forEach(varName => { |
| 139 | + console.log(` - ${varName}`); |
| 140 | + }); |
| 141 | + } |
| 142 | + |
| 143 | + console.log('\n💡 To fix this:'); |
| 144 | + console.log(' 1. Add missing variables to the implementation'); |
| 145 | + console.log(' 2. Remove extra variables from the implementation'); |
| 146 | + console.log(' 3. Or update the TypeScript interface if needed'); |
| 147 | + |
| 148 | + process.exit(1); |
| 149 | + } |
| 150 | +} |
| 151 | + |
| 152 | +// Run validation if this script is executed directly |
| 153 | +if (require.main === module) { |
| 154 | + validateCSSVariables(); |
| 155 | +} |
| 156 | + |
| 157 | +module.exports = { |
| 158 | + extractVariablesFromInterface, |
| 159 | + extractVariablesFromImplementation, |
| 160 | + compareVariables, |
| 161 | + validateCSSVariables |
| 162 | +}; |
0 commit comments