vite-plugin-generoutes 0.2.0 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +18 -2
- package/dist/index.js +93 -41
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -10,13 +10,29 @@ import { Plugin } from 'vite';
|
|
|
10
10
|
|
|
11
11
|
interface Options {
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
13
|
+
* pages 文件夹
|
|
14
|
+
*
|
|
15
|
+
* default: `src/pages`
|
|
14
16
|
*/
|
|
15
17
|
pagesFolder: string;
|
|
16
18
|
/**
|
|
17
|
-
*
|
|
19
|
+
* 忽略文件夹
|
|
20
|
+
*
|
|
21
|
+
* default: `['components']`
|
|
22
|
+
*/
|
|
23
|
+
ignoreFolders: string[];
|
|
24
|
+
/**
|
|
25
|
+
* 路由文件路径
|
|
26
|
+
*
|
|
27
|
+
* default: `${pagesFolder}/generoutes.js`
|
|
18
28
|
*/
|
|
19
29
|
routesPath?: string;
|
|
30
|
+
/**
|
|
31
|
+
* 是否嵌套
|
|
32
|
+
*
|
|
33
|
+
* default: false
|
|
34
|
+
*/
|
|
35
|
+
nested: boolean;
|
|
20
36
|
}
|
|
21
37
|
declare function VitePluginGeneroutes(options?: Partial<Options>): Plugin<any>;
|
|
22
38
|
|
package/dist/index.js
CHANGED
|
@@ -6,52 +6,86 @@ import { parse } from "@vue/compiler-sfc";
|
|
|
6
6
|
import { debounce, slash } from "@antfu/utils";
|
|
7
7
|
import chokidar from "chokidar";
|
|
8
8
|
import prettier from "prettier";
|
|
9
|
+
|
|
10
|
+
// src/utils.ts
|
|
9
11
|
function toPascalCase(str) {
|
|
10
12
|
return str.toLowerCase().replace(/(?:^|-)([a-z])/g, (_, p1) => {
|
|
11
13
|
return p1.toUpperCase();
|
|
12
14
|
});
|
|
13
15
|
}
|
|
16
|
+
function convertToTree(routes) {
|
|
17
|
+
const nodeMap = {};
|
|
18
|
+
const result = [];
|
|
19
|
+
routes.forEach((route) => {
|
|
20
|
+
const { parent, ...node } = route;
|
|
21
|
+
nodeMap[node.name] = node;
|
|
22
|
+
});
|
|
23
|
+
routes.forEach((route) => {
|
|
24
|
+
if (route.parent) {
|
|
25
|
+
const parentNode = nodeMap[route.parent];
|
|
26
|
+
if (parentNode) {
|
|
27
|
+
if (!parentNode.children) {
|
|
28
|
+
parentNode.children = [];
|
|
29
|
+
}
|
|
30
|
+
parentNode.children.push(nodeMap[route.name]);
|
|
31
|
+
}
|
|
32
|
+
} else {
|
|
33
|
+
result.push(nodeMap[route.name]);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
function findDuplicateRoutes(routes) {
|
|
39
|
+
const nameSet = /* @__PURE__ */ new Set();
|
|
40
|
+
const pathSet = /* @__PURE__ */ new Set();
|
|
41
|
+
const duplicateNames = [];
|
|
42
|
+
const duplicatePaths = [];
|
|
43
|
+
for (const route of routes) {
|
|
44
|
+
if (nameSet.has(route.name)) {
|
|
45
|
+
duplicateNames.push(route.name);
|
|
46
|
+
} else {
|
|
47
|
+
nameSet.add(route.name);
|
|
48
|
+
}
|
|
49
|
+
if (pathSet.has(route.path)) {
|
|
50
|
+
duplicatePaths.push(route.path);
|
|
51
|
+
} else {
|
|
52
|
+
pathSet.add(route.path);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
duplicateNames,
|
|
57
|
+
duplicatePaths
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// src/index.ts
|
|
14
62
|
var defaultOptions = {
|
|
15
|
-
pagesFolder: "src/pages"
|
|
63
|
+
pagesFolder: "src/pages",
|
|
64
|
+
ignoreFolders: ["components"],
|
|
65
|
+
nested: false
|
|
16
66
|
};
|
|
17
67
|
function VitePluginGeneroutes(options = {}) {
|
|
18
68
|
if (options.routesPath && ![".ts", ".js"].includes(path.extname(options.routesPath)))
|
|
19
69
|
throw new Error("routesPath must be a js or ts file path, such as src/router/generoutes.js");
|
|
20
|
-
const defineOptionsCache = /* @__PURE__ */ new Map();
|
|
21
70
|
let rootDir;
|
|
22
71
|
const pagesFolder = options.pagesFolder || defaultOptions.pagesFolder;
|
|
23
|
-
const routesPath = options.routesPath || path.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
// ! \u6B64\u6587\u4EF6\u7531 vite-plugin-generoutes \u81EA\u52A8\u751F\u6210\uFF0C\u5EFA\u8BAE\u6DFB\u52A0\u5230 .gitignore\uFF0C\u8BF7\u52FF\u76F4\u63A5\u5728\u6B64\u6587\u4EF6\u4FEE\u6539!!!
|
|
28
|
-
// ! This file is generated by vite-plugin-generoutes, it is recommended to add it to .gitignore, do not modify it directly in this file!!!
|
|
29
|
-
|
|
30
|
-
export const routes = ${JSON.stringify(routes, null, 2)}
|
|
31
|
-
`;
|
|
32
|
-
routesStr = routesStr.replace(/"##(.*)##"/g, (_, p1) => `() => import('${p1}')`);
|
|
33
|
-
routesStr = await prettier.format(routesStr, { parser: "babel", semi: false, singleQuote: true });
|
|
34
|
-
fs.writeFileSync(`${path.resolve(rootDir, routesPath)}`, routesStr);
|
|
35
|
-
}
|
|
36
|
-
const debounceWriter = debounce(500, writerRoutesFile);
|
|
72
|
+
const routesPath = options.routesPath || path.join(pagesFolder, "generoutes.js");
|
|
73
|
+
const nested = options.nested || defaultOptions.nested;
|
|
74
|
+
const ignoreFolders = options.ignoreFolders || defaultOptions.ignoreFolders;
|
|
75
|
+
const defineOptionsCache = /* @__PURE__ */ new Map();
|
|
37
76
|
function generateMenusAndRoutes() {
|
|
38
|
-
const pages = globSync(`${pagesFolder}
|
|
77
|
+
const pages = globSync(`${pagesFolder}/**/*.vue`, { ignore: ignoreFolders.map((folder) => `${pagesFolder}/**/${folder}/**`) });
|
|
39
78
|
const routes = pages.map((filePath) => {
|
|
40
79
|
filePath = slash(filePath);
|
|
41
|
-
const defineOptions = parseDefineOptions(filePath);
|
|
80
|
+
const defineOptions = parseDefineOptions(filePath) || {};
|
|
42
81
|
defineOptionsCache.set(filePath, JSON.stringify(defineOptions));
|
|
43
82
|
const meta = defineOptions?.meta || {};
|
|
44
83
|
if (meta.enabled === false)
|
|
45
84
|
return null;
|
|
46
|
-
const
|
|
47
|
-
const
|
|
48
|
-
let name = defineOptions?.name || pathSegments.map((item) => toPascalCase(item)).join("_") || "Index";
|
|
85
|
+
const pathSegments = filePath.replace(`${pagesFolder}`, "").replace(".vue", "").replace("index", "").split("/").filter((item) => !!item && !/^\(.*\)$/.test(item));
|
|
86
|
+
const name = defineOptions?.name || pathSegments.map((item) => toPascalCase(item)).join("_") || "Index";
|
|
49
87
|
const component = `##/${filePath}##`;
|
|
50
|
-
|
|
51
|
-
if (fileName === "[...all].vue") {
|
|
52
|
-
name = `${name}_[...all]`;
|
|
53
|
-
routePath = routePath === "/" ? "/:pathMatch(.*)*" : `${routePath}/:pathMatch(.*)*`;
|
|
54
|
-
}
|
|
88
|
+
const routePath = `/${pathSegments.map((item) => item.replace(/\[(.*?)\]/g, (_, p1) => p1 === "...all" ? ":pathMatch(.*)*" : p1.split(",").map((i) => `:${i}`).join("/"))).join("/")}`;
|
|
55
89
|
if (!("title" in meta))
|
|
56
90
|
meta.title = name;
|
|
57
91
|
if (!("show" in meta))
|
|
@@ -61,17 +95,40 @@ function VitePluginGeneroutes(options = {}) {
|
|
|
61
95
|
name,
|
|
62
96
|
path: routePath,
|
|
63
97
|
component,
|
|
64
|
-
meta
|
|
98
|
+
meta,
|
|
99
|
+
parent: defineOptions?.parent
|
|
65
100
|
};
|
|
66
101
|
}).filter(Boolean);
|
|
102
|
+
const { duplicateNames, duplicatePaths } = findDuplicateRoutes(routes);
|
|
103
|
+
if (duplicateNames.length)
|
|
104
|
+
console.warn(`Warning: Duplicate names found in routes: ${duplicateNames.join(", ")}`);
|
|
105
|
+
if (duplicatePaths.length)
|
|
106
|
+
console.warn(`Warning: Duplicate paths found in routes: ${duplicatePaths.join(", ")}`);
|
|
67
107
|
return {
|
|
68
|
-
routes
|
|
108
|
+
routes: nested ? convertToTree(routes) : routes
|
|
69
109
|
};
|
|
70
110
|
}
|
|
111
|
+
async function writerRoutesFile() {
|
|
112
|
+
const { routes } = generateMenusAndRoutes();
|
|
113
|
+
let routesStr = `
|
|
114
|
+
// ! \u6B64\u6587\u4EF6\u7531 vite-plugin-generoutes \u81EA\u52A8\u751F\u6210\uFF0C\u5EFA\u8BAE\u6DFB\u52A0\u5230 .gitignore\uFF0C\u8BF7\u52FF\u76F4\u63A5\u5728\u6B64\u6587\u4EF6\u4FEE\u6539!!!
|
|
115
|
+
// ! This file is generated by vite-plugin-generoutes, it is recommended to add it to .gitignore, do not modify it directly in this file!!!
|
|
116
|
+
|
|
117
|
+
export const routes = ${JSON.stringify(routes, null, 2)}
|
|
118
|
+
`;
|
|
119
|
+
routesStr = routesStr.replace(/"##(.*)##"/g, (_, p1) => `() => import('${p1}')`);
|
|
120
|
+
routesStr = await prettier.format(routesStr, { parser: "babel", semi: false, singleQuote: true });
|
|
121
|
+
const filePath = path.resolve(rootDir, routesPath);
|
|
122
|
+
await fs.ensureDir(path.dirname(filePath));
|
|
123
|
+
fs.writeFileSync(filePath, routesStr);
|
|
124
|
+
}
|
|
125
|
+
const debounceWriter = debounce(500, writerRoutesFile);
|
|
71
126
|
function createWatcher() {
|
|
72
|
-
const watcher = chokidar.watch(
|
|
127
|
+
const watcher = chokidar.watch(`${pagesFolder}/**/*.vue`, { ignoreInitial: true });
|
|
73
128
|
return watcher.on("all", async (event, path2) => {
|
|
74
|
-
if (
|
|
129
|
+
if (ignoreFolders.some((folder) => slash(path2).includes(`/${folder}/`)))
|
|
130
|
+
return;
|
|
131
|
+
if (path2.endsWith(".vue") && (event === "add" || event === "unlink")) {
|
|
75
132
|
debounceWriter();
|
|
76
133
|
await watcher.close();
|
|
77
134
|
createWatcher();
|
|
@@ -82,20 +139,15 @@ function VitePluginGeneroutes(options = {}) {
|
|
|
82
139
|
name: "vite-plugin-generoutes",
|
|
83
140
|
async configResolved(config) {
|
|
84
141
|
rootDir = config.root;
|
|
85
|
-
await fs.ensureDir(path.dirname(routesPath));
|
|
86
142
|
await writerRoutesFile();
|
|
87
143
|
config.command !== "build" && createWatcher();
|
|
88
144
|
},
|
|
89
145
|
async handleHotUpdate({ file, read }) {
|
|
90
|
-
if (file.includes(
|
|
146
|
+
if (file.includes(pagesFolder) && !ignoreFolders.some((folder) => file.includes(`/${folder}/`)) && file.endsWith(".vue")) {
|
|
91
147
|
const prevDefineOptions = defineOptionsCache.get(slash(path.relative(rootDir, file)));
|
|
92
|
-
|
|
148
|
+
const defineOptions = JSON.stringify(parseDefineOptions(file, await read()));
|
|
149
|
+
if (prevDefineOptions !== defineOptions) {
|
|
93
150
|
debounceWriter();
|
|
94
|
-
} else {
|
|
95
|
-
const defineOptions = JSON.stringify(parseDefineOptions(file, await read()));
|
|
96
|
-
if (prevDefineOptions !== defineOptions) {
|
|
97
|
-
debounceWriter();
|
|
98
|
-
}
|
|
99
151
|
}
|
|
100
152
|
}
|
|
101
153
|
}
|
|
@@ -106,16 +158,16 @@ function parseDefineOptions(filePath, content) {
|
|
|
106
158
|
const { descriptor } = parse(content);
|
|
107
159
|
const setupScript = descriptor.scriptSetup?.content;
|
|
108
160
|
if (setupScript) {
|
|
109
|
-
const defineOptionsMatch = setupScript.match(/defineOptions\(([
|
|
161
|
+
const defineOptionsMatch = setupScript.match(/defineOptions\s*\(\s*(\{[\s\S]*?\})\s*\)/);
|
|
110
162
|
if (defineOptionsMatch) {
|
|
111
163
|
try {
|
|
112
164
|
return new Function(`return ${defineOptionsMatch[1]}`)();
|
|
113
165
|
} catch (e) {
|
|
114
|
-
|
|
166
|
+
throw new Error(`Failed to parse defineOptions in ${filePath}: ${e}`);
|
|
115
167
|
}
|
|
116
168
|
}
|
|
117
169
|
}
|
|
118
|
-
return
|
|
170
|
+
return {};
|
|
119
171
|
}
|
|
120
172
|
var src_default = VitePluginGeneroutes;
|
|
121
173
|
export {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vite-plugin-generoutes",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.3",
|
|
5
5
|
"packageManager": "pnpm@9.1.1",
|
|
6
6
|
"description": "_description_",
|
|
7
7
|
"author": "Ronnie Zhang <zclzone@outlook.com>",
|
|
@@ -78,4 +78,4 @@
|
|
|
78
78
|
"lint-staged": {
|
|
79
79
|
"*": "eslint --fix"
|
|
80
80
|
}
|
|
81
|
-
}
|
|
81
|
+
}
|