@uni-helper/vite-plugin-uni-pages 0.3.2 → 0.3.4

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 CHANGED
@@ -2,39 +2,67 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- const path = require('node:path');
6
5
  const node_child_process = require('node:child_process');
6
+ const path = require('node:path');
7
7
  const process = require('node:process');
8
- const vite = require('vite');
9
- const MagicString = require('magic-string');
8
+ const astKit = require('ast-kit');
10
9
  const chokidar = require('chokidar');
11
- const unconfig = require('unconfig');
12
- const Debug = require('debug');
10
+ const kolorist = require('kolorist');
11
+ const MagicString = require('magic-string');
12
+ const vite = require('vite');
13
13
  const uniEnv = require('@uni-helper/uni-env');
14
+ const commentJson = require('comment-json');
15
+ const Debug = require('debug');
14
16
  const detectIndent = require('detect-indent');
15
17
  const detectNewline = require('detect-newline');
16
- const commentJson = require('comment-json');
18
+ const unconfig = require('unconfig');
17
19
  const fs = require('node:fs');
18
20
  const promises = require('node:fs/promises');
21
+ const fg = require('fast-glob');
22
+ const node_module = require('node:module');
23
+ const vm = require('node:vm');
24
+ const babelGenerator = require('@babel/generator');
19
25
  const groupBy = require('lodash.groupby');
26
+ const ts = require('typescript');
27
+ const t = require('@babel/types');
28
+ const compilerSfc = require('@vue/compiler-sfc');
20
29
  const JSON5 = require('json5');
21
30
  const yaml = require('yaml');
22
- const compilerSfc = require('@vue/compiler-sfc');
23
- const fg = require('fast-glob');
24
31
 
25
32
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
26
33
 
34
+ function _interopNamespaceCompat(e) {
35
+ if (e && typeof e === 'object' && 'default' in e) return e;
36
+ const n = Object.create(null);
37
+ if (e) {
38
+ for (const k in e) {
39
+ n[k] = e[k];
40
+ }
41
+ }
42
+ n.default = e;
43
+ return n;
44
+ }
45
+
27
46
  const path__default = /*#__PURE__*/_interopDefaultCompat(path);
28
47
  const process__default = /*#__PURE__*/_interopDefaultCompat(process);
29
- const MagicString__default = /*#__PURE__*/_interopDefaultCompat(MagicString);
30
48
  const chokidar__default = /*#__PURE__*/_interopDefaultCompat(chokidar);
49
+ const MagicString__default = /*#__PURE__*/_interopDefaultCompat(MagicString);
31
50
  const Debug__default = /*#__PURE__*/_interopDefaultCompat(Debug);
32
51
  const detectIndent__default = /*#__PURE__*/_interopDefaultCompat(detectIndent);
33
52
  const detectNewline__default = /*#__PURE__*/_interopDefaultCompat(detectNewline);
34
53
  const fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
54
+ const fg__default = /*#__PURE__*/_interopDefaultCompat(fg);
55
+ const vm__default = /*#__PURE__*/_interopDefaultCompat(vm);
56
+ const babelGenerator__default = /*#__PURE__*/_interopDefaultCompat(babelGenerator);
35
57
  const groupBy__default = /*#__PURE__*/_interopDefaultCompat(groupBy);
58
+ const ts__namespace = /*#__PURE__*/_interopNamespaceCompat(ts);
59
+ const t__namespace = /*#__PURE__*/_interopNamespaceCompat(t);
36
60
  const JSON5__default = /*#__PURE__*/_interopDefaultCompat(JSON5);
37
- const fg__default = /*#__PURE__*/_interopDefaultCompat(fg);
61
+
62
+ const MODULE_ID_VIRTUAL = "virtual:uni-pages";
63
+ const RESOLVED_MODULE_ID_VIRTUAL = `\0${MODULE_ID_VIRTUAL}`;
64
+ const OUTPUT_NAME = "pages.json";
65
+ const FILE_EXTENSIONS = ["vue", "nvue", "uvue"];
38
66
 
39
67
  function slash(str) {
40
68
  return str.replace(/\\/g, "/");
@@ -86,86 +114,6 @@ async function writeDeclaration(ctx, filepath) {
86
114
  await writeFile(filepath, code);
87
115
  }
88
116
 
89
- const MODULE_ID_VIRTUAL = "virtual:uni-pages";
90
- const RESOLVED_MODULE_ID_VIRTUAL = `\0${MODULE_ID_VIRTUAL}`;
91
- const OUTPUT_NAME = "pages.json";
92
- const FILE_EXTENSIONS = ["vue", "nvue", "uvue"];
93
-
94
- async function parseSFC(code) {
95
- try {
96
- return compilerSfc.parse(code, {
97
- pad: "space"
98
- }).descriptor || compilerSfc.parse({
99
- source: code
100
- });
101
- } catch (error) {
102
- throw new Error(`[vite-plugin-uni-pages] Vue3's "@vue/compiler-sfc" is required.
103
- Original error:
104
- ${error}`);
105
- }
106
- }
107
- function parseCustomBlock(block, filePath, options) {
108
- const lang = block.lang ?? options.routeBlockLang;
109
- const attr = {
110
- type: "page",
111
- ...block.attrs
112
- };
113
- let content;
114
- debug.routeBlock(`use ${lang} parser`);
115
- if (lang === "json5") {
116
- try {
117
- content = JSON5__default.parse(block.content);
118
- } catch (err) {
119
- throw new Error(
120
- `Invalid JSON5 format of <${block.type}> content in ${filePath}
121
- ${err.message}`
122
- );
123
- }
124
- } else if (lang === "jsonc") {
125
- try {
126
- content = commentJson.parse(block.content);
127
- } catch (err) {
128
- throw new Error(
129
- `Invalid JSONC format of <${block.type}> content in ${filePath}
130
- ${err.message}`
131
- );
132
- }
133
- } else if (lang === "json") {
134
- try {
135
- content = JSON.parse(block.content);
136
- } catch (err) {
137
- throw new Error(
138
- `Invalid JSON format of <${block.type}> content in ${filePath}
139
- ${err.message}`
140
- );
141
- }
142
- } else if (lang === "yaml" || lang === "yml") {
143
- try {
144
- content = yaml.parse(block.content);
145
- } catch (err) {
146
- throw new Error(
147
- `Invalid YAML format of <${block.type}> content in ${filePath}
148
- ${err.message}`
149
- );
150
- }
151
- }
152
- return {
153
- attr,
154
- content: content ?? {}
155
- };
156
- }
157
- async function getRouteSfcBlock(path) {
158
- const content = fs__default.readFileSync(path, "utf8");
159
- const parsedSFC = await parseSFC(content);
160
- const blockStr = parsedSFC?.customBlocks.find((b) => b.type === "route");
161
- return blockStr;
162
- }
163
- async function getRouteBlock(path, blockStr, options) {
164
- if (!blockStr)
165
- return;
166
- return parseCustomBlock(blockStr, path, options);
167
- }
168
-
169
117
  function invalidatePagesModule(server) {
170
118
  const { moduleGraph } = server;
171
119
  const mods = moduleGraph.getModulesByFile(RESOLVED_MODULE_ID_VIRTUAL);
@@ -184,20 +132,21 @@ const debug = {
184
132
  subPages: Debug__default("vite-plugin-uni-pages:subPages"),
185
133
  error: Debug__default("vite-plugin-uni-pages:error"),
186
134
  cache: Debug__default("vite-plugin-uni-pages:cache"),
187
- declaration: Debug__default("vite-plugin-uni-pages:declaration")
135
+ declaration: Debug__default("vite-plugin-uni-pages:declaration"),
136
+ definePage: Debug__default("vite-plugin-uni-pages:definePage")
188
137
  };
189
138
  function extsToGlob(extensions) {
190
139
  return extensions.length > 1 ? `{${extensions.join(",")}}` : extensions[0] || "";
191
140
  }
192
- function isTargetFile(path) {
193
- const ext = path.split(".").pop();
141
+ function isTargetFile(path2) {
142
+ const ext = path2.split(".").pop();
194
143
  return FILE_EXTENSIONS.includes(ext);
195
144
  }
196
145
  function mergePageMetaDataArray(pageMetaData) {
197
146
  const pageMetaDataObj = groupBy__default(pageMetaData, "path");
198
147
  const result = [];
199
- for (const path in pageMetaDataObj) {
200
- const _pageMetaData = pageMetaDataObj[path];
148
+ for (const path2 in pageMetaDataObj) {
149
+ const _pageMetaData = pageMetaDataObj[path2];
201
150
  const options = _pageMetaData[0];
202
151
  for (const page of _pageMetaData) {
203
152
  options.style = Object.assign(options.style ?? {}, page.style ?? {});
@@ -207,26 +156,64 @@ function mergePageMetaDataArray(pageMetaData) {
207
156
  }
208
157
  return result;
209
158
  }
210
- function useCachedPages() {
211
- const pages = /* @__PURE__ */ new Map();
212
- function parseData(block) {
213
- return {
214
- content: block?.loc.source.trim() ?? "",
215
- attr: block?.attrs ?? ""
216
- };
159
+ async function execScript(code, filename) {
160
+ const jsCode = ts__namespace.transpileModule(code, {
161
+ compilerOptions: {
162
+ module: ts__namespace.ModuleKind.CommonJS,
163
+ target: ts__namespace.ScriptTarget.ESNext
164
+ }
165
+ }).outputText;
166
+ const dir = path__default.dirname(filename);
167
+ const vmContext = {
168
+ require: node_module.createRequire(dir),
169
+ module: {},
170
+ exports: {},
171
+ __filename: filename,
172
+ __dirname: dir
173
+ };
174
+ const script = new vm__default.Script(jsCode);
175
+ try {
176
+ script.runInNewContext(vmContext);
177
+ } catch (error) {
178
+ throw new Error(`${filename}: ${error.message}`);
217
179
  }
218
- function setCache(filePath, routeBlock) {
219
- pages.set(filePath, commentJson.stringify(parseData(routeBlock)));
180
+ const result = vmContext.exports.default || vmContext.exports;
181
+ if (typeof result === "function") {
182
+ return Promise.resolve(result());
220
183
  }
221
- async function hasChanged(filePath, routeBlock) {
222
- if (!routeBlock)
223
- routeBlock = await getRouteSfcBlock(vite.normalizePath(filePath));
224
- return !pages.has(filePath) || commentJson.stringify(parseData(routeBlock)) !== pages.get(filePath);
184
+ return Promise.resolve(result);
185
+ }
186
+ function getDefaultExport(expr) {
187
+ return expr.default === void 0 ? expr : expr.default;
188
+ }
189
+ const babelGenerate = getDefaultExport(babelGenerator__default);
190
+
191
+ function getPageFiles(path, options) {
192
+ const { exclude } = options;
193
+ const ext = extsToGlob(FILE_EXTENSIONS);
194
+ const files = fg__default.sync(`**/*.${ext}`, {
195
+ ignore: exclude,
196
+ onlyFiles: true,
197
+ cwd: path
198
+ });
199
+ return files;
200
+ }
201
+ function checkPagesJsonFile(path) {
202
+ if (!fs__default.existsSync(path)) {
203
+ writeFileSync(path, commentJson.stringify({ pages: [{ path: "" }] }, null, 2));
204
+ return false;
225
205
  }
226
- return {
227
- setCache,
228
- hasChanged
229
- };
206
+ return true;
207
+ }
208
+ function readFileSync(path) {
209
+ try {
210
+ return fs__default.readFileSync(path, { encoding: "utf-8" });
211
+ } catch {
212
+ return "";
213
+ }
214
+ }
215
+ function writeFileSync(path, content) {
216
+ fs__default.writeFileSync(path, content, { encoding: "utf-8" });
230
217
  }
231
218
 
232
219
  function resolveOptions(userOptions, viteRoot = process__default.cwd()) {
@@ -300,32 +287,190 @@ function resolvePageDirs(dir, root, exclude) {
300
287
  return dirs;
301
288
  }
302
289
 
303
- function getPageFiles(path, options) {
304
- const { exclude } = options;
305
- const ext = extsToGlob(FILE_EXTENSIONS);
306
- const files = fg__default.sync(`**/*.${ext}`, {
307
- ignore: exclude,
308
- onlyFiles: true,
309
- cwd: path
310
- });
311
- return files;
290
+ function parseCustomBlock(block, filePath, routeBlockLang) {
291
+ const lang = block.lang ?? routeBlockLang;
292
+ const attr = {
293
+ type: "page",
294
+ ...block.attrs
295
+ };
296
+ let content;
297
+ debug.routeBlock(`use ${lang} parser`);
298
+ if (lang === "json5") {
299
+ try {
300
+ content = JSON5__default.parse(block.content);
301
+ } catch (err) {
302
+ throw new Error(
303
+ `Invalid JSON5 format of <${block.type}> content in ${filePath}
304
+ ${err.message}`
305
+ );
306
+ }
307
+ } else if (lang === "jsonc") {
308
+ try {
309
+ content = commentJson.parse(block.content);
310
+ } catch (err) {
311
+ throw new Error(
312
+ `Invalid JSONC format of <${block.type}> content in ${filePath}
313
+ ${err.message}`
314
+ );
315
+ }
316
+ } else if (lang === "json") {
317
+ try {
318
+ content = JSON.parse(block.content);
319
+ } catch (err) {
320
+ throw new Error(
321
+ `Invalid JSON format of <${block.type}> content in ${filePath}
322
+ ${err.message}`
323
+ );
324
+ }
325
+ } else if (lang === "yaml" || lang === "yml") {
326
+ try {
327
+ content = yaml.parse(block.content);
328
+ } catch (err) {
329
+ throw new Error(
330
+ `Invalid YAML format of <${block.type}> content in ${filePath}
331
+ ${err.message}`
332
+ );
333
+ }
334
+ }
335
+ return {
336
+ attr,
337
+ content: content ?? {}
338
+ };
312
339
  }
313
- function checkPagesJsonFile(path) {
314
- if (!fs__default.existsSync(path)) {
315
- writeFileSync(path, commentJson.stringify({ pages: [{ path: "" }] }, null, 2));
316
- return false;
340
+ function getRouteSfcBlock(sfc) {
341
+ return sfc?.customBlocks.find((b) => b.type === "route");
342
+ }
343
+ function getRouteBlock(path, blockStr, routeBlockLang) {
344
+ if (!blockStr)
345
+ return;
346
+ return parseCustomBlock(blockStr, path, routeBlockLang);
347
+ }
348
+
349
+ var __defProp$1 = Object.defineProperty;
350
+ var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
351
+ var __publicField$1 = (obj, key, value) => {
352
+ __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
353
+ return value;
354
+ };
355
+ class Page {
356
+ constructor(ctx, path) {
357
+ __publicField$1(this, "ctx");
358
+ __publicField$1(this, "path");
359
+ __publicField$1(this, "rawOptions", "");
360
+ __publicField$1(this, "options");
361
+ this.ctx = ctx;
362
+ this.path = path;
363
+ }
364
+ async getPageMeta(forceUpdate = false) {
365
+ if (forceUpdate || !this.options) {
366
+ await this.readPageMeta();
367
+ }
368
+ return this.options;
369
+ }
370
+ async hasChanged() {
371
+ const { hasChanged } = await this.readPageMeta();
372
+ return hasChanged;
373
+ }
374
+ async readPageMeta() {
375
+ try {
376
+ const { relativePath } = this.path;
377
+ const { path: path$1, ...others } = await this.readPageMetaFromFile();
378
+ this.options = {
379
+ path: path$1 ?? vite.normalizePath(relativePath.replace(path.extname(relativePath), "")),
380
+ ...others
381
+ };
382
+ const raw = this.options ? JSON.stringify(this.options) : "";
383
+ const hasChanged = this.rawOptions !== raw;
384
+ this.rawOptions = raw;
385
+ return {
386
+ options: this.options,
387
+ hasChanged
388
+ };
389
+ } catch (err) {
390
+ throw new Error(`Read page options fail in ${this.path.relativePath}
391
+ ${err.message}`);
392
+ }
393
+ }
394
+ async readPageMetaFromFile() {
395
+ const content = fs.readFileSync(this.path.absolutePath, "utf-8");
396
+ const sfc = parseSFC(content, { filename: this.path.absolutePath });
397
+ const meta = await tryPageMetaFromMacro(sfc);
398
+ if (meta) {
399
+ return meta;
400
+ }
401
+ return tryPageMetaFromCustomBlock(sfc, this.ctx.options.routeBlockLang);
317
402
  }
318
- return true;
319
403
  }
320
- function readFileSync(path) {
404
+ function parseSFC(code, options) {
321
405
  try {
322
- return fs__default.readFileSync(path, { encoding: "utf-8" });
323
- } catch {
324
- return "";
406
+ return compilerSfc.parse(code, {
407
+ pad: "space",
408
+ ...options
409
+ }).descriptor || compilerSfc.parse({
410
+ source: code,
411
+ ...options
412
+ });
413
+ } catch (error) {
414
+ throw new Error(`[vite-plugin-uni-pages] Vue3's "@vue/compiler-sfc" is required.
415
+ Original error:
416
+ ${error}`);
325
417
  }
326
418
  }
327
- function writeFileSync(path, content) {
328
- fs__default.writeFileSync(path, content, { encoding: "utf-8" });
419
+ async function tryPageMetaFromMacro(sfc) {
420
+ const sfcScript = sfc.scriptSetup || sfc.script;
421
+ if (!sfcScript) {
422
+ return void 0;
423
+ }
424
+ const ast = astKit.babelParse(sfcScript.content, sfcScript.lang || "js", {
425
+ plugins: [["importAttributes", { deprecatedAssertSyntax: true }]]
426
+ });
427
+ const macro = findMacro(ast.body, sfc.filename);
428
+ if (macro) {
429
+ const imports = findImports(ast.body).map((imp) => babelGenerate(imp).code);
430
+ const [macroOption] = macro.arguments;
431
+ const code = babelGenerate(macroOption).code;
432
+ let script = "";
433
+ const importScript = imports.join("");
434
+ script += importScript;
435
+ script += `export default ${code}`;
436
+ const result = await execScript(script, sfc.filename);
437
+ return result;
438
+ }
439
+ return void 0;
440
+ }
441
+ async function tryPageMetaFromCustomBlock(sfc, routeBlockLang) {
442
+ const block = getRouteSfcBlock(sfc);
443
+ const routeBlock = getRouteBlock(sfc.filename, block, routeBlockLang);
444
+ const pageMeta = {
445
+ type: routeBlock?.attr.type ?? "page"
446
+ };
447
+ if (routeBlock) {
448
+ commentJson.assign(pageMeta, routeBlock.content);
449
+ }
450
+ return pageMeta;
451
+ }
452
+ function findMacro(stmts, filename) {
453
+ const nodes = stmts.map((raw) => {
454
+ let node = raw;
455
+ if (raw.type === "ExpressionStatement")
456
+ node = raw.expression;
457
+ return astKit.isCallOf(node, "definePage") ? node : void 0;
458
+ }).filter((node) => !!node);
459
+ if (!nodes.length)
460
+ return;
461
+ if (nodes.length > 1) {
462
+ throw new Error(`\u6BCF\u4E2A\u6587\u4EF6\u53EA\u5141\u8BB8\u8C03\u7528\u4E00\u6B21 definePage(): ${filename}`);
463
+ }
464
+ const macro = nodes[0];
465
+ const [opt] = macro.arguments;
466
+ if (opt && !t__namespace.isFunctionExpression(opt) && !t__namespace.isArrowFunctionExpression(opt) && !t__namespace.isObjectExpression(opt)) {
467
+ debug.definePage(`definePage() only accept argument in function or object: ${filename}`);
468
+ return;
469
+ }
470
+ return macro;
471
+ }
472
+ function findImports(stmts) {
473
+ return stmts.map((node) => node.type === "ImportDeclaration" ? node : void 0).filter((node) => !!node);
329
474
  }
330
475
 
331
476
  var __defProp = Object.defineProperty;
@@ -335,14 +480,15 @@ var __publicField = (obj, key, value) => {
335
480
  return value;
336
481
  };
337
482
  let lsatPagesJson = "";
338
- const { setCache, hasChanged } = useCachedPages();
339
483
  class PageContext {
340
484
  constructor(userOptions, viteRoot = process__default.cwd()) {
341
485
  __publicField(this, "_server");
342
486
  __publicField(this, "pagesGlobConfig");
343
487
  __publicField(this, "pagesConfigSourcePaths", []);
344
- __publicField(this, "pagesPath", []);
345
- __publicField(this, "subPagesPath", {});
488
+ __publicField(this, "pages", /* @__PURE__ */ new Map());
489
+ // abs path -> Page
490
+ __publicField(this, "subPages", /* @__PURE__ */ new Map());
491
+ // root -> abs path -> page
346
492
  __publicField(this, "pageMetaData", []);
347
493
  __publicField(this, "subPageMetaData", []);
348
494
  __publicField(this, "resolvedPagesJSONPath", "");
@@ -385,17 +531,30 @@ class PageContext {
385
531
  const pageDirFiles = this.options.dirs.map((dir) => {
386
532
  return { dir, files: getPagePaths(dir, this.options) };
387
533
  });
388
- this.pagesPath = pageDirFiles.map((page) => page.files).flat();
389
- debug.pages(this.pagesPath);
534
+ const paths = pageDirFiles.map((page) => page.files).flat();
535
+ debug.pages(paths);
536
+ const pages = /* @__PURE__ */ new Map();
537
+ for (const path2 of paths) {
538
+ const page = this.pages.get(path2.absolutePath) || new Page(this, path2);
539
+ pages.set(path2.absolutePath, page);
540
+ }
541
+ this.pages = pages;
390
542
  }
391
543
  async scanSubPages() {
392
- const subPagesPath = {};
544
+ const paths = {};
545
+ const subPages = /* @__PURE__ */ new Map();
393
546
  for (const dir of this.options.subPackages) {
394
547
  const pagePaths = getPagePaths(dir, this.options);
395
- subPagesPath[dir] = pagePaths;
548
+ paths[dir] = pagePaths;
549
+ const pages = /* @__PURE__ */ new Map();
550
+ for (const path2 of pagePaths) {
551
+ const page = this.subPages.get(dir)?.get(path2.absolutePath) || new Page(this, path2);
552
+ pages.set(path2.absolutePath, page);
553
+ }
554
+ subPages.set(dir, pages);
396
555
  }
397
- this.subPagesPath = subPagesPath;
398
- debug.subPages(this.subPagesPath);
556
+ debug.subPages(JSON.stringify(paths, null, 2));
557
+ this.subPages = subPages;
399
558
  }
400
559
  setupViteServer(server) {
401
560
  if (this._server === server)
@@ -456,20 +615,6 @@ class PageContext {
456
615
  type: "full-reload"
457
616
  });
458
617
  }
459
- async parsePage(page) {
460
- const { relativePath, absolutePath } = page;
461
- const routeSfcBlock = await getRouteSfcBlock(absolutePath);
462
- const routeBlock = await getRouteBlock(absolutePath, routeSfcBlock, this.options);
463
- setCache(absolutePath, routeSfcBlock);
464
- const relativePathWithFileName = relativePath.replace(path__default.extname(relativePath), "");
465
- const pageMetaDatum = {
466
- path: vite.normalizePath(relativePathWithFileName),
467
- type: routeBlock?.attr.type ?? "page"
468
- };
469
- if (routeBlock)
470
- commentJson.assign(pageMetaDatum, routeBlock.content);
471
- return pageMetaDatum;
472
- }
473
618
  /**
474
619
  * parse pages rules && set page type
475
620
  * @param pages page path array
@@ -478,7 +623,11 @@ class PageContext {
478
623
  * @returns pages rules
479
624
  */
480
625
  async parsePages(pages, type, overrides) {
481
- const generatedPageMetaData = await Promise.all(pages.map(async (page) => await this.parsePage(page)));
626
+ const jobs = [];
627
+ for (const [_, page] of pages) {
628
+ jobs.push(page.getPageMeta());
629
+ }
630
+ const generatedPageMetaData = await Promise.all(jobs);
482
631
  const customPageMetaData = overrides || [];
483
632
  const result = customPageMetaData.length ? mergePageMetaDataArray(generatedPageMetaData.concat(customPageMetaData)) : generatedPageMetaData;
484
633
  const parseMeta = result.filter(
@@ -510,14 +659,14 @@ class PageContext {
510
659
  return result;
511
660
  }
512
661
  async mergePageMetaData() {
513
- const pageMetaData = await this.parsePages(this.pagesPath, "main", this.pagesGlobConfig?.pages);
662
+ const pageMetaData = await this.parsePages(this.pages, "main", this.pagesGlobConfig?.pages);
514
663
  this.pageMetaData = pageMetaData;
515
664
  debug.pages(this.pageMetaData);
516
665
  }
517
666
  async mergeSubPageMetaData() {
518
667
  const subPageMaps = {};
519
668
  const subPackages = this.pagesGlobConfig?.subPackages || [];
520
- for (const [dir, pages] of Object.entries(this.subPagesPath)) {
669
+ for (const [dir, pages] of this.subPages) {
521
670
  const basePath = slash(path__default.join(this.options.root, this.options.outDir));
522
671
  const root = slash(path__default.relative(basePath, path__default.join(this.options.root, dir)));
523
672
  const globPackage = subPackages?.find((v) => v.root === root);
@@ -534,7 +683,18 @@ class PageContext {
534
683
  }
535
684
  async updatePagesJSON(filepath) {
536
685
  if (filepath) {
537
- if (!await hasChanged(filepath)) {
686
+ let page = this.pages.get(filepath);
687
+ if (!page) {
688
+ let subPage;
689
+ for (const [_, pages2] of this.subPages) {
690
+ subPage = pages2.get(filepath);
691
+ if (subPage) {
692
+ break;
693
+ }
694
+ }
695
+ page = subPage;
696
+ }
697
+ if (page && !await page.hasChanged()) {
538
698
  debug.cache(`The route block on page ${filepath} did not send any changes, skipping`);
539
699
  return false;
540
700
  }
@@ -662,16 +822,39 @@ function VitePluginUniPages(userOptions = {}) {
662
822
  },
663
823
  // Applet do not support custom route block, so we need to remove the route block here
664
824
  async transform(code, id) {
665
- if (!/\.n?vue$/.test(id) && !code.includes("</route>"))
825
+ if (!FILE_EXTENSIONS.find((ext) => id.endsWith(ext))) {
666
826
  return null;
827
+ }
828
+ const sfc = parseSFC(code, { filename: id });
829
+ let macro;
830
+ if (sfc.scriptSetup) {
831
+ const ast = astKit.babelParse(sfc.scriptSetup.content, sfc.scriptSetup.lang || "js");
832
+ macro = findMacro(ast.body, sfc.filename);
833
+ }
834
+ if (!macro && sfc.script) {
835
+ const ast = astKit.babelParse(sfc.script.content, sfc.script.lang || "js");
836
+ macro = findMacro(ast.body, sfc.filename);
837
+ }
838
+ const routeBlock = sfc.customBlocks.find((block) => block.type === "route");
839
+ if (!macro && !routeBlock)
840
+ return null;
841
+ if (macro && routeBlock)
842
+ throw new Error(`\u4E0D\u652F\u6301\u6DF7\u5408\u4F7F\u7528 definePage() \u548C <route/> ${id}`);
667
843
  const s = new MagicString__default(code);
668
- const routeBlockMatches = s.original.matchAll(
669
- /<route[^>]*>([\s\S]*?)<\/route>/g
670
- );
671
- for (const match of routeBlockMatches) {
672
- const index = match.index;
673
- const length = match[0].length;
674
- s.remove(index, index + length);
844
+ if (macro)
845
+ s.remove(macro.start, macro.end);
846
+ if (routeBlock) {
847
+ console.log(kolorist.lightYellow("\u8B66\u544A\uFF1A"), `${kolorist.bold("<route/>")} \u6807\u7B7E\u5DF2\u5E9F\u5F03\uFF0C\u5C06\u5728\u4E0B\u4E00\u4E2A\u7248\u672C\u4E2D\u79FB\u9664\uFF0C\u8BF7\u4F7F\u7528 definePage() \u4EE3\u66FF\uFF1B${kolorist.link("\u67E5\u770B\u8FC1\u79FB\u6307\u5357", "https://uni-helper.js.org/vite-plugin-uni-pages/definePage")}\u3002`);
848
+ console.log(kolorist.dim(id));
849
+ console.log();
850
+ const routeBlockMatches = s.original.matchAll(
851
+ /<route[^>]*>([\s\S]*?)<\/route>/g
852
+ );
853
+ for (const match of routeBlockMatches) {
854
+ const index = match.index;
855
+ const length = match[0].length;
856
+ s.remove(index, index + length);
857
+ }
675
858
  }
676
859
  if (s.hasChanged()) {
677
860
  return {
@@ -701,14 +884,19 @@ function VitePluginUniPages(userOptions = {}) {
701
884
  exports.FILE_EXTENSIONS = FILE_EXTENSIONS;
702
885
  exports.MODULE_ID_VIRTUAL = MODULE_ID_VIRTUAL;
703
886
  exports.OUTPUT_NAME = OUTPUT_NAME;
887
+ exports.Page = Page;
704
888
  exports.PageContext = PageContext;
705
889
  exports.RESOLVED_MODULE_ID_VIRTUAL = RESOLVED_MODULE_ID_VIRTUAL;
706
890
  exports.VitePluginUniPages = VitePluginUniPages;
891
+ exports.babelGenerate = babelGenerate;
707
892
  exports.checkPagesJsonFile = checkPagesJsonFile;
708
893
  exports.debug = debug;
709
894
  exports.default = VitePluginUniPages;
710
895
  exports.defineUniPages = defineUniPages;
896
+ exports.execScript = execScript;
711
897
  exports.extsToGlob = extsToGlob;
898
+ exports.findImports = findImports;
899
+ exports.findMacro = findMacro;
712
900
  exports.getPageFiles = getPageFiles;
713
901
  exports.getRouteBlock = getRouteBlock;
714
902
  exports.getRouteSfcBlock = getRouteSfcBlock;
@@ -720,5 +908,6 @@ exports.parseSFC = parseSFC;
720
908
  exports.readFileSync = readFileSync;
721
909
  exports.resolveOptions = resolveOptions;
722
910
  exports.resolvePageDirs = resolvePageDirs;
723
- exports.useCachedPages = useCachedPages;
911
+ exports.tryPageMetaFromCustomBlock = tryPageMetaFromCustomBlock;
912
+ exports.tryPageMetaFromMacro = tryPageMetaFromMacro;
724
913
  exports.writeFileSync = writeFileSync;