weapp-tailwindcss 4.11.2 → 4.12.0-alpha.2

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 (73) hide show
  1. package/README.md +38 -0
  2. package/bin/weapp-tailwindcss.js +21 -1
  3. package/dist/{chunk-AV3XB6EQ.js → chunk-2A4NRLSY.js} +5 -5
  4. package/dist/{chunk-WJIRXC26.js → chunk-6JBFHYFM.js} +134 -128
  5. package/dist/{chunk-OMARW5NC.mjs → chunk-AYJ4HLWZ.mjs} +4 -2
  6. package/dist/{chunk-W3DXDWYC.mjs → chunk-CMNCGACY.mjs} +66 -60
  7. package/dist/{chunk-ZZ36BKM5.mjs → chunk-CQMHHQRN.mjs} +6 -2
  8. package/dist/{chunk-OYSABARD.js → chunk-E7I5TW5K.js} +3 -2
  9. package/dist/{chunk-7LKMJZD2.js → chunk-GMKSBLNY.js} +2 -2
  10. package/dist/{chunk-EFBQ4SQR.mjs → chunk-HL3US2OT.mjs} +1 -1
  11. package/dist/{chunk-AB2RGZQO.mjs → chunk-LWEVOVRD.mjs} +144 -76
  12. package/dist/{chunk-QK6VNNNL.js → chunk-NIS74SI6.js} +8 -6
  13. package/dist/{chunk-CRDOWYG4.js → chunk-ONLKZIRQ.js} +1 -1
  14. package/dist/{chunk-3QHYEMEW.js → chunk-PAAX4FDD.js} +45 -40
  15. package/dist/{chunk-JIERVBTX.mjs → chunk-SHDJA4GG.mjs} +1 -1
  16. package/dist/{chunk-SUKOZ6OG.js → chunk-SRAG3FST.js} +10 -6
  17. package/dist/{chunk-TT5WHNGS.js → chunk-YVRX3F6S.js} +149 -81
  18. package/dist/{chunk-2LH6PZH3.mjs → chunk-ZCH4YINE.mjs} +3 -2
  19. package/dist/{chunk-VGPAKLMZ.mjs → chunk-ZGIN2OAY.mjs} +12 -7
  20. package/dist/cli.js +2233 -158
  21. package/dist/cli.mjs +2238 -163
  22. package/dist/core.d.mts +1 -1
  23. package/dist/core.d.ts +1 -1
  24. package/dist/core.js +14 -9
  25. package/dist/core.mjs +10 -5
  26. package/dist/css-macro/postcss.js +4 -4
  27. package/dist/css-macro/postcss.mjs +2 -2
  28. package/dist/css-macro.js +5 -5
  29. package/dist/css-macro.mjs +2 -2
  30. package/dist/defaults.d.mts +1 -1
  31. package/dist/defaults.d.ts +1 -1
  32. package/dist/defaults.js +1 -1
  33. package/dist/defaults.mjs +1 -1
  34. package/dist/gulp.d.mts +1 -1
  35. package/dist/gulp.d.ts +1 -1
  36. package/dist/gulp.js +5 -5
  37. package/dist/gulp.mjs +4 -4
  38. package/dist/{index-CoXntW_P.d.mts → index-BXrmQelt.d.mts} +29 -1
  39. package/dist/{index-CoXntW_P.d.ts → index-BXrmQelt.d.ts} +29 -1
  40. package/dist/index.d.mts +1 -1
  41. package/dist/index.d.ts +1 -1
  42. package/dist/index.js +9 -9
  43. package/dist/index.mjs +7 -7
  44. package/dist/postcss-html-transform.js +1 -1
  45. package/dist/postcss-html-transform.mjs +1 -1
  46. package/dist/presets.d.mts +8 -1
  47. package/dist/presets.d.ts +8 -1
  48. package/dist/presets.js +7 -6
  49. package/dist/presets.mjs +3 -2
  50. package/dist/reset.d.mts +1 -31
  51. package/dist/reset.d.ts +3 -32
  52. package/dist/reset.js +3 -160
  53. package/dist/reset.mjs +3 -160
  54. package/dist/types.d.mts +2 -2
  55. package/dist/types.d.ts +2 -2
  56. package/dist/types.js +1 -1
  57. package/dist/types.mjs +1 -1
  58. package/dist/vite.d.mts +1 -1
  59. package/dist/vite.d.ts +1 -1
  60. package/dist/vite.js +6 -6
  61. package/dist/vite.mjs +4 -4
  62. package/dist/weapp-tw-css-import-rewrite-loader.js +10 -5
  63. package/dist/weapp-tw-runtime-classset-loader.js +9 -4
  64. package/dist/webpack.d.mts +1 -1
  65. package/dist/webpack.d.ts +1 -1
  66. package/dist/webpack.js +7 -7
  67. package/dist/webpack.mjs +5 -5
  68. package/dist/webpack4.d.mts +1 -1
  69. package/dist/webpack4.d.ts +1 -1
  70. package/dist/webpack4.js +65 -56
  71. package/dist/webpack4.mjs +35 -26
  72. package/package.json +12 -7
  73. package/scripts/postinstall.mjs +59 -0
package/dist/cli.js CHANGED
@@ -23,8 +23,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
23
23
  ));
24
24
 
25
25
  // src/cli.ts
26
- var import_node_process18 = __toESM(require("process"));
27
- var import_semver = __toESM(require("semver"));
26
+ var import_node_process19 = __toESM(require("process"));
27
+ var import_semver2 = __toESM(require("semver"));
28
28
  var import_tailwindcss_patch3 = require("tailwindcss-patch");
29
29
 
30
30
  // src/cli/context.ts
@@ -208,7 +208,7 @@ var import_logger2 = require("@weapp-tailwindcss/logger");
208
208
  // package.json
209
209
  var package_default = {
210
210
  name: "weapp-tailwindcss",
211
- version: "4.11.2",
211
+ version: "4.12.0-alpha.2",
212
212
  description: "\u628A tailwindcss \u539F\u5B50\u5316\u6837\u5F0F\u601D\u60F3\uFF0C\u5E26\u7ED9\u5C0F\u7A0B\u5E8F\u5F00\u53D1\u8005\u4EEC! bring tailwindcss to miniprogram developers!",
213
213
  author: "ice breaker <1324318532@qq.com>",
214
214
  license: "MIT",
@@ -358,13 +358,14 @@ var package_default = {
358
358
  "dist",
359
359
  "index.css",
360
360
  "preflight.css",
361
+ "scripts/postinstall.mjs",
361
362
  "theme.css",
362
363
  "uni-app-x.css",
363
364
  "utilities.css",
364
365
  "with-layer.css"
365
366
  ],
366
367
  engines: {
367
- node: "^18.17.0 || >=20.5.0"
368
+ node: "^20.19.0 || >=22.12.0"
368
369
  },
369
370
  scripts: {
370
371
  dev: "tsup --watch --sourcemap",
@@ -373,7 +374,7 @@ var package_default = {
373
374
  "build:cli": "cd plugins/cli && pnpm run build",
374
375
  "build:css": "tsx scripts/build-css.ts",
375
376
  "build:weapp-theme": "tsx scripts/build-weapp-theme.ts",
376
- test: "npm run postinstall && vitest run",
377
+ test: "pnpm run cli:patch && vitest run",
377
378
  "test:dev": "vitest",
378
379
  "test:ui": "vitest --ui",
379
380
  bench: "vitest bench --config ./vitest.config.ts",
@@ -390,7 +391,7 @@ var package_default = {
390
391
  release: "tsx scripts/release.ts",
391
392
  lint: "eslint .",
392
393
  "lint:fix": "eslint ./src --fix",
393
- postinstall: "node bin/weapp-tailwindcss.js patch",
394
+ postinstall: "node scripts/postinstall.mjs",
394
395
  "bench:vite-dev-hmr": "tsx scripts/vite-dev-hmr-bench.ts",
395
396
  "test:watch-hmr": "node --import tsx scripts/watch-hmr-regression/index.ts"
396
397
  },
@@ -410,6 +411,7 @@ var package_default = {
410
411
  "@weapp-core/regex": "~1.0.1",
411
412
  "@weapp-tailwindcss/logger": "workspace:*",
412
413
  "@weapp-tailwindcss/postcss": "workspace:*",
414
+ "@weapp-tailwindcss/reset": "workspace:*",
413
415
  "@weapp-tailwindcss/shared": "workspace:*",
414
416
  cac: "6.7.14",
415
417
  "comment-json": "^4.6.2",
@@ -424,11 +426,14 @@ var package_default = {
424
426
  "tailwindcss-patch": "catalog:tailwindcssPatch",
425
427
  "webpack-sources": "3.3.4",
426
428
  yaml: "^2.8.3"
429
+ },
430
+ devDependencies: {
431
+ "fast-check": "^4.7.0"
427
432
  }
428
433
  };
429
434
 
430
435
  // src/constants.ts
431
- var WEAPP_TW_REQUIRED_NODE_VERSION = "18.17.0";
436
+ var WEAPP_TW_REQUIRED_NODE_VERSION_RANGE = "^20.19.0 || >=22.12.0";
432
437
  var WEAPP_TW_VERSION = package_default.version;
433
438
 
434
439
  // src/tailwindcss/targets/record-io.ts
@@ -583,102 +588,1894 @@ function createPatchTargetRecorder(baseDir, patcher, options) {
583
588
  packageJsonPath: location.packageJsonPath
584
589
  });
585
590
  return {
586
- recordPath: location.recordPath,
587
- message,
588
- reason,
589
- onPatched
591
+ recordPath: location.recordPath,
592
+ message,
593
+ reason,
594
+ onPatched
595
+ };
596
+ }
597
+
598
+ // src/tailwindcss/targets.ts
599
+ function logTailwindcssTarget(kind, patcher, baseDir) {
600
+ const packageInfo = patcher?.packageInfo;
601
+ const label = kind === "cli" ? "weapp-tw patch" : "Weapp-tailwindcss";
602
+ if (!packageInfo?.rootPath) {
603
+ import_logger3.logger.warn(
604
+ "%s \u672A\u627E\u5230 Tailwind CSS \u4F9D\u8D56\uFF0C\u8BF7\u68C0\u67E5\u5728 %s \u662F\u5426\u5DF2\u5B89\u88C5 tailwindcss",
605
+ label,
606
+ baseDir ?? import_node_process6.default.cwd()
607
+ );
608
+ return;
609
+ }
610
+ const displayPath = formatRelativeToBase(packageInfo.rootPath, baseDir);
611
+ const version = packageInfo.version ? ` (v${packageInfo.version})` : "";
612
+ if (kind === "runtime") {
613
+ logRuntimeTailwindcssTarget(baseDir, packageInfo.rootPath, packageInfo.version);
614
+ return;
615
+ }
616
+ import_logger3.logger.info("%s \u7ED1\u5B9A Tailwind CSS -> %s%s", label, displayPath, version);
617
+ }
618
+
619
+ // src/tailwindcss/v4/config.ts
620
+ var import_logger4 = require("@weapp-tailwindcss/logger");
621
+
622
+ // src/tailwindcss/v4/patcher.ts
623
+ var import_logger6 = require("@weapp-tailwindcss/logger");
624
+
625
+ // src/tailwindcss/patcher.ts
626
+ var import_node_path7 = __toESM(require("path"));
627
+ var import_node_process8 = __toESM(require("process"));
628
+ var import_logger5 = require("@weapp-tailwindcss/logger");
629
+ var import_shared2 = require("@weapp-tailwindcss/shared");
630
+ var import_tailwindcss_patch = require("tailwindcss-patch");
631
+
632
+ // src/tailwindcss/patcher-resolve.ts
633
+ var import_node_fs5 = require("fs");
634
+ var import_node_module = require("module");
635
+ var import_node_path6 = __toESM(require("path"));
636
+ var import_node_process7 = __toESM(require("process"));
637
+ var import_node_url = require("url");
638
+
639
+ // src/tailwindcss/v4/css-entries.ts
640
+ var import_node_path8 = __toESM(require("path"));
641
+
642
+ // src/context/compiler-context-cache.ts
643
+ var import_node_buffer = require("buffer");
644
+ var import_node_path9 = __toESM(require("path"));
645
+ var import_node_process9 = __toESM(require("process"));
646
+ var import_logger7 = require("@weapp-tailwindcss/logger");
647
+ var globalCacheHolder = globalThis;
648
+ var compilerContextCache = globalCacheHolder.__WEAPP_TW_COMPILER_CONTEXT_CACHE__ ?? (globalCacheHolder.__WEAPP_TW_COMPILER_CONTEXT_CACHE__ = /* @__PURE__ */ new Map());
649
+
650
+ // src/context/handlers.ts
651
+ var import_postcss = require("@weapp-tailwindcss/postcss");
652
+
653
+ // src/js/index.ts
654
+ var import_lru_cache3 = require("lru-cache");
655
+
656
+ // src/babel/index.ts
657
+ var import_traverse = __toESM(require("@babel/traverse"));
658
+ var import_parser = require("@babel/parser");
659
+ function _interopDefaultCompat(e) {
660
+ return e && typeof e === "object" && "default" in e ? e.default : e;
661
+ }
662
+ var traverse = _interopDefaultCompat(import_traverse.default);
663
+
664
+ // src/utils/nameMatcher.ts
665
+ var import_regex = require("@weapp-core/regex");
666
+ var NEVER_MATCH_NAME = () => false;
667
+ var GLOBAL_FLAG_REGEXP = /g/g;
668
+ function buildFuzzyMatcher(fuzzyStrings) {
669
+ if (fuzzyStrings.length === 0) {
670
+ return void 0;
671
+ }
672
+ if (fuzzyStrings.length === 1) {
673
+ const [needle] = fuzzyStrings;
674
+ return (value) => value.includes(needle);
675
+ }
676
+ const unique = [...new Set(fuzzyStrings)];
677
+ const pattern = new RegExp(unique.map(import_regex.escapeStringRegexp).join("|"));
678
+ return (value) => pattern.test(value);
679
+ }
680
+ function normaliseRegex(regex) {
681
+ const { source, flags } = regex;
682
+ if (!flags.includes("g")) {
683
+ return regex;
684
+ }
685
+ return new RegExp(source, flags.replace(GLOBAL_FLAG_REGEXP, ""));
686
+ }
687
+ function createNameMatcher(list, { exact = false } = {}) {
688
+ if (!list || list.length === 0) {
689
+ return NEVER_MATCH_NAME;
690
+ }
691
+ const exactStrings = exact ? /* @__PURE__ */ new Set() : void 0;
692
+ const fuzzyStrings = [];
693
+ const regexList = [];
694
+ for (const item of list) {
695
+ if (typeof item === "string") {
696
+ if (exact) {
697
+ exactStrings.add(item);
698
+ } else {
699
+ fuzzyStrings.push(item);
700
+ }
701
+ } else {
702
+ regexList.push(normaliseRegex(item));
703
+ }
704
+ }
705
+ if (exact) {
706
+ const exactStringCount = exactStrings?.size ?? 0;
707
+ if (exactStringCount === 1 && regexList.length === 0) {
708
+ const [needle] = exactStrings;
709
+ return (value) => value === needle;
710
+ }
711
+ if (regexList.length === 0) {
712
+ return (value) => exactStrings.has(value);
713
+ }
714
+ if (exactStringCount === 0 && regexList.length === 1) {
715
+ const [regex] = regexList;
716
+ return (value) => regex.test(value);
717
+ }
718
+ return (value) => {
719
+ if (exactStrings?.has(value)) {
720
+ return true;
721
+ }
722
+ return regexList.some((regex) => regex.test(value));
723
+ };
724
+ }
725
+ const fuzzyMatcher = exact ? void 0 : buildFuzzyMatcher(fuzzyStrings);
726
+ const hasRegex = regexList.length > 0;
727
+ if (fuzzyMatcher && !hasRegex) {
728
+ return fuzzyMatcher;
729
+ }
730
+ if (!fuzzyMatcher && regexList.length === 1) {
731
+ const [regex] = regexList;
732
+ return (value) => regex.test(value);
733
+ }
734
+ return (value) => {
735
+ if (fuzzyMatcher?.(value)) {
736
+ return true;
737
+ }
738
+ if (!hasRegex) {
739
+ return false;
740
+ }
741
+ return regexList.some((regex) => regex.test(value));
742
+ };
743
+ }
744
+
745
+ // src/js/babel/parse.ts
746
+ var import_lru_cache2 = require("lru-cache");
747
+ var parseCache = new import_lru_cache2.LRUCache(
748
+ {
749
+ max: 1024
750
+ }
751
+ );
752
+ function genCacheKey(source, options) {
753
+ if (typeof options === "string") {
754
+ return source + options;
755
+ }
756
+ return source + JSON.stringify(options, (_, val) => typeof val === "function" ? val.toString() : val);
757
+ }
758
+ function babelParse(code, opts = {}) {
759
+ const { cache, cacheKey, ...rest } = opts;
760
+ const cacheKeyString = genCacheKey(code, cacheKey ?? rest);
761
+ let result;
762
+ if (cache) {
763
+ result = parseCache.get(cacheKeyString);
764
+ }
765
+ if (!result) {
766
+ const { cache: _cache, cacheKey: _cacheKey, ...parseOptions } = opts;
767
+ result = (0, import_parser.parse)(code, parseOptions);
768
+ if (cache) {
769
+ parseCache.set(cacheKeyString, result);
770
+ }
771
+ }
772
+ return result;
773
+ }
774
+
775
+ // src/js/babel/process.ts
776
+ var import_magic_string = __toESM(require("magic-string"));
777
+
778
+ // src/js/handlers.ts
779
+ var import_escape3 = require("@ast-core/escape");
780
+ var import_extractors = require("@weapp-tailwindcss/shared/extractors");
781
+
782
+ // src/wxml/shared.ts
783
+ var import_escape2 = require("@weapp-core/escape");
784
+ var NEWLINE_RE = /[\n\r]+/g;
785
+ function replaceWxml(original, options = {
786
+ keepEOL: false,
787
+ escapeMap: import_escape2.MappingChars2String
788
+ }) {
789
+ const { keepEOL, escapeMap, ignoreHead } = options;
790
+ let res = original;
791
+ if (!keepEOL) {
792
+ res = res.replaceAll(NEWLINE_RE, "");
793
+ }
794
+ res = (0, import_escape2.escape)(res, {
795
+ map: escapeMap,
796
+ ignoreHead
797
+ });
798
+ return res;
799
+ }
800
+
801
+ // src/shared/classname-transform.ts
802
+ var escapedCandidateCacheByEscapeMap = /* @__PURE__ */ new WeakMap();
803
+ var defaultEscapedCandidateCache = /* @__PURE__ */ new Map();
804
+ var lastEscapedCandidateEscapeMap;
805
+ var lastEscapedCandidateCacheStore;
806
+ function isUrlLikeCandidate(candidate) {
807
+ return candidate.startsWith("//") || candidate.startsWith("http://") || candidate.startsWith("https://");
808
+ }
809
+ function isArbitraryValueCandidate(candidate) {
810
+ let hasOpenBracket = false;
811
+ let hasCloseBracket = false;
812
+ for (let i = 0; i < candidate.length; i++) {
813
+ const char = candidate[i];
814
+ if (char === "[") {
815
+ hasOpenBracket = true;
816
+ } else if (char === "]") {
817
+ hasCloseBracket = true;
818
+ }
819
+ if (hasOpenBracket && hasCloseBracket) {
820
+ break;
821
+ }
822
+ }
823
+ if (!hasOpenBracket || !hasCloseBracket) {
824
+ return false;
825
+ }
826
+ const normalized = candidate.trim();
827
+ if (isUrlLikeCandidate(normalized)) {
828
+ return false;
829
+ }
830
+ return true;
831
+ }
832
+ function shouldEnableArbitraryValueFallbackByInputs(classNameSet, jsArbitraryValueFallback, tailwindcssMajorVersion) {
833
+ if (jsArbitraryValueFallback === true) {
834
+ return true;
835
+ }
836
+ if (jsArbitraryValueFallback === false) {
837
+ return false;
838
+ }
839
+ return tailwindcssMajorVersion === 4 && (!classNameSet || classNameSet.size === 0);
840
+ }
841
+ function shouldEnableArbitraryValueFallback({
842
+ classNameSet,
843
+ jsArbitraryValueFallback,
844
+ tailwindcssMajorVersion
845
+ }) {
846
+ return shouldEnableArbitraryValueFallbackByInputs(
847
+ classNameSet,
848
+ jsArbitraryValueFallback,
849
+ tailwindcssMajorVersion
850
+ );
851
+ }
852
+ var SKIP_RESULT = { decision: "skip" };
853
+ var DIRECT_RESULT = { decision: "direct" };
854
+ var FALLBACK_RESULT = { decision: "fallback" };
855
+ function getEscapedCandidateCacheStore(escapeMap) {
856
+ if (!escapeMap) {
857
+ return defaultEscapedCandidateCache;
858
+ }
859
+ if (escapeMap === lastEscapedCandidateEscapeMap && lastEscapedCandidateCacheStore) {
860
+ return lastEscapedCandidateCacheStore;
861
+ }
862
+ let store = escapedCandidateCacheByEscapeMap.get(escapeMap);
863
+ if (!store) {
864
+ store = /* @__PURE__ */ new Map();
865
+ escapedCandidateCacheByEscapeMap.set(escapeMap, store);
866
+ }
867
+ lastEscapedCandidateEscapeMap = escapeMap;
868
+ lastEscapedCandidateCacheStore = store;
869
+ return store;
870
+ }
871
+ function getEscapedCandidate(candidate, escapeMap, store = getEscapedCandidateCacheStore(escapeMap)) {
872
+ let cached = store.get(candidate);
873
+ if (cached === void 0) {
874
+ cached = replaceWxml(candidate, { escapeMap });
875
+ store.set(candidate, cached);
876
+ }
877
+ return cached;
878
+ }
879
+ function resolveClassNameTransformWithResult(candidate, {
880
+ alwaysEscape,
881
+ classNameSet,
882
+ escapeMap,
883
+ jsArbitraryValueFallback,
884
+ jsPreserveClass,
885
+ tailwindcssMajorVersion,
886
+ classContext
887
+ }) {
888
+ if (alwaysEscape) {
889
+ return DIRECT_RESULT;
890
+ }
891
+ if (jsPreserveClass?.(candidate)) {
892
+ return SKIP_RESULT;
893
+ }
894
+ if (classNameSet?.has(candidate)) {
895
+ return DIRECT_RESULT;
896
+ }
897
+ if (classNameSet && classNameSet.size > 0) {
898
+ const escapedCandidate = getEscapedCandidate(candidate, escapeMap);
899
+ if (escapedCandidate !== candidate && classNameSet.has(escapedCandidate)) {
900
+ return { decision: "escaped", escapedValue: escapedCandidate };
901
+ }
902
+ }
903
+ if (classContext && shouldEnableArbitraryValueFallbackByInputs(classNameSet, jsArbitraryValueFallback, tailwindcssMajorVersion) && isArbitraryValueCandidate(candidate)) {
904
+ return FALLBACK_RESULT;
905
+ }
906
+ return SKIP_RESULT;
907
+ }
908
+
909
+ // src/utils/decode.ts
910
+ var unicodeEscapeRE = /\\u([\dA-Fa-f]{4})/g;
911
+ var unicodeEscapeTestRE = /\\u[\dA-Fa-f]{4}/;
912
+ function decodeUnicode(value) {
913
+ if (!unicodeEscapeTestRE.test(value)) {
914
+ return value;
915
+ }
916
+ return value.replace(unicodeEscapeRE, (_match, hex) => {
917
+ const codePoint = Number.parseInt(hex, 16);
918
+ return Number.isNaN(codePoint) ? _match : String.fromCharCode(codePoint);
919
+ });
920
+ }
921
+ function decodeUnicode2(input) {
922
+ if (!unicodeEscapeTestRE.test(input)) {
923
+ return input;
924
+ }
925
+ try {
926
+ return JSON.parse(`"${input}"`);
927
+ } catch (_error) {
928
+ return decodeUnicode(input);
929
+ }
930
+ }
931
+
932
+ // src/js/class-context.ts
933
+ var CLASS_LIKE_KEYWORDS = /* @__PURE__ */ new Set([
934
+ "class",
935
+ "classname",
936
+ "hoverclass",
937
+ "virtualhostclass",
938
+ "rootclass"
939
+ ]);
940
+ var CLASS_HELPER_IDENTIFIERS = /* @__PURE__ */ new Set([
941
+ "cn",
942
+ "clsx",
943
+ "classnames",
944
+ "twmerge",
945
+ "cva",
946
+ "tv",
947
+ "cx",
948
+ "r"
949
+ ]);
950
+ var DASH_CODE = 45;
951
+ var COLON_CODE = 58;
952
+ var UPPERCASE_A_CODE = 65;
953
+ var UPPERCASE_Z_CODE = 90;
954
+ var UNDERSCORE_CODE = 95;
955
+ var ASCII_MAX_CODE = 127;
956
+ var NORMALIZE_KEYWORD_REGEXP = /[-_:]/g;
957
+ function normalizeKeyword(name) {
958
+ const length = name.length;
959
+ let firstNormalizedIndex = -1;
960
+ for (let i = 0; i < length; i++) {
961
+ const code = name.charCodeAt(i);
962
+ if (code === DASH_CODE || code === UNDERSCORE_CODE || code === COLON_CODE || code >= UPPERCASE_A_CODE && code <= UPPERCASE_Z_CODE) {
963
+ firstNormalizedIndex = i;
964
+ break;
965
+ }
966
+ if (code > ASCII_MAX_CODE) {
967
+ return name.replace(NORMALIZE_KEYWORD_REGEXP, "").toLowerCase();
968
+ }
969
+ }
970
+ if (firstNormalizedIndex === -1) {
971
+ return name;
972
+ }
973
+ let normalized = name.slice(0, firstNormalizedIndex);
974
+ for (let i = firstNormalizedIndex; i < length; i++) {
975
+ const code = name.charCodeAt(i);
976
+ if (code === DASH_CODE || code === UNDERSCORE_CODE || code === COLON_CODE) {
977
+ continue;
978
+ }
979
+ if (code >= UPPERCASE_A_CODE && code <= UPPERCASE_Z_CODE) {
980
+ normalized += String.fromCharCode(code + 32);
981
+ continue;
982
+ }
983
+ if (code > ASCII_MAX_CODE) {
984
+ return name.replace(NORMALIZE_KEYWORD_REGEXP, "").toLowerCase();
985
+ }
986
+ normalized += name[i];
987
+ }
988
+ return normalized;
989
+ }
990
+ function readObjectKeyName(path22) {
991
+ if (path22.isIdentifier()) {
992
+ return path22.node.name;
993
+ }
994
+ if (path22.isStringLiteral()) {
995
+ return path22.node.value;
996
+ }
997
+ if (path22.isTemplateLiteral() && path22.node.expressions.length === 0) {
998
+ return path22.node.quasis[0]?.value.cooked ?? path22.node.quasis[0]?.value.raw;
999
+ }
1000
+ return void 0;
1001
+ }
1002
+ function isClassLikeObjectProperty(path22, valuePath) {
1003
+ if (!path22.isObjectProperty()) {
1004
+ return false;
1005
+ }
1006
+ if (path22.get("value") !== valuePath) {
1007
+ return false;
1008
+ }
1009
+ const keyName = readObjectKeyName(path22.get("key"));
1010
+ if (!keyName) {
1011
+ return false;
1012
+ }
1013
+ return CLASS_LIKE_KEYWORDS.has(normalizeKeyword(keyName));
1014
+ }
1015
+ function isClassLikeJsxAttribute(path22) {
1016
+ if (!path22.isJSXAttribute()) {
1017
+ return false;
1018
+ }
1019
+ const namePath = path22.get("name");
1020
+ if (!namePath.isJSXIdentifier()) {
1021
+ return false;
1022
+ }
1023
+ return CLASS_LIKE_KEYWORDS.has(normalizeKeyword(namePath.node.name));
1024
+ }
1025
+ function readCallHelperName(calleePath) {
1026
+ if (calleePath.isIdentifier()) {
1027
+ return calleePath.node.name;
1028
+ }
1029
+ if (calleePath.isMemberExpression()) {
1030
+ const propertyPath = calleePath.get("property");
1031
+ if (propertyPath.isIdentifier()) {
1032
+ return propertyPath.node.name;
1033
+ }
1034
+ if (propertyPath.isStringLiteral()) {
1035
+ return propertyPath.node.value;
1036
+ }
1037
+ }
1038
+ return void 0;
1039
+ }
1040
+ function isClassLikeCallExpression(path22, valuePath) {
1041
+ if (!path22.isCallExpression()) {
1042
+ return false;
1043
+ }
1044
+ const helperName = readCallHelperName(path22.get("callee"));
1045
+ if (!helperName || !CLASS_HELPER_IDENTIFIERS.has(normalizeKeyword(helperName))) {
1046
+ return false;
1047
+ }
1048
+ return path22.get("arguments").includes(valuePath);
1049
+ }
1050
+ function isClassContextLiteralPath(path22) {
1051
+ let current = path22;
1052
+ while (current.parentPath) {
1053
+ const parent = current.parentPath;
1054
+ if (isClassLikeObjectProperty(parent, current)) {
1055
+ return true;
1056
+ }
1057
+ if (isClassLikeJsxAttribute(parent)) {
1058
+ return true;
1059
+ }
1060
+ if (isClassLikeCallExpression(parent, current)) {
1061
+ return true;
1062
+ }
1063
+ current = parent;
1064
+ }
1065
+ return false;
1066
+ }
1067
+
1068
+ // src/js/handlers.ts
1069
+ var debug2 = createDebug("[js:handlers] ");
1070
+ var replacementCacheByEscapeMap = /* @__PURE__ */ new WeakMap();
1071
+ var defaultReplacementCache = /* @__PURE__ */ new Map();
1072
+ var WEAPP_TW_IGNORE_MARKER = "weapp-tw";
1073
+ var IGNORE_MARKER = "ignore";
1074
+ function getReplacementCacheStore(escapeMap) {
1075
+ if (!escapeMap) {
1076
+ return defaultReplacementCache;
1077
+ }
1078
+ let store = replacementCacheByEscapeMap.get(escapeMap);
1079
+ if (!store) {
1080
+ store = /* @__PURE__ */ new Map();
1081
+ replacementCacheByEscapeMap.set(escapeMap, store);
1082
+ }
1083
+ return store;
1084
+ }
1085
+ function getReplacement(candidate, escapeMap, store = getReplacementCacheStore(escapeMap)) {
1086
+ let cached = store.get(candidate);
1087
+ if (cached === void 0) {
1088
+ cached = replaceWxml(candidate, { escapeMap });
1089
+ store.set(candidate, cached);
1090
+ }
1091
+ return cached;
1092
+ }
1093
+ function hasIgnoreComment(node) {
1094
+ const { leadingComments } = node;
1095
+ if (!Array.isArray(leadingComments) || leadingComments.length === 0) {
1096
+ return false;
1097
+ }
1098
+ for (const comment of leadingComments) {
1099
+ const { value } = comment;
1100
+ if (value.includes(WEAPP_TW_IGNORE_MARKER) && value.includes(IGNORE_MARKER)) {
1101
+ return true;
1102
+ }
1103
+ }
1104
+ return false;
1105
+ }
1106
+ function extractLiteralValue(path22, { unescapeUnicode, arbitraryValues }) {
1107
+ const allowDoubleQuotes = arbitraryValues?.allowDoubleQuotes;
1108
+ const { node } = path22;
1109
+ let offset = 0;
1110
+ let original;
1111
+ if (node.type === "StringLiteral") {
1112
+ offset = 1;
1113
+ original = node.value;
1114
+ } else if (node.type === "TemplateElement") {
1115
+ original = node.value.raw;
1116
+ } else {
1117
+ original = "";
1118
+ }
1119
+ let literal = original;
1120
+ if (unescapeUnicode && original.includes("\\u")) {
1121
+ literal = decodeUnicode2(original);
1122
+ }
1123
+ return {
1124
+ allowDoubleQuotes,
1125
+ literal,
1126
+ offset,
1127
+ original
1128
+ };
1129
+ }
1130
+ function createCandidatePlanResolver(options, classContext) {
1131
+ const { escapeMap } = options;
1132
+ const replacementCache = getReplacementCacheStore(escapeMap);
1133
+ const transformOptions = classContext ? {
1134
+ ...options,
1135
+ classContext
1136
+ } : options;
1137
+ let firstCandidate = "";
1138
+ let firstPlan;
1139
+ let cache;
1140
+ const buildCandidatePlan = (candidate) => {
1141
+ const result = resolveClassNameTransformWithResult(candidate, transformOptions);
1142
+ if (result.decision === "skip") {
1143
+ return { result };
1144
+ }
1145
+ let replacement;
1146
+ if (result.decision === "escaped" && result.escapedValue) {
1147
+ replacement = result.escapedValue;
1148
+ replacementCache.set(candidate, replacement);
1149
+ } else {
1150
+ replacement = getReplacement(candidate, escapeMap, replacementCache);
1151
+ }
1152
+ return {
1153
+ result,
1154
+ replacement
1155
+ };
1156
+ };
1157
+ return (candidate) => {
1158
+ if (cache) {
1159
+ const cached = cache.get(candidate);
1160
+ if (cached) {
1161
+ return cached;
1162
+ }
1163
+ } else if (firstPlan && candidate === firstCandidate) {
1164
+ return firstPlan;
1165
+ }
1166
+ const plan = buildCandidatePlan(candidate);
1167
+ if (!firstPlan) {
1168
+ firstCandidate = candidate;
1169
+ firstPlan = plan;
1170
+ return plan;
1171
+ }
1172
+ if (!cache) {
1173
+ cache = /* @__PURE__ */ new Map();
1174
+ cache.set(firstCandidate, firstPlan);
1175
+ }
1176
+ cache.set(candidate, plan);
1177
+ return plan;
1178
+ };
1179
+ }
1180
+ function replaceHandleValue(path22, options) {
1181
+ const { needEscaped = false } = options;
1182
+ const { classNameSet, alwaysEscape } = options;
1183
+ const fallbackEnabled = shouldEnableArbitraryValueFallback(options);
1184
+ if (!alwaysEscape && !fallbackEnabled && (!classNameSet || classNameSet.size === 0)) {
1185
+ return void 0;
1186
+ }
1187
+ if (hasIgnoreComment(path22.node)) {
1188
+ return void 0;
1189
+ }
1190
+ const { literal, original, allowDoubleQuotes, offset } = extractLiteralValue(path22, options);
1191
+ const candidates = (0, import_extractors.splitCode)(literal, allowDoubleQuotes);
1192
+ if (candidates.length === 0) {
1193
+ return void 0;
1194
+ }
1195
+ const debugEnabled = debug2.enabled;
1196
+ const classContext = options.wrapExpression || isClassContextLiteralPath(path22);
1197
+ let transformed = literal;
1198
+ let mutated = false;
1199
+ let matchedCandidateCount = 0;
1200
+ let escapedDecisionCount = 0;
1201
+ let fallbackDecisionCount = 0;
1202
+ let escapedSamples;
1203
+ let skippedSamples;
1204
+ const resolveCandidatePlan = createCandidatePlanResolver(options, classContext);
1205
+ for (const candidate of candidates) {
1206
+ const plan = resolveCandidatePlan(candidate);
1207
+ if (plan.result.decision === "skip") {
1208
+ if (debugEnabled) {
1209
+ if (!skippedSamples) {
1210
+ skippedSamples = [];
1211
+ }
1212
+ if (skippedSamples.length < 6) {
1213
+ skippedSamples.push(candidate);
1214
+ }
1215
+ }
1216
+ continue;
1217
+ }
1218
+ if (debugEnabled) {
1219
+ matchedCandidateCount += 1;
1220
+ if (plan.result.decision === "escaped") {
1221
+ escapedDecisionCount += 1;
1222
+ if (!escapedSamples) {
1223
+ escapedSamples = [];
1224
+ }
1225
+ if (escapedSamples.length < 6) {
1226
+ escapedSamples.push(candidate);
1227
+ }
1228
+ }
1229
+ if (plan.result.decision === "fallback") {
1230
+ fallbackDecisionCount += 1;
1231
+ }
1232
+ }
1233
+ const replaced = transformed.replace(candidate, plan.replacement);
1234
+ if (replaced !== transformed) {
1235
+ transformed = replaced;
1236
+ mutated = true;
1237
+ }
1238
+ }
1239
+ const node = path22.node;
1240
+ if (!mutated || typeof node.start !== "number" || typeof node.end !== "number") {
1241
+ return void 0;
1242
+ }
1243
+ if (debugEnabled) {
1244
+ debug2(
1245
+ "runtimeSet size=%d fallbackTriggered=%s candidates=%d matched=%d escapedHits=%d skipped=%d file=%s escapedSamples=%s skippedSamples=%s",
1246
+ classNameSet?.size ?? 0,
1247
+ fallbackDecisionCount > 0,
1248
+ candidates.length,
1249
+ matchedCandidateCount,
1250
+ escapedDecisionCount,
1251
+ skippedSamples?.length ?? 0,
1252
+ options.filename ?? "unknown",
1253
+ escapedSamples?.join(",") || "-",
1254
+ skippedSamples?.join(",") || "-"
1255
+ );
1256
+ }
1257
+ const start = node.start + offset;
1258
+ const end = node.end - offset;
1259
+ if (start >= end || transformed === original) {
1260
+ return void 0;
1261
+ }
1262
+ const value = needEscaped ? (0, import_escape3.jsStringEscape)(transformed) : transformed;
1263
+ return {
1264
+ start,
1265
+ end,
1266
+ value,
1267
+ path: path22
1268
+ };
1269
+ }
1270
+
1271
+ // src/js/sourceAnalysis.ts
1272
+ function hasReplacementEntries(replacements) {
1273
+ for (const key in replacements) {
1274
+ if (Object.hasOwn(replacements, key)) {
1275
+ return true;
1276
+ }
1277
+ }
1278
+ return false;
1279
+ }
1280
+ function createModuleSpecifierReplacementToken(path22, replacement) {
1281
+ const node = path22.node;
1282
+ if (node.value === replacement) {
1283
+ return void 0;
1284
+ }
1285
+ if (typeof node.start !== "number" || typeof node.end !== "number") {
1286
+ return void 0;
1287
+ }
1288
+ const start = node.start + 1;
1289
+ const end = node.end - 1;
1290
+ if (start >= end) {
1291
+ return void 0;
1292
+ }
1293
+ return {
1294
+ start,
1295
+ end,
1296
+ value: replacement,
1297
+ path: path22
1298
+ };
1299
+ }
1300
+ function collectModuleSpecifierReplacementTokens(analysis, replacements) {
1301
+ if (!hasReplacementEntries(replacements)) {
1302
+ return [];
1303
+ }
1304
+ if (analysis.importDeclarations.size === 0 && analysis.exportDeclarations.size === 0 && analysis.requireCallPaths.length === 0 && analysis.walker.imports.size === 0) {
1305
+ return [];
1306
+ }
1307
+ const tokens = [];
1308
+ const applyReplacement = (path22) => {
1309
+ const replacement = replacements[path22.node.value];
1310
+ if (!replacement) {
1311
+ return;
1312
+ }
1313
+ const token = createModuleSpecifierReplacementToken(path22, replacement);
1314
+ if (token) {
1315
+ tokens.push(token);
1316
+ }
1317
+ };
1318
+ for (const importPath of analysis.importDeclarations) {
1319
+ const source = importPath.get("source");
1320
+ if (source.isStringLiteral()) {
1321
+ applyReplacement(source);
1322
+ }
1323
+ }
1324
+ for (const exportPath of analysis.exportDeclarations) {
1325
+ if (exportPath.isExportNamedDeclaration() || exportPath.isExportAllDeclaration()) {
1326
+ const source = exportPath.get("source");
1327
+ if (source && !Array.isArray(source) && source.isStringLiteral()) {
1328
+ applyReplacement(source);
1329
+ }
1330
+ }
1331
+ }
1332
+ for (const literalPath of analysis.requireCallPaths) {
1333
+ applyReplacement(literalPath);
1334
+ }
1335
+ for (const token of analysis.walker.imports) {
1336
+ const replacement = replacements[token.source];
1337
+ if (replacement) {
1338
+ token.source = replacement;
1339
+ }
1340
+ }
1341
+ return tokens;
1342
+ }
1343
+
1344
+ // src/js/babel/process.ts
1345
+ var optionVariantsCache = /* @__PURE__ */ new WeakMap();
1346
+ function getNeedEscapedOptions(options, needEscaped) {
1347
+ if (options.needEscaped === needEscaped) {
1348
+ return options;
1349
+ }
1350
+ let cached = optionVariantsCache.get(options);
1351
+ if (!cached) {
1352
+ cached = {};
1353
+ optionVariantsCache.set(options, cached);
1354
+ }
1355
+ if (needEscaped) {
1356
+ if (!cached.stringLiteralOptions) {
1357
+ cached.stringLiteralOptions = {
1358
+ ...options,
1359
+ needEscaped: true
1360
+ };
1361
+ }
1362
+ return cached.stringLiteralOptions;
1363
+ }
1364
+ if (!cached.templateLiteralOptions) {
1365
+ cached.templateLiteralOptions = {
1366
+ ...options,
1367
+ needEscaped: false
1368
+ };
1369
+ }
1370
+ return cached.templateLiteralOptions;
1371
+ }
1372
+ function processUpdatedSource(rawSource, options, analysis) {
1373
+ const { targetPaths, jsTokenUpdater, ignoredPaths } = analysis;
1374
+ if (targetPaths.length === 0 && !options.moduleSpecifierReplacements && jsTokenUpdater.length === 0) {
1375
+ return new import_magic_string.default(rawSource);
1376
+ }
1377
+ const replacementTokens = [];
1378
+ for (const path22 of targetPaths) {
1379
+ if (ignoredPaths.has(path22)) {
1380
+ continue;
1381
+ }
1382
+ const token = replaceHandleValue(
1383
+ path22,
1384
+ path22.isStringLiteral() ? getNeedEscapedOptions(options, true) : getNeedEscapedOptions(options, false)
1385
+ );
1386
+ if (token) {
1387
+ replacementTokens.push(token);
1388
+ }
1389
+ }
1390
+ if (options.moduleSpecifierReplacements) {
1391
+ replacementTokens.push(
1392
+ ...collectModuleSpecifierReplacementTokens(analysis, options.moduleSpecifierReplacements)
1393
+ );
1394
+ }
1395
+ if (jsTokenUpdater.length + replacementTokens.length === 0) {
1396
+ return new import_magic_string.default(rawSource);
1397
+ }
1398
+ const ms = new import_magic_string.default(rawSource);
1399
+ jsTokenUpdater.push(...replacementTokens).filter((token) => !ignoredPaths.has(token.path)).updateMagicString(ms);
1400
+ return ms;
1401
+ }
1402
+
1403
+ // src/js/evalTransforms.ts
1404
+ var import_escape4 = require("@ast-core/escape");
1405
+ var evalHandlerOptionsCache = /* @__PURE__ */ new WeakMap();
1406
+ var EVAL_SCOPE_ERROR_REGEXP = /pass a scope and parentPath|traversing a Program\/File/i;
1407
+ function isEvalPath(path22) {
1408
+ if (path22.isCallExpression()) {
1409
+ const calleePath = path22.get("callee");
1410
+ return calleePath.isIdentifier({ name: "eval" });
1411
+ }
1412
+ return false;
1413
+ }
1414
+ function createEvalReplacementToken(path22, updated) {
1415
+ const node = path22.node;
1416
+ let offset = 0;
1417
+ let original;
1418
+ if (path22.isStringLiteral()) {
1419
+ offset = 1;
1420
+ original = path22.node.value;
1421
+ } else if (path22.isTemplateElement()) {
1422
+ original = path22.node.value.raw;
1423
+ } else {
1424
+ original = "";
1425
+ }
1426
+ if (typeof node.start !== "number" || typeof node.end !== "number") {
1427
+ return void 0;
1428
+ }
1429
+ const start = node.start + offset;
1430
+ const end = node.end - offset;
1431
+ if (start >= end) {
1432
+ return void 0;
1433
+ }
1434
+ if (original === updated) {
1435
+ return void 0;
1436
+ }
1437
+ const value = path22.isStringLiteral() ? (0, import_escape4.jsStringEscape)(updated) : updated;
1438
+ return {
1439
+ start,
1440
+ end,
1441
+ value,
1442
+ path: path22
1443
+ };
1444
+ }
1445
+ function handleEvalStringLiteral(path22, handlerOptions, updater, handler) {
1446
+ const { code } = handler(path22.node.value, handlerOptions);
1447
+ if (!code) {
1448
+ return;
1449
+ }
1450
+ const token = createEvalReplacementToken(path22, code);
1451
+ if (token) {
1452
+ updater.addToken(token);
1453
+ }
1454
+ }
1455
+ function handleEvalTemplateElement(path22, handlerOptions, updater, handler) {
1456
+ const { code } = handler(path22.node.value.raw, handlerOptions);
1457
+ if (!code) {
1458
+ return;
1459
+ }
1460
+ const token = createEvalReplacementToken(path22, code);
1461
+ if (token) {
1462
+ updater.addToken(token);
1463
+ }
1464
+ }
1465
+ function getEvalStringHandlerOptions(options) {
1466
+ if (options.needEscaped === false && options.generateMap === false) {
1467
+ return options;
1468
+ }
1469
+ let cached = evalHandlerOptionsCache.get(options);
1470
+ if (!cached) {
1471
+ cached = {};
1472
+ evalHandlerOptionsCache.set(options, cached);
1473
+ }
1474
+ if (!cached.stringLiteralOptions) {
1475
+ cached.stringLiteralOptions = {
1476
+ ...options,
1477
+ needEscaped: false,
1478
+ generateMap: false
1479
+ };
1480
+ }
1481
+ return cached.stringLiteralOptions;
1482
+ }
1483
+ function getEvalTemplateHandlerOptions(options) {
1484
+ if (options.generateMap === false) {
1485
+ return options;
1486
+ }
1487
+ let cached = evalHandlerOptionsCache.get(options);
1488
+ if (!cached) {
1489
+ cached = {};
1490
+ evalHandlerOptionsCache.set(options, cached);
1491
+ }
1492
+ if (!cached.templateLiteralOptions) {
1493
+ cached.templateLiteralOptions = {
1494
+ ...options,
1495
+ generateMap: false
1496
+ };
1497
+ }
1498
+ return cached.templateLiteralOptions;
1499
+ }
1500
+ function walkEvalExpression(path22, options, updater, handler) {
1501
+ const stringHandlerOptions = getEvalStringHandlerOptions(options);
1502
+ const templateHandlerOptions = getEvalTemplateHandlerOptions(options);
1503
+ const maybeTraverse = path22?.traverse;
1504
+ if (typeof maybeTraverse === "function") {
1505
+ try {
1506
+ return maybeTraverse.call(path22, {
1507
+ StringLiteral(innerPath) {
1508
+ handleEvalStringLiteral(innerPath, stringHandlerOptions, updater, handler);
1509
+ },
1510
+ TemplateElement(innerPath) {
1511
+ handleEvalTemplateElement(innerPath, templateHandlerOptions, updater, handler);
1512
+ }
1513
+ });
1514
+ } catch (error) {
1515
+ const msg = error?.message ?? "";
1516
+ const scopeError = EVAL_SCOPE_ERROR_REGEXP.test(msg);
1517
+ if (!scopeError) {
1518
+ throw error;
1519
+ }
1520
+ }
1521
+ }
1522
+ const getArgs = path22?.get?.("arguments");
1523
+ if (Array.isArray(getArgs)) {
1524
+ for (const arg of getArgs) {
1525
+ if (arg?.isStringLiteral?.()) {
1526
+ handleEvalStringLiteral(arg, stringHandlerOptions, updater, handler);
1527
+ continue;
1528
+ }
1529
+ if (arg?.isTemplateLiteral?.()) {
1530
+ for (const quasi of arg.get("quasis")) {
1531
+ handleEvalTemplateElement(quasi, templateHandlerOptions, updater, handler);
1532
+ }
1533
+ }
1534
+ }
1535
+ return;
1536
+ }
1537
+ const nodeArgs = path22?.node?.arguments;
1538
+ if (Array.isArray(nodeArgs)) {
1539
+ for (const n of nodeArgs) {
1540
+ if (n?.type === "StringLiteral") {
1541
+ const stub = {
1542
+ node: n,
1543
+ isStringLiteral: () => true
1544
+ };
1545
+ handleEvalStringLiteral(stub, stringHandlerOptions, updater, handler);
1546
+ } else if (n?.type === "TemplateLiteral" && Array.isArray(n.quasis)) {
1547
+ for (const q of n.quasis) {
1548
+ const stub = {
1549
+ node: q,
1550
+ isTemplateElement: () => true
1551
+ };
1552
+ handleEvalTemplateElement(stub, templateHandlerOptions, updater, handler);
1553
+ }
1554
+ }
1555
+ }
1556
+ }
1557
+ }
1558
+
1559
+ // src/js/JsTokenUpdater.ts
1560
+ var JsTokenUpdater = class {
1561
+ constructor({ value } = {}) {
1562
+ this.tokens = value ? [...value] : [];
1563
+ }
1564
+ addToken(token) {
1565
+ if (token) {
1566
+ this.tokens.push(token);
1567
+ }
1568
+ }
1569
+ push(...args) {
1570
+ this.tokens.push(...args);
1571
+ return this;
1572
+ }
1573
+ /**
1574
+ * 待写入的 token 数量。
1575
+ */
1576
+ get length() {
1577
+ return this.tokens.length;
1578
+ }
1579
+ map(callbackfn) {
1580
+ this.tokens = this.tokens.map(callbackfn);
1581
+ return this;
1582
+ }
1583
+ filter(callbackfn) {
1584
+ this.tokens = this.tokens.filter(callbackfn);
1585
+ return this;
1586
+ }
1587
+ updateMagicString(ms) {
1588
+ for (const { start, end, value } of this.tokens) {
1589
+ ms.update(start, end, value);
1590
+ }
1591
+ return ms;
1592
+ }
1593
+ };
1594
+
1595
+ // src/js/module-graph/ignored-exports.ts
1596
+ var IgnoredExportsTracker = class {
1597
+ constructor(options) {
1598
+ this.options = options;
1599
+ this.ignoredExportNames = /* @__PURE__ */ new Map();
1600
+ }
1601
+ addIgnoredExport(filename, exportName) {
1602
+ if (!exportName) {
1603
+ return;
1604
+ }
1605
+ let pending = this.ignoredExportNames.get(filename);
1606
+ if (!pending) {
1607
+ pending = /* @__PURE__ */ new Set();
1608
+ this.ignoredExportNames.set(filename, pending);
1609
+ }
1610
+ if (pending.has(exportName)) {
1611
+ return;
1612
+ }
1613
+ pending.add(exportName);
1614
+ const existing = this.options.modules.get(filename);
1615
+ if (existing) {
1616
+ this.applyIgnoredExportsToAnalysis(filename, existing.analysis);
1617
+ }
1618
+ }
1619
+ registerIgnoredExportsFromTokens(resolved, tokens) {
1620
+ for (const token of tokens) {
1621
+ if (token.type === "ImportSpecifier") {
1622
+ this.addIgnoredExport(resolved, token.imported);
1623
+ } else if (token.type === "ImportDefaultSpecifier") {
1624
+ this.addIgnoredExport(resolved, "default");
1625
+ }
1626
+ }
1627
+ }
1628
+ applyIgnoredExportsToAnalysis(filename, analysis) {
1629
+ const pending = this.ignoredExportNames.get(filename);
1630
+ if (!pending || pending.size === 0) {
1631
+ return;
1632
+ }
1633
+ const names = new Set(pending);
1634
+ pending.clear();
1635
+ const propagate = [];
1636
+ for (const exportPath of analysis.exportDeclarations) {
1637
+ if (names.size === 0) {
1638
+ break;
1639
+ }
1640
+ if (exportPath.isExportDefaultDeclaration()) {
1641
+ if (names.has("default")) {
1642
+ analysis.walker.walkExportDefaultDeclaration(exportPath);
1643
+ names.delete("default");
1644
+ }
1645
+ continue;
1646
+ }
1647
+ if (exportPath.isExportNamedDeclaration()) {
1648
+ const source = exportPath.node.source?.value;
1649
+ if (typeof source === "string") {
1650
+ for (const spec of exportPath.get("specifiers")) {
1651
+ if (!spec.isExportSpecifier()) {
1652
+ continue;
1653
+ }
1654
+ const exported = spec.get("exported");
1655
+ let exportedName;
1656
+ if (exported.isIdentifier()) {
1657
+ exportedName = exported.node.name;
1658
+ } else if (exported.isStringLiteral()) {
1659
+ exportedName = exported.node.value;
1660
+ }
1661
+ if (!exportedName || !names.has(exportedName)) {
1662
+ continue;
1663
+ }
1664
+ const local = spec.get("local");
1665
+ if (local.isIdentifier()) {
1666
+ propagate.push({
1667
+ specifier: source,
1668
+ exportName: local.node.name
1669
+ });
1670
+ names.delete(exportedName);
1671
+ } else if (local.isStringLiteral()) {
1672
+ propagate.push({
1673
+ specifier: source,
1674
+ exportName: local.node.value
1675
+ });
1676
+ names.delete(exportedName);
1677
+ }
1678
+ }
1679
+ continue;
1680
+ }
1681
+ const declaration = exportPath.get("declaration");
1682
+ if (declaration.isVariableDeclaration()) {
1683
+ for (const decl of declaration.get("declarations")) {
1684
+ const id = decl.get("id");
1685
+ if (id.isIdentifier()) {
1686
+ const exportName = id.node.name;
1687
+ if (names.has(exportName)) {
1688
+ analysis.walker.walkVariableDeclarator(decl);
1689
+ names.delete(exportName);
1690
+ }
1691
+ }
1692
+ }
1693
+ }
1694
+ for (const spec of exportPath.get("specifiers")) {
1695
+ if (!spec.isExportSpecifier()) {
1696
+ continue;
1697
+ }
1698
+ const exported = spec.get("exported");
1699
+ let exportedName;
1700
+ if (exported.isIdentifier()) {
1701
+ exportedName = exported.node.name;
1702
+ } else if (exported.isStringLiteral()) {
1703
+ exportedName = exported.node.value;
1704
+ }
1705
+ if (!exportedName || !names.has(exportedName)) {
1706
+ continue;
1707
+ }
1708
+ const local = spec.get("local");
1709
+ analysis.walker.walkNode(local);
1710
+ names.delete(exportedName);
1711
+ }
1712
+ continue;
1713
+ }
1714
+ if (exportPath.isExportAllDeclaration()) {
1715
+ const source = exportPath.node.source?.value;
1716
+ if (typeof source === "string") {
1717
+ for (const exportName of names) {
1718
+ propagate.push({
1719
+ specifier: source,
1720
+ exportName
1721
+ });
1722
+ }
1723
+ names.clear();
1724
+ }
1725
+ }
1726
+ }
1727
+ for (const { specifier, exportName } of propagate) {
1728
+ let resolved;
1729
+ try {
1730
+ resolved = this.options.resolve(specifier, filename);
1731
+ } catch {
1732
+ resolved = void 0;
1733
+ }
1734
+ if (!resolved) {
1735
+ pending.add(exportName);
1736
+ continue;
1737
+ }
1738
+ if (this.options.filter && !this.options.filter(resolved, specifier, filename)) {
1739
+ pending.add(exportName);
1740
+ continue;
1741
+ }
1742
+ this.addIgnoredExport(resolved, exportName);
1743
+ }
1744
+ for (const name of names) {
1745
+ pending.add(name);
1746
+ }
1747
+ }
1748
+ };
1749
+
1750
+ // src/js/ModuleGraph.ts
1751
+ var JsModuleGraph = class {
1752
+ constructor(entry, graphOptions) {
1753
+ this.modules = /* @__PURE__ */ new Map();
1754
+ this.queue = [];
1755
+ this.resolve = graphOptions.resolve;
1756
+ this.load = graphOptions.load;
1757
+ this.filter = graphOptions.filter;
1758
+ this.maxDepth = graphOptions.maxDepth ?? Number.POSITIVE_INFINITY;
1759
+ const { moduleGraph: _moduleGraph, filename: _ignoredFilename, ...rest } = entry.handlerOptions;
1760
+ this.baseOptions = {
1761
+ ...rest,
1762
+ filename: entry.filename
1763
+ };
1764
+ this.parserOptions = entry.handlerOptions.babelParserOptions;
1765
+ this.rootFilename = entry.filename;
1766
+ this.ignoredExports = new IgnoredExportsTracker({
1767
+ resolve: this.resolve,
1768
+ filter: this.filter,
1769
+ modules: this.modules
1770
+ });
1771
+ this.modules.set(entry.filename, {
1772
+ filename: entry.filename,
1773
+ source: entry.source,
1774
+ analysis: entry.analysis
1775
+ });
1776
+ this.queue.push({ filename: entry.filename, depth: 0 });
1777
+ }
1778
+ build() {
1779
+ this.collectDependencies();
1780
+ let linked;
1781
+ for (const [filename, state] of this.modules) {
1782
+ if (filename === this.rootFilename) {
1783
+ continue;
1784
+ }
1785
+ const childOptions = {
1786
+ ...this.baseOptions,
1787
+ filename
1788
+ };
1789
+ const ms = processUpdatedSource(state.source, childOptions, state.analysis);
1790
+ const code = ms.toString();
1791
+ if (code !== state.source) {
1792
+ if (!linked) {
1793
+ linked = {};
1794
+ }
1795
+ linked[filename] = { code };
1796
+ }
1797
+ }
1798
+ return linked;
1799
+ }
1800
+ collectDependencies() {
1801
+ while (this.queue.length > 0) {
1802
+ const { filename, depth } = this.queue.shift();
1803
+ if (depth >= this.maxDepth) {
1804
+ continue;
1805
+ }
1806
+ const state = this.modules.get(filename);
1807
+ if (!state) {
1808
+ continue;
1809
+ }
1810
+ const dependencySpecifiers = /* @__PURE__ */ new Map();
1811
+ for (const token of state.analysis.walker.imports) {
1812
+ if (!dependencySpecifiers.has(token.source)) {
1813
+ dependencySpecifiers.set(token.source, []);
1814
+ }
1815
+ dependencySpecifiers.get(token.source).push(token);
1816
+ }
1817
+ for (const exportPath of state.analysis.exportDeclarations) {
1818
+ if (exportPath.isExportAllDeclaration() || exportPath.isExportNamedDeclaration()) {
1819
+ const source = exportPath.node.source?.value;
1820
+ if (typeof source === "string" && !dependencySpecifiers.has(source)) {
1821
+ dependencySpecifiers.set(source, []);
1822
+ }
1823
+ }
1824
+ }
1825
+ for (const [specifier, tokens] of dependencySpecifiers) {
1826
+ let resolved;
1827
+ try {
1828
+ resolved = this.resolve(specifier, filename);
1829
+ } catch {
1830
+ continue;
1831
+ }
1832
+ if (!resolved) {
1833
+ continue;
1834
+ }
1835
+ if (this.filter && !this.filter(resolved, specifier, filename)) {
1836
+ continue;
1837
+ }
1838
+ if (tokens.length > 0) {
1839
+ this.ignoredExports.registerIgnoredExportsFromTokens(resolved, tokens);
1840
+ }
1841
+ if (this.modules.has(resolved)) {
1842
+ continue;
1843
+ }
1844
+ let source;
1845
+ try {
1846
+ source = this.load(resolved);
1847
+ } catch {
1848
+ continue;
1849
+ }
1850
+ if (typeof source !== "string") {
1851
+ continue;
1852
+ }
1853
+ let analysis;
1854
+ try {
1855
+ const ast = babelParse(source, {
1856
+ ...this.parserOptions,
1857
+ sourceFilename: resolved
1858
+ });
1859
+ analysis = analyzeSource(ast, {
1860
+ ...this.baseOptions,
1861
+ filename: resolved
1862
+ });
1863
+ this.ignoredExports.applyIgnoredExportsToAnalysis(resolved, analysis);
1864
+ } catch {
1865
+ continue;
1866
+ }
1867
+ this.modules.set(resolved, {
1868
+ filename: resolved,
1869
+ source,
1870
+ analysis
1871
+ });
1872
+ this.queue.push({ filename: resolved, depth: depth + 1 });
1873
+ }
1874
+ }
1875
+ }
1876
+ };
1877
+
1878
+ // src/js/node-path-walker/export-handlers.ts
1879
+ function walkExportDeclaration(ctx, path22) {
1880
+ if (path22.isExportDeclaration()) {
1881
+ if (path22.isExportNamedDeclaration()) {
1882
+ walkExportNamedDeclaration(ctx, path22);
1883
+ } else if (path22.isExportDefaultDeclaration()) {
1884
+ walkExportDefaultDeclaration(ctx, path22);
1885
+ } else if (path22.isExportAllDeclaration()) {
1886
+ walkExportAllDeclaration(ctx, path22);
1887
+ }
1888
+ }
1889
+ }
1890
+ function walkExportNamedDeclaration(ctx, path22) {
1891
+ const declaration = path22.get("declaration");
1892
+ if (declaration.isVariableDeclaration()) {
1893
+ for (const decl of declaration.get("declarations")) {
1894
+ ctx.walkNode(decl);
1895
+ }
1896
+ }
1897
+ const specifiers = path22.get("specifiers");
1898
+ for (const spec of specifiers) {
1899
+ if (spec.isExportSpecifier()) {
1900
+ const local = spec.get("local");
1901
+ if (local.isIdentifier()) {
1902
+ ctx.walkNode(local);
1903
+ }
1904
+ }
1905
+ }
1906
+ }
1907
+ function walkExportDefaultDeclaration(ctx, path22) {
1908
+ const decl = path22.get("declaration");
1909
+ if (decl.isIdentifier()) {
1910
+ ctx.walkNode(decl);
1911
+ } else {
1912
+ ctx.walkNode(decl);
1913
+ }
1914
+ }
1915
+ function walkExportAllDeclaration(ctx, path22) {
1916
+ const source = path22.get("source");
1917
+ if (source.isStringLiteral()) {
1918
+ ctx.addImportToken(
1919
+ {
1920
+ declaration: path22,
1921
+ source: source.node.value,
1922
+ type: "ExportAllDeclaration"
1923
+ }
1924
+ );
1925
+ }
1926
+ }
1927
+
1928
+ // src/js/node-path-walker/import-tokens.ts
1929
+ function maybeAddImportToken(imports, arg) {
1930
+ if (!(arg.isImportSpecifier() && arg.node.importKind !== "type" || arg.isImportDefaultSpecifier())) {
1931
+ return false;
1932
+ }
1933
+ const importDeclaration = arg.parentPath;
1934
+ if (!importDeclaration.isImportDeclaration() || importDeclaration.node.importKind === "type") {
1935
+ return false;
1936
+ }
1937
+ if (arg.isImportSpecifier()) {
1938
+ const imported = arg.get("imported");
1939
+ if (imported.isIdentifier()) {
1940
+ imports.add(
1941
+ {
1942
+ declaration: importDeclaration,
1943
+ specifier: arg,
1944
+ imported: imported.node.name,
1945
+ local: arg.node.local.name,
1946
+ source: importDeclaration.node.source.value,
1947
+ type: "ImportSpecifier"
1948
+ }
1949
+ );
1950
+ }
1951
+ return true;
1952
+ }
1953
+ imports.add(
1954
+ {
1955
+ declaration: importDeclaration,
1956
+ specifier: arg,
1957
+ local: arg.node.local.name,
1958
+ source: importDeclaration.node.source.value,
1959
+ type: "ImportDefaultSpecifier"
1960
+ }
1961
+ );
1962
+ return true;
1963
+ }
1964
+
1965
+ // src/js/NodePathWalker.ts
1966
+ var EMPTY_IGNORE_CALL_EXPRESSION_IDENTIFIERS = [];
1967
+ var EMPTY_IMPORT_TOKENS = /* @__PURE__ */ new Set();
1968
+ function NOOP_STRING_PATH_CALLBACK() {
1969
+ }
1970
+ var NEVER_MATCH_NAME2 = () => false;
1971
+ var NodePathWalker = class {
1972
+ constructor({ ignoreCallExpressionIdentifiers, callback } = {}) {
1973
+ this.hasIgnoredCallIdentifiers = Boolean(ignoreCallExpressionIdentifiers && ignoreCallExpressionIdentifiers.length > 0);
1974
+ this.ignoreCallExpressionIdentifiers = ignoreCallExpressionIdentifiers ?? EMPTY_IGNORE_CALL_EXPRESSION_IDENTIFIERS;
1975
+ this.callback = callback ?? NOOP_STRING_PATH_CALLBACK;
1976
+ this.isIgnoredCallIdentifier = this.hasIgnoredCallIdentifiers ? createNameMatcher(this.ignoreCallExpressionIdentifiers, { exact: true }) : NEVER_MATCH_NAME2;
1977
+ }
1978
+ get imports() {
1979
+ return this.importsStore ?? EMPTY_IMPORT_TOKENS;
1980
+ }
1981
+ getWritableImports() {
1982
+ if (!this.importsStore) {
1983
+ this.importsStore = /* @__PURE__ */ new Set();
1984
+ }
1985
+ return this.importsStore;
1986
+ }
1987
+ addImportToken(token) {
1988
+ this.getWritableImports().add(token);
1989
+ }
1990
+ getVisited() {
1991
+ if (!this.visitedStore) {
1992
+ this.visitedStore = /* @__PURE__ */ new WeakSet();
1993
+ }
1994
+ return this.visitedStore;
1995
+ }
1996
+ walkVariableDeclarator(path22) {
1997
+ const init = path22.get("init");
1998
+ this.walkNode(init);
1999
+ }
2000
+ walkTemplateLiteral(path22) {
2001
+ for (const exp of path22.get("expressions")) {
2002
+ this.walkNode(exp);
2003
+ }
2004
+ for (const quasis of path22.get("quasis")) {
2005
+ this.callback(quasis);
2006
+ }
2007
+ }
2008
+ walkStringLiteral(path22) {
2009
+ this.callback(path22);
2010
+ }
2011
+ walkBinaryExpression(path22) {
2012
+ const left = path22.get("left");
2013
+ this.walkNode(left);
2014
+ const right = path22.get("right");
2015
+ this.walkNode(right);
2016
+ }
2017
+ walkLogicalExpression(path22) {
2018
+ const left = path22.get("left");
2019
+ this.walkNode(left);
2020
+ const right = path22.get("right");
2021
+ this.walkNode(right);
2022
+ }
2023
+ walkObjectExpression(path22) {
2024
+ const props = path22.get("properties");
2025
+ for (const prop of props) {
2026
+ if (prop.isObjectProperty()) {
2027
+ const key = prop.get("key");
2028
+ this.walkNode(key);
2029
+ const value = prop.get("value");
2030
+ this.walkNode(value);
2031
+ }
2032
+ }
2033
+ }
2034
+ walkArrayExpression(path22) {
2035
+ const elements = path22.get("elements");
2036
+ for (const element of elements) {
2037
+ this.walkNode(element);
2038
+ }
2039
+ }
2040
+ walkNode(arg) {
2041
+ const visited = this.getVisited();
2042
+ if (visited.has(arg)) {
2043
+ return;
2044
+ }
2045
+ visited.add(arg);
2046
+ if (arg.isIdentifier()) {
2047
+ const binding = arg?.scope?.getBinding?.(arg.node.name);
2048
+ if (binding) {
2049
+ this.walkNode(binding.path);
2050
+ }
2051
+ } else if (arg.isMemberExpression()) {
2052
+ const objectPath = arg.get("object");
2053
+ if (objectPath.isIdentifier()) {
2054
+ const binding = arg?.scope?.getBinding?.(objectPath.node.name);
2055
+ if (binding) {
2056
+ if (binding.path.isVariableDeclarator()) {
2057
+ this.walkVariableDeclarator(binding.path);
2058
+ }
2059
+ }
2060
+ }
2061
+ } else if (arg.isTemplateLiteral()) {
2062
+ this.walkTemplateLiteral(arg);
2063
+ } else if (arg.isStringLiteral()) {
2064
+ this.walkStringLiteral(arg);
2065
+ } else if (arg.isBinaryExpression()) {
2066
+ this.walkBinaryExpression(arg);
2067
+ } else if (arg.isLogicalExpression()) {
2068
+ this.walkLogicalExpression(arg);
2069
+ } else if (arg.isObjectExpression()) {
2070
+ this.walkObjectExpression(arg);
2071
+ } else if (arg.isArrayExpression()) {
2072
+ this.walkArrayExpression(arg);
2073
+ } else if (arg.isVariableDeclarator()) {
2074
+ this.walkVariableDeclarator(arg);
2075
+ } else if (maybeAddImportToken(this.getWritableImports(), arg)) {
2076
+ }
2077
+ }
2078
+ /**
2079
+ * Walk the arguments of a desired call expression so their bindings can be analysed.
2080
+ */
2081
+ walkCallExpression(path22) {
2082
+ if (!this.hasIgnoredCallIdentifiers) {
2083
+ return;
2084
+ }
2085
+ const calleePath = path22.get("callee");
2086
+ if (calleePath.isIdentifier() && this.isIgnoredCallIdentifier(calleePath.node.name)) {
2087
+ for (const arg of path22.get("arguments")) {
2088
+ this.walkNode(arg);
2089
+ }
2090
+ }
2091
+ }
2092
+ walkExportDeclaration(path22) {
2093
+ walkExportDeclaration(this, path22);
2094
+ }
2095
+ walkExportNamedDeclaration(path22) {
2096
+ walkExportNamedDeclaration(this, path22);
2097
+ }
2098
+ walkExportDefaultDeclaration(path22) {
2099
+ walkExportDefaultDeclaration(this, path22);
2100
+ }
2101
+ walkExportAllDeclaration(path22) {
2102
+ walkExportAllDeclaration(this, path22);
2103
+ }
2104
+ };
2105
+
2106
+ // src/js/taggedTemplateIgnore.ts
2107
+ function createTaggedTemplateIgnore({ matcher, names }) {
2108
+ const bindingIgnoreCache = /* @__PURE__ */ new Map();
2109
+ const taggedTemplateIgnoreCache = /* @__PURE__ */ new WeakMap();
2110
+ const seenBindings = /* @__PURE__ */ new Set();
2111
+ let singleCanonicalIgnoreName;
2112
+ let canonicalIgnoreNames;
2113
+ for (const item of names ?? []) {
2114
+ if (typeof item !== "string") {
2115
+ continue;
2116
+ }
2117
+ if (singleCanonicalIgnoreName === void 0) {
2118
+ singleCanonicalIgnoreName = item;
2119
+ continue;
2120
+ }
2121
+ if (item === singleCanonicalIgnoreName) {
2122
+ continue;
2123
+ }
2124
+ if (!canonicalIgnoreNames) {
2125
+ canonicalIgnoreNames = /* @__PURE__ */ new Set([singleCanonicalIgnoreName, item]);
2126
+ continue;
2127
+ }
2128
+ canonicalIgnoreNames.add(item);
2129
+ }
2130
+ const hasCanonicalIgnoreNames = singleCanonicalIgnoreName !== void 0;
2131
+ const matchesIgnoreName = (value) => {
2132
+ if (hasCanonicalIgnoreNames) {
2133
+ if (canonicalIgnoreNames) {
2134
+ if (canonicalIgnoreNames.has(value)) {
2135
+ return true;
2136
+ }
2137
+ } else if (value === singleCanonicalIgnoreName) {
2138
+ return true;
2139
+ }
2140
+ }
2141
+ return matcher(value);
2142
+ };
2143
+ const propertyMatches = (propertyPath) => {
2144
+ if (!propertyPath) {
2145
+ return false;
2146
+ }
2147
+ if (propertyPath.isIdentifier()) {
2148
+ return matchesIgnoreName(propertyPath.node.name);
2149
+ }
2150
+ if (propertyPath.isStringLiteral()) {
2151
+ return matchesIgnoreName(propertyPath.node.value);
2152
+ }
2153
+ return false;
2154
+ };
2155
+ const resolvesMemberExpressionToIgnore = (path22, seen) => {
2156
+ const propertyPath = path22.get("property");
2157
+ if (propertyMatches(propertyPath)) {
2158
+ return true;
2159
+ }
2160
+ const objectPath = path22.get("object");
2161
+ if (objectPath.isIdentifier()) {
2162
+ const scope = objectPath?.scope;
2163
+ const binding = scope?.getBinding?.(objectPath.node.name);
2164
+ if (binding) {
2165
+ return resolvesToWeappTwIgnore(binding, seen);
2166
+ }
2167
+ }
2168
+ return false;
2169
+ };
2170
+ const resolvesToWeappTwIgnore = (binding, seen) => {
2171
+ const cached = bindingIgnoreCache.get(binding);
2172
+ if (cached !== void 0) {
2173
+ return cached;
2174
+ }
2175
+ if (seen.has(binding)) {
2176
+ return false;
2177
+ }
2178
+ seen.add(binding);
2179
+ let result = false;
2180
+ const bindingPath = binding.path;
2181
+ if (bindingPath.isImportSpecifier()) {
2182
+ const imported = bindingPath.node.imported;
2183
+ if (imported.type === "Identifier" && matchesIgnoreName(imported.name)) {
2184
+ result = true;
2185
+ } else if (imported.type === "StringLiteral" && matchesIgnoreName(imported.value)) {
2186
+ result = true;
2187
+ }
2188
+ } else if (bindingPath.isVariableDeclarator()) {
2189
+ const init = bindingPath.get("init");
2190
+ if (init && init.node) {
2191
+ if (init.isIdentifier()) {
2192
+ const target = binding?.scope?.getBinding?.(init.node.name);
2193
+ if (target) {
2194
+ result = resolvesToWeappTwIgnore(target, seen);
2195
+ }
2196
+ } else if (init.isMemberExpression()) {
2197
+ result = resolvesMemberExpressionToIgnore(init, seen);
2198
+ }
2199
+ }
2200
+ }
2201
+ bindingIgnoreCache.set(binding, result);
2202
+ seen.delete(binding);
2203
+ return result;
2204
+ };
2205
+ const getEffectiveTagPath = (tagPath) => {
2206
+ let current = tagPath;
2207
+ while (true) {
2208
+ if (current.isParenthesizedExpression?.() || current.node.type === "ParenthesizedExpression") {
2209
+ current = current.get("expression");
2210
+ continue;
2211
+ }
2212
+ if (current.isTSAsExpression() || current.isTSTypeAssertion()) {
2213
+ current = current.get("expression");
2214
+ continue;
2215
+ }
2216
+ if (current.isTSNonNullExpression()) {
2217
+ current = current.get("expression");
2218
+ continue;
2219
+ }
2220
+ if (current.isTypeCastExpression?.()) {
2221
+ current = current.get("expression");
2222
+ continue;
2223
+ }
2224
+ if (current.isSequenceExpression()) {
2225
+ const expressions = current.get("expressions");
2226
+ const last = expressions.at(-1);
2227
+ if (last) {
2228
+ current = last;
2229
+ continue;
2230
+ }
2231
+ }
2232
+ if (current.isCallExpression?.() || current.node.type === "CallExpression") {
2233
+ const callee = current.get("callee");
2234
+ current = callee;
2235
+ continue;
2236
+ }
2237
+ break;
2238
+ }
2239
+ return current;
2240
+ };
2241
+ const evaluateTagPath = (tagPath, seen) => {
2242
+ if (tagPath.isCallExpression?.() || tagPath.node.type === "CallExpression") {
2243
+ const calleePath = tagPath.get("callee");
2244
+ return evaluateTagPath(calleePath, seen);
2245
+ }
2246
+ if (tagPath.isIdentifier()) {
2247
+ if (matchesIgnoreName(tagPath.node.name)) {
2248
+ return true;
2249
+ }
2250
+ const binding = tagPath?.scope?.getBinding?.(tagPath.node.name);
2251
+ if (binding) {
2252
+ return resolvesToWeappTwIgnore(binding, seen);
2253
+ }
2254
+ return false;
2255
+ }
2256
+ if (tagPath.isMemberExpression()) {
2257
+ return resolvesMemberExpressionToIgnore(tagPath, seen);
2258
+ }
2259
+ return false;
2260
+ };
2261
+ const computeIgnore = (tagPath) => {
2262
+ const cached = taggedTemplateIgnoreCache.get(tagPath.node);
2263
+ if (cached !== void 0) {
2264
+ return cached;
2265
+ }
2266
+ const effectiveTagPath = getEffectiveTagPath(tagPath);
2267
+ const effectiveCached = taggedTemplateIgnoreCache.get(effectiveTagPath.node);
2268
+ if (effectiveCached !== void 0) {
2269
+ taggedTemplateIgnoreCache.set(tagPath.node, effectiveCached);
2270
+ return effectiveCached;
2271
+ }
2272
+ seenBindings.clear();
2273
+ const result = evaluateTagPath(effectiveTagPath, seenBindings);
2274
+ taggedTemplateIgnoreCache.set(effectiveTagPath.node, result);
2275
+ taggedTemplateIgnoreCache.set(tagPath.node, result);
2276
+ return result;
2277
+ };
2278
+ return {
2279
+ shouldIgnore(tagPath) {
2280
+ return computeIgnore(tagPath);
2281
+ },
2282
+ getEffectiveTagPath
590
2283
  };
591
2284
  }
592
2285
 
593
- // src/tailwindcss/targets.ts
594
- function logTailwindcssTarget(kind, patcher, baseDir) {
595
- const packageInfo = patcher?.packageInfo;
596
- const label = kind === "cli" ? "weapp-tw patch" : "Weapp-tailwindcss";
597
- if (!packageInfo?.rootPath) {
598
- import_logger3.logger.warn(
599
- "%s \u672A\u627E\u5230 Tailwind CSS \u4F9D\u8D56\uFF0C\u8BF7\u68C0\u67E5\u5728 %s \u662F\u5426\u5DF2\u5B89\u88C5 tailwindcss",
600
- label,
601
- baseDir ?? import_node_process6.default.cwd()
602
- );
603
- return;
604
- }
605
- const displayPath = formatRelativeToBase(packageInfo.rootPath, baseDir);
606
- const version = packageInfo.version ? ` (v${packageInfo.version})` : "";
607
- if (kind === "runtime") {
608
- logRuntimeTailwindcssTarget(baseDir, packageInfo.rootPath, packageInfo.version);
609
- return;
2286
+ // src/js/babel.ts
2287
+ var EXPRESSION_WRAPPER_PREFIX = "(\n";
2288
+ var EXPRESSION_WRAPPER_SUFFIX = "\n)";
2289
+ var EMPTY_IGNORED_PATHS = /* @__PURE__ */ new WeakSet();
2290
+ var EMPTY_IMPORT_DECLARATIONS = /* @__PURE__ */ new Set();
2291
+ var EMPTY_EXPORT_DECLARATIONS = /* @__PURE__ */ new Set();
2292
+ var EMPTY_REQUIRE_CALL_PATHS = [];
2293
+ var ignoredTaggedTemplateMatcherCache = /* @__PURE__ */ new WeakMap();
2294
+ var defaultEvalHandler;
2295
+ function getIgnoredTaggedTemplateMatcher(options) {
2296
+ const cached = ignoredTaggedTemplateMatcherCache.get(options);
2297
+ if (cached) {
2298
+ return cached;
2299
+ }
2300
+ const created = createNameMatcher(options.ignoreTaggedTemplateExpressionIdentifiers, { exact: true });
2301
+ ignoredTaggedTemplateMatcherCache.set(options, created);
2302
+ return created;
2303
+ }
2304
+ function getDefaultEvalHandler() {
2305
+ if (!defaultEvalHandler) {
2306
+ throw new Error("Default JS eval handler is not initialized.");
610
2307
  }
611
- import_logger3.logger.info("%s \u7ED1\u5B9A Tailwind CSS -> %s%s", label, displayPath, version);
2308
+ return defaultEvalHandler;
612
2309
  }
613
-
614
- // src/tailwindcss/v4/config.ts
615
- var import_logger4 = require("@weapp-tailwindcss/logger");
616
-
617
- // src/tailwindcss/v4/patcher.ts
618
- var import_logger6 = require("@weapp-tailwindcss/logger");
619
-
620
- // src/tailwindcss/patcher.ts
621
- var import_node_path7 = __toESM(require("path"));
622
- var import_node_process8 = __toESM(require("process"));
623
- var import_logger5 = require("@weapp-tailwindcss/logger");
624
- var import_shared2 = require("@weapp-tailwindcss/shared");
625
- var import_tailwindcss_patch = require("tailwindcss-patch");
626
-
627
- // src/tailwindcss/patcher-resolve.ts
628
- var import_node_fs5 = require("fs");
629
- var import_node_module = require("module");
630
- var import_node_path6 = __toESM(require("path"));
631
- var import_node_process7 = __toESM(require("process"));
632
- var import_node_url = require("url");
633
-
634
- // src/tailwindcss/v4/css-entries.ts
635
- var import_node_path8 = __toESM(require("path"));
636
-
637
- // src/context/compiler-context-cache.ts
638
- var import_node_buffer = require("buffer");
639
- var import_node_path9 = __toESM(require("path"));
640
- var import_node_process9 = __toESM(require("process"));
641
- var import_logger7 = require("@weapp-tailwindcss/logger");
642
- var globalCacheHolder = globalThis;
643
- var compilerContextCache = globalCacheHolder.__WEAPP_TW_COMPILER_CONTEXT_CACHE__ ?? (globalCacheHolder.__WEAPP_TW_COMPILER_CONTEXT_CACHE__ = /* @__PURE__ */ new Map());
644
-
645
- // src/context/handlers.ts
646
- var import_postcss = require("@weapp-tailwindcss/postcss");
647
-
648
- // src/babel/index.ts
649
- var import_traverse = __toESM(require("@babel/traverse"));
650
- var import_parser = require("@babel/parser");
651
- function _interopDefaultCompat(e) {
652
- return e && typeof e === "object" && "default" in e ? e.default : e;
2310
+ function analyzeSource(ast, options, handler, collectModuleMetadata = true) {
2311
+ const jsTokenUpdater = new JsTokenUpdater();
2312
+ const needScope = Boolean(options.ignoreCallExpressionIdentifiers && options.ignoreCallExpressionIdentifiers.length > 0);
2313
+ const ignoredPaths = needScope ? /* @__PURE__ */ new WeakSet() : EMPTY_IGNORED_PATHS;
2314
+ const walker = needScope ? new NodePathWalker({
2315
+ ignoreCallExpressionIdentifiers: options.ignoreCallExpressionIdentifiers,
2316
+ callback(path22) {
2317
+ ignoredPaths.add(path22);
2318
+ }
2319
+ }) : new NodePathWalker();
2320
+ let taggedTemplateIgnore;
2321
+ const hasTaggedTemplateIgnoreIdentifiers = Boolean(
2322
+ options.ignoreTaggedTemplateExpressionIdentifiers && options.ignoreTaggedTemplateExpressionIdentifiers.length > 0
2323
+ );
2324
+ function getTaggedTemplateIgnore() {
2325
+ if (!taggedTemplateIgnore) {
2326
+ taggedTemplateIgnore = createTaggedTemplateIgnore({
2327
+ matcher: getIgnoredTaggedTemplateMatcher(options),
2328
+ names: options.ignoreTaggedTemplateExpressionIdentifiers
2329
+ });
2330
+ }
2331
+ return taggedTemplateIgnore;
2332
+ }
2333
+ const targetPaths = [];
2334
+ const importDeclarations = collectModuleMetadata ? /* @__PURE__ */ new Set() : EMPTY_IMPORT_DECLARATIONS;
2335
+ const exportDeclarations = collectModuleMetadata ? /* @__PURE__ */ new Set() : EMPTY_EXPORT_DECLARATIONS;
2336
+ const requireCallPaths = collectModuleMetadata ? [] : EMPTY_REQUIRE_CALL_PATHS;
2337
+ const evalHandler = handler ?? getDefaultEvalHandler();
2338
+ const templateElementEnter = hasTaggedTemplateIgnoreIdentifiers ? (p) => {
2339
+ const pp = p.parentPath;
2340
+ if (pp.isTemplateLiteral()) {
2341
+ const ppp = pp.parentPath;
2342
+ if (isEvalPath(ppp)) {
2343
+ return;
2344
+ }
2345
+ if (ppp.isTaggedTemplateExpression()) {
2346
+ const tagPath = ppp.get("tag");
2347
+ if (getTaggedTemplateIgnore().shouldIgnore(tagPath)) {
2348
+ return;
2349
+ }
2350
+ }
2351
+ }
2352
+ targetPaths.push(p);
2353
+ } : (p) => {
2354
+ const pp = p.parentPath;
2355
+ if (pp.isTemplateLiteral()) {
2356
+ const ppp = pp.parentPath;
2357
+ if (isEvalPath(ppp)) {
2358
+ return;
2359
+ }
2360
+ }
2361
+ targetPaths.push(p);
2362
+ };
2363
+ const callExpressionEnter = !collectModuleMetadata && !needScope ? (p) => {
2364
+ if (isEvalPath(p)) {
2365
+ walkEvalExpression(p, options, jsTokenUpdater, evalHandler);
2366
+ }
2367
+ } : (p) => {
2368
+ if (isEvalPath(p)) {
2369
+ walkEvalExpression(p, options, jsTokenUpdater, evalHandler);
2370
+ return;
2371
+ }
2372
+ const calleePath = p.get("callee");
2373
+ if (collectModuleMetadata && calleePath.isIdentifier({ name: "require" }) && !p?.scope?.hasBinding?.("require")) {
2374
+ const args = p.get("arguments");
2375
+ if (Array.isArray(args) && args.length > 0) {
2376
+ const first = args[0];
2377
+ if (first?.isStringLiteral()) {
2378
+ requireCallPaths.push(first);
2379
+ }
2380
+ }
2381
+ }
2382
+ if (needScope) {
2383
+ walker.walkCallExpression(p);
2384
+ }
2385
+ };
2386
+ const traverseOptions = {
2387
+ StringLiteral: {
2388
+ enter(p) {
2389
+ if (isEvalPath(p.parentPath)) {
2390
+ return;
2391
+ }
2392
+ targetPaths.push(p);
2393
+ }
2394
+ },
2395
+ TemplateElement: {
2396
+ enter: templateElementEnter
2397
+ },
2398
+ CallExpression: {
2399
+ enter: callExpressionEnter
2400
+ },
2401
+ ...collectModuleMetadata ? {
2402
+ ImportDeclaration: {
2403
+ enter(p) {
2404
+ importDeclarations.add(p);
2405
+ }
2406
+ },
2407
+ ExportDeclaration: {
2408
+ enter(p) {
2409
+ exportDeclarations.add(p);
2410
+ }
2411
+ }
2412
+ } : {}
2413
+ };
2414
+ traverse(ast, { ...traverseOptions, noScope: !needScope });
2415
+ return {
2416
+ walker,
2417
+ jsTokenUpdater,
2418
+ ast,
2419
+ targetPaths,
2420
+ importDeclarations,
2421
+ exportDeclarations,
2422
+ requireCallPaths,
2423
+ ignoredPaths
2424
+ };
653
2425
  }
654
- var traverse = _interopDefaultCompat(import_traverse.default);
655
-
656
- // src/utils/nameMatcher.ts
657
- var import_regex = require("@weapp-core/regex");
658
-
659
- // src/js/babel/parse.ts
660
- var import_lru_cache2 = require("lru-cache");
661
- var parseCache = new import_lru_cache2.LRUCache(
662
- {
663
- max: 1024
2426
+ function jsHandler(rawSource, options) {
2427
+ const shouldWrapExpression = Boolean(options.wrapExpression);
2428
+ const source = shouldWrapExpression ? `${EXPRESSION_WRAPPER_PREFIX}${rawSource}${EXPRESSION_WRAPPER_SUFFIX}` : rawSource;
2429
+ let ast;
2430
+ try {
2431
+ ast = babelParse(source, options.babelParserOptions);
2432
+ } catch (error) {
2433
+ return {
2434
+ code: rawSource,
2435
+ error
2436
+ };
664
2437
  }
665
- );
666
-
667
- // src/js/babel/process.ts
668
- var import_magic_string = __toESM(require("magic-string"));
669
-
670
- // src/js/handlers.ts
671
- var import_escape3 = require("@ast-core/escape");
672
- var import_extractors = require("@weapp-tailwindcss/shared/extractors");
673
-
674
- // src/wxml/shared.ts
675
- var import_escape2 = require("@weapp-core/escape");
676
-
677
- // src/js/handlers.ts
678
- var debug2 = createDebug("[js:handlers] ");
679
-
680
- // src/js/evalTransforms.ts
681
- var import_escape4 = require("@ast-core/escape");
2438
+ const needsModuleMetadata = Boolean(options.moduleSpecifierReplacements || options.moduleGraph && options.filename);
2439
+ const analysis = analyzeSource(ast, options, jsHandler, needsModuleMetadata);
2440
+ const ms = processUpdatedSource(source, options, analysis);
2441
+ if (shouldWrapExpression) {
2442
+ const start = 0;
2443
+ const end = source.length;
2444
+ const prefixLength = EXPRESSION_WRAPPER_PREFIX.length;
2445
+ const suffixLength = EXPRESSION_WRAPPER_SUFFIX.length;
2446
+ ms.remove(start, start + prefixLength);
2447
+ ms.remove(end - suffixLength, end);
2448
+ }
2449
+ const result = {
2450
+ code: ms.toString()
2451
+ };
2452
+ if (options.generateMap) {
2453
+ Object.defineProperty(result, "map", {
2454
+ configurable: true,
2455
+ enumerable: true,
2456
+ get() {
2457
+ return ms.generateMap();
2458
+ }
2459
+ });
2460
+ }
2461
+ if (options.moduleGraph && options.filename) {
2462
+ const graph = new JsModuleGraph(
2463
+ {
2464
+ filename: options.filename,
2465
+ source: rawSource,
2466
+ analysis,
2467
+ handlerOptions: options
2468
+ },
2469
+ options.moduleGraph
2470
+ );
2471
+ const linked = graph.build();
2472
+ if (linked) {
2473
+ result.linked = linked;
2474
+ }
2475
+ }
2476
+ return result;
2477
+ }
2478
+ defaultEvalHandler = jsHandler;
682
2479
 
683
2480
  // src/wxml/utils/codegen/legacy-rewriter.ts
684
2481
  var import_magic_string2 = __toESM(require("magic-string"));
@@ -922,9 +2719,273 @@ function formatOutputPath(target, baseDir) {
922
2719
  return relative.startsWith(".") ? relative : `.${import_node_path12.default.sep}${relative}`;
923
2720
  }
924
2721
 
2722
+ // src/cli/doctor.ts
2723
+ var import_node_fs7 = require("fs");
2724
+ var import_node_module3 = require("module");
2725
+ var import_node_path13 = __toESM(require("path"));
2726
+ var import_node_process13 = __toESM(require("process"));
2727
+ var import_semver = __toESM(require("semver"));
2728
+
2729
+ // src/cli/doctor/constants.ts
2730
+ var CONFIG_FILES = {
2731
+ tailwind: [
2732
+ "tailwind.config.js",
2733
+ "tailwind.config.cjs",
2734
+ "tailwind.config.mjs",
2735
+ "tailwind.config.ts"
2736
+ ],
2737
+ postcss: [
2738
+ "postcss.config.js",
2739
+ "postcss.config.cjs",
2740
+ "postcss.config.mjs",
2741
+ "postcss.config.ts"
2742
+ ],
2743
+ vite: ["vite.config.js", "vite.config.mjs", "vite.config.ts"],
2744
+ webpack: ["webpack.config.js", "webpack.config.cjs", "webpack.config.ts"]
2745
+ };
2746
+ var FRAMEWORK_DEPS = [
2747
+ ["@tarojs/taro", "Taro"],
2748
+ ["@dcloudio/uni-app", "uni-app"],
2749
+ ["@mpxjs/core", "MPX"],
2750
+ ["remax", "Remax"],
2751
+ ["rax", "Rax"]
2752
+ ];
2753
+
2754
+ // src/cli/doctor.ts
2755
+ function tryReadJson(file) {
2756
+ try {
2757
+ return JSON.parse((0, import_node_fs7.readFileSync)(file, "utf8"));
2758
+ } catch {
2759
+ return void 0;
2760
+ }
2761
+ }
2762
+ function findFirstExisting(cwd, files) {
2763
+ return files.find((file) => (0, import_node_fs7.existsSync)(import_node_path13.default.join(cwd, file)));
2764
+ }
2765
+ function readProjectPackageJson(cwd) {
2766
+ return tryReadJson(import_node_path13.default.join(cwd, "package.json"));
2767
+ }
2768
+ function readDependencyVersion(cwd, packageName) {
2769
+ try {
2770
+ const requireFromCwd = (0, import_node_module3.createRequire)(import_node_path13.default.join(cwd, "package.json"));
2771
+ const packageJsonPath = requireFromCwd.resolve(`${packageName}/package.json`);
2772
+ return tryReadJson(packageJsonPath)?.version;
2773
+ } catch {
2774
+ return void 0;
2775
+ }
2776
+ }
2777
+ function collectDependencySpecs(pkg) {
2778
+ return {
2779
+ ...pkg?.dependencies ?? {},
2780
+ ...pkg?.devDependencies ?? {},
2781
+ ...pkg?.optionalDependencies ?? {},
2782
+ ...pkg?.peerDependencies ?? {}
2783
+ };
2784
+ }
2785
+ function detectPackageManager(cwd, pkg) {
2786
+ if (pkg?.packageManager) {
2787
+ return pkg.packageManager;
2788
+ }
2789
+ if ((0, import_node_fs7.existsSync)(import_node_path13.default.join(cwd, "pnpm-lock.yaml"))) {
2790
+ return "pnpm";
2791
+ }
2792
+ if ((0, import_node_fs7.existsSync)(import_node_path13.default.join(cwd, "package-lock.json"))) {
2793
+ return "npm";
2794
+ }
2795
+ if ((0, import_node_fs7.existsSync)(import_node_path13.default.join(cwd, "yarn.lock"))) {
2796
+ return "yarn";
2797
+ }
2798
+ return void 0;
2799
+ }
2800
+ function detectFrameworks(deps) {
2801
+ return FRAMEWORK_DEPS.filter(([dependency]) => dependency in deps).map(([, label]) => label);
2802
+ }
2803
+ function addCheck(checks, check) {
2804
+ checks.push(check);
2805
+ }
2806
+ function summarizeChecks(checks) {
2807
+ return checks.reduce((summary, check) => {
2808
+ summary[check.status] += 1;
2809
+ return summary;
2810
+ }, { ok: 0, warn: 0, error: 0, info: 0 });
2811
+ }
2812
+ function hasDependency(deps, packageName) {
2813
+ return packageName in deps;
2814
+ }
2815
+ function getMajorVersion(version) {
2816
+ if (!version) {
2817
+ return void 0;
2818
+ }
2819
+ return import_semver.default.parse(version)?.major;
2820
+ }
2821
+ function getDependencyMajor(deps, packageName) {
2822
+ const spec = deps[packageName];
2823
+ return spec ? import_semver.default.minVersion(spec)?.major : void 0;
2824
+ }
2825
+ function createDoctorReport(options = {}) {
2826
+ const cwd = import_node_path13.default.resolve(options.cwd ?? import_node_process13.default.cwd());
2827
+ const nodeVersion = options.nodeVersion ?? import_node_process13.default.versions.node;
2828
+ const pkg = readProjectPackageJson(cwd);
2829
+ const deps = collectDependencySpecs(pkg);
2830
+ const checks = [];
2831
+ const packageManager = detectPackageManager(cwd, pkg);
2832
+ const frameworks = detectFrameworks(deps);
2833
+ const tailwindcssVersion = readDependencyVersion(cwd, "tailwindcss");
2834
+ const weappTailwindcssVersion = readDependencyVersion(cwd, "weapp-tailwindcss");
2835
+ const tailwindMajor = getMajorVersion(tailwindcssVersion) ?? getDependencyMajor(deps, "tailwindcss");
2836
+ const tailwindConfig = findFirstExisting(cwd, CONFIG_FILES.tailwind);
2837
+ const postcssConfig = findFirstExisting(cwd, CONFIG_FILES.postcss);
2838
+ const viteConfig = findFirstExisting(cwd, CONFIG_FILES.vite);
2839
+ const webpackConfig = findFirstExisting(cwd, CONFIG_FILES.webpack);
2840
+ addCheck(checks, pkg ? {
2841
+ id: "package-json",
2842
+ title: "package.json",
2843
+ status: "ok",
2844
+ message: "\u5DF2\u627E\u5230\u9879\u76EE package.json\u3002"
2845
+ } : {
2846
+ id: "package-json",
2847
+ title: "package.json",
2848
+ status: "error",
2849
+ message: "\u5F53\u524D\u76EE\u5F55\u6CA1\u6709 package.json\u3002",
2850
+ suggestion: "\u8BF7\u5728\u9879\u76EE\u6839\u76EE\u5F55\u8FD0\u884C doctor\uFF0C\u6216\u901A\u8FC7 --cwd \u6307\u5411\u9879\u76EE\u6839\u76EE\u5F55\u3002"
2851
+ });
2852
+ addCheck(checks, import_semver.default.satisfies(nodeVersion, WEAPP_TW_REQUIRED_NODE_VERSION_RANGE) ? {
2853
+ id: "node-version",
2854
+ title: "Node.js",
2855
+ status: "ok",
2856
+ message: `\u5F53\u524D Node.js ${nodeVersion} \u6EE1\u8DB3\u7248\u672C\u8981\u6C42 ${WEAPP_TW_REQUIRED_NODE_VERSION_RANGE}\u3002`
2857
+ } : {
2858
+ id: "node-version",
2859
+ title: "Node.js",
2860
+ status: "error",
2861
+ message: `\u5F53\u524D Node.js ${nodeVersion} \u4E0D\u6EE1\u8DB3\u7248\u672C\u8981\u6C42 ${WEAPP_TW_REQUIRED_NODE_VERSION_RANGE}\u3002`,
2862
+ suggestion: "\u8BF7\u5347\u7EA7 Node.js \u540E\u518D\u5B89\u88C5\u6216\u6784\u5EFA weapp-tailwindcss \u9879\u76EE\u3002"
2863
+ });
2864
+ addCheck(checks, packageManager ? {
2865
+ id: "package-manager",
2866
+ title: "\u5305\u7BA1\u7406\u5668",
2867
+ status: packageManager.startsWith("pnpm") ? "ok" : "info",
2868
+ message: `\u68C0\u6D4B\u5230 ${packageManager}\u3002`
2869
+ } : {
2870
+ id: "package-manager",
2871
+ title: "\u5305\u7BA1\u7406\u5668",
2872
+ status: "info",
2873
+ message: "\u672A\u68C0\u6D4B\u5230 lockfile \u6216 packageManager \u5B57\u6BB5\u3002"
2874
+ });
2875
+ addCheck(checks, hasDependency(deps, "weapp-tailwindcss") || Boolean(weappTailwindcssVersion) ? {
2876
+ id: "weapp-tailwindcss",
2877
+ title: "weapp-tailwindcss",
2878
+ status: "ok",
2879
+ message: `\u68C0\u6D4B\u5230 weapp-tailwindcss${weappTailwindcssVersion ? `@${weappTailwindcssVersion}` : ""}\u3002`
2880
+ } : {
2881
+ id: "weapp-tailwindcss",
2882
+ title: "weapp-tailwindcss",
2883
+ status: "warn",
2884
+ message: "\u672A\u5728\u5F53\u524D\u9879\u76EE\u4F9D\u8D56\u4E2D\u68C0\u6D4B\u5230 weapp-tailwindcss\u3002",
2885
+ suggestion: "\u5982\u679C\u8FD9\u662F\u4E1A\u52A1\u9879\u76EE\uFF0C\u8BF7\u5B89\u88C5 weapp-tailwindcss \u5E76\u786E\u8BA4\u547D\u4EE4\u8FD0\u884C\u5728\u9879\u76EE\u6839\u76EE\u5F55\u3002"
2886
+ });
2887
+ addCheck(checks, hasDependency(deps, "tailwindcss") || Boolean(tailwindcssVersion) ? {
2888
+ id: "tailwindcss",
2889
+ title: "Tailwind CSS",
2890
+ status: "ok",
2891
+ message: `\u68C0\u6D4B\u5230 tailwindcss${tailwindcssVersion ? `@${tailwindcssVersion}` : ""}\u3002`
2892
+ } : {
2893
+ id: "tailwindcss",
2894
+ title: "Tailwind CSS",
2895
+ status: "error",
2896
+ message: "\u672A\u68C0\u6D4B\u5230 tailwindcss\u3002",
2897
+ suggestion: "\u8BF7\u5B89\u88C5 tailwindcss\uFF0C\u5E76\u786E\u8BA4\u4F9D\u8D56\u53EF\u4EE5\u4ECE\u5F53\u524D\u9879\u76EE\u89E3\u6790\u3002"
2898
+ });
2899
+ addCheck(checks, tailwindConfig ? {
2900
+ id: "tailwind-config",
2901
+ title: "Tailwind \u914D\u7F6E",
2902
+ status: "ok",
2903
+ message: `\u68C0\u6D4B\u5230 ${tailwindConfig}\u3002`
2904
+ } : {
2905
+ id: "tailwind-config",
2906
+ title: "Tailwind \u914D\u7F6E",
2907
+ status: tailwindMajor === 4 ? "info" : "warn",
2908
+ message: "\u672A\u68C0\u6D4B\u5230 tailwind.config.*\u3002",
2909
+ suggestion: tailwindMajor === 4 ? "Tailwind CSS v4 \u53EF\u4EE5\u91C7\u7528 CSS-first \u914D\u7F6E\uFF1B\u5982\u679C\u4F7F\u7528 v3 \u6216\u590D\u6742 content/source\uFF0C\u8BF7\u8865\u5145\u914D\u7F6E\u6587\u4EF6\u3002" : "\u8BF7\u786E\u8BA4 Tailwind content/source \u914D\u7F6E\u80FD\u591F\u8986\u76D6\u5C0F\u7A0B\u5E8F\u9875\u9762\u3001\u7EC4\u4EF6\u548C\u811A\u672C\u6587\u4EF6\u3002"
2910
+ });
2911
+ addCheck(checks, postcssConfig ? {
2912
+ id: "postcss-config",
2913
+ title: "PostCSS \u914D\u7F6E",
2914
+ status: "ok",
2915
+ message: `\u68C0\u6D4B\u5230 ${postcssConfig}\u3002`
2916
+ } : {
2917
+ id: "postcss-config",
2918
+ title: "PostCSS \u914D\u7F6E",
2919
+ status: viteConfig ? "info" : "warn",
2920
+ message: "\u672A\u68C0\u6D4B\u5230 postcss.config.*\u3002",
2921
+ suggestion: "\u5982\u679C\u901A\u8FC7 PostCSS \u63A5\u5165\uFF0C\u8BF7\u8865\u5145 postcss.config.*\uFF1B\u5982\u679C\u901A\u8FC7 Vite/Taro \u63D2\u4EF6\u63A5\u5165\uFF0C\u53EF\u5FFD\u7565\u6B64\u9879\u3002"
2922
+ });
2923
+ if (tailwindMajor === 4 && postcssConfig && !hasDependency(deps, "@tailwindcss/postcss")) {
2924
+ addCheck(checks, {
2925
+ id: "tailwindcss-v4-postcss",
2926
+ title: "Tailwind v4 PostCSS",
2927
+ status: "warn",
2928
+ message: "Tailwind CSS v4 \u9879\u76EE\u5B58\u5728 PostCSS \u914D\u7F6E\uFF0C\u4F46\u672A\u68C0\u6D4B\u5230 @tailwindcss/postcss\u3002",
2929
+ suggestion: "\u5982\u679C PostCSS \u914D\u7F6E\u4E2D\u4ECD\u76F4\u63A5\u4F7F\u7528 tailwindcss\uFF0C\u8BF7\u8FC1\u79FB\u5230 @tailwindcss/postcss\u3002"
2930
+ });
2931
+ }
2932
+ addCheck(checks, frameworks.length > 0 ? {
2933
+ id: "framework",
2934
+ title: "\u6846\u67B6\u8BC6\u522B",
2935
+ status: "ok",
2936
+ message: `\u68C0\u6D4B\u5230 ${frameworks.join(", ")}\u3002`
2937
+ } : {
2938
+ id: "framework",
2939
+ title: "\u6846\u67B6\u8BC6\u522B",
2940
+ status: "info",
2941
+ message: "\u672A\u4ECE\u4F9D\u8D56\u4E2D\u8BC6\u522B\u51FA Taro\u3001uni-app\u3001MPX\u3001Remax \u6216 Rax\u3002"
2942
+ });
2943
+ addCheck(checks, viteConfig || webpackConfig ? {
2944
+ id: "bundler-config",
2945
+ title: "\u6784\u5EFA\u5668\u914D\u7F6E",
2946
+ status: "ok",
2947
+ message: `\u68C0\u6D4B\u5230 ${[viteConfig, webpackConfig].filter(Boolean).join(", ")}\u3002`
2948
+ } : {
2949
+ id: "bundler-config",
2950
+ title: "\u6784\u5EFA\u5668\u914D\u7F6E",
2951
+ status: "info",
2952
+ message: "\u672A\u68C0\u6D4B\u5230 vite.config.* \u6216 webpack.config.*\u3002"
2953
+ });
2954
+ return {
2955
+ cwd,
2956
+ nodeVersion,
2957
+ detected: {
2958
+ packageManager,
2959
+ frameworks,
2960
+ tailwindcssVersion,
2961
+ weappTailwindcssVersion
2962
+ },
2963
+ summary: summarizeChecks(checks),
2964
+ checks
2965
+ };
2966
+ }
2967
+ function hasDoctorFailure(report, strict = false) {
2968
+ return report.summary.error > 0 || strict && report.summary.warn > 0;
2969
+ }
2970
+ function formatDoctorReport(report) {
2971
+ const lines = [
2972
+ `weapp-tailwindcss doctor`,
2973
+ `cwd: ${report.cwd}`,
2974
+ `summary: ${report.summary.error} error, ${report.summary.warn} warn, ${report.summary.ok} ok, ${report.summary.info} info`,
2975
+ ""
2976
+ ];
2977
+ for (const check of report.checks) {
2978
+ lines.push(`[${check.status}] ${check.title}: ${check.message}`);
2979
+ if (check.suggestion) {
2980
+ lines.push(` -> ${check.suggestion}`);
2981
+ }
2982
+ }
2983
+ return lines.join("\n");
2984
+ }
2985
+
925
2986
  // src/cli/helpers.ts
926
2987
  var import_promises3 = require("fs/promises");
927
- var import_node_process15 = __toESM(require("process"));
2988
+ var import_node_process16 = __toESM(require("process"));
928
2989
 
929
2990
  // src/logger/index.ts
930
2991
  var import_logger13 = require("@weapp-tailwindcss/logger");
@@ -982,19 +3043,19 @@ function toBoolean(value, fallback) {
982
3043
  }
983
3044
 
984
3045
  // src/cli/helpers/options/resolve.ts
985
- var import_node_path13 = __toESM(require("path"));
986
- var import_node_process13 = __toESM(require("process"));
3046
+ var import_node_path14 = __toESM(require("path"));
3047
+ var import_node_process14 = __toESM(require("process"));
987
3048
  function resolveCliCwd(value) {
988
3049
  const raw = readStringOption("cwd", value);
989
3050
  if (!raw) {
990
3051
  return void 0;
991
3052
  }
992
- return import_node_path13.default.isAbsolute(raw) ? import_node_path13.default.normalize(raw) : import_node_path13.default.resolve(import_node_process13.default.cwd(), raw);
3053
+ return import_node_path14.default.isAbsolute(raw) ? import_node_path14.default.normalize(raw) : import_node_path14.default.resolve(import_node_process14.default.cwd(), raw);
993
3054
  }
994
3055
 
995
3056
  // src/cli/helpers/patch-cwd.ts
996
- var import_node_path14 = __toESM(require("path"));
997
- var import_node_process14 = __toESM(require("process"));
3057
+ var import_node_path15 = __toESM(require("path"));
3058
+ var import_node_process15 = __toESM(require("process"));
998
3059
 
999
3060
  // src/tailwindcss/index.ts
1000
3061
  var import_local_pkg = require("local-pkg");
@@ -1007,7 +3068,7 @@ function normalizeCandidatePath(baseDir, candidate) {
1007
3068
  if (!candidate) {
1008
3069
  return void 0;
1009
3070
  }
1010
- return import_node_path14.default.isAbsolute(candidate) ? import_node_path14.default.normalize(candidate) : import_node_path14.default.resolve(baseDir, candidate);
3071
+ return import_node_path15.default.isAbsolute(candidate) ? import_node_path15.default.normalize(candidate) : import_node_path15.default.resolve(baseDir, candidate);
1011
3072
  }
1012
3073
  function detectTailwindWorkspace(paths) {
1013
3074
  for (const candidate of paths) {
@@ -1021,15 +3082,15 @@ function detectTailwindWorkspace(paths) {
1021
3082
  }
1022
3083
  return void 0;
1023
3084
  }
1024
- function resolvePatchDefaultCwd(currentCwd = import_node_process14.default.cwd()) {
1025
- const baseDir = import_node_path14.default.normalize(currentCwd);
1026
- const explicitCwd = normalizeCandidatePath(baseDir, import_node_process14.default.env.WEAPP_TW_PATCH_CWD);
3085
+ function resolvePatchDefaultCwd(currentCwd = import_node_process15.default.cwd()) {
3086
+ const baseDir = import_node_path15.default.normalize(currentCwd);
3087
+ const explicitCwd = normalizeCandidatePath(baseDir, import_node_process15.default.env.WEAPP_TW_PATCH_CWD);
1027
3088
  if (explicitCwd) {
1028
3089
  return explicitCwd;
1029
3090
  }
1030
3091
  const workspaceRoot = findWorkspaceRoot(baseDir);
1031
- const initCwd = normalizeCandidatePath(baseDir, import_node_process14.default.env.INIT_CWD);
1032
- const localPrefix = normalizeCandidatePath(baseDir, import_node_process14.default.env.npm_config_local_prefix);
3092
+ const initCwd = normalizeCandidatePath(baseDir, import_node_process15.default.env.INIT_CWD);
3093
+ const localPrefix = normalizeCandidatePath(baseDir, import_node_process15.default.env.npm_config_local_prefix);
1033
3094
  const candidates = [
1034
3095
  baseDir,
1035
3096
  workspaceRoot,
@@ -1050,7 +3111,7 @@ async function ensureDir(dir) {
1050
3111
  function handleCliError(error) {
1051
3112
  if (error instanceof Error) {
1052
3113
  import_logger13.logger.error(error.message);
1053
- if (error.stack && import_node_process15.default.env.WEAPP_TW_DEBUG === "1") {
3114
+ if (error.stack && import_node_process16.default.env.WEAPP_TW_DEBUG === "1") {
1054
3115
  import_logger13.logger.error(error.stack);
1055
3116
  }
1056
3117
  } else {
@@ -1063,13 +3124,13 @@ function commandAction(handler) {
1063
3124
  await handler(...args);
1064
3125
  } catch (error) {
1065
3126
  handleCliError(error);
1066
- import_node_process15.default.exitCode = 1;
3127
+ import_node_process16.default.exitCode = 1;
1067
3128
  }
1068
3129
  };
1069
3130
  }
1070
3131
 
1071
3132
  // src/cli/mount-options.ts
1072
- var import_node_process17 = __toESM(require("process"));
3133
+ var import_node_process18 = __toESM(require("process"));
1073
3134
 
1074
3135
  // src/cli/mount-options/patch-status.ts
1075
3136
  function formatStatusFilesHint(files) {
@@ -1144,24 +3205,24 @@ function buildExtendLengthUnitsOverride(options) {
1144
3205
  }
1145
3206
 
1146
3207
  // src/cli/workspace.ts
1147
- var import_node_path19 = __toESM(require("path"));
1148
- var import_node_process16 = __toESM(require("process"));
3208
+ var import_node_path20 = __toESM(require("path"));
3209
+ var import_node_process17 = __toESM(require("process"));
1149
3210
 
1150
3211
  // src/cli/workspace/package-dirs.ts
1151
- var import_node_fs10 = require("fs");
1152
- var import_node_path17 = __toESM(require("path"));
3212
+ var import_node_fs11 = require("fs");
3213
+ var import_node_path18 = __toESM(require("path"));
1153
3214
  var import_fast_glob = __toESM(require("fast-glob"));
1154
3215
 
1155
3216
  // src/cli/workspace/workspace-globs.ts
1156
- var import_node_fs8 = require("fs");
1157
- var import_node_path15 = __toESM(require("path"));
3217
+ var import_node_fs9 = require("fs");
3218
+ var import_node_path16 = __toESM(require("path"));
1158
3219
  var import_yaml = require("yaml");
1159
3220
 
1160
3221
  // src/cli/workspace/workspace-io.ts
1161
- var import_node_fs7 = require("fs");
1162
- function tryReadJson(file) {
3222
+ var import_node_fs8 = require("fs");
3223
+ function tryReadJson2(file) {
1163
3224
  try {
1164
- const content = (0, import_node_fs7.readFileSync)(file, "utf8");
3225
+ const content = (0, import_node_fs8.readFileSync)(file, "utf8");
1165
3226
  return JSON.parse(content);
1166
3227
  } catch {
1167
3228
  return void 0;
@@ -1170,8 +3231,8 @@ function tryReadJson(file) {
1170
3231
 
1171
3232
  // src/cli/workspace/workspace-globs.ts
1172
3233
  function parseWorkspaceGlobsFromPackageJson(workspaceRoot) {
1173
- const pkgJsonPath = import_node_path15.default.join(workspaceRoot, "package.json");
1174
- const pkg = tryReadJson(pkgJsonPath);
3234
+ const pkgJsonPath = import_node_path16.default.join(workspaceRoot, "package.json");
3235
+ const pkg = tryReadJson2(pkgJsonPath);
1175
3236
  if (!pkg?.workspaces) {
1176
3237
  return [];
1177
3238
  }
@@ -1184,12 +3245,12 @@ function parseWorkspaceGlobsFromPackageJson(workspaceRoot) {
1184
3245
  return [];
1185
3246
  }
1186
3247
  function parseWorkspaceGlobsFromWorkspaceFile(workspaceRoot) {
1187
- const workspaceFile = import_node_path15.default.join(workspaceRoot, "pnpm-workspace.yaml");
1188
- if (!(0, import_node_fs8.existsSync)(workspaceFile)) {
3248
+ const workspaceFile = import_node_path16.default.join(workspaceRoot, "pnpm-workspace.yaml");
3249
+ if (!(0, import_node_fs9.existsSync)(workspaceFile)) {
1189
3250
  return [];
1190
3251
  }
1191
3252
  try {
1192
- const parsed = (0, import_yaml.parse)((0, import_node_fs8.readFileSync)(workspaceFile, "utf8"));
3253
+ const parsed = (0, import_yaml.parse)((0, import_node_fs9.readFileSync)(workspaceFile, "utf8"));
1193
3254
  return Array.isArray(parsed?.packages) ? parsed.packages.filter(Boolean) : [];
1194
3255
  } catch {
1195
3256
  return [];
@@ -1197,16 +3258,16 @@ function parseWorkspaceGlobsFromWorkspaceFile(workspaceRoot) {
1197
3258
  }
1198
3259
 
1199
3260
  // src/cli/workspace/workspace-lock.ts
1200
- var import_node_fs9 = require("fs");
1201
- var import_node_path16 = __toESM(require("path"));
3261
+ var import_node_fs10 = require("fs");
3262
+ var import_node_path17 = __toESM(require("path"));
1202
3263
  var import_yaml2 = require("yaml");
1203
3264
  function parseImportersFromLock(workspaceRoot) {
1204
- const lockPath = import_node_path16.default.join(workspaceRoot, "pnpm-lock.yaml");
1205
- if (!(0, import_node_fs9.existsSync)(lockPath)) {
3265
+ const lockPath = import_node_path17.default.join(workspaceRoot, "pnpm-lock.yaml");
3266
+ if (!(0, import_node_fs10.existsSync)(lockPath)) {
1206
3267
  return [];
1207
3268
  }
1208
3269
  try {
1209
- const parsed = (0, import_yaml2.parse)((0, import_node_fs9.readFileSync)(lockPath, "utf8"));
3270
+ const parsed = (0, import_yaml2.parse)((0, import_node_fs10.readFileSync)(lockPath, "utf8"));
1210
3271
  const importers = parsed?.importers;
1211
3272
  if (!importers) {
1212
3273
  return [];
@@ -1215,7 +3276,7 @@ function parseImportersFromLock(workspaceRoot) {
1215
3276
  if (!key || key === ".") {
1216
3277
  return workspaceRoot;
1217
3278
  }
1218
- return import_node_path16.default.join(workspaceRoot, key);
3279
+ return import_node_path17.default.join(workspaceRoot, key);
1219
3280
  });
1220
3281
  } catch {
1221
3282
  return [];
@@ -1228,7 +3289,7 @@ var TRAILING_SLASH_RE = /\/+$/;
1228
3289
  async function resolveWorkspacePackageDirs(workspaceRoot) {
1229
3290
  const dirs = /* @__PURE__ */ new Set();
1230
3291
  for (const importerDir of parseImportersFromLock(workspaceRoot)) {
1231
- dirs.add(import_node_path17.default.normalize(importerDir));
3292
+ dirs.add(import_node_path18.default.normalize(importerDir));
1232
3293
  }
1233
3294
  if (!dirs.size) {
1234
3295
  let globs = parseWorkspaceGlobsFromWorkspaceFile(workspaceRoot);
@@ -1248,13 +3309,13 @@ async function resolveWorkspacePackageDirs(workspaceRoot) {
1248
3309
  ignore: ["**/node_modules/**", "**/.git/**"]
1249
3310
  });
1250
3311
  for (const file of packageJsonFiles) {
1251
- dirs.add(import_node_path17.default.normalize(import_node_path17.default.dirname(file)));
3312
+ dirs.add(import_node_path18.default.normalize(import_node_path18.default.dirname(file)));
1252
3313
  }
1253
3314
  }
1254
3315
  }
1255
- const rootPkg = import_node_path17.default.join(workspaceRoot, "package.json");
1256
- if ((0, import_node_fs10.existsSync)(rootPkg)) {
1257
- dirs.add(import_node_path17.default.normalize(workspaceRoot));
3316
+ const rootPkg = import_node_path18.default.join(workspaceRoot, "package.json");
3317
+ if ((0, import_node_fs11.existsSync)(rootPkg)) {
3318
+ dirs.add(import_node_path18.default.normalize(workspaceRoot));
1258
3319
  }
1259
3320
  return [...dirs];
1260
3321
  }
@@ -1263,9 +3324,9 @@ async function resolveWorkspacePackageDirs(workspaceRoot) {
1263
3324
  var import_tailwindcss_patch2 = require("tailwindcss-patch");
1264
3325
 
1265
3326
  // src/cli/workspace/patch-utils.ts
1266
- var import_node_path18 = __toESM(require("path"));
3327
+ var import_node_path19 = __toESM(require("path"));
1267
3328
  function formatDisplayName(workspaceRoot, dir, name) {
1268
- const relative = import_node_path18.default.relative(workspaceRoot, dir) || ".";
3329
+ const relative = import_node_path19.default.relative(workspaceRoot, dir) || ".";
1269
3330
  return name ? `${name} (${relative})` : relative;
1270
3331
  }
1271
3332
  function summarizeWorkspaceResults(results) {
@@ -1338,7 +3399,7 @@ async function patchWorkspacePackage(workspaceRoot, dir, pkgName, options) {
1338
3399
 
1339
3400
  // src/cli/workspace.ts
1340
3401
  async function patchWorkspace(options) {
1341
- const cwd = options.cwd ?? import_node_process16.default.cwd();
3402
+ const cwd = options.cwd ?? import_node_process17.default.cwd();
1342
3403
  const workspaceRoot = findWorkspaceRoot(cwd) ?? cwd;
1343
3404
  const packageDirs = await resolveWorkspacePackageDirs(workspaceRoot);
1344
3405
  if (packageDirs.length === 0) {
@@ -1347,8 +3408,8 @@ async function patchWorkspace(options) {
1347
3408
  }
1348
3409
  const results = [];
1349
3410
  for (const dir of packageDirs) {
1350
- const pkgJsonPath = import_node_path19.default.join(dir, "package.json");
1351
- const pkgJson = tryReadJson(pkgJsonPath);
3411
+ const pkgJsonPath = import_node_path20.default.join(dir, "package.json");
3412
+ const pkgJson = tryReadJson2(pkgJsonPath);
1352
3413
  results.push(await patchWorkspacePackage(workspaceRoot, dir, pkgJson?.name, options));
1353
3414
  }
1354
3415
  summarizeWorkspaceResults(results);
@@ -1358,7 +3419,7 @@ async function patchWorkspace(options) {
1358
3419
  function handleCliError2(error) {
1359
3420
  if (error instanceof Error) {
1360
3421
  import_logger13.logger.error(error.message);
1361
- if (error.stack && import_node_process17.default.env.WEAPP_TW_DEBUG === "1") {
3422
+ if (error.stack && import_node_process18.default.env.WEAPP_TW_DEBUG === "1") {
1362
3423
  import_logger13.logger.error(error.stack);
1363
3424
  }
1364
3425
  } else {
@@ -1371,7 +3432,7 @@ function withCommandErrorHandling(handler) {
1371
3432
  return await handler(ctx, next);
1372
3433
  } catch (error) {
1373
3434
  handleCliError2(error);
1374
- import_node_process17.default.exitCode = 1;
3435
+ import_node_process18.default.exitCode = 1;
1375
3436
  return void 0;
1376
3437
  }
1377
3438
  });
@@ -1479,9 +3540,9 @@ var mountOptions = {
1479
3540
  };
1480
3541
 
1481
3542
  // src/cli/vscode-entry.ts
1482
- var import_node_fs11 = require("fs");
3543
+ var import_node_fs12 = require("fs");
1483
3544
  var import_promises4 = require("fs/promises");
1484
- var import_node_path20 = __toESM(require("path"));
3545
+ var import_node_path21 = __toESM(require("path"));
1485
3546
  var DEFAULT_VSCODE_ENTRY_OUTPUT = ".vscode/weapp-tailwindcss.intellisense.css";
1486
3547
  var DEFAULT_VSCODE_SOURCES = [
1487
3548
  'not "./dist"',
@@ -1498,7 +3559,7 @@ function toPosixPath(filepath) {
1498
3559
  }
1499
3560
  async function assertFileExists(filepath) {
1500
3561
  try {
1501
- await (0, import_promises4.access)(filepath, import_node_fs11.constants.F_OK);
3562
+ await (0, import_promises4.access)(filepath, import_node_fs12.constants.F_OK);
1502
3563
  } catch (error) {
1503
3564
  const err = error;
1504
3565
  if (err?.code === "ENOENT") {
@@ -1509,7 +3570,7 @@ async function assertFileExists(filepath) {
1509
3570
  }
1510
3571
  async function assertCanWrite(filepath, force) {
1511
3572
  try {
1512
- await (0, import_promises4.access)(filepath, import_node_fs11.constants.F_OK);
3573
+ await (0, import_promises4.access)(filepath, import_node_fs12.constants.F_OK);
1513
3574
  if (!force) {
1514
3575
  throw new Error(
1515
3576
  `VS Code helper already exists at ${filepath}. Re-run with --force to overwrite it.`
@@ -1554,16 +3615,16 @@ function formatSource(pattern) {
1554
3615
  }
1555
3616
  function resolveOutputPath(baseDir, output) {
1556
3617
  const target = output ?? DEFAULT_VSCODE_ENTRY_OUTPUT;
1557
- return import_node_path20.default.isAbsolute(target) ? import_node_path20.default.normalize(target) : import_node_path20.default.resolve(baseDir, target);
3618
+ return import_node_path21.default.isAbsolute(target) ? import_node_path21.default.normalize(target) : import_node_path21.default.resolve(baseDir, target);
1558
3619
  }
1559
3620
  function resolveCssEntry(baseDir, entry) {
1560
- return import_node_path20.default.isAbsolute(entry) ? import_node_path20.default.normalize(entry) : import_node_path20.default.resolve(baseDir, entry);
3621
+ return import_node_path21.default.isAbsolute(entry) ? import_node_path21.default.normalize(entry) : import_node_path21.default.resolve(baseDir, entry);
1561
3622
  }
1562
3623
  function toRelativeImport(fromFile, targetFile) {
1563
- const fromDir = import_node_path20.default.dirname(fromFile);
1564
- let relative = import_node_path20.default.relative(fromDir, targetFile);
3624
+ const fromDir = import_node_path21.default.dirname(fromFile);
3625
+ let relative = import_node_path21.default.relative(fromDir, targetFile);
1565
3626
  if (!relative) {
1566
- relative = import_node_path20.default.basename(targetFile);
3627
+ relative = import_node_path21.default.basename(targetFile);
1567
3628
  }
1568
3629
  if (!relative.startsWith(".")) {
1569
3630
  relative = `./${relative}`;
@@ -1575,7 +3636,7 @@ async function generateVscodeIntellisenseEntry(options) {
1575
3636
  const cssEntryPath = resolveCssEntry(baseDir, options.cssEntry);
1576
3637
  await assertFileExists(cssEntryPath);
1577
3638
  const outputPath = resolveOutputPath(baseDir, options.output);
1578
- await ensureDir(import_node_path20.default.dirname(outputPath));
3639
+ await ensureDir(import_node_path21.default.dirname(outputPath));
1579
3640
  await assertCanWrite(outputPath, options.force);
1580
3641
  const sources = options.sources && options.sources.length > 0 ? options.sources : DEFAULT_VSCODE_SOURCES;
1581
3642
  const formattedSources = sources.map(formatSource).filter((statement) => Boolean(statement));
@@ -1600,10 +3661,10 @@ async function generateVscodeIntellisenseEntry(options) {
1600
3661
  }
1601
3662
 
1602
3663
  // src/cli.ts
1603
- import_node_process18.default.title = "node (weapp-tailwindcss)";
1604
- if (import_semver.default.lt(import_node_process18.default.versions.node, WEAPP_TW_REQUIRED_NODE_VERSION)) {
3664
+ import_node_process19.default.title = "node (weapp-tailwindcss)";
3665
+ if (!import_semver2.default.satisfies(import_node_process19.default.versions.node, WEAPP_TW_REQUIRED_NODE_VERSION_RANGE)) {
1605
3666
  import_logger13.logger.warn(
1606
- `You are using Node.js ${import_node_process18.default.versions.node}. For weapp-tailwindcss, Node.js version >= v${WEAPP_TW_REQUIRED_NODE_VERSION} is required.`
3667
+ `You are using Node.js ${import_node_process19.default.versions.node}. For weapp-tailwindcss, Node.js version ${WEAPP_TW_REQUIRED_NODE_VERSION_RANGE} is required.`
1607
3668
  );
1608
3669
  }
1609
3670
  var cli = (0, import_tailwindcss_patch3.createTailwindcssPatchCli)({
@@ -1613,7 +3674,7 @@ var cli = (0, import_tailwindcss_patch3.createTailwindcssPatchCli)({
1613
3674
  cli.command("vscode-entry", "Generate a VS Code helper CSS for Tailwind IntelliSense").option("--cwd <dir>", "Working directory").option("--css <file>", "Path to the CSS file that imports weapp-tailwindcss (required)").option("--output <file>", `Helper output path. Defaults to ${DEFAULT_VSCODE_ENTRY_OUTPUT}`).option("--source <pattern>", "Additional @source glob (can be repeated)").option("--force", "Overwrite the helper file when it already exists").action(
1614
3675
  commandAction(async (options) => {
1615
3676
  const resolvedCwd = resolveCliCwd(options.cwd);
1616
- const baseDir = resolvedCwd ?? import_node_process18.default.cwd();
3677
+ const baseDir = resolvedCwd ?? import_node_process19.default.cwd();
1617
3678
  const cssEntry = readStringOption("css", options.css);
1618
3679
  if (!cssEntry) {
1619
3680
  throw new Error('Option "--css" is required.');
@@ -1633,6 +3694,20 @@ cli.command("vscode-entry", "Generate a VS Code helper CSS for Tailwind IntelliS
1633
3694
  );
1634
3695
  })
1635
3696
  );
3697
+ cli.command("doctor", "Check project setup for weapp-tailwindcss").option("--cwd <dir>", "Working directory").option("--json", "Print a JSON report").option("--strict", "Exit with code 1 when warnings are found").action(
3698
+ commandAction(async (options) => {
3699
+ const resolvedCwd = resolveCliCwd(options.cwd);
3700
+ const report = createDoctorReport({ cwd: resolvedCwd });
3701
+ if (toBoolean(options.json, false)) {
3702
+ import_logger13.logger.log(JSON.stringify(report, null, 2));
3703
+ } else {
3704
+ import_logger13.logger.log(formatDoctorReport(report));
3705
+ }
3706
+ if (hasDoctorFailure(report, toBoolean(options.strict, false))) {
3707
+ import_node_process19.default.exitCode = 1;
3708
+ }
3709
+ })
3710
+ );
1636
3711
  cli.help();
1637
- cli.version(import_node_process18.default.env.npm_package_version ?? "0.0.0");
3712
+ cli.version(import_node_process19.default.env.npm_package_version ?? "0.0.0");
1638
3713
  cli.parse();