@uni-helper/vite-plugin-uni-pages 0.3.16 → 0.3.18

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
@@ -164,7 +164,7 @@ function mergePageMetaDataArray(pageMetaData) {
164
164
  }
165
165
  return result;
166
166
  }
167
- async function execScript(options) {
167
+ async function parseCode(options) {
168
168
  const { imports = [], code, filename } = options;
169
169
  let jsCode = "";
170
170
  try {
@@ -215,7 +215,24 @@ async function execScript(options) {
215
215
  __filename: filename,
216
216
  __dirname: dir,
217
217
  require: node_module.createRequire(dir),
218
- import: (id) => import(id)
218
+ import: (id) => import(id),
219
+ // 定时器相关
220
+ setTimeout,
221
+ clearTimeout,
222
+ setInterval,
223
+ clearInterval,
224
+ setImmediate,
225
+ clearImmediate,
226
+ // 控制台相关
227
+ console,
228
+ // URL 处理
229
+ URL,
230
+ URLSearchParams,
231
+ // 进程和性能相关
232
+ performance,
233
+ // 全局对象引用
234
+ global: globalThis,
235
+ globalThis
219
236
  };
220
237
  const script = new vm__default.Script(jsCode, { filename });
221
238
  await script.runInNewContext(vmContext, {
@@ -223,10 +240,7 @@ async function execScript(options) {
223
240
  // 设置超时避免长时间运行
224
241
  });
225
242
  const result = vmContext.exports.default || vmContext.exports;
226
- if (typeof result === "function") {
227
- return Promise.resolve(result());
228
- }
229
- return Promise.resolve(result);
243
+ return result;
230
244
  } catch (error) {
231
245
  throw new Error(`EXEC SCRIPT FAIL IN ${filename}: ${error.message}
232
246
 
@@ -235,6 +249,9 @@ ${jsCode}
235
249
  `);
236
250
  }
237
251
  }
252
+ function sleep(ms) {
253
+ return new Promise((resolve) => setTimeout(resolve, ms));
254
+ }
238
255
  function getDefaultExport(expr) {
239
256
  return expr.default === void 0 ? expr : expr.default;
240
257
  }
@@ -250,33 +267,73 @@ function getPageFiles(path, options) {
250
267
  });
251
268
  return files;
252
269
  }
253
- async function checkPagesJsonFile(path) {
270
+ function checkPagesJsonFileSync(path) {
254
271
  const createEmptyFile = (path2) => {
255
- return fs__default.promises.writeFile(path2, JSON.stringify({ pages: [{ path: "" }] }, null, 2), { encoding: "utf-8" }).then(() => true).catch(() => false);
272
+ try {
273
+ fs__default.writeFileSync(
274
+ path2,
275
+ JSON.stringify({ pages: [{ path: "" }] }, null, 2),
276
+ { encoding: "utf-8" }
277
+ );
278
+ return true;
279
+ } catch {
280
+ return false;
281
+ }
256
282
  };
257
- const unlink = (path2) => {
258
- return fs__default.promises.unlink(path2).then(() => true).catch(() => false);
283
+ const unlinkFile = (path2) => {
284
+ try {
285
+ fs__default.unlinkSync(path2);
286
+ return true;
287
+ } catch {
288
+ return false;
289
+ }
259
290
  };
260
291
  try {
261
- const stat = await fs__default.promises.stat(path);
292
+ try {
293
+ fs__default.accessSync(path, fs__default.constants.F_OK);
294
+ } catch {
295
+ return createEmptyFile(path);
296
+ }
297
+ const stat = fs__default.statSync(path);
262
298
  if (!stat.isFile()) {
263
- if (!await unlink(path)) {
299
+ if (!unlinkFile(path)) {
264
300
  return false;
265
301
  }
266
302
  return createEmptyFile(path);
267
303
  }
268
- const access = await fs__default.promises.access(path, fs__default.constants.W_OK | fs__default.constants.R_OK).then(() => true).catch(() => false);
269
- if (!access) {
270
- if (!await unlink(path)) {
304
+ try {
305
+ fs__default.accessSync(path, fs__default.constants.R_OK | fs__default.constants.W_OK);
306
+ return true;
307
+ } catch {
308
+ if (!unlinkFile(path)) {
271
309
  return false;
272
310
  }
273
311
  return createEmptyFile(path);
274
312
  }
275
- return true;
276
313
  } catch {
277
314
  return createEmptyFile(path);
278
315
  }
279
316
  }
317
+ async function writeFileWithLock(path, content, retry = 3) {
318
+ if (retry <= 0) {
319
+ debug.error(`${path} \u83B7\u53D6\u6587\u4EF6\u9501\u5931\u8D25\uFF0C\u5199\u5165\u5931\u8D25`);
320
+ return;
321
+ }
322
+ let relase;
323
+ try {
324
+ try {
325
+ relase = await lockfile__default.lock(path, { realpath: false });
326
+ } catch {
327
+ await sleep(500);
328
+ return writeFileWithLock(path, content, retry - 1);
329
+ }
330
+ await fs__default.promises.writeFile(path, content, { encoding: "utf-8" });
331
+ } finally {
332
+ if (relase) {
333
+ await relase();
334
+ }
335
+ }
336
+ }
280
337
 
281
338
  function resolveOptions(userOptions, viteRoot = process__default.cwd()) {
282
339
  const {
@@ -430,7 +487,7 @@ class Page {
430
487
  if (forceUpdate || !this.meta) {
431
488
  await this.read();
432
489
  }
433
- const { path, tabBar: _, ...others } = this.meta;
490
+ const { path, tabBar: _, ...others } = this.meta || {};
434
491
  return {
435
492
  path: path ?? this.uri,
436
493
  ...others
@@ -507,14 +564,15 @@ async function tryPageMetaFromMacro(sfc) {
507
564
  const imports = findImports(ast.body).filter((imp) => !!imp.specifiers.length).map((imp) => babelGenerate(imp).code);
508
565
  const [macroOption] = macro.arguments;
509
566
  const code = babelGenerate(macroOption).code;
510
- const result = await execScript({
567
+ const parsed = await parseCode({
511
568
  imports,
512
569
  code,
513
570
  filename: sfc.filename
514
571
  });
572
+ const res = typeof parsed === "function" ? await Promise.resolve(parsed()) : await Promise.resolve(parsed);
515
573
  return {
516
574
  type: "page",
517
- ...result
575
+ ...res
518
576
  };
519
577
  }
520
578
  return void 0;
@@ -569,7 +627,6 @@ var __publicField = (obj, key, value) => {
569
627
  __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
570
628
  return value;
571
629
  };
572
- let lsatPagesJson = "";
573
630
  class PageContext {
574
631
  constructor(userOptions, viteRoot = process__default.cwd()) {
575
632
  __publicField(this, "_server");
@@ -593,6 +650,7 @@ class PageContext {
593
650
  __publicField(this, "options");
594
651
  __publicField(this, "logger");
595
652
  __publicField(this, "withUniPlatform", false);
653
+ __publicField(this, "lastPagesJson", "");
596
654
  this.rawOptions = userOptions;
597
655
  this.root = slash(viteRoot);
598
656
  debug.options("root", this.root);
@@ -819,7 +877,7 @@ class PageContext {
819
877
  }
820
878
  }
821
879
  }
822
- await checkPagesJsonFile(this.resolvedPagesJSONPath);
880
+ checkPagesJsonFileSync(this.resolvedPagesJSONPath);
823
881
  this.options.onBeforeLoadUserConfig(this);
824
882
  await this.loadUserPagesConfig();
825
883
  this.options.onAfterLoadUserConfig(this);
@@ -841,29 +899,19 @@ class PageContext {
841
899
  pages.forEach((v) => pagesMap.set(v.path, v));
842
900
  this.pageMetaData = [...pagesMap.values()];
843
901
  this.options.onBeforeWriteFile(this);
844
- const data = {
845
- ...this.pagesGlobConfig,
846
- pages: this.pageMetaData,
847
- subPackages: this.subPageMetaData,
848
- tabBar: await this.getTabBarMerged()
849
- };
902
+ const data = await this.genratePagesJSON();
850
903
  const pagesJson = commentJson.stringify(
851
904
  data,
852
905
  null,
853
906
  this.options.minify ? void 0 : await this.getIndent()
854
907
  ) + (await this.getEndOfLine() ? await this.getNewline() : "");
855
908
  this.generateDeclaration();
856
- if (lsatPagesJson === pagesJson) {
909
+ if (this.lastPagesJson === pagesJson) {
857
910
  debug.pages("PagesJson Not have change");
858
911
  return false;
859
912
  }
860
- const relase = await lockfile__default.lock(this.resolvedPagesJSONPath, { realpath: false });
861
- try {
862
- await fs__default.promises.writeFile(this.resolvedPagesJSONPath, pagesJson, { encoding: "utf-8" });
863
- } finally {
864
- await relase();
865
- }
866
- lsatPagesJson = pagesJson;
913
+ await writeFileWithLock(this.resolvedPagesJSONPath, pagesJson);
914
+ this.lastPagesJson = pagesJson;
867
915
  this.options.onAfterWriteFile(this);
868
916
  return true;
869
917
  }
@@ -884,6 +932,64 @@ class PageContext {
884
932
  debug.declaration("generating");
885
933
  return writeDeclaration(this, this.options.dts);
886
934
  }
935
+ async writePagesJSONFile(pagesJson, retry = 3) {
936
+ if (retry <= 0) {
937
+ debug.error(`${this.resolvedPagesJSONPath} \u83B7\u53D6\u6587\u4EF6\u9501\u5931\u8D25\uFF0C\u5199\u5165\u5931\u8D25`);
938
+ return;
939
+ }
940
+ let relase;
941
+ try {
942
+ try {
943
+ relase = await lockfile__default.lock(this.resolvedPagesJSONPath, { realpath: false });
944
+ } catch {
945
+ return this.writePagesJSONFile(pagesJson, retry - 1);
946
+ }
947
+ await fs__default.promises.writeFile(this.resolvedPagesJSONPath, pagesJson, { encoding: "utf-8" });
948
+ } finally {
949
+ if (relase) {
950
+ await relase();
951
+ }
952
+ }
953
+ }
954
+ async genratePagesJSON() {
955
+ const content = await fs__default.promises.readFile(this.resolvedPagesJSONPath, { encoding: "utf-8" }).catch(() => "");
956
+ let pageJson = commentJson.parse(content || "{}");
957
+ const { pages: _, subPackages: __, tabBar: ___, ...others } = this.pagesGlobConfig || {};
958
+ pageJson = Object.assign(pageJson, {
959
+ ...others
960
+ });
961
+ const currentPlatform = uniEnv.platform.toUpperCase();
962
+ pageJson.pages = mergePlatformItems(pageJson?.pages, currentPlatform, this.pageMetaData, "path");
963
+ pageJson.subPackages = pageJson?.subPackages || new commentJson.CommentArray();
964
+ const newSubPackages = /* @__PURE__ */ new Map();
965
+ for (const item of this.subPageMetaData) {
966
+ newSubPackages.set(item.root, item);
967
+ }
968
+ for (const existing of pageJson.subPackages) {
969
+ const sub = newSubPackages.get(existing.root);
970
+ if (sub) {
971
+ existing.pages = mergePlatformItems(existing.pages, currentPlatform, sub.pages, "path");
972
+ newSubPackages.delete(existing.root);
973
+ }
974
+ }
975
+ for (const [_2, newSub] of newSubPackages) {
976
+ pageJson.subPackages.push({
977
+ root: newSub.root,
978
+ pages: mergePlatformItems(void 0, currentPlatform, newSub.pages, "path")
979
+ });
980
+ }
981
+ const tabBar = await this.getTabBarMerged();
982
+ if (tabBar) {
983
+ const list = mergePlatformItems(pageJson?.tabBar?.list, currentPlatform, tabBar.list, "pagePath");
984
+ if (pageJson?.tabBar?.list) {
985
+ pageJson.tabBar.list = list;
986
+ } else {
987
+ pageJson.tabBar = pageJson.tabBar || {};
988
+ pageJson.tabBar.list = list;
989
+ }
990
+ }
991
+ return pageJson;
992
+ }
887
993
  async readInfoFromPagesJSON() {
888
994
  const resolvedPagesJSONContent = await fs__default.promises.readFile(this.resolvedPagesJSONPath, { encoding: "utf-8" }).catch(() => "");
889
995
  this.resolvedPagesJSONIndent = detectIndent__default(resolvedPagesJSONContent).indent || " ";
@@ -920,19 +1026,125 @@ function getPagePaths(dir, options) {
920
1026
  }));
921
1027
  return pagePaths;
922
1028
  }
1029
+ function mergePlatformItems(source, currentPlatform, items, uniqueKeyName) {
1030
+ const src = source || new commentJson.CommentArray();
1031
+ currentPlatform = currentPlatform.toUpperCase();
1032
+ let lastPlatforms = [];
1033
+ for (const comment of src[Symbol.for("before:0")] || []) {
1034
+ const trimed = comment.value.trim();
1035
+ if (trimed.startsWith("GENERATED BY UNI-PAGES, PLATFORM:")) {
1036
+ lastPlatforms = trimed.split(":")[1].split("||").map((s) => s.trim()).filter((s) => s !== currentPlatform).sort();
1037
+ }
1038
+ }
1039
+ const tmpMap = /* @__PURE__ */ new Map();
1040
+ for (let i = 0; i < src.length; i++) {
1041
+ const item = src[i];
1042
+ const uniqueKey = item[uniqueKeyName];
1043
+ if (!uniqueKey) {
1044
+ continue;
1045
+ }
1046
+ const beforeComments = src[Symbol.for(`before:${i}`)];
1047
+ const ifdefComment = beforeComments?.find((c) => c.value.trim().startsWith("#ifdef"));
1048
+ let platforms = [...lastPlatforms];
1049
+ if (ifdefComment) {
1050
+ const match = ifdefComment.value.match(/#ifdef\s+(.+)/);
1051
+ if (match) {
1052
+ platforms = match[1].split("||").map((p) => p.trim()).filter((s) => s !== currentPlatform).sort();
1053
+ }
1054
+ }
1055
+ if (platforms.length === 0) {
1056
+ continue;
1057
+ }
1058
+ const existing = tmpMap.get(uniqueKey) || [];
1059
+ existing.push({ item, platforms, platformStr: platforms.join(" || ") });
1060
+ tmpMap.set(uniqueKey, existing);
1061
+ }
1062
+ for (const item of items) {
1063
+ const newItem = item;
1064
+ const uniqueKey = item[uniqueKeyName];
1065
+ if (!uniqueKey) {
1066
+ continue;
1067
+ }
1068
+ if (!tmpMap.has(uniqueKey)) {
1069
+ tmpMap.set(uniqueKey, [{
1070
+ item: newItem,
1071
+ platforms: [currentPlatform],
1072
+ platformStr: currentPlatform
1073
+ }]);
1074
+ continue;
1075
+ }
1076
+ const existing = tmpMap.get(uniqueKey);
1077
+ const newItemStr = JSON.stringify(newItem);
1078
+ const equalObj = existing.find((val) => JSON.stringify(val.item) === newItemStr);
1079
+ if (equalObj) {
1080
+ equalObj.platforms.push(currentPlatform);
1081
+ equalObj.platformStr = equalObj.platforms.join(" || ");
1082
+ } else {
1083
+ existing.push({
1084
+ item: newItem,
1085
+ platforms: [currentPlatform],
1086
+ platformStr: currentPlatform
1087
+ });
1088
+ }
1089
+ }
1090
+ const result = new commentJson.CommentArray();
1091
+ const platformUsage = {};
1092
+ tmpMap.forEach((val) => {
1093
+ Object.values(val).forEach((v) => {
1094
+ platformUsage[v.platformStr] = (platformUsage[v.platformStr] || 0) + 1;
1095
+ });
1096
+ });
1097
+ const usageKeys = Object.keys(platformUsage);
1098
+ const defaultPlatformStr = usageKeys.length ? usageKeys.reduce((a, b) => platformUsage[a] > platformUsage[b] ? a : b) : currentPlatform;
1099
+ result[Symbol.for("before:0")] = [{
1100
+ type: "LineComment",
1101
+ value: ` GENERATED BY UNI-PAGES, PLATFORM: ${defaultPlatformStr}`,
1102
+ inline: false,
1103
+ loc: {
1104
+ start: { line: 0, column: 0 },
1105
+ end: { line: 0, column: 0 }
1106
+ }
1107
+ }];
1108
+ for (const [_, list] of tmpMap) {
1109
+ for (const { item, platformStr } of list) {
1110
+ result.push(item);
1111
+ if (platformStr !== defaultPlatformStr) {
1112
+ result[Symbol.for(`before:${result.length - 1}`)] = [{
1113
+ type: "LineComment",
1114
+ value: ` #ifdef ${platformStr}`,
1115
+ inline: false,
1116
+ loc: {
1117
+ start: { line: 0, column: 0 },
1118
+ end: { line: 0, column: 0 }
1119
+ }
1120
+ }];
1121
+ result[Symbol.for(`after:${result.length - 1}`)] = [{
1122
+ type: "LineComment",
1123
+ value: " #endif",
1124
+ inline: false,
1125
+ loc: {
1126
+ start: { line: 0, column: 0 },
1127
+ end: { line: 0, column: 0 }
1128
+ }
1129
+ }];
1130
+ }
1131
+ }
1132
+ }
1133
+ return result;
1134
+ }
923
1135
 
924
1136
  function defineUniPages(config) {
925
1137
  return config;
926
1138
  }
927
1139
 
928
- async function VitePluginUniPages(userOptions = {}) {
1140
+ function VitePluginUniPages(userOptions = {}) {
929
1141
  let ctx;
930
1142
  const resolvedPagesJSONPath = path__default.join(
931
1143
  process__default.env.VITE_ROOT_DIR || process__default.cwd(),
932
1144
  userOptions.outDir ?? "src",
933
1145
  OUTPUT_NAME
934
1146
  );
935
- await checkPagesJsonFile(resolvedPagesJSONPath);
1147
+ checkPagesJsonFileSync(resolvedPagesJSONPath);
936
1148
  return {
937
1149
  name: "vite-plugin-uni-pages",
938
1150
  enforce: "pre",
@@ -1019,11 +1231,10 @@ exports.PageContext = PageContext;
1019
1231
  exports.RESOLVED_MODULE_ID_VIRTUAL = RESOLVED_MODULE_ID_VIRTUAL;
1020
1232
  exports.VitePluginUniPages = VitePluginUniPages;
1021
1233
  exports.babelGenerate = babelGenerate;
1022
- exports.checkPagesJsonFile = checkPagesJsonFile;
1234
+ exports.checkPagesJsonFileSync = checkPagesJsonFileSync;
1023
1235
  exports.debug = debug;
1024
1236
  exports.default = VitePluginUniPages;
1025
1237
  exports.defineUniPages = defineUniPages;
1026
- exports.execScript = execScript;
1027
1238
  exports.extsToGlob = extsToGlob;
1028
1239
  exports.findImports = findImports;
1029
1240
  exports.findMacro = findMacro;
@@ -1033,9 +1244,12 @@ exports.getRouteSfcBlock = getRouteSfcBlock;
1033
1244
  exports.invalidatePagesModule = invalidatePagesModule;
1034
1245
  exports.isTargetFile = isTargetFile;
1035
1246
  exports.mergePageMetaDataArray = mergePageMetaDataArray;
1247
+ exports.parseCode = parseCode;
1036
1248
  exports.parseCustomBlock = parseCustomBlock;
1037
1249
  exports.parseSFC = parseSFC;
1038
1250
  exports.resolveOptions = resolveOptions;
1039
1251
  exports.resolvePageDirs = resolvePageDirs;
1252
+ exports.sleep = sleep;
1040
1253
  exports.tryPageMetaFromCustomBlock = tryPageMetaFromCustomBlock;
1041
1254
  exports.tryPageMetaFromMacro = tryPageMetaFromMacro;
1255
+ exports.writeFileWithLock = writeFileWithLock;
package/dist/index.d.cts CHANGED
@@ -2964,6 +2964,7 @@ declare class PageContext {
2964
2964
  options: ResolvedOptions;
2965
2965
  logger?: Logger;
2966
2966
  withUniPlatform: boolean;
2967
+ private lastPagesJson;
2967
2968
  constructor(userOptions: UserOptions, viteRoot?: string);
2968
2969
  setLogger(logger: Logger): void;
2969
2970
  loadUserPagesConfig(): Promise<void>;
@@ -2994,6 +2995,8 @@ declare class PageContext {
2994
2995
  resolveRoutes(): string;
2995
2996
  resolveSubRoutes(): string;
2996
2997
  generateDeclaration(): Promise<void> | undefined;
2998
+ private writePagesJSONFile;
2999
+ private genratePagesJSON;
2997
3000
  private readInfoFromPagesJSON;
2998
3001
  private getIndent;
2999
3002
  private getNewline;
@@ -3021,7 +3024,7 @@ declare function isTargetFile(path: string): boolean;
3021
3024
  */
3022
3025
  declare function mergePageMetaDataArray(pageMetaData: PageMetaDatum[]): PageMetaDatum[];
3023
3026
  /**
3024
- * 执行一段 TypeScript / JavaScript 脚本代码,并返回执行结果
3027
+ * 将 TypeScript / JavaScript 脚本代码,转换为对象/函数
3025
3028
  *
3026
3029
  * @param options - 执行脚本所需的配置项
3027
3030
  * @param options.imports - 需要引入的模块导入语句列表
@@ -3029,11 +3032,12 @@ declare function mergePageMetaDataArray(pageMetaData: PageMetaDatum[]): PageMeta
3029
3032
  * @param options.filename - 脚本文件名,用于错误定位和上下文环境
3030
3033
  * @returns 返回脚本执行后的结果,若导出的是函数则执行后返回其返回值
3031
3034
  */
3032
- declare function execScript(options: {
3035
+ declare function parseCode(options: {
3033
3036
  imports: string[];
3034
3037
  code: string;
3035
3038
  filename: string;
3036
3039
  }): Promise<any>;
3040
+ declare function sleep(ms: number): Promise<unknown>;
3037
3041
  declare const babelGenerate: typeof babelGenerator;
3038
3042
 
3039
3043
  interface CustomBlock {
@@ -3195,11 +3199,12 @@ declare function getRouteBlock(path: string, blockStr: SFCBlock | undefined, rou
3195
3199
  */
3196
3200
  declare function getPageFiles(path: string, options: ResolvedOptions): string[];
3197
3201
  /**
3198
- * 检查指定路径的pages.json文件,如果文件不存在或不是有效文件则创建一个空的pages.json文件
3202
+ * 检查指定路径的 pages.json 文件,如果文件不存在或不是有效文件则创建一个空的 pages.json 文件
3199
3203
  * @param path - 要检查的文件路径
3200
- * @returns Promise<void> - 无返回值的异步函数
3204
+ * @returns boolean - 返回操作是否成功
3201
3205
  */
3202
- declare function checkPagesJsonFile(path: fs.PathLike): Promise<boolean>;
3206
+ declare function checkPagesJsonFileSync(path: fs.PathLike): boolean;
3207
+ declare function writeFileWithLock(path: string, content: string, retry?: number): Promise<void>;
3203
3208
 
3204
3209
  declare function resolveOptions(userOptions: UserOptions, viteRoot?: string): ResolvedOptions;
3205
3210
  /**
@@ -3207,7 +3212,7 @@ declare function resolveOptions(userOptions: UserOptions, viteRoot?: string): Re
3207
3212
  */
3208
3213
  declare function resolvePageDirs(dir: string, root: string, exclude: string[]): string[];
3209
3214
 
3210
- declare function VitePluginUniPages(userOptions?: UserOptions): Promise<Plugin>;
3215
+ declare function VitePluginUniPages(userOptions?: UserOptions): Plugin;
3211
3216
 
3212
- export { FILE_EXTENSIONS, MODULE_ID_VIRTUAL, OUTPUT_NAME, Page, PageContext, RESOLVED_MODULE_ID_VIRTUAL, VitePluginUniPages, babelGenerate, checkPagesJsonFile, debug, VitePluginUniPages as default, definePage, defineUniPages, execScript, extsToGlob, findImports, findMacro, getPageFiles, getRouteBlock, getRouteSfcBlock, invalidatePagesModule, isTargetFile, mergePageMetaDataArray, parseCustomBlock, parseSFC, resolveOptions, resolvePageDirs, tryPageMetaFromCustomBlock, tryPageMetaFromMacro };
3217
+ export { FILE_EXTENSIONS, MODULE_ID_VIRTUAL, OUTPUT_NAME, Page, PageContext, RESOLVED_MODULE_ID_VIRTUAL, VitePluginUniPages, babelGenerate, checkPagesJsonFileSync, debug, VitePluginUniPages as default, definePage, defineUniPages, extsToGlob, findImports, findMacro, getPageFiles, getRouteBlock, getRouteSfcBlock, invalidatePagesModule, isTargetFile, mergePageMetaDataArray, parseCode, parseCustomBlock, parseSFC, resolveOptions, resolvePageDirs, sleep, tryPageMetaFromCustomBlock, tryPageMetaFromMacro, writeFileWithLock };
3213
3218
  export type { Condition, ConditionItem, ConfigSource, CustomBlock, DefinePage, EasyCom, GlobalStyle, MaybeCallable, MaybePromise, MaybePromiseCallable, Options, PageMetaDatum, PagePath, PagesConfig, ResolvedOptions, RouteBlockLang, SubPackage, SubPackages, SubPageMetaDatum, TabBar, TabBarIconFont, TabBarItem, TabBarMidButton, TheWindow, UniIdRouter, UserOptions, UserPageMeta, UserPagesConfig, UserTabBarItem, debugType };
package/dist/index.d.mts CHANGED
@@ -2964,6 +2964,7 @@ declare class PageContext {
2964
2964
  options: ResolvedOptions;
2965
2965
  logger?: Logger;
2966
2966
  withUniPlatform: boolean;
2967
+ private lastPagesJson;
2967
2968
  constructor(userOptions: UserOptions, viteRoot?: string);
2968
2969
  setLogger(logger: Logger): void;
2969
2970
  loadUserPagesConfig(): Promise<void>;
@@ -2994,6 +2995,8 @@ declare class PageContext {
2994
2995
  resolveRoutes(): string;
2995
2996
  resolveSubRoutes(): string;
2996
2997
  generateDeclaration(): Promise<void> | undefined;
2998
+ private writePagesJSONFile;
2999
+ private genratePagesJSON;
2997
3000
  private readInfoFromPagesJSON;
2998
3001
  private getIndent;
2999
3002
  private getNewline;
@@ -3021,7 +3024,7 @@ declare function isTargetFile(path: string): boolean;
3021
3024
  */
3022
3025
  declare function mergePageMetaDataArray(pageMetaData: PageMetaDatum[]): PageMetaDatum[];
3023
3026
  /**
3024
- * 执行一段 TypeScript / JavaScript 脚本代码,并返回执行结果
3027
+ * 将 TypeScript / JavaScript 脚本代码,转换为对象/函数
3025
3028
  *
3026
3029
  * @param options - 执行脚本所需的配置项
3027
3030
  * @param options.imports - 需要引入的模块导入语句列表
@@ -3029,11 +3032,12 @@ declare function mergePageMetaDataArray(pageMetaData: PageMetaDatum[]): PageMeta
3029
3032
  * @param options.filename - 脚本文件名,用于错误定位和上下文环境
3030
3033
  * @returns 返回脚本执行后的结果,若导出的是函数则执行后返回其返回值
3031
3034
  */
3032
- declare function execScript(options: {
3035
+ declare function parseCode(options: {
3033
3036
  imports: string[];
3034
3037
  code: string;
3035
3038
  filename: string;
3036
3039
  }): Promise<any>;
3040
+ declare function sleep(ms: number): Promise<unknown>;
3037
3041
  declare const babelGenerate: typeof babelGenerator;
3038
3042
 
3039
3043
  interface CustomBlock {
@@ -3195,11 +3199,12 @@ declare function getRouteBlock(path: string, blockStr: SFCBlock | undefined, rou
3195
3199
  */
3196
3200
  declare function getPageFiles(path: string, options: ResolvedOptions): string[];
3197
3201
  /**
3198
- * 检查指定路径的pages.json文件,如果文件不存在或不是有效文件则创建一个空的pages.json文件
3202
+ * 检查指定路径的 pages.json 文件,如果文件不存在或不是有效文件则创建一个空的 pages.json 文件
3199
3203
  * @param path - 要检查的文件路径
3200
- * @returns Promise<void> - 无返回值的异步函数
3204
+ * @returns boolean - 返回操作是否成功
3201
3205
  */
3202
- declare function checkPagesJsonFile(path: fs.PathLike): Promise<boolean>;
3206
+ declare function checkPagesJsonFileSync(path: fs.PathLike): boolean;
3207
+ declare function writeFileWithLock(path: string, content: string, retry?: number): Promise<void>;
3203
3208
 
3204
3209
  declare function resolveOptions(userOptions: UserOptions, viteRoot?: string): ResolvedOptions;
3205
3210
  /**
@@ -3207,7 +3212,7 @@ declare function resolveOptions(userOptions: UserOptions, viteRoot?: string): Re
3207
3212
  */
3208
3213
  declare function resolvePageDirs(dir: string, root: string, exclude: string[]): string[];
3209
3214
 
3210
- declare function VitePluginUniPages(userOptions?: UserOptions): Promise<Plugin>;
3215
+ declare function VitePluginUniPages(userOptions?: UserOptions): Plugin;
3211
3216
 
3212
- export { FILE_EXTENSIONS, MODULE_ID_VIRTUAL, OUTPUT_NAME, Page, PageContext, RESOLVED_MODULE_ID_VIRTUAL, VitePluginUniPages, babelGenerate, checkPagesJsonFile, debug, VitePluginUniPages as default, definePage, defineUniPages, execScript, extsToGlob, findImports, findMacro, getPageFiles, getRouteBlock, getRouteSfcBlock, invalidatePagesModule, isTargetFile, mergePageMetaDataArray, parseCustomBlock, parseSFC, resolveOptions, resolvePageDirs, tryPageMetaFromCustomBlock, tryPageMetaFromMacro };
3217
+ export { FILE_EXTENSIONS, MODULE_ID_VIRTUAL, OUTPUT_NAME, Page, PageContext, RESOLVED_MODULE_ID_VIRTUAL, VitePluginUniPages, babelGenerate, checkPagesJsonFileSync, debug, VitePluginUniPages as default, definePage, defineUniPages, extsToGlob, findImports, findMacro, getPageFiles, getRouteBlock, getRouteSfcBlock, invalidatePagesModule, isTargetFile, mergePageMetaDataArray, parseCode, parseCustomBlock, parseSFC, resolveOptions, resolvePageDirs, sleep, tryPageMetaFromCustomBlock, tryPageMetaFromMacro, writeFileWithLock };
3213
3218
  export type { Condition, ConditionItem, ConfigSource, CustomBlock, DefinePage, EasyCom, GlobalStyle, MaybeCallable, MaybePromise, MaybePromiseCallable, Options, PageMetaDatum, PagePath, PagesConfig, ResolvedOptions, RouteBlockLang, SubPackage, SubPackages, SubPageMetaDatum, TabBar, TabBarIconFont, TabBarItem, TabBarMidButton, TheWindow, UniIdRouter, UserOptions, UserPageMeta, UserPagesConfig, UserTabBarItem, debugType };
package/dist/index.d.ts CHANGED
@@ -2964,6 +2964,7 @@ declare class PageContext {
2964
2964
  options: ResolvedOptions;
2965
2965
  logger?: Logger;
2966
2966
  withUniPlatform: boolean;
2967
+ private lastPagesJson;
2967
2968
  constructor(userOptions: UserOptions, viteRoot?: string);
2968
2969
  setLogger(logger: Logger): void;
2969
2970
  loadUserPagesConfig(): Promise<void>;
@@ -2994,6 +2995,8 @@ declare class PageContext {
2994
2995
  resolveRoutes(): string;
2995
2996
  resolveSubRoutes(): string;
2996
2997
  generateDeclaration(): Promise<void> | undefined;
2998
+ private writePagesJSONFile;
2999
+ private genratePagesJSON;
2997
3000
  private readInfoFromPagesJSON;
2998
3001
  private getIndent;
2999
3002
  private getNewline;
@@ -3021,7 +3024,7 @@ declare function isTargetFile(path: string): boolean;
3021
3024
  */
3022
3025
  declare function mergePageMetaDataArray(pageMetaData: PageMetaDatum[]): PageMetaDatum[];
3023
3026
  /**
3024
- * 执行一段 TypeScript / JavaScript 脚本代码,并返回执行结果
3027
+ * 将 TypeScript / JavaScript 脚本代码,转换为对象/函数
3025
3028
  *
3026
3029
  * @param options - 执行脚本所需的配置项
3027
3030
  * @param options.imports - 需要引入的模块导入语句列表
@@ -3029,11 +3032,12 @@ declare function mergePageMetaDataArray(pageMetaData: PageMetaDatum[]): PageMeta
3029
3032
  * @param options.filename - 脚本文件名,用于错误定位和上下文环境
3030
3033
  * @returns 返回脚本执行后的结果,若导出的是函数则执行后返回其返回值
3031
3034
  */
3032
- declare function execScript(options: {
3035
+ declare function parseCode(options: {
3033
3036
  imports: string[];
3034
3037
  code: string;
3035
3038
  filename: string;
3036
3039
  }): Promise<any>;
3040
+ declare function sleep(ms: number): Promise<unknown>;
3037
3041
  declare const babelGenerate: typeof babelGenerator;
3038
3042
 
3039
3043
  interface CustomBlock {
@@ -3195,11 +3199,12 @@ declare function getRouteBlock(path: string, blockStr: SFCBlock | undefined, rou
3195
3199
  */
3196
3200
  declare function getPageFiles(path: string, options: ResolvedOptions): string[];
3197
3201
  /**
3198
- * 检查指定路径的pages.json文件,如果文件不存在或不是有效文件则创建一个空的pages.json文件
3202
+ * 检查指定路径的 pages.json 文件,如果文件不存在或不是有效文件则创建一个空的 pages.json 文件
3199
3203
  * @param path - 要检查的文件路径
3200
- * @returns Promise<void> - 无返回值的异步函数
3204
+ * @returns boolean - 返回操作是否成功
3201
3205
  */
3202
- declare function checkPagesJsonFile(path: fs.PathLike): Promise<boolean>;
3206
+ declare function checkPagesJsonFileSync(path: fs.PathLike): boolean;
3207
+ declare function writeFileWithLock(path: string, content: string, retry?: number): Promise<void>;
3203
3208
 
3204
3209
  declare function resolveOptions(userOptions: UserOptions, viteRoot?: string): ResolvedOptions;
3205
3210
  /**
@@ -3207,7 +3212,7 @@ declare function resolveOptions(userOptions: UserOptions, viteRoot?: string): Re
3207
3212
  */
3208
3213
  declare function resolvePageDirs(dir: string, root: string, exclude: string[]): string[];
3209
3214
 
3210
- declare function VitePluginUniPages(userOptions?: UserOptions): Promise<Plugin>;
3215
+ declare function VitePluginUniPages(userOptions?: UserOptions): Plugin;
3211
3216
 
3212
- export { FILE_EXTENSIONS, MODULE_ID_VIRTUAL, OUTPUT_NAME, Page, PageContext, RESOLVED_MODULE_ID_VIRTUAL, VitePluginUniPages, babelGenerate, checkPagesJsonFile, debug, VitePluginUniPages as default, definePage, defineUniPages, execScript, extsToGlob, findImports, findMacro, getPageFiles, getRouteBlock, getRouteSfcBlock, invalidatePagesModule, isTargetFile, mergePageMetaDataArray, parseCustomBlock, parseSFC, resolveOptions, resolvePageDirs, tryPageMetaFromCustomBlock, tryPageMetaFromMacro };
3217
+ export { FILE_EXTENSIONS, MODULE_ID_VIRTUAL, OUTPUT_NAME, Page, PageContext, RESOLVED_MODULE_ID_VIRTUAL, VitePluginUniPages, babelGenerate, checkPagesJsonFileSync, debug, VitePluginUniPages as default, definePage, defineUniPages, extsToGlob, findImports, findMacro, getPageFiles, getRouteBlock, getRouteSfcBlock, invalidatePagesModule, isTargetFile, mergePageMetaDataArray, parseCode, parseCustomBlock, parseSFC, resolveOptions, resolvePageDirs, sleep, tryPageMetaFromCustomBlock, tryPageMetaFromMacro, writeFileWithLock };
3213
3218
  export type { Condition, ConditionItem, ConfigSource, CustomBlock, DefinePage, EasyCom, GlobalStyle, MaybeCallable, MaybePromise, MaybePromiseCallable, Options, PageMetaDatum, PagePath, PagesConfig, ResolvedOptions, RouteBlockLang, SubPackage, SubPackages, SubPageMetaDatum, TabBar, TabBarIconFont, TabBarItem, TabBarMidButton, TheWindow, UniIdRouter, UserOptions, UserPageMeta, UserPagesConfig, UserTabBarItem, debugType };
package/dist/index.mjs CHANGED
@@ -7,7 +7,7 @@ import MagicString from 'magic-string';
7
7
  import { normalizePath, createLogger } from 'vite';
8
8
  import fs, { existsSync } from 'node:fs';
9
9
  import { platform } from '@uni-helper/uni-env';
10
- import { parse, assign, stringify } from 'comment-json';
10
+ import { parse, assign, stringify, CommentArray } from 'comment-json';
11
11
  import Debug from 'debug';
12
12
  import detectIndent from 'detect-indent';
13
13
  import detectNewline from 'detect-newline';
@@ -129,7 +129,7 @@ function mergePageMetaDataArray(pageMetaData) {
129
129
  }
130
130
  return result;
131
131
  }
132
- async function execScript(options) {
132
+ async function parseCode(options) {
133
133
  const { imports = [], code, filename } = options;
134
134
  let jsCode = "";
135
135
  try {
@@ -180,7 +180,24 @@ async function execScript(options) {
180
180
  __filename: filename,
181
181
  __dirname: dir,
182
182
  require: createRequire(dir),
183
- import: (id) => import(id)
183
+ import: (id) => import(id),
184
+ // 定时器相关
185
+ setTimeout,
186
+ clearTimeout,
187
+ setInterval,
188
+ clearInterval,
189
+ setImmediate,
190
+ clearImmediate,
191
+ // 控制台相关
192
+ console,
193
+ // URL 处理
194
+ URL,
195
+ URLSearchParams,
196
+ // 进程和性能相关
197
+ performance,
198
+ // 全局对象引用
199
+ global: globalThis,
200
+ globalThis
184
201
  };
185
202
  const script = new vm.Script(jsCode, { filename });
186
203
  await script.runInNewContext(vmContext, {
@@ -188,10 +205,7 @@ async function execScript(options) {
188
205
  // 设置超时避免长时间运行
189
206
  });
190
207
  const result = vmContext.exports.default || vmContext.exports;
191
- if (typeof result === "function") {
192
- return Promise.resolve(result());
193
- }
194
- return Promise.resolve(result);
208
+ return result;
195
209
  } catch (error) {
196
210
  throw new Error(`EXEC SCRIPT FAIL IN ${filename}: ${error.message}
197
211
 
@@ -200,6 +214,9 @@ ${jsCode}
200
214
  `);
201
215
  }
202
216
  }
217
+ function sleep(ms) {
218
+ return new Promise((resolve) => setTimeout(resolve, ms));
219
+ }
203
220
  function getDefaultExport(expr) {
204
221
  return expr.default === void 0 ? expr : expr.default;
205
222
  }
@@ -215,33 +232,73 @@ function getPageFiles(path, options) {
215
232
  });
216
233
  return files;
217
234
  }
218
- async function checkPagesJsonFile(path) {
235
+ function checkPagesJsonFileSync(path) {
219
236
  const createEmptyFile = (path2) => {
220
- return fs.promises.writeFile(path2, JSON.stringify({ pages: [{ path: "" }] }, null, 2), { encoding: "utf-8" }).then(() => true).catch(() => false);
237
+ try {
238
+ fs.writeFileSync(
239
+ path2,
240
+ JSON.stringify({ pages: [{ path: "" }] }, null, 2),
241
+ { encoding: "utf-8" }
242
+ );
243
+ return true;
244
+ } catch {
245
+ return false;
246
+ }
221
247
  };
222
- const unlink = (path2) => {
223
- return fs.promises.unlink(path2).then(() => true).catch(() => false);
248
+ const unlinkFile = (path2) => {
249
+ try {
250
+ fs.unlinkSync(path2);
251
+ return true;
252
+ } catch {
253
+ return false;
254
+ }
224
255
  };
225
256
  try {
226
- const stat = await fs.promises.stat(path);
257
+ try {
258
+ fs.accessSync(path, fs.constants.F_OK);
259
+ } catch {
260
+ return createEmptyFile(path);
261
+ }
262
+ const stat = fs.statSync(path);
227
263
  if (!stat.isFile()) {
228
- if (!await unlink(path)) {
264
+ if (!unlinkFile(path)) {
229
265
  return false;
230
266
  }
231
267
  return createEmptyFile(path);
232
268
  }
233
- const access = await fs.promises.access(path, fs.constants.W_OK | fs.constants.R_OK).then(() => true).catch(() => false);
234
- if (!access) {
235
- if (!await unlink(path)) {
269
+ try {
270
+ fs.accessSync(path, fs.constants.R_OK | fs.constants.W_OK);
271
+ return true;
272
+ } catch {
273
+ if (!unlinkFile(path)) {
236
274
  return false;
237
275
  }
238
276
  return createEmptyFile(path);
239
277
  }
240
- return true;
241
278
  } catch {
242
279
  return createEmptyFile(path);
243
280
  }
244
281
  }
282
+ async function writeFileWithLock(path, content, retry = 3) {
283
+ if (retry <= 0) {
284
+ debug.error(`${path} \u83B7\u53D6\u6587\u4EF6\u9501\u5931\u8D25\uFF0C\u5199\u5165\u5931\u8D25`);
285
+ return;
286
+ }
287
+ let relase;
288
+ try {
289
+ try {
290
+ relase = await lockfile.lock(path, { realpath: false });
291
+ } catch {
292
+ await sleep(500);
293
+ return writeFileWithLock(path, content, retry - 1);
294
+ }
295
+ await fs.promises.writeFile(path, content, { encoding: "utf-8" });
296
+ } finally {
297
+ if (relase) {
298
+ await relase();
299
+ }
300
+ }
301
+ }
245
302
 
246
303
  function resolveOptions(userOptions, viteRoot = process.cwd()) {
247
304
  const {
@@ -395,7 +452,7 @@ class Page {
395
452
  if (forceUpdate || !this.meta) {
396
453
  await this.read();
397
454
  }
398
- const { path, tabBar: _, ...others } = this.meta;
455
+ const { path, tabBar: _, ...others } = this.meta || {};
399
456
  return {
400
457
  path: path ?? this.uri,
401
458
  ...others
@@ -472,14 +529,15 @@ async function tryPageMetaFromMacro(sfc) {
472
529
  const imports = findImports(ast.body).filter((imp) => !!imp.specifiers.length).map((imp) => babelGenerate(imp).code);
473
530
  const [macroOption] = macro.arguments;
474
531
  const code = babelGenerate(macroOption).code;
475
- const result = await execScript({
532
+ const parsed = await parseCode({
476
533
  imports,
477
534
  code,
478
535
  filename: sfc.filename
479
536
  });
537
+ const res = typeof parsed === "function" ? await Promise.resolve(parsed()) : await Promise.resolve(parsed);
480
538
  return {
481
539
  type: "page",
482
- ...result
540
+ ...res
483
541
  };
484
542
  }
485
543
  return void 0;
@@ -534,7 +592,6 @@ var __publicField = (obj, key, value) => {
534
592
  __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
535
593
  return value;
536
594
  };
537
- let lsatPagesJson = "";
538
595
  class PageContext {
539
596
  constructor(userOptions, viteRoot = process.cwd()) {
540
597
  __publicField(this, "_server");
@@ -558,6 +615,7 @@ class PageContext {
558
615
  __publicField(this, "options");
559
616
  __publicField(this, "logger");
560
617
  __publicField(this, "withUniPlatform", false);
618
+ __publicField(this, "lastPagesJson", "");
561
619
  this.rawOptions = userOptions;
562
620
  this.root = slash(viteRoot);
563
621
  debug.options("root", this.root);
@@ -784,7 +842,7 @@ class PageContext {
784
842
  }
785
843
  }
786
844
  }
787
- await checkPagesJsonFile(this.resolvedPagesJSONPath);
845
+ checkPagesJsonFileSync(this.resolvedPagesJSONPath);
788
846
  this.options.onBeforeLoadUserConfig(this);
789
847
  await this.loadUserPagesConfig();
790
848
  this.options.onAfterLoadUserConfig(this);
@@ -806,29 +864,19 @@ class PageContext {
806
864
  pages.forEach((v) => pagesMap.set(v.path, v));
807
865
  this.pageMetaData = [...pagesMap.values()];
808
866
  this.options.onBeforeWriteFile(this);
809
- const data = {
810
- ...this.pagesGlobConfig,
811
- pages: this.pageMetaData,
812
- subPackages: this.subPageMetaData,
813
- tabBar: await this.getTabBarMerged()
814
- };
867
+ const data = await this.genratePagesJSON();
815
868
  const pagesJson = stringify(
816
869
  data,
817
870
  null,
818
871
  this.options.minify ? void 0 : await this.getIndent()
819
872
  ) + (await this.getEndOfLine() ? await this.getNewline() : "");
820
873
  this.generateDeclaration();
821
- if (lsatPagesJson === pagesJson) {
874
+ if (this.lastPagesJson === pagesJson) {
822
875
  debug.pages("PagesJson Not have change");
823
876
  return false;
824
877
  }
825
- const relase = await lockfile.lock(this.resolvedPagesJSONPath, { realpath: false });
826
- try {
827
- await fs.promises.writeFile(this.resolvedPagesJSONPath, pagesJson, { encoding: "utf-8" });
828
- } finally {
829
- await relase();
830
- }
831
- lsatPagesJson = pagesJson;
878
+ await writeFileWithLock(this.resolvedPagesJSONPath, pagesJson);
879
+ this.lastPagesJson = pagesJson;
832
880
  this.options.onAfterWriteFile(this);
833
881
  return true;
834
882
  }
@@ -849,6 +897,64 @@ class PageContext {
849
897
  debug.declaration("generating");
850
898
  return writeDeclaration(this, this.options.dts);
851
899
  }
900
+ async writePagesJSONFile(pagesJson, retry = 3) {
901
+ if (retry <= 0) {
902
+ debug.error(`${this.resolvedPagesJSONPath} \u83B7\u53D6\u6587\u4EF6\u9501\u5931\u8D25\uFF0C\u5199\u5165\u5931\u8D25`);
903
+ return;
904
+ }
905
+ let relase;
906
+ try {
907
+ try {
908
+ relase = await lockfile.lock(this.resolvedPagesJSONPath, { realpath: false });
909
+ } catch {
910
+ return this.writePagesJSONFile(pagesJson, retry - 1);
911
+ }
912
+ await fs.promises.writeFile(this.resolvedPagesJSONPath, pagesJson, { encoding: "utf-8" });
913
+ } finally {
914
+ if (relase) {
915
+ await relase();
916
+ }
917
+ }
918
+ }
919
+ async genratePagesJSON() {
920
+ const content = await fs.promises.readFile(this.resolvedPagesJSONPath, { encoding: "utf-8" }).catch(() => "");
921
+ let pageJson = parse(content || "{}");
922
+ const { pages: _, subPackages: __, tabBar: ___, ...others } = this.pagesGlobConfig || {};
923
+ pageJson = Object.assign(pageJson, {
924
+ ...others
925
+ });
926
+ const currentPlatform = platform.toUpperCase();
927
+ pageJson.pages = mergePlatformItems(pageJson?.pages, currentPlatform, this.pageMetaData, "path");
928
+ pageJson.subPackages = pageJson?.subPackages || new CommentArray();
929
+ const newSubPackages = /* @__PURE__ */ new Map();
930
+ for (const item of this.subPageMetaData) {
931
+ newSubPackages.set(item.root, item);
932
+ }
933
+ for (const existing of pageJson.subPackages) {
934
+ const sub = newSubPackages.get(existing.root);
935
+ if (sub) {
936
+ existing.pages = mergePlatformItems(existing.pages, currentPlatform, sub.pages, "path");
937
+ newSubPackages.delete(existing.root);
938
+ }
939
+ }
940
+ for (const [_2, newSub] of newSubPackages) {
941
+ pageJson.subPackages.push({
942
+ root: newSub.root,
943
+ pages: mergePlatformItems(void 0, currentPlatform, newSub.pages, "path")
944
+ });
945
+ }
946
+ const tabBar = await this.getTabBarMerged();
947
+ if (tabBar) {
948
+ const list = mergePlatformItems(pageJson?.tabBar?.list, currentPlatform, tabBar.list, "pagePath");
949
+ if (pageJson?.tabBar?.list) {
950
+ pageJson.tabBar.list = list;
951
+ } else {
952
+ pageJson.tabBar = pageJson.tabBar || {};
953
+ pageJson.tabBar.list = list;
954
+ }
955
+ }
956
+ return pageJson;
957
+ }
852
958
  async readInfoFromPagesJSON() {
853
959
  const resolvedPagesJSONContent = await fs.promises.readFile(this.resolvedPagesJSONPath, { encoding: "utf-8" }).catch(() => "");
854
960
  this.resolvedPagesJSONIndent = detectIndent(resolvedPagesJSONContent).indent || " ";
@@ -885,19 +991,125 @@ function getPagePaths(dir, options) {
885
991
  }));
886
992
  return pagePaths;
887
993
  }
994
+ function mergePlatformItems(source, currentPlatform, items, uniqueKeyName) {
995
+ const src = source || new CommentArray();
996
+ currentPlatform = currentPlatform.toUpperCase();
997
+ let lastPlatforms = [];
998
+ for (const comment of src[Symbol.for("before:0")] || []) {
999
+ const trimed = comment.value.trim();
1000
+ if (trimed.startsWith("GENERATED BY UNI-PAGES, PLATFORM:")) {
1001
+ lastPlatforms = trimed.split(":")[1].split("||").map((s) => s.trim()).filter((s) => s !== currentPlatform).sort();
1002
+ }
1003
+ }
1004
+ const tmpMap = /* @__PURE__ */ new Map();
1005
+ for (let i = 0; i < src.length; i++) {
1006
+ const item = src[i];
1007
+ const uniqueKey = item[uniqueKeyName];
1008
+ if (!uniqueKey) {
1009
+ continue;
1010
+ }
1011
+ const beforeComments = src[Symbol.for(`before:${i}`)];
1012
+ const ifdefComment = beforeComments?.find((c) => c.value.trim().startsWith("#ifdef"));
1013
+ let platforms = [...lastPlatforms];
1014
+ if (ifdefComment) {
1015
+ const match = ifdefComment.value.match(/#ifdef\s+(.+)/);
1016
+ if (match) {
1017
+ platforms = match[1].split("||").map((p) => p.trim()).filter((s) => s !== currentPlatform).sort();
1018
+ }
1019
+ }
1020
+ if (platforms.length === 0) {
1021
+ continue;
1022
+ }
1023
+ const existing = tmpMap.get(uniqueKey) || [];
1024
+ existing.push({ item, platforms, platformStr: platforms.join(" || ") });
1025
+ tmpMap.set(uniqueKey, existing);
1026
+ }
1027
+ for (const item of items) {
1028
+ const newItem = item;
1029
+ const uniqueKey = item[uniqueKeyName];
1030
+ if (!uniqueKey) {
1031
+ continue;
1032
+ }
1033
+ if (!tmpMap.has(uniqueKey)) {
1034
+ tmpMap.set(uniqueKey, [{
1035
+ item: newItem,
1036
+ platforms: [currentPlatform],
1037
+ platformStr: currentPlatform
1038
+ }]);
1039
+ continue;
1040
+ }
1041
+ const existing = tmpMap.get(uniqueKey);
1042
+ const newItemStr = JSON.stringify(newItem);
1043
+ const equalObj = existing.find((val) => JSON.stringify(val.item) === newItemStr);
1044
+ if (equalObj) {
1045
+ equalObj.platforms.push(currentPlatform);
1046
+ equalObj.platformStr = equalObj.platforms.join(" || ");
1047
+ } else {
1048
+ existing.push({
1049
+ item: newItem,
1050
+ platforms: [currentPlatform],
1051
+ platformStr: currentPlatform
1052
+ });
1053
+ }
1054
+ }
1055
+ const result = new CommentArray();
1056
+ const platformUsage = {};
1057
+ tmpMap.forEach((val) => {
1058
+ Object.values(val).forEach((v) => {
1059
+ platformUsage[v.platformStr] = (platformUsage[v.platformStr] || 0) + 1;
1060
+ });
1061
+ });
1062
+ const usageKeys = Object.keys(platformUsage);
1063
+ const defaultPlatformStr = usageKeys.length ? usageKeys.reduce((a, b) => platformUsage[a] > platformUsage[b] ? a : b) : currentPlatform;
1064
+ result[Symbol.for("before:0")] = [{
1065
+ type: "LineComment",
1066
+ value: ` GENERATED BY UNI-PAGES, PLATFORM: ${defaultPlatformStr}`,
1067
+ inline: false,
1068
+ loc: {
1069
+ start: { line: 0, column: 0 },
1070
+ end: { line: 0, column: 0 }
1071
+ }
1072
+ }];
1073
+ for (const [_, list] of tmpMap) {
1074
+ for (const { item, platformStr } of list) {
1075
+ result.push(item);
1076
+ if (platformStr !== defaultPlatformStr) {
1077
+ result[Symbol.for(`before:${result.length - 1}`)] = [{
1078
+ type: "LineComment",
1079
+ value: ` #ifdef ${platformStr}`,
1080
+ inline: false,
1081
+ loc: {
1082
+ start: { line: 0, column: 0 },
1083
+ end: { line: 0, column: 0 }
1084
+ }
1085
+ }];
1086
+ result[Symbol.for(`after:${result.length - 1}`)] = [{
1087
+ type: "LineComment",
1088
+ value: " #endif",
1089
+ inline: false,
1090
+ loc: {
1091
+ start: { line: 0, column: 0 },
1092
+ end: { line: 0, column: 0 }
1093
+ }
1094
+ }];
1095
+ }
1096
+ }
1097
+ }
1098
+ return result;
1099
+ }
888
1100
 
889
1101
  function defineUniPages(config) {
890
1102
  return config;
891
1103
  }
892
1104
 
893
- async function VitePluginUniPages(userOptions = {}) {
1105
+ function VitePluginUniPages(userOptions = {}) {
894
1106
  let ctx;
895
1107
  const resolvedPagesJSONPath = path.join(
896
1108
  process.env.VITE_ROOT_DIR || process.cwd(),
897
1109
  userOptions.outDir ?? "src",
898
1110
  OUTPUT_NAME
899
1111
  );
900
- await checkPagesJsonFile(resolvedPagesJSONPath);
1112
+ checkPagesJsonFileSync(resolvedPagesJSONPath);
901
1113
  return {
902
1114
  name: "vite-plugin-uni-pages",
903
1115
  enforce: "pre",
@@ -976,4 +1188,4 @@ async function VitePluginUniPages(userOptions = {}) {
976
1188
  };
977
1189
  }
978
1190
 
979
- export { FILE_EXTENSIONS, MODULE_ID_VIRTUAL, OUTPUT_NAME, Page, PageContext, RESOLVED_MODULE_ID_VIRTUAL, VitePluginUniPages, babelGenerate, checkPagesJsonFile, debug, VitePluginUniPages as default, defineUniPages, execScript, extsToGlob, findImports, findMacro, getPageFiles, getRouteBlock, getRouteSfcBlock, invalidatePagesModule, isTargetFile, mergePageMetaDataArray, parseCustomBlock, parseSFC, resolveOptions, resolvePageDirs, tryPageMetaFromCustomBlock, tryPageMetaFromMacro };
1191
+ export { FILE_EXTENSIONS, MODULE_ID_VIRTUAL, OUTPUT_NAME, Page, PageContext, RESOLVED_MODULE_ID_VIRTUAL, VitePluginUniPages, babelGenerate, checkPagesJsonFileSync, debug, VitePluginUniPages as default, defineUniPages, extsToGlob, findImports, findMacro, getPageFiles, getRouteBlock, getRouteSfcBlock, invalidatePagesModule, isTargetFile, mergePageMetaDataArray, parseCode, parseCustomBlock, parseSFC, resolveOptions, resolvePageDirs, sleep, tryPageMetaFromCustomBlock, tryPageMetaFromMacro, writeFileWithLock };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@uni-helper/vite-plugin-uni-pages",
3
3
  "type": "module",
4
- "version": "0.3.16",
4
+ "version": "0.3.18",
5
5
  "description": "File system based routing for uni-app applications using Vite",
6
6
  "author": "KeJun",
7
7
  "maintainers": [