d36-round8-rules.js 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. #!/usr/bin/env node
  2. /**
  3. * D36: 第八轮令牌收割(仅登记 uni.scss 已有等值令牌的残留 hex)
  4. * 排除 8 位带 alpha 的 hex(如 #F9731622),避免丢失透明度
  5. */
  6. const fs = require('fs');
  7. const path = require('path');
  8. function norm(h) {
  9. const x = h.toUpperCase();
  10. const body = x.slice(1);
  11. if (body.length === 3) return '#' + body.split('').map(c => c + c).join('');
  12. return x;
  13. }
  14. const scss = fs.readFileSync('uni.scss', 'utf8');
  15. const byHex = {};
  16. for (const line of scss.split(/\r?\n/)) {
  17. const m = line.match(/^\s*(\$[\w-]+)\s*:\s*(#[0-9a-fA-F]{3,8})\s*;/);
  18. if (m) {
  19. const k = norm(m[2]);
  20. (byHex[k] = byHex[k] || []).push(m[1]);
  21. }
  22. }
  23. const RULES_FILE = 'scripts/replace-hex-to-token.js';
  24. let ruleSrc = fs.readFileSync(RULES_FILE, 'utf8');
  25. const ruleUpper = ruleSrc.toUpperCase();
  26. const HEX = /#[0-9a-fA-F]{3,8}\b/g;
  27. const counts = new Map();
  28. function walk(d) {
  29. for (const n of fs.readdirSync(d)) {
  30. if (['node_modules', 'dist', 'unpackage', '.git', 'scripts', '.tmp_equiv'].includes(n)) continue;
  31. const p = path.join(d, n);
  32. const st = fs.statSync(p);
  33. if (st.isDirectory()) walk(p);
  34. else if (n.endsWith('.vue')) {
  35. const s = fs.readFileSync(p, 'utf8');
  36. const si = s.search(/<style/);
  37. if (si === -1) continue;
  38. (s.slice(si).match(HEX) || []).forEach(h => counts.set(h.toUpperCase(), (counts.get(h.toUpperCase()) || 0) + 1));
  39. }
  40. }
  41. }
  42. walk('.');
  43. const pairs = [];
  44. for (const [hex, cnt] of counts) {
  45. if (hex.slice(1).length === 8) continue; // 带 alpha,跳过
  46. const tokens = byHex[norm(hex)];
  47. if (!tokens) continue;
  48. if (ruleUpper.includes("'" + hex + "'")) continue; // 已登记
  49. pairs.push({ hex, token: tokens[0], cnt });
  50. }
  51. pairs.sort((a, b) => b.cnt - a.cnt);
  52. if (!pairs.length) {
  53. console.log('无新增可映射 hex');
  54. process.exit(0);
  55. }
  56. const lines = pairs.map(p =>
  57. " ['" + p.hex + "', '" + p.token + "'],\n ['" + p.hex.toLowerCase() + "', '" + p.token + "'],"
  58. ).join('\n');
  59. ruleSrc = ruleSrc.replace(
  60. /\n\]\.sort\(\(a, b\) => b\[0\]\.length - a\[0\]\.length\)/,
  61. '\n // ---- 第八轮(uni.scss 已有令牌补登记,2026-10-21)----\n' + lines + '\n].sort((a, b) => b[0].length - a[0].length)'
  62. );
  63. fs.writeFileSync(RULES_FILE, ruleSrc);
  64. console.log('登记规则数:', pairs.length);
  65. console.log(pairs.map(p => p.hex + ' x' + p.cnt + ' -> ' + p.token).join('\n'));