| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 |
- // 输出画板分类所需信息:顶层图层、文本样本、图片填充、字体与色板汇总
- import { readFileSync, writeFileSync, readdirSync } from 'node:fs'
- import { join } from 'node:path'
- const dir = '.scratch/lanhu-cockpit-asset-replacement/research/raw'
- const files = readdirSync(dir).filter((f) => /^desktop-\d+\.json$/.test(f)).sort()
- function hex(c) {
- const h = (v) => Math.round(v * 255).toString(16).padStart(2, '0')
- return `#${h(c.r)}${h(c.g)}${h(c.b)}`
- }
- const detail = []
- const globalColors = new Map()
- const globalFonts = new Map()
- let totalAssets = 0
- let totalImageFills = 0
- let flagImage = 0
- let flagDds = 0
- for (const file of files) {
- const j = JSON.parse(readFileSync(join(dir, file), 'utf8'))
- const ab = j.artboard
- const texts = []
- const images = []
- const fonts = new Map()
- function walk(node) {
- if (node.hasExportImage) flagImage += 1
- if (node.hasExportDDSImage) flagDds += 1
- if (node.type === 'textLayer' && node.text?.style?.content && texts.length < 40) {
- texts.push(String(node.text.style.content).slice(0, 24))
- }
- if (node.type === 'textLayer' && node.text?.style?.font?.name) {
- const fam = node.text.style.font.name
- fonts.set(fam, (fonts.get(fam) || 0) + 1)
- globalFonts.set(fam, (globalFonts.get(fam) || 0) + 1)
- }
- for (const f of node.style?.fills || []) {
- if (f.type === 'color' && f.color) {
- const c = hex(f.color)
- globalColors.set(c, (globalColors.get(c) || 0) + 1)
- }
- const url = f.ddsImage?.imageUrl || f.image?.imageUrl || f.imageUrl
- if (f.type === 'image' && url) {
- images.push({ name: node.name, path: '', w: Math.round(node.frame?.width ?? 0), h: Math.round(node.frame?.height ?? 0), url })
- }
- }
- for (const ch of node.layers || []) walk(ch)
- }
- for (const l of ab.layers || []) walk(l)
- totalAssets += (j.assets || []).length
- totalImageFills += images.length
- detail.push({
- file,
- artboard: ab.name,
- frame: { w: ab.frame.width, h: ab.frame.height },
- topLayers: (ab.layers || []).map((l) => `${l.type}:${l.name}`),
- texts,
- images,
- fonts: [...fonts.entries()].sort((a, b) => b[1] - a[1]),
- assetFiles: j.assets || [],
- })
- }
- writeFileSync(join(dir, 'inventory-detail.json'), JSON.stringify(detail, null, 1))
- for (const d of detail) {
- console.log(`\n=== ${d.artboard} (${d.frame.w}x${d.frame.h})`)
- console.log(' top:', d.topLayers.join(', ').slice(0, 300))
- console.log(' texts:', d.texts.slice(0, 26).join(' | ').slice(0, 320))
- console.log(' images:', d.images.map((i) => `${i.name}(${i.w}x${i.h})`).join(', ').slice(0, 260))
- console.log(' fonts:', d.fonts.map(([f, c]) => `${f}×${c}`).join(', ').slice(0, 260))
- }
- console.log('\n=== GLOBAL')
- console.log('assets files:', totalAssets, '| image fills:', totalImageFills, '| flagImage:', flagImage, '| flagDds:', flagDds)
- console.log('fonts:', [...globalFonts.entries()].sort((a, b) => b[1] - a[1]).map(([f, c]) => `${f}×${c}`).join(', '))
- console.log('palette:', [...globalColors.entries()].sort((a, b) => b[1] - a[1]).slice(0, 40).map(([c, n]) => `${c}×${n}`).join(' '))
|