update-brand-book.js
1 #!/usr/bin/env node 2 /** 3 * Update Brand Book 4 * 5 * Automatically updates the brand-book/index.html with current token values 6 * from src/tokens/index.ts 7 * 8 * Run: node scripts/update-brand-book.js 9 */ 10 11 import { readFileSync, writeFileSync } from 'fs'; 12 import { resolve, dirname } from 'path'; 13 import { fileURLToPath } from 'url'; 14 15 const __dirname = dirname(fileURLToPath(import.meta.url)); 16 const ROOT = resolve(__dirname, '..'); 17 18 // Read tokens from TypeScript file 19 const tokensPath = resolve(ROOT, 'src/tokens/index.ts'); 20 const tokensContent = readFileSync(tokensPath, 'utf-8'); 21 22 // Extract color values using regex 23 function extractColors(content) { 24 const colors = { alpha: {}, delta: {} }; 25 26 // Match alpha colors 27 const alphaMatch = content.match(/alpha:\s*\{([^}]+)\}/s); 28 if (alphaMatch) { 29 const colorMatches = alphaMatch[1].matchAll(/(\d+):\s*['"]([#\w]+)['"]/g); 30 for (const match of colorMatches) { 31 colors.alpha[match[1]] = match[2]; 32 } 33 } 34 35 // Match delta colors 36 const deltaMatch = content.match(/delta:\s*\{([^}]+)\}/s); 37 if (deltaMatch) { 38 const colorMatches = deltaMatch[1].matchAll(/(\d+):\s*['"]([#\w]+)['"]/g); 39 for (const match of colorMatches) { 40 colors.delta[match[1]] = match[2]; 41 } 42 } 43 44 // Match semantic colors 45 const semanticMatch = content.match(/semantic:\s*\{([^}]+)\}/s); 46 if (semanticMatch) { 47 colors.semantic = {}; 48 const colorMatches = semanticMatch[1].matchAll(/(\w+):\s*['"]([#\w]+)['"]/g); 49 for (const match of colorMatches) { 50 colors.semantic[match[1]] = match[2]; 51 } 52 } 53 54 return colors; 55 } 56 57 const colors = extractColors(tokensContent); 58 59 // Generate CSS variables block 60 function generateCSSVariables(colors) { 61 let css = ''; 62 63 // Alpha colors 64 css += ' /* Alpha Chain - Trust, Technology, Security */\n'; 65 for (const [shade, value] of Object.entries(colors.alpha)) { 66 css += ` --alpha-${shade}: ${value};\n`; 67 } 68 69 css += '\n /* Delta Chain - Energy, Exchange, Commerce (Orange scale) */\n'; 70 for (const [shade, value] of Object.entries(colors.delta)) { 71 css += ` --delta-${shade}: ${value};\n`; 72 } 73 74 if (colors.semantic) { 75 css += '\n /* Semantic */\n'; 76 for (const [name, value] of Object.entries(colors.semantic)) { 77 css += ` --${name}: ${value};\n`; 78 } 79 } 80 81 return css; 82 } 83 84 // Read brand book 85 const brandBookPath = resolve(ROOT, 'brand-book/index.html'); 86 let brandBook = readFileSync(brandBookPath, 'utf-8'); 87 88 // Update CSS variables in :root 89 const cssVarsRegex = /(\/\* Alpha Chain[^]*?--delta-900:[^;]+;)/; 90 const newCSSVars = `/* Alpha Chain - Trust, Technology, Security */ 91 --alpha-50: ${colors.alpha['50']}; 92 --alpha-100: ${colors.alpha['100']}; 93 --alpha-200: ${colors.alpha['200']}; 94 --alpha-300: ${colors.alpha['300']}; 95 --alpha-400: ${colors.alpha['400']}; 96 --alpha-500: ${colors.alpha['500']}; 97 --alpha-600: ${colors.alpha['600']}; 98 --alpha-700: ${colors.alpha['700']}; 99 --alpha-800: ${colors.alpha['800']}; 100 --alpha-900: ${colors.alpha['900']}; 101 102 /* Delta Chain - Energy, Exchange, Commerce (Orange scale) */ 103 --delta-50: ${colors.delta['50']}; 104 --delta-100: ${colors.delta['100']}; 105 --delta-200: ${colors.delta['200']}; 106 --delta-300: ${colors.delta['300']}; 107 --delta-400: ${colors.delta['400']}; 108 --delta-500: ${colors.delta['500']}; 109 --delta-600: ${colors.delta['600']}; 110 --delta-700: ${colors.delta['700']}; 111 --delta-800: ${colors.delta['800']}; 112 --delta-900: ${colors.delta['900']}`; 113 114 brandBook = brandBook.replace(cssVarsRegex, newCSSVars); 115 116 // Update color documentation text 117 const alphaHexRegex = /<strong>Primary:<\/strong> <code>#[A-Fa-f0-9]+<\/code> \(500\) · <strong>Hover:<\/strong> <code>#[A-Fa-f0-9]+<\/code> \(600\)<\/p>\s*<h2>Delta/; 118 brandBook = brandBook.replace( 119 alphaHexRegex, 120 `<strong>Primary:</strong> <code>${colors.alpha['500']}</code> (500) · <strong>Hover:</strong> <code>${colors.alpha['600']}</code> (600)</p>\n\n <h2>Delta` 121 ); 122 123 const deltaHexRegex = /<strong>Primary:<\/strong> <code>#[A-Fa-f0-9]+<\/code> \(500\) · <strong>Hover:<\/strong> <code>#[A-Fa-f0-9]+<\/code> \(600\)<\/p>\s*<h2>Semantic/; 124 brandBook = brandBook.replace( 125 deltaHexRegex, 126 `<strong>Primary:</strong> <code>${colors.delta['500']}</code> (500) · <strong>Hover:</strong> <code>${colors.delta['600']}</code> (600)</p>\n\n <h2>Semantic` 127 ); 128 129 // Write updated brand book 130 writeFileSync(brandBookPath, brandBook); 131 132 console.log('✓ Brand book updated with current token values'); 133 console.log(' Alpha 500:', colors.alpha['500']); 134 console.log(' Delta 500:', colors.delta['500']); 135 console.log(' Delta 50:', colors.delta['50'], '(light shade)');