60 lines
1.9 KiB
JavaScript
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()]
|
|
}
|