139 lines
4.0 KiB
JavaScript
139 lines
4.0 KiB
JavaScript
|
const fs = require('fs')
|
||
|
const path = require('path')
|
||
|
|
||
|
/**
|
||
|
* PB 模块导入导出代码生成器
|
||
|
* @param {string} pbDir - PB 文件所在的目录路径
|
||
|
* @param {string} outputFile - 生成的代码输出文件路径
|
||
|
* @param {string} [relativePath='../pb'] - 导入语句中的相对路径
|
||
|
*/
|
||
|
function generatePbImportsAndExports(pbDir, outputFile, relativePath = '../pb') {
|
||
|
try {
|
||
|
// 读取 PB 目录下的所有文件
|
||
|
const files = fs.readdirSync(pbDir)
|
||
|
|
||
|
// 过滤出 .js 文件并去除扩展名
|
||
|
const jsFiles = files.filter((file) => file.endsWith('.js'))
|
||
|
|
||
|
if (jsFiles.length === 0) {
|
||
|
console.warn(`警告: 在目录 ${pbDir} 中没有找到任何 .js 文件`)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// 生成导入语句
|
||
|
const importStatements = jsFiles
|
||
|
.map((file) => {
|
||
|
const moduleName = file.replace('.js', '')
|
||
|
return `import ${moduleName} from '${relativePath}/${moduleName}.js'`
|
||
|
})
|
||
|
.join('\n')
|
||
|
|
||
|
// 为每个文件生成导出内容
|
||
|
const moduleExports = {}
|
||
|
const allExports = new Set()
|
||
|
const exportSources = {} // 记录每个导出项的来源
|
||
|
|
||
|
jsFiles.forEach((file) => {
|
||
|
const filePath = path.join(pbDir, file)
|
||
|
const code = fs.readFileSync(filePath, 'utf-8')
|
||
|
const moduleName = file.replace('.js', '')
|
||
|
|
||
|
// 提取 $root.X 形式的导出
|
||
|
const rootExports = extractRootExports(code)
|
||
|
|
||
|
// 提取 enum 定义
|
||
|
const enumExports = extractEnumExports(code)
|
||
|
|
||
|
// 合并所有导出
|
||
|
const exports = [...rootExports, ...enumExports]
|
||
|
|
||
|
if (exports.length > 0) {
|
||
|
moduleExports[moduleName] = exports
|
||
|
|
||
|
// 记录导出项的来源
|
||
|
exports.forEach((exp) => {
|
||
|
if (!exportSources[exp]) {
|
||
|
exportSources[exp] = moduleName
|
||
|
allExports.add(exp)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
})
|
||
|
|
||
|
if (allExports.size === 0) {
|
||
|
console.warn(`警告: 没有找到任何可导出的类或枚举`)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// 生成解构赋值语句(只包含首次出现的导出项)
|
||
|
const destructureStatements = Object.entries(moduleExports)
|
||
|
.map(([moduleName, exports]) => {
|
||
|
// 过滤出该模块独有的导出项
|
||
|
const uniqueExports = exports.filter((exp) => exportSources[exp] === moduleName)
|
||
|
if (uniqueExports.length > 0) {
|
||
|
return `const { ${uniqueExports.join(', ')} } = ${moduleName}`
|
||
|
}
|
||
|
return ''
|
||
|
})
|
||
|
.filter(Boolean) // 移除空字符串
|
||
|
.join('\n')
|
||
|
|
||
|
// 生成导出语句(所有唯一导出项)
|
||
|
const exportList = Array.from(allExports)
|
||
|
|
||
|
// 完整的输出代码
|
||
|
const outputCode =
|
||
|
`// 由 pb-import-export-generator 自动生成,请勿手动修改\n\n` +
|
||
|
`// 导入语句\n${importStatements}\n\n` +
|
||
|
`// 解构赋值\n${destructureStatements}\n\n` +
|
||
|
`// 导出语句\nexport {\n ${exportList.join(',\n ')}\n};\n`
|
||
|
|
||
|
// 确保输出目录存在
|
||
|
const outputDir = path.dirname(outputFile)
|
||
|
if (!fs.existsSync(outputDir)) {
|
||
|
fs.mkdirSync(outputDir, { recursive: true })
|
||
|
}
|
||
|
|
||
|
// 写入输出文件
|
||
|
fs.writeFileSync(outputFile, outputCode)
|
||
|
|
||
|
console.log(`成功生成 PB 导入导出代码到 ${outputFile}`)
|
||
|
console.log(`共生成 ${jsFiles.length} 个导入语句和 ${exportList.length} 个导出变量`)
|
||
|
} catch (error) {
|
||
|
console.error('生成 PB 导入导出代码时出错:', error.message)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 提取 $root.X 形式的导出
|
||
|
*/
|
||
|
function extractRootExports(code) {
|
||
|
const exports = []
|
||
|
const rootExportRegex = /\$root\.([A-Za-z][A-Za-z0-9_]*)\s*=/g
|
||
|
|
||
|
let match
|
||
|
while ((match = rootExportRegex.exec(code)) !== null) {
|
||
|
exports.push(match[1])
|
||
|
}
|
||
|
|
||
|
return exports
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 提取 enum 定义
|
||
|
*/
|
||
|
function extractEnumExports(code) {
|
||
|
const exports = []
|
||
|
const enumRegex = /@enum\s*{.*?}\s*\n\s*\*\s*@exports\s+([A-Za-z][A-Za-z0-9_]*)/g
|
||
|
|
||
|
let match
|
||
|
while ((match = enumRegex.exec(code)) !== null) {
|
||
|
exports.push(match[1])
|
||
|
}
|
||
|
|
||
|
return exports
|
||
|
}
|
||
|
|
||
|
// 示例用法
|
||
|
generatePbImportsAndExports('../assets/scripts/pb', '../assets/scripts/network/pbExport.ts')
|