Files
2024-09-27 00:58:46 +08:00

283 lines
8.6 KiB
JavaScript
Raw Permalink 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.

const Glob = require('glob');
const pify = require('pify');
const path = require('path');
const fs = require('fs');
const { parseComponent } = require('vue-template-compiler')
const glob = pify(Glob);
let globPath = "";
let OptionSetting = {};
// 获取文件路径,构造路由参数数组
generateRoutesAndFiles = async (PagePath) => {
const files = {};
(await glob(`${PagePath}/**/*.{vue,js,tsx,jsx}`, {
cwd: path.resolve(process.cwd(), OptionSetting.RootFolderName),
ignore: ['**/*.test.*', '**/*.spec.*', '**/-*.*']
})).forEach((f) => {
const key = f.replace(/\.(js|vue)$/, '')
if (/\.vue$/.test(f) || !files[key]) {
files[key] = f.replace(/('|")/g, '\\$1')
}
});
return createRoutes(
Object.values(files),
path.resolve(process.cwd(), OptionSetting.RootFolderName),
PagePath
)
};
// 填充路由配置
// `Utils.AsyncComponentHook('${camelCase(keys.join('-').replace('_', ''))}')`
const createRoutes = function createRoutes(files, srcDir, pagesDir) {
const routes = [];
files.forEach((file) => {
const keys = file
.replace(RegExp(`^${pagesDir}`), '')
.replace(/\.(vue|js)$/, '')
.replace(/\/{2,}/g, '/')
.split('/')
.slice(1);
const route = {
name: '',
path: '',
component: `_() => import(/* webpackChunkName: '${keys.toString().replace(/,/g, "")}' */ '@/${pagesDir}/${keys.join('/')}.vue')`,
meta: JSON.parse(routeMeta(file))
};
let parent = routes;
keys.forEach((key, i) => {
const sanitizedKey = key.startsWith('_') ? key.substr(1) : key;
route.name = route.name
? route.name + '-' + sanitizedKey
: sanitizedKey;
route.name += key === '_' ? 'all' : '';
const child = parent.find(parentRoute => parentRoute.name === route.name);
if (child) {
child.children = child.children || [];
parent = child.children;
route.path = '';
} else if (key === 'index' && i + 1 === keys.length) {
route.path += i > 0 ? '' : '/';
} else {
route.path += '/' + getRoutePathExtension(key);
if (key.startsWith('_') && key.length > 1) {
route.path += '?';
}
}
});
parent.push(route);
});
sortRoutes(routes);
return cleanChildrenRoutes(routes)
};
const startsWithAlias = aliasArray => str => aliasArray.some(c => str.startsWith(c));
const reqSep = /\//g;
const sysSep = escapeRegExp(path.sep);
const normalize = string => string.replace(reqSep, sysSep);
const startsWithSrcAlias = startsWithAlias(['@', '~']);
function routeMeta(f) {
let meta = {};
const VuePath = path.join(__dirname,`../../.${OptionSetting.RootFolderName}/${f}`);
let VueSource = fs.readFileSync(VuePath);
const parsed = parseComponent(VueSource.toString(), { pad: 'space' });
const routeMetaBlock = parsed.customBlocks.find(
b => b.type === 'route-meta'
);
if(routeMetaBlock) {
return routeMetaBlock.content;
} else {
return JSON.stringify({
test: `请在组件配置route-meta 标签参考文档https://www.npmjs.com/package/vue-cli-plugin-autorouter`
})
}
}
const r = function r(...args) {
const lastArg = args[args.length - 1];
if (startsWithSrcAlias(lastArg)) {
return wp(lastArg)
}
return wp(path.resolve(...args.map(normalize)))
};
function baseToString(value) {
if (typeof value == 'string') {
return value;
}
if (isArray_1(value)) {
return _arrayMap(value, baseToString) + '';
}
if (isSymbol_1(value)) {
return symbolToString ? symbolToString.call(value) : '';
}
var result = (value + '');
return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
}
function toString(value) {
return value == null ? '' : baseToString(value);
}
function escapeRegExp(string) {
const reRegExpChar = /[\\^$.*+?()[\]{}|]/g,
reHasRegExpChar = RegExp(reRegExpChar.source);
string = toString(string);
return (string && reHasRegExpChar.test(string)) ?
string.replace(reRegExpChar, '\\$&') :
string;
}
const isWindows = /^win/.test(process.platform);
const wp = function wp(p = '') {
if (isWindows) {
return p.replace(/\\/g, '\\\\')
}
return p
};
const getRoutePathExtension = (key) => {
if (key === '_') {
return '*'
}
if (key.startsWith('_')) {
return `:${key.substr(1)}`
}
return key
};
const DYNAMIC_ROUTE_REGEX = /^\/(:|\*)/;
/**
* 排序路由
* @param {*} routes
*/
function sortRoutes(routes) {
routes.sort((a, b) => {
if (!a.path.length) {
return -1
}
if (!b.path.length) {
return 1
}
if (a.path === '/') {
return DYNAMIC_ROUTE_REGEX.test(b.path) ? -1 : 1
}
if (b.path === '/') {
return DYNAMIC_ROUTE_REGEX.test(a.path) ? 1 : -1
}
let i
let res = 0
let y = 0
let z = 0
const _a = a.path.split('/')
const _b = b.path.split('/')
for (i = 0; i < _a.length; i++) {
if (res !== 0) {
break
}
y = _a[i] === '*' ? 2 : _a[i].includes(':') ? 1 : 0
z = _b[i] === '*' ? 2 : _b[i].includes(':') ? 1 : 0
res = y - z
// If a.length >= b.length
if (i === _b.length - 1 && res === 0) {
// unless * found sort by level, then alphabetically
res = _a[i] === '*' ? -1 : (
_a.length === _b.length ? a.path.localeCompare(b.path) : (_a.length - _b.length)
)
}
}
if (res === 0) {
res = _a[i - 1] === '*' && _b[i] ? 1 : (
_a.length === _b.length ? a.path.localeCompare(b.path) : (_a.length - _b.length)
)
}
return res
})
routes.forEach((route) => {
if (route.children) {
sortRoutes(route.children)
}
})
return routes
}
function cleanChildrenRoutes(routes, isChild = false) {
let start = -1
const routesIndex = []
routes.forEach((route) => {
if (/-index$/.test(route.name) || route.name === 'index') {
const res = route.name.split('-')
const s = res.indexOf('index')
start = start === -1 || s < start ? s : start
routesIndex.push(res)
}
})
routes.forEach((route) => {
route.path = isChild ? route.path.replace('/', '') : route.path
if (route.path.includes('?')) {
const names = route.name.split('-')
const paths = route.path.split('/')
if (!isChild) {
paths.shift()
}
routesIndex.forEach((r) => {
const i = r.indexOf('index') - start
if (i < paths.length) {
for (let a = 0; a <= i; a++) {
if (a === i) {
paths[a] = paths[a].replace('?', '')
}
if (a < i && names[a] !== r[a]) {
break
}
}
}
})
route.path = (isChild ? '' : '/') + paths.join('/')
}
route.name = route.name.replace(/-index$/, '')
if (route.children) {
if (route.children.find(child => child.path === '')) {
delete route.name
}
route.children = cleanChildrenRoutes(route.children, true)
}
})
return routes
}
function camelCase(string) {
return string.replace(/-([a-z])/g, function (all, letter) {
return letter.toUpperCase();
});
}
module.exports.creatRouter = (flag = false, root) => {
if (flag) return;
OptionSetting = root;
generateRoutesAndFiles(OptionSetting.TemplateFolderName).then(res => {
let string = `// 根据page目录结构自动生成的路由配置文件\n// 参考Nuxt.jshttps://zh.nuxtjs.org/guide/routing\n// @ts-ignore\n\n`;
string += `export const AutoRoutesConfig = ${JSON.stringify(res, null, 2)};`
.replace(/"component": "(\w+?)"/g, `"component": $1`)
.replace(/"(\w+?)":/g, '$1:')
.replace(/"_()/g, "")
.replace(/vue'\)"/g, "vue')");
let buildPath = path.resolve(process.cwd(), path.join(__dirname, OptionSetting.SaveConfigPath));
fs.writeFileSync(buildPath, string);
})
};