2020-10-27 14:31:37 +08:00

164 lines
5.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// pages
// ├── index.vue # 根路由页面 路径 /
// ├── *.vue # 模糊匹配 路径 *
// ├── a.vue # 路径 /a
// ├── b
// │ ├── index.vue # 路径 /b
// │ ├── @id.vue # 动态路由 /b/:id
// │ └── c.vue # 路径 /b/c
// └── layout.vue # 根路由下所有page共用的外层
const fs = require('fs');
const Path = require('path');
const isProcessFile = function (path) {
const ext = Path.extname(path);
return fs.statSync(path).isFile() && ['.fes', '.vue'].includes(ext);
};
const isProcessDirectory = function (path, item) {
const component = Path.join(path, item);
return fs.statSync(component).isDirectory() && !['components'].includes(item);
};
const checkHasLayout = function (path) {
const dirList = fs.readdirSync(path);
return dirList.some((item) => {
if (!isProcessFile(Path.join(path, item))) {
return false;
}
const ext = Path.extname(item);
const fileName = Path.basename(item, ext);
return fileName === 'layout';
});
};
const getRouteName = function (parentRoutePath, fileName) {
const routeName = Path.posix.join(parentRoutePath, fileName);
return routeName.slice(1).replace(/\//g, '_').replace(/@/g, '_').replace(/\*/g, 'FUZZYMATCH');
};
const getRoutePath = function (parentRoutePath, fileName) {
// /index.vue -> /
if (fileName === 'index') {
fileName = '';
}
let routePath = Path.posix.join(parentRoutePath, fileName);
// /@id.vue -> /:id
routePath = routePath.replace(/@/g, ':');
// /*.vue -> *
if (routePath === '/*') {
routePath = '*';
}
return routePath;
};
const build = function (components, parentRoutes, path, parentRoutePath) {
const dirList = fs.readdirSync(path);
const hasLayout = checkHasLayout(path);
const layoutRoute = {
children: []
};
if (hasLayout) {
layoutRoute.path = parentRoutePath;
parentRoutes.push(layoutRoute);
}
dirList.forEach((item) => {
// 文件或者目录的绝对路径
const component = Path.join(path, item);
if (isProcessFile(component)) {
const ext = Path.extname(item);
const fileName = Path.basename(item, ext);
// 路由的path
const routePath = getRoutePath(parentRoutePath, fileName);
// 路由名称
const routeName = getRouteName(parentRoutePath, fileName);
components.push({
name: routeName,
path: component.replace(/\\/g, '\\\\') // 处理windows兼容性
});
if (hasLayout) {
if (fileName === 'layout') {
layoutRoute.component = routeName;
} else {
layoutRoute.children.push({
path: routePath,
component: routeName,
name: routeName
});
}
} else {
parentRoutes.push({
path: routePath,
component: routeName,
name: routeName
});
}
}
});
dirList.forEach((item) => {
if (isProcessDirectory(path, item)) {
// 文件或者目录的绝对路径
const component = Path.join(path, item);
const nextParentRouteUrl = Path.posix.join(parentRoutePath, item);
if (hasLayout) {
build(components, layoutRoute.children, component, nextParentRouteUrl);
} else {
build(components, parentRoutes, component, nextParentRouteUrl);
}
}
});
};
/**
* 智能路由
* 1、路由的路径是多个“/”组成的字符串,使用“/”分割后得到不同的子项
* 2、计算子项个数用个数乘以4计入得分
* 3、判断子项是否是静态的即不包含“”、“*”等特殊字符串若是计入3分。
* 4、判断子项是否是动态的即包含“”特殊字符若是计入2分。
* 5、判断子项是否是模糊匹配即包含“*”特殊字符若是扣除1分。
* 6、判断子项是否是根端即只是“/”若是计入1分。
* @param {*} routes
*/
const fix = function (routes) {
routes.forEach((item) => {
const path = item.path;
let arr = path.split('/');
if (arr[0] === '') {
arr = arr.slice(1);
}
let count = 0;
arr.forEach((sonPath) => {
count += 4;
if (sonPath.indexOf(':') !== -1) {
count += 2;
} else if (sonPath.indexOf('*') !== -1) {
count -= 1;
} else if (sonPath === '') {
count += 1;
} else {
count += 3;
}
});
item.count = count;
if (item.children && item.children.length) {
fix(item.children);
}
});
routes = routes.sort((a, b) => b.count - a.count);
};
module.exports = function (pageDir) {
const components = [];
const routes = [];
build(components, routes, pageDir, '/');
fix(routes);
return {
components,
routes
};
};