analyze-hex-distribution.js 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. #!/usr/bin/env node
  2. /**
  3. * 统计全站剩余硬编码色值分布(按 <style> 块内),找出高频可令牌化色值
  4. * 用法: node scripts/analyze-hex-distribution.js
  5. */
  6. const fs = require('fs')
  7. const path = require('path')
  8. const ROOT = path.resolve(__dirname, '..')
  9. const EXCLUDE_DIRS = new Set(['node_modules', 'dist', 'unpackage', '.git', 'docs'])
  10. function walk(dir, out = []) {
  11. for (const name of fs.readdirSync(dir)) {
  12. if (EXCLUDE_DIRS.has(name)) continue
  13. const p = path.join(dir, name)
  14. const st = fs.statSync(p)
  15. if (st.isDirectory()) walk(p, out)
  16. else if (name.endsWith('.vue')) out.push(p)
  17. }
  18. return out
  19. }
  20. const files = walk(ROOT)
  21. const counts = {} // hex → count
  22. const fileMap = {} // hex → Set(fileRel)
  23. const HEX_IN_STYLE = /#[0-9a-fA-F]{3,8}\b/g
  24. for (const f of files) {
  25. const src = fs.readFileSync(f, 'utf8')
  26. // 只统计 style 块内
  27. const styleBlocks = [...src.matchAll(/(<style[^>]*>)([\s\S]*?)(<\/style>)/gi)]
  28. const rel = path.relative(ROOT, f).split(path.sep).join('/')
  29. for (const m of styleBlocks) {
  30. const body = m[2]
  31. for (const hexMatch of body.match(HEX_IN_STYLE) || []) {
  32. const upper = hexMatch.toUpperCase()
  33. if (!counts[upper]) { counts[upper] = 0; fileMap[upper] = new Set() }
  34. counts[upper]++
  35. fileMap[upper].add(rel)
  36. }
  37. }
  38. }
  39. const sorted = Object.entries(counts).sort((a, b) => b[1] - a[1])
  40. console.log('=== <style> 块内 TOP 60 硬编码色 ===')
  41. for (const [hex, count] of sorted.slice(0, 60)) {
  42. const filesN = fileMap[hex].size
  43. const sample = [...fileMap[hex]].slice(0, 3).join(', ')
  44. console.log(`${String(count).padStart(5)} ${hex} (${filesN}文件) e.g. ${sample}`)
  45. }