weapp-tailwindcss 5.4.2 → 5.5.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 (89) hide show
  1. package/README.md +13 -1
  2. package/README.zh-CN.md +13 -1
  3. package/dist/bundlers/shared/v4-generation-core.d.ts +1 -0
  4. package/dist/bundlers/vite/capability-profile.d.ts +1 -0
  5. package/dist/bundlers/vite/css-finalizer/web-plugin.d.ts +3 -0
  6. package/dist/bundlers/vite/css-handler-options.d.ts +32 -0
  7. package/dist/bundlers/vite/{generate-bundle/css-output.d.ts → css-output.d.ts} +1 -1
  8. package/dist/bundlers/vite/frameworks/generic/web.d.ts +2 -0
  9. package/dist/bundlers/vite/generate-bundle/css-handler-options.d.ts +2 -32
  10. package/dist/bundlers/vite/generate-bundle/finalize/root-import-shell.d.ts +1 -1
  11. package/dist/bundlers/vite/generate-bundle/remembered-css-replay.d.ts +2 -2
  12. package/dist/bundlers/vite/generate-bundle/runtime.d.ts +1 -1
  13. package/dist/bundlers/vite/generate-bundle/uni-app-x-postprocess.d.ts +1 -1
  14. package/dist/bundlers/vite/generate-bundle.d.ts +1 -1
  15. package/dist/bundlers/vite/runtime-class-set.d.ts +1 -5
  16. package/dist/bundlers/vite/shared/create-css-only-plugins-runtime.d.ts +3 -0
  17. package/dist/cache-CBJFB1HN.cjs +223 -0
  18. package/dist/compiler/events.d.ts +32 -0
  19. package/dist/compiler/host.d.ts +13 -0
  20. package/dist/compiler/index.d.ts +3 -0
  21. package/dist/compiler/runtime-state.d.ts +17 -0
  22. package/dist/compiler-B0YSc0DY.js +4877 -0
  23. package/dist/{wxml-o-CUulAM.cjs → compiler-SwMb3lOX.cjs} +3649 -283
  24. package/dist/core.cjs +6 -3
  25. package/dist/core.d.ts +2 -0
  26. package/dist/core.js +4 -4
  27. package/dist/defaults-B5ep0ojb.js +120 -0
  28. package/dist/defaults-BI9j1znS.cjs +156 -0
  29. package/dist/defaults.cjs +5 -121
  30. package/dist/defaults.js +1 -116
  31. package/dist/final-css-cleanup-BMlUDzik.cjs +112 -0
  32. package/dist/final-css-cleanup-CmVYbXPr.js +282 -0
  33. package/dist/{generator-WlhrtNa3.cjs → generator-DsrQ9txU.cjs} +62 -5
  34. package/dist/{generator-BjK5PRR-.js → generator-DyXTBPmE.js} +47 -2
  35. package/dist/generator.cjs +1 -1
  36. package/dist/generator.js +1 -1
  37. package/dist/{gulp-D6LcfRz_.js → gulp-CVUiPXPy.js} +7 -7
  38. package/dist/{gulp-ChecVI6A.cjs → gulp-Dtc01FdI.cjs} +30 -28
  39. package/dist/gulp.cjs +1 -1
  40. package/dist/gulp.js +1 -1
  41. package/dist/{hmr-timing-afnWvy7u.cjs → hmr-timing-3SdRVfZx.cjs} +6 -229
  42. package/dist/{hmr-timing-CqDfjvqE.js → hmr-timing-DNxQm-bN.js} +6 -1258
  43. package/dist/index.cjs +4 -4
  44. package/dist/index.js +4 -4
  45. package/dist/{pipeline-helpers-DxPFMGxz.cjs → pipeline-helpers-DVrgv1HS.cjs} +6 -5
  46. package/dist/postcss.cjs +1 -1
  47. package/dist/postcss.js +1 -1
  48. package/dist/presets.cjs +4 -4
  49. package/dist/presets.js +2 -2
  50. package/dist/rspack.cjs +2 -2
  51. package/dist/rspack.js +2 -2
  52. package/dist/runtime-state-BBQcA0n5.cjs +54 -0
  53. package/dist/{source-candidate-scan-signature-FywFU3Rg.cjs → scoped-generator-B7thnzzm.cjs} +5 -123
  54. package/dist/{source-candidate-scan-signature-BVScymyM.js → scoped-generator-kRj_5Axx.js} +4 -92
  55. package/dist/source-candidate-scan-signature-B7cUxqqX.cjs +129 -0
  56. package/dist/source-candidate-scan-signature-CsP4BQNa.js +92 -0
  57. package/dist/style-injector/internal.d.ts +1 -1
  58. package/dist/style-injector/vite-web.d.ts +3 -0
  59. package/dist/{tailwindcss-9xmoCkaR.js → tailwindcss-BK9S7zuq.js} +1 -2
  60. package/dist/{tailwindcss-D3jltF7M.cjs → tailwindcss-C-jBBQfw.cjs} +8 -9
  61. package/dist/{transform-DQhgAarN.js → transform-C0rWZblB.js} +3 -3
  62. package/dist/{transform-C6k9zTQR.cjs → transform-C7QxW-fV.cjs} +27 -27
  63. package/dist/{v4-generation-core-CPKNwzjz.cjs → v4-generation-core-DuIVZvRz.cjs} +29 -1172
  64. package/dist/vite/web.cjs +27 -0
  65. package/dist/vite/web.d.ts +1 -0
  66. package/dist/vite/web.js +25 -0
  67. package/dist/{vite-D3aCtpmv.js → vite-0PsttwuR.js} +241 -3581
  68. package/dist/{vite-D-gmOkPN.cjs → vite-CJbO-7AQ.cjs} +494 -3794
  69. package/dist/vite-web.d.ts +4 -0
  70. package/dist/vite.cjs +1 -1
  71. package/dist/vite.js +1 -1
  72. package/dist/weapp-tw-css-generation-loader.cjs +1 -1
  73. package/dist/weapp-tw-css-import-rewrite-loader.cjs +5 -5
  74. package/dist/web-BFOkkJ-8.cjs +4357 -0
  75. package/dist/web-D8HSs56R.js +3792 -0
  76. package/dist/{webpack-yAne9ZYu.cjs → webpack-BWknqSDV.cjs} +51 -49
  77. package/dist/{webpack-B-6a8Z8F.js → webpack-DVtKeBq1.js} +13 -12
  78. package/dist/webpack.cjs +1 -1
  79. package/dist/webpack.js +1 -1
  80. package/package.json +12 -3
  81. package/dist/cache-options-DavPxrhC.cjs +0 -16
  82. package/dist/cache-options-DwBtLwQe.js +0 -5
  83. package/dist/compiler-B-m9VGqj.cjs +0 -2316
  84. package/dist/compiler-BgMj2E5l.js +0 -2051
  85. package/dist/local-style-matcher-DRpFEu1s.cjs +0 -34
  86. package/dist/local-style-matcher-DsiI2wIc.js +0 -17
  87. package/dist/object-B-8IHefx.js +0 -47
  88. package/dist/object-DbHtAXRk.cjs +0 -58
  89. package/dist/wxml-CvKyV69S.js +0 -1822
@@ -1,1822 +0,0 @@
1
- import { n as _defineProperty, t as omitUndefined } from "./object-B-8IHefx.js";
2
- import { n as HARD_PARSE_CACHE_MAX_ENTRIES, t as DEFAULT_PARSE_CACHE_MAX_SOURCE_LENGTH } from "./cache-options-DwBtLwQe.js";
3
- import { splitCandidateTokens } from "@tailwindcss-mangle/engine";
4
- import { LRUCache } from "lru-cache";
5
- import { defuOverrideArray } from "@weapp-tailwindcss/shared";
6
- import { md5 as md5Hash } from "@weapp-tailwindcss/shared/node";
7
- import { Parser } from "htmlparser2";
8
- import _babelTraverse from "@babel/traverse";
9
- import { parse, parseExpression } from "@babel/parser";
10
- import MagicString from "magic-string";
11
- import _createDebug from "debug";
12
- import { MappingChars2String, escape } from "@weapp-core/escape";
13
- import * as t from "@babel/types";
14
- //#region src/babel/index.ts
15
- function _interopDefaultCompat(e) {
16
- return e && typeof e === "object" && "default" in e ? e.default : e;
17
- }
18
- const traverse = _interopDefaultCompat(_babelTraverse);
19
- //#endregion
20
- //#region src/utils/regex.ts
21
- function escapeStringRegexp(str) {
22
- if (typeof str !== "string") throw new TypeError("Expected a string");
23
- return str.replaceAll(/[$()*+.?[\\\]^{|}]/g, "\\$&").replaceAll("-", "\\x2d");
24
- }
25
- //#endregion
26
- //#region src/utils/nameMatcher.ts
27
- const NEVER_MATCH_NAME$1 = () => false;
28
- const GLOBAL_FLAG_REGEXP = /g/g;
29
- function buildFuzzyMatcher(fuzzyStrings) {
30
- if (fuzzyStrings.length === 0) return;
31
- if (fuzzyStrings.length === 1) {
32
- const [needle] = fuzzyStrings;
33
- if (needle === void 0) return;
34
- return (value) => value.includes(needle);
35
- }
36
- const unique = [...new Set(fuzzyStrings)];
37
- const pattern = new RegExp(unique.map(escapeStringRegexp).join("|"));
38
- return (value) => pattern.test(value);
39
- }
40
- function normaliseRegex(regex) {
41
- const { source, flags } = regex;
42
- if (!flags.includes("g")) return regex;
43
- return new RegExp(source, flags.replace(GLOBAL_FLAG_REGEXP, ""));
44
- }
45
- function createNameMatcher(list, { exact = false } = {}) {
46
- if (!list || list.length === 0) return NEVER_MATCH_NAME$1;
47
- const exactStrings = exact ? /* @__PURE__ */ new Set() : void 0;
48
- const fuzzyStrings = [];
49
- const regexList = [];
50
- for (const item of list) if (typeof item === "string") {
51
- if (exact) exactStrings.add(item);
52
- else fuzzyStrings.push(item);
53
- } else regexList.push(normaliseRegex(item));
54
- if (exact) {
55
- const exactStringCount = exactStrings?.size ?? 0;
56
- if (exactStringCount === 1 && regexList.length === 0) {
57
- const [needle] = exactStrings;
58
- if (needle === void 0) return NEVER_MATCH_NAME$1;
59
- return (value) => value === needle;
60
- }
61
- if (regexList.length === 0) return (value) => exactStrings.has(value);
62
- if (exactStringCount === 0 && regexList.length === 1) {
63
- const [regex] = regexList;
64
- if (!regex) return NEVER_MATCH_NAME$1;
65
- return (value) => regex.test(value);
66
- }
67
- return (value) => {
68
- if (exactStrings?.has(value)) return true;
69
- return regexList.some((regex) => regex.test(value));
70
- };
71
- }
72
- const fuzzyMatcher = exact ? void 0 : buildFuzzyMatcher(fuzzyStrings);
73
- const hasRegex = regexList.length > 0;
74
- if (fuzzyMatcher && !hasRegex) return fuzzyMatcher;
75
- if (!fuzzyMatcher && regexList.length === 1) {
76
- const [regex] = regexList;
77
- if (!regex) return NEVER_MATCH_NAME$1;
78
- return (value) => regex.test(value);
79
- }
80
- return (value) => {
81
- if (fuzzyMatcher?.(value)) return true;
82
- if (!hasRegex) return false;
83
- return regexList.some((regex) => regex.test(value));
84
- };
85
- }
86
- //#endregion
87
- //#region src/js/babel/parse.ts
88
- const parseCache = new LRUCache({ max: HARD_PARSE_CACHE_MAX_ENTRIES });
89
- function genCacheKey(source, options) {
90
- if (typeof options === "string") return `${md5Hash(source)}:${options}`;
91
- return `${md5Hash(source)}:${JSON.stringify(options, (_, val) => typeof val === "function" ? val.toString() : val)}`;
92
- }
93
- function normalizeCacheMaxEntries(value) {
94
- if (typeof value !== "number" || !Number.isFinite(value)) return 128;
95
- return Math.min(Math.max(Math.floor(value), 0), HARD_PARSE_CACHE_MAX_ENTRIES);
96
- }
97
- function normalizeCacheMaxSourceLength(value) {
98
- if (typeof value !== "number" || !Number.isFinite(value)) return DEFAULT_PARSE_CACHE_MAX_SOURCE_LENGTH;
99
- return Math.max(Math.floor(value), 0);
100
- }
101
- function trimParseCache(maxEntries) {
102
- while (parseCache.size > maxEntries) parseCache.pop();
103
- }
104
- function babelParse(code, opts = {}) {
105
- const { cache, cacheKey, cacheMaxEntries, cacheMaxSourceLength, ...rest } = opts;
106
- const maxEntries = normalizeCacheMaxEntries(cacheMaxEntries);
107
- const maxSourceLength = normalizeCacheMaxSourceLength(cacheMaxSourceLength);
108
- const shouldCache = cache === true && maxEntries > 0 && code.length <= maxSourceLength;
109
- const cacheKeyString = shouldCache ? genCacheKey(code, cacheKey ?? rest) : void 0;
110
- let result;
111
- if (shouldCache) {
112
- trimParseCache(maxEntries);
113
- result = parseCache.get(cacheKeyString);
114
- }
115
- if (!result) {
116
- const { cache: _cache, cacheKey: _cacheKey, cacheMaxEntries: _cacheMaxEntries, cacheMaxSourceLength: _cacheMaxSourceLength, ...parseOptions } = opts;
117
- result = parse(code, parseOptions);
118
- if (shouldCache) {
119
- parseCache.set(cacheKeyString, result);
120
- trimParseCache(maxEntries);
121
- }
122
- }
123
- return result;
124
- }
125
- //#endregion
126
- //#region src/debug/index.ts
127
- const _debug = _createDebug("weapp-tw");
128
- function createDebug(prefix) {
129
- const debug = ((formatter, ...args) => {
130
- return _debug((prefix ?? "") + formatter, ...args);
131
- });
132
- Object.defineProperty(debug, "enabled", {
133
- enumerable: false,
134
- configurable: false,
135
- get() {
136
- return _debug.enabled;
137
- }
138
- });
139
- return debug;
140
- }
141
- //#endregion
142
- //#region src/wxml/shared.ts
143
- const NEWLINE_RE = /[\n\r]+/g;
144
- function replaceWxml(original, options = {
145
- keepEOL: false,
146
- escapeMap: MappingChars2String
147
- }) {
148
- const { keepEOL, escapeMap, ignoreHead } = options;
149
- let res = original;
150
- if (!keepEOL) res = res.replaceAll(NEWLINE_RE, "");
151
- res = escape(res, omitUndefined({
152
- map: escapeMap,
153
- ignoreHead
154
- }));
155
- return res;
156
- }
157
- //#endregion
158
- //#region src/shared/classname-transform.ts
159
- const escapedCandidateCacheByEscapeMap = /* @__PURE__ */ new WeakMap();
160
- const defaultEscapedCandidateCache = /* @__PURE__ */ new Map();
161
- let lastEscapedCandidateEscapeMap;
162
- let lastEscapedCandidateCacheStore;
163
- function isUrlLikeCandidate(candidate) {
164
- return candidate.startsWith("//") || candidate.startsWith("http://") || candidate.startsWith("https://");
165
- }
166
- function isPlainSlashPathCandidate(candidate) {
167
- const slashIndex = candidate.indexOf("/");
168
- if (slashIndex <= 0) return false;
169
- if (isUrlLikeCandidate(candidate)) return true;
170
- if (candidate.includes("[") || candidate.includes("]") || candidate.includes(":")) return false;
171
- return !candidate.slice(0, slashIndex).includes("-");
172
- }
173
- const SKIP_RESULT = { decision: "skip" };
174
- const DIRECT_RESULT = { decision: "direct" };
175
- function getEscapedCandidateCacheStore(escapeMap) {
176
- if (!escapeMap) return defaultEscapedCandidateCache;
177
- if (escapeMap === lastEscapedCandidateEscapeMap && lastEscapedCandidateCacheStore) return lastEscapedCandidateCacheStore;
178
- let store = escapedCandidateCacheByEscapeMap.get(escapeMap);
179
- if (!store) {
180
- store = /* @__PURE__ */ new Map();
181
- escapedCandidateCacheByEscapeMap.set(escapeMap, store);
182
- }
183
- lastEscapedCandidateEscapeMap = escapeMap;
184
- lastEscapedCandidateCacheStore = store;
185
- return store;
186
- }
187
- function getEscapedCandidate(candidate, escapeMap, store = getEscapedCandidateCacheStore(escapeMap)) {
188
- let cached = store.get(candidate);
189
- if (cached === void 0) {
190
- cached = replaceWxml(candidate, { escapeMap });
191
- store.set(candidate, cached);
192
- }
193
- return cached;
194
- }
195
- /**
196
- * JS 转译严格遵循 runtime class set:
197
- * 1. 直接命中 classNameSet 原始值;
198
- * 2. 兼容命中 classNameSet 中已转义值;
199
- * 3. 除显式 alwaysEscape 外,不允许绕过 classNameSet。
200
- *
201
- * 返回结构化结果,附带已计算的 escapedValue 以避免下游重复 escape。
202
- */
203
- function resolveClassNameTransformWithResult(candidate, { alwaysEscape, classNameSet, escapeMap, jsPreserveClass, classContext }) {
204
- if (jsPreserveClass?.(candidate)) return SKIP_RESULT;
205
- if (alwaysEscape) return DIRECT_RESULT;
206
- if (!classContext && isPlainSlashPathCandidate(candidate)) return SKIP_RESULT;
207
- if (classNameSet?.has(candidate)) return DIRECT_RESULT;
208
- if (classNameSet && classNameSet.size > 0) {
209
- const escapedCandidate = getEscapedCandidate(candidate, escapeMap);
210
- if (escapedCandidate !== candidate && classNameSet.has(escapedCandidate)) return {
211
- decision: "escaped",
212
- escapedValue: escapedCandidate
213
- };
214
- }
215
- return SKIP_RESULT;
216
- }
217
- //#endregion
218
- //#region src/utils/decode.ts
219
- const unicodeEscapeRE = /\\u([\dA-Fa-f]{4})/g;
220
- const unicodeEscapeTestRE = /\\u[\dA-Fa-f]{4}/;
221
- function decodeUnicode(value) {
222
- if (!unicodeEscapeTestRE.test(value)) return value;
223
- return value.replace(unicodeEscapeRE, (_match, hex) => {
224
- const codePoint = Number.parseInt(hex, 16);
225
- return Number.isNaN(codePoint) ? _match : String.fromCharCode(codePoint);
226
- });
227
- }
228
- function decodeUnicode2(input) {
229
- if (!unicodeEscapeTestRE.test(input)) return input;
230
- try {
231
- return JSON.parse(`"${input}"`);
232
- } catch (_error) {
233
- return decodeUnicode(input);
234
- }
235
- }
236
- //#endregion
237
- //#region src/js/class-context.ts
238
- const CLASS_LIKE_KEYWORDS = /* @__PURE__ */ new Set([
239
- "class",
240
- "classname",
241
- "hoverclass",
242
- "virtualhostclass",
243
- "rootclass"
244
- ]);
245
- const CLASS_HELPER_IDENTIFIERS = /* @__PURE__ */ new Set([
246
- "cn",
247
- "clsx",
248
- "classnames",
249
- "twmerge",
250
- "cva",
251
- "tv",
252
- "cx",
253
- "r"
254
- ]);
255
- const DASH_CODE = 45;
256
- const COLON_CODE = 58;
257
- const UPPERCASE_A_CODE = 65;
258
- const UPPERCASE_Z_CODE = 90;
259
- const UNDERSCORE_CODE = 95;
260
- const ASCII_MAX_CODE = 127;
261
- const NORMALIZE_KEYWORD_REGEXP = /[-_:]/g;
262
- function normalizeKeyword(name) {
263
- const length = name.length;
264
- let firstNormalizedIndex = -1;
265
- for (let i = 0; i < length; i++) {
266
- const code = name.charCodeAt(i);
267
- if (code === DASH_CODE || code === UNDERSCORE_CODE || code === COLON_CODE || code >= UPPERCASE_A_CODE && code <= UPPERCASE_Z_CODE) {
268
- firstNormalizedIndex = i;
269
- break;
270
- }
271
- if (code > ASCII_MAX_CODE) return name.replace(NORMALIZE_KEYWORD_REGEXP, "").toLowerCase();
272
- }
273
- if (firstNormalizedIndex === -1) return name;
274
- let normalized = name.slice(0, firstNormalizedIndex);
275
- for (let i = firstNormalizedIndex; i < length; i++) {
276
- const code = name.charCodeAt(i);
277
- if (code === DASH_CODE || code === UNDERSCORE_CODE || code === COLON_CODE) continue;
278
- if (code >= UPPERCASE_A_CODE && code <= UPPERCASE_Z_CODE) {
279
- normalized += String.fromCharCode(code + 32);
280
- continue;
281
- }
282
- if (code > ASCII_MAX_CODE) return name.replace(NORMALIZE_KEYWORD_REGEXP, "").toLowerCase();
283
- normalized += name[i];
284
- }
285
- return normalized;
286
- }
287
- function readObjectKeyName(path) {
288
- if (path.isIdentifier()) return path.node.name;
289
- if (path.isStringLiteral()) return path.node.value;
290
- if (path.isTemplateLiteral() && path.node.expressions.length === 0) return path.node.quasis[0]?.value.cooked ?? path.node.quasis[0]?.value.raw;
291
- }
292
- function isClassLikeObjectProperty(path, valuePath) {
293
- if (!path.isObjectProperty()) return false;
294
- if (path.get("value") !== valuePath) return false;
295
- const keyName = readObjectKeyName(path.get("key"));
296
- if (!keyName) return false;
297
- return CLASS_LIKE_KEYWORDS.has(normalizeKeyword(keyName));
298
- }
299
- function isClassLikeJsxAttribute(path) {
300
- if (!path.isJSXAttribute()) return false;
301
- const namePath = path.get("name");
302
- if (!namePath.isJSXIdentifier()) return false;
303
- return CLASS_LIKE_KEYWORDS.has(normalizeKeyword(namePath.node.name));
304
- }
305
- function readCallHelperName(calleePath) {
306
- if (calleePath.isIdentifier()) return calleePath.node.name;
307
- if (calleePath.isMemberExpression()) {
308
- const propertyPath = calleePath.get("property");
309
- if (propertyPath.isIdentifier()) return propertyPath.node.name;
310
- if (propertyPath.isStringLiteral()) return propertyPath.node.value;
311
- }
312
- }
313
- function isClassLikeCallExpression(path, valuePath) {
314
- if (!path.isCallExpression()) return false;
315
- const helperName = readCallHelperName(path.get("callee"));
316
- if (!helperName || !CLASS_HELPER_IDENTIFIERS.has(normalizeKeyword(helperName))) return false;
317
- return path.get("arguments").some((argumentPath) => argumentPath.node === valuePath.node);
318
- }
319
- /**
320
- * 判断字符串字面量是否处于 class 语义上下文。
321
- * 仅用于受控兜底场景,避免将普通业务文本误判为 class。
322
- */
323
- function isClassContextLiteralPath(path) {
324
- let current = path;
325
- while (current.parentPath) {
326
- const parent = current.parentPath;
327
- if (isClassLikeObjectProperty(parent, current)) return true;
328
- if (isClassLikeJsxAttribute(parent)) return true;
329
- if (isClassLikeCallExpression(parent, current)) return true;
330
- current = parent;
331
- }
332
- return false;
333
- }
334
- //#endregion
335
- //#region src/js/js-string-escape.ts
336
- function jsStringEscape(value) {
337
- return String(value).replaceAll(/[\n\r"'\\\u2028\u2029]/g, (character) => {
338
- switch (character) {
339
- case "\"":
340
- case "'":
341
- case "\\": return `\\${character}`;
342
- case "\n": return "\\n";
343
- case "\r": return "\\r";
344
- case "\u2028": return "\\u2028";
345
- case "\u2029": return "\\u2029";
346
- default: return character;
347
- }
348
- });
349
- }
350
- //#endregion
351
- //#region src/js/replacement-cache.ts
352
- const replacementCacheByEscapeMap = /* @__PURE__ */ new WeakMap();
353
- const defaultReplacementCache = /* @__PURE__ */ new Map();
354
- function getReplacementCacheStore(escapeMap) {
355
- if (!escapeMap) return defaultReplacementCache;
356
- let store = replacementCacheByEscapeMap.get(escapeMap);
357
- if (!store) {
358
- store = /* @__PURE__ */ new Map();
359
- replacementCacheByEscapeMap.set(escapeMap, store);
360
- }
361
- return store;
362
- }
363
- function getReplacement(candidate, escapeMap, store = getReplacementCacheStore(escapeMap)) {
364
- let cached = store.get(candidate);
365
- if (cached === void 0) {
366
- cached = replaceWxml(candidate, { escapeMap });
367
- store.set(candidate, cached);
368
- }
369
- return cached;
370
- }
371
- //#endregion
372
- //#region src/js/handlers.ts
373
- const debug = createDebug("[js:handlers] ");
374
- const WEAPP_TW_IGNORE_MARKER = "weapp-tw";
375
- const IGNORE_MARKER = "ignore";
376
- function hasIgnoreComment(node) {
377
- const { leadingComments } = node;
378
- if (!Array.isArray(leadingComments) || leadingComments.length === 0) return false;
379
- for (const comment of leadingComments) {
380
- const { value } = comment;
381
- if (value.includes(WEAPP_TW_IGNORE_MARKER) && value.includes(IGNORE_MARKER)) return true;
382
- }
383
- return false;
384
- }
385
- function isConditionTestLiteral(path) {
386
- let current = path;
387
- while (current?.parentPath) {
388
- const parent = current.parentPath;
389
- if (parent.isConditionalExpression()) return parent.node.test === current.node;
390
- if (parent.isBinaryExpression() || parent.isCallExpression() || parent.isLogicalExpression() || parent.isMemberExpression() || parent.isUnaryExpression()) {
391
- current = parent;
392
- continue;
393
- }
394
- return false;
395
- }
396
- return false;
397
- }
398
- function extractLiteralValue(path, { unescapeUnicode }) {
399
- const { node } = path;
400
- let offset = 0;
401
- let original;
402
- if (node.type === "StringLiteral") {
403
- offset = 1;
404
- original = node.value;
405
- } else if (node.type === "TemplateElement") original = node.value.raw;
406
- else original = "";
407
- let literal = original;
408
- if (unescapeUnicode && original.includes("\\u")) literal = decodeUnicode2(original);
409
- return {
410
- literal,
411
- offset,
412
- original
413
- };
414
- }
415
- function createCandidatePlanResolver(options, classContext) {
416
- const { escapeMap } = options;
417
- const replacementCache = getReplacementCacheStore(escapeMap);
418
- const transformOptions = classContext ? {
419
- ...options,
420
- classContext
421
- } : options;
422
- let firstCandidate = "";
423
- let firstPlan;
424
- let cache;
425
- const buildCandidatePlan = (candidate) => {
426
- const result = resolveClassNameTransformWithResult(candidate, transformOptions);
427
- if (result.decision === "skip") return { result };
428
- let replacement;
429
- if (result.decision === "escaped" && result.escapedValue) {
430
- replacement = result.escapedValue;
431
- replacementCache.set(candidate, replacement);
432
- } else replacement = getReplacement(candidate, escapeMap, replacementCache);
433
- return {
434
- result,
435
- replacement
436
- };
437
- };
438
- return (candidate) => {
439
- if (cache) {
440
- const cached = cache.get(candidate);
441
- if (cached) return cached;
442
- } else if (firstPlan && candidate === firstCandidate) return firstPlan;
443
- const plan = buildCandidatePlan(candidate);
444
- if (!firstPlan) {
445
- firstCandidate = candidate;
446
- firstPlan = plan;
447
- return plan;
448
- }
449
- if (!cache) {
450
- cache = /* @__PURE__ */ new Map();
451
- cache.set(firstCandidate, firstPlan);
452
- }
453
- cache.set(candidate, plan);
454
- return plan;
455
- };
456
- }
457
- function replaceHandleValue(path, options) {
458
- const { needEscaped = false } = options;
459
- const { classNameSet, alwaysEscape } = options;
460
- if (!alwaysEscape && (!classNameSet || classNameSet.size === 0)) return;
461
- if (hasIgnoreComment(path.node)) return;
462
- if (isConditionTestLiteral(path)) return;
463
- const { literal, original, offset } = extractLiteralValue(path, options);
464
- const candidates = splitCandidateTokens(literal);
465
- if (candidates.length === 0) return;
466
- const debugEnabled = debug.enabled;
467
- const classContext = options.wrapExpression || isClassContextLiteralPath(path);
468
- let transformed = literal;
469
- let mutated = false;
470
- let matchedCandidateCount = 0;
471
- let escapedDecisionCount = 0;
472
- let escapedSamples;
473
- let skippedSamples;
474
- const resolveCandidatePlan = createCandidatePlanResolver(options, classContext);
475
- for (const candidate of candidates) {
476
- const plan = resolveCandidatePlan(candidate);
477
- if (plan.result.decision === "skip") {
478
- if (debugEnabled) {
479
- if (!skippedSamples) skippedSamples = [];
480
- if (skippedSamples.length < 6) skippedSamples.push(candidate);
481
- }
482
- continue;
483
- }
484
- if (debugEnabled) {
485
- matchedCandidateCount += 1;
486
- if (plan.result.decision === "escaped") {
487
- escapedDecisionCount += 1;
488
- if (!escapedSamples) escapedSamples = [];
489
- if (escapedSamples.length < 6) escapedSamples.push(candidate);
490
- }
491
- }
492
- const replaced = transformed.replace(candidate, plan.replacement);
493
- if (replaced !== transformed) {
494
- transformed = replaced;
495
- mutated = true;
496
- }
497
- }
498
- const node = path.node;
499
- if (!mutated || typeof node.start !== "number" || typeof node.end !== "number") return;
500
- 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(",") || "-");
501
- const start = node.start + offset;
502
- const end = node.end - offset;
503
- if (start >= end || transformed === original) return;
504
- return {
505
- start,
506
- end,
507
- value: needEscaped ? jsStringEscape(transformed) : transformed,
508
- path
509
- };
510
- }
511
- //#endregion
512
- //#region src/js/sourceAnalysis.ts
513
- function hasReplacementEntries(replacements) {
514
- for (const key in replacements) if (Object.hasOwn(replacements, key)) return true;
515
- return false;
516
- }
517
- function createModuleSpecifierReplacementToken(path, replacement) {
518
- const node = path.node;
519
- if (node.value === replacement) return;
520
- if (typeof node.start !== "number" || typeof node.end !== "number") return;
521
- const start = node.start + 1;
522
- const end = node.end - 1;
523
- if (start >= end) return;
524
- return {
525
- start,
526
- end,
527
- value: replacement,
528
- path
529
- };
530
- }
531
- function collectModuleSpecifierReplacementTokens(analysis, replacements) {
532
- if (!hasReplacementEntries(replacements)) return [];
533
- if (analysis.importDeclarations.size === 0 && analysis.exportDeclarations.size === 0 && analysis.requireCallPaths.length === 0 && analysis.walker.imports.size === 0) return [];
534
- const tokens = [];
535
- const applyReplacement = (path) => {
536
- const replacement = replacements[path.node.value];
537
- if (!replacement) return;
538
- const token = createModuleSpecifierReplacementToken(path, replacement);
539
- if (token) tokens.push(token);
540
- };
541
- for (const importPath of analysis.importDeclarations) {
542
- const source = importPath.get("source");
543
- if (source.isStringLiteral()) applyReplacement(source);
544
- }
545
- for (const exportPath of analysis.exportDeclarations) if (exportPath.isExportNamedDeclaration() || exportPath.isExportAllDeclaration()) {
546
- const source = exportPath.get("source");
547
- if (source && !Array.isArray(source) && source.isStringLiteral()) applyReplacement(source);
548
- }
549
- for (const literalPath of analysis.requireCallPaths) applyReplacement(literalPath);
550
- for (const token of analysis.walker.imports) {
551
- const replacement = replacements[token.source];
552
- if (replacement) token.source = replacement;
553
- }
554
- return tokens;
555
- }
556
- //#endregion
557
- //#region src/js/babel/process.ts
558
- const optionVariantsCache = /* @__PURE__ */ new WeakMap();
559
- function getNeedEscapedOptions(options, needEscaped) {
560
- if (options.needEscaped === needEscaped) return options;
561
- let cached = optionVariantsCache.get(options);
562
- if (!cached) {
563
- cached = {};
564
- optionVariantsCache.set(options, cached);
565
- }
566
- if (needEscaped) {
567
- if (!cached.stringLiteralOptions) cached.stringLiteralOptions = {
568
- ...options,
569
- needEscaped: true
570
- };
571
- return cached.stringLiteralOptions;
572
- }
573
- if (!cached.templateLiteralOptions) cached.templateLiteralOptions = {
574
- ...options,
575
- needEscaped: false
576
- };
577
- return cached.templateLiteralOptions;
578
- }
579
- function processUpdatedSource(rawSource, options, analysis) {
580
- const { targetPaths, jsTokenUpdater, ignoredPaths } = analysis;
581
- if (targetPaths.length === 0 && !options.moduleSpecifierReplacements && jsTokenUpdater.length === 0) return new MagicString(rawSource);
582
- const replacementTokens = [];
583
- for (const path of targetPaths) {
584
- if (ignoredPaths.has(path)) continue;
585
- const token = replaceHandleValue(path, path.isStringLiteral() ? getNeedEscapedOptions(options, true) : getNeedEscapedOptions(options, false));
586
- if (token) replacementTokens.push(token);
587
- }
588
- if (options.moduleSpecifierReplacements) replacementTokens.push(...collectModuleSpecifierReplacementTokens(analysis, options.moduleSpecifierReplacements));
589
- if (jsTokenUpdater.length + replacementTokens.length === 0) return new MagicString(rawSource);
590
- const ms = new MagicString(rawSource);
591
- jsTokenUpdater.push(...replacementTokens).filter((token) => !ignoredPaths.has(token.path)).updateMagicString(ms);
592
- return ms;
593
- }
594
- //#endregion
595
- //#region src/js/evalTransforms.ts
596
- const evalHandlerOptionsCache = /* @__PURE__ */ new WeakMap();
597
- const EVAL_SCOPE_ERROR_REGEXP = /pass a scope and parentPath|traversing a Program\/File/i;
598
- function isEvalPath(path) {
599
- if (path.isCallExpression()) return path.get("callee").isIdentifier({ name: "eval" });
600
- return false;
601
- }
602
- function createEvalReplacementToken(path, updated) {
603
- const node = path.node;
604
- let offset = 0;
605
- let original;
606
- if (path.isStringLiteral()) {
607
- offset = 1;
608
- original = path.node.value;
609
- } else if (path.isTemplateElement()) original = path.node.value.raw;
610
- else original = "";
611
- if (typeof node.start !== "number" || typeof node.end !== "number") return;
612
- const start = node.start + offset;
613
- const end = node.end - offset;
614
- if (start >= end) return;
615
- if (original === updated) return;
616
- return {
617
- start,
618
- end,
619
- value: path.isStringLiteral() ? jsStringEscape(updated) : updated,
620
- path
621
- };
622
- }
623
- function handleEvalStringLiteral(path, handlerOptions, updater, handler) {
624
- const { code } = handler(path.node.value, handlerOptions);
625
- if (!code) return;
626
- const token = createEvalReplacementToken(path, code);
627
- if (token) updater.addToken(token);
628
- }
629
- function handleEvalTemplateElement(path, handlerOptions, updater, handler) {
630
- const { code } = handler(path.node.value.raw, handlerOptions);
631
- if (!code) return;
632
- const token = createEvalReplacementToken(path, code);
633
- if (token) updater.addToken(token);
634
- }
635
- function getEvalStringHandlerOptions(options) {
636
- if (options.needEscaped === false && options.generateMap === false) return options;
637
- let cached = evalHandlerOptionsCache.get(options);
638
- if (!cached) {
639
- cached = {};
640
- evalHandlerOptionsCache.set(options, cached);
641
- }
642
- if (!cached.stringLiteralOptions) cached.stringLiteralOptions = {
643
- ...options,
644
- needEscaped: false,
645
- generateMap: false
646
- };
647
- return cached.stringLiteralOptions;
648
- }
649
- function getEvalTemplateHandlerOptions(options) {
650
- if (options.generateMap === false) return options;
651
- let cached = evalHandlerOptionsCache.get(options);
652
- if (!cached) {
653
- cached = {};
654
- evalHandlerOptionsCache.set(options, cached);
655
- }
656
- if (!cached.templateLiteralOptions) cached.templateLiteralOptions = {
657
- ...options,
658
- generateMap: false
659
- };
660
- return cached.templateLiteralOptions;
661
- }
662
- function walkEvalExpression(path, options, updater, handler) {
663
- const stringHandlerOptions = getEvalStringHandlerOptions(options);
664
- const templateHandlerOptions = getEvalTemplateHandlerOptions(options);
665
- const maybeTraverse = path?.traverse;
666
- if (typeof maybeTraverse === "function") try {
667
- return maybeTraverse.call(path, {
668
- StringLiteral(innerPath) {
669
- handleEvalStringLiteral(innerPath, stringHandlerOptions, updater, handler);
670
- },
671
- TemplateElement(innerPath) {
672
- handleEvalTemplateElement(innerPath, templateHandlerOptions, updater, handler);
673
- }
674
- });
675
- } catch (error) {
676
- const msg = error?.message ?? "";
677
- if (!EVAL_SCOPE_ERROR_REGEXP.test(msg)) throw error;
678
- }
679
- const getArgs = path?.get?.("arguments");
680
- if (Array.isArray(getArgs)) {
681
- for (const arg of getArgs) {
682
- if (arg?.isStringLiteral?.()) {
683
- handleEvalStringLiteral(arg, stringHandlerOptions, updater, handler);
684
- continue;
685
- }
686
- if (arg?.isTemplateLiteral?.()) for (const quasi of arg.get("quasis")) handleEvalTemplateElement(quasi, templateHandlerOptions, updater, handler);
687
- }
688
- return;
689
- }
690
- const nodeArgs = path?.node?.arguments;
691
- if (Array.isArray(nodeArgs)) {
692
- for (const n of nodeArgs) if (n?.type === "StringLiteral") handleEvalStringLiteral({
693
- node: n,
694
- isStringLiteral: () => true
695
- }, stringHandlerOptions, updater, handler);
696
- else if (n?.type === "TemplateLiteral" && Array.isArray(n.quasis)) for (const q of n.quasis) handleEvalTemplateElement({
697
- node: q,
698
- isStringLiteral: () => false,
699
- isTemplateElement: () => true
700
- }, templateHandlerOptions, updater, handler);
701
- }
702
- }
703
- //#endregion
704
- //#region src/js/JsTokenUpdater.ts
705
- /**
706
- * Lightweight helper that batches updates to {@link MagicString}.
707
- * It keeps the transformation logic out of the traversal code and makes
708
- * it easier to reason about the order in which tokens are written back.
709
- */
710
- var JsTokenUpdater = class {
711
- constructor({ value } = {}) {
712
- _defineProperty(this, "tokens", void 0);
713
- this.tokens = value ? [...value] : [];
714
- }
715
- addToken(token) {
716
- if (token) this.tokens.push(token);
717
- }
718
- push(...args) {
719
- this.tokens.push(...args);
720
- return this;
721
- }
722
- /**
723
- * 待写入的 token 数量。
724
- */
725
- get length() {
726
- return this.tokens.length;
727
- }
728
- map(callbackfn) {
729
- this.tokens = this.tokens.map(callbackfn);
730
- return this;
731
- }
732
- filter(callbackfn) {
733
- this.tokens = this.tokens.filter(callbackfn);
734
- return this;
735
- }
736
- updateMagicString(ms) {
737
- for (const { start, end, value } of this.tokens) ms.update(start, end, value);
738
- return ms;
739
- }
740
- };
741
- //#endregion
742
- //#region src/js/module-graph/ignored-exports.ts
743
- var IgnoredExportsTracker = class {
744
- constructor(options) {
745
- this.options = options;
746
- _defineProperty(this, "ignoredExportNames", /* @__PURE__ */ new Map());
747
- }
748
- addIgnoredExport(filename, exportName) {
749
- if (!exportName) return;
750
- let pending = this.ignoredExportNames.get(filename);
751
- if (!pending) {
752
- pending = /* @__PURE__ */ new Set();
753
- this.ignoredExportNames.set(filename, pending);
754
- }
755
- if (pending.has(exportName)) return;
756
- pending.add(exportName);
757
- const existing = this.options.modules.get(filename);
758
- if (existing) this.applyIgnoredExportsToAnalysis(filename, existing.analysis);
759
- }
760
- registerIgnoredExportsFromTokens(resolved, tokens) {
761
- for (const token of tokens) if (token.type === "ImportSpecifier") this.addIgnoredExport(resolved, token.imported);
762
- else if (token.type === "ImportDefaultSpecifier") this.addIgnoredExport(resolved, "default");
763
- }
764
- applyIgnoredExportsToAnalysis(filename, analysis) {
765
- const pending = this.ignoredExportNames.get(filename);
766
- if (!pending || pending.size === 0) return;
767
- const names = new Set(pending);
768
- pending.clear();
769
- const propagate = [];
770
- for (const exportPath of analysis.exportDeclarations) {
771
- if (names.size === 0) break;
772
- if (exportPath.isExportDefaultDeclaration()) {
773
- if (names.has("default")) {
774
- analysis.walker.walkExportDefaultDeclaration(exportPath);
775
- names.delete("default");
776
- }
777
- continue;
778
- }
779
- if (exportPath.isExportNamedDeclaration()) {
780
- const source = exportPath.node.source?.value;
781
- if (typeof source === "string") {
782
- for (const spec of exportPath.get("specifiers")) {
783
- if (!spec.isExportSpecifier()) continue;
784
- const exported = spec.get("exported");
785
- let exportedName;
786
- if (exported.isIdentifier()) exportedName = exported.node.name;
787
- else if (exported.isStringLiteral()) exportedName = exported.node.value;
788
- if (!exportedName || !names.has(exportedName)) continue;
789
- const local = spec.get("local");
790
- if (local.isIdentifier()) {
791
- propagate.push({
792
- specifier: source,
793
- exportName: local.node.name
794
- });
795
- names.delete(exportedName);
796
- } else if (local.isStringLiteral()) {
797
- propagate.push({
798
- specifier: source,
799
- exportName: local.node.value
800
- });
801
- names.delete(exportedName);
802
- }
803
- }
804
- continue;
805
- }
806
- const declaration = exportPath.get("declaration");
807
- if (declaration.isVariableDeclaration()) for (const decl of declaration.get("declarations")) {
808
- const id = decl.get("id");
809
- if (id.isIdentifier()) {
810
- const exportName = id.node.name;
811
- if (names.has(exportName)) {
812
- analysis.walker.walkVariableDeclarator(decl);
813
- names.delete(exportName);
814
- }
815
- }
816
- }
817
- for (const spec of exportPath.get("specifiers")) {
818
- if (!spec.isExportSpecifier()) continue;
819
- const exported = spec.get("exported");
820
- let exportedName;
821
- if (exported.isIdentifier()) exportedName = exported.node.name;
822
- else if (exported.isStringLiteral()) exportedName = exported.node.value;
823
- if (!exportedName || !names.has(exportedName)) continue;
824
- const local = spec.get("local");
825
- analysis.walker.walkNode(local);
826
- names.delete(exportedName);
827
- }
828
- continue;
829
- }
830
- if (exportPath.isExportAllDeclaration()) {
831
- const source = exportPath.node.source?.value;
832
- if (typeof source === "string") {
833
- for (const exportName of names) propagate.push({
834
- specifier: source,
835
- exportName
836
- });
837
- names.clear();
838
- }
839
- }
840
- }
841
- for (const { specifier, exportName } of propagate) {
842
- let resolved;
843
- try {
844
- resolved = this.options.resolve(specifier, filename);
845
- } catch {
846
- resolved = void 0;
847
- }
848
- if (!resolved) {
849
- pending.add(exportName);
850
- continue;
851
- }
852
- if (this.options.filter && !this.options.filter(resolved, specifier, filename)) {
853
- pending.add(exportName);
854
- continue;
855
- }
856
- this.addIgnoredExport(resolved, exportName);
857
- }
858
- for (const name of names) pending.add(name);
859
- }
860
- };
861
- //#endregion
862
- //#region src/js/ModuleGraph.ts
863
- var JsModuleGraph = class {
864
- constructor(entry, graphOptions) {
865
- _defineProperty(this, "modules", /* @__PURE__ */ new Map());
866
- _defineProperty(this, "queue", []);
867
- _defineProperty(this, "resolve", void 0);
868
- _defineProperty(this, "load", void 0);
869
- _defineProperty(this, "filter", void 0);
870
- _defineProperty(this, "maxDepth", void 0);
871
- _defineProperty(this, "baseOptions", void 0);
872
- _defineProperty(this, "parserOptions", void 0);
873
- _defineProperty(this, "rootFilename", void 0);
874
- _defineProperty(this, "ignoredExports", void 0);
875
- this.resolve = graphOptions.resolve;
876
- this.load = graphOptions.load;
877
- this.filter = graphOptions.filter;
878
- this.maxDepth = graphOptions.maxDepth ?? Number.POSITIVE_INFINITY;
879
- const { moduleGraph: _moduleGraph, filename: _ignoredFilename, ...rest } = entry.handlerOptions;
880
- this.baseOptions = {
881
- ...rest,
882
- filename: entry.filename
883
- };
884
- this.parserOptions = entry.handlerOptions.babelParserOptions;
885
- this.rootFilename = entry.filename;
886
- this.ignoredExports = new IgnoredExportsTracker({
887
- resolve: this.resolve,
888
- filter: this.filter,
889
- modules: this.modules
890
- });
891
- this.modules.set(entry.filename, {
892
- filename: entry.filename,
893
- source: entry.source,
894
- analysis: entry.analysis
895
- });
896
- this.queue.push({
897
- filename: entry.filename,
898
- depth: 0
899
- });
900
- }
901
- build() {
902
- this.collectDependencies();
903
- let linked;
904
- for (const [filename, state] of this.modules) {
905
- if (filename === this.rootFilename) continue;
906
- const childOptions = {
907
- ...this.baseOptions,
908
- filename
909
- };
910
- const code = processUpdatedSource(state.source, childOptions, state.analysis).toString();
911
- if (code !== state.source) {
912
- if (!linked) linked = {};
913
- linked[filename] = { code };
914
- }
915
- }
916
- return linked;
917
- }
918
- collectDependencies() {
919
- while (this.queue.length > 0) {
920
- const { filename, depth } = this.queue.shift();
921
- if (depth >= this.maxDepth) continue;
922
- const state = this.modules.get(filename);
923
- if (!state) continue;
924
- const dependencySpecifiers = /* @__PURE__ */ new Map();
925
- for (const token of state.analysis.walker.imports) {
926
- if (!dependencySpecifiers.has(token.source)) dependencySpecifiers.set(token.source, []);
927
- dependencySpecifiers.get(token.source).push(token);
928
- }
929
- for (const exportPath of state.analysis.exportDeclarations) if (exportPath.isExportAllDeclaration() || exportPath.isExportNamedDeclaration()) {
930
- const source = exportPath.node.source?.value;
931
- if (typeof source === "string" && !dependencySpecifiers.has(source)) dependencySpecifiers.set(source, []);
932
- }
933
- for (const [specifier, tokens] of dependencySpecifiers) {
934
- let resolved;
935
- try {
936
- resolved = this.resolve(specifier, filename);
937
- } catch {
938
- continue;
939
- }
940
- if (!resolved) continue;
941
- if (this.filter && !this.filter(resolved, specifier, filename)) continue;
942
- if (tokens.length > 0) this.ignoredExports.registerIgnoredExportsFromTokens(resolved, tokens);
943
- if (this.modules.has(resolved)) continue;
944
- let source;
945
- try {
946
- source = this.load(resolved);
947
- } catch {
948
- continue;
949
- }
950
- if (typeof source !== "string") continue;
951
- let analysis;
952
- try {
953
- analysis = analyzeSource(babelParse(source, {
954
- ...this.parserOptions,
955
- sourceFilename: resolved
956
- }), {
957
- ...this.baseOptions,
958
- filename: resolved
959
- });
960
- this.ignoredExports.applyIgnoredExportsToAnalysis(resolved, analysis);
961
- } catch {
962
- continue;
963
- }
964
- this.modules.set(resolved, {
965
- filename: resolved,
966
- source,
967
- analysis
968
- });
969
- this.queue.push({
970
- filename: resolved,
971
- depth: depth + 1
972
- });
973
- }
974
- }
975
- }
976
- };
977
- //#endregion
978
- //#region src/js/node-path-walker/export-handlers.ts
979
- function walkExportDeclaration(ctx, path) {
980
- if (path.isExportDeclaration()) {
981
- if (path.isExportNamedDeclaration()) walkExportNamedDeclaration(ctx, path);
982
- else if (path.isExportDefaultDeclaration()) walkExportDefaultDeclaration(ctx, path);
983
- else if (path.isExportAllDeclaration()) walkExportAllDeclaration(ctx, path);
984
- }
985
- }
986
- function walkExportNamedDeclaration(ctx, path) {
987
- const declaration = path.get("declaration");
988
- if (declaration.isVariableDeclaration()) for (const decl of declaration.get("declarations")) ctx.walkNode(decl);
989
- const specifiers = path.get("specifiers");
990
- for (const spec of specifiers) if (spec.isExportSpecifier()) {
991
- const local = spec.get("local");
992
- if (local.isIdentifier()) ctx.walkNode(local);
993
- }
994
- }
995
- function walkExportDefaultDeclaration(ctx, path) {
996
- const decl = path.get("declaration");
997
- if (decl.isIdentifier()) ctx.walkNode(decl);
998
- else ctx.walkNode(decl);
999
- }
1000
- function walkExportAllDeclaration(ctx, path) {
1001
- const source = path.get("source");
1002
- if (source.isStringLiteral()) ctx.addImportToken({
1003
- declaration: path,
1004
- source: source.node.value,
1005
- type: "ExportAllDeclaration"
1006
- });
1007
- }
1008
- //#endregion
1009
- //#region src/js/node-path-walker/import-tokens.ts
1010
- function maybeAddImportToken(imports, arg) {
1011
- if (!(arg.isImportSpecifier() && arg.node.importKind !== "type" || arg.isImportDefaultSpecifier())) return false;
1012
- const importDeclaration = arg.parentPath;
1013
- if (!importDeclaration.isImportDeclaration() || importDeclaration.node.importKind === "type") return false;
1014
- if (arg.isImportSpecifier()) {
1015
- const imported = arg.get("imported");
1016
- if (imported.isIdentifier()) imports.add({
1017
- declaration: importDeclaration,
1018
- specifier: arg,
1019
- imported: imported.node.name,
1020
- local: arg.node.local.name,
1021
- source: importDeclaration.node.source.value,
1022
- type: "ImportSpecifier"
1023
- });
1024
- return true;
1025
- }
1026
- imports.add({
1027
- declaration: importDeclaration,
1028
- specifier: arg,
1029
- local: arg.node.local.name,
1030
- source: importDeclaration.node.source.value,
1031
- type: "ImportDefaultSpecifier"
1032
- });
1033
- return true;
1034
- }
1035
- //#endregion
1036
- //#region src/js/NodePathWalker.ts
1037
- const EMPTY_IGNORE_CALL_EXPRESSION_IDENTIFIERS = [];
1038
- const EMPTY_IMPORT_TOKENS = /* @__PURE__ */ new Set();
1039
- function NOOP_STRING_PATH_CALLBACK() {}
1040
- const NEVER_MATCH_NAME = () => false;
1041
- /**
1042
- * 遍历我们关注的调用表达式所关联的绑定,收集后续需要转换的字符串节点。
1043
- */
1044
- var NodePathWalker = class {
1045
- constructor({ ignoreCallExpressionIdentifiers, callback } = {}) {
1046
- _defineProperty(this, "ignoreCallExpressionIdentifiers", void 0);
1047
- _defineProperty(this, "callback", void 0);
1048
- _defineProperty(this, "isIgnoredCallIdentifier", void 0);
1049
- _defineProperty(this, "hasIgnoredCallIdentifiers", void 0);
1050
- _defineProperty(this, "importsStore", void 0);
1051
- _defineProperty(this, "visitedStore", void 0);
1052
- this.hasIgnoredCallIdentifiers = Boolean(ignoreCallExpressionIdentifiers && ignoreCallExpressionIdentifiers.length > 0);
1053
- this.ignoreCallExpressionIdentifiers = ignoreCallExpressionIdentifiers ?? EMPTY_IGNORE_CALL_EXPRESSION_IDENTIFIERS;
1054
- this.callback = callback ?? NOOP_STRING_PATH_CALLBACK;
1055
- this.isIgnoredCallIdentifier = this.hasIgnoredCallIdentifiers ? createNameMatcher(this.ignoreCallExpressionIdentifiers, { exact: true }) : NEVER_MATCH_NAME;
1056
- }
1057
- get imports() {
1058
- return this.importsStore ?? EMPTY_IMPORT_TOKENS;
1059
- }
1060
- getWritableImports() {
1061
- if (!this.importsStore) this.importsStore = /* @__PURE__ */ new Set();
1062
- return this.importsStore;
1063
- }
1064
- addImportToken(token) {
1065
- this.getWritableImports().add(token);
1066
- }
1067
- getVisited() {
1068
- if (!this.visitedStore) this.visitedStore = /* @__PURE__ */ new WeakSet();
1069
- return this.visitedStore;
1070
- }
1071
- walkVariableDeclarator(path) {
1072
- const init = path.get("init");
1073
- this.walkNode(init);
1074
- }
1075
- walkTemplateLiteral(path) {
1076
- for (const exp of path.get("expressions")) this.walkNode(exp);
1077
- for (const quasis of path.get("quasis")) this.callback(quasis);
1078
- }
1079
- walkStringLiteral(path) {
1080
- this.callback(path);
1081
- }
1082
- walkBinaryExpression(path) {
1083
- const left = path.get("left");
1084
- this.walkNode(left);
1085
- const right = path.get("right");
1086
- this.walkNode(right);
1087
- }
1088
- walkLogicalExpression(path) {
1089
- const left = path.get("left");
1090
- this.walkNode(left);
1091
- const right = path.get("right");
1092
- this.walkNode(right);
1093
- }
1094
- walkObjectExpression(path) {
1095
- const props = path.get("properties");
1096
- for (const prop of props) if (prop.isObjectProperty()) {
1097
- const key = prop.get("key");
1098
- this.walkNode(key);
1099
- const value = prop.get("value");
1100
- this.walkNode(value);
1101
- }
1102
- }
1103
- walkArrayExpression(path) {
1104
- const elements = path.get("elements");
1105
- for (const element of elements) this.walkNode(element);
1106
- }
1107
- walkNode(arg) {
1108
- const visited = this.getVisited();
1109
- if (visited.has(arg)) return;
1110
- visited.add(arg);
1111
- if (arg.isIdentifier()) {
1112
- const binding = arg?.scope?.getBinding?.(arg.node.name);
1113
- if (binding) this.walkNode(binding.path);
1114
- } else if (arg.isMemberExpression()) {
1115
- const objectPath = arg.get("object");
1116
- if (objectPath.isIdentifier()) {
1117
- const binding = arg?.scope?.getBinding?.(objectPath.node.name);
1118
- if (binding) {
1119
- if (binding.path.isVariableDeclarator()) this.walkVariableDeclarator(binding.path);
1120
- }
1121
- }
1122
- } else if (arg.isTemplateLiteral()) this.walkTemplateLiteral(arg);
1123
- else if (arg.isStringLiteral()) this.walkStringLiteral(arg);
1124
- else if (arg.isBinaryExpression()) this.walkBinaryExpression(arg);
1125
- else if (arg.isLogicalExpression()) this.walkLogicalExpression(arg);
1126
- else if (arg.isObjectExpression()) this.walkObjectExpression(arg);
1127
- else if (arg.isArrayExpression()) this.walkArrayExpression(arg);
1128
- else if (arg.isVariableDeclarator()) this.walkVariableDeclarator(arg);
1129
- else if (maybeAddImportToken(this.getWritableImports(), arg)) {}
1130
- }
1131
- /**
1132
- * Walk the arguments of a desired call expression so their bindings can be analysed.
1133
- */
1134
- walkCallExpression(path) {
1135
- if (!this.hasIgnoredCallIdentifiers) return;
1136
- const calleePath = path.get("callee");
1137
- if (calleePath.isIdentifier() && this.isIgnoredCallIdentifier(calleePath.node.name)) for (const arg of path.get("arguments")) this.walkNode(arg);
1138
- }
1139
- walkExportDeclaration(path) {
1140
- walkExportDeclaration(this, path);
1141
- }
1142
- walkExportNamedDeclaration(path) {
1143
- walkExportNamedDeclaration(this, path);
1144
- }
1145
- walkExportDefaultDeclaration(path) {
1146
- walkExportDefaultDeclaration(this, path);
1147
- }
1148
- walkExportAllDeclaration(path) {
1149
- walkExportAllDeclaration(this, path);
1150
- }
1151
- };
1152
- //#endregion
1153
- //#region src/js/taggedTemplateIgnore.ts
1154
- function createTaggedTemplateIgnore({ matcher, names }) {
1155
- const bindingIgnoreCache = /* @__PURE__ */ new Map();
1156
- const taggedTemplateIgnoreCache = /* @__PURE__ */ new WeakMap();
1157
- const seenBindings = /* @__PURE__ */ new Set();
1158
- let singleCanonicalIgnoreName;
1159
- let canonicalIgnoreNames;
1160
- for (const item of names ?? []) {
1161
- if (typeof item !== "string") continue;
1162
- if (singleCanonicalIgnoreName === void 0) {
1163
- singleCanonicalIgnoreName = item;
1164
- continue;
1165
- }
1166
- if (item === singleCanonicalIgnoreName) continue;
1167
- if (!canonicalIgnoreNames) {
1168
- canonicalIgnoreNames = /* @__PURE__ */ new Set([singleCanonicalIgnoreName, item]);
1169
- continue;
1170
- }
1171
- canonicalIgnoreNames.add(item);
1172
- }
1173
- const hasCanonicalIgnoreNames = singleCanonicalIgnoreName !== void 0;
1174
- const matchesIgnoreName = (value) => {
1175
- if (hasCanonicalIgnoreNames) {
1176
- if (canonicalIgnoreNames) {
1177
- if (canonicalIgnoreNames.has(value)) return true;
1178
- } else if (value === singleCanonicalIgnoreName) return true;
1179
- }
1180
- return matcher(value);
1181
- };
1182
- const propertyMatches = (propertyPath) => {
1183
- if (!propertyPath) return false;
1184
- if (propertyPath.isIdentifier()) return matchesIgnoreName(propertyPath.node.name);
1185
- if (propertyPath.isStringLiteral()) return matchesIgnoreName(propertyPath.node.value);
1186
- return false;
1187
- };
1188
- const resolvesMemberExpressionToIgnore = (path, seen) => {
1189
- const propertyPath = path.get("property");
1190
- if (propertyMatches(propertyPath)) return true;
1191
- const objectPath = path.get("object");
1192
- if (objectPath.isIdentifier()) {
1193
- const binding = (objectPath?.scope)?.getBinding?.(objectPath.node.name);
1194
- if (binding) return resolvesToWeappTwIgnore(binding, seen);
1195
- }
1196
- return false;
1197
- };
1198
- const resolvesToWeappTwIgnore = (binding, seen) => {
1199
- const cached = bindingIgnoreCache.get(binding);
1200
- if (cached !== void 0) return cached;
1201
- if (seen.has(binding)) return false;
1202
- seen.add(binding);
1203
- let result = false;
1204
- const bindingPath = binding.path;
1205
- if (bindingPath.isImportSpecifier()) {
1206
- const imported = bindingPath.node.imported;
1207
- if (imported.type === "Identifier" && matchesIgnoreName(imported.name)) result = true;
1208
- else if (imported.type === "StringLiteral" && matchesIgnoreName(imported.value)) result = true;
1209
- } else if (bindingPath.isVariableDeclarator()) {
1210
- const init = bindingPath.get("init");
1211
- if (init && init.node) {
1212
- if (init.isIdentifier()) {
1213
- const target = binding?.scope?.getBinding?.(init.node.name);
1214
- if (target) result = resolvesToWeappTwIgnore(target, seen);
1215
- } else if (init.isMemberExpression()) result = resolvesMemberExpressionToIgnore(init, seen);
1216
- }
1217
- }
1218
- bindingIgnoreCache.set(binding, result);
1219
- seen.delete(binding);
1220
- return result;
1221
- };
1222
- const getEffectiveTagPath = (tagPath) => {
1223
- let current = tagPath;
1224
- while (true) {
1225
- if (current.isParenthesizedExpression?.() || current.node.type === "ParenthesizedExpression") {
1226
- current = current.get("expression");
1227
- continue;
1228
- }
1229
- if (current.isTSAsExpression() || current.isTSTypeAssertion()) {
1230
- current = current.get("expression");
1231
- continue;
1232
- }
1233
- if (current.isTSNonNullExpression()) {
1234
- current = current.get("expression");
1235
- continue;
1236
- }
1237
- if (current.isTypeCastExpression?.()) {
1238
- current = current.get("expression");
1239
- continue;
1240
- }
1241
- if (current.isSequenceExpression()) {
1242
- const last = current.get("expressions").at(-1);
1243
- if (last) {
1244
- current = last;
1245
- continue;
1246
- }
1247
- }
1248
- if (current.isCallExpression?.() || current.node.type === "CallExpression") {
1249
- current = current.get("callee");
1250
- continue;
1251
- }
1252
- break;
1253
- }
1254
- return current;
1255
- };
1256
- const evaluateTagPath = (tagPath, seen) => {
1257
- if (tagPath.isCallExpression?.() || tagPath.node.type === "CallExpression") {
1258
- const calleePath = tagPath.get("callee");
1259
- return evaluateTagPath(calleePath, seen);
1260
- }
1261
- if (tagPath.isIdentifier()) {
1262
- if (matchesIgnoreName(tagPath.node.name)) return true;
1263
- const binding = tagPath?.scope?.getBinding?.(tagPath.node.name);
1264
- if (binding) return resolvesToWeappTwIgnore(binding, seen);
1265
- return false;
1266
- }
1267
- if (tagPath.isMemberExpression()) return resolvesMemberExpressionToIgnore(tagPath, seen);
1268
- return false;
1269
- };
1270
- const computeIgnore = (tagPath) => {
1271
- const cached = taggedTemplateIgnoreCache.get(tagPath.node);
1272
- if (cached !== void 0) return cached;
1273
- const effectiveTagPath = getEffectiveTagPath(tagPath);
1274
- const effectiveCached = taggedTemplateIgnoreCache.get(effectiveTagPath.node);
1275
- if (effectiveCached !== void 0) {
1276
- taggedTemplateIgnoreCache.set(tagPath.node, effectiveCached);
1277
- return effectiveCached;
1278
- }
1279
- seenBindings.clear();
1280
- const result = evaluateTagPath(effectiveTagPath, seenBindings);
1281
- taggedTemplateIgnoreCache.set(effectiveTagPath.node, result);
1282
- taggedTemplateIgnoreCache.set(tagPath.node, result);
1283
- return result;
1284
- };
1285
- return {
1286
- shouldIgnore(tagPath) {
1287
- return computeIgnore(tagPath);
1288
- },
1289
- getEffectiveTagPath
1290
- };
1291
- }
1292
- //#endregion
1293
- //#region src/js/babel.ts
1294
- const EXPRESSION_WRAPPER_PREFIX = "(\n";
1295
- const EXPRESSION_WRAPPER_SUFFIX = "\n)";
1296
- const EMPTY_IGNORED_PATHS = /* @__PURE__ */ new WeakSet();
1297
- const EMPTY_IMPORT_DECLARATIONS = /* @__PURE__ */ new Set();
1298
- const EMPTY_EXPORT_DECLARATIONS = /* @__PURE__ */ new Set();
1299
- const EMPTY_REQUIRE_CALL_PATHS = [];
1300
- const ignoredTaggedTemplateMatcherCache = /* @__PURE__ */ new WeakMap();
1301
- let defaultEvalHandler;
1302
- function getIgnoredTaggedTemplateMatcher(options) {
1303
- const cached = ignoredTaggedTemplateMatcherCache.get(options);
1304
- if (cached) return cached;
1305
- const created = createNameMatcher(options.ignoreTaggedTemplateExpressionIdentifiers, { exact: true });
1306
- ignoredTaggedTemplateMatcherCache.set(options, created);
1307
- return created;
1308
- }
1309
- function getDefaultEvalHandler() {
1310
- if (!defaultEvalHandler) throw new Error("Default JS eval handler is not initialized.");
1311
- return defaultEvalHandler;
1312
- }
1313
- function analyzeSource(ast, options, handler, collectModuleMetadata = true) {
1314
- const jsTokenUpdater = new JsTokenUpdater();
1315
- const needScope = Boolean(options.ignoreCallExpressionIdentifiers && options.ignoreCallExpressionIdentifiers.length > 0);
1316
- const ignoredPaths = needScope ? /* @__PURE__ */ new WeakSet() : EMPTY_IGNORED_PATHS;
1317
- const walker = needScope ? new NodePathWalker({
1318
- ...options.ignoreCallExpressionIdentifiers === void 0 ? {} : { ignoreCallExpressionIdentifiers: options.ignoreCallExpressionIdentifiers },
1319
- callback(path) {
1320
- ignoredPaths.add(path);
1321
- }
1322
- }) : new NodePathWalker();
1323
- let taggedTemplateIgnore;
1324
- const hasTaggedTemplateIgnoreIdentifiers = Boolean(options.ignoreTaggedTemplateExpressionIdentifiers && options.ignoreTaggedTemplateExpressionIdentifiers.length > 0);
1325
- function getTaggedTemplateIgnore() {
1326
- if (!taggedTemplateIgnore) taggedTemplateIgnore = createTaggedTemplateIgnore({
1327
- matcher: getIgnoredTaggedTemplateMatcher(options),
1328
- ...options.ignoreTaggedTemplateExpressionIdentifiers === void 0 ? {} : { names: options.ignoreTaggedTemplateExpressionIdentifiers }
1329
- });
1330
- return taggedTemplateIgnore;
1331
- }
1332
- const targetPaths = [];
1333
- const importDeclarations = collectModuleMetadata ? /* @__PURE__ */ new Set() : EMPTY_IMPORT_DECLARATIONS;
1334
- const exportDeclarations = collectModuleMetadata ? /* @__PURE__ */ new Set() : EMPTY_EXPORT_DECLARATIONS;
1335
- const requireCallPaths = collectModuleMetadata ? [] : EMPTY_REQUIRE_CALL_PATHS;
1336
- const evalHandler = handler ?? getDefaultEvalHandler();
1337
- const traverseOptions = {
1338
- StringLiteral: { enter(p) {
1339
- if (isEvalPath(p.parentPath)) return;
1340
- targetPaths.push(p);
1341
- } },
1342
- TemplateElement: { enter: hasTaggedTemplateIgnoreIdentifiers ? (p) => {
1343
- const pp = p.parentPath;
1344
- if (pp.isTemplateLiteral()) {
1345
- const ppp = pp.parentPath;
1346
- if (isEvalPath(ppp)) return;
1347
- if (ppp.isTaggedTemplateExpression()) {
1348
- const tagPath = ppp.get("tag");
1349
- if (getTaggedTemplateIgnore().shouldIgnore(tagPath)) return;
1350
- }
1351
- }
1352
- targetPaths.push(p);
1353
- } : (p) => {
1354
- const pp = p.parentPath;
1355
- if (pp.isTemplateLiteral()) {
1356
- const ppp = pp.parentPath;
1357
- if (isEvalPath(ppp)) return;
1358
- }
1359
- targetPaths.push(p);
1360
- } },
1361
- CallExpression: { enter: !collectModuleMetadata && !needScope ? (p) => {
1362
- if (isEvalPath(p)) walkEvalExpression(p, options, jsTokenUpdater, evalHandler);
1363
- } : (p) => {
1364
- if (isEvalPath(p)) {
1365
- walkEvalExpression(p, options, jsTokenUpdater, evalHandler);
1366
- return;
1367
- }
1368
- const calleePath = p.get("callee");
1369
- if (collectModuleMetadata && calleePath.isIdentifier({ name: "require" }) && !p?.scope?.hasBinding?.("require")) {
1370
- const args = p.get("arguments");
1371
- if (Array.isArray(args) && args.length > 0) {
1372
- const first = args[0];
1373
- if (first?.isStringLiteral()) requireCallPaths.push(first);
1374
- }
1375
- }
1376
- if (needScope) walker.walkCallExpression(p);
1377
- } },
1378
- ...collectModuleMetadata ? {
1379
- ImportDeclaration: { enter(p) {
1380
- importDeclarations.add(p);
1381
- } },
1382
- ExportDeclaration: { enter(p) {
1383
- exportDeclarations.add(p);
1384
- } }
1385
- } : {}
1386
- };
1387
- traverse(ast, {
1388
- ...traverseOptions,
1389
- noScope: !needScope
1390
- });
1391
- return {
1392
- walker,
1393
- jsTokenUpdater,
1394
- ast,
1395
- targetPaths,
1396
- importDeclarations,
1397
- exportDeclarations,
1398
- requireCallPaths,
1399
- ignoredPaths
1400
- };
1401
- }
1402
- function jsHandler(rawSource, options) {
1403
- const shouldWrapExpression = Boolean(options.wrapExpression);
1404
- const source = shouldWrapExpression ? `${EXPRESSION_WRAPPER_PREFIX}${rawSource}${EXPRESSION_WRAPPER_SUFFIX}` : rawSource;
1405
- let ast;
1406
- try {
1407
- ast = babelParse(source, options.babelParserOptions);
1408
- } catch (error) {
1409
- return {
1410
- code: rawSource,
1411
- error
1412
- };
1413
- }
1414
- const needsModuleMetadata = Boolean(options.moduleSpecifierReplacements || options.moduleGraph && options.filename);
1415
- const analysis = analyzeSource(ast, options, jsHandler, needsModuleMetadata);
1416
- const ms = processUpdatedSource(source, options, analysis);
1417
- if (shouldWrapExpression) {
1418
- const start = 0;
1419
- const end = source.length;
1420
- const suffixLength = 2;
1421
- ms.remove(start, 2);
1422
- ms.remove(end - suffixLength, end);
1423
- }
1424
- const result = { code: ms.toString() };
1425
- if (options.generateMap) Object.defineProperty(result, "map", {
1426
- configurable: true,
1427
- enumerable: true,
1428
- get() {
1429
- return ms.generateMap();
1430
- }
1431
- });
1432
- if (options.moduleGraph && options.filename) {
1433
- const linked = new JsModuleGraph({
1434
- filename: options.filename,
1435
- source: rawSource,
1436
- analysis,
1437
- handlerOptions: options
1438
- }, options.moduleGraph).build();
1439
- if (linked) result.linked = linked;
1440
- }
1441
- return result;
1442
- }
1443
- defaultEvalHandler = jsHandler;
1444
- //#endregion
1445
- //#region src/wxml/custom-attributes.ts
1446
- function regTest(reg, str) {
1447
- reg.lastIndex = 0;
1448
- return reg.test(str);
1449
- }
1450
- function isPropsMatch(props, attr) {
1451
- if (Array.isArray(props)) {
1452
- let lowerAttr;
1453
- for (const prop of props) if (typeof prop === "string") {
1454
- lowerAttr ?? (lowerAttr = attr.toLowerCase());
1455
- if (prop.toLowerCase() === lowerAttr) return true;
1456
- } else if (regTest(prop, attr)) return true;
1457
- return false;
1458
- } else if (typeof props === "string") return props === attr;
1459
- else return regTest(props, attr);
1460
- }
1461
- function createAttributeMatcher(entities) {
1462
- if (!entities || entities.length === 0) return;
1463
- const wildcardAttributeRules = [];
1464
- const tagAttributeRuleMap = /* @__PURE__ */ new Map();
1465
- const regexpAttributeRules = [];
1466
- for (const [selector, props] of entities) if (selector === "*") wildcardAttributeRules.push(props);
1467
- else if (typeof selector === "string") {
1468
- const list = tagAttributeRuleMap.get(selector);
1469
- if (list) list.push(props);
1470
- else tagAttributeRuleMap.set(selector, [props]);
1471
- } else regexpAttributeRules.push([selector, props]);
1472
- return (tag, attr) => {
1473
- for (const props of wildcardAttributeRules) if (isPropsMatch(props, attr)) return true;
1474
- const tagRules = tagAttributeRuleMap.get(tag);
1475
- if (tagRules) {
1476
- for (const props of tagRules) if (isPropsMatch(props, attr)) return true;
1477
- }
1478
- for (const [selector, props] of regexpAttributeRules) if (regTest(selector, tag) && isPropsMatch(props, attr)) return true;
1479
- return false;
1480
- };
1481
- }
1482
- //#endregion
1483
- //#region src/wxml/utils/codegen/legacy-visitor.ts
1484
- function shouldSkipLegacyStringLiteral(path) {
1485
- if (t.isMemberExpression(path.parent)) return true;
1486
- return Boolean(t.isBinaryExpression(path.parent) && (t.isConditionalExpression(path.parentPath?.parent) || t.isLogicalExpression(path.parentPath?.parent)));
1487
- }
1488
- function createLegacyTraverseOptions(options, jsTokenUpdater) {
1489
- const legacyReplaceOptions = {
1490
- escapeMap: options.escapeMap,
1491
- classNameSet: options.runtimeSet,
1492
- needEscaped: true,
1493
- alwaysEscape: true
1494
- };
1495
- return {
1496
- StringLiteral(path) {
1497
- if (shouldSkipLegacyStringLiteral(path)) return;
1498
- jsTokenUpdater.addToken(replaceHandleValue(path, legacyReplaceOptions));
1499
- },
1500
- noScope: true
1501
- };
1502
- }
1503
- //#endregion
1504
- //#region src/wxml/utils/codegen/legacy-rewriter.ts
1505
- function rewriteLegacyExpression(match, options) {
1506
- const ast = parseExpression(match);
1507
- const jsTokenUpdater = new JsTokenUpdater();
1508
- traverse(ast, createLegacyTraverseOptions(options, jsTokenUpdater));
1509
- if (jsTokenUpdater.length === 0) return match;
1510
- const ms = new MagicString(match);
1511
- jsTokenUpdater.updateMagicString(ms);
1512
- return ms.toString();
1513
- }
1514
- //#endregion
1515
- //#region src/wxml/utils/codegen.ts
1516
- const WRAP_EXPRESSION_HANDLER_OPTIONS = Object.freeze({ wrapExpression: true });
1517
- function generateCode(match, options = {}) {
1518
- try {
1519
- const { jsHandler, runtimeSet, wrapExpression } = options;
1520
- if (jsHandler && runtimeSet) {
1521
- const initial = jsHandler(match, runtimeSet, wrapExpression ? WRAP_EXPRESSION_HANDLER_OPTIONS : void 0);
1522
- if (!initial.error || wrapExpression) return initial.code;
1523
- return jsHandler(match, runtimeSet, WRAP_EXPRESSION_HANDLER_OPTIONS).code;
1524
- } else return rewriteLegacyExpression(match, options);
1525
- } catch {
1526
- return match;
1527
- }
1528
- }
1529
- //#endregion
1530
- //#region src/wxml/whitespace.ts
1531
- const WHITESPACE_CODES = /* @__PURE__ */ new Set([
1532
- 9,
1533
- 10,
1534
- 11,
1535
- 12,
1536
- 13,
1537
- 32,
1538
- 160,
1539
- 65279
1540
- ]);
1541
- function isWhitespace(char) {
1542
- if (char.length === 0) return false;
1543
- return WHITESPACE_CODES.has(char.charCodeAt(0));
1544
- }
1545
- function isAllWhitespace(value) {
1546
- for (let i = 0; i < value.length; i++) if (!WHITESPACE_CODES.has(value.charCodeAt(i))) return false;
1547
- return true;
1548
- }
1549
- //#endregion
1550
- //#region src/wxml/Tokenizer.ts
1551
- var Tokenizer = class {
1552
- constructor() {
1553
- _defineProperty(this, "state", void 0);
1554
- _defineProperty(this, "buffer", void 0);
1555
- _defineProperty(this, "tokens", void 0);
1556
- _defineProperty(this, "bufferStartIndex", void 0);
1557
- _defineProperty(this, "expressionStartIndex", void 0);
1558
- _defineProperty(this, "expressionBuffer", void 0);
1559
- _defineProperty(this, "expressions", void 0);
1560
- this.reset();
1561
- }
1562
- processChar(char, index) {
1563
- switch (this.state) {
1564
- case 0:
1565
- if (isWhitespace(char)) {} else if (char === "{") {
1566
- this.state = 2;
1567
- this.bufferStartIndex = index;
1568
- this.buffer += char;
1569
- this.expressionBuffer = char;
1570
- this.expressionStartIndex = index;
1571
- } else {
1572
- this.state = 1;
1573
- this.bufferStartIndex = index;
1574
- this.buffer += char;
1575
- }
1576
- break;
1577
- case 1:
1578
- if (isWhitespace(char)) {
1579
- this.tokens.push({
1580
- start: this.bufferStartIndex,
1581
- end: index,
1582
- value: this.buffer,
1583
- expressions: this.expressions
1584
- });
1585
- this.buffer = "";
1586
- this.expressions = [];
1587
- this.state = 0;
1588
- } else if (char === "{") {
1589
- this.buffer += char;
1590
- this.expressionBuffer = char;
1591
- this.expressionStartIndex = index;
1592
- this.state = 2;
1593
- } else this.buffer += char;
1594
- break;
1595
- case 2:
1596
- if (char === "}") {
1597
- this.buffer += char;
1598
- this.expressionBuffer += char;
1599
- this.state = 3;
1600
- } else {
1601
- this.buffer += char;
1602
- this.expressionBuffer += char;
1603
- }
1604
- break;
1605
- case 3:
1606
- if (char === "}") {
1607
- this.buffer += char;
1608
- this.expressionBuffer += char;
1609
- this.expressions.push({
1610
- start: this.expressionStartIndex,
1611
- end: index + 1,
1612
- value: this.expressionBuffer
1613
- });
1614
- this.expressionBuffer = "";
1615
- this.state = 4;
1616
- } else {
1617
- this.buffer += char;
1618
- this.expressionBuffer += char;
1619
- this.state = 2;
1620
- }
1621
- break;
1622
- case 4:
1623
- if (isWhitespace(char)) {
1624
- this.tokens.push({
1625
- start: this.bufferStartIndex,
1626
- end: index,
1627
- value: this.buffer,
1628
- expressions: this.expressions
1629
- });
1630
- this.buffer = "";
1631
- this.expressions = [];
1632
- this.state = 0;
1633
- } else if (char === "{") {
1634
- this.expressionStartIndex = index;
1635
- this.expressionBuffer = char;
1636
- this.buffer += char;
1637
- this.state = 2;
1638
- } else {
1639
- this.buffer += char;
1640
- this.state = 1;
1641
- }
1642
- break;
1643
- default: throw new Error("Unexpected state");
1644
- }
1645
- }
1646
- run(input) {
1647
- this.reset();
1648
- for (let i = 0; i < input.length; i++) {
1649
- const char = input[i];
1650
- if (char === void 0) continue;
1651
- this.processChar(char, i);
1652
- }
1653
- if (this.buffer.length > 0) this.tokens.push({
1654
- start: this.bufferStartIndex,
1655
- end: input.length,
1656
- value: this.buffer,
1657
- expressions: this.expressions
1658
- });
1659
- const tokens = this.tokens;
1660
- this.reset();
1661
- return tokens;
1662
- }
1663
- reset() {
1664
- this.state = 0;
1665
- this.buffer = "";
1666
- this.tokens = [];
1667
- this.bufferStartIndex = 0;
1668
- this.expressionBuffer = "";
1669
- this.expressionStartIndex = 0;
1670
- this.expressions = [];
1671
- }
1672
- };
1673
- //#endregion
1674
- //#region src/wxml/utils/fragment-helpers.ts
1675
- function updateWhitespaceGap(ms, start, end, options) {
1676
- const gap = ms.slice(start, end);
1677
- if (isAllWhitespace(gap)) ms.update(start, end, replaceWxml(gap, {
1678
- keepEOL: false,
1679
- escapeMap: options.escapeMap,
1680
- ignoreHead: true
1681
- }));
1682
- }
1683
- function updateWxmlSegment(ms, start, end, options, keepEOL, ignoreHead) {
1684
- const value = ms.slice(start, end);
1685
- const replaceOptions = {
1686
- keepEOL,
1687
- escapeMap: options.escapeMap,
1688
- ignoreHead
1689
- };
1690
- if (options.classSetMode === "exact" && options.runtimeSet) {
1691
- ms.update(start, end, value.replace(/\S+/g, (candidate) => options.runtimeSet.has(candidate) ? replaceWxml(candidate, replaceOptions) : candidate));
1692
- return;
1693
- }
1694
- ms.update(start, end, replaceWxml(value, replaceOptions));
1695
- }
1696
- function updateExpressionSegment(ms, exp, options) {
1697
- const code = `{{${generateCode(exp.value.slice(2, -2), options)}}}`;
1698
- ms.update(exp.start, exp.end, code);
1699
- }
1700
- //#endregion
1701
- //#region src/wxml/utils/fragment-updater.ts
1702
- function handleEachClassFragment(ms, tokens, options = {}) {
1703
- let previousEnd = 0;
1704
- for (const token of tokens) {
1705
- if (token.start > previousEnd) updateWhitespaceGap(ms, previousEnd, token.start, options);
1706
- let p = token.start;
1707
- if (token.expressions.length > 0) {
1708
- for (const exp of token.expressions) {
1709
- if (exp.start > token.start && p < exp.start) updateWxmlSegment(ms, p, exp.start, options, true, p > 0);
1710
- updateExpressionSegment(ms, exp, options);
1711
- p = exp.end;
1712
- }
1713
- if (token.end > p) updateWxmlSegment(ms, p, token.end, options, false, true);
1714
- } else updateWxmlSegment(ms, token.start, token.end, options, false, false);
1715
- previousEnd = token.end;
1716
- }
1717
- if (tokens.length > 0) {
1718
- const lastToken = tokens[tokens.length - 1];
1719
- if (!lastToken) return;
1720
- if (lastToken.end < ms.original.length) updateWhitespaceGap(ms, lastToken.end, ms.original.length, options);
1721
- }
1722
- }
1723
- //#endregion
1724
- //#region src/wxml/utils/template-fragments.ts
1725
- /**
1726
- * 模块级共享 Tokenizer 实例,避免每次调用都重新创建。
1727
- * Tokenizer.run() 末尾已调用 reset(),天然支持复用。
1728
- */
1729
- const sharedTokenizer = new Tokenizer();
1730
- function templateReplacer(original, options = {}, tokenizer) {
1731
- const ms = new MagicString(original);
1732
- handleEachClassFragment(ms, (tokenizer ?? sharedTokenizer).run(ms.original), options);
1733
- return ms.toString();
1734
- }
1735
- //#endregion
1736
- //#region src/wxml/utils/custom-template.ts
1737
- async function customTemplateHandler(rawSource, options, cachedMatcher) {
1738
- const { customAttributesEntities = [], disabledDefaultTemplateHandler, inlineWxs, runtimeSet, jsHandler } = options ?? {};
1739
- const matchCustomAttribute = cachedMatcher ?? createAttributeMatcher(customAttributesEntities);
1740
- const defaultTemplateHandlerEnabled = !disabledDefaultTemplateHandler;
1741
- let replaceOptions;
1742
- let cachedQuote;
1743
- let s;
1744
- let tag = "";
1745
- let wxsArray;
1746
- function getMagicString() {
1747
- if (!s) s = new MagicString(rawSource);
1748
- return s;
1749
- }
1750
- function getReplaceOptions(quote) {
1751
- if (!replaceOptions) {
1752
- replaceOptions = {
1753
- ...options,
1754
- quote
1755
- };
1756
- cachedQuote = quote;
1757
- return replaceOptions;
1758
- }
1759
- if (cachedQuote !== quote) {
1760
- replaceOptions.quote = quote;
1761
- cachedQuote = quote;
1762
- }
1763
- return replaceOptions;
1764
- }
1765
- function isDefaultTemplateAttribute(name) {
1766
- if (name === "class" || name === "hover-class" || name === "virtualhostclass") return true;
1767
- const lowerName = name.toLowerCase();
1768
- return lowerName === "class" || lowerName === "hover-class" || lowerName === "virtualhostclass";
1769
- }
1770
- const parser = new Parser({
1771
- onopentagname(name) {
1772
- tag = name;
1773
- },
1774
- onattribute(name, value, quote) {
1775
- if (!value) return;
1776
- const shouldHandleDefault = defaultTemplateHandlerEnabled && isDefaultTemplateAttribute(name);
1777
- const shouldHandleCustom = matchCustomAttribute?.(tag, name) ?? false;
1778
- if (!shouldHandleDefault && !shouldHandleCustom) return;
1779
- getMagicString().update(parser.startIndex + name.length + 2, parser.endIndex - 1, templateReplacer(value, getReplaceOptions(quote)));
1780
- },
1781
- ontext(data) {
1782
- if (inlineWxs && tag === "wxs") (wxsArray ?? (wxsArray = [])).push({
1783
- data,
1784
- endIndex: parser.endIndex + 1,
1785
- startIndex: parser.startIndex
1786
- });
1787
- },
1788
- onclosetag() {
1789
- tag = "";
1790
- }
1791
- }, { xmlMode: true });
1792
- parser.write(rawSource);
1793
- parser.end();
1794
- if (jsHandler) for (const { data, endIndex, startIndex } of wxsArray ?? []) {
1795
- const { code } = await jsHandler(data, runtimeSet);
1796
- if (code !== data) getMagicString().update(startIndex, endIndex, code);
1797
- }
1798
- return s?.toString() ?? rawSource;
1799
- }
1800
- //#endregion
1801
- //#region src/wxml/utils.ts
1802
- function createTemplateHandler(options = {}) {
1803
- const cachedMatcher = createAttributeMatcher(options.customAttributesEntities);
1804
- const defaultOptions = options;
1805
- let cachedRuntimeSet;
1806
- let cachedOptionsWithRuntimeSet;
1807
- return (rawSource, opt) => {
1808
- const runtimeSet = opt?.runtimeSet;
1809
- if (opt && Object.keys(opt).some((key) => key !== "runtimeSet")) return customTemplateHandler(rawSource, defuOverrideArray(opt, defaultOptions), opt.customAttributesEntities === void 0 ? cachedMatcher : void 0);
1810
- if (runtimeSet === void 0) return customTemplateHandler(rawSource, defaultOptions, cachedMatcher);
1811
- if (cachedRuntimeSet !== runtimeSet || !cachedOptionsWithRuntimeSet) {
1812
- cachedRuntimeSet = runtimeSet;
1813
- cachedOptionsWithRuntimeSet = {
1814
- ...defaultOptions,
1815
- runtimeSet
1816
- };
1817
- }
1818
- return customTemplateHandler(rawSource, cachedOptionsWithRuntimeSet, cachedMatcher);
1819
- };
1820
- }
1821
- //#endregion
1822
- export { md5Hash as _, jsHandler as a, getReplacementCacheStore as c, decodeUnicode2 as d, resolveClassNameTransformWithResult as f, traverse as g, babelParse as h, analyzeSource as i, jsStringEscape as l, createDebug as m, generateCode as n, JsTokenUpdater as o, replaceWxml as p, createAttributeMatcher as r, getReplacement as s, createTemplateHandler as t, isClassContextLiteralPath as u };