collect-charset.mjs 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. // 采集驾驶舱的「实际用字清单」——中文字体子集化的输入(规格 11:中文字体必须子集化)。
  2. //
  3. // 为什么是源码而不是运行时:运行时文本来自后端(设备名/点位名/事件文本),无法穷举,
  4. // 这正是规格 11 要求「子集字体必须保留系统回退链」的原因——子集外汉字落到系统字体。
  5. // 本脚本只收「源码里能看到的静态用字」+ 设计稿可见文案,动态值不假装能覆盖。
  6. //
  7. // 用法:node .scratch/lanhu-cockpit-asset-replacement/tools/collect-charset.mjs
  8. import { readFileSync, writeFileSync, readdirSync, statSync } from 'node:fs'
  9. import { join, dirname } from 'node:path'
  10. import { fileURLToPath } from 'node:url'
  11. const here = dirname(fileURLToPath(import.meta.url))
  12. const ROOT = join(here, '..', '..', '..')
  13. function walk(dir, exts, out = []) {
  14. for (const name of readdirSync(dir)) {
  15. if (name === 'node_modules') continue
  16. const p = join(dir, name)
  17. if (statSync(p).isDirectory()) walk(p, exts, out)
  18. else if (exts.some((e) => name.endsWith(e))) out.push(p)
  19. }
  20. return out
  21. }
  22. const sourceFiles = walk(join(ROOT, 'src', 'modules', 'cockpit'), ['.vue', '.js', '.css'])
  23. const staticChars = new Set()
  24. for (const f of sourceFiles) {
  25. for (const ch of readFileSync(f, 'utf8')) if (ch.codePointAt(0) > 0x7f) staticChars.add(ch)
  26. }
  27. // 设计稿可见文案(raw-v2 的 Figma JSON):补上「源码没有但设计稿有」的字
  28. const designChars = new Set()
  29. const rawV2 = join(here, '..', 'research', 'raw-v2')
  30. for (const f of readdirSync(rawV2)) {
  31. for (const ch of readFileSync(join(rawV2, f), 'utf8')) {
  32. const cp = ch.codePointAt(0)
  33. if (cp > 0x2e80) designChars.add(ch)
  34. }
  35. }
  36. // 子集文本 = 静态用字 ∪ 设计稿文案 ∪ 可打印 ASCII
  37. const ascii = Array.from({ length: 0x7f - 0x20 }, (_, i) => String.fromCodePoint(0x20 + i)).join('')
  38. const subsetChars = new Set([...staticChars, ...designChars, ...ascii])
  39. const result = {
  40. note: '驾驶舱静态用字清单;运行时动态文本不在内,故子集字体必须保留系统回退链(规格 11)。',
  41. sources: {
  42. sourceFiles: sourceFiles.length,
  43. staticChars: staticChars.size,
  44. designChars: designChars.size,
  45. },
  46. subsetText: [...subsetChars].sort().join(''),
  47. }
  48. writeFileSync(join(here, 'charset.json'), JSON.stringify(result, null, 2), 'utf8')
  49. console.log('source files:', sourceFiles.length)
  50. console.log('static non-ASCII chars:', staticChars.size, '| design-only chars:', designChars.size)
  51. console.log('subset text chars:', subsetChars.size)
  52. console.log('wrote tools/charset.json')