vite-plugin-pages2 0.32.5

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.cjs ADDED
@@ -0,0 +1,974 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __defProps = Object.defineProperties;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
7
+ var __getOwnPropNames = Object.getOwnPropertyNames;
8
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
9
+ var __getProtoOf = Object.getPrototypeOf;
10
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
11
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
12
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
13
+ var __spreadValues = (a, b) => {
14
+ for (var prop in b || (b = {}))
15
+ if (__hasOwnProp.call(b, prop))
16
+ __defNormalProp(a, prop, b[prop]);
17
+ if (__getOwnPropSymbols)
18
+ for (var prop of __getOwnPropSymbols(b)) {
19
+ if (__propIsEnum.call(b, prop))
20
+ __defNormalProp(a, prop, b[prop]);
21
+ }
22
+ return a;
23
+ };
24
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
25
+ var __export = (target, all) => {
26
+ for (var name in all)
27
+ __defProp(target, name, { get: all[name], enumerable: true });
28
+ };
29
+ var __copyProps = (to, from, except, desc) => {
30
+ if (from && typeof from === "object" || typeof from === "function") {
31
+ for (let key of __getOwnPropNames(from))
32
+ if (!__hasOwnProp.call(to, key) && key !== except)
33
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
34
+ }
35
+ return to;
36
+ };
37
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
38
+ // If the importer is in node compatibility mode or this is not an ESM
39
+ // file that has been converted to a CommonJS file using a Babel-
40
+ // compatible transform (i.e. "__esModule" has not been set), then set
41
+ // "default" to the CommonJS "module.exports" for node compatibility.
42
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
43
+ mod
44
+ ));
45
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
46
+
47
+ // src/index.ts
48
+ var index_exports = {};
49
+ __export(index_exports, {
50
+ PageContext: () => PageContext,
51
+ default: () => index_default,
52
+ reactResolver: () => reactResolver,
53
+ solidResolver: () => solidResolver,
54
+ syncIndexResolver: () => syncIndexResolver,
55
+ vueResolver: () => vueResolver
56
+ });
57
+ module.exports = __toCommonJS(index_exports);
58
+
59
+ // src/constants.ts
60
+ var MODULE_IDS = [
61
+ "~pages",
62
+ "~react-pages",
63
+ "~solid-pages",
64
+ "pages-generated",
65
+ "virtual:generated-pages",
66
+ "virtual:generated-pages-react"
67
+ ];
68
+ var MODULE_ID_VIRTUAL = "virtual:vite-plugin-pages/generated-pages";
69
+ var ROUTE_BLOCK_ID_VIRTUAL = "virtual:vite-plugin-pages/route-block";
70
+ var ROUTE_IMPORT_NAME = "__pages_import_$1__";
71
+ var routeBlockQueryRE = /\?vue&type=route/;
72
+ var dynamicRouteRE = /^\[(.+)\]$/;
73
+ var cacheAllRouteRE = /^\[\.{3}(.*)\]$/;
74
+ var replaceDynamicRouteRE = /^\[(?:\.{3})?(.*)\]$/;
75
+ var nuxtDynamicRouteRE = /^_(.*)$/;
76
+ var nuxtCacheAllRouteRE = /^_$/;
77
+ var countSlashRE = /\//g;
78
+ var replaceIndexRE = /\/?index$/;
79
+
80
+ // src/context.ts
81
+ var import_node_path4 = require("path");
82
+ var import_node_process2 = __toESM(require("process"), 1);
83
+
84
+ // node_modules/.pnpm/@antfu+utils@8.1.0/node_modules/@antfu/utils/dist/index.mjs
85
+ function toArray(array) {
86
+ array = array != null ? array : [];
87
+ return Array.isArray(array) ? array : [array];
88
+ }
89
+ var VOID = Symbol("p-void");
90
+ function slash(str) {
91
+ return str.replace(/\\/g, "/");
92
+ }
93
+
94
+ // src/files.ts
95
+ var import_node_path2 = require("path");
96
+ var import_fast_glob = __toESM(require("fast-glob"), 1);
97
+
98
+ // src/utils.ts
99
+ var import_node_path = require("path");
100
+ var import_node_url = require("url");
101
+ var import_debug = __toESM(require("debug"), 1);
102
+ var debug = {
103
+ hmr: (0, import_debug.default)("vite-plugin-pages:hmr"),
104
+ routeBlock: (0, import_debug.default)("vite-plugin-pages:routeBlock"),
105
+ options: (0, import_debug.default)("vite-plugin-pages:options"),
106
+ pages: (0, import_debug.default)("vite-plugin-pages:pages"),
107
+ search: (0, import_debug.default)("vite-plugin-pages:search"),
108
+ env: (0, import_debug.default)("vite-plugin-pages:env"),
109
+ cache: (0, import_debug.default)("vite-plugin-pages:cache"),
110
+ resolver: (0, import_debug.default)("vite-plugin-pages:resolver")
111
+ };
112
+ function extsToGlob(extensions) {
113
+ return extensions.length > 1 ? `{${extensions.join(",")}}` : extensions[0] || "";
114
+ }
115
+ function countSlash(value) {
116
+ return (value.match(countSlashRE) || []).length;
117
+ }
118
+ function isPagesDir(path, options) {
119
+ for (const page of options.dirs) {
120
+ const dirPath = slash((0, import_node_path.resolve)(options.root, page.dir));
121
+ if (path.startsWith(dirPath))
122
+ return true;
123
+ }
124
+ return false;
125
+ }
126
+ function isTarget(path, options) {
127
+ return isPagesDir(path, options) && options.extensionsRE.test(path);
128
+ }
129
+ function isDynamicRoute(routePath, nuxtStyle = false) {
130
+ return nuxtStyle ? nuxtDynamicRouteRE.test(routePath) : dynamicRouteRE.test(routePath);
131
+ }
132
+ function isCatchAllRoute(routePath, nuxtStyle = false) {
133
+ return nuxtStyle ? nuxtCacheAllRouteRE.test(routePath) : cacheAllRouteRE.test(routePath);
134
+ }
135
+ function resolveImportMode(filepath, options) {
136
+ const mode = options.importMode;
137
+ if (typeof mode === "function")
138
+ return mode(filepath, options);
139
+ return mode;
140
+ }
141
+ function invalidatePagesModule(server) {
142
+ const { moduleGraph } = server;
143
+ const mods = moduleGraph.getModulesByFile(MODULE_ID_VIRTUAL);
144
+ if (mods) {
145
+ const seen = /* @__PURE__ */ new Set();
146
+ mods.forEach((mod) => {
147
+ moduleGraph.invalidateModule(mod, seen);
148
+ });
149
+ }
150
+ }
151
+ function normalizeCase(str, caseSensitive) {
152
+ if (!caseSensitive)
153
+ return str.toLocaleLowerCase();
154
+ return str;
155
+ }
156
+ function normalizeName(name, isDynamic, nuxtStyle = false) {
157
+ if (!isDynamic)
158
+ return name;
159
+ return nuxtStyle ? name.replace(nuxtDynamicRouteRE, "$1") || "all" : name.replace(replaceDynamicRouteRE, "$1");
160
+ }
161
+ function buildReactRoutePath(node, nuxtStyle = false) {
162
+ const isDynamic = isDynamicRoute(node, nuxtStyle);
163
+ const isCatchAll = isCatchAllRoute(node, nuxtStyle);
164
+ const normalizedName = normalizeName(node, isDynamic, nuxtStyle);
165
+ if (isDynamic) {
166
+ if (isCatchAll)
167
+ return "*";
168
+ return `:${normalizedName}`;
169
+ }
170
+ return `${normalizedName}`;
171
+ }
172
+ function buildReactRemixRoutePath(node) {
173
+ const escapeStart = "[";
174
+ const escapeEnd = "]";
175
+ let result = "";
176
+ let rawSegmentBuffer = "";
177
+ let inEscapeSequence = 0;
178
+ let skipSegment = false;
179
+ for (let i = 0; i < node.length; i++) {
180
+ let isNewEscapeSequence2 = function() {
181
+ return !inEscapeSequence && char === escapeStart && lastChar !== escapeStart;
182
+ }, isCloseEscapeSequence2 = function() {
183
+ return inEscapeSequence && char === escapeEnd && nextChar !== escapeEnd;
184
+ }, isStartOfLayoutSegment2 = function() {
185
+ return char === "_" && nextChar === "_" && !rawSegmentBuffer;
186
+ };
187
+ var isNewEscapeSequence = isNewEscapeSequence2, isCloseEscapeSequence = isCloseEscapeSequence2, isStartOfLayoutSegment = isStartOfLayoutSegment2;
188
+ const char = node.charAt(i);
189
+ const lastChar = i > 0 ? node.charAt(i - 1) : void 0;
190
+ const nextChar = i < node.length - 1 ? node.charAt(i + 1) : void 0;
191
+ if (skipSegment) {
192
+ if (char === "/" || char === "." || char === import_node_path.win32.sep)
193
+ skipSegment = false;
194
+ continue;
195
+ }
196
+ if (isNewEscapeSequence2()) {
197
+ inEscapeSequence++;
198
+ continue;
199
+ }
200
+ if (isCloseEscapeSequence2()) {
201
+ inEscapeSequence--;
202
+ continue;
203
+ }
204
+ if (inEscapeSequence) {
205
+ result += char;
206
+ continue;
207
+ }
208
+ if (char === "/" || char === import_node_path.win32.sep || char === ".") {
209
+ if (rawSegmentBuffer === "index" && result.endsWith("index"))
210
+ result = result.replace(replaceIndexRE, "");
211
+ else result += "/";
212
+ rawSegmentBuffer = "";
213
+ continue;
214
+ }
215
+ if (isStartOfLayoutSegment2()) {
216
+ skipSegment = true;
217
+ continue;
218
+ }
219
+ rawSegmentBuffer += char;
220
+ if (char === "$") {
221
+ result += typeof nextChar === "undefined" ? "*" : ":";
222
+ continue;
223
+ }
224
+ result += char;
225
+ }
226
+ if (rawSegmentBuffer === "index" && result.endsWith("index"))
227
+ result = result.replace(replaceIndexRE, "");
228
+ return result || void 0;
229
+ }
230
+ function parsePageRequest(id) {
231
+ const [moduleId, rawQuery] = id.split("?", 2);
232
+ const query = new import_node_url.URLSearchParams(rawQuery);
233
+ const pageId = query.get("id");
234
+ return {
235
+ moduleId,
236
+ query,
237
+ pageId
238
+ };
239
+ }
240
+
241
+ // src/files.ts
242
+ function getPageDirs(PageOptions, root, exclude) {
243
+ const dirs = import_fast_glob.default.sync(slash(PageOptions.dir), {
244
+ ignore: exclude,
245
+ onlyDirectories: true,
246
+ dot: true,
247
+ unique: true,
248
+ cwd: root
249
+ });
250
+ const pageDirs = dirs.map((dir) => __spreadProps(__spreadValues({}, PageOptions), {
251
+ dir
252
+ }));
253
+ return pageDirs;
254
+ }
255
+ function getPageFiles(path, options, pageOptions) {
256
+ var _a;
257
+ const {
258
+ exclude,
259
+ extensions
260
+ } = options;
261
+ const ext = extsToGlob(extensions);
262
+ const pattern = (_a = (pageOptions == null ? void 0 : pageOptions.filePatern) || (pageOptions == null ? void 0 : pageOptions.filePattern)) != null ? _a : `**/*.${ext}`;
263
+ const files = import_fast_glob.default.sync(pattern, {
264
+ ignore: exclude,
265
+ onlyFiles: true,
266
+ cwd: path
267
+ }).map((p) => slash((0, import_node_path2.join)(path, p)));
268
+ return files;
269
+ }
270
+
271
+ // src/options.ts
272
+ var import_node_path3 = require("path");
273
+ var import_node_process = __toESM(require("process"), 1);
274
+
275
+ // src/stringify.ts
276
+ var componentRE = /"(?:component|element)":("(.*?)")/g;
277
+ var hasFunctionRE = /"(?:props|beforeEnter)":("(.*?)")/g;
278
+ var multilineCommentsRE = /\/\*(.|[\r\n])*?\*\//g;
279
+ var singlelineCommentsRE = /\/\/.*/g;
280
+ function replaceFunction(_, value) {
281
+ if (value instanceof Function || typeof value === "function") {
282
+ const fnBody = value.toString().replace(multilineCommentsRE, "").replace(singlelineCommentsRE, "").replace(/(\s)/g, "");
283
+ if (fnBody.length < 8 || fnBody.substring(0, 8) !== "function")
284
+ return `_NuFrRa_${fnBody}`;
285
+ return fnBody;
286
+ }
287
+ return value;
288
+ }
289
+ function stringifyRoutes(preparedRoutes, options) {
290
+ const importsMap = /* @__PURE__ */ new Map();
291
+ function getImportString(path, importName) {
292
+ var _a, _b;
293
+ const mode = resolveImportMode(path, options);
294
+ return mode === "sync" ? `import ${importName} from "${path}"` : `const ${importName} = ${((_b = (_a = options.resolver.stringify) == null ? void 0 : _a.dynamicImport) == null ? void 0 : _b.call(_a, path)) || `() => import("${path}")`}`;
295
+ }
296
+ function componentReplacer(str, replaceStr, path) {
297
+ var _a, _b;
298
+ let importName = importsMap.get(path);
299
+ if (!importName)
300
+ importName = ROUTE_IMPORT_NAME.replace("$1", `${importsMap.size}`);
301
+ importsMap.set(path, importName);
302
+ importName = ((_b = (_a = options.resolver.stringify) == null ? void 0 : _a.component) == null ? void 0 : _b.call(_a, importName)) || importName;
303
+ return str.replace(replaceStr, importName);
304
+ }
305
+ function functionReplacer(str, replaceStr, content) {
306
+ if (content.startsWith("function"))
307
+ return str.replace(replaceStr, content);
308
+ if (content.startsWith("_NuFrRa_"))
309
+ return str.replace(replaceStr, content.slice(8));
310
+ return str;
311
+ }
312
+ const stringRoutes = JSON.stringify(preparedRoutes, replaceFunction).replace(componentRE, componentReplacer).replace(hasFunctionRE, functionReplacer);
313
+ const imports = Array.from(importsMap).map((args) => getImportString(...args));
314
+ return {
315
+ imports,
316
+ stringRoutes
317
+ };
318
+ }
319
+ function generateClientCode(routes, options) {
320
+ var _a, _b;
321
+ const { imports, stringRoutes } = stringifyRoutes(routes, options);
322
+ const code = `${imports.join(";\n")};
323
+
324
+ const routes = ${stringRoutes};
325
+
326
+ export default routes;`;
327
+ return ((_b = (_a = options.resolver.stringify) == null ? void 0 : _a.final) == null ? void 0 : _b.call(_a, code)) || code;
328
+ }
329
+
330
+ // src/resolvers/react.ts
331
+ function prepareRoutes(routes, options, parent) {
332
+ var _a, _b;
333
+ for (const route of routes) {
334
+ if (parent)
335
+ route.path = (_a = route.path) == null ? void 0 : _a.replace(/^\//, "");
336
+ if (route.children)
337
+ route.children = prepareRoutes(route.children, options, route);
338
+ delete route.rawRoute;
339
+ Object.assign(route, ((_b = options.extendRoute) == null ? void 0 : _b.call(options, route, parent)) || {});
340
+ }
341
+ return routes;
342
+ }
343
+ async function computeReactRoutes(ctx) {
344
+ var _a, _b;
345
+ const { routeStyle, caseSensitive, importPath } = ctx.options;
346
+ const nuxtStyle = routeStyle === "nuxt";
347
+ const pageRoutes = [...ctx.pageRouteMap.values()].sort((a, b) => countSlash(a.route) - countSlash(b.route));
348
+ const routes = [];
349
+ pageRoutes.forEach((page) => {
350
+ const pathNodes = page.route.split("/");
351
+ const element = importPath === "relative" ? page.path.replace(ctx.root, "") : page.path;
352
+ let parentRoutes = routes;
353
+ for (let i = 0; i < pathNodes.length; i++) {
354
+ const node = pathNodes[i];
355
+ const route = {
356
+ caseSensitive,
357
+ path: "",
358
+ rawRoute: pathNodes.slice(0, i + 1).join("/")
359
+ };
360
+ if (i === pathNodes.length - 1)
361
+ route.element = element;
362
+ const isIndexRoute = normalizeCase(node, caseSensitive).endsWith("index");
363
+ if (!route.path && isIndexRoute) {
364
+ route.path = "/";
365
+ } else if (!isIndexRoute) {
366
+ if (routeStyle === "remix")
367
+ route.path = buildReactRemixRoutePath(node);
368
+ else
369
+ route.path = buildReactRoutePath(node, nuxtStyle);
370
+ }
371
+ const parent = parentRoutes.find((parent2) => {
372
+ return pathNodes.slice(0, i).join("/") === parent2.rawRoute;
373
+ });
374
+ if (parent) {
375
+ parent.children = parent.children || [];
376
+ parentRoutes = parent.children;
377
+ }
378
+ const exits = parentRoutes.some((parent2) => {
379
+ return pathNodes.slice(0, i + 1).join("/") === parent2.rawRoute;
380
+ });
381
+ if (!exits)
382
+ parentRoutes.push(route);
383
+ }
384
+ });
385
+ let finalRoutes = prepareRoutes(routes, ctx.options);
386
+ finalRoutes = await ((_b = (_a = ctx.options).onRoutesGenerated) == null ? void 0 : _b.call(_a, finalRoutes)) || finalRoutes;
387
+ return finalRoutes;
388
+ }
389
+ async function resolveReactRoutes(ctx) {
390
+ var _a, _b;
391
+ const finalRoutes = await computeReactRoutes(ctx);
392
+ let client = generateClientCode(finalRoutes, ctx.options);
393
+ client = await ((_b = (_a = ctx.options).onClientGenerated) == null ? void 0 : _b.call(_a, client)) || client;
394
+ return client;
395
+ }
396
+ function reactResolver() {
397
+ return {
398
+ resolveModuleIds() {
399
+ return ["~react-pages", "virtual:generated-pages-react"];
400
+ },
401
+ resolveExtensions() {
402
+ return ["tsx", "jsx", "ts", "js"];
403
+ },
404
+ async resolveRoutes(ctx) {
405
+ return resolveReactRoutes(ctx);
406
+ },
407
+ async getComputedRoutes(ctx) {
408
+ return computeReactRoutes(ctx);
409
+ },
410
+ stringify: {
411
+ component: (path) => `React.createElement(${path})`,
412
+ dynamicImport: (path) => `React.lazy(() => import("${path}"))`,
413
+ final: (code) => `import React from "react";
414
+ ${code}`
415
+ }
416
+ };
417
+ }
418
+
419
+ // src/resolvers/solid.ts
420
+ function prepareRoutes2(options, routes, parent) {
421
+ var _a, _b;
422
+ for (const route of routes) {
423
+ if (parent)
424
+ route.path = (_a = route.path) == null ? void 0 : _a.replace(/^\//, "");
425
+ if (route.children)
426
+ route.children = prepareRoutes2(options, route.children, route);
427
+ delete route.rawRoute;
428
+ Object.assign(route, ((_b = options.extendRoute) == null ? void 0 : _b.call(options, route, parent)) || {});
429
+ }
430
+ return routes;
431
+ }
432
+ async function computeSolidRoutes(ctx) {
433
+ var _a, _b;
434
+ const { routeStyle, caseSensitive, importPath } = ctx.options;
435
+ const nuxtStyle = routeStyle === "nuxt";
436
+ const pageRoutes = [...ctx.pageRouteMap.values()].sort((a, b) => countSlash(a.route) - countSlash(b.route));
437
+ const routes = [];
438
+ pageRoutes.forEach((page) => {
439
+ const pathNodes = page.route.split("/");
440
+ const component = importPath === "relative" ? page.path.replace(ctx.root, "") : page.path;
441
+ const element = importPath === "relative" ? page.path.replace(ctx.root, "") : page.path;
442
+ let parentRoutes = routes;
443
+ for (let i = 0; i < pathNodes.length; i++) {
444
+ const node = pathNodes[i];
445
+ const normalizedPath = normalizeCase(node, caseSensitive);
446
+ const route = {
447
+ path: "",
448
+ rawRoute: pathNodes.slice(0, i + 1).join("/")
449
+ };
450
+ const parent = parentRoutes.find(
451
+ (parent2) => pathNodes.slice(0, i).join("/") === parent2.rawRoute
452
+ );
453
+ if (parent) {
454
+ parent.children = parent.children || [];
455
+ parentRoutes = parent.children;
456
+ }
457
+ if (i === pathNodes.length - 1) {
458
+ route.element = element;
459
+ route.component = component;
460
+ }
461
+ if (normalizedPath === "index") {
462
+ if (!route.path)
463
+ route.path = "/";
464
+ } else if (normalizedPath !== "index") {
465
+ if (routeStyle === "remix")
466
+ route.path = buildReactRemixRoutePath(node) || "";
467
+ else
468
+ route.path = buildReactRoutePath(node, nuxtStyle) || "";
469
+ }
470
+ const exist = parentRoutes.some((parent2) => {
471
+ return pathNodes.slice(0, i + 1).join("/") === parent2.rawRoute;
472
+ });
473
+ if (!exist)
474
+ parentRoutes.push(route);
475
+ }
476
+ });
477
+ let finalRoutes = prepareRoutes2(ctx.options, routes);
478
+ finalRoutes = await ((_b = (_a = ctx.options).onRoutesGenerated) == null ? void 0 : _b.call(_a, finalRoutes)) || finalRoutes;
479
+ return finalRoutes;
480
+ }
481
+ async function resolveSolidRoutes(ctx) {
482
+ var _a, _b;
483
+ const finalRoutes = await computeSolidRoutes(ctx);
484
+ let client = generateClientCode(finalRoutes, ctx.options);
485
+ client = await ((_b = (_a = ctx.options).onClientGenerated) == null ? void 0 : _b.call(_a, client)) || client;
486
+ return client;
487
+ }
488
+ function solidResolver() {
489
+ return {
490
+ resolveModuleIds() {
491
+ return ["~solid-pages"];
492
+ },
493
+ resolveExtensions() {
494
+ return ["tsx", "jsx", "ts", "js"];
495
+ },
496
+ async resolveRoutes(ctx) {
497
+ return resolveSolidRoutes(ctx);
498
+ },
499
+ async getComputedRoutes(ctx) {
500
+ return computeSolidRoutes(ctx);
501
+ },
502
+ stringify: {
503
+ dynamicImport: (path) => `Solid.lazy(() => import("${path}"))`,
504
+ final: (code) => `import * as Solid from "solid-js";
505
+ ${code}`
506
+ }
507
+ };
508
+ }
509
+
510
+ // src/resolvers/vue.ts
511
+ var import_dequal = require("dequal");
512
+ var import_picocolors = __toESM(require("picocolors"), 1);
513
+
514
+ // src/customBlock.ts
515
+ var import_node_fs = __toESM(require("fs"), 1);
516
+ var import_extract_comments = __toESM(require("extract-comments"), 1);
517
+ var import_json5 = __toESM(require("json5"), 1);
518
+ var import_local_pkg = require("local-pkg");
519
+ var import_yaml = require("yaml");
520
+ var routeJSXReg = /^\s+(route)\s+/gm;
521
+ function parseJSX(code) {
522
+ return (0, import_extract_comments.default)(code).slice(0, 1).filter((comment) => routeJSXReg.test(comment.value) && comment.value.includes(":") && comment.loc.start.line === 1);
523
+ }
524
+ function parseYamlComment(code, path) {
525
+ return code.reduce((memo, item) => {
526
+ const { value } = item;
527
+ const v = value.replace(routeJSXReg, "");
528
+ debug.routeBlock(`use ${v} parser`);
529
+ try {
530
+ const yamlResult = (0, import_yaml.parse)(v);
531
+ return __spreadValues(__spreadValues({}, memo), yamlResult);
532
+ } catch (err) {
533
+ throw new Error(`Invalid YAML format of comment in ${path}
534
+ ${err.message}`);
535
+ }
536
+ }, {});
537
+ }
538
+ async function parseSFC(code) {
539
+ try {
540
+ const { parse } = await (0, import_local_pkg.importModule)("@vue/compiler-sfc");
541
+ return parse(code, {
542
+ pad: "space"
543
+ }).descriptor || parse({
544
+ source: code
545
+ });
546
+ } catch (e) {
547
+ throw new Error(`[vite-plugin-pages] Vue3's "@vue/compiler-sfc" is required.`);
548
+ }
549
+ }
550
+ function parseCustomBlock(block, filePath, options) {
551
+ var _a;
552
+ const lang = (_a = block.lang) != null ? _a : options.routeBlockLang;
553
+ debug.routeBlock(`use ${lang} parser`);
554
+ if (lang === "json5") {
555
+ try {
556
+ return import_json5.default.parse(block.content);
557
+ } catch (err) {
558
+ throw new Error(`Invalid JSON5 format of <${block.type}> content in ${filePath}
559
+ ${err.message}`);
560
+ }
561
+ } else if (lang === "json") {
562
+ try {
563
+ return JSON.parse(block.content);
564
+ } catch (err) {
565
+ throw new Error(`Invalid JSON format of <${block.type}> content in ${filePath}
566
+ ${err.message}`);
567
+ }
568
+ } else if (lang === "yaml" || lang === "yml") {
569
+ try {
570
+ return (0, import_yaml.parse)(block.content);
571
+ } catch (err) {
572
+ throw new Error(`Invalid YAML format of <${block.type}> content in ${filePath}
573
+ ${err.message}`);
574
+ }
575
+ }
576
+ }
577
+ async function getRouteBlock(path, options) {
578
+ const content = import_node_fs.default.readFileSync(path, "utf8");
579
+ const parsedSFC = await parseSFC(content);
580
+ const blockStr = parsedSFC == null ? void 0 : parsedSFC.customBlocks.find((b) => b.type === "route");
581
+ const parsedJSX = parseJSX(content);
582
+ if (!blockStr && parsedJSX.length === 0)
583
+ return;
584
+ let result;
585
+ if (blockStr)
586
+ result = parseCustomBlock(blockStr, path, options);
587
+ if (parsedJSX.length > 0)
588
+ result = parseYamlComment(parsedJSX, path);
589
+ return result;
590
+ }
591
+
592
+ // src/resolvers/vue.ts
593
+ function prepareRoutes3(ctx, routes, parent) {
594
+ var _a, _b, _c, _d;
595
+ for (const route of routes) {
596
+ if (route.name)
597
+ route.name = route.name.replace(new RegExp(`${ctx.options.routeNameSeparator}index$`), "");
598
+ if (parent)
599
+ route.path = (_a = route.path) == null ? void 0 : _a.replace(/^\//, "");
600
+ if (route.children)
601
+ route.children = prepareRoutes3(ctx, route.children, route);
602
+ if ((_b = route.children) == null ? void 0 : _b.find((c) => c.name === route.name))
603
+ delete route.name;
604
+ route.props = true;
605
+ delete route.rawRoute;
606
+ if (route.customBlock) {
607
+ Object.assign(route, route.customBlock || {});
608
+ delete route.customBlock;
609
+ }
610
+ Object.assign(route, ((_d = (_c = ctx.options).extendRoute) == null ? void 0 : _d.call(_c, route, parent)) || {});
611
+ }
612
+ return routes;
613
+ }
614
+ async function computeVueRoutes(ctx, customBlockMap) {
615
+ var _a, _b;
616
+ const { routeStyle, caseSensitive, importPath, routeNameSeparator } = ctx.options;
617
+ const pageRoutes = [...ctx.pageRouteMap.values()].sort((a, b) => countSlash(a.route) - countSlash(b.route));
618
+ const routes = [];
619
+ pageRoutes.forEach((page) => {
620
+ const pathNodes = page.route.split("/");
621
+ const component = importPath === "relative" ? page.path.replace(ctx.root, "") : page.path;
622
+ const customBlock = customBlockMap.get(page.path);
623
+ const route = {
624
+ name: "",
625
+ path: "",
626
+ component,
627
+ customBlock,
628
+ rawRoute: page.route
629
+ };
630
+ let parentRoutes = routes;
631
+ let dynamicRoute = false;
632
+ for (let i = 0; i < pathNodes.length; i++) {
633
+ const node = pathNodes[i];
634
+ const nuxtStyle = routeStyle === "nuxt";
635
+ const isDynamic = isDynamicRoute(node, nuxtStyle);
636
+ const isCatchAll = isCatchAllRoute(node, nuxtStyle);
637
+ const normalizedName = normalizeName(node, isDynamic, nuxtStyle);
638
+ const normalizedPath = normalizeCase(normalizedName, caseSensitive);
639
+ if (isDynamic)
640
+ dynamicRoute = true;
641
+ route.name += route.name ? `${routeNameSeparator}${normalizedName}` : normalizedName;
642
+ const parent = parentRoutes.find((parent2) => {
643
+ return pathNodes.slice(0, i + 1).join("/") === parent2.rawRoute;
644
+ });
645
+ if (parent) {
646
+ parent.children = parent.children || [];
647
+ parentRoutes = parent.children;
648
+ route.path = "";
649
+ } else if (normalizedPath === "index") {
650
+ if (!route.path)
651
+ route.path = "/";
652
+ } else if (normalizedPath !== "index") {
653
+ if (isDynamic) {
654
+ route.path += `/:${normalizedName}`;
655
+ if (isCatchAll) {
656
+ if (i === 0)
657
+ route.path += "(.*)*";
658
+ else
659
+ route.path += "(.*)";
660
+ } else if (nuxtStyle && i === pathNodes.length - 1) {
661
+ const isIndexFound = pageRoutes.find(({ route: route2 }) => {
662
+ return route2 === page.route.replace(pathNodes[i], "index");
663
+ });
664
+ if (!isIndexFound)
665
+ route.path += "?";
666
+ }
667
+ } else {
668
+ route.path += `/${normalizedPath}`;
669
+ }
670
+ }
671
+ }
672
+ if (dynamicRoute)
673
+ parentRoutes.push(route);
674
+ else
675
+ parentRoutes.unshift(route);
676
+ });
677
+ let finalRoutes = prepareRoutes3(ctx, routes);
678
+ finalRoutes = await ((_b = (_a = ctx.options).onRoutesGenerated) == null ? void 0 : _b.call(_a, finalRoutes)) || finalRoutes;
679
+ return finalRoutes;
680
+ }
681
+ async function resolveVueRoutes(ctx, customBlockMap) {
682
+ var _a, _b;
683
+ const finalRoutes = await computeVueRoutes(ctx, customBlockMap);
684
+ let client = generateClientCode(finalRoutes, ctx.options);
685
+ client = await ((_b = (_a = ctx.options).onClientGenerated) == null ? void 0 : _b.call(_a, client)) || client;
686
+ return client;
687
+ }
688
+ function vueResolver() {
689
+ const customBlockMap = /* @__PURE__ */ new Map();
690
+ async function checkCustomBlockChange(ctx, path) {
691
+ var _a;
692
+ const exitsCustomBlock = customBlockMap.get(path);
693
+ let customBlock;
694
+ try {
695
+ customBlock = await getRouteBlock(path, ctx.options);
696
+ } catch (error) {
697
+ (_a = ctx.logger) == null ? void 0 : _a.error(import_picocolors.default.red(`[vite-plugin-pages] ${error.message}`));
698
+ return;
699
+ }
700
+ if (!exitsCustomBlock && !customBlock)
701
+ return;
702
+ if (!customBlock) {
703
+ customBlockMap.delete(path);
704
+ ctx.debug.routeBlock("%s deleted", path);
705
+ return;
706
+ }
707
+ if (!exitsCustomBlock || !(0, import_dequal.dequal)(exitsCustomBlock, customBlock)) {
708
+ ctx.debug.routeBlock("%s old: %O", path, exitsCustomBlock);
709
+ ctx.debug.routeBlock("%s new: %O", path, customBlock);
710
+ customBlockMap.set(path, customBlock);
711
+ ctx.onUpdate();
712
+ }
713
+ }
714
+ return {
715
+ resolveExtensions() {
716
+ return ["vue", "ts", "js"];
717
+ },
718
+ resolveModuleIds() {
719
+ return ["~pages", "pages-generated", "virtual:generated-pages"];
720
+ },
721
+ async resolveRoutes(ctx) {
722
+ return resolveVueRoutes(ctx, customBlockMap);
723
+ },
724
+ async getComputedRoutes(ctx) {
725
+ return computeVueRoutes(ctx, customBlockMap);
726
+ },
727
+ hmr: {
728
+ added: async (ctx, path) => checkCustomBlockChange(ctx, path),
729
+ changed: async (ctx, path) => checkCustomBlockChange(ctx, path),
730
+ removed: async (_ctx, path) => {
731
+ customBlockMap.delete(path);
732
+ }
733
+ }
734
+ };
735
+ }
736
+
737
+ // src/options.ts
738
+ function resolvePageDirs(dirs, root, exclude) {
739
+ dirs = toArray(dirs);
740
+ return dirs.flatMap((dir) => {
741
+ const option = typeof dir === "string" ? { dir, baseRoute: "" } : dir;
742
+ option.dir = slash((0, import_node_path3.resolve)(root, option.dir)).replace(`${root}/`, "");
743
+ option.baseRoute = option.baseRoute.replace(/^\//, "").replace(/\/$/, "");
744
+ return getPageDirs(option, root, exclude);
745
+ });
746
+ }
747
+ var syncIndexResolver = (filepath, options) => {
748
+ for (const page of options.dirs) {
749
+ if (page.baseRoute === "" && filepath.startsWith(`/${page.dir}/index`))
750
+ return "sync";
751
+ }
752
+ return "async";
753
+ };
754
+ function getResolver(originalResolver) {
755
+ let resolver = originalResolver || "vue";
756
+ if (typeof resolver !== "string")
757
+ return resolver;
758
+ switch (resolver) {
759
+ case "vue":
760
+ resolver = vueResolver();
761
+ break;
762
+ case "react":
763
+ resolver = reactResolver();
764
+ break;
765
+ case "solid":
766
+ resolver = solidResolver();
767
+ break;
768
+ default:
769
+ throw new Error(`Unsupported resolver: ${resolver}`);
770
+ }
771
+ return resolver;
772
+ }
773
+ function resolveOptions(userOptions, viteRoot) {
774
+ var _a;
775
+ const {
776
+ dirs = userOptions.pagesDir || ["src/pages"],
777
+ routeBlockLang = "json5",
778
+ exclude = ["node_modules", ".git", "**/__*__/**"],
779
+ caseSensitive = false,
780
+ syncIndex = true,
781
+ routeNameSeparator = "-",
782
+ extendRoute,
783
+ onRoutesGenerated,
784
+ onClientGenerated
785
+ } = userOptions;
786
+ const root = viteRoot || slash(import_node_process.default.cwd());
787
+ const importMode = userOptions.importMode || (syncIndex ? syncIndexResolver : "async");
788
+ const importPath = userOptions.importPath || "relative";
789
+ const resolver = getResolver(userOptions.resolver);
790
+ const extensions = userOptions.extensions || resolver.resolveExtensions();
791
+ const extensionsRE = new RegExp(`\\.(${extensions.join("|")})$`);
792
+ const resolvedDirs = resolvePageDirs(dirs, root, exclude);
793
+ const routeStyle = userOptions.nuxtStyle ? "nuxt" : userOptions.routeStyle || "next";
794
+ const moduleIds = userOptions.moduleId ? [userOptions.moduleId] : ((_a = resolver.resolveModuleIds) == null ? void 0 : _a.call(resolver)) || MODULE_IDS;
795
+ const resolvedOptions = {
796
+ dirs: resolvedDirs,
797
+ routeStyle,
798
+ routeBlockLang,
799
+ moduleIds,
800
+ root,
801
+ extensions,
802
+ importMode,
803
+ importPath,
804
+ exclude,
805
+ caseSensitive,
806
+ resolver,
807
+ extensionsRE,
808
+ extendRoute,
809
+ onRoutesGenerated,
810
+ onClientGenerated,
811
+ routeNameSeparator
812
+ };
813
+ return resolvedOptions;
814
+ }
815
+
816
+ // src/context.ts
817
+ var PageContext = class {
818
+ constructor(userOptions, viteRoot = import_node_process2.default.cwd()) {
819
+ this._pageRouteMap = /* @__PURE__ */ new Map();
820
+ this.rawOptions = userOptions;
821
+ this.root = slash(viteRoot);
822
+ debug.env("root", this.root);
823
+ this.options = resolveOptions(userOptions, this.root);
824
+ debug.options(this.options);
825
+ }
826
+ setLogger(logger) {
827
+ this.logger = logger;
828
+ }
829
+ setupViteServer(server) {
830
+ if (this._server === server)
831
+ return;
832
+ this._server = server;
833
+ this.setupWatcher(server.watcher);
834
+ }
835
+ setupWatcher(watcher) {
836
+ watcher.on("unlink", async (path) => {
837
+ path = slash(path);
838
+ if (!isTarget(path, this.options))
839
+ return;
840
+ await this.removePage(path);
841
+ this.onUpdate();
842
+ });
843
+ watcher.on("add", async (path) => {
844
+ path = slash(path);
845
+ if (!isTarget(path, this.options))
846
+ return;
847
+ const page = this.options.dirs.find((i) => path.startsWith(slash((0, import_node_path4.resolve)(this.root, i.dir))));
848
+ await this.addPage(path, page);
849
+ this.onUpdate();
850
+ });
851
+ watcher.on("change", async (path) => {
852
+ var _a, _b;
853
+ path = slash(path);
854
+ if (!isTarget(path, this.options))
855
+ return;
856
+ const page = this._pageRouteMap.get(path);
857
+ if (page)
858
+ await ((_b = (_a = this.options.resolver.hmr) == null ? void 0 : _a.changed) == null ? void 0 : _b.call(_a, this, path));
859
+ });
860
+ }
861
+ async addPage(path, pageDir) {
862
+ var _a, _b;
863
+ debug.pages("add", path);
864
+ for (const p of toArray(path)) {
865
+ const pageDirPath = slash((0, import_node_path4.resolve)(this.root, pageDir.dir));
866
+ const extension = this.options.extensions.find((ext) => p.endsWith(`.${ext}`));
867
+ if (!extension)
868
+ continue;
869
+ const route = slash((0, import_node_path4.join)(pageDir.baseRoute, p.replace(`${pageDirPath}/`, "").replace(`.${extension}`, "")));
870
+ this._pageRouteMap.set(p, {
871
+ path: p,
872
+ route
873
+ });
874
+ await ((_b = (_a = this.options.resolver.hmr) == null ? void 0 : _a.added) == null ? void 0 : _b.call(_a, this, p));
875
+ }
876
+ }
877
+ async removePage(path) {
878
+ var _a, _b;
879
+ debug.pages("remove", path);
880
+ this._pageRouteMap.delete(path);
881
+ await ((_b = (_a = this.options.resolver.hmr) == null ? void 0 : _a.removed) == null ? void 0 : _b.call(_a, this, path));
882
+ }
883
+ onUpdate() {
884
+ if (!this._server)
885
+ return;
886
+ invalidatePagesModule(this._server);
887
+ debug.hmr("Reload generated pages.");
888
+ this._server.ws.send({
889
+ type: "full-reload"
890
+ });
891
+ }
892
+ async resolveRoutes() {
893
+ return this.options.resolver.resolveRoutes(this);
894
+ }
895
+ async searchGlob() {
896
+ const pageDirFiles = this.options.dirs.map((page) => {
897
+ const pagesDirPath = slash((0, import_node_path4.resolve)(this.options.root, page.dir));
898
+ const files = getPageFiles(pagesDirPath, this.options, page);
899
+ debug.search(page.dir, files);
900
+ return __spreadProps(__spreadValues({}, page), {
901
+ files: files.map((file) => slash(file))
902
+ });
903
+ });
904
+ for (const page of pageDirFiles)
905
+ await this.addPage(page.files, page);
906
+ debug.cache(this.pageRouteMap);
907
+ }
908
+ get debug() {
909
+ return debug;
910
+ }
911
+ get pageRouteMap() {
912
+ return this._pageRouteMap;
913
+ }
914
+ };
915
+
916
+ // src/index.ts
917
+ function pagesPlugin(userOptions = {}) {
918
+ let ctx;
919
+ return {
920
+ name: "vite-plugin-pages",
921
+ enforce: "pre",
922
+ async configResolved(config) {
923
+ if (!userOptions.resolver && config.plugins.find((i) => i.name.includes("vite:react"))) {
924
+ userOptions.resolver = "react";
925
+ }
926
+ if (!userOptions.resolver && config.plugins.find((i) => i.name.includes("solid"))) {
927
+ userOptions.resolver = "solid";
928
+ }
929
+ ctx = new PageContext(userOptions, config.root);
930
+ ctx.setLogger(config.logger);
931
+ await ctx.searchGlob();
932
+ },
933
+ api: {
934
+ getResolvedRoutes() {
935
+ return ctx.options.resolver.getComputedRoutes(ctx);
936
+ }
937
+ },
938
+ configureServer(server) {
939
+ ctx.setupViteServer(server);
940
+ },
941
+ resolveId(id) {
942
+ if (ctx.options.moduleIds.includes(id))
943
+ return `${MODULE_ID_VIRTUAL}?id=${id}`;
944
+ if (routeBlockQueryRE.test(id))
945
+ return ROUTE_BLOCK_ID_VIRTUAL;
946
+ return null;
947
+ },
948
+ async load(id) {
949
+ const {
950
+ moduleId,
951
+ pageId
952
+ } = parsePageRequest(id);
953
+ if (moduleId === MODULE_ID_VIRTUAL && pageId && ctx.options.moduleIds.includes(pageId))
954
+ return ctx.resolveRoutes();
955
+ if (id === ROUTE_BLOCK_ID_VIRTUAL) {
956
+ return {
957
+ code: "export default {};",
958
+ map: null
959
+ };
960
+ }
961
+ return null;
962
+ }
963
+ };
964
+ }
965
+ var index_default = pagesPlugin;
966
+ // Annotate the CommonJS export names for ESM import in node:
967
+ 0 && (module.exports = {
968
+ PageContext,
969
+ reactResolver,
970
+ solidResolver,
971
+ syncIndexResolver,
972
+ vueResolver
973
+ });
974
+ //# sourceMappingURL=index.cjs.map