You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
222 lines
5.8 KiB
222 lines
5.8 KiB
const { readFileSync, existsSync } = require('fs') |
|
const { resolve } = require('path') |
|
const parser = require('@babel/parser') |
|
const traverse = require('@babel/traverse').default |
|
|
|
/** |
|
* 路由分析模块 |
|
* 负责分析路由配置,从import语句中提取模块信息 |
|
*/ |
|
class RouteAnalyzer { |
|
constructor() { |
|
this.routes = [] |
|
this.componentModuleMap = new Map() // 组件名 -> 模块名的映射 |
|
} |
|
|
|
/** |
|
* 分析路由配置 |
|
* @returns {Array} 路由数组 |
|
*/ |
|
analyzeRoutes() { |
|
this.routes = [] |
|
this.componentModuleMap.clear() |
|
|
|
try { |
|
const routeConfigPath = resolve(__dirname, '../../src/renderer/router/index.js') |
|
if (existsSync(routeConfigPath)) { |
|
const routeContent = readFileSync(routeConfigPath, 'utf-8') |
|
|
|
// 第一步:解析import语句,建立组件与模块的映射关系 |
|
this.parseImportStatements(routeContent) |
|
|
|
// 第二步:解析路由配置,为每个路由添加模块信息 |
|
this.routes = this.parseRouteConfig(routeContent) |
|
} |
|
} catch (error) { |
|
// 静默处理错误 |
|
} |
|
|
|
return this.routes |
|
} |
|
|
|
/** |
|
* 解析import语句,建立组件与模块的映射关系 |
|
* @param {string} routeContent - 路由配置内容 |
|
*/ |
|
parseImportStatements(routeContent) { |
|
try { |
|
const ast = parser.parse(routeContent, { |
|
sourceType: 'module', |
|
plugins: ['jsx', 'typescript'] |
|
}) |
|
|
|
const self = this |
|
traverse(ast, { |
|
ImportDeclaration(path) { |
|
const source = path.node.source.value |
|
|
|
// 解析模块路径,提取模块名 |
|
const moduleName = self.extractModuleName(source) |
|
if (moduleName) { |
|
// 处理导入的组件 |
|
path.node.specifiers.forEach(spec => { |
|
let componentName = null |
|
|
|
if (spec.type === 'ImportDefaultSpecifier') { |
|
// 默认导入:import Component from '...' |
|
componentName = spec.local.name |
|
} else if (spec.type === 'ImportSpecifier') { |
|
// 命名导入:import { Component } from '...' |
|
componentName = spec.imported.name |
|
} |
|
|
|
if (componentName) { |
|
self.componentModuleMap.set(componentName, moduleName) |
|
} |
|
}) |
|
} |
|
} |
|
}) |
|
} catch (error) { |
|
// 静默处理错误 |
|
} |
|
} |
|
|
|
/** |
|
* 从import路径中提取模块名 |
|
* @param {string} importPath - import路径 |
|
* @returns {string|null} 模块名 |
|
*/ |
|
extractModuleName(importPath) { |
|
// 匹配 @/modules/module-name 格式 |
|
const moduleMatch = importPath.match(/@\/modules\/([^\/]+)/) |
|
if (moduleMatch) { |
|
return moduleMatch[1] |
|
} |
|
return null |
|
} |
|
|
|
/** |
|
* 解析路由配置,为每个路由添加模块信息 |
|
* @param {string} routeContent - 路由配置内容 |
|
* @returns {Array} 路由数组 |
|
*/ |
|
parseRouteConfig(routeContent) { |
|
const routes = [] |
|
|
|
try { |
|
const ast = parser.parse(routeContent, { |
|
sourceType: 'module', |
|
plugins: ['jsx', 'typescript'] |
|
}) |
|
|
|
const self = this |
|
traverse(ast, { |
|
ObjectExpression(path) { |
|
// 查找路由对象 |
|
if (self.isRouteObject(path)) { |
|
const route = self.extractRouteInfo(path) |
|
if (route) { |
|
routes.push(route) |
|
} |
|
} |
|
} |
|
}) |
|
} catch (error) { |
|
// 静默处理错误 |
|
} |
|
|
|
return routes |
|
} |
|
|
|
/** |
|
* 判断是否是路由对象 |
|
* @param {Object} path - AST路径 |
|
* @returns {boolean} 是否是路由对象 |
|
*/ |
|
isRouteObject(path) { |
|
const properties = path.node.properties |
|
return properties.some(prop => |
|
prop.key && prop.key.name === 'path' && |
|
prop.value && prop.value.type === 'StringLiteral' |
|
) |
|
} |
|
|
|
/** |
|
* 从路由对象中提取路由信息 |
|
* @param {Object} path - AST路径 |
|
* @returns {Object|null} 路由信息 |
|
*/ |
|
extractRouteInfo(path) { |
|
const route = {} |
|
const properties = path.node.properties |
|
|
|
properties.forEach(prop => { |
|
if (prop.key && prop.value) { |
|
const key = prop.key.name |
|
const value = prop.value |
|
|
|
switch (key) { |
|
case 'path': |
|
if (value.type === 'StringLiteral') { |
|
route.path = value.value |
|
} |
|
break |
|
case 'component': |
|
if (value.type === 'Identifier') { |
|
route.component = value.name |
|
// 从组件名获取模块信息 |
|
const moduleName = this.componentModuleMap.get(value.name) |
|
if (moduleName) { |
|
route.module = moduleName |
|
} |
|
} |
|
break |
|
case 'name': |
|
if (value.type === 'StringLiteral') { |
|
route.name = value.value |
|
} |
|
break |
|
case 'description': |
|
if (value.type === 'StringLiteral') { |
|
route.description = value.value |
|
} |
|
break |
|
} |
|
} |
|
}) |
|
|
|
// 只有当path和component都存在时才返回路由信息 |
|
if (route.path && route.component) { |
|
return route |
|
} |
|
|
|
return null |
|
} |
|
|
|
/** |
|
* 获取模块列表 |
|
* @returns {Array} 模块目录列表 |
|
*/ |
|
getModuleDirs() { |
|
const moduleDirs = [] |
|
|
|
try { |
|
const modulesPath = resolve(__dirname, '../../src/renderer/modules') |
|
if (existsSync(modulesPath)) { |
|
const dirs = require('fs').readdirSync(modulesPath, { withFileTypes: true }) |
|
dirs.forEach(dirent => { |
|
if (dirent.isDirectory()) { |
|
moduleDirs.push(dirent.name) |
|
} |
|
}) |
|
} |
|
} catch (error) { |
|
// 静默处理错误 |
|
} |
|
|
|
return moduleDirs |
|
} |
|
} |
|
|
|
module.exports = RouteAnalyzer
|
|
|