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.
332 lines
8.6 KiB
332 lines
8.6 KiB
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.writeNewRoute = writeNewRoute;
|
|
exports.getNewRouteCode = getNewRouteCode;
|
|
exports.writeRouteNode = writeRouteNode;
|
|
|
|
function _react() {
|
|
const data = _interopRequireDefault(require("react"));
|
|
|
|
_react = function _react() {
|
|
return data;
|
|
};
|
|
|
|
return data;
|
|
}
|
|
|
|
function _fs() {
|
|
const data = require("fs");
|
|
|
|
_fs = function _fs() {
|
|
return data;
|
|
};
|
|
|
|
return data;
|
|
}
|
|
|
|
function _path() {
|
|
const data = require("path");
|
|
|
|
_path = function _path() {
|
|
return data;
|
|
};
|
|
|
|
return data;
|
|
}
|
|
|
|
function parser() {
|
|
const data = _interopRequireWildcard(require("@babel/parser"));
|
|
|
|
parser = function parser() {
|
|
return data;
|
|
};
|
|
|
|
return data;
|
|
}
|
|
|
|
function _traverse() {
|
|
const data = _interopRequireDefault(require("@babel/traverse"));
|
|
|
|
_traverse = function _traverse() {
|
|
return data;
|
|
};
|
|
|
|
return data;
|
|
}
|
|
|
|
function _generator() {
|
|
const data = _interopRequireDefault(require("@babel/generator"));
|
|
|
|
_generator = function _generator() {
|
|
return data;
|
|
};
|
|
|
|
return data;
|
|
}
|
|
|
|
function t() {
|
|
const data = _interopRequireWildcard(require("@babel/types"));
|
|
|
|
t = function t() {
|
|
return data;
|
|
};
|
|
|
|
return data;
|
|
}
|
|
|
|
function _utils() {
|
|
const data = require("@umijs/utils");
|
|
|
|
_utils = function _utils() {
|
|
return data;
|
|
};
|
|
|
|
return data;
|
|
}
|
|
|
|
function _prettier() {
|
|
const data = _interopRequireDefault(require("prettier"));
|
|
|
|
_prettier = function _prettier() {
|
|
return data;
|
|
};
|
|
|
|
return data;
|
|
}
|
|
|
|
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
|
|
|
|
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
const debug = (0, _utils().createDebug)('umi-build-dev:writeNewRoute');
|
|
/**
|
|
* 将路由写入路由文件
|
|
* @param {*} newRoute 新的路由配置: { path, component, ... }
|
|
* @param {*} configPath 配置路径
|
|
* @param {*} absSrcPath 代码路径
|
|
*/
|
|
|
|
function writeNewRoute(newRoute, configPath, absSrcPath) {
|
|
const _getNewRouteCode = getNewRouteCode(configPath, newRoute, absSrcPath),
|
|
code = _getNewRouteCode.code,
|
|
routesPath = _getNewRouteCode.routesPath;
|
|
|
|
(0, _fs().writeFileSync)(routesPath, code, 'utf-8');
|
|
}
|
|
/**
|
|
* 获取目标
|
|
* @param {*} configPath
|
|
* @param {*} newRoute
|
|
*/
|
|
|
|
|
|
function getNewRouteCode(configPath, newRoute, absSrcPath) {
|
|
debug(`find routes in configPath: ${configPath}`);
|
|
const ast = parser().parse((0, _fs().readFileSync)(configPath, 'utf-8'), {
|
|
sourceType: 'module',
|
|
plugins: ['typescript']
|
|
});
|
|
let routesNode = null;
|
|
const importModules = []; // 查询当前配置文件是否导出 routes 属性
|
|
|
|
(0, _traverse().default)(ast, {
|
|
Program({
|
|
node
|
|
}) {
|
|
// find import
|
|
const body = node.body;
|
|
body.forEach(item => {
|
|
if (t().isImportDeclaration(item)) {
|
|
const specifiers = item.specifiers;
|
|
const defaultEpecifier = specifiers.find(s => t().isImportDefaultSpecifier(s) && t().isIdentifier(s.local));
|
|
|
|
if (defaultEpecifier && t().isStringLiteral(item.source)) {
|
|
importModules.push({
|
|
identifierName: defaultEpecifier.local.name,
|
|
modulePath: item.source.value
|
|
});
|
|
}
|
|
}
|
|
});
|
|
},
|
|
|
|
AssignmentExpression({
|
|
node
|
|
}) {
|
|
// for exports.routes
|
|
const left = node.left,
|
|
operator = node.operator,
|
|
right = node.right;
|
|
|
|
if (operator === '=' && t().isMemberExpression(left) && t().isIdentifier(left.object) && left.object.name === 'exports' && t().isIdentifier(left.property) && left.property.name === 'routes') {
|
|
routesNode = right;
|
|
}
|
|
},
|
|
|
|
ExportDefaultDeclaration({
|
|
node
|
|
}) {
|
|
// export default []
|
|
const declaration = node.declaration;
|
|
|
|
if (t().isArrayExpression(declaration)) {
|
|
routesNode = declaration;
|
|
}
|
|
},
|
|
|
|
ObjectExpression({
|
|
node,
|
|
parent
|
|
}) {
|
|
// find routes on object, like { routes: [] }
|
|
if (t().isArrayExpression(parent)) {
|
|
// children routes
|
|
return;
|
|
}
|
|
|
|
const properties = node.properties;
|
|
properties.forEach(p => {
|
|
const key = p.key,
|
|
value = p.value;
|
|
|
|
if (t().isObjectProperty(p) && t().isIdentifier(key) && key.name === 'routes') {
|
|
routesNode = value;
|
|
}
|
|
});
|
|
}
|
|
|
|
});
|
|
|
|
if (routesNode) {
|
|
// routes 配置不在当前文件, 需要 load 对应的文件 export default { routes: pageRoutes } case 1
|
|
if (!t().isArrayExpression(routesNode)) {
|
|
const source = importModules.find(m => m.identifierName === routesNode.name);
|
|
|
|
if (source) {
|
|
const newConfigPath = getModulePath(configPath, source.modulePath, absSrcPath);
|
|
return getNewRouteCode(newConfigPath, newRoute, absSrcPath);
|
|
}
|
|
|
|
throw new Error(`can not find import of ${routesNode.name}`);
|
|
} else {
|
|
// 配置在当前文件 // export default { routes: [] } case 2
|
|
writeRouteNode(routesNode, newRoute);
|
|
}
|
|
} else {
|
|
throw new Error('route array config not found.');
|
|
}
|
|
|
|
const code = generateCode(ast);
|
|
debug(code, configPath);
|
|
return {
|
|
code,
|
|
routesPath: configPath
|
|
};
|
|
}
|
|
|
|
function getNewRouteNode(newRoute) {
|
|
return parser().parse(`(${JSON.stringify(newRoute)})`).program.body[0].expression;
|
|
}
|
|
/**
|
|
* 写入节点
|
|
* @param {*} node 找到的节点
|
|
* @param {*} newRoute 新的路由配置
|
|
*/
|
|
|
|
|
|
function writeRouteNode(targetNode, newRoute, currentPath = '/') {
|
|
debug(`writeRouteNode currentPath newRoute.path: ${newRoute.path} currentPath: ${currentPath}`);
|
|
const elements = targetNode.elements;
|
|
const paths = elements.map(ele => {
|
|
if (!t().isObjectExpression(ele)) {
|
|
return false;
|
|
}
|
|
|
|
const properties = ele.properties;
|
|
const redirect = properties.find(p => p.key.name === 'redirect');
|
|
|
|
if (redirect) {
|
|
return false;
|
|
}
|
|
|
|
const pathProp = properties.find(p => p.key.name === 'path');
|
|
|
|
if (!pathProp) {
|
|
return currentPath;
|
|
}
|
|
|
|
let fullPath = pathProp.value.value;
|
|
|
|
if (fullPath.indexOf('/') !== 0) {
|
|
fullPath = (0, _path().join)(currentPath, fullPath);
|
|
}
|
|
|
|
return fullPath;
|
|
});
|
|
debug('paths', paths);
|
|
const matchedIndex = paths.findIndex(p => p && newRoute.path.indexOf((0, _utils().winPath)(p)) === 0);
|
|
const newNode = getNewRouteNode(newRoute);
|
|
|
|
if (matchedIndex === -1) {
|
|
elements.push(newNode); // return container for test
|
|
|
|
return targetNode;
|
|
} // matched, insert to children routes
|
|
|
|
|
|
const matchedEle = elements[matchedIndex];
|
|
const routesProp = matchedEle.properties.find(p => p.key.name === 'routes' || process.env.BIGFISH_COMPAT && p.key.name === 'childRoutes');
|
|
|
|
if (!routesProp) {
|
|
// not find children routes, insert before the matched element
|
|
elements.splice(matchedIndex, 0, newNode);
|
|
return targetNode;
|
|
}
|
|
|
|
return writeRouteNode(routesProp.value, newRoute, paths[matchedIndex]);
|
|
}
|
|
/**
|
|
* 生成代码
|
|
* @param {*} ast
|
|
*/
|
|
|
|
|
|
function generateCode(ast) {
|
|
const newCode = (0, _generator().default)(ast, {}).code;
|
|
return _prettier().default.format(newCode, {
|
|
// format same as ant-design-pro
|
|
singleQuote: true,
|
|
trailingComma: 'es5',
|
|
printWidth: 100,
|
|
parser: 'typescript'
|
|
});
|
|
}
|
|
/**
|
|
* 获取路由配置的真实路径
|
|
* @param {*} modulePath
|
|
*/
|
|
|
|
|
|
function getModulePath(configPath, modulePath, absSrcPath) {
|
|
// like @/route.config
|
|
if (/^@\//.test(modulePath)) {
|
|
modulePath = (0, _path().join)(absSrcPath, modulePath.replace(/^@\//, ''));
|
|
} else {
|
|
modulePath = (0, _path().join)((0, _path().dirname)(configPath), modulePath);
|
|
}
|
|
|
|
if (!/\.[j|t]s$/.test(modulePath)) {
|
|
if ((0, _fs().existsSync)(`${modulePath}.js`)) {
|
|
modulePath = `${modulePath}.js`;
|
|
} else {
|
|
modulePath = `${modulePath}.ts`;
|
|
}
|
|
}
|
|
|
|
return modulePath;
|
|
} |