weapp-tailwindcss 5.2.13 → 5.3.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.
Files changed (62) hide show
  1. package/README.md +55 -8
  2. package/README.zh-CN.md +64 -0
  3. package/dist/bundlers/rspack/rule-match.d.ts +13 -0
  4. package/dist/bundlers/shared/source-candidates/scan-root.d.ts +1 -1
  5. package/dist/bundlers/shared/source-candidates/types-and-cache.d.ts +2 -0
  6. package/dist/bundlers/vite/generate-bundle/root-style-output.d.ts +7 -0
  7. package/dist/bundlers/vite/shared/create-framework-plugins.d.ts +1 -0
  8. package/dist/bundlers/vite/shared/framework-plugin-order.d.ts +2 -0
  9. package/dist/bundlers/vite/shared/framework-source-scan-session.d.ts +2 -2
  10. package/dist/{transform-BiHG42Rp.cjs → component-local-style-BirkN5f8.cjs} +33 -168
  11. package/dist/{transform-52FLRu-0.js → component-local-style-CFL4ClhS.js} +22 -174
  12. package/dist/generator/index.d.ts +2 -2
  13. package/dist/generator.cjs +7 -0
  14. package/dist/generator.js +2 -2
  15. package/dist/{gulp-DxKLSgXX.cjs → gulp-B0qcNiuP.cjs} +2 -2
  16. package/dist/{gulp-G--cGMcR.js → gulp-D1vDx4H1.js} +1 -1
  17. package/dist/gulp.cjs +1 -1
  18. package/dist/gulp.js +1 -1
  19. package/dist/{hmr-timing-iTua_Z55.js → hmr-timing-Dq1_msos.js} +19 -15
  20. package/dist/{hmr-timing-BtqnyxAO.cjs → hmr-timing-pF6k35pP.cjs} +1 -1
  21. package/dist/index.cjs +3 -3
  22. package/dist/index.js +3 -3
  23. package/dist/{pipeline-helpers-DnYpfbat.cjs → pipeline-helpers-DA5-EzbO.cjs} +1 -1
  24. package/dist/rspack.cjs +124 -7
  25. package/dist/rspack.js +124 -7
  26. package/dist/{source-candidate-scan-signature-Ggn8fzkT.cjs → source-candidate-scan-signature-DGQufJk3.cjs} +1 -1
  27. package/dist/{source-candidate-scan-signature-TKJIs7VF.js → source-candidate-scan-signature-DSsjYtlq.js} +1 -1
  28. package/dist/tailwindcss/candidates.d.ts +2 -2
  29. package/dist/transform-BYhgJszj.cjs +200 -0
  30. package/dist/transform-Ck31voUU.js +201 -0
  31. package/dist/uni-app-x/component-local-style.d.ts +3 -1
  32. package/dist/uni-app-x/transform.d.ts +2 -0
  33. package/dist/uni-app-x/vite/style-request.d.ts +1 -0
  34. package/dist/uni-app-x/vite/web-local-style.d.ts +6 -0
  35. package/dist/{v4-generation-core-D-zVR2mt.cjs → v4-generation-core-BEYGV4eB.cjs} +19 -15
  36. package/dist/{vite-B577QMUl.js → vite-DBgbFsei.js} +240 -82
  37. package/dist/{vite-BFWJAH16.cjs → vite-jftHIupF.cjs} +240 -82
  38. package/dist/vite.cjs +1 -1
  39. package/dist/vite.js +1 -1
  40. package/dist/weapp-tw-css-import-rewrite-loader.cjs +2 -2
  41. package/dist/{webpack-DLJkStre.js → webpack-BSIWFzAA.js} +3 -3
  42. package/dist/{webpack-DTqFKvcE.cjs → webpack-DhwW2cva.cjs} +4 -4
  43. package/dist/webpack.cjs +1 -1
  44. package/dist/webpack.js +1 -1
  45. package/package.json +9 -14
  46. package/README.en.md +0 -17
  47. package/bin/weapp-tailwindcss.cjs +0 -8
  48. package/dist/cli/context.d.ts +0 -3
  49. package/dist/cli/doctor/constants.d.ts +0 -7
  50. package/dist/cli/doctor/types.d.ts +0 -31
  51. package/dist/cli/doctor.d.ts +0 -4
  52. package/dist/cli/helpers/options/format.d.ts +0 -2
  53. package/dist/cli/helpers/options/parse.d.ts +0 -3
  54. package/dist/cli/helpers/options/resolve.d.ts +0 -1
  55. package/dist/cli/helpers/options.d.ts +0 -3
  56. package/dist/cli/helpers.d.ts +0 -4
  57. package/dist/cli/mount-options.d.ts +0 -4
  58. package/dist/cli/types.d.ts +0 -15
  59. package/dist/cli/vscode-entry.d.ts +0 -14
  60. package/dist/cli.cjs +0 -37065
  61. package/dist/cli.d.ts +0 -1
  62. package/dist/cli.js +0 -2298
package/dist/cli.js DELETED
@@ -1,2298 +0,0 @@
1
- import { createRequire } from "node:module";
2
- import process from "node:process";
3
- import semver from "semver";
4
- import path from "node:path";
5
- import { access, mkdir, writeFile } from "node:fs/promises";
6
- import { logger } from "@weapp-tailwindcss/logger";
7
- import { LRUCache } from "lru-cache";
8
- import { md5 as md5Hash } from "@weapp-tailwindcss/shared/node";
9
- import { MappingChars2String, escape } from "@weapp-core/escape";
10
- import "@weapp-tailwindcss/shared";
11
- import { constants, existsSync, readFileSync } from "node:fs";
12
- import _createDebug from "debug";
13
- import { splitCandidateTokens } from "@tailwindcss-mangle/engine";
14
- import { createStyleHandler } from "@weapp-tailwindcss/postcss";
15
- import "micromatch";
16
- import "fast-glob";
17
- import "tailwindcss-config";
18
- import _babelTraverse from "@babel/traverse";
19
- import { parse } from "@babel/parser";
20
- import MagicString from "magic-string";
21
- import "oxc-walker";
22
- import "@babel/types";
23
- import "htmlparser2";
24
- //#region src/js/babel/cache-options.ts
25
- const DEFAULT_PARSE_CACHE_MAX_SOURCE_LENGTH = 5e4;
26
- const HARD_PARSE_CACHE_MAX_ENTRIES = 1024;
27
- //#endregion
28
- //#region src/debug/index.ts
29
- const _debug = _createDebug("weapp-tw");
30
- function createDebug(prefix) {
31
- const debug = ((formatter, ...args) => {
32
- return _debug((prefix ?? "") + formatter, ...args);
33
- });
34
- Object.defineProperty(debug, "enabled", {
35
- enumerable: false,
36
- configurable: false,
37
- get() {
38
- return _debug.enabled;
39
- }
40
- });
41
- return debug;
42
- }
43
- //#endregion
44
- //#region src/tailwindcss/v4-engine/generator/rpx-candidates.ts
45
- const RPX_LENGTH_UTILITY_PATTERN = String.raw`text|border(?:-[trblxyse])?|bg|outline|ring`;
46
- new RegExp(String.raw`(^|:)(!?)(${RPX_LENGTH_UTILITY_PATTERN})-\[([-+]?(?:\d+|\d*\.\d+)rpx)\](.*)$`, "u");
47
- new RegExp(String.raw`(?:^|:)!?(${RPX_LENGTH_UTILITY_PATTERN})-\[length:([-+]?(?:\d+|\d*\.\d+)rpx)\].*$`, "u");
48
- new RegExp(String.raw`(${RPX_LENGTH_UTILITY_PATTERN})-\\\[length\\:((?:\\[.+-]|[+\-.\d])+rpx)\\\]`, "g");
49
- new LRUCache({ max: 8 });
50
- new LRUCache({ max: 32 });
51
- createStyleHandler({
52
- cssChildCombinatorReplaceValue: ["view", "text"],
53
- cssRemoveActivePseudoClass: true,
54
- cssRemoveHoverPseudoClass: true,
55
- cssRemoveFocusPseudoClass: true,
56
- isMainChunk: true,
57
- majorVersion: 4
58
- });
59
- createRequire(import.meta.url);
60
- //#endregion
61
- //#region \0@oxc-project+runtime@0.143.0/helpers/esm/typeof.js
62
- function _typeof(o) {
63
- "@babel/helpers - typeof";
64
- return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
65
- return typeof o;
66
- } : function(o) {
67
- return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
68
- }, _typeof(o);
69
- }
70
- //#endregion
71
- //#region \0@oxc-project+runtime@0.143.0/helpers/esm/toPrimitive.js
72
- function toPrimitive(t, r) {
73
- if ("object" != _typeof(t) || !t) return t;
74
- var e = t[Symbol.toPrimitive];
75
- if (void 0 !== e) {
76
- var i = e.call(t, r || "default");
77
- if ("object" != _typeof(i)) return i;
78
- throw new TypeError("@@toPrimitive must return a primitive value.");
79
- }
80
- return ("string" === r ? String : Number)(t);
81
- }
82
- //#endregion
83
- //#region \0@oxc-project+runtime@0.143.0/helpers/esm/toPropertyKey.js
84
- function toPropertyKey(t) {
85
- var i = toPrimitive(t, "string");
86
- return "symbol" == _typeof(i) ? i : i + "";
87
- }
88
- //#endregion
89
- //#region \0@oxc-project+runtime@0.143.0/helpers/esm/defineProperty.js
90
- function _defineProperty(e, r, t) {
91
- return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
92
- value: t,
93
- enumerable: !0,
94
- configurable: !0,
95
- writable: !0
96
- }) : e[r] = t, e;
97
- }
98
- //#endregion
99
- //#region src/tailwindcss/source-scan.ts
100
- const DEFAULT_SOURCE_SCAN_EXTENSIONS = [
101
- "html",
102
- "wxml",
103
- "axml",
104
- "jxml",
105
- "ksml",
106
- "ttml",
107
- "qml",
108
- "tyml",
109
- "xhsml",
110
- "swan",
111
- "vue",
112
- "mpx",
113
- "js",
114
- "jsx",
115
- "ts",
116
- "tsx"
117
- ];
118
- const FULL_SOURCE_SCAN_EXTENSIONS = [
119
- "js",
120
- "jsx",
121
- "mjs",
122
- "cjs",
123
- "ts",
124
- "tsx",
125
- "mts",
126
- "cts",
127
- "vue",
128
- "uvue",
129
- "nvue",
130
- "svelte",
131
- "mpx",
132
- "html",
133
- "wxml",
134
- "axml",
135
- "jxml",
136
- "ksml",
137
- "ttml",
138
- "qml",
139
- "tyml",
140
- "xhsml",
141
- "swan",
142
- "css",
143
- "wxss",
144
- "acss",
145
- "jxss",
146
- "ttss",
147
- "qss",
148
- "tyss",
149
- "scss",
150
- "sass",
151
- "less",
152
- "styl",
153
- "stylus"
154
- ];
155
- function createSourceScanPattern(extensions = DEFAULT_SOURCE_SCAN_EXTENSIONS) {
156
- return `**/*.{${extensions.join(",")}}`;
157
- }
158
- createSourceScanPattern(FULL_SOURCE_SCAN_EXTENSIONS);
159
- new RegExp(`\\.(?:${FULL_SOURCE_SCAN_EXTENSIONS.map((extension) => extension.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|")})$`);
160
- //#endregion
161
- //#region src/utils/object.ts
162
- function definedEntries(value) {
163
- return Object.entries(value).filter(([, item]) => item !== void 0);
164
- }
165
- function omitUndefined(value) {
166
- return Object.fromEntries(definedEntries(value));
167
- }
168
- createRequire(import.meta.url);
169
- createDebug("[tailwindcss:runtime] ");
170
- //#endregion
171
- //#region src/tailwindcss/runtime-logs.ts
172
- const runtimeLogDedupeHolder = globalThis;
173
- runtimeLogDedupeHolder.__WEAPP_TW_RUNTIME_LOG_DEDUPE__ ?? (runtimeLogDedupeHolder.__WEAPP_TW_RUNTIME_LOG_DEDUPE__ = /* @__PURE__ */ new Set());
174
- createRequire(import.meta.url);
175
- //#endregion
176
- //#region src/context/compiler-context-cache.ts
177
- const globalCacheHolder = globalThis;
178
- globalCacheHolder.__WEAPP_TW_COMPILER_CONTEXT_CACHE__ ?? (globalCacheHolder.__WEAPP_TW_COMPILER_CONTEXT_CACHE__ = /* @__PURE__ */ new Map());
179
- //#endregion
180
- //#region src/babel/index.ts
181
- function _interopDefaultCompat(e) {
182
- return e && typeof e === "object" && "default" in e ? e.default : e;
183
- }
184
- const traverse = _interopDefaultCompat(_babelTraverse);
185
- //#endregion
186
- //#region src/utils/regex.ts
187
- function escapeStringRegexp(str) {
188
- if (typeof str !== "string") throw new TypeError("Expected a string");
189
- return str.replaceAll(/[$()*+.?[\\\]^{|}]/g, "\\$&").replaceAll("-", "\\x2d");
190
- }
191
- //#endregion
192
- //#region src/utils/nameMatcher.ts
193
- const NEVER_MATCH_NAME$1 = () => false;
194
- const GLOBAL_FLAG_REGEXP = /g/g;
195
- function buildFuzzyMatcher(fuzzyStrings) {
196
- if (fuzzyStrings.length === 0) return;
197
- if (fuzzyStrings.length === 1) {
198
- const [needle] = fuzzyStrings;
199
- if (needle === void 0) return;
200
- return (value) => value.includes(needle);
201
- }
202
- const unique = [...new Set(fuzzyStrings)];
203
- const pattern = new RegExp(unique.map(escapeStringRegexp).join("|"));
204
- return (value) => pattern.test(value);
205
- }
206
- function normaliseRegex(regex) {
207
- const { source, flags } = regex;
208
- if (!flags.includes("g")) return regex;
209
- return new RegExp(source, flags.replace(GLOBAL_FLAG_REGEXP, ""));
210
- }
211
- function createNameMatcher(list, { exact = false } = {}) {
212
- if (!list || list.length === 0) return NEVER_MATCH_NAME$1;
213
- const exactStrings = exact ? /* @__PURE__ */ new Set() : void 0;
214
- const fuzzyStrings = [];
215
- const regexList = [];
216
- for (const item of list) if (typeof item === "string") {
217
- if (exact) exactStrings.add(item);
218
- else fuzzyStrings.push(item);
219
- } else regexList.push(normaliseRegex(item));
220
- if (exact) {
221
- const exactStringCount = exactStrings?.size ?? 0;
222
- if (exactStringCount === 1 && regexList.length === 0) {
223
- const [needle] = exactStrings;
224
- if (needle === void 0) return NEVER_MATCH_NAME$1;
225
- return (value) => value === needle;
226
- }
227
- if (regexList.length === 0) return (value) => exactStrings.has(value);
228
- if (exactStringCount === 0 && regexList.length === 1) {
229
- const [regex] = regexList;
230
- if (!regex) return NEVER_MATCH_NAME$1;
231
- return (value) => regex.test(value);
232
- }
233
- return (value) => {
234
- if (exactStrings?.has(value)) return true;
235
- return regexList.some((regex) => regex.test(value));
236
- };
237
- }
238
- const fuzzyMatcher = exact ? void 0 : buildFuzzyMatcher(fuzzyStrings);
239
- const hasRegex = regexList.length > 0;
240
- if (fuzzyMatcher && !hasRegex) return fuzzyMatcher;
241
- if (!fuzzyMatcher && regexList.length === 1) {
242
- const [regex] = regexList;
243
- if (!regex) return NEVER_MATCH_NAME$1;
244
- return (value) => regex.test(value);
245
- }
246
- return (value) => {
247
- if (fuzzyMatcher?.(value)) return true;
248
- if (!hasRegex) return false;
249
- return regexList.some((regex) => regex.test(value));
250
- };
251
- }
252
- //#endregion
253
- //#region src/js/babel/parse.ts
254
- const parseCache = new LRUCache({ max: HARD_PARSE_CACHE_MAX_ENTRIES });
255
- function genCacheKey(source, options) {
256
- if (typeof options === "string") return `${md5Hash(source)}:${options}`;
257
- return `${md5Hash(source)}:${JSON.stringify(options, (_, val) => typeof val === "function" ? val.toString() : val)}`;
258
- }
259
- function normalizeCacheMaxEntries(value) {
260
- if (typeof value !== "number" || !Number.isFinite(value)) return 128;
261
- return Math.min(Math.max(Math.floor(value), 0), HARD_PARSE_CACHE_MAX_ENTRIES);
262
- }
263
- function normalizeCacheMaxSourceLength(value) {
264
- if (typeof value !== "number" || !Number.isFinite(value)) return DEFAULT_PARSE_CACHE_MAX_SOURCE_LENGTH;
265
- return Math.max(Math.floor(value), 0);
266
- }
267
- function trimParseCache(maxEntries) {
268
- while (parseCache.size > maxEntries) parseCache.pop();
269
- }
270
- function babelParse(code, opts = {}) {
271
- const { cache, cacheKey, cacheMaxEntries, cacheMaxSourceLength, ...rest } = opts;
272
- const maxEntries = normalizeCacheMaxEntries(cacheMaxEntries);
273
- const maxSourceLength = normalizeCacheMaxSourceLength(cacheMaxSourceLength);
274
- const shouldCache = cache === true && maxEntries > 0 && code.length <= maxSourceLength;
275
- const cacheKeyString = shouldCache ? genCacheKey(code, cacheKey ?? rest) : void 0;
276
- let result;
277
- if (shouldCache) {
278
- trimParseCache(maxEntries);
279
- result = parseCache.get(cacheKeyString);
280
- }
281
- if (!result) {
282
- const { cache: _cache, cacheKey: _cacheKey, cacheMaxEntries: _cacheMaxEntries, cacheMaxSourceLength: _cacheMaxSourceLength, ...parseOptions } = opts;
283
- result = parse(code, parseOptions);
284
- if (shouldCache) {
285
- parseCache.set(cacheKeyString, result);
286
- trimParseCache(maxEntries);
287
- }
288
- }
289
- return result;
290
- }
291
- //#endregion
292
- //#region src/wxml/shared.ts
293
- const NEWLINE_RE = /[\n\r]+/g;
294
- function replaceWxml(original, options = {
295
- keepEOL: false,
296
- escapeMap: MappingChars2String
297
- }) {
298
- const { keepEOL, escapeMap, ignoreHead } = options;
299
- let res = original;
300
- if (!keepEOL) res = res.replaceAll(NEWLINE_RE, "");
301
- res = escape(res, omitUndefined({
302
- map: escapeMap,
303
- ignoreHead
304
- }));
305
- return res;
306
- }
307
- //#endregion
308
- //#region src/shared/classname-transform.ts
309
- const escapedCandidateCacheByEscapeMap = /* @__PURE__ */ new WeakMap();
310
- const defaultEscapedCandidateCache = /* @__PURE__ */ new Map();
311
- let lastEscapedCandidateEscapeMap;
312
- let lastEscapedCandidateCacheStore;
313
- function isUrlLikeCandidate(candidate) {
314
- return candidate.startsWith("//") || candidate.startsWith("http://") || candidate.startsWith("https://");
315
- }
316
- function isPlainSlashPathCandidate(candidate) {
317
- const slashIndex = candidate.indexOf("/");
318
- if (slashIndex <= 0) return false;
319
- if (isUrlLikeCandidate(candidate)) return true;
320
- if (candidate.includes("[") || candidate.includes("]") || candidate.includes(":")) return false;
321
- return !candidate.slice(0, slashIndex).includes("-");
322
- }
323
- const SKIP_RESULT = { decision: "skip" };
324
- const DIRECT_RESULT = { decision: "direct" };
325
- function getEscapedCandidateCacheStore(escapeMap) {
326
- if (!escapeMap) return defaultEscapedCandidateCache;
327
- if (escapeMap === lastEscapedCandidateEscapeMap && lastEscapedCandidateCacheStore) return lastEscapedCandidateCacheStore;
328
- let store = escapedCandidateCacheByEscapeMap.get(escapeMap);
329
- if (!store) {
330
- store = /* @__PURE__ */ new Map();
331
- escapedCandidateCacheByEscapeMap.set(escapeMap, store);
332
- }
333
- lastEscapedCandidateEscapeMap = escapeMap;
334
- lastEscapedCandidateCacheStore = store;
335
- return store;
336
- }
337
- function getEscapedCandidate(candidate, escapeMap, store = getEscapedCandidateCacheStore(escapeMap)) {
338
- let cached = store.get(candidate);
339
- if (cached === void 0) {
340
- cached = replaceWxml(candidate, { escapeMap });
341
- store.set(candidate, cached);
342
- }
343
- return cached;
344
- }
345
- /**
346
- * JS 转译严格遵循 runtime class set:
347
- * 1. 直接命中 classNameSet 原始值;
348
- * 2. 兼容命中 classNameSet 中已转义值;
349
- * 3. 除显式 alwaysEscape 外,不允许绕过 classNameSet。
350
- *
351
- * 返回结构化结果,附带已计算的 escapedValue 以避免下游重复 escape。
352
- */
353
- function resolveClassNameTransformWithResult(candidate, { alwaysEscape, classNameSet, escapeMap, jsPreserveClass, classContext }) {
354
- if (jsPreserveClass?.(candidate)) return SKIP_RESULT;
355
- if (alwaysEscape) return DIRECT_RESULT;
356
- if (!classContext && isPlainSlashPathCandidate(candidate)) return SKIP_RESULT;
357
- if (classNameSet?.has(candidate)) return DIRECT_RESULT;
358
- if (classNameSet && classNameSet.size > 0) {
359
- const escapedCandidate = getEscapedCandidate(candidate, escapeMap);
360
- if (escapedCandidate !== candidate && classNameSet.has(escapedCandidate)) return {
361
- decision: "escaped",
362
- escapedValue: escapedCandidate
363
- };
364
- }
365
- return SKIP_RESULT;
366
- }
367
- //#endregion
368
- //#region src/utils/decode.ts
369
- const unicodeEscapeRE = /\\u([\dA-Fa-f]{4})/g;
370
- const unicodeEscapeTestRE = /\\u[\dA-Fa-f]{4}/;
371
- function decodeUnicode(value) {
372
- if (!unicodeEscapeTestRE.test(value)) return value;
373
- return value.replace(unicodeEscapeRE, (_match, hex) => {
374
- const codePoint = Number.parseInt(hex, 16);
375
- return Number.isNaN(codePoint) ? _match : String.fromCharCode(codePoint);
376
- });
377
- }
378
- function decodeUnicode2(input) {
379
- if (!unicodeEscapeTestRE.test(input)) return input;
380
- try {
381
- return JSON.parse(`"${input}"`);
382
- } catch (_error) {
383
- return decodeUnicode(input);
384
- }
385
- }
386
- //#endregion
387
- //#region src/js/class-context.ts
388
- const CLASS_LIKE_KEYWORDS = /* @__PURE__ */ new Set([
389
- "class",
390
- "classname",
391
- "hoverclass",
392
- "virtualhostclass",
393
- "rootclass"
394
- ]);
395
- const CLASS_HELPER_IDENTIFIERS = /* @__PURE__ */ new Set([
396
- "cn",
397
- "clsx",
398
- "classnames",
399
- "twmerge",
400
- "cva",
401
- "tv",
402
- "cx",
403
- "r"
404
- ]);
405
- const DASH_CODE = 45;
406
- const COLON_CODE = 58;
407
- const UPPERCASE_A_CODE = 65;
408
- const UPPERCASE_Z_CODE = 90;
409
- const UNDERSCORE_CODE = 95;
410
- const ASCII_MAX_CODE = 127;
411
- const NORMALIZE_KEYWORD_REGEXP = /[-_:]/g;
412
- function normalizeKeyword(name) {
413
- const length = name.length;
414
- let firstNormalizedIndex = -1;
415
- for (let i = 0; i < length; i++) {
416
- const code = name.charCodeAt(i);
417
- if (code === DASH_CODE || code === UNDERSCORE_CODE || code === COLON_CODE || code >= UPPERCASE_A_CODE && code <= UPPERCASE_Z_CODE) {
418
- firstNormalizedIndex = i;
419
- break;
420
- }
421
- if (code > ASCII_MAX_CODE) return name.replace(NORMALIZE_KEYWORD_REGEXP, "").toLowerCase();
422
- }
423
- if (firstNormalizedIndex === -1) return name;
424
- let normalized = name.slice(0, firstNormalizedIndex);
425
- for (let i = firstNormalizedIndex; i < length; i++) {
426
- const code = name.charCodeAt(i);
427
- if (code === DASH_CODE || code === UNDERSCORE_CODE || code === COLON_CODE) continue;
428
- if (code >= UPPERCASE_A_CODE && code <= UPPERCASE_Z_CODE) {
429
- normalized += String.fromCharCode(code + 32);
430
- continue;
431
- }
432
- if (code > ASCII_MAX_CODE) return name.replace(NORMALIZE_KEYWORD_REGEXP, "").toLowerCase();
433
- normalized += name[i];
434
- }
435
- return normalized;
436
- }
437
- function readObjectKeyName(path) {
438
- if (path.isIdentifier()) return path.node.name;
439
- if (path.isStringLiteral()) return path.node.value;
440
- if (path.isTemplateLiteral() && path.node.expressions.length === 0) return path.node.quasis[0]?.value.cooked ?? path.node.quasis[0]?.value.raw;
441
- }
442
- function isClassLikeObjectProperty(path, valuePath) {
443
- if (!path.isObjectProperty()) return false;
444
- if (path.get("value") !== valuePath) return false;
445
- const keyName = readObjectKeyName(path.get("key"));
446
- if (!keyName) return false;
447
- return CLASS_LIKE_KEYWORDS.has(normalizeKeyword(keyName));
448
- }
449
- function isClassLikeJsxAttribute(path) {
450
- if (!path.isJSXAttribute()) return false;
451
- const namePath = path.get("name");
452
- if (!namePath.isJSXIdentifier()) return false;
453
- return CLASS_LIKE_KEYWORDS.has(normalizeKeyword(namePath.node.name));
454
- }
455
- function readCallHelperName(calleePath) {
456
- if (calleePath.isIdentifier()) return calleePath.node.name;
457
- if (calleePath.isMemberExpression()) {
458
- const propertyPath = calleePath.get("property");
459
- if (propertyPath.isIdentifier()) return propertyPath.node.name;
460
- if (propertyPath.isStringLiteral()) return propertyPath.node.value;
461
- }
462
- }
463
- function isClassLikeCallExpression(path, valuePath) {
464
- if (!path.isCallExpression()) return false;
465
- const helperName = readCallHelperName(path.get("callee"));
466
- if (!helperName || !CLASS_HELPER_IDENTIFIERS.has(normalizeKeyword(helperName))) return false;
467
- return path.get("arguments").some((argumentPath) => argumentPath.node === valuePath.node);
468
- }
469
- /**
470
- * 判断字符串字面量是否处于 class 语义上下文。
471
- * 仅用于受控兜底场景,避免将普通业务文本误判为 class。
472
- */
473
- function isClassContextLiteralPath(path) {
474
- let current = path;
475
- while (current.parentPath) {
476
- const parent = current.parentPath;
477
- if (isClassLikeObjectProperty(parent, current)) return true;
478
- if (isClassLikeJsxAttribute(parent)) return true;
479
- if (isClassLikeCallExpression(parent, current)) return true;
480
- current = parent;
481
- }
482
- return false;
483
- }
484
- //#endregion
485
- //#region src/js/js-string-escape.ts
486
- function jsStringEscape(value) {
487
- return String(value).replaceAll(/[\n\r"'\\\u2028\u2029]/g, (character) => {
488
- switch (character) {
489
- case "\"":
490
- case "'":
491
- case "\\": return `\\${character}`;
492
- case "\n": return "\\n";
493
- case "\r": return "\\r";
494
- case "\u2028": return "\\u2028";
495
- case "\u2029": return "\\u2029";
496
- default: return character;
497
- }
498
- });
499
- }
500
- //#endregion
501
- //#region src/js/replacement-cache.ts
502
- const replacementCacheByEscapeMap = /* @__PURE__ */ new WeakMap();
503
- const defaultReplacementCache = /* @__PURE__ */ new Map();
504
- function getReplacementCacheStore(escapeMap) {
505
- if (!escapeMap) return defaultReplacementCache;
506
- let store = replacementCacheByEscapeMap.get(escapeMap);
507
- if (!store) {
508
- store = /* @__PURE__ */ new Map();
509
- replacementCacheByEscapeMap.set(escapeMap, store);
510
- }
511
- return store;
512
- }
513
- function getReplacement(candidate, escapeMap, store = getReplacementCacheStore(escapeMap)) {
514
- let cached = store.get(candidate);
515
- if (cached === void 0) {
516
- cached = replaceWxml(candidate, { escapeMap });
517
- store.set(candidate, cached);
518
- }
519
- return cached;
520
- }
521
- //#endregion
522
- //#region src/js/handlers.ts
523
- const debug = createDebug("[js:handlers] ");
524
- const WEAPP_TW_IGNORE_MARKER = "weapp-tw";
525
- const IGNORE_MARKER = "ignore";
526
- function hasIgnoreComment(node) {
527
- const { leadingComments } = node;
528
- if (!Array.isArray(leadingComments) || leadingComments.length === 0) return false;
529
- for (const comment of leadingComments) {
530
- const { value } = comment;
531
- if (value.includes(WEAPP_TW_IGNORE_MARKER) && value.includes(IGNORE_MARKER)) return true;
532
- }
533
- return false;
534
- }
535
- function isConditionTestLiteral(path) {
536
- let current = path;
537
- while (current?.parentPath) {
538
- const parent = current.parentPath;
539
- if (parent.isConditionalExpression()) return parent.node.test === current.node;
540
- if (parent.isBinaryExpression() || parent.isCallExpression() || parent.isLogicalExpression() || parent.isMemberExpression() || parent.isUnaryExpression()) {
541
- current = parent;
542
- continue;
543
- }
544
- return false;
545
- }
546
- return false;
547
- }
548
- function extractLiteralValue(path, { unescapeUnicode }) {
549
- const { node } = path;
550
- let offset = 0;
551
- let original;
552
- if (node.type === "StringLiteral") {
553
- offset = 1;
554
- original = node.value;
555
- } else if (node.type === "TemplateElement") original = node.value.raw;
556
- else original = "";
557
- let literal = original;
558
- if (unescapeUnicode && original.includes("\\u")) literal = decodeUnicode2(original);
559
- return {
560
- literal,
561
- offset,
562
- original
563
- };
564
- }
565
- function createCandidatePlanResolver(options, classContext) {
566
- const { escapeMap } = options;
567
- const replacementCache = getReplacementCacheStore(escapeMap);
568
- const transformOptions = classContext ? {
569
- ...options,
570
- classContext
571
- } : options;
572
- let firstCandidate = "";
573
- let firstPlan;
574
- let cache;
575
- const buildCandidatePlan = (candidate) => {
576
- const result = resolveClassNameTransformWithResult(candidate, transformOptions);
577
- if (result.decision === "skip") return { result };
578
- let replacement;
579
- if (result.decision === "escaped" && result.escapedValue) {
580
- replacement = result.escapedValue;
581
- replacementCache.set(candidate, replacement);
582
- } else replacement = getReplacement(candidate, escapeMap, replacementCache);
583
- return {
584
- result,
585
- replacement
586
- };
587
- };
588
- return (candidate) => {
589
- if (cache) {
590
- const cached = cache.get(candidate);
591
- if (cached) return cached;
592
- } else if (firstPlan && candidate === firstCandidate) return firstPlan;
593
- const plan = buildCandidatePlan(candidate);
594
- if (!firstPlan) {
595
- firstCandidate = candidate;
596
- firstPlan = plan;
597
- return plan;
598
- }
599
- if (!cache) {
600
- cache = /* @__PURE__ */ new Map();
601
- cache.set(firstCandidate, firstPlan);
602
- }
603
- cache.set(candidate, plan);
604
- return plan;
605
- };
606
- }
607
- function replaceHandleValue(path, options) {
608
- const { needEscaped = false } = options;
609
- const { classNameSet, alwaysEscape } = options;
610
- if (!alwaysEscape && (!classNameSet || classNameSet.size === 0)) return;
611
- if (hasIgnoreComment(path.node)) return;
612
- if (isConditionTestLiteral(path)) return;
613
- const { literal, original, offset } = extractLiteralValue(path, options);
614
- const candidates = splitCandidateTokens(literal);
615
- if (candidates.length === 0) return;
616
- const debugEnabled = debug.enabled;
617
- const classContext = options.wrapExpression || isClassContextLiteralPath(path);
618
- let transformed = literal;
619
- let mutated = false;
620
- let matchedCandidateCount = 0;
621
- let escapedDecisionCount = 0;
622
- let escapedSamples;
623
- let skippedSamples;
624
- const resolveCandidatePlan = createCandidatePlanResolver(options, classContext);
625
- for (const candidate of candidates) {
626
- const plan = resolveCandidatePlan(candidate);
627
- if (plan.result.decision === "skip") {
628
- if (debugEnabled) {
629
- if (!skippedSamples) skippedSamples = [];
630
- if (skippedSamples.length < 6) skippedSamples.push(candidate);
631
- }
632
- continue;
633
- }
634
- if (debugEnabled) {
635
- matchedCandidateCount += 1;
636
- if (plan.result.decision === "escaped") {
637
- escapedDecisionCount += 1;
638
- if (!escapedSamples) escapedSamples = [];
639
- if (escapedSamples.length < 6) escapedSamples.push(candidate);
640
- }
641
- }
642
- const replaced = transformed.replace(candidate, plan.replacement);
643
- if (replaced !== transformed) {
644
- transformed = replaced;
645
- mutated = true;
646
- }
647
- }
648
- const node = path.node;
649
- if (!mutated || typeof node.start !== "number" || typeof node.end !== "number") return;
650
- if (debugEnabled) debug("runtimeSet size=%d candidates=%d matched=%d escapedHits=%d skipped=%d file=%s escapedSamples=%s skippedSamples=%s", classNameSet?.size ?? 0, candidates.length, matchedCandidateCount, escapedDecisionCount, skippedSamples?.length ?? 0, options.filename ?? "unknown", escapedSamples?.join(",") || "-", skippedSamples?.join(",") || "-");
651
- const start = node.start + offset;
652
- const end = node.end - offset;
653
- if (start >= end || transformed === original) return;
654
- return {
655
- start,
656
- end,
657
- value: needEscaped ? jsStringEscape(transformed) : transformed,
658
- path
659
- };
660
- }
661
- //#endregion
662
- //#region src/js/sourceAnalysis.ts
663
- function hasReplacementEntries(replacements) {
664
- for (const key in replacements) if (Object.hasOwn(replacements, key)) return true;
665
- return false;
666
- }
667
- function createModuleSpecifierReplacementToken(path, replacement) {
668
- const node = path.node;
669
- if (node.value === replacement) return;
670
- if (typeof node.start !== "number" || typeof node.end !== "number") return;
671
- const start = node.start + 1;
672
- const end = node.end - 1;
673
- if (start >= end) return;
674
- return {
675
- start,
676
- end,
677
- value: replacement,
678
- path
679
- };
680
- }
681
- function collectModuleSpecifierReplacementTokens(analysis, replacements) {
682
- if (!hasReplacementEntries(replacements)) return [];
683
- if (analysis.importDeclarations.size === 0 && analysis.exportDeclarations.size === 0 && analysis.requireCallPaths.length === 0 && analysis.walker.imports.size === 0) return [];
684
- const tokens = [];
685
- const applyReplacement = (path) => {
686
- const replacement = replacements[path.node.value];
687
- if (!replacement) return;
688
- const token = createModuleSpecifierReplacementToken(path, replacement);
689
- if (token) tokens.push(token);
690
- };
691
- for (const importPath of analysis.importDeclarations) {
692
- const source = importPath.get("source");
693
- if (source.isStringLiteral()) applyReplacement(source);
694
- }
695
- for (const exportPath of analysis.exportDeclarations) if (exportPath.isExportNamedDeclaration() || exportPath.isExportAllDeclaration()) {
696
- const source = exportPath.get("source");
697
- if (source && !Array.isArray(source) && source.isStringLiteral()) applyReplacement(source);
698
- }
699
- for (const literalPath of analysis.requireCallPaths) applyReplacement(literalPath);
700
- for (const token of analysis.walker.imports) {
701
- const replacement = replacements[token.source];
702
- if (replacement) token.source = replacement;
703
- }
704
- return tokens;
705
- }
706
- //#endregion
707
- //#region src/js/babel/process.ts
708
- const optionVariantsCache = /* @__PURE__ */ new WeakMap();
709
- function getNeedEscapedOptions(options, needEscaped) {
710
- if (options.needEscaped === needEscaped) return options;
711
- let cached = optionVariantsCache.get(options);
712
- if (!cached) {
713
- cached = {};
714
- optionVariantsCache.set(options, cached);
715
- }
716
- if (needEscaped) {
717
- if (!cached.stringLiteralOptions) cached.stringLiteralOptions = {
718
- ...options,
719
- needEscaped: true
720
- };
721
- return cached.stringLiteralOptions;
722
- }
723
- if (!cached.templateLiteralOptions) cached.templateLiteralOptions = {
724
- ...options,
725
- needEscaped: false
726
- };
727
- return cached.templateLiteralOptions;
728
- }
729
- function processUpdatedSource(rawSource, options, analysis) {
730
- const { targetPaths, jsTokenUpdater, ignoredPaths } = analysis;
731
- if (targetPaths.length === 0 && !options.moduleSpecifierReplacements && jsTokenUpdater.length === 0) return new MagicString(rawSource);
732
- const replacementTokens = [];
733
- for (const path of targetPaths) {
734
- if (ignoredPaths.has(path)) continue;
735
- const token = replaceHandleValue(path, path.isStringLiteral() ? getNeedEscapedOptions(options, true) : getNeedEscapedOptions(options, false));
736
- if (token) replacementTokens.push(token);
737
- }
738
- if (options.moduleSpecifierReplacements) replacementTokens.push(...collectModuleSpecifierReplacementTokens(analysis, options.moduleSpecifierReplacements));
739
- if (jsTokenUpdater.length + replacementTokens.length === 0) return new MagicString(rawSource);
740
- const ms = new MagicString(rawSource);
741
- jsTokenUpdater.push(...replacementTokens).filter((token) => !ignoredPaths.has(token.path)).updateMagicString(ms);
742
- return ms;
743
- }
744
- //#endregion
745
- //#region src/js/evalTransforms.ts
746
- const evalHandlerOptionsCache = /* @__PURE__ */ new WeakMap();
747
- const EVAL_SCOPE_ERROR_REGEXP = /pass a scope and parentPath|traversing a Program\/File/i;
748
- function isEvalPath(path) {
749
- if (path.isCallExpression()) return path.get("callee").isIdentifier({ name: "eval" });
750
- return false;
751
- }
752
- function createEvalReplacementToken(path, updated) {
753
- const node = path.node;
754
- let offset = 0;
755
- let original;
756
- if (path.isStringLiteral()) {
757
- offset = 1;
758
- original = path.node.value;
759
- } else if (path.isTemplateElement()) original = path.node.value.raw;
760
- else original = "";
761
- if (typeof node.start !== "number" || typeof node.end !== "number") return;
762
- const start = node.start + offset;
763
- const end = node.end - offset;
764
- if (start >= end) return;
765
- if (original === updated) return;
766
- return {
767
- start,
768
- end,
769
- value: path.isStringLiteral() ? jsStringEscape(updated) : updated,
770
- path
771
- };
772
- }
773
- function handleEvalStringLiteral(path, handlerOptions, updater, handler) {
774
- const { code } = handler(path.node.value, handlerOptions);
775
- if (!code) return;
776
- const token = createEvalReplacementToken(path, code);
777
- if (token) updater.addToken(token);
778
- }
779
- function handleEvalTemplateElement(path, handlerOptions, updater, handler) {
780
- const { code } = handler(path.node.value.raw, handlerOptions);
781
- if (!code) return;
782
- const token = createEvalReplacementToken(path, code);
783
- if (token) updater.addToken(token);
784
- }
785
- function getEvalStringHandlerOptions(options) {
786
- if (options.needEscaped === false && options.generateMap === false) return options;
787
- let cached = evalHandlerOptionsCache.get(options);
788
- if (!cached) {
789
- cached = {};
790
- evalHandlerOptionsCache.set(options, cached);
791
- }
792
- if (!cached.stringLiteralOptions) cached.stringLiteralOptions = {
793
- ...options,
794
- needEscaped: false,
795
- generateMap: false
796
- };
797
- return cached.stringLiteralOptions;
798
- }
799
- function getEvalTemplateHandlerOptions(options) {
800
- if (options.generateMap === false) return options;
801
- let cached = evalHandlerOptionsCache.get(options);
802
- if (!cached) {
803
- cached = {};
804
- evalHandlerOptionsCache.set(options, cached);
805
- }
806
- if (!cached.templateLiteralOptions) cached.templateLiteralOptions = {
807
- ...options,
808
- generateMap: false
809
- };
810
- return cached.templateLiteralOptions;
811
- }
812
- function walkEvalExpression(path, options, updater, handler) {
813
- const stringHandlerOptions = getEvalStringHandlerOptions(options);
814
- const templateHandlerOptions = getEvalTemplateHandlerOptions(options);
815
- const maybeTraverse = path?.traverse;
816
- if (typeof maybeTraverse === "function") try {
817
- return maybeTraverse.call(path, {
818
- StringLiteral(innerPath) {
819
- handleEvalStringLiteral(innerPath, stringHandlerOptions, updater, handler);
820
- },
821
- TemplateElement(innerPath) {
822
- handleEvalTemplateElement(innerPath, templateHandlerOptions, updater, handler);
823
- }
824
- });
825
- } catch (error) {
826
- const msg = error?.message ?? "";
827
- if (!EVAL_SCOPE_ERROR_REGEXP.test(msg)) throw error;
828
- }
829
- const getArgs = path?.get?.("arguments");
830
- if (Array.isArray(getArgs)) {
831
- for (const arg of getArgs) {
832
- if (arg?.isStringLiteral?.()) {
833
- handleEvalStringLiteral(arg, stringHandlerOptions, updater, handler);
834
- continue;
835
- }
836
- if (arg?.isTemplateLiteral?.()) for (const quasi of arg.get("quasis")) handleEvalTemplateElement(quasi, templateHandlerOptions, updater, handler);
837
- }
838
- return;
839
- }
840
- const nodeArgs = path?.node?.arguments;
841
- if (Array.isArray(nodeArgs)) {
842
- for (const n of nodeArgs) if (n?.type === "StringLiteral") handleEvalStringLiteral({
843
- node: n,
844
- isStringLiteral: () => true
845
- }, stringHandlerOptions, updater, handler);
846
- else if (n?.type === "TemplateLiteral" && Array.isArray(n.quasis)) for (const q of n.quasis) handleEvalTemplateElement({
847
- node: q,
848
- isStringLiteral: () => false,
849
- isTemplateElement: () => true
850
- }, templateHandlerOptions, updater, handler);
851
- }
852
- }
853
- //#endregion
854
- //#region src/js/JsTokenUpdater.ts
855
- /**
856
- * Lightweight helper that batches updates to {@link MagicString}.
857
- * It keeps the transformation logic out of the traversal code and makes
858
- * it easier to reason about the order in which tokens are written back.
859
- */
860
- var JsTokenUpdater = class {
861
- constructor({ value } = {}) {
862
- _defineProperty(this, "tokens", void 0);
863
- this.tokens = value ? [...value] : [];
864
- }
865
- addToken(token) {
866
- if (token) this.tokens.push(token);
867
- }
868
- push(...args) {
869
- this.tokens.push(...args);
870
- return this;
871
- }
872
- /**
873
- * 待写入的 token 数量。
874
- */
875
- get length() {
876
- return this.tokens.length;
877
- }
878
- map(callbackfn) {
879
- this.tokens = this.tokens.map(callbackfn);
880
- return this;
881
- }
882
- filter(callbackfn) {
883
- this.tokens = this.tokens.filter(callbackfn);
884
- return this;
885
- }
886
- updateMagicString(ms) {
887
- for (const { start, end, value } of this.tokens) ms.update(start, end, value);
888
- return ms;
889
- }
890
- };
891
- //#endregion
892
- //#region src/js/module-graph/ignored-exports.ts
893
- var IgnoredExportsTracker = class {
894
- constructor(options) {
895
- this.options = options;
896
- _defineProperty(this, "ignoredExportNames", /* @__PURE__ */ new Map());
897
- }
898
- addIgnoredExport(filename, exportName) {
899
- if (!exportName) return;
900
- let pending = this.ignoredExportNames.get(filename);
901
- if (!pending) {
902
- pending = /* @__PURE__ */ new Set();
903
- this.ignoredExportNames.set(filename, pending);
904
- }
905
- if (pending.has(exportName)) return;
906
- pending.add(exportName);
907
- const existing = this.options.modules.get(filename);
908
- if (existing) this.applyIgnoredExportsToAnalysis(filename, existing.analysis);
909
- }
910
- registerIgnoredExportsFromTokens(resolved, tokens) {
911
- for (const token of tokens) if (token.type === "ImportSpecifier") this.addIgnoredExport(resolved, token.imported);
912
- else if (token.type === "ImportDefaultSpecifier") this.addIgnoredExport(resolved, "default");
913
- }
914
- applyIgnoredExportsToAnalysis(filename, analysis) {
915
- const pending = this.ignoredExportNames.get(filename);
916
- if (!pending || pending.size === 0) return;
917
- const names = new Set(pending);
918
- pending.clear();
919
- const propagate = [];
920
- for (const exportPath of analysis.exportDeclarations) {
921
- if (names.size === 0) break;
922
- if (exportPath.isExportDefaultDeclaration()) {
923
- if (names.has("default")) {
924
- analysis.walker.walkExportDefaultDeclaration(exportPath);
925
- names.delete("default");
926
- }
927
- continue;
928
- }
929
- if (exportPath.isExportNamedDeclaration()) {
930
- const source = exportPath.node.source?.value;
931
- if (typeof source === "string") {
932
- for (const spec of exportPath.get("specifiers")) {
933
- if (!spec.isExportSpecifier()) continue;
934
- const exported = spec.get("exported");
935
- let exportedName;
936
- if (exported.isIdentifier()) exportedName = exported.node.name;
937
- else if (exported.isStringLiteral()) exportedName = exported.node.value;
938
- if (!exportedName || !names.has(exportedName)) continue;
939
- const local = spec.get("local");
940
- if (local.isIdentifier()) {
941
- propagate.push({
942
- specifier: source,
943
- exportName: local.node.name
944
- });
945
- names.delete(exportedName);
946
- } else if (local.isStringLiteral()) {
947
- propagate.push({
948
- specifier: source,
949
- exportName: local.node.value
950
- });
951
- names.delete(exportedName);
952
- }
953
- }
954
- continue;
955
- }
956
- const declaration = exportPath.get("declaration");
957
- if (declaration.isVariableDeclaration()) for (const decl of declaration.get("declarations")) {
958
- const id = decl.get("id");
959
- if (id.isIdentifier()) {
960
- const exportName = id.node.name;
961
- if (names.has(exportName)) {
962
- analysis.walker.walkVariableDeclarator(decl);
963
- names.delete(exportName);
964
- }
965
- }
966
- }
967
- for (const spec of exportPath.get("specifiers")) {
968
- if (!spec.isExportSpecifier()) continue;
969
- const exported = spec.get("exported");
970
- let exportedName;
971
- if (exported.isIdentifier()) exportedName = exported.node.name;
972
- else if (exported.isStringLiteral()) exportedName = exported.node.value;
973
- if (!exportedName || !names.has(exportedName)) continue;
974
- const local = spec.get("local");
975
- analysis.walker.walkNode(local);
976
- names.delete(exportedName);
977
- }
978
- continue;
979
- }
980
- if (exportPath.isExportAllDeclaration()) {
981
- const source = exportPath.node.source?.value;
982
- if (typeof source === "string") {
983
- for (const exportName of names) propagate.push({
984
- specifier: source,
985
- exportName
986
- });
987
- names.clear();
988
- }
989
- }
990
- }
991
- for (const { specifier, exportName } of propagate) {
992
- let resolved;
993
- try {
994
- resolved = this.options.resolve(specifier, filename);
995
- } catch {
996
- resolved = void 0;
997
- }
998
- if (!resolved) {
999
- pending.add(exportName);
1000
- continue;
1001
- }
1002
- if (this.options.filter && !this.options.filter(resolved, specifier, filename)) {
1003
- pending.add(exportName);
1004
- continue;
1005
- }
1006
- this.addIgnoredExport(resolved, exportName);
1007
- }
1008
- for (const name of names) pending.add(name);
1009
- }
1010
- };
1011
- //#endregion
1012
- //#region src/js/ModuleGraph.ts
1013
- var JsModuleGraph = class {
1014
- constructor(entry, graphOptions) {
1015
- _defineProperty(this, "modules", /* @__PURE__ */ new Map());
1016
- _defineProperty(this, "queue", []);
1017
- _defineProperty(this, "resolve", void 0);
1018
- _defineProperty(this, "load", void 0);
1019
- _defineProperty(this, "filter", void 0);
1020
- _defineProperty(this, "maxDepth", void 0);
1021
- _defineProperty(this, "baseOptions", void 0);
1022
- _defineProperty(this, "parserOptions", void 0);
1023
- _defineProperty(this, "rootFilename", void 0);
1024
- _defineProperty(this, "ignoredExports", void 0);
1025
- this.resolve = graphOptions.resolve;
1026
- this.load = graphOptions.load;
1027
- this.filter = graphOptions.filter;
1028
- this.maxDepth = graphOptions.maxDepth ?? Number.POSITIVE_INFINITY;
1029
- const { moduleGraph: _moduleGraph, filename: _ignoredFilename, ...rest } = entry.handlerOptions;
1030
- this.baseOptions = {
1031
- ...rest,
1032
- filename: entry.filename
1033
- };
1034
- this.parserOptions = entry.handlerOptions.babelParserOptions;
1035
- this.rootFilename = entry.filename;
1036
- this.ignoredExports = new IgnoredExportsTracker({
1037
- resolve: this.resolve,
1038
- filter: this.filter,
1039
- modules: this.modules
1040
- });
1041
- this.modules.set(entry.filename, {
1042
- filename: entry.filename,
1043
- source: entry.source,
1044
- analysis: entry.analysis
1045
- });
1046
- this.queue.push({
1047
- filename: entry.filename,
1048
- depth: 0
1049
- });
1050
- }
1051
- build() {
1052
- this.collectDependencies();
1053
- let linked;
1054
- for (const [filename, state] of this.modules) {
1055
- if (filename === this.rootFilename) continue;
1056
- const childOptions = {
1057
- ...this.baseOptions,
1058
- filename
1059
- };
1060
- const code = processUpdatedSource(state.source, childOptions, state.analysis).toString();
1061
- if (code !== state.source) {
1062
- if (!linked) linked = {};
1063
- linked[filename] = { code };
1064
- }
1065
- }
1066
- return linked;
1067
- }
1068
- collectDependencies() {
1069
- while (this.queue.length > 0) {
1070
- const { filename, depth } = this.queue.shift();
1071
- if (depth >= this.maxDepth) continue;
1072
- const state = this.modules.get(filename);
1073
- if (!state) continue;
1074
- const dependencySpecifiers = /* @__PURE__ */ new Map();
1075
- for (const token of state.analysis.walker.imports) {
1076
- if (!dependencySpecifiers.has(token.source)) dependencySpecifiers.set(token.source, []);
1077
- dependencySpecifiers.get(token.source).push(token);
1078
- }
1079
- for (const exportPath of state.analysis.exportDeclarations) if (exportPath.isExportAllDeclaration() || exportPath.isExportNamedDeclaration()) {
1080
- const source = exportPath.node.source?.value;
1081
- if (typeof source === "string" && !dependencySpecifiers.has(source)) dependencySpecifiers.set(source, []);
1082
- }
1083
- for (const [specifier, tokens] of dependencySpecifiers) {
1084
- let resolved;
1085
- try {
1086
- resolved = this.resolve(specifier, filename);
1087
- } catch {
1088
- continue;
1089
- }
1090
- if (!resolved) continue;
1091
- if (this.filter && !this.filter(resolved, specifier, filename)) continue;
1092
- if (tokens.length > 0) this.ignoredExports.registerIgnoredExportsFromTokens(resolved, tokens);
1093
- if (this.modules.has(resolved)) continue;
1094
- let source;
1095
- try {
1096
- source = this.load(resolved);
1097
- } catch {
1098
- continue;
1099
- }
1100
- if (typeof source !== "string") continue;
1101
- let analysis;
1102
- try {
1103
- analysis = analyzeSource(babelParse(source, {
1104
- ...this.parserOptions,
1105
- sourceFilename: resolved
1106
- }), {
1107
- ...this.baseOptions,
1108
- filename: resolved
1109
- });
1110
- this.ignoredExports.applyIgnoredExportsToAnalysis(resolved, analysis);
1111
- } catch {
1112
- continue;
1113
- }
1114
- this.modules.set(resolved, {
1115
- filename: resolved,
1116
- source,
1117
- analysis
1118
- });
1119
- this.queue.push({
1120
- filename: resolved,
1121
- depth: depth + 1
1122
- });
1123
- }
1124
- }
1125
- }
1126
- };
1127
- //#endregion
1128
- //#region src/js/node-path-walker/export-handlers.ts
1129
- function walkExportDeclaration(ctx, path) {
1130
- if (path.isExportDeclaration()) {
1131
- if (path.isExportNamedDeclaration()) walkExportNamedDeclaration(ctx, path);
1132
- else if (path.isExportDefaultDeclaration()) walkExportDefaultDeclaration(ctx, path);
1133
- else if (path.isExportAllDeclaration()) walkExportAllDeclaration(ctx, path);
1134
- }
1135
- }
1136
- function walkExportNamedDeclaration(ctx, path) {
1137
- const declaration = path.get("declaration");
1138
- if (declaration.isVariableDeclaration()) for (const decl of declaration.get("declarations")) ctx.walkNode(decl);
1139
- const specifiers = path.get("specifiers");
1140
- for (const spec of specifiers) if (spec.isExportSpecifier()) {
1141
- const local = spec.get("local");
1142
- if (local.isIdentifier()) ctx.walkNode(local);
1143
- }
1144
- }
1145
- function walkExportDefaultDeclaration(ctx, path) {
1146
- const decl = path.get("declaration");
1147
- if (decl.isIdentifier()) ctx.walkNode(decl);
1148
- else ctx.walkNode(decl);
1149
- }
1150
- function walkExportAllDeclaration(ctx, path) {
1151
- const source = path.get("source");
1152
- if (source.isStringLiteral()) ctx.addImportToken({
1153
- declaration: path,
1154
- source: source.node.value,
1155
- type: "ExportAllDeclaration"
1156
- });
1157
- }
1158
- //#endregion
1159
- //#region src/js/node-path-walker/import-tokens.ts
1160
- function maybeAddImportToken(imports, arg) {
1161
- if (!(arg.isImportSpecifier() && arg.node.importKind !== "type" || arg.isImportDefaultSpecifier())) return false;
1162
- const importDeclaration = arg.parentPath;
1163
- if (!importDeclaration.isImportDeclaration() || importDeclaration.node.importKind === "type") return false;
1164
- if (arg.isImportSpecifier()) {
1165
- const imported = arg.get("imported");
1166
- if (imported.isIdentifier()) imports.add({
1167
- declaration: importDeclaration,
1168
- specifier: arg,
1169
- imported: imported.node.name,
1170
- local: arg.node.local.name,
1171
- source: importDeclaration.node.source.value,
1172
- type: "ImportSpecifier"
1173
- });
1174
- return true;
1175
- }
1176
- imports.add({
1177
- declaration: importDeclaration,
1178
- specifier: arg,
1179
- local: arg.node.local.name,
1180
- source: importDeclaration.node.source.value,
1181
- type: "ImportDefaultSpecifier"
1182
- });
1183
- return true;
1184
- }
1185
- //#endregion
1186
- //#region src/js/NodePathWalker.ts
1187
- const EMPTY_IGNORE_CALL_EXPRESSION_IDENTIFIERS = [];
1188
- const EMPTY_IMPORT_TOKENS = /* @__PURE__ */ new Set();
1189
- function NOOP_STRING_PATH_CALLBACK() {}
1190
- const NEVER_MATCH_NAME = () => false;
1191
- /**
1192
- * 遍历我们关注的调用表达式所关联的绑定,收集后续需要转换的字符串节点。
1193
- */
1194
- var NodePathWalker = class {
1195
- constructor({ ignoreCallExpressionIdentifiers, callback } = {}) {
1196
- _defineProperty(this, "ignoreCallExpressionIdentifiers", void 0);
1197
- _defineProperty(this, "callback", void 0);
1198
- _defineProperty(this, "isIgnoredCallIdentifier", void 0);
1199
- _defineProperty(this, "hasIgnoredCallIdentifiers", void 0);
1200
- _defineProperty(this, "importsStore", void 0);
1201
- _defineProperty(this, "visitedStore", void 0);
1202
- this.hasIgnoredCallIdentifiers = Boolean(ignoreCallExpressionIdentifiers && ignoreCallExpressionIdentifiers.length > 0);
1203
- this.ignoreCallExpressionIdentifiers = ignoreCallExpressionIdentifiers ?? EMPTY_IGNORE_CALL_EXPRESSION_IDENTIFIERS;
1204
- this.callback = callback ?? NOOP_STRING_PATH_CALLBACK;
1205
- this.isIgnoredCallIdentifier = this.hasIgnoredCallIdentifiers ? createNameMatcher(this.ignoreCallExpressionIdentifiers, { exact: true }) : NEVER_MATCH_NAME;
1206
- }
1207
- get imports() {
1208
- return this.importsStore ?? EMPTY_IMPORT_TOKENS;
1209
- }
1210
- getWritableImports() {
1211
- if (!this.importsStore) this.importsStore = /* @__PURE__ */ new Set();
1212
- return this.importsStore;
1213
- }
1214
- addImportToken(token) {
1215
- this.getWritableImports().add(token);
1216
- }
1217
- getVisited() {
1218
- if (!this.visitedStore) this.visitedStore = /* @__PURE__ */ new WeakSet();
1219
- return this.visitedStore;
1220
- }
1221
- walkVariableDeclarator(path) {
1222
- const init = path.get("init");
1223
- this.walkNode(init);
1224
- }
1225
- walkTemplateLiteral(path) {
1226
- for (const exp of path.get("expressions")) this.walkNode(exp);
1227
- for (const quasis of path.get("quasis")) this.callback(quasis);
1228
- }
1229
- walkStringLiteral(path) {
1230
- this.callback(path);
1231
- }
1232
- walkBinaryExpression(path) {
1233
- const left = path.get("left");
1234
- this.walkNode(left);
1235
- const right = path.get("right");
1236
- this.walkNode(right);
1237
- }
1238
- walkLogicalExpression(path) {
1239
- const left = path.get("left");
1240
- this.walkNode(left);
1241
- const right = path.get("right");
1242
- this.walkNode(right);
1243
- }
1244
- walkObjectExpression(path) {
1245
- const props = path.get("properties");
1246
- for (const prop of props) if (prop.isObjectProperty()) {
1247
- const key = prop.get("key");
1248
- this.walkNode(key);
1249
- const value = prop.get("value");
1250
- this.walkNode(value);
1251
- }
1252
- }
1253
- walkArrayExpression(path) {
1254
- const elements = path.get("elements");
1255
- for (const element of elements) this.walkNode(element);
1256
- }
1257
- walkNode(arg) {
1258
- const visited = this.getVisited();
1259
- if (visited.has(arg)) return;
1260
- visited.add(arg);
1261
- if (arg.isIdentifier()) {
1262
- const binding = arg?.scope?.getBinding?.(arg.node.name);
1263
- if (binding) this.walkNode(binding.path);
1264
- } else if (arg.isMemberExpression()) {
1265
- const objectPath = arg.get("object");
1266
- if (objectPath.isIdentifier()) {
1267
- const binding = arg?.scope?.getBinding?.(objectPath.node.name);
1268
- if (binding) {
1269
- if (binding.path.isVariableDeclarator()) this.walkVariableDeclarator(binding.path);
1270
- }
1271
- }
1272
- } else if (arg.isTemplateLiteral()) this.walkTemplateLiteral(arg);
1273
- else if (arg.isStringLiteral()) this.walkStringLiteral(arg);
1274
- else if (arg.isBinaryExpression()) this.walkBinaryExpression(arg);
1275
- else if (arg.isLogicalExpression()) this.walkLogicalExpression(arg);
1276
- else if (arg.isObjectExpression()) this.walkObjectExpression(arg);
1277
- else if (arg.isArrayExpression()) this.walkArrayExpression(arg);
1278
- else if (arg.isVariableDeclarator()) this.walkVariableDeclarator(arg);
1279
- else if (maybeAddImportToken(this.getWritableImports(), arg)) {}
1280
- }
1281
- /**
1282
- * Walk the arguments of a desired call expression so their bindings can be analysed.
1283
- */
1284
- walkCallExpression(path) {
1285
- if (!this.hasIgnoredCallIdentifiers) return;
1286
- const calleePath = path.get("callee");
1287
- if (calleePath.isIdentifier() && this.isIgnoredCallIdentifier(calleePath.node.name)) for (const arg of path.get("arguments")) this.walkNode(arg);
1288
- }
1289
- walkExportDeclaration(path) {
1290
- walkExportDeclaration(this, path);
1291
- }
1292
- walkExportNamedDeclaration(path) {
1293
- walkExportNamedDeclaration(this, path);
1294
- }
1295
- walkExportDefaultDeclaration(path) {
1296
- walkExportDefaultDeclaration(this, path);
1297
- }
1298
- walkExportAllDeclaration(path) {
1299
- walkExportAllDeclaration(this, path);
1300
- }
1301
- };
1302
- //#endregion
1303
- //#region src/js/taggedTemplateIgnore.ts
1304
- function createTaggedTemplateIgnore({ matcher, names }) {
1305
- const bindingIgnoreCache = /* @__PURE__ */ new Map();
1306
- const taggedTemplateIgnoreCache = /* @__PURE__ */ new WeakMap();
1307
- const seenBindings = /* @__PURE__ */ new Set();
1308
- let singleCanonicalIgnoreName;
1309
- let canonicalIgnoreNames;
1310
- for (const item of names ?? []) {
1311
- if (typeof item !== "string") continue;
1312
- if (singleCanonicalIgnoreName === void 0) {
1313
- singleCanonicalIgnoreName = item;
1314
- continue;
1315
- }
1316
- if (item === singleCanonicalIgnoreName) continue;
1317
- if (!canonicalIgnoreNames) {
1318
- canonicalIgnoreNames = /* @__PURE__ */ new Set([singleCanonicalIgnoreName, item]);
1319
- continue;
1320
- }
1321
- canonicalIgnoreNames.add(item);
1322
- }
1323
- const hasCanonicalIgnoreNames = singleCanonicalIgnoreName !== void 0;
1324
- const matchesIgnoreName = (value) => {
1325
- if (hasCanonicalIgnoreNames) {
1326
- if (canonicalIgnoreNames) {
1327
- if (canonicalIgnoreNames.has(value)) return true;
1328
- } else if (value === singleCanonicalIgnoreName) return true;
1329
- }
1330
- return matcher(value);
1331
- };
1332
- const propertyMatches = (propertyPath) => {
1333
- if (!propertyPath) return false;
1334
- if (propertyPath.isIdentifier()) return matchesIgnoreName(propertyPath.node.name);
1335
- if (propertyPath.isStringLiteral()) return matchesIgnoreName(propertyPath.node.value);
1336
- return false;
1337
- };
1338
- const resolvesMemberExpressionToIgnore = (path, seen) => {
1339
- const propertyPath = path.get("property");
1340
- if (propertyMatches(propertyPath)) return true;
1341
- const objectPath = path.get("object");
1342
- if (objectPath.isIdentifier()) {
1343
- const binding = (objectPath?.scope)?.getBinding?.(objectPath.node.name);
1344
- if (binding) return resolvesToWeappTwIgnore(binding, seen);
1345
- }
1346
- return false;
1347
- };
1348
- const resolvesToWeappTwIgnore = (binding, seen) => {
1349
- const cached = bindingIgnoreCache.get(binding);
1350
- if (cached !== void 0) return cached;
1351
- if (seen.has(binding)) return false;
1352
- seen.add(binding);
1353
- let result = false;
1354
- const bindingPath = binding.path;
1355
- if (bindingPath.isImportSpecifier()) {
1356
- const imported = bindingPath.node.imported;
1357
- if (imported.type === "Identifier" && matchesIgnoreName(imported.name)) result = true;
1358
- else if (imported.type === "StringLiteral" && matchesIgnoreName(imported.value)) result = true;
1359
- } else if (bindingPath.isVariableDeclarator()) {
1360
- const init = bindingPath.get("init");
1361
- if (init && init.node) {
1362
- if (init.isIdentifier()) {
1363
- const target = binding?.scope?.getBinding?.(init.node.name);
1364
- if (target) result = resolvesToWeappTwIgnore(target, seen);
1365
- } else if (init.isMemberExpression()) result = resolvesMemberExpressionToIgnore(init, seen);
1366
- }
1367
- }
1368
- bindingIgnoreCache.set(binding, result);
1369
- seen.delete(binding);
1370
- return result;
1371
- };
1372
- const getEffectiveTagPath = (tagPath) => {
1373
- let current = tagPath;
1374
- while (true) {
1375
- if (current.isParenthesizedExpression?.() || current.node.type === "ParenthesizedExpression") {
1376
- current = current.get("expression");
1377
- continue;
1378
- }
1379
- if (current.isTSAsExpression() || current.isTSTypeAssertion()) {
1380
- current = current.get("expression");
1381
- continue;
1382
- }
1383
- if (current.isTSNonNullExpression()) {
1384
- current = current.get("expression");
1385
- continue;
1386
- }
1387
- if (current.isTypeCastExpression?.()) {
1388
- current = current.get("expression");
1389
- continue;
1390
- }
1391
- if (current.isSequenceExpression()) {
1392
- const last = current.get("expressions").at(-1);
1393
- if (last) {
1394
- current = last;
1395
- continue;
1396
- }
1397
- }
1398
- if (current.isCallExpression?.() || current.node.type === "CallExpression") {
1399
- current = current.get("callee");
1400
- continue;
1401
- }
1402
- break;
1403
- }
1404
- return current;
1405
- };
1406
- const evaluateTagPath = (tagPath, seen) => {
1407
- if (tagPath.isCallExpression?.() || tagPath.node.type === "CallExpression") {
1408
- const calleePath = tagPath.get("callee");
1409
- return evaluateTagPath(calleePath, seen);
1410
- }
1411
- if (tagPath.isIdentifier()) {
1412
- if (matchesIgnoreName(tagPath.node.name)) return true;
1413
- const binding = tagPath?.scope?.getBinding?.(tagPath.node.name);
1414
- if (binding) return resolvesToWeappTwIgnore(binding, seen);
1415
- return false;
1416
- }
1417
- if (tagPath.isMemberExpression()) return resolvesMemberExpressionToIgnore(tagPath, seen);
1418
- return false;
1419
- };
1420
- const computeIgnore = (tagPath) => {
1421
- const cached = taggedTemplateIgnoreCache.get(tagPath.node);
1422
- if (cached !== void 0) return cached;
1423
- const effectiveTagPath = getEffectiveTagPath(tagPath);
1424
- const effectiveCached = taggedTemplateIgnoreCache.get(effectiveTagPath.node);
1425
- if (effectiveCached !== void 0) {
1426
- taggedTemplateIgnoreCache.set(tagPath.node, effectiveCached);
1427
- return effectiveCached;
1428
- }
1429
- seenBindings.clear();
1430
- const result = evaluateTagPath(effectiveTagPath, seenBindings);
1431
- taggedTemplateIgnoreCache.set(effectiveTagPath.node, result);
1432
- taggedTemplateIgnoreCache.set(tagPath.node, result);
1433
- return result;
1434
- };
1435
- return {
1436
- shouldIgnore(tagPath) {
1437
- return computeIgnore(tagPath);
1438
- },
1439
- getEffectiveTagPath
1440
- };
1441
- }
1442
- //#endregion
1443
- //#region src/js/babel.ts
1444
- const EXPRESSION_WRAPPER_PREFIX = "(\n";
1445
- const EXPRESSION_WRAPPER_SUFFIX = "\n)";
1446
- const EMPTY_IGNORED_PATHS = /* @__PURE__ */ new WeakSet();
1447
- const EMPTY_IMPORT_DECLARATIONS = /* @__PURE__ */ new Set();
1448
- const EMPTY_EXPORT_DECLARATIONS = /* @__PURE__ */ new Set();
1449
- const EMPTY_REQUIRE_CALL_PATHS = [];
1450
- const ignoredTaggedTemplateMatcherCache = /* @__PURE__ */ new WeakMap();
1451
- let defaultEvalHandler;
1452
- function getIgnoredTaggedTemplateMatcher(options) {
1453
- const cached = ignoredTaggedTemplateMatcherCache.get(options);
1454
- if (cached) return cached;
1455
- const created = createNameMatcher(options.ignoreTaggedTemplateExpressionIdentifiers, { exact: true });
1456
- ignoredTaggedTemplateMatcherCache.set(options, created);
1457
- return created;
1458
- }
1459
- function getDefaultEvalHandler() {
1460
- if (!defaultEvalHandler) throw new Error("Default JS eval handler is not initialized.");
1461
- return defaultEvalHandler;
1462
- }
1463
- function analyzeSource(ast, options, handler, collectModuleMetadata = true) {
1464
- const jsTokenUpdater = new JsTokenUpdater();
1465
- const needScope = Boolean(options.ignoreCallExpressionIdentifiers && options.ignoreCallExpressionIdentifiers.length > 0);
1466
- const ignoredPaths = needScope ? /* @__PURE__ */ new WeakSet() : EMPTY_IGNORED_PATHS;
1467
- const walker = needScope ? new NodePathWalker({
1468
- ...options.ignoreCallExpressionIdentifiers === void 0 ? {} : { ignoreCallExpressionIdentifiers: options.ignoreCallExpressionIdentifiers },
1469
- callback(path) {
1470
- ignoredPaths.add(path);
1471
- }
1472
- }) : new NodePathWalker();
1473
- let taggedTemplateIgnore;
1474
- const hasTaggedTemplateIgnoreIdentifiers = Boolean(options.ignoreTaggedTemplateExpressionIdentifiers && options.ignoreTaggedTemplateExpressionIdentifiers.length > 0);
1475
- function getTaggedTemplateIgnore() {
1476
- if (!taggedTemplateIgnore) taggedTemplateIgnore = createTaggedTemplateIgnore({
1477
- matcher: getIgnoredTaggedTemplateMatcher(options),
1478
- ...options.ignoreTaggedTemplateExpressionIdentifiers === void 0 ? {} : { names: options.ignoreTaggedTemplateExpressionIdentifiers }
1479
- });
1480
- return taggedTemplateIgnore;
1481
- }
1482
- const targetPaths = [];
1483
- const importDeclarations = collectModuleMetadata ? /* @__PURE__ */ new Set() : EMPTY_IMPORT_DECLARATIONS;
1484
- const exportDeclarations = collectModuleMetadata ? /* @__PURE__ */ new Set() : EMPTY_EXPORT_DECLARATIONS;
1485
- const requireCallPaths = collectModuleMetadata ? [] : EMPTY_REQUIRE_CALL_PATHS;
1486
- const evalHandler = handler ?? getDefaultEvalHandler();
1487
- const traverseOptions = {
1488
- StringLiteral: { enter(p) {
1489
- if (isEvalPath(p.parentPath)) return;
1490
- targetPaths.push(p);
1491
- } },
1492
- TemplateElement: { enter: hasTaggedTemplateIgnoreIdentifiers ? (p) => {
1493
- const pp = p.parentPath;
1494
- if (pp.isTemplateLiteral()) {
1495
- const ppp = pp.parentPath;
1496
- if (isEvalPath(ppp)) return;
1497
- if (ppp.isTaggedTemplateExpression()) {
1498
- const tagPath = ppp.get("tag");
1499
- if (getTaggedTemplateIgnore().shouldIgnore(tagPath)) return;
1500
- }
1501
- }
1502
- targetPaths.push(p);
1503
- } : (p) => {
1504
- const pp = p.parentPath;
1505
- if (pp.isTemplateLiteral()) {
1506
- const ppp = pp.parentPath;
1507
- if (isEvalPath(ppp)) return;
1508
- }
1509
- targetPaths.push(p);
1510
- } },
1511
- CallExpression: { enter: !collectModuleMetadata && !needScope ? (p) => {
1512
- if (isEvalPath(p)) walkEvalExpression(p, options, jsTokenUpdater, evalHandler);
1513
- } : (p) => {
1514
- if (isEvalPath(p)) {
1515
- walkEvalExpression(p, options, jsTokenUpdater, evalHandler);
1516
- return;
1517
- }
1518
- const calleePath = p.get("callee");
1519
- if (collectModuleMetadata && calleePath.isIdentifier({ name: "require" }) && !p?.scope?.hasBinding?.("require")) {
1520
- const args = p.get("arguments");
1521
- if (Array.isArray(args) && args.length > 0) {
1522
- const first = args[0];
1523
- if (first?.isStringLiteral()) requireCallPaths.push(first);
1524
- }
1525
- }
1526
- if (needScope) walker.walkCallExpression(p);
1527
- } },
1528
- ...collectModuleMetadata ? {
1529
- ImportDeclaration: { enter(p) {
1530
- importDeclarations.add(p);
1531
- } },
1532
- ExportDeclaration: { enter(p) {
1533
- exportDeclarations.add(p);
1534
- } }
1535
- } : {}
1536
- };
1537
- traverse(ast, {
1538
- ...traverseOptions,
1539
- noScope: !needScope
1540
- });
1541
- return {
1542
- walker,
1543
- jsTokenUpdater,
1544
- ast,
1545
- targetPaths,
1546
- importDeclarations,
1547
- exportDeclarations,
1548
- requireCallPaths,
1549
- ignoredPaths
1550
- };
1551
- }
1552
- function jsHandler(rawSource, options) {
1553
- const shouldWrapExpression = Boolean(options.wrapExpression);
1554
- const source = shouldWrapExpression ? `${EXPRESSION_WRAPPER_PREFIX}${rawSource}${EXPRESSION_WRAPPER_SUFFIX}` : rawSource;
1555
- let ast;
1556
- try {
1557
- ast = babelParse(source, options.babelParserOptions);
1558
- } catch (error) {
1559
- return {
1560
- code: rawSource,
1561
- error
1562
- };
1563
- }
1564
- const needsModuleMetadata = Boolean(options.moduleSpecifierReplacements || options.moduleGraph && options.filename);
1565
- const analysis = analyzeSource(ast, options, jsHandler, needsModuleMetadata);
1566
- const ms = processUpdatedSource(source, options, analysis);
1567
- if (shouldWrapExpression) {
1568
- const start = 0;
1569
- const end = source.length;
1570
- const suffixLength = 2;
1571
- ms.remove(start, 2);
1572
- ms.remove(end - suffixLength, end);
1573
- }
1574
- const result = { code: ms.toString() };
1575
- if (options.generateMap) Object.defineProperty(result, "map", {
1576
- configurable: true,
1577
- enumerable: true,
1578
- get() {
1579
- return ms.generateMap();
1580
- }
1581
- });
1582
- if (options.moduleGraph && options.filename) {
1583
- const linked = new JsModuleGraph({
1584
- filename: options.filename,
1585
- source: rawSource,
1586
- analysis,
1587
- handlerOptions: options
1588
- }, options.moduleGraph).build();
1589
- if (linked) result.linked = linked;
1590
- }
1591
- return result;
1592
- }
1593
- defaultEvalHandler = jsHandler;
1594
- createRequire(import.meta.url);
1595
- Object.freeze({ wrapExpression: true });
1596
- //#endregion
1597
- //#region src/wxml/whitespace.ts
1598
- const WHITESPACE_CODES = /* @__PURE__ */ new Set([
1599
- 9,
1600
- 10,
1601
- 11,
1602
- 12,
1603
- 13,
1604
- 32,
1605
- 160,
1606
- 65279
1607
- ]);
1608
- function isWhitespace(char) {
1609
- if (char.length === 0) return false;
1610
- return WHITESPACE_CODES.has(char.charCodeAt(0));
1611
- }
1612
- //#endregion
1613
- //#region src/wxml/Tokenizer.ts
1614
- var Tokenizer = class {
1615
- constructor() {
1616
- _defineProperty(this, "state", void 0);
1617
- _defineProperty(this, "buffer", void 0);
1618
- _defineProperty(this, "tokens", void 0);
1619
- _defineProperty(this, "bufferStartIndex", void 0);
1620
- _defineProperty(this, "expressionStartIndex", void 0);
1621
- _defineProperty(this, "expressionBuffer", void 0);
1622
- _defineProperty(this, "expressions", void 0);
1623
- this.reset();
1624
- }
1625
- processChar(char, index) {
1626
- switch (this.state) {
1627
- case 0:
1628
- if (isWhitespace(char)) {} else if (char === "{") {
1629
- this.state = 2;
1630
- this.bufferStartIndex = index;
1631
- this.buffer += char;
1632
- this.expressionBuffer = char;
1633
- this.expressionStartIndex = index;
1634
- } else {
1635
- this.state = 1;
1636
- this.bufferStartIndex = index;
1637
- this.buffer += char;
1638
- }
1639
- break;
1640
- case 1:
1641
- if (isWhitespace(char)) {
1642
- this.tokens.push({
1643
- start: this.bufferStartIndex,
1644
- end: index,
1645
- value: this.buffer,
1646
- expressions: this.expressions
1647
- });
1648
- this.buffer = "";
1649
- this.expressions = [];
1650
- this.state = 0;
1651
- } else if (char === "{") {
1652
- this.buffer += char;
1653
- this.expressionBuffer = char;
1654
- this.expressionStartIndex = index;
1655
- this.state = 2;
1656
- } else this.buffer += char;
1657
- break;
1658
- case 2:
1659
- if (char === "}") {
1660
- this.buffer += char;
1661
- this.expressionBuffer += char;
1662
- this.state = 3;
1663
- } else {
1664
- this.buffer += char;
1665
- this.expressionBuffer += char;
1666
- }
1667
- break;
1668
- case 3:
1669
- if (char === "}") {
1670
- this.buffer += char;
1671
- this.expressionBuffer += char;
1672
- this.expressions.push({
1673
- start: this.expressionStartIndex,
1674
- end: index + 1,
1675
- value: this.expressionBuffer
1676
- });
1677
- this.expressionBuffer = "";
1678
- this.state = 4;
1679
- } else {
1680
- this.buffer += char;
1681
- this.expressionBuffer += char;
1682
- this.state = 2;
1683
- }
1684
- break;
1685
- case 4:
1686
- if (isWhitespace(char)) {
1687
- this.tokens.push({
1688
- start: this.bufferStartIndex,
1689
- end: index,
1690
- value: this.buffer,
1691
- expressions: this.expressions
1692
- });
1693
- this.buffer = "";
1694
- this.expressions = [];
1695
- this.state = 0;
1696
- } else if (char === "{") {
1697
- this.expressionStartIndex = index;
1698
- this.expressionBuffer = char;
1699
- this.buffer += char;
1700
- this.state = 2;
1701
- } else {
1702
- this.buffer += char;
1703
- this.state = 1;
1704
- }
1705
- break;
1706
- default: throw new Error("Unexpected state");
1707
- }
1708
- }
1709
- run(input) {
1710
- this.reset();
1711
- for (let i = 0; i < input.length; i++) {
1712
- const char = input[i];
1713
- if (char === void 0) continue;
1714
- this.processChar(char, i);
1715
- }
1716
- if (this.buffer.length > 0) this.tokens.push({
1717
- start: this.bufferStartIndex,
1718
- end: input.length,
1719
- value: this.buffer,
1720
- expressions: this.expressions
1721
- });
1722
- const tokens = this.tokens;
1723
- this.reset();
1724
- return tokens;
1725
- }
1726
- reset() {
1727
- this.state = 0;
1728
- this.buffer = "";
1729
- this.tokens = [];
1730
- this.bufferStartIndex = 0;
1731
- this.expressionBuffer = "";
1732
- this.expressionStartIndex = 0;
1733
- this.expressions = [];
1734
- }
1735
- };
1736
- new Tokenizer();
1737
- //#endregion
1738
- //#region src/constants.ts
1739
- const WEAPP_TW_REQUIRED_NODE_VERSION_RANGE = "^22.18.0 || >=24.11.0";
1740
- //#endregion
1741
- //#region src/cli/context.ts
1742
- function formatOutputPath(target, baseDir) {
1743
- const root = baseDir ?? process.cwd();
1744
- const relative = path.relative(root, target);
1745
- if (!relative) return ".";
1746
- if (relative.startsWith("..")) return path.normalize(target);
1747
- return relative.startsWith(".") ? relative : `.${path.sep}${relative}`;
1748
- }
1749
- //#endregion
1750
- //#region src/cli/doctor/constants.ts
1751
- const CONFIG_FILES = {
1752
- tailwind: [
1753
- "tailwind.config.js",
1754
- "tailwind.config.cjs",
1755
- "tailwind.config.mjs",
1756
- "tailwind.config.ts"
1757
- ],
1758
- postcss: [
1759
- "postcss.config.js",
1760
- "postcss.config.cjs",
1761
- "postcss.config.mjs",
1762
- "postcss.config.ts"
1763
- ],
1764
- vite: [
1765
- "vite.config.js",
1766
- "vite.config.mjs",
1767
- "vite.config.ts"
1768
- ],
1769
- webpack: [
1770
- "webpack.config.js",
1771
- "webpack.config.cjs",
1772
- "webpack.config.ts"
1773
- ]
1774
- };
1775
- const FRAMEWORK_DEPS = [
1776
- ["@tarojs/taro", "Taro"],
1777
- ["@dcloudio/uni-app", "uni-app"],
1778
- ["@mpxjs/core", "MPX"],
1779
- ["remax", "Remax"]
1780
- ];
1781
- //#endregion
1782
- //#region src/cli/doctor.ts
1783
- function tryReadJson(file) {
1784
- try {
1785
- return JSON.parse(readFileSync(file, "utf8"));
1786
- } catch {
1787
- return;
1788
- }
1789
- }
1790
- function findFirstExisting(cwd, files) {
1791
- return files.find((file) => existsSync(path.join(cwd, file)));
1792
- }
1793
- function readProjectPackageJson(cwd) {
1794
- return tryReadJson(path.join(cwd, "package.json"));
1795
- }
1796
- function readDependencyVersion(cwd, packageName) {
1797
- try {
1798
- return tryReadJson(createRequire(path.join(cwd, "package.json")).resolve(`${packageName}/package.json`))?.version;
1799
- } catch {
1800
- return;
1801
- }
1802
- }
1803
- function collectDependencySpecs(pkg) {
1804
- return {
1805
- ...pkg?.dependencies ?? {},
1806
- ...pkg?.devDependencies ?? {},
1807
- ...pkg?.optionalDependencies ?? {},
1808
- ...pkg?.peerDependencies ?? {}
1809
- };
1810
- }
1811
- function detectPackageManager(cwd, pkg) {
1812
- if (pkg?.packageManager) return pkg.packageManager;
1813
- if (existsSync(path.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
1814
- if (existsSync(path.join(cwd, "package-lock.json"))) return "npm";
1815
- if (existsSync(path.join(cwd, "yarn.lock"))) return "yarn";
1816
- }
1817
- function detectFrameworks(deps) {
1818
- return FRAMEWORK_DEPS.filter(([dependency]) => dependency in deps).map(([, label]) => label);
1819
- }
1820
- function addCheck(checks, check) {
1821
- checks.push(check);
1822
- }
1823
- function summarizeChecks(checks) {
1824
- return checks.reduce((summary, check) => {
1825
- summary[check.status] += 1;
1826
- return summary;
1827
- }, {
1828
- ok: 0,
1829
- warn: 0,
1830
- error: 0,
1831
- info: 0
1832
- });
1833
- }
1834
- function hasDependency(deps, packageName) {
1835
- return packageName in deps;
1836
- }
1837
- function getMajorVersion(version) {
1838
- if (!version) return;
1839
- return semver.parse(version)?.major;
1840
- }
1841
- function getDependencyMajor(deps, packageName) {
1842
- const spec = deps[packageName];
1843
- return spec ? semver.minVersion(spec)?.major : void 0;
1844
- }
1845
- function createDoctorReport(options = {}) {
1846
- const cwd = path.resolve(options.cwd ?? process.cwd());
1847
- const nodeVersion = options.nodeVersion ?? process.versions.node;
1848
- const pkg = readProjectPackageJson(cwd);
1849
- const deps = collectDependencySpecs(pkg);
1850
- const checks = [];
1851
- const packageManager = detectPackageManager(cwd, pkg);
1852
- const frameworks = detectFrameworks(deps);
1853
- const tailwindcssVersion = readDependencyVersion(cwd, "tailwindcss");
1854
- const weappTailwindcssVersion = readDependencyVersion(cwd, "weapp-tailwindcss");
1855
- const tailwindMajor = getMajorVersion(tailwindcssVersion) ?? getDependencyMajor(deps, "tailwindcss");
1856
- const tailwindConfig = findFirstExisting(cwd, CONFIG_FILES.tailwind);
1857
- const postcssConfig = findFirstExisting(cwd, CONFIG_FILES.postcss);
1858
- const viteConfig = findFirstExisting(cwd, CONFIG_FILES.vite);
1859
- const webpackConfig = findFirstExisting(cwd, CONFIG_FILES.webpack);
1860
- addCheck(checks, pkg ? {
1861
- id: "package-json",
1862
- title: "package.json",
1863
- status: "ok",
1864
- message: "已找到项目 package.json。"
1865
- } : {
1866
- id: "package-json",
1867
- title: "package.json",
1868
- status: "error",
1869
- message: "当前目录没有 package.json。",
1870
- suggestion: "请在项目根目录运行 doctor,或通过 --cwd 指向项目根目录。"
1871
- });
1872
- addCheck(checks, semver.satisfies(nodeVersion, "^22.18.0 || >=24.11.0") ? {
1873
- id: "node-version",
1874
- title: "Node.js",
1875
- status: "ok",
1876
- message: `当前 Node.js ${nodeVersion} 满足版本要求 ${WEAPP_TW_REQUIRED_NODE_VERSION_RANGE}。`
1877
- } : {
1878
- id: "node-version",
1879
- title: "Node.js",
1880
- status: "error",
1881
- message: `当前 Node.js ${nodeVersion} 不满足版本要求 ${WEAPP_TW_REQUIRED_NODE_VERSION_RANGE}。`,
1882
- suggestion: "请升级 Node.js 后再安装或构建 weapp-tailwindcss 项目。"
1883
- });
1884
- addCheck(checks, packageManager ? {
1885
- id: "package-manager",
1886
- title: "包管理器",
1887
- status: packageManager.startsWith("pnpm") ? "ok" : "info",
1888
- message: `检测到 ${packageManager}。`
1889
- } : {
1890
- id: "package-manager",
1891
- title: "包管理器",
1892
- status: "info",
1893
- message: "未检测到 lockfile 或 packageManager 字段。"
1894
- });
1895
- addCheck(checks, hasDependency(deps, "weapp-tailwindcss") || Boolean(weappTailwindcssVersion) ? {
1896
- id: "weapp-tailwindcss",
1897
- title: "weapp-tailwindcss",
1898
- status: "ok",
1899
- message: `检测到 weapp-tailwindcss${weappTailwindcssVersion ? `@${weappTailwindcssVersion}` : ""}。`
1900
- } : {
1901
- id: "weapp-tailwindcss",
1902
- title: "weapp-tailwindcss",
1903
- status: "warn",
1904
- message: "未在当前项目依赖中检测到 weapp-tailwindcss。",
1905
- suggestion: "如果这是业务项目,请安装 weapp-tailwindcss 并确认命令运行在项目根目录。"
1906
- });
1907
- addCheck(checks, hasDependency(deps, "tailwindcss") || Boolean(tailwindcssVersion) ? {
1908
- id: "tailwindcss",
1909
- title: "Tailwind CSS",
1910
- status: "ok",
1911
- message: `检测到 tailwindcss${tailwindcssVersion ? `@${tailwindcssVersion}` : ""}。`
1912
- } : {
1913
- id: "tailwindcss",
1914
- title: "Tailwind CSS",
1915
- status: "error",
1916
- message: "未检测到 tailwindcss。",
1917
- suggestion: "请安装 tailwindcss,并确认依赖可以从当前项目解析。"
1918
- });
1919
- addCheck(checks, tailwindConfig ? {
1920
- id: "tailwind-config",
1921
- title: "Tailwind 配置",
1922
- status: "ok",
1923
- message: `检测到 ${tailwindConfig}。`
1924
- } : {
1925
- id: "tailwind-config",
1926
- title: "Tailwind 配置",
1927
- status: tailwindMajor === 4 ? "info" : "warn",
1928
- message: "未检测到 tailwind.config.*。",
1929
- suggestion: tailwindMajor === 4 ? "Tailwind CSS v4 可以采用 CSS-first 配置;复杂 content/source 场景请补充配置文件。" : "请确认 Tailwind content/source 配置能够覆盖小程序页面、组件和脚本文件。"
1930
- });
1931
- addCheck(checks, postcssConfig ? {
1932
- id: "postcss-config",
1933
- title: "PostCSS 配置",
1934
- status: "ok",
1935
- message: `检测到 ${postcssConfig}。`
1936
- } : {
1937
- id: "postcss-config",
1938
- title: "PostCSS 配置",
1939
- status: viteConfig ? "info" : "warn",
1940
- message: "未检测到 postcss.config.*。",
1941
- suggestion: "如果通过 PostCSS 接入,请补充 postcss.config.*;如果通过 Vite/Taro 插件接入,可忽略此项。"
1942
- });
1943
- if (tailwindMajor === 4 && postcssConfig && !hasDependency(deps, "@tailwindcss/postcss")) addCheck(checks, {
1944
- id: "tailwindcss-v4-postcss",
1945
- title: "Tailwind v4 PostCSS",
1946
- status: "warn",
1947
- message: "Tailwind CSS v4 项目存在 PostCSS 配置,但未检测到 @tailwindcss/postcss。",
1948
- suggestion: "如果 PostCSS 配置中仍直接使用 tailwindcss,请迁移到 @tailwindcss/postcss。"
1949
- });
1950
- addCheck(checks, frameworks.length > 0 ? {
1951
- id: "framework",
1952
- title: "框架识别",
1953
- status: "ok",
1954
- message: `检测到 ${frameworks.join(", ")}。`
1955
- } : {
1956
- id: "framework",
1957
- title: "框架识别",
1958
- status: "info",
1959
- message: "未从依赖中识别出 Taro、uni-app、MPX 或 Remax。"
1960
- });
1961
- addCheck(checks, viteConfig || webpackConfig ? {
1962
- id: "bundler-config",
1963
- title: "构建器配置",
1964
- status: "ok",
1965
- message: `检测到 ${[viteConfig, webpackConfig].filter(Boolean).join(", ")}。`
1966
- } : {
1967
- id: "bundler-config",
1968
- title: "构建器配置",
1969
- status: "info",
1970
- message: "未检测到 vite.config.* 或 webpack.config.*。"
1971
- });
1972
- return {
1973
- cwd,
1974
- nodeVersion,
1975
- detected: {
1976
- packageManager,
1977
- frameworks,
1978
- tailwindcssVersion,
1979
- weappTailwindcssVersion
1980
- },
1981
- summary: summarizeChecks(checks),
1982
- checks
1983
- };
1984
- }
1985
- function hasDoctorFailure(report, strict = false) {
1986
- return report.summary.error > 0 || strict && report.summary.warn > 0;
1987
- }
1988
- function formatDoctorReport(report) {
1989
- const lines = [
1990
- `weapp-tailwindcss doctor`,
1991
- `cwd: ${report.cwd}`,
1992
- `summary: ${report.summary.error} error, ${report.summary.warn} warn, ${report.summary.ok} ok, ${report.summary.info} info`,
1993
- ""
1994
- ];
1995
- for (const check of report.checks) {
1996
- lines.push(`[${check.status}] ${check.title}: ${check.message}`);
1997
- if (check.suggestion) lines.push(` -> ${check.suggestion}`);
1998
- }
1999
- return lines.join("\n");
2000
- }
2001
- //#endregion
2002
- //#region src/cli/helpers/options/parse.ts
2003
- function readStringOption(flag, value) {
2004
- if (value == null) return;
2005
- if (typeof value !== "string") throw new TypeError(`Option "--${flag}" expects a string value.`);
2006
- const trimmed = value.trim();
2007
- if (trimmed.length === 0) throw new TypeError(`Option "--${flag}" expects a non-empty value.`);
2008
- return trimmed;
2009
- }
2010
- function readStringArrayOption(flag, value) {
2011
- if (value == null) return;
2012
- if (Array.isArray(value)) {
2013
- const normalized = value.filter((entry) => entry != null).map((entry) => {
2014
- if (typeof entry !== "string") throw new TypeError(`Option "--${flag}" expects string values.`);
2015
- const trimmed = entry.trim();
2016
- if (!trimmed) throw new TypeError(`Option "--${flag}" expects non-empty values.`);
2017
- return trimmed;
2018
- });
2019
- return normalized.length > 0 ? normalized : void 0;
2020
- }
2021
- const normalized = readStringOption(flag, value);
2022
- return normalized ? [normalized] : void 0;
2023
- }
2024
- function toBoolean(value, fallback) {
2025
- if (typeof value === "boolean") return value;
2026
- if (typeof value === "string") {
2027
- if (value === "true") return true;
2028
- if (value === "false") return false;
2029
- }
2030
- if (value == null) return fallback;
2031
- return Boolean(value);
2032
- }
2033
- //#endregion
2034
- //#region src/cli/helpers/options/resolve.ts
2035
- function resolveCliCwd(value) {
2036
- const raw = readStringOption("cwd", value);
2037
- if (!raw) return;
2038
- return path.isAbsolute(raw) ? path.normalize(raw) : path.resolve(process.cwd(), raw);
2039
- }
2040
- //#endregion
2041
- //#region src/cli/helpers.ts
2042
- async function ensureDir(dir) {
2043
- await mkdir(dir, { recursive: true });
2044
- }
2045
- function handleCliError(error) {
2046
- if (error instanceof Error) {
2047
- logger.error(error.message);
2048
- if (error.stack && process.env["WEAPP_TW_DEBUG"] === "1") logger.error(error.stack);
2049
- } else logger.error(String(error));
2050
- }
2051
- function commandAction(handler) {
2052
- return async (...args) => {
2053
- try {
2054
- await handler(...args);
2055
- } catch (error) {
2056
- handleCliError(error);
2057
- process.exitCode = 1;
2058
- }
2059
- };
2060
- }
2061
- //#endregion
2062
- //#region src/cli/mount-options.ts
2063
- const PATCH_COMMAND_OBSOLETE_NOTICE = "提示:weapp-tailwindcss@5 已由构建运行时接管 Tailwind CSS 处理,weapp-tw patch 已无需执行;请移除 package.json 中的 postinstall 钩子。";
2064
- const obsoletePatchCommands = [
2065
- "extract",
2066
- "tokens",
2067
- "init",
2068
- "migrate",
2069
- "restore",
2070
- "validate"
2071
- ];
2072
- function logPatchCommandObsoleteNotice() {
2073
- logger.warn(PATCH_COMMAND_OBSOLETE_NOTICE);
2074
- }
2075
- function logObsoletePatchCommand(command) {
2076
- logPatchCommandObsoleteNotice();
2077
- logger.warn(`命令 "${command}" 来自旧版 tailwindcss-patch 工作流,当前版本无需执行。`);
2078
- }
2079
- const DEFAULT_VSCODE_SOURCES = [
2080
- "not \"./dist\"",
2081
- "not \"./unpackage\"",
2082
- "./src/**/*.{wxml,axml,swan,qml,ttml,ux,uts}",
2083
- "./src/**/*.{js,jsx,ts,tsx,mjs,cjs,wxs,sjs}",
2084
- "./src/**/*.{vue,svelte,mpx,html,md,mdx}"
2085
- ];
2086
- const SINGLE_QUOTE = "'";
2087
- const DOUBLE_QUOTE = "\"";
2088
- const BACKSLASH_RE = /\\/g;
2089
- function toPosixPath(filepath) {
2090
- return filepath.replace(BACKSLASH_RE, "/");
2091
- }
2092
- async function assertFileExists(filepath) {
2093
- try {
2094
- await access(filepath, constants.F_OK);
2095
- } catch (error) {
2096
- const err = error;
2097
- if (err?.code === "ENOENT") throw new Error(`CSS entry file not found: ${filepath}`);
2098
- throw err;
2099
- }
2100
- }
2101
- async function assertCanWrite(filepath, force) {
2102
- try {
2103
- await access(filepath, constants.F_OK);
2104
- if (!force) throw new Error(`VS Code helper already exists at ${filepath}. Re-run with --force to overwrite it.`);
2105
- } catch (error) {
2106
- const err = error;
2107
- if (err?.code === "ENOENT") return;
2108
- throw err;
2109
- }
2110
- }
2111
- function toCssLiteral(value) {
2112
- const normalized = toPosixPath(value);
2113
- return JSON.stringify(normalized);
2114
- }
2115
- function formatSource(pattern) {
2116
- const trimmed = pattern.trim();
2117
- if (!trimmed) return null;
2118
- if (trimmed.startsWith("@source ")) return trimmed.endsWith(";") ? trimmed : `${trimmed};`;
2119
- let body = trimmed;
2120
- let keyword = "";
2121
- if (body.startsWith("not ")) {
2122
- keyword = "not ";
2123
- body = body.slice(4).trim();
2124
- } else if (body.startsWith("!")) {
2125
- keyword = "not ";
2126
- body = body.slice(1).trim();
2127
- }
2128
- if (!body) throw new Error("Invalid @source pattern: empty body.");
2129
- if (!body.startsWith(SINGLE_QUOTE) && !body.startsWith(DOUBLE_QUOTE)) body = toCssLiteral(body);
2130
- return `@source ${keyword}${body};`;
2131
- }
2132
- function resolveOutputPath(baseDir, output) {
2133
- const target = output ?? ".vscode/weapp-tailwindcss.intellisense.css";
2134
- return path.isAbsolute(target) ? path.normalize(target) : path.resolve(baseDir, target);
2135
- }
2136
- function resolveCssEntry(baseDir, entry) {
2137
- return path.isAbsolute(entry) ? path.normalize(entry) : path.resolve(baseDir, entry);
2138
- }
2139
- function toRelativeImport(fromFile, targetFile) {
2140
- const fromDir = path.dirname(fromFile);
2141
- let relative = path.relative(fromDir, targetFile);
2142
- if (!relative) relative = path.basename(targetFile);
2143
- if (!relative.startsWith(".")) relative = `./${relative}`;
2144
- return toPosixPath(relative);
2145
- }
2146
- async function generateVscodeIntellisenseEntry(options) {
2147
- const baseDir = options.baseDir;
2148
- const cssEntryPath = resolveCssEntry(baseDir, options.cssEntry);
2149
- await assertFileExists(cssEntryPath);
2150
- const outputPath = resolveOutputPath(baseDir, options.output);
2151
- await ensureDir(path.dirname(outputPath));
2152
- await assertCanWrite(outputPath, options.force);
2153
- const formattedSources = (options.sources && options.sources.length > 0 ? options.sources : DEFAULT_VSCODE_SOURCES).map(formatSource).filter((statement) => Boolean(statement));
2154
- const cssImport = toRelativeImport(outputPath, cssEntryPath);
2155
- const separator = formattedSources.length > 0 ? [""] : [];
2156
- const content = [
2157
- "/*",
2158
- " * Auto-generated by weapp-tailwindcss.",
2159
- " * This file exists solely to activate Tailwind CSS IntelliSense in VS Code.",
2160
- " * Do not import it in your actual mini-program bundles.",
2161
- " */",
2162
- "@import 'tailwindcss';",
2163
- "",
2164
- ...formattedSources,
2165
- ...separator,
2166
- `@import '${cssImport}';`,
2167
- ""
2168
- ].filter((line, idx, arr) => !(line === "" && arr[idx - 1] === "")).join("\n");
2169
- await writeFile(outputPath, `${content}\n`, "utf8");
2170
- return {
2171
- outputPath,
2172
- cssEntryPath
2173
- };
2174
- }
2175
- //#endregion
2176
- //#region src/cli.ts
2177
- process.title = "node (weapp-tailwindcss)";
2178
- if (!semver.satisfies(process.versions.node, "^22.18.0 || >=24.11.0")) logger.warn(`You are using Node.js ${process.versions.node}. For weapp-tailwindcss, Node.js version ${WEAPP_TW_REQUIRED_NODE_VERSION_RANGE} is required.`);
2179
- function parseArgs(argv) {
2180
- const options = {};
2181
- const positional = [];
2182
- for (let index = 0; index < argv.length; index++) {
2183
- const arg = argv[index];
2184
- if (arg === void 0) continue;
2185
- if (!arg.startsWith("--")) {
2186
- positional.push(arg);
2187
- continue;
2188
- }
2189
- const [rawKey, inlineValue] = arg.slice(2).split("=", 2);
2190
- if (!rawKey) continue;
2191
- const key = rawKey.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
2192
- const next = argv[index + 1];
2193
- let value = true;
2194
- if (inlineValue !== void 0) value = inlineValue;
2195
- else if (next !== void 0 && !next.startsWith("-")) {
2196
- index++;
2197
- value = next;
2198
- }
2199
- const current = options[key];
2200
- if (current === void 0) options[key] = value;
2201
- else if (Array.isArray(current)) current.push(String(value));
2202
- else options[key] = [String(current), String(value)];
2203
- }
2204
- return {
2205
- command: positional[0],
2206
- options
2207
- };
2208
- }
2209
- function printHelp() {
2210
- logger.log(`weapp-tailwindcss
2211
-
2212
- Usage:
2213
- weapp-tw <command> [options]
2214
-
2215
- Commands:
2216
- patch Deprecated no-op: v5 runtime handles Tailwind CSS automatically
2217
- status Deprecated no-op: patch status is no longer required
2218
- vscode-entry Generate a VS Code helper CSS for Tailwind IntelliSense
2219
- doctor Check project setup for weapp-tailwindcss
2220
- `);
2221
- }
2222
- async function runPatch() {
2223
- logPatchCommandObsoleteNotice();
2224
- logger.success("已跳过:当前版本不需要手动执行 Tailwind CSS patch。");
2225
- }
2226
- async function runStatus(options) {
2227
- const payload = {
2228
- required: false,
2229
- status: "unnecessary",
2230
- message: PATCH_COMMAND_OBSOLETE_NOTICE
2231
- };
2232
- if (toBoolean(options["json"], false)) {
2233
- logger.log(JSON.stringify(payload, null, 2));
2234
- return;
2235
- }
2236
- logPatchCommandObsoleteNotice();
2237
- logger.success("无需检查 Tailwind CSS patch 状态。");
2238
- }
2239
- async function runVscodeEntry(options) {
2240
- const resolvedCwd = resolveCliCwd(options.cwd);
2241
- const baseDir = resolvedCwd ?? process.cwd();
2242
- const cssEntry = readStringOption("css", options["css"]);
2243
- if (!cssEntry) throw new Error("Option \"--css\" is required.");
2244
- const result = await generateVscodeIntellisenseEntry({
2245
- baseDir,
2246
- cssEntry,
2247
- output: readStringOption("output", options["output"]),
2248
- sources: readStringArrayOption("source", options["source"]),
2249
- force: toBoolean(options["force"], false)
2250
- });
2251
- logger.success(`VS Code helper generated -> ${formatOutputPath(result.outputPath, resolvedCwd)}`);
2252
- }
2253
- async function runDoctor(options) {
2254
- const report = createDoctorReport({ cwd: resolveCliCwd(options.cwd) });
2255
- if (toBoolean(options["json"], false)) logger.log(JSON.stringify(report, null, 2));
2256
- else logger.log(formatDoctorReport(report));
2257
- if (hasDoctorFailure(report, toBoolean(options["strict"], false))) process.exitCode = 1;
2258
- }
2259
- async function main() {
2260
- const { command, options } = parseArgs(process.argv.slice(2));
2261
- await commandAction(async () => {
2262
- switch (command) {
2263
- case void 0:
2264
- case "-h":
2265
- case "--help":
2266
- case "help":
2267
- printHelp();
2268
- return;
2269
- case "-v":
2270
- case "--version":
2271
- case "version":
2272
- logger.log(process.env["npm_package_version"] ?? "0.0.0");
2273
- return;
2274
- case "patch":
2275
- case "install":
2276
- await runPatch();
2277
- return;
2278
- case "status":
2279
- await runStatus(options);
2280
- return;
2281
- case "vscode-entry":
2282
- await runVscodeEntry(options);
2283
- return;
2284
- case "doctor":
2285
- await runDoctor(options);
2286
- return;
2287
- default:
2288
- if (obsoletePatchCommands.includes(command)) {
2289
- logObsoletePatchCommand(command);
2290
- return;
2291
- }
2292
- throw new Error(`Unknown command: ${command}`);
2293
- }
2294
- })();
2295
- }
2296
- main();
2297
- //#endregion
2298
- export {};