@weapp-tailwindcss/env 0.0.0-stage → 0.2.0

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