Files
Starlight_Lancher/scripts/axolotl/skin-site-messages.mjs
T
AxTps fd341d4b9e
Sync source to CNB / Sync Git ref (push) Skipped
fix: 统一皮肤站文案脚本的拼写
2026-10-20 22:09:31 +08:00

60 lines
1.9 KiB
JavaScript

import fs from 'node:fs'
import path from 'node:path'
import { createRequire } from 'node:module'
const require = createRequire(new URL('../../apps/app-frontend/package.json', import.meta.url))
const ts = require('typescript')
const { parse } = require('vue/compiler-sfc')
/** Read the message IDs actually used by skin-site UI, including uncataloged messages. */
export function collectSkinSiteMessages(root = 'apps/app-frontend/src') {
const messages = new Map()
function walk(directory) {
for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
const file = path.join(directory, entry.name)
if (entry.isDirectory()) {
if (entry.name !== 'locales') walk(file)
continue
}
if (!/\.(vue|ts)$/.test(file) || file.endsWith('.test.ts')) continue
let source = fs.readFileSync(file, 'utf8')
if (file.endsWith('.vue')) {
const { descriptor } = parse(source)
source = [descriptor.script?.content, descriptor.scriptSetup?.content]
.filter(Boolean)
.join('\n')
}
const ast = ts.createSourceFile(`${file}.ts`, source, ts.ScriptTarget.Latest, true)
function visit(node) {
if (ts.isObjectLiteralExpression(node)) {
const properties = Object.fromEntries(
node.properties
.filter(ts.isPropertyAssignment)
.map((property) => [
property.name.getText(ast).replace(/^['"]|['"]$/g, ''),
property.initializer,
]),
)
if (
properties.id &&
properties.defaultMessage &&
ts.isStringLiteralLike(properties.id) &&
ts.isStringLiteralLike(properties.defaultMessage) &&
properties.id.text.startsWith('app.skin-site.')
) {
messages.set(properties.id.text, {
id: properties.id.text,
defaultMessage: properties.defaultMessage.text,
file,
})
}
}
ts.forEachChild(node, visit)
}
visit(ast)
}
}
walk(root)
return [...messages.values()]
}