@weapp-tailwindcss/env 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- //#region \0rolldown/runtime.js
2
+ // \0rolldown/runtime.js
3
3
  var __create = Object.create;
4
4
  var __defProp = Object.defineProperty;
5
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -20,13 +20,12 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
20
20
  value: mod,
21
21
  enumerable: true
22
22
  }) : target, mod));
23
- //#endregion
24
23
  let node_process = require("node:process");
25
24
  node_process = __toESM(node_process, 1);
26
25
  let node_path = require("node:path");
27
26
  node_path = __toESM(node_path, 1);
28
27
  let node_fs = require("node:fs");
29
- //#region src/environment.ts
28
+ // src/environment.ts
30
29
  function getProcessEnv() {
31
30
  return {
32
31
  MPX_CLI_MODE: node_process.default.env["MPX_CLI_MODE"],
@@ -39,8 +38,7 @@ function getProcessEnv() {
39
38
  WEAPP_TW_TARGET: node_process.default.env["WEAPP_TW_TARGET"]
40
39
  };
41
40
  }
42
- //#endregion
43
- //#region src/hbuilderx.ts
41
+ // src/hbuilderx.ts
44
42
  const KNOWN_MAC_HBUILDERX_PLUGIN_DIRS = ["/Applications/HBuilderX.app/Contents/HBuilderX/plugins/uniapp-cli-vite", "/Applications/HBuilderX.app/Contents/HBuilderX/plugins/uniapp-cli"];
45
43
  const HBUILDERX_PLUGIN_CWD_RE = /[\\/]HBuilderX(?:\.[^\\/]*)?(?:[\\/]Contents[\\/]HBuilderX)?[\\/]plugins[\\/]uniapp-cli(?:-vite)?(?:[\\/]|$)/i;
46
44
  function hasKnownHBuilderXPluginPrefix(normalizedCwd) {
@@ -61,23 +59,74 @@ function isRunningInHBuilderX(options = {}) {
61
59
  if (!(nodePath == null || nodePath.trim().length === 0)) return false;
62
60
  return matchesHBuilderXPluginCwd(options.cwd ?? node_process.default.cwd());
63
61
  }
64
- //#endregion
65
- //#region src/platform.ts
66
- const MINI_PROGRAM_PLATFORMS = /* @__PURE__ */ new Set([
67
- "alipay",
68
- "baidu",
69
- "jd",
70
- "qq",
71
- "swan",
72
- "tt",
73
- "weapp",
74
- "wechat",
75
- "wx"
62
+ // src/matching.ts
63
+ function evidence(source, key, value, file) {
64
+ return {
65
+ source,
66
+ key,
67
+ ...value !== void 0 ? { value } : {},
68
+ ...file !== void 0 ? { path: file } : {}
69
+ };
70
+ }
71
+ function collectMatches(matches, all) {
72
+ const result = [];
73
+ for (const candidate of matches) {
74
+ result.push(candidate);
75
+ if (!all) break;
76
+ }
77
+ return result;
78
+ }
79
+ function detectionReport(candidates) {
80
+ const grouped = /* @__PURE__ */ new Map();
81
+ for (const candidate of candidates) {
82
+ const existing = grouped.get(candidate.appType);
83
+ if (existing) existing.evidence.push(...candidate.evidence);
84
+ else grouped.set(candidate.appType, {
85
+ ...candidate,
86
+ evidence: [...candidate.evidence]
87
+ });
88
+ }
89
+ const unique = [...grouped.values()];
90
+ const appType = unique[0]?.appType;
91
+ const family = (value) => value.startsWith("uni-app") ? "uni-app" : value;
92
+ return {
93
+ appType,
94
+ candidates: unique,
95
+ conflicts: appType === void 0 ? [] : unique.filter((candidate) => family(candidate.appType) !== family(appType)).map((candidate) => candidate.appType)
96
+ };
97
+ }
98
+ // src/platform.ts
99
+ const MPX_TO_UNI_PLATFORM = /* @__PURE__ */ new Map([
100
+ ["ali", "mp-alipay"],
101
+ ["dd", "mp-dingtalk"],
102
+ ["jd", "mp-jd"],
103
+ ["qq", "mp-qq"],
104
+ ["swan", "mp-baidu"],
105
+ ["tt", "mp-toutiao"],
106
+ ["wx", "mp-weixin"]
107
+ ]);
108
+ const TARO_TO_CANONICAL_PLATFORM = /* @__PURE__ */ new Map([["harmony-hybrid", "web"]]);
109
+ const MINI_PROGRAM_PLATFORMS = new Map([
110
+ ...[...MPX_TO_UNI_PLATFORM].filter(([alias]) => alias !== "ali" && alias !== "dd"),
111
+ ["alipay", "mp-alipay"],
112
+ ["baidu", "mp-baidu"],
113
+ ["weapp", "mp-weixin"],
114
+ ["wechat", "mp-weixin"]
115
+ ]);
116
+ const CANONICAL_PLATFORMS = new Map([
117
+ ...[...MPX_TO_UNI_PLATFORM.values()].map((value) => [value, value]),
118
+ ["web", "web"],
119
+ ["h5", "web"],
120
+ ["app", "app"],
121
+ ["app-plus", "app-plus"],
122
+ ["app-android", "app-android"],
123
+ ["app-ios", "app-ios"],
124
+ ["app-harmony", "app-harmony"]
76
125
  ]);
77
126
  function normalizePlatform(value) {
78
127
  return value?.trim().toLowerCase() || void 0;
79
128
  }
80
- function resolvePlatformInfo(value) {
129
+ function resolvePlatformInfo(value, appType) {
81
130
  const normalized = normalizePlatform(value);
82
131
  const isAppAndroid = normalized === "app-android";
83
132
  const isAppIos = normalized === "app-ios";
@@ -89,21 +138,29 @@ function resolvePlatformInfo(value) {
89
138
  isAppAndroid,
90
139
  isAppHarmony,
91
140
  isAppIos,
92
- isMp: normalized?.startsWith("mp-") === true || (normalized ? MINI_PROGRAM_PLATFORMS.has(normalized) : false),
93
- isWeb: normalized?.startsWith("web") === true || normalized === "h5"
141
+ isMp: normalized?.startsWith("mp-") === true || (normalized ? MINI_PROGRAM_PLATFORMS.has(normalized) || appType === "mpx" && MPX_TO_UNI_PLATFORM.has(normalized) : false),
142
+ isWeb: normalized?.startsWith("web") === true || normalized === "h5" || appType === "taro" && normalized !== void 0 && TARO_TO_CANONICAL_PLATFORM.get(normalized) === "web"
94
143
  };
95
144
  }
96
145
  function resolvePlatform(value) {
97
146
  return resolvePlatformInfo(value);
98
147
  }
99
148
  function resolveTaroPlatform(value = getProcessEnv().TARO_ENV) {
100
- return resolvePlatform(value);
149
+ return resolvePlatformInfo(value, "taro");
150
+ }
151
+ /** 读取 Taro 环境快照;省略快照时才使用调用时的进程环境。 */
152
+ function resolveTaroPlatformFromEnv(env = getProcessEnv()) {
153
+ return resolvePlatformInfo(env.TARO_ENV, "taro");
101
154
  }
102
155
  function resolveMpxPlatformValue(env = getProcessEnv()) {
103
156
  return env.MPX_CURRENT_TARGET_MODE ?? env.MPX_CLI_MODE;
104
157
  }
105
158
  function resolveMpxPlatform(value = resolveMpxPlatformValue()) {
106
- return resolvePlatform(value);
159
+ return resolvePlatformInfo(value, "mpx");
160
+ }
161
+ /** 读取 MPX 环境快照,保留 current mode 的空字符串优先级。 */
162
+ function resolveMpxPlatformFromEnv(env = getProcessEnv()) {
163
+ return resolvePlatformInfo(resolveMpxPlatformValue(env), "mpx");
107
164
  }
108
165
  function resolveUniPlatform(value = getProcessEnv().UNI_PLATFORM) {
109
166
  return resolvePlatform(value);
@@ -121,141 +178,468 @@ function resolveUniPlatformsFromEnv(env = getProcessEnv()) {
121
178
  uniUtsPlatform: resolvePlatform(env.UNI_UTS_PLATFORM)
122
179
  };
123
180
  }
124
- const MPX_TO_UNI_PLATFORM = {
125
- ali: "mp-alipay",
126
- dd: "mp-dingtalk",
127
- jd: "mp-jd",
128
- qq: "mp-qq",
129
- swan: "mp-baidu",
130
- tt: "mp-toutiao",
131
- wx: "mp-weixin"
132
- };
133
181
  function normalizeFrameworkStylePlatform(platform, appType) {
134
182
  const normalized = platform?.trim().toLowerCase();
135
183
  if (!normalized) return;
136
- if (appType === "mpx") return MPX_TO_UNI_PLATFORM[normalized] ?? normalized;
184
+ if (appType === "mpx") return MPX_TO_UNI_PLATFORM.get(normalized) ?? normalized;
137
185
  return normalized;
138
186
  }
139
- //#endregion
140
- //#region src/detect-env.ts
141
- function detectAppTypeFromEnv(env = getProcessEnv(), options = {}) {
142
- if (env.WEAPP_TW_TARGET === "weapp-vite" || env.WEAPP_TAILWINDCSS_TARGET === "weapp-vite") return "weapp-vite";
143
- if (env.TARO_ENV) return "taro";
144
- if (env.MPX_CLI_MODE || env.MPX_CURRENT_TARGET_MODE) return "mpx";
187
+ function resolvePlatformIdentity(platform, appType) {
188
+ const normalized = normalizePlatform(platform);
189
+ return {
190
+ raw: platform,
191
+ normalized,
192
+ canonical: normalized ? (appType === "mpx" ? MPX_TO_UNI_PLATFORM.get(normalized) : void 0) ?? (appType === "taro" ? TARO_TO_CANONICAL_PLATFORM.get(normalized) : void 0) ?? MINI_PROGRAM_PLATFORMS.get(normalized) ?? CANONICAL_PLATFORMS.get(normalized) : void 0
193
+ };
194
+ }
195
+ // src/detect-env.ts
196
+ function* matchEnvironment(env, options = {}) {
197
+ for (const key of ["WEAPP_TW_TARGET", "WEAPP_TAILWINDCSS_TARGET"]) {
198
+ const value = env[key];
199
+ if (value === "weapp-vite") yield {
200
+ appType: "weapp-vite",
201
+ evidence: [evidence("env", key, value)]
202
+ };
203
+ }
204
+ const taro = env.TARO_ENV;
205
+ if (taro) yield {
206
+ appType: "taro",
207
+ evidence: [evidence("env", "TARO_ENV", taro)]
208
+ };
209
+ for (const key of ["MPX_CLI_MODE", "MPX_CURRENT_TARGET_MODE"]) {
210
+ const value = env[key];
211
+ if (value) yield {
212
+ appType: "mpx",
213
+ evidence: [evidence("env", key, value)]
214
+ };
215
+ }
145
216
  const { uniPlatform, uniUtsPlatform } = resolveUniPlatformsFromEnv(env);
146
- if (uniUtsPlatform.normalized) return "uni-app-x";
147
- if (uniPlatform.normalized) return "uni-app-vite";
217
+ if (uniUtsPlatform.normalized) yield {
218
+ appType: "uni-app-x",
219
+ evidence: [evidence("env", "UNI_UTS_PLATFORM", uniUtsPlatform.raw)]
220
+ };
221
+ if (uniPlatform.normalized) yield {
222
+ appType: "uni-app-vite",
223
+ evidence: [evidence("env", "UNI_PLATFORM", uniPlatform.raw)]
224
+ };
148
225
  if (isRunningInHBuilderX({
149
226
  cwd: options.cwd,
150
227
  env
151
- })) return options.hbuilderxVite === false ? "uni-app" : "uni-app-vite";
152
- }
153
- //#endregion
154
- //#region src/package.ts
155
- const MPX_SCRIPT_RE = /\bmpx(?:-cli-service)?\b/u;
156
- const TARO_SCRIPT_RE = /\btaro\b/u;
157
- const WEAPP_VITE_SCRIPT_RE = /\bweapp-vite\b/u;
158
- const UNI_APP_SCRIPT_RE = /\buni(?:\s|$)/u;
159
- const UNI_APP_VITE_SCRIPT_RE = /\buni(?:\s|$)/u;
160
- function resolveDependencyNames(pkg) {
161
- return /* @__PURE__ */ new Set([
162
- ...Object.keys(pkg.dependencies ?? {}),
163
- ...Object.keys(pkg.devDependencies ?? {}),
164
- ...Object.keys(pkg.peerDependencies ?? {}),
165
- ...Object.keys(pkg.optionalDependencies ?? {})
166
- ]);
167
- }
168
- function hasDependencyPrefix(dependencyNames, prefix) {
169
- return [...dependencyNames].some((name) => name.startsWith(prefix));
170
- }
171
- function hasScriptMatch(pkg, pattern) {
172
- return Object.values(pkg.scripts ?? {}).some((script) => pattern.test(script));
228
+ })) yield {
229
+ appType: options.hbuilderxVite === false ? "uni-app" : "uni-app-vite",
230
+ evidence: [evidence("hbuilderx", "cwd", options.cwd ?? node_process.default.cwd())]
231
+ };
232
+ }
233
+ function detectAppTypeFromEnv(env = getProcessEnv(), options = {}) {
234
+ return collectMatches(matchEnvironment(env, options), false)[0]?.appType;
235
+ }
236
+ // src/script-command.ts
237
+ const ASSIGNMENT_RE = /^[A-Z_]\w*=/iu;
238
+ const COMMAND_TYPES = /* @__PURE__ */ new Map([
239
+ ["mpx", "mpx"],
240
+ ["mpx-cli-service", "mpx"],
241
+ ["taro", "taro"],
242
+ ["uni", "uni-app-vite"],
243
+ ["weapp-vite", "weapp-vite"]
244
+ ]);
245
+ const PNPM_VALUE_OPTIONS = /* @__PURE__ */ new Set([
246
+ "-C",
247
+ "--dir",
248
+ "-F",
249
+ "--filter",
250
+ "--filter-prod",
251
+ "--reporter"
252
+ ]);
253
+ const PNPM_FLAGS = /* @__PURE__ */ new Set([
254
+ "-w",
255
+ "--workspace-root",
256
+ "-r",
257
+ "--recursive",
258
+ "-s",
259
+ "--silent"
260
+ ]);
261
+ const NPX_VALUE_OPTIONS = /* @__PURE__ */ new Set([
262
+ "-p",
263
+ "--package",
264
+ "--cache",
265
+ "--userconfig"
266
+ ]);
267
+ const NPX_FLAGS = /* @__PURE__ */ new Set([
268
+ "-y",
269
+ "--yes",
270
+ "--no",
271
+ "--no-install",
272
+ "-q",
273
+ "--quiet"
274
+ ]);
275
+ const ENV_VALUE_OPTIONS = /* @__PURE__ */ new Set([
276
+ "-u",
277
+ "--unset",
278
+ "-C",
279
+ "--chdir"
280
+ ]);
281
+ function readExpansionEnd(script, start, opening, closing) {
282
+ let depth = 1;
283
+ let quote;
284
+ for (let index = start + 2; index < script.length; index++) {
285
+ const character = script[index];
286
+ if (character === "\\" && quote !== "'") index++;
287
+ else if (quote) {
288
+ if (character === quote) quote = void 0;
289
+ } else if (character === "\"" || character === "'" || character === "`") quote = character;
290
+ else if (character === opening) depth++;
291
+ else if (character === closing && --depth === 0) return index;
292
+ }
293
+ return -1;
294
+ }
295
+ function tokenizeCommands(script) {
296
+ const commands = [];
297
+ let command = [];
298
+ let value = "";
299
+ let active = false;
300
+ let quoted = false;
301
+ let shellAssignment = false;
302
+ let protectedPrefix = false;
303
+ let quote;
304
+ function flushToken() {
305
+ if (active) {
306
+ command.push({
307
+ value,
308
+ quoted,
309
+ shellAssignment
310
+ });
311
+ value = "";
312
+ active = false;
313
+ quoted = false;
314
+ shellAssignment = false;
315
+ protectedPrefix = false;
316
+ }
317
+ }
318
+ function flushCommand() {
319
+ flushToken();
320
+ if (command.length) {
321
+ commands.push(command);
322
+ command = [];
323
+ }
324
+ }
325
+ for (let index = 0; index < script.length; index++) {
326
+ const character = script[index];
327
+ const next = script[index + 1];
328
+ if (character === "\\" && quote !== "'" && next && /[\s"'\\$`;&|]/u.test(next) || character === "^" && !quote && next && /[\s"^;&|]/u.test(next)) {
329
+ if (next !== "\n" && next !== "\r") {
330
+ protectedPrefix = true;
331
+ value += next;
332
+ active = true;
333
+ } else if (next === "\r" && script[index + 2] === "\n") index++;
334
+ index++;
335
+ } else if (character === "$" && (next === "(" || next === "{") && quote !== "'") {
336
+ const end = readExpansionEnd(script, index, next, next === "(" ? ")" : "}");
337
+ if (end === -1) return [];
338
+ value += script.slice(index, end + 1);
339
+ protectedPrefix = true;
340
+ active = true;
341
+ index = end;
342
+ } else if (quote) {
343
+ if (character === quote) quote = void 0;
344
+ else value += character;
345
+ } else if (character === "\"" || character === "'" || character === "`") {
346
+ quote = character;
347
+ quoted = true;
348
+ protectedPrefix = true;
349
+ active = true;
350
+ if (character === "`") value += character;
351
+ } else if (character === "<" && next === "<") return [];
352
+ else if ((character === ">" || character === "<") && next === "&" || character === "&" && next === ">") {
353
+ value += character + next;
354
+ active = true;
355
+ index++;
356
+ } else if (character === "#" && !active) while (script[index + 1] && script[index + 1] !== "\n") index++;
357
+ else if (character === ";" || character === "&" || character === "|" || character === "\n" || character === "\r") flushCommand();
358
+ else if (/\s/u.test(character)) flushToken();
359
+ else {
360
+ if (character === "=" && !protectedPrefix && ASSIGNMENT_RE.test(`${value}=`)) shellAssignment = true;
361
+ value += character;
362
+ active = true;
363
+ }
364
+ }
365
+ if (quote) return [];
366
+ flushCommand();
367
+ return commands;
368
+ }
369
+ function executableName(value, allowVersion = false) {
370
+ if (allowVersion && value.startsWith("@")) return value;
371
+ const name = node_path.default.win32.basename(node_path.default.posix.basename(value));
372
+ const executable = /\.(?:cmd|bat|exe)$/iu.test(name) ? name.replace(/\.(?:cmd|bat|exe)$/iu, "").toLowerCase() : name;
373
+ return allowVersion ? executable.replace(/@[^@]+$/u, "") : executable;
374
+ }
375
+ function skipAssignments(tokens, index, shellPosition = false) {
376
+ while (tokens[index] && (shellPosition ? tokens[index].shellAssignment : ASSIGNMENT_RE.test(tokens[index].value))) index++;
377
+ return index;
378
+ }
379
+ function skipOptions(tokens, index, flags, valueOptions) {
380
+ while (tokens[index]?.value.startsWith("-")) {
381
+ const value = tokens[index].value;
382
+ if (value === "--") return index + 1;
383
+ if (flags.has(value)) index++;
384
+ else if (valueOptions.has(value)) {
385
+ if (!tokens[index + 1]) return tokens.length;
386
+ index += 2;
387
+ } else if (value.includes("=") && valueOptions.has(value.slice(0, value.indexOf("=")))) index++;
388
+ else return tokens.length;
389
+ }
390
+ return index;
391
+ }
392
+ function collectCommands(script, detected, depth = 0) {
393
+ if (depth > 8) return;
394
+ for (const tokens of tokenizeCommands(script)) {
395
+ let index = skipAssignments(tokens, 0, true);
396
+ let allowVersion = false;
397
+ while (tokens[index]) {
398
+ const name = executableName(tokens[index].value, allowVersion);
399
+ const appType = COMMAND_TYPES.get(name);
400
+ if (appType) {
401
+ detected.add(appType);
402
+ break;
403
+ }
404
+ allowVersion = false;
405
+ index++;
406
+ if (name === "cross-env" || name === "cross-env-shell") {
407
+ index = skipAssignments(tokens, index);
408
+ const payload = tokens[index];
409
+ if (name === "cross-env-shell" && payload?.quoted) {
410
+ collectCommands(payload.value, detected, depth + 1);
411
+ break;
412
+ }
413
+ } else if (name === "env") {
414
+ index = skipOptions(tokens, index, /* @__PURE__ */ new Set(["-i", "--ignore-environment"]), ENV_VALUE_OPTIONS);
415
+ index = skipAssignments(tokens, index);
416
+ } else if (name === "pnpm") {
417
+ index = skipOptions(tokens, index, PNPM_FLAGS, PNPM_VALUE_OPTIONS);
418
+ if (tokens[index]?.value === "exec" || tokens[index]?.value === "dlx") {
419
+ const dlx = tokens[index].value === "dlx";
420
+ index++;
421
+ index = skipOptions(tokens, index, dlx ? NPX_FLAGS : PNPM_FLAGS, dlx ? NPX_VALUE_OPTIONS : PNPM_VALUE_OPTIONS);
422
+ allowVersion = dlx;
423
+ }
424
+ } else if (name === "npx") {
425
+ index = skipOptions(tokens, index, NPX_FLAGS, NPX_VALUE_OPTIONS);
426
+ allowVersion = true;
427
+ } else break;
428
+ }
429
+ }
430
+ }
431
+ /**
432
+ * 仅识别脚本中明确的命令位置,不执行脚本或推断任意参数中的框架名称。
433
+ */
434
+ function detectFrameworkCommands(script) {
435
+ const detected = /* @__PURE__ */ new Set();
436
+ collectCommands(script, detected);
437
+ return [...detected];
438
+ }
439
+ // src/package.ts
440
+ const FRAMEWORK_PRIORITY = [
441
+ "weapp-vite",
442
+ "mpx",
443
+ "taro",
444
+ "uni-app-x",
445
+ "uni-app-vite",
446
+ "uni-app"
447
+ ];
448
+ const DEPENDENCY_FIELDS = [
449
+ "dependencies",
450
+ "devDependencies",
451
+ "peerDependencies",
452
+ "optionalDependencies"
453
+ ];
454
+ function matchesDependency(appType, name) {
455
+ switch (appType) {
456
+ case "weapp-vite": return name === "weapp-vite" || name.startsWith("@weapp-vite/");
457
+ case "mpx": return name.startsWith("@mpxjs/");
458
+ case "taro": return name.startsWith("@tarojs/");
459
+ case "uni-app-x": return name === "@dcloudio/uni-uts-v1" || name === "@weapp-tailwindcss/debug-uni-app-x";
460
+ case "uni-app-vite": return name === "@dcloudio/vite-plugin-uni";
461
+ case "uni-app": return name === "@dcloudio/vue-cli-plugin-uni" || name === "@dcloudio/uni-app";
462
+ }
463
+ }
464
+ function packageMatcher(pkg, file) {
465
+ let scripts;
466
+ return (appType, all) => {
467
+ const result = [];
468
+ for (const field of DEPENDENCY_FIELDS) for (const [name, version] of Object.entries(pkg[field] ?? {})) if (matchesDependency(appType, name)) {
469
+ result.push(evidence("dependency", `${field}.${name}`, version, file));
470
+ if (!all) return result;
471
+ }
472
+ if (appType === "uni-app" && Object.hasOwn(pkg, "uni-app")) {
473
+ result.push(evidence("package-field", "uni-app", void 0, file));
474
+ if (!all) return result;
475
+ }
476
+ if (appType === "uni-app-x") return result;
477
+ scripts ??= Object.entries(pkg.scripts ?? {}).map(([name, value]) => ({
478
+ name,
479
+ value,
480
+ commands: detectFrameworkCommands(value)
481
+ }));
482
+ for (const script of scripts) {
483
+ const commandType = appType === "uni-app" ? "uni-app-vite" : appType;
484
+ if (script.commands.includes(commandType)) {
485
+ result.push(evidence("script", `scripts.${script.name}`, script.value, file));
486
+ if (!all) return result;
487
+ }
488
+ }
489
+ return result;
490
+ };
491
+ }
492
+ function* matchPackageJson(pkg, all, file) {
493
+ const match = packageMatcher(pkg, file);
494
+ for (const appType of FRAMEWORK_PRIORITY) {
495
+ const evidence = match(appType, all);
496
+ if (evidence.length) yield {
497
+ appType,
498
+ evidence
499
+ };
500
+ }
173
501
  }
174
502
  function isWeappVitePackage(pkg) {
175
- const dependencyNames = resolveDependencyNames(pkg);
176
- return dependencyNames.has("weapp-vite") || hasDependencyPrefix(dependencyNames, "@weapp-vite/") || hasScriptMatch(pkg, WEAPP_VITE_SCRIPT_RE);
503
+ return packageMatcher(pkg)("weapp-vite", false).length > 0;
177
504
  }
178
505
  function isMpxPackage(pkg) {
179
- return hasDependencyPrefix(resolveDependencyNames(pkg), "@mpxjs/") || hasScriptMatch(pkg, MPX_SCRIPT_RE);
506
+ return packageMatcher(pkg)("mpx", false).length > 0;
180
507
  }
181
508
  function isTaroPackage(pkg) {
182
- return hasDependencyPrefix(resolveDependencyNames(pkg), "@tarojs/") || hasScriptMatch(pkg, TARO_SCRIPT_RE);
509
+ return packageMatcher(pkg)("taro", false).length > 0;
183
510
  }
184
511
  function isUniAppVitePackage(pkg) {
185
- return resolveDependencyNames(pkg).has("@dcloudio/vite-plugin-uni") || hasScriptMatch(pkg, UNI_APP_VITE_SCRIPT_RE);
512
+ return packageMatcher(pkg)("uni-app-vite", false).length > 0;
186
513
  }
187
514
  function isUniAppXPackage(pkg) {
188
- const dependencyNames = resolveDependencyNames(pkg);
189
- return dependencyNames.has("@dcloudio/uni-uts-v1") || dependencyNames.has("@weapp-tailwindcss/debug-uni-app-x");
515
+ return packageMatcher(pkg)("uni-app-x", false).length > 0;
190
516
  }
191
517
  function isUniAppPackage(pkg) {
192
- const dependencyNames = resolveDependencyNames(pkg);
193
- return dependencyNames.has("@dcloudio/vue-cli-plugin-uni") || dependencyNames.has("@dcloudio/uni-app") || Object.hasOwn(pkg, "uni-app") || hasScriptMatch(pkg, UNI_APP_SCRIPT_RE);
518
+ return packageMatcher(pkg)("uni-app", false).length > 0;
194
519
  }
195
520
  function isUniAppXManifest(manifest) {
196
521
  return Boolean(manifest && Object.hasOwn(manifest, "uni-app-x"));
197
522
  }
198
523
  function detectAppTypeFromPackageJson(pkg) {
199
- if (isWeappVitePackage(pkg)) return "weapp-vite";
200
- if (isMpxPackage(pkg)) return "mpx";
201
- if (isTaroPackage(pkg)) return "taro";
202
- if (isUniAppXPackage(pkg)) return "uni-app-x";
203
- if (isUniAppVitePackage(pkg)) return "uni-app-vite";
204
- if (isUniAppPackage(pkg)) return "uni-app";
205
- }
206
- //#endregion
207
- //#region src/project.ts
524
+ return collectMatches(matchPackageJson(pkg, false), false)[0]?.appType;
525
+ }
526
+ // src/manifest.ts
527
+ /** 仅移除字符串外的注释,其余语法仍交给严格 JSON 解析。 */
528
+ function parseManifestJson(source) {
529
+ const characters = source.split("");
530
+ let inString = false;
531
+ for (let index = 0; index < source.length; index++) {
532
+ const character = source[index];
533
+ if (inString) {
534
+ if (character === "\\") index++;
535
+ else if (character === "\"") inString = false;
536
+ continue;
537
+ }
538
+ if (character === "\"") {
539
+ inString = true;
540
+ continue;
541
+ }
542
+ if (character !== "/") continue;
543
+ if (source[index + 1] === "/") {
544
+ characters[index] = " ";
545
+ characters[++index] = " ";
546
+ while (index + 1 < source.length && source[index + 1] !== "\n" && source[index + 1] !== "\r") characters[++index] = " ";
547
+ } else if (source[index + 1] === "*") {
548
+ characters[index] = " ";
549
+ characters[++index] = " ";
550
+ let closed = false;
551
+ while (++index < source.length) {
552
+ if (source[index] === "*" && source[index + 1] === "/") {
553
+ characters[index] = " ";
554
+ characters[++index] = " ";
555
+ closed = true;
556
+ break;
557
+ }
558
+ if (source[index] !== "\n" && source[index] !== "\r") characters[index] = " ";
559
+ }
560
+ if (!closed) throw new SyntaxError("manifest.json 中存在未闭合的块注释");
561
+ }
562
+ }
563
+ return JSON.parse(characters.join(""));
564
+ }
565
+ // src/project.ts
208
566
  const PACKAGE_JSON_FILE = "package.json";
209
567
  const MANIFEST_JSON_FILE = "manifest.json";
210
568
  const MPX_MARKERS = [["src", "app.mpx"], ["app.mpx"]];
211
- function tryReadJson(file) {
569
+ function tryReadJson(file, parse = JSON.parse) {
212
570
  if (!(0, node_fs.existsSync)(file)) return;
213
571
  try {
214
- return JSON.parse((0, node_fs.readFileSync)(file, "utf8"));
572
+ return parse((0, node_fs.readFileSync)(file, "utf8"));
215
573
  } catch {}
216
574
  }
217
- function detectAppTypeFromMarkers(root) {
218
- for (const segments of MPX_MARKERS) if ((0, node_fs.existsSync)(node_path.default.join(root, ...segments))) return "mpx";
575
+ function manifestMatches(manifest, file) {
576
+ return isUniAppXManifest(manifest) ? [{
577
+ appType: "uni-app-x",
578
+ evidence: [evidence("manifest", "uni-app-x", void 0, file)]
579
+ }] : [];
219
580
  }
220
- function detectAppTypeFromRoot(root, searchUp = true) {
581
+ function matchRoot(root, searchUp, all) {
221
582
  const resolvedRoot = node_path.default.resolve(root);
222
- if (!(0, node_fs.existsSync)(resolvedRoot)) return;
223
- const markerDetected = detectAppTypeFromMarkers(resolvedRoot);
224
- if (markerDetected) return markerDetected;
583
+ if (!(0, node_fs.existsSync)(resolvedRoot)) return [];
584
+ const markers = [];
585
+ for (const segments of MPX_MARKERS) {
586
+ const file = node_path.default.join(resolvedRoot, ...segments);
587
+ if ((0, node_fs.existsSync)(file)) {
588
+ markers.push(evidence("marker", "app.mpx", void 0, file));
589
+ if (!all) break;
590
+ }
591
+ }
592
+ if (markers.length) return [{
593
+ appType: "mpx",
594
+ evidence: markers
595
+ }];
225
596
  let current = resolvedRoot;
226
597
  while (true) {
227
- if (isUniAppXManifest(tryReadJson(node_path.default.join(current, MANIFEST_JSON_FILE)))) return "uni-app-x";
228
- const pkg = tryReadJson(node_path.default.join(current, PACKAGE_JSON_FILE));
598
+ const manifestFile = node_path.default.join(current, MANIFEST_JSON_FILE);
599
+ const manifest = manifestMatches(tryReadJson(manifestFile, parseManifestJson), manifestFile);
600
+ if (manifest.length) return manifest;
601
+ const packageFile = node_path.default.join(current, PACKAGE_JSON_FILE);
602
+ const pkg = tryReadJson(packageFile);
229
603
  if (pkg) {
230
- const detected = detectAppTypeFromPackageJson(pkg);
231
- if (detected) return detected;
604
+ const candidates = collectMatches(matchPackageJson(pkg, all, packageFile), all);
605
+ if (candidates.length) return candidates;
232
606
  }
233
607
  if (!searchUp) break;
234
608
  const parent = node_path.default.dirname(current);
235
609
  if (parent === current) break;
236
610
  current = parent;
237
611
  }
612
+ return [];
238
613
  }
239
- function detectAppType(options = {}) {
240
- if (isUniAppXManifest(options.manifest)) return "uni-app-x";
614
+ function matchAppType(options, all) {
615
+ const manifest = manifestMatches(options.manifest);
616
+ if (manifest.length) return manifest;
241
617
  if (options.packageJson) {
242
- const detected = detectAppTypeFromPackageJson(options.packageJson);
243
- if (detected) return detected;
618
+ const candidates = collectMatches(matchPackageJson(options.packageJson, all), all);
619
+ if (candidates.length) return candidates;
244
620
  }
245
621
  if (options.root) {
246
- const detected = detectAppTypeFromRoot(options.root, options.searchUp ?? true);
247
- if (detected) return detected;
622
+ const candidates = matchRoot(options.root, options.searchUp ?? true, all);
623
+ if (candidates.length) return candidates;
248
624
  }
249
625
  const env = options.env ?? (options.detectEnv ? getProcessEnv() : void 0);
250
- if (env) return detectAppTypeFromEnv(env, {
626
+ if (!env) return [];
627
+ return collectMatches(matchEnvironment(env, {
251
628
  cwd: options.cwd ?? options.root ?? (options.detectEnv ? node_process.default.cwd() : void 0),
252
629
  hbuilderxVite: options.hbuilderxVite
253
- });
630
+ }), all);
631
+ }
632
+ function detectAppType(options = {}) {
633
+ return matchAppType(options, false)[0]?.appType;
634
+ }
635
+ /** 解释首次命中阶段的框架候选与冲突,不扩大项目搜索范围。 */
636
+ function detectAppTypeReport(options = {}) {
637
+ return detectionReport(matchAppType(options, true));
254
638
  }
255
- //#endregion
256
639
  exports.detectAppType = detectAppType;
257
640
  exports.detectAppTypeFromEnv = detectAppTypeFromEnv;
258
641
  exports.detectAppTypeFromPackageJson = detectAppTypeFromPackageJson;
642
+ exports.detectAppTypeReport = detectAppTypeReport;
259
643
  exports.isMpxPackage = isMpxPackage;
260
644
  exports.isRunningInHBuilderX = isRunningInHBuilderX;
261
645
  exports.isTaroPackage = isTaroPackage;
@@ -266,8 +650,11 @@ exports.isUniAppXPackage = isUniAppXPackage;
266
650
  exports.isWeappVitePackage = isWeappVitePackage;
267
651
  exports.normalizeFrameworkStylePlatform = normalizeFrameworkStylePlatform;
268
652
  exports.resolveMpxPlatform = resolveMpxPlatform;
653
+ exports.resolveMpxPlatformFromEnv = resolveMpxPlatformFromEnv;
269
654
  exports.resolvePlatform = resolvePlatform;
655
+ exports.resolvePlatformIdentity = resolvePlatformIdentity;
270
656
  exports.resolveTaroPlatform = resolveTaroPlatform;
657
+ exports.resolveTaroPlatformFromEnv = resolveTaroPlatformFromEnv;
271
658
  exports.resolveUniAppXPlatform = resolveUniAppXPlatform;
272
659
  exports.resolveUniPlatform = resolveUniPlatform;
273
660
  exports.resolveUniPlatformsFromEnv = resolveUniPlatformsFromEnv;