vite-plugin-generoutes 1.1.1 → 2.0.0-beta.1

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/README.md CHANGED
@@ -14,6 +14,7 @@ A Vite plugin that automatically generates Vue router configuration based on fil
14
14
  - 🎨 Customizable route configuration
15
15
  - 🧩 Support for route metadata via `defineOptions`
16
16
  - 🚦 Route redirection support
17
+ - 🖼️ Layout-based route grouping
17
18
 
18
19
  ### 📦 Installation
19
20
 
@@ -52,6 +53,7 @@ export default defineConfig({
52
53
  | Option | Type | Default | Description |
53
54
  | --------------- | ---------- | ---------------- | ----------------------------------------------------------------------------------------------------------------- |
54
55
  | `pagesFolder` | `string` | `'src/pages'` | Path to pages folder |
56
+ | `layoutsFolder` | `string` | `'src/layouts'` | Path to layouts folder |
55
57
  | `ignoreFolders` | `string[]` | `['components']` | Folders to ignore when generating routes |
56
58
  | `routesPath` | `string` | Auto-detected | Path to generated routes file. Auto-detected based on `tsconfig.json` presence (`.ts` if exists, otherwise `.js`) |
57
59
  | `nested` | `boolean` | `false` | Whether to generate nested routes |
@@ -119,7 +121,70 @@ defineOptions({
119
121
  </script>
120
122
  ```
121
123
 
122
- ### 🚀 Complete Example
124
+ ### �️ Layout Routes
125
+
126
+ Routes are automatically grouped by their `meta.layout` property and wrapped with a parent layout route:
127
+
128
+ - Routes with `meta.layout: false` will **not** be wrapped with a layout
129
+ - Routes without `meta.layout` will use the `'default'` layout by default
130
+ - Routes with `meta.layout: 'xxx'` will use the corresponding layout component from `layoutsFolder`
131
+
132
+ ```vue
133
+ <!-- src/pages/login.vue - No layout wrapper -->
134
+ <script setup>
135
+ defineOptions({
136
+ name: 'Login',
137
+ meta: {
138
+ layout: false
139
+ }
140
+ })
141
+ </script>
142
+ ```
143
+
144
+ ```vue
145
+ <!-- src/pages/home.vue - Uses 'admin' layout -->
146
+ <script setup>
147
+ defineOptions({
148
+ name: 'Home',
149
+ meta: {
150
+ layout: 'admin'
151
+ }
152
+ })
153
+ </script>
154
+ ```
155
+
156
+ **Generated route structure example:**
157
+
158
+ ```javascript
159
+ [
160
+ // Routes with layout: false are not wrapped
161
+ {
162
+ name: 'Login',
163
+ path: '/login',
164
+ component: () => import('/src/pages/login.vue'),
165
+ meta: { layout: false }
166
+ },
167
+ // Routes are grouped by layout
168
+ {
169
+ name: 'LAYOUT_DEFAULT',
170
+ path: '/__layout_default__',
171
+ component: () => import('/src/layouts/default.vue'),
172
+ children: [
173
+ { name: 'Index', path: '/' }
174
+ ]
175
+ },
176
+ {
177
+ name: 'LAYOUT_ADMIN',
178
+ path: '/__layout_admin__',
179
+ component: () => import('/src/layouts/admin.vue'),
180
+ children: [
181
+ { name: 'Home', path: '/home' }
182
+ ]
183
+ }
184
+ ]
185
+ ```
186
+
187
+ ### �🚀 Complete Example
123
188
 
124
189
  ```javascript
125
190
  import vue from '@vitejs/plugin-vue'
package/README.zh_CN.md CHANGED
@@ -14,6 +14,7 @@
14
14
  - 🎨 可自定义路由配置
15
15
  - 🧩 支持通过`defineOptions`设置路由元数据
16
16
  - 🚦 支持路由重定向
17
+ - 🖼️ 支持按布局分组路由
17
18
 
18
19
  ### 📦 安装
19
20
 
@@ -52,6 +53,7 @@ export default defineConfig({
52
53
  | 选项 | 类型 | 默认值 | 描述 |
53
54
  | --------------- | ---------- | ---------------- | ----------------------------------------------------------------------------------------- |
54
55
  | `pagesFolder` | `string` | `'src/pages'` | 页面文件夹路径 |
56
+ | `layoutsFolder` | `string` | `'src/layouts'` | 布局组件文件夹路径 |
55
57
  | `ignoreFolders` | `string[]` | `['components']` | 生成路由时忽略的文件夹 |
56
58
  | `routesPath` | `string` | 自动检测 | 生成的路由文件路径,根据 `tsconfig.json` 是否存在自动检测(存在则为 `.ts`,否则为 `.js`) |
57
59
  | `nested` | `boolean` | `false` | 是否生成嵌套路由 |
@@ -119,7 +121,70 @@ defineOptions({
119
121
  </script>
120
122
  ```
121
123
 
122
- ### 🚀 完整示例
124
+ ### �️ 布局路由
125
+
126
+ 路由会根据 `meta.layout` 属性自动分组,并包裹在对应的布局父级路由中:
127
+
128
+ - 设置 `meta.layout: false` 的路由**不会**被布局包裹
129
+ - 未设置 `meta.layout` 的路由默认使用 `'default'` 布局
130
+ - 设置 `meta.layout: 'xxx'` 的路由会使用 `layoutsFolder` 中对应的布局组件
131
+
132
+ ```vue
133
+ <!-- src/pages/login.vue - 不使用布局包裹 -->
134
+ <script setup>
135
+ defineOptions({
136
+ name: 'Login',
137
+ meta: {
138
+ layout: false
139
+ }
140
+ })
141
+ </script>
142
+ ```
143
+
144
+ ```vue
145
+ <!-- src/pages/home.vue - 使用 'admin' 布局 -->
146
+ <script setup>
147
+ defineOptions({
148
+ name: 'Home',
149
+ meta: {
150
+ layout: 'admin'
151
+ }
152
+ })
153
+ </script>
154
+ ```
155
+
156
+ **生成的路由结构示例:**
157
+
158
+ ```javascript
159
+ [
160
+ // layout: false 的路由不会被包裹
161
+ {
162
+ name: 'Login',
163
+ path: '/login',
164
+ component: () => import('/src/pages/login.vue'),
165
+ meta: { layout: false }
166
+ },
167
+ // 路由按布局分组
168
+ {
169
+ name: 'LAYOUT_DEFAULT',
170
+ path: '/__layout_default__',
171
+ component: () => import('/src/layouts/default.vue'),
172
+ children: [
173
+ { name: 'Index', path: '/' }
174
+ ]
175
+ },
176
+ {
177
+ name: 'LAYOUT_ADMIN',
178
+ path: '/__layout_admin__',
179
+ component: () => import('/src/layouts/admin.vue'),
180
+ children: [
181
+ { name: 'Home', path: '/home' }
182
+ ]
183
+ }
184
+ ]
185
+ ```
186
+
187
+ ### �🚀 完整示例
123
188
 
124
189
  ```javascript
125
190
  import vue from '@vitejs/plugin-vue'
package/dist/index.d.ts CHANGED
@@ -12,6 +12,8 @@ interface RouteMeta {
12
12
  requiresAuth?: boolean;
13
13
  /** Whether the route is enabled */
14
14
  enabled?: boolean;
15
+ /** Layout component name, false to disable layout wrapping */
16
+ layout?: string | false;
15
17
  /** Custom properties */
16
18
  [key: string]: unknown;
17
19
  }
@@ -69,6 +71,12 @@ interface Options {
69
71
  * @default src/pages
70
72
  */
71
73
  pagesFolder: string;
74
+ /**
75
+ * layouts folder
76
+ *
77
+ * @default src/layouts
78
+ */
79
+ layoutsFolder: string;
72
80
  /**
73
81
  * ignore folders, ignore these folders when generating routes
74
82
  *
package/dist/index.js CHANGED
@@ -66,6 +66,7 @@ function VitePluginGeneroutes(options = {}) {
66
66
  let routesPath;
67
67
  let isTypeScript;
68
68
  const pagesFolder = options.pagesFolder || "src/pages";
69
+ const layoutsFolder = options.layoutsFolder || "src/layouts";
69
70
  const ignoreFolders = options.ignoreFolders || ["components"];
70
71
  const nested = options.nested || false;
71
72
  const defineOptionsCache = /* @__PURE__ */ new Map();
@@ -100,10 +101,37 @@ function VitePluginGeneroutes(options = {}) {
100
101
  console.warn(`Warning: Duplicate names found in routes: ${duplicateNames.join(", ")}`);
101
102
  if (duplicatePaths.length)
102
103
  console.warn(`Warning: Duplicate paths found in routes: ${duplicatePaths.join(", ")}`);
104
+ const processedRoutes = wrapRoutesWithLayout(nested ? convertToTree(routes) : routes);
103
105
  return {
104
- routes: nested ? convertToTree(routes) : routes
106
+ routes: processedRoutes
105
107
  };
106
108
  }
109
+ function wrapRoutesWithLayout(routes) {
110
+ const layoutGroups = /* @__PURE__ */ new Map();
111
+ const noLayoutRoutes = [];
112
+ for (const route of routes) {
113
+ const layout = route.meta?.layout;
114
+ if (layout === false) {
115
+ noLayoutRoutes.push(route);
116
+ } else {
117
+ const layoutName = layout || "default";
118
+ const group = layoutGroups.get(layoutName);
119
+ if (group) {
120
+ group.push(route);
121
+ } else {
122
+ layoutGroups.set(layoutName, [route]);
123
+ }
124
+ }
125
+ }
126
+ const layoutRoutes = Array.from(layoutGroups, ([layoutName, children]) => ({
127
+ name: `LAYOUT_${layoutName.toUpperCase()}`,
128
+ path: `/__layout_${layoutName}__`,
129
+ component: `@@layout@@/${layoutsFolder}/${layoutName}.vue@@`,
130
+ meta: {},
131
+ children
132
+ }));
133
+ return [...noLayoutRoutes, ...layoutRoutes];
134
+ }
107
135
  async function writerRoutesFile(isInit = false) {
108
136
  const { routes } = generateMenusAndRoutes();
109
137
  const typeDefinitions = isTypeScript ? `
@@ -148,6 +176,7 @@ export type GeneratedRoute = RouteRecordRaw & {
148
176
  export const routes${routesType} = ${JSON.stringify(routes, null, 2)}
149
177
  `;
150
178
  routesStr = routesStr.replace(/"##(.*)##"/g, (_, p1) => `async () => ({...(await import('${p1.split("@@")[0]}')).default, name: '${p1.split("@@")[1]}'})`);
179
+ routesStr = routesStr.replace(/"@@layout@@(.*)@@"/g, (_, p1) => `() => import('${p1}')`);
151
180
  const parser = isTypeScript ? "typescript" : "babel";
152
181
  routesStr = await prettier.format(routesStr, { parser, semi: false, singleQuote: true });
153
182
  const filePath = path.resolve(rootDir, routesPath);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "vite-plugin-generoutes",
3
3
  "type": "module",
4
- "version": "1.1.1",
4
+ "version": "2.0.0-beta.1",
5
5
  "packageManager": "pnpm@10.27.0",
6
6
  "description": "A Vite plugin that generate routes based on the file structure, supports dynamic routes, and supports custom meta data for each route.",
7
7
  "author": "Ronnie Zhang <zclzone@outlook.com>",