Files
starRiverProperty/frontend/scripts/extract-router.js
T
hpd840321 7b2bd307f1 Initial commit: reorganized source tree
- backend/: 13 Maven modules (cw-elevator-application, cloudwalk-cloud, intelligent-cwoscomponent, ninca-crk, etc.)
- frontend/: 4 Vue projects (elevator-front, cwos-portal, alarm-front, front_acs) + decompiled + scripts
- scripts/: build, test-env, tools (Docker Compose, service templates, API parity)
- docs/: AGENTS.md, superpowers specs, architecture docs
- .gitignore: standard Java/Maven exclusions

Moved from legacy maven-*/ root layout to backend/ organized structure.
2026-05-09 09:56:45 +08:00

117 lines
4.3 KiB
JavaScript

#!/usr/bin/env node
/**
* 路由表提取器
* 从格式化后的 JS 中提取 vue-router 的 routes 定义
*
* 用法: node extract-router.js <formatted-dir> <output.json>
*/
const fs = require('fs');
const path = require('path');
const parser = require('@babel/parser');
const traverse = require('@babel/traverse').default;
function extractRouter(inputDir, outputFile) {
const files = fs.readdirSync(inputDir).filter(f => f.endsWith('.formatted.js'));
const routes = [];
for (const file of files) {
const code = fs.readFileSync(path.join(inputDir, file), 'utf-8');
try {
const ast = parser.parse(code, {
sourceType: 'script',
plugins: ['jsx', 'typescript', 'classProperties', 'dynamicImport'],
errorRecovery: true,
});
traverse(ast, {
// Match routes: [...] arrays containing path/component objects
ArrayExpression(nodePath) {
const node = nodePath.node;
const hasRoutes = node.elements.some(el =>
el.type === 'ObjectExpression' &&
el.properties.some(prop => prop.key && prop.key.name === 'path')
);
if (hasRoutes) {
node.elements.forEach(el => {
if (el.type === 'ObjectExpression') {
const routeDef = {};
el.properties.forEach(prop => {
if (prop.key && prop.key.type === 'Identifier') {
if (prop.key.name === 'path' && prop.value.type === 'StringLiteral') {
routeDef.path = prop.value.value;
}
if (prop.key.name === 'name' && prop.value.type === 'StringLiteral') {
routeDef.name = prop.value.value;
}
if (prop.key.name === 'meta' && prop.value.type === 'ObjectExpression') {
routeDef.meta = {};
prop.value.properties.forEach(mp => {
if (mp.key && mp.key.type === 'Identifier') {
routeDef.meta[mp.key.name] = mp.value.type === 'StringLiteral' ? mp.value.value : true;
}
});
}
if (prop.key.name === 'component') {
routeDef.component = prop.value.type === 'ArrowFunctionExpression'
? 'lazyImport'
: (prop.value.type === 'Identifier' ? prop.value.name : 'inline');
}
}
});
if (routeDef.path && !routes.find(r => r.path === routeDef.path)) {
routes.push(routeDef);
}
}
});
}
},
// Match path-like strings: /xxx/xxx
StringLiteral(nodePath) {
const value = nodePath.node.value;
if (typeof value === 'string' && /^\/[a-z][a-z0-9_/-]*$/i.test(value) && value.length > 2) {
const parent = nodePath.parent;
if (parent.type === 'ObjectProperty' && parent.key && parent.key.name === 'path') {
return; // Already handled above
}
if (!routes.find(r => r.path === value)) {
routes.push({ path: value, source: 'stringLiteral', file: file });
}
}
},
});
} catch (e) {
// Skip unparseable files
}
}
const result = routes.sort((a, b) => (a.path || '').localeCompare(b.path || ''));
fs.writeFileSync(outputFile, JSON.stringify(result, null, 2));
console.log(`提取完成: ${result.length} 条路由 → ${outputFile}`);
// Generate Markdown route table
const mdPath = outputFile.replace('.json', '.md');
let md = '# 路由表\n\n';
md += `| Path | Name | Component | Meta |\n`;
md += `|------|------|-----------|------|\n`;
result.forEach(r => {
md += `| \`${r.path || '-'}\` | ${r.name || '-'} | ${r.component || '-'} | ${r.meta ? JSON.stringify(r.meta) : '-'} |\n`;
});
fs.writeFileSync(mdPath, md);
console.log(`路由表 Markdown: ${mdPath}`);
}
const args = process.argv.slice(2);
if (args.length < 2) {
console.log('用法: node extract-router.js <formatted-dir> <output.json>');
process.exit(1);
}
extractRouter(args[0], args[1]);