first commit

This commit is contained in:
编码猿
2024-09-27 01:00:10 +08:00
commit b00667a14d
12 changed files with 886 additions and 0 deletions

23
.gitignore vendored Normal file
View File

@@ -0,0 +1,23 @@
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

1
.pydio Normal file
View File

@@ -0,0 +1 @@
6e388d74-c773-45ae-bc65-b69a46cca116

326
README.md Normal file
View File

@@ -0,0 +1,326 @@
## vue-cli-plugin-autorouter
借鉴 [Nuxt.js](https://zh.nuxtjs.org/) 的路由源码实现。可以根据存放Vue-Router页面的文件夹结构自动生成Vue-Router配置文件。
**相信我,你会中毒的,妈妈再也不用担心我手动低效的去`Ctrl + C``Ctrl + V`了,一切交给插件自动生成路由配置文件,我们要做的就是按照规则维护好文件夹结构,世界突然美妙了。**
> 注意:这个插件目前为止还没有改成通用的插件包,有这个考虑。不过现阶段主要用于 [Vue3template](https://github.com/helpcode/Vue3template) 这个脚手架项目。后面还会考虑再开发一个脚手架项目的`cli`命令行工具,实现类似`Vue-cli`通过命令进行项目的初始化等功能。
## 1安装Vue3template默认已安装配置好可直接使用
注意这是一个基于[Vue-cli 3.0](https://cli.vuejs.org/zh/)也就是 vue-cli-service 开发的插件不支持老版本Vue 2.0的脚手架哦,请注意了!
```bash
vue add vue-cli-plugin-autorouter
```
`add`安装的时候会自动向你项目的`package.json``devDependencies`注入下面依赖:
```txt
"glob": "^7.1.3",
"pify": "^4.0.1"
```
这是 `vue-cli-service`插件开发`Generator`自动注入的,也是本插件需要使用到的依赖。请勿随意删除。
## 2配置
`vue.config.js`中你可以增加`pluginOptions`配置节点,实现对插件的自定义化需求定制:
```js
module.exports = {
// ...
pluginOptions: {
route: {
// 默认page。存放Vue路由页面的文件夹名称
TemplateFolderName: 'page',
// 默认:./src/application。从src/开始到TemplateFolderName文件夹父一级文件夹相对路径
RootFolderName: './src/application',
// 默认 src/core/config/route.config.ts。生成的配置文件保存路径相对插件的位置来。
SaveConfigPath: '../../../src/core/config/route.config.ts'
}
},
// ...
}
```
**然后你就可以很爽的直接使用命令,注意这个命令是用来自动生成配置文件的:**
```bash
vue-cli-service route
```
> 注意:每次项目新增页面后,请重新执行此命令用以生成新的路由配置文件!!
不过,推荐在项目的`package.json`中做如下配置:
```txt
"scripts": {
"serve": "npm run route && vue-cli-service serve",
"route": "vue-cli-service route",
"build": "vue-cli-service build",
},
```
注意:一定要在 `vue-cli-service serve`命令运行前,先跑`vue-cli-service route`来扫描`src/application/page`的文件结构进而自动生成`Vue-Router`的配置文件。默认配置文件保存在:`src/core/config/route.config.ts`中。
## 3卸载
东西再好,总有些开发者拒绝学习,或者拒绝尝试新的东西,喜欢固守自己已熟知的技术栈,那么下面提供卸载`Vue3template`自带的` vue-cli-plugin-autorouter`教程。
### 3.1: 删除依赖(两种方式)
- 1: 使用npm命令卸载依赖
```bash
npm uninstall --save glob pify vue-cli-plugin-autorouter
```
- 2: 从`package.json`中手动删除下面依赖信息
```text
"glob": "^7.1.3",
"pify": "^4.0.1",
"vue-cli-plugin-autorouter": "^1.1.8",
```
然后删除项目`node_modules`,在重新`npm i`
### 3.2: vue.config.js
`vue.config.js`中你删除`pluginOptions`配置节点。
### 3.3: 修改源码
1: 从`src/core/config`中删除文件`route.config.ts`
2然后修改`index.config.ts`,去除:`import { AutoRoutesConfig } from './route.config';`
3之后修改`RouterConfigUrl`中的`routes`对象,`routes`对象的内容需要你自己手动
> 注意:`RouterConfigUrl` 中的 `routes` 需要你自己手动配置了,这里提供一份配置参考:
```typescript
public static RouterConfigUrl: RouterOptions = {
mode: 'hash',
routes: [
{
name: "user",
path: "/user",
component: () => import(/* webpackChunkName: '[request]' */ '@/page/user/index.vue'),
meta: {}
},
{
name: "user-one",
path: "/user/one",
component: () => import(/* webpackChunkName: '[request]' */ '@/page/user/one.vue'),
meta: {}
},
{
name: "index",
path: "/",
component: () => import(/* webpackChunkName: '[request]' */ '@/page/index.vue'),
meta: {}
}
]
}
```
## 【新增功能】4路由meta配置
`page/`文件夹的组件中使用可以直接使用自定义标签`<route-meta></route-meta>`来实现对路由`meta`的直接配置,插件会提取`<route-meta></route-meta>`中的代码直接注入到生成的路由配置文件中。下面请看使用案例:
```vue
<route-meta>
{
"isLogin": false,
"title": "首页"
}
</route-meta>
<template lang="pug">
.home
h2 测试标题
</template>
```
**注意这里`route-meta`标签中填的必须是一个`JSON`对象,注意书写格式,不能有误!!**
那么自动生成的路由配置如下:
```js
{
name: "index",
path: "/",
component: () => import(/* webpackChunkName: 'index' */ '@/page/index.vue'),
meta: {
isLogin: false,
title: "首页"
}
}
```
## 5使用
这里使用请注意文件夹结构,多看几次下面的例子加强理解,以便能够更好的组织自己的路由结构!!
### 5.1: 基础路由
基础路由很简单,直接在`page/`文件下新建`vue`组件即可,插件会根据文件结构自动生成路由配置文件!!
假设 page 的目录结构如下:
```txt
pages/
--| user/
-----| index.vue
-----| one.vue
--| index.vue
```
那么自动生成的路由配置如下:
```js
[
{
name: "user",
path: "/user",
component: () => import(/* webpackChunkName: '[request]' */ '@/page/user/index.vue'),
meta: {}
},
{
name: "user-one",
path: "/user/one",
component: () => import(/* webpackChunkName: '[request]' */ '@/page/user/one.vue'),
meta: {}
},
{
name: "index",
path: "/",
component: () => import(/* webpackChunkName: '[request]' */ '@/page/index.vue'),
meta: {}
}
]
```
### 5.2: 动态路由(带参数)
如果路由需要参数,那么可以按照命名的规则:`_参数名.vue`,在`user/`文件夹创建`Vue`组件。例如这里的:`_id.vue`,其实这里的 `_id.vue`就相当于我们平时开发时用的`user_info.vue`组件。
假设 page 的目录结构如下:
```txt
page/
--| user/
-----| _id.vue
--| index.vue
```
那么自动生成的路由配置如下:
```js
[
{
name: "user-id",
path: "/user/:id?",
component: () => import(/* webpackChunkName: '[request]' */ '@/page/user/_id.vue'),
meta: {}
},
{
name: "index",
path: "/",
component: () => import(/* webpackChunkName: '[request]' */ '@/page/index.vue'),
meta: {}
}
]
```
---
这里我们有了`user-id`组件(相当于 `user_info.vue`),那么`user`首页组件如何添加?其实很简单!
基于上面的文件结构在`user/`里面在创建一个`index.vue`组件即可,默认文件夹下面的`index.vue`作为路由的首页
改变后的文件结构如下:
```txt
page/
--| user/
-----| _id.vue # 这个相当于平时开发的 user_info.vue个人中心的详情页面
-----| index.vue # user首页类似个人中心
--| index.vue
```
那么自动生成的路由配置如下:
```js
[
{
name: "user",
path: "/user",
component: () => import(/* webpackChunkName: '[request]' */ '@/page/user/index.vue'),
meta: {}
},
{
name: "user-id",
path: "/user/:id",
component: () => import(/* webpackChunkName: '[request]' */ '@/page/user/_id.vue'),
meta: {}
},
{
name: "index",
path: "/",
component: () => import(/* webpackChunkName: '[request]' */ '@/page/index.vue'),
meta: {}
}
]
````
### 5.3: 嵌套路由
创建内嵌子路由上面我们已经有了`user/`文件夹那么我们可以在`user/`文件夹同级目录创建一个名字一样的`Vue`组件这里添加`user.vue`!
假设 page 的目录结构如下
```txt
page/
--| user/
-----| _id.vue
-----| index.vue
--| user.vue
--| index.vue
```
那么自动生成的路由配置如下:
```js
[
{
path: "/user",
component: () => import(/* webpackChunkName: '[request]' */ '@/page/user.vue'),
meta: {},
children: [
{
name: "user",
path: "",
component: () => import(/* webpackChunkName: '[request]' */ '@/page/user/index.vue'),
meta: {}
},
{
name: "user-id",
path: ":id",
component: () => import(/* webpackChunkName: '[request]' */ '@/page/user/_id.vue'),
meta: {}
}
]
},
{
name: "index",
path: "/",
component: () => import(/* webpackChunkName: '[request]' */ '@/page/index.vue'),
meta: {}
}
]
```
> 记住:这是嵌套路由所以别忘记在`user.vue`组件中添加:`router-view` 来展示子路由的页面。

1
generator/.pydio Normal file
View File

@@ -0,0 +1 @@
7d22662f-47a9-47f7-9945-1c842bb893aa

11
generator/index.js Normal file
View File

@@ -0,0 +1,11 @@
module.exports = (api, options, rootOptions) => {
api.extendPackage({
devDependencies: {
"@babel/generator": "^7.11.4",
"@babel/types": "^7.11.0",
"@babel/parser": "^7.11.4",
"glob": "^7.1.3",
"pify": "^4.0.1"
},
});
}

17
index.js Normal file
View File

@@ -0,0 +1,17 @@
const creatRouter = require('./service/regist-route')
require('./utils/welcome');
module.exports = (api, projectOptions) => {
api.registerCommand('route', {
description: '根据page文件结构自动生成路由配置文件',
usage: 'vue-cli-service route',
options: {}
}, (args) => {
let routeParams = projectOptions.pluginOptions.route;
creatRouter.creatRouter(false, routeParams);
})
};
module.exports.defaultModes = {
build: 'development'
};

159
package-lock.json generated Normal file
View File

@@ -0,0 +1,159 @@
{
"name": "vue-cli-plugin-autorouter",
"version": "1.3.3",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@babel/generator": {
"version": "7.11.4",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.4.tgz",
"integrity": "sha512-Rn26vueFx0eOoz7iifCN2UHT6rGtnkSGWSoDRIy8jZN3B91PzeSULbswfLoOWuTuAcNwpG/mxy+uCTDnZ9Mp1g==",
"requires": {
"@babel/types": "^7.11.0",
"jsesc": "^2.5.1",
"source-map": "^0.5.0"
}
},
"@babel/helper-validator-identifier": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
"integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw=="
},
"@babel/parser": {
"version": "7.11.4",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.4.tgz",
"integrity": "sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA=="
},
"@babel/types": {
"version": "7.11.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz",
"integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==",
"requires": {
"@babel/helper-validator-identifier": "^7.10.4",
"lodash": "^4.17.19",
"to-fast-properties": "^2.0.0"
}
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"de-indent": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz",
"integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0="
},
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"glob": {
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"he": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
},
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"requires": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"jsesc": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
"integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA=="
},
"lodash": {
"version": "4.17.20",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"requires": {
"brace-expansion": "^1.1.7"
}
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"requires": {
"wrappy": "1"
}
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
},
"pify": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g=="
},
"source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
},
"to-fast-properties": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
"integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4="
},
"vue-template-compiler": {
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.12.tgz",
"integrity": "sha512-OzzZ52zS41YUbkCBfdXShQTe69j1gQDZ9HIX8miuC9C3rBCk9wIRjLiZZLrmX9V+Ftq/YEyv1JaVr5Y/hNtByg==",
"requires": {
"de-indent": "^1.0.2",
"he": "^1.1.0"
}
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
}
}
}

25
package.json Normal file
View File

@@ -0,0 +1,25 @@
{
"name": "vue-cli-plugin-tsx-autorouter",
"version": "1.3.8",
"description": "vue cli plugin to auto add router tsx",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "bmy",
"license": "ISC",
"dependencies": {
"@babel/generator": "^7.11.4",
"@babel/types": "^7.11.0",
"@babel/parser": "^7.11.4",
"glob": "^7.1.3",
"pify": "^4.0.1"
},
"keywords": [
"vue",
"vue-cli",
"vue-router",
"autorouter"
],
"devDependencies": {}
}

1
service/.pydio Normal file
View File

@@ -0,0 +1 @@
876a8496-8207-43a5-ab7b-f46a75d7118a

309
service/regist-route.js Normal file
View File

@@ -0,0 +1,309 @@
const Glob = require('glob');
const pify = require('pify');
const path = require('path');
const fs = require('fs');
const { parse } = require('@babel/parser');
const t = require('@babel/types');
const generate = require('@babel/generator');
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|tsx)$/, '')
.replace(/\/{2,}/g, '/')
.split('/')
.slice(1);
const route = {
name: '',
path: '',
component: `_() => import(/* webpackChunkName: '${keys.toString().replace(/,/g, "")}' */ '@${pagesDir}/${keys.join('/')}')`,
meta: 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).toString();
// 将tsx字符串代码转换成ast语法树
const ast = parse(VueSource, {
sourceType: 'module',
plugins: ['typescript', 'jsx', 'classProperties',
['decorators', { decoratorsBeforeExport: true }]
]
});
// 从语法树中找到类私有属性 private RouterMeta
output = ""
ast.program.body.forEach((v, i) => {
if (t.isExportDefaultDeclaration(v)) {
v.declaration.body.body.forEach((b)=>{
if (t.isClassProperty(b)) {
if (t.isIdentifier(b.key) && b.key.name == 'RouterMeta') {
// 将 私有属性 RouterMeta 的值从语法树转换为js代码
output = generate.default(b.value, {
compact: true,
}).code;
}
}
})
}
})
if(output.length != 0) {
return eval(JSON.stringify(output));
} 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(/"{/g, "{")
.replace(/}"/g, "}")
.replace(/\'\)\"/g, "')")
let buildPath = path.resolve(process.cwd(), path.join(__dirname, OptionSetting.SaveConfigPath));
fs.writeFileSync(buildPath, string);
})
};

1
utils/.pydio Normal file
View File

@@ -0,0 +1 @@
57690bf2-4361-4277-ae8c-5aab54aeb228

12
utils/welcome.js Normal file
View File

@@ -0,0 +1,12 @@
const { readFileSync, writeFileSync } = require("fs");
const { join } = require("path");
const package = require("../package.json");
const Path = '../../@vue/cli-service/lib/commands/serve.js';
let serve = (readFileSync(join(__dirname, Path))).toString();
serve = serve.replace('Starting development server...',"正在启动开发服务器...");
serve = serve.replace('App running at:',`🎉 欢迎使用 ${package.name}\n 🎉 该插件基于本人另一个项目[vue-cli-plugin-autorouter]适配自己的VueClassApi + Tsx 的脚手架而来 \n\n 📦 项目地址https://www.npmjs.com/package/vue-cli-plugin-autorouter\n 👨‍💻 作者bmy\n 📞 Githubhttps://github.com/helpcode\n 应用运行在:`);
serve = serve.replace('- Local:'," - 本地:");
serve = serve.replace('- Network:'," - 网络:");
serve = serve.replace('Note that the development build is not optimized.',"注意开发阶段项目没有做优化。");
serve = serve.replace('To create a production build, run',"如果要创建生产代码,请运行命令: ");
writeFileSync(join(__dirname, Path),serve);