weapp-tailwindcss 4.11.0-alpha.0 → 4.11.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/dist/{chunk-35EI5JMK.mjs → chunk-23K4XDKF.mjs} +3 -1
  2. package/dist/{chunk-FV4ZRTAK.js → chunk-2W24MRCQ.js} +10 -12
  3. package/dist/chunk-4AFQP74Z.js +24 -0
  4. package/dist/{chunk-7XQXBJL6.js → chunk-4TTPYMVM.js} +12 -8
  5. package/dist/{chunk-RXNSOSCT.js → chunk-5KSBT6GU.js} +448 -270
  6. package/dist/{chunk-QX2A7SBB.mjs → chunk-66E76FQE.mjs} +666 -102
  7. package/dist/{chunk-WGFNCK5B.js → chunk-6O7HJU2F.js} +123 -42
  8. package/dist/{chunk-RRHPTTCP.mjs → chunk-76S2EME4.mjs} +2 -0
  9. package/dist/{chunk-G3G437UE.js → chunk-7LKMJZD2.js} +2 -2
  10. package/dist/{chunk-OV7FX6XR.js → chunk-CRDOWYG4.js} +1 -1
  11. package/dist/{chunk-DOH7FULQ.mjs → chunk-EFBQ4SQR.mjs} +1 -1
  12. package/dist/{chunk-XGUD52TA.mjs → chunk-EW2K6CO5.mjs} +413 -235
  13. package/dist/{chunk-FMWKBZWX.mjs → chunk-HADJCWHU.mjs} +291 -265
  14. package/dist/{chunk-FKUPQQYX.js → chunk-K7CZXT46.js} +692 -125
  15. package/dist/{chunk-ACTJYB33.js → chunk-LL3QUKJI.js} +3 -1
  16. package/dist/{chunk-I4EOMKX2.js → chunk-LYGLQCWI.js} +356 -330
  17. package/dist/{chunk-LTJQUORK.js → chunk-OF6MFURR.js} +2 -0
  18. package/dist/{chunk-W3JO6LBC.mjs → chunk-RED7Y22U.mjs} +91 -10
  19. package/dist/{chunk-CLNUBO3Q.mjs → chunk-SJ3SG6DU.mjs} +5 -1
  20. package/dist/{chunk-OIDFSOER.mjs → chunk-UCUAXK7F.mjs} +4 -6
  21. package/dist/cli.js +1006 -147
  22. package/dist/cli.mjs +942 -107
  23. package/dist/core.d.mts +2 -2
  24. package/dist/core.d.ts +2 -2
  25. package/dist/core.js +9 -11
  26. package/dist/core.mjs +6 -8
  27. package/dist/css-macro/postcss.js +1 -1
  28. package/dist/css-macro/postcss.mjs +1 -1
  29. package/dist/css-macro.js +3 -3
  30. package/dist/css-macro.mjs +4 -4
  31. package/dist/defaults.d.mts +2 -2
  32. package/dist/defaults.d.ts +2 -2
  33. package/dist/defaults.js +3 -3
  34. package/dist/defaults.mjs +2 -2
  35. package/dist/gulp.d.mts +2 -2
  36. package/dist/gulp.d.ts +2 -2
  37. package/dist/gulp.js +7 -8
  38. package/dist/gulp.mjs +6 -7
  39. package/dist/{index-t_VBjwYm.d.ts → index-BMwzhITq.d.mts} +6 -6
  40. package/dist/{index-t_VBjwYm.d.mts → index-BMwzhITq.d.ts} +6 -6
  41. package/dist/index.d.mts +2 -2
  42. package/dist/index.d.ts +2 -2
  43. package/dist/index.js +11 -12
  44. package/dist/index.mjs +9 -10
  45. package/dist/postcss-html-transform.js +1 -1
  46. package/dist/postcss-html-transform.mjs +1 -1
  47. package/dist/presets.d.mts +2 -2
  48. package/dist/presets.d.ts +2 -2
  49. package/dist/presets.js +5 -5
  50. package/dist/presets.mjs +2 -2
  51. package/dist/reset.js +1 -1
  52. package/dist/reset.mjs +1 -1
  53. package/dist/types.d.mts +4 -4
  54. package/dist/types.d.ts +4 -4
  55. package/dist/types.js +1 -1
  56. package/dist/types.mjs +1 -1
  57. package/dist/vite.d.mts +2 -2
  58. package/dist/vite.d.ts +2 -2
  59. package/dist/vite.js +8 -9
  60. package/dist/vite.mjs +6 -7
  61. package/dist/weapp-tw-css-import-rewrite-loader.js +3 -1
  62. package/dist/weapp-tw-runtime-classset-loader.js +29 -2
  63. package/dist/webpack.d.mts +2 -2
  64. package/dist/webpack.d.ts +2 -2
  65. package/dist/webpack.js +9 -10
  66. package/dist/webpack.mjs +7 -8
  67. package/dist/webpack4.d.mts +2 -2
  68. package/dist/webpack4.d.ts +2 -2
  69. package/dist/webpack4.js +41 -41
  70. package/dist/webpack4.mjs +12 -12
  71. package/package.json +9 -9
  72. package/dist/chunk-EOK3NZVC.mjs +0 -29
  73. package/dist/chunk-PXZUQ7RR.js +0 -29
@@ -9,10 +9,7 @@ import {
9
9
  } from "./chunk-F2CKKG6Q.mjs";
10
10
  import {
11
11
  processCachedTask
12
- } from "./chunk-RRHPTTCP.mjs";
13
- import {
14
- setupPatchRecorder
15
- } from "./chunk-EOK3NZVC.mjs";
12
+ } from "./chunk-76S2EME4.mjs";
16
13
  import {
17
14
  babelParse,
18
15
  collectRuntimeClassSet,
@@ -20,20 +17,27 @@ import {
20
17
  createDebug,
21
18
  generateCode,
22
19
  getCompilerContext,
23
- getRuntimeClassSetSignature,
24
20
  refreshTailwindRuntimeState,
25
21
  replaceWxml,
22
+ setupPatchRecorder,
26
23
  toCustomAttributesEntities,
27
24
  traverse,
28
25
  vitePluginName
29
- } from "./chunk-FMWKBZWX.mjs";
26
+ } from "./chunk-HADJCWHU.mjs";
27
+ import {
28
+ findNearestPackageRoot,
29
+ findTailwindConfig,
30
+ getRuntimeClassSetSignature,
31
+ resolveTailwindcssOptions
32
+ } from "./chunk-EW2K6CO5.mjs";
30
33
  import {
31
34
  resolveUniUtsPlatform
32
35
  } from "./chunk-OOHJLO5M.mjs";
33
36
 
34
37
  // src/bundlers/vite/index.ts
35
- import path3 from "path";
36
- import process3 from "process";
38
+ import { existsSync } from "fs";
39
+ import path4 from "path";
40
+ import process4 from "process";
37
41
  import postcssHtmlTransform from "@weapp-tailwindcss/postcss/html-transform";
38
42
 
39
43
  // src/uni-app-x/transform.ts
@@ -369,7 +373,7 @@ function createUniAppXAssetTask(file, originalSource, outDir, options) {
369
373
  cache,
370
374
  hashKey,
371
375
  createHandlerOptions,
372
- debug: debug2,
376
+ debug: debug3,
373
377
  jsHandler,
374
378
  onUpdate,
375
379
  runtimeSet,
@@ -388,7 +392,7 @@ function createUniAppXAssetTask(file, originalSource, outDir, options) {
388
392
  originalSource.source = source;
389
393
  },
390
394
  onCacheHit() {
391
- debug2("js cache hit: %s", file);
395
+ debug3("js cache hit: %s", file);
392
396
  },
393
397
  async transform() {
394
398
  const currentSource = originalSource.source.toString();
@@ -402,7 +406,7 @@ function createUniAppXAssetTask(file, originalSource, outDir, options) {
402
406
  }
403
407
  }));
404
408
  onUpdate(file, currentSource, code);
405
- debug2("js handle: %s", file);
409
+ debug3("js handle: %s", file);
406
410
  applyLinkedResults2(linked);
407
411
  return {
408
412
  result: code
@@ -415,6 +419,8 @@ function createUniAppXAssetTask(file, originalSource, outDir, options) {
415
419
  // src/bundlers/vite/generate-bundle.ts
416
420
  import path2 from "path";
417
421
  import process2 from "process";
422
+ import { logger } from "@weapp-tailwindcss/logger";
423
+ import { splitCode } from "@weapp-tailwindcss/shared/extractors";
418
424
 
419
425
  // src/bundlers/vite/bundle-entries.ts
420
426
  import { Buffer } from "buffer";
@@ -486,6 +492,10 @@ function applyLinkedResults(linked, entries, onLinkedUpdate, onApplied) {
486
492
 
487
493
  // src/bundlers/vite/runtime-affecting-signature.ts
488
494
  import { Parser } from "htmlparser2";
495
+ var CSS_BLOCK_COMMENT_RE = /\/\*[\s\S]*?\*\//g;
496
+ var CSS_AROUND_PUNCTUATION_RE = /\s*([{}:;,>+~()])\s*/g;
497
+ var CSS_TRAILING_DECLARATION_SEMICOLON_RE = /;\}/g;
498
+ var CSS_WHITESPACE_RE = /\s+/g;
489
499
  function createHtmlRuntimeAffectingSignature(source) {
490
500
  try {
491
501
  const parts = [];
@@ -526,14 +536,14 @@ function createJsRuntimeAffectingSignature(source) {
526
536
  const parts = [];
527
537
  traverse(ast, {
528
538
  noScope: true,
529
- StringLiteral(path4) {
530
- parts.push(`s:${path4.node.value}`);
539
+ StringLiteral(path5) {
540
+ parts.push(`s:${path5.node.value}`);
531
541
  },
532
- TemplateElement(path4) {
533
- parts.push(`t:${path4.node.value.raw}`);
542
+ TemplateElement(path5) {
543
+ parts.push(`t:${path5.node.value.raw}`);
534
544
  },
535
- JSXText(path4) {
536
- const value = path4.node.value.trim();
545
+ JSXText(path5) {
546
+ const value = path5.node.value.trim();
537
547
  if (value.length > 0) {
538
548
  parts.push(`x:${value}`);
539
549
  }
@@ -552,6 +562,9 @@ function createJsRuntimeAffectingSignature(source) {
552
562
  return source;
553
563
  }
554
564
  }
565
+ function createCssRuntimeAffectingSignature(source) {
566
+ return source.replace(CSS_BLOCK_COMMENT_RE, "").replace(CSS_AROUND_PUNCTUATION_RE, "$1").replace(CSS_TRAILING_DECLARATION_SEMICOLON_RE, "}").replace(CSS_WHITESPACE_RE, " ").trim();
567
+ }
555
568
  function createRuntimeAffectingSourceSignature(source, type) {
556
569
  if (type === "html") {
557
570
  return createHtmlRuntimeAffectingSignature(source);
@@ -559,6 +572,9 @@ function createRuntimeAffectingSourceSignature(source, type) {
559
572
  if (type === "js") {
560
573
  return createJsRuntimeAffectingSignature(source);
561
574
  }
575
+ if (type === "css") {
576
+ return createCssRuntimeAffectingSignature(source);
577
+ }
562
578
  return source;
563
579
  }
564
580
 
@@ -620,6 +636,7 @@ function markProcessFile(type, file, processFiles) {
620
636
  }
621
637
  function buildBundleSnapshot(bundle, opts, outDir, state, forceAll = false) {
622
638
  const sourceHashByFile = /* @__PURE__ */ new Map();
639
+ const runtimeAffectingSignatureByFile = /* @__PURE__ */ new Map();
623
640
  const runtimeAffectingHashByFile = /* @__PURE__ */ new Map();
624
641
  const changedByType = createChangedByType();
625
642
  const runtimeAffectingChangedByType = createChangedByType();
@@ -634,6 +651,7 @@ function buildBundleSnapshot(bundle, opts, outDir, state, forceAll = false) {
634
651
  const hash = opts.cache.computeHash(source);
635
652
  sourceHashByFile.set(file, hash);
636
653
  const runtimeAffectingSignature = createRuntimeAffectingSourceSignature(source, type);
654
+ runtimeAffectingSignatureByFile.set(file, runtimeAffectingSignature);
637
655
  const runtimeAffectingHash = opts.cache.computeHash(runtimeAffectingSignature);
638
656
  runtimeAffectingHashByFile.set(file, runtimeAffectingHash);
639
657
  const previousHash = state.sourceHashByFile.get(file);
@@ -682,6 +700,7 @@ function buildBundleSnapshot(bundle, opts, outDir, state, forceAll = false) {
682
700
  entries,
683
701
  jsEntries,
684
702
  sourceHashByFile,
703
+ runtimeAffectingSignatureByFile,
685
704
  runtimeAffectingHashByFile,
686
705
  changedByType,
687
706
  runtimeAffectingChangedByType,
@@ -703,12 +722,22 @@ function invertLinkedByEntry(linkedByEntry) {
703
722
  }
704
723
  return dependentsByLinkedFile;
705
724
  }
706
- function updateBundleBuildState(state, snapshot, linkedByEntry) {
725
+ function updateBundleBuildState(state, snapshot, linkedByEntry, options = {}) {
726
+ const incremental = options.incremental === true;
707
727
  state.iteration += 1;
708
- state.sourceHashByFile = snapshot.sourceHashByFile;
709
- state.runtimeAffectingHashByFile = snapshot.runtimeAffectingHashByFile;
710
- state.linkedByEntry = linkedByEntry;
711
- state.dependentsByLinkedFile = invertLinkedByEntry(linkedByEntry);
728
+ state.sourceHashByFile = incremental ? new Map([
729
+ ...state.sourceHashByFile,
730
+ ...snapshot.sourceHashByFile
731
+ ]) : snapshot.sourceHashByFile;
732
+ state.runtimeAffectingHashByFile = incremental ? new Map([
733
+ ...state.runtimeAffectingHashByFile,
734
+ ...snapshot.runtimeAffectingHashByFile
735
+ ]) : snapshot.runtimeAffectingHashByFile;
736
+ state.linkedByEntry = incremental ? new Map([
737
+ ...state.linkedByEntry,
738
+ ...linkedByEntry
739
+ ]) : linkedByEntry;
740
+ state.dependentsByLinkedFile = invertLinkedByEntry(state.linkedByEntry);
712
741
  }
713
742
 
714
743
  // src/bundlers/vite/js-precheck.ts
@@ -813,6 +842,42 @@ function createJsHashSalt(runtimeSignature, linkedImpactSignature) {
813
842
  function hasRuntimeAffectingSourceChanges(changedByType) {
814
843
  return changedByType.html.size > 0 || changedByType.js.size > 0;
815
844
  }
845
+ function canShareCssTransformResult(rawSource) {
846
+ return !rawSource.includes("@import") && !rawSource.includes("url(");
847
+ }
848
+ function hasOmittedKnownBundleFiles(currentBundleFiles, previousBundleFiles) {
849
+ const currentFileSet = new Set(currentBundleFiles);
850
+ for (const file of previousBundleFiles) {
851
+ if (!currentFileSet.has(file)) {
852
+ return true;
853
+ }
854
+ }
855
+ return false;
856
+ }
857
+ var MUSTACHE_EXPRESSION_RE = /\{\{[\s\S]*?\}\}/g;
858
+ var QUOTED_LITERAL_RE = /'([^']*)'|"([^"]*)"|`([^`]*)`/g;
859
+ function isArbitraryValueCandidate(candidate) {
860
+ return candidate.includes("[") && candidate.includes("]");
861
+ }
862
+ function collectUnescapedDynamicCandidates(source) {
863
+ const matches = /* @__PURE__ */ new Set();
864
+ for (const expression of source.match(MUSTACHE_EXPRESSION_RE) ?? []) {
865
+ QUOTED_LITERAL_RE.lastIndex = 0;
866
+ let quoted = QUOTED_LITERAL_RE.exec(expression);
867
+ while (quoted !== null) {
868
+ const literal = quoted[1] ?? quoted[2] ?? quoted[3] ?? "";
869
+ for (const candidate of splitCode(literal, true)) {
870
+ const normalized = candidate.trim();
871
+ if (!normalized || !isArbitraryValueCandidate(normalized)) {
872
+ continue;
873
+ }
874
+ matches.add(normalized);
875
+ }
876
+ quoted = QUOTED_LITERAL_RE.exec(expression);
877
+ }
878
+ }
879
+ return [...matches];
880
+ }
816
881
  function createGenerateBundleHook(context) {
817
882
  const state = createBundleBuildState();
818
883
  const cssHandlerOptionsCache = /* @__PURE__ */ new Map();
@@ -820,8 +885,8 @@ function createGenerateBundleHook(context) {
820
885
  const {
821
886
  opts,
822
887
  runtimeState,
823
- ensureRuntimeClassSet,
824
- debug: debug2,
888
+ ensureBundleRuntimeClassSet,
889
+ debug: debug3,
825
890
  getResolvedConfig
826
891
  } = context;
827
892
  const {
@@ -857,7 +922,7 @@ function createGenerateBundleHook(context) {
857
922
  return created;
858
923
  };
859
924
  await runtimeState.patchPromise;
860
- debug2("start");
925
+ debug3("start");
861
926
  onStart();
862
927
  const metrics = createEmptyMetrics();
863
928
  const forceRuntimeRefreshByEnv = process2.env.WEAPP_TW_VITE_FORCE_RUNTIME_REFRESH === "1";
@@ -865,54 +930,69 @@ function createGenerateBundleHook(context) {
865
930
  const disableJsPrecheck = process2.env.WEAPP_TW_VITE_DISABLE_JS_PRECHECK === "1";
866
931
  const debugCssDiff = process2.env.WEAPP_TW_VITE_DEBUG_CSS_DIFF === "1";
867
932
  const resolvedConfig = getResolvedConfig();
933
+ const bundleFiles = Object.keys(bundle);
934
+ const buildCommand = resolvedConfig?.command === "build";
935
+ const useIncrementalMode = !buildCommand || hasOmittedKnownBundleFiles(bundleFiles, state.sourceHashByFile.keys());
868
936
  const rootDir = resolvedConfig?.root ? path2.resolve(resolvedConfig.root) : process2.cwd();
869
937
  const outDir = resolvedConfig?.build?.outDir ? path2.resolve(rootDir, resolvedConfig.build.outDir) : rootDir;
870
- const snapshot = buildBundleSnapshot(bundle, opts, outDir, state, disableDirtyOptimization);
871
- const forceRuntimeRefreshBySource = hasRuntimeAffectingSourceChanges(snapshot.runtimeAffectingChangedByType);
872
- const forceRuntimeRefresh = forceRuntimeRefreshByEnv || forceRuntimeRefreshBySource;
938
+ const snapshot = buildBundleSnapshot(bundle, opts, outDir, state, disableDirtyOptimization || !useIncrementalMode);
939
+ const useBundleRuntimeClassSet = useIncrementalMode || runtimeState.twPatcher.majorVersion === 4;
940
+ const forceRuntimeRefreshBySource = useIncrementalMode && hasRuntimeAffectingSourceChanges(snapshot.runtimeAffectingChangedByType);
873
941
  const processFiles = snapshot.processFiles;
874
- debug2(
875
- "dirty iteration=%d html=%d[%s] js=%d[%s] css=%d[%s] other=%d[%s]",
876
- state.iteration + 1,
877
- snapshot.changedByType.html.size,
878
- formatDebugFileList(snapshot.changedByType.html),
879
- snapshot.changedByType.js.size,
880
- formatDebugFileList(snapshot.changedByType.js),
881
- snapshot.changedByType.css.size,
882
- formatDebugFileList(snapshot.changedByType.css),
883
- snapshot.changedByType.other.size,
884
- formatDebugFileList(snapshot.changedByType.other)
885
- );
886
- debug2(
887
- "process iteration=%d html=%d[%s] js=%d[%s] css=%d[%s]",
888
- state.iteration + 1,
889
- processFiles.html.size,
890
- formatDebugFileList(processFiles.html),
891
- processFiles.js.size,
892
- formatDebugFileList(processFiles.js),
893
- processFiles.css.size,
894
- formatDebugFileList(processFiles.css)
895
- );
942
+ if (useIncrementalMode) {
943
+ debug3(
944
+ "dirty iteration=%d html=%d[%s] js=%d[%s] css=%d[%s] other=%d[%s]",
945
+ state.iteration + 1,
946
+ snapshot.changedByType.html.size,
947
+ formatDebugFileList(snapshot.changedByType.html),
948
+ snapshot.changedByType.js.size,
949
+ formatDebugFileList(snapshot.changedByType.js),
950
+ snapshot.changedByType.css.size,
951
+ formatDebugFileList(snapshot.changedByType.css),
952
+ snapshot.changedByType.other.size,
953
+ formatDebugFileList(snapshot.changedByType.other)
954
+ );
955
+ debug3(
956
+ "process iteration=%d html=%d[%s] js=%d[%s] css=%d[%s]",
957
+ state.iteration + 1,
958
+ processFiles.html.size,
959
+ formatDebugFileList(processFiles.html),
960
+ processFiles.js.size,
961
+ formatDebugFileList(processFiles.js),
962
+ processFiles.css.size,
963
+ formatDebugFileList(processFiles.css)
964
+ );
965
+ } else {
966
+ debug3(
967
+ "build mode full process html=%d[%s] js=%d[%s] css=%d[%s]",
968
+ processFiles.html.size,
969
+ formatDebugFileList(processFiles.html),
970
+ processFiles.js.size,
971
+ formatDebugFileList(processFiles.js),
972
+ processFiles.css.size,
973
+ formatDebugFileList(processFiles.css)
974
+ );
975
+ }
896
976
  const jsEntries = snapshot.jsEntries;
897
977
  const moduleGraphOptions = createBundleModuleGraphOptions(outDir, jsEntries);
898
978
  const runtimeStart = performance.now();
899
- const runtime = await ensureRuntimeClassSet(forceRuntimeRefresh);
979
+ const runtime = useBundleRuntimeClassSet ? await ensureBundleRuntimeClassSet(snapshot, forceRuntimeRefreshByEnv) : await context.ensureRuntimeClassSet(forceRuntimeRefreshByEnv);
900
980
  const defaultTemplateHandlerOptions = {
901
981
  runtimeSet: runtime
902
982
  };
903
983
  metrics.runtimeSet = measureElapsed(runtimeStart);
904
984
  if (forceRuntimeRefreshBySource) {
905
- debug2(
985
+ debug3(
906
986
  "runtimeSet forced refresh due to source changes: html=%d js=%d",
907
987
  snapshot.runtimeAffectingChangedByType.html.size,
908
988
  snapshot.runtimeAffectingChangedByType.js.size
909
989
  );
910
990
  }
911
- debug2("get runtimeSet, class count: %d", runtime.size);
991
+ debug3("get runtimeSet, class count: %d", runtime.size);
912
992
  const runtimeSignature = getRuntimeClassSetSignature(runtimeState.twPatcher) ?? "runtime:missing";
913
993
  const handleLinkedUpdate = (fileName, previous, next) => {
914
994
  onUpdate(fileName, previous, next);
915
- debug2("js linked handle: %s", fileName);
995
+ debug3("js linked handle: %s", fileName);
916
996
  };
917
997
  const pendingLinkedUpdates = [];
918
998
  const scheduleLinkedApply = (entry, code) => {
@@ -937,7 +1017,8 @@ function createGenerateBundleHook(context) {
937
1017
  sourceFilename: absoluteFilename
938
1018
  }
939
1019
  });
940
- const linkedByEntry = /* @__PURE__ */ new Map();
1020
+ const linkedByEntry = useIncrementalMode ? /* @__PURE__ */ new Map() : void 0;
1021
+ const sharedCssResultCache = /* @__PURE__ */ new Map();
941
1022
  const tasks = [];
942
1023
  const jsTaskFactories = [];
943
1024
  for (const entry of snapshot.entries) {
@@ -959,15 +1040,35 @@ function createGenerateBundleHook(context) {
959
1040
  },
960
1041
  onCacheHit() {
961
1042
  metrics.html.cacheHits++;
962
- debug2("html cache hit: %s", file);
1043
+ debug3("html cache hit: %s", file);
963
1044
  },
964
1045
  async transform() {
965
1046
  const start = performance.now();
966
- const transformed = await templateHandler(rawSource, defaultTemplateHandlerOptions);
1047
+ let transformed = await templateHandler(rawSource, defaultTemplateHandlerOptions);
1048
+ let unresolvedDynamicCandidates = collectUnescapedDynamicCandidates(transformed);
1049
+ if (unresolvedDynamicCandidates.length > 0) {
1050
+ logger.warn(
1051
+ "\u68C0\u6D4B\u5230 WXML \u52A8\u6001\u7C7B\u540D\u672A\u5B8C\u6210\u8F6C\u8BD1\uFF0C\u5DF2\u56DE\u9000\u5230\u5B8C\u6574 runtimeSet \u91CD\u8BD5: %s -> %O",
1052
+ file,
1053
+ unresolvedDynamicCandidates
1054
+ );
1055
+ const fullRuntimeSet = await context.ensureRuntimeClassSet(true);
1056
+ transformed = await templateHandler(rawSource, {
1057
+ runtimeSet: fullRuntimeSet
1058
+ });
1059
+ unresolvedDynamicCandidates = collectUnescapedDynamicCandidates(transformed);
1060
+ if (unresolvedDynamicCandidates.length > 0) {
1061
+ logger.warn(
1062
+ "WXML \u52A8\u6001\u7C7B\u540D\u5728\u5B8C\u6574 runtimeSet \u91CD\u8BD5\u540E\u4ECD\u672A\u5B8C\u6210\u8F6C\u8BD1: %s -> %O",
1063
+ file,
1064
+ unresolvedDynamicCandidates
1065
+ );
1066
+ }
1067
+ }
967
1068
  metrics.html.elapsed += measureElapsed(start);
968
1069
  metrics.html.transformed++;
969
1070
  onUpdate(file, rawSource, transformed);
970
- debug2("html handle: %s", file);
1071
+ debug3("html handle: %s", file);
971
1072
  return {
972
1073
  result: transformed
973
1074
  };
@@ -979,30 +1080,53 @@ function createGenerateBundleHook(context) {
979
1080
  if (type === "css" && originalSource.type === "asset") {
980
1081
  metrics.css.total++;
981
1082
  const rawSource = originalEntrySource;
1083
+ const cssRuntimeAffectingSignature = snapshot.runtimeAffectingSignatureByFile.get(file) ?? rawSource;
1084
+ const shareCssResult = canShareCssTransformResult(rawSource);
1085
+ const cssSharedCacheKey = shareCssResult ? `${runtimeSignature}:${runtimeState.twPatcher.majorVersion ?? "unknown"}:${getCssHandlerOptions(file).isMainChunk ? "1" : "0"}:${cssRuntimeAffectingSignature}` : void 0;
982
1086
  tasks.push(
983
1087
  processCachedTask({
984
1088
  cache,
985
1089
  cacheKey: file,
986
- rawSource,
987
1090
  hashKey: `${file}:css:${runtimeSignature}:${runtimeState.twPatcher.majorVersion ?? "unknown"}`,
1091
+ rawSource: cssRuntimeAffectingSignature,
988
1092
  applyResult(source) {
989
1093
  originalSource.source = source;
990
1094
  },
991
1095
  onCacheHit() {
992
1096
  metrics.css.cacheHits++;
993
- debug2("css cache hit: %s", file);
1097
+ debug3("css cache hit: %s", file);
994
1098
  },
995
1099
  async transform() {
996
- const start = performance.now();
997
- await runtimeState.patchPromise;
998
- const { css } = await styleHandler(rawSource, getCssHandlerOptions(file));
999
- if (debugCssDiff) {
1000
- debug2("css diff %s: %s", file, summarizeStringDiff(rawSource, css));
1100
+ if (cssSharedCacheKey) {
1101
+ const sharedCssTask = sharedCssResultCache.get(cssSharedCacheKey);
1102
+ if (sharedCssTask != null) {
1103
+ metrics.css.cacheHits++;
1104
+ debug3("css shared hit: %s", file);
1105
+ const sharedCss = await sharedCssTask;
1106
+ onUpdate(file, rawSource, sharedCss);
1107
+ return {
1108
+ result: sharedCss
1109
+ };
1110
+ }
1001
1111
  }
1002
- metrics.css.elapsed += measureElapsed(start);
1003
- metrics.css.transformed++;
1112
+ const runTransform = async () => {
1113
+ const start = performance.now();
1114
+ await runtimeState.patchPromise;
1115
+ const { css: css2 } = await styleHandler(rawSource, getCssHandlerOptions(file));
1116
+ if (debugCssDiff) {
1117
+ debug3("css diff %s: %s", file, summarizeStringDiff(rawSource, css2));
1118
+ }
1119
+ metrics.css.elapsed += measureElapsed(start);
1120
+ metrics.css.transformed++;
1121
+ return css2;
1122
+ };
1123
+ const cssTask = cssSharedCacheKey ? sharedCssResultCache.get(cssSharedCacheKey) ?? runTransform() : runTransform();
1124
+ if (cssSharedCacheKey && !sharedCssResultCache.has(cssSharedCacheKey)) {
1125
+ sharedCssResultCache.set(cssSharedCacheKey, cssTask);
1126
+ }
1127
+ const css = await cssTask;
1004
1128
  onUpdate(file, rawSource, css);
1005
- debug2("css handle: %s", file);
1129
+ debug3("css handle: %s", file);
1006
1130
  return {
1007
1131
  result: css
1008
1132
  };
@@ -1015,21 +1139,23 @@ function createGenerateBundleHook(context) {
1015
1139
  continue;
1016
1140
  }
1017
1141
  metrics.js.total++;
1018
- const shouldTransformJs = processFiles.js.has(file);
1142
+ const shouldTransformJs = !useIncrementalMode || processFiles.js.has(file);
1019
1143
  if (!shouldTransformJs) {
1020
- debug2("js skip transform (clean), replay cache: %s", file);
1144
+ debug3("js skip transform (clean), replay cache: %s", file);
1021
1145
  }
1022
1146
  if (originalSource.type === "chunk") {
1023
1147
  const absoluteFile = path2.resolve(outDir, file);
1024
1148
  const initialRawSource = originalEntrySource;
1025
- const linkedSet = /* @__PURE__ */ new Set();
1026
- linkedByEntry.set(file, linkedSet);
1149
+ const linkedSet = useIncrementalMode ? /* @__PURE__ */ new Set() : void 0;
1150
+ if (linkedByEntry && linkedSet) {
1151
+ linkedByEntry.set(file, linkedSet);
1152
+ }
1027
1153
  jsTaskFactories.push(async () => {
1028
- const linkedImpactSignature = createLinkedImpactSignature(
1154
+ const linkedImpactSignature = useIncrementalMode ? createLinkedImpactSignature(
1029
1155
  file,
1030
1156
  snapshot.linkedImpactsByEntry,
1031
1157
  snapshot.sourceHashByFile
1032
- );
1158
+ ) : void 0;
1033
1159
  const hashSalt = createJsHashSalt(runtimeSignature, linkedImpactSignature);
1034
1160
  await processCachedTask({
1035
1161
  cache,
@@ -1042,13 +1168,13 @@ function createGenerateBundleHook(context) {
1042
1168
  },
1043
1169
  onCacheHit() {
1044
1170
  metrics.js.cacheHits++;
1045
- debug2("js cache hit: %s", file);
1171
+ debug3("js cache hit: %s", file);
1046
1172
  },
1047
1173
  async transform() {
1048
1174
  const start = performance.now();
1049
1175
  const rawSource = originalSource.code;
1050
1176
  if (!shouldTransformJs) {
1051
- debug2("js cache replay miss, fallback transform: %s", file);
1177
+ debug3("js cache replay miss, fallback transform: %s", file);
1052
1178
  }
1053
1179
  const handlerOptions = createHandlerOptions(absoluteFile);
1054
1180
  if (!disableJsPrecheck && shouldSkipViteJsTransform(rawSource, handlerOptions)) {
@@ -1062,11 +1188,11 @@ function createGenerateBundleHook(context) {
1062
1188
  metrics.js.elapsed += measureElapsed(start);
1063
1189
  metrics.js.transformed++;
1064
1190
  onUpdate(file, rawSource, code);
1065
- debug2("js handle: %s", file);
1191
+ debug3("js handle: %s", file);
1066
1192
  if (linked) {
1067
1193
  for (const id of Object.keys(linked)) {
1068
1194
  const linkedEntry = jsEntries.get(id);
1069
- if (linkedEntry) {
1195
+ if (linkedEntry && linkedSet) {
1070
1196
  linkedSet.add(linkedEntry.fileName);
1071
1197
  }
1072
1198
  }
@@ -1079,14 +1205,16 @@ function createGenerateBundleHook(context) {
1079
1205
  });
1080
1206
  });
1081
1207
  } else if (uniAppX && originalSource.type === "asset") {
1082
- const linkedSet = /* @__PURE__ */ new Set();
1083
- linkedByEntry.set(file, linkedSet);
1208
+ const linkedSet = useIncrementalMode ? /* @__PURE__ */ new Set() : void 0;
1209
+ if (linkedByEntry && linkedSet) {
1210
+ linkedByEntry.set(file, linkedSet);
1211
+ }
1084
1212
  const baseApplyLinkedUpdates = applyLinkedUpdates;
1085
1213
  const wrappedApplyLinkedUpdates = (linked) => {
1086
1214
  if (linked) {
1087
1215
  for (const id of Object.keys(linked)) {
1088
1216
  const linkedEntry = jsEntries.get(id);
1089
- if (linkedEntry) {
1217
+ if (linkedEntry && linkedSet) {
1090
1218
  linkedSet.add(linkedEntry.fileName);
1091
1219
  }
1092
1220
  }
@@ -1102,14 +1230,14 @@ function createGenerateBundleHook(context) {
1102
1230
  hashKey: `${file}:js`,
1103
1231
  hashSalt: createJsHashSalt(
1104
1232
  runtimeSignature,
1105
- createLinkedImpactSignature(
1233
+ useIncrementalMode ? createLinkedImpactSignature(
1106
1234
  file,
1107
1235
  snapshot.linkedImpactsByEntry,
1108
1236
  snapshot.sourceHashByFile
1109
- )
1237
+ ) : void 0
1110
1238
  ),
1111
1239
  createHandlerOptions,
1112
- debug: debug2,
1240
+ debug: debug3,
1113
1241
  jsHandler,
1114
1242
  onUpdate,
1115
1243
  runtimeSet: runtime,
@@ -1120,7 +1248,7 @@ function createGenerateBundleHook(context) {
1120
1248
  jsTaskFactories.push(async () => {
1121
1249
  const start = performance.now();
1122
1250
  if (!shouldTransformJs) {
1123
- debug2("js skip transform (clean, uni-app-x), replay cache: %s", file);
1251
+ debug3("js skip transform (clean, uni-app-x), replay cache: %s", file);
1124
1252
  await factory();
1125
1253
  metrics.js.elapsed += measureElapsed(start);
1126
1254
  metrics.js.transformed++;
@@ -1151,10 +1279,15 @@ function createGenerateBundleHook(context) {
1151
1279
  for (const apply of pendingLinkedUpdates) {
1152
1280
  apply();
1153
1281
  }
1154
- updateBundleBuildState(state, snapshot, linkedByEntry);
1155
- debug2(
1282
+ updateBundleBuildState(
1283
+ state,
1284
+ snapshot,
1285
+ useIncrementalMode ? linkedByEntry ?? /* @__PURE__ */ new Map() : /* @__PURE__ */ new Map(),
1286
+ { incremental: useIncrementalMode }
1287
+ );
1288
+ debug3(
1156
1289
  "metrics iteration=%d runtime=%sms html(total=%d transform=%d hit=%d rate=%s elapsed=%sms) js(total=%d transform=%d hit=%d rate=%s elapsed=%sms) css(total=%d transform=%d hit=%d rate=%s elapsed=%sms)",
1157
- state.iteration,
1290
+ useIncrementalMode ? state.iteration : 0,
1158
1291
  formatMs(metrics.runtimeSet),
1159
1292
  metrics.html.total,
1160
1293
  metrics.html.transformed,
@@ -1173,7 +1306,363 @@ function createGenerateBundleHook(context) {
1173
1306
  formatMs(metrics.css.elapsed)
1174
1307
  );
1175
1308
  onEnd();
1176
- debug2("end");
1309
+ debug3("end");
1310
+ };
1311
+ }
1312
+
1313
+ // src/bundlers/vite/incremental-runtime-class-set.ts
1314
+ import { mkdir, readFile, rm, writeFile } from "fs/promises";
1315
+ import { createRequire } from "module";
1316
+ import path3 from "path";
1317
+ import process3 from "process";
1318
+ import { extractRawCandidatesWithPositions, extractValidCandidates } from "tailwindcss-patch";
1319
+ var debug = createDebug("[vite:runtime-set] ");
1320
+ var require2 = createRequire(import.meta.url);
1321
+ var EXTENSION_DOT_PREFIX_RE = /^\./;
1322
+ var VALIDATION_FILE_NAME = "runtime-candidates.html";
1323
+ var tailwindNodeModulePromise;
1324
+ function toPosixPath(value) {
1325
+ return value.replaceAll("\\", "/");
1326
+ }
1327
+ function createCssImportSource(imports) {
1328
+ return imports.map((value) => `@import "${toPosixPath(value)}";`).join("\n");
1329
+ }
1330
+ function isPostcssPluginImportTarget(value) {
1331
+ if (!value) {
1332
+ return false;
1333
+ }
1334
+ return value === "@tailwindcss/postcss" || value === "@tailwindcss/postcss7-compat" || value.includes("/postcss");
1335
+ }
1336
+ function resolveTailwindCssImportTarget(patcher) {
1337
+ const tailwindOptions = resolveTailwindcssOptions(patcher.options);
1338
+ const cssEntries = tailwindOptions?.v4?.cssEntries?.filter((item) => typeof item === "string" && item.length > 0);
1339
+ if (cssEntries && cssEntries.length > 0) {
1340
+ return createCssImportSource(cssEntries);
1341
+ }
1342
+ const configuredPackageName = tailwindOptions?.packageName;
1343
+ if (typeof configuredPackageName === "string" && configuredPackageName.length > 0 && !isPostcssPluginImportTarget(configuredPackageName)) {
1344
+ return createCssImportSource([configuredPackageName]);
1345
+ }
1346
+ const packageName = patcher.packageInfo?.name;
1347
+ if (typeof packageName === "string" && packageName.length > 0 && !isPostcssPluginImportTarget(packageName)) {
1348
+ return createCssImportSource([packageName]);
1349
+ }
1350
+ return createCssImportSource(["tailwindcss"]);
1351
+ }
1352
+ function getProjectRoot(patcher) {
1353
+ return patcher.options?.projectRoot ?? process3.cwd();
1354
+ }
1355
+ async function importTailwindNodeModule() {
1356
+ if (!tailwindNodeModulePromise) {
1357
+ tailwindNodeModulePromise = (async () => {
1358
+ try {
1359
+ const resolved = require2.resolve("@tailwindcss/node");
1360
+ return await import(resolved);
1361
+ } catch {
1362
+ const tailwindcssPatchEntry = require2.resolve("tailwindcss-patch");
1363
+ const resolved = require2.resolve("@tailwindcss/node", {
1364
+ paths: [path3.dirname(tailwindcssPatchEntry)]
1365
+ });
1366
+ return await import(resolved);
1367
+ }
1368
+ })();
1369
+ }
1370
+ return tailwindNodeModulePromise;
1371
+ }
1372
+ function resolveMaybeAbsolute(base, value) {
1373
+ if (!value) {
1374
+ return void 0;
1375
+ }
1376
+ return path3.isAbsolute(value) ? value : path3.resolve(base, value);
1377
+ }
1378
+ async function resolveTailwindCssSource(patcher) {
1379
+ const projectRoot = getProjectRoot(patcher);
1380
+ const tailwindOptions = resolveTailwindcssOptions(patcher.options);
1381
+ const configuredBase = resolveMaybeAbsolute(projectRoot, tailwindOptions?.v4?.base);
1382
+ const configDir = tailwindOptions?.config ? path3.dirname(tailwindOptions.config) : void 0;
1383
+ const sharedFallbacks = [
1384
+ configuredBase,
1385
+ projectRoot,
1386
+ tailwindOptions?.cwd,
1387
+ configDir
1388
+ ].filter((item) => typeof item === "string" && item.length > 0);
1389
+ if (tailwindOptions?.v4?.css) {
1390
+ return {
1391
+ projectRoot,
1392
+ base: configuredBase ?? projectRoot,
1393
+ baseFallbacks: [...new Set(sharedFallbacks)],
1394
+ css: tailwindOptions.v4.css
1395
+ };
1396
+ }
1397
+ const cssEntries = tailwindOptions?.v4?.cssEntries?.filter((item) => typeof item === "string" && item.length > 0) ?? [];
1398
+ if (cssEntries.length > 0) {
1399
+ const resolvedEntries = cssEntries.map((entry) => resolveMaybeAbsolute(projectRoot, entry) ?? entry);
1400
+ const cssChunks = [];
1401
+ const entryDirs = [];
1402
+ for (const entry of resolvedEntries) {
1403
+ try {
1404
+ cssChunks.push(await readFile(entry, "utf8"));
1405
+ entryDirs.push(path3.dirname(entry));
1406
+ } catch {
1407
+ }
1408
+ }
1409
+ if (cssChunks.length > 0) {
1410
+ const base = entryDirs[0] ?? configuredBase ?? projectRoot;
1411
+ const baseFallbacks = [...new Set([
1412
+ ...entryDirs.slice(1),
1413
+ ...sharedFallbacks
1414
+ ].filter((item) => typeof item === "string" && item.length > 0 && item !== base))];
1415
+ return {
1416
+ projectRoot,
1417
+ base,
1418
+ baseFallbacks,
1419
+ css: cssChunks.join("\n")
1420
+ };
1421
+ }
1422
+ }
1423
+ return {
1424
+ projectRoot,
1425
+ base: configuredBase ?? projectRoot,
1426
+ baseFallbacks: [...new Set(sharedFallbacks)],
1427
+ css: resolveTailwindCssImportTarget(patcher)
1428
+ };
1429
+ }
1430
+ function createExtractOptions(context, tempRoot, pattern) {
1431
+ return {
1432
+ cwd: context.projectRoot,
1433
+ base: context.base,
1434
+ baseFallbacks: context.baseFallbacks,
1435
+ css: context.css,
1436
+ sources: [{
1437
+ base: tempRoot,
1438
+ pattern,
1439
+ negated: false
1440
+ }]
1441
+ };
1442
+ }
1443
+ function createRuntimeEntries(snapshot) {
1444
+ return snapshot.entries.filter((entry) => entry.type === "html" || entry.type === "js");
1445
+ }
1446
+ function collectChangedRuntimeFiles(snapshot) {
1447
+ return /* @__PURE__ */ new Set([
1448
+ ...snapshot.runtimeAffectingChangedByType.html,
1449
+ ...snapshot.runtimeAffectingChangedByType.js
1450
+ ]);
1451
+ }
1452
+ async function writeTempEntryFile(tempRoot, file, source) {
1453
+ const absoluteFile = path3.join(tempRoot, file);
1454
+ await mkdir(path3.dirname(absoluteFile), { recursive: true });
1455
+ await writeFile(absoluteFile, source, "utf8");
1456
+ return file;
1457
+ }
1458
+ function resolveEntryExtension(entry) {
1459
+ const ext = path3.extname(entry.file).replace(EXTENSION_DOT_PREFIX_RE, "");
1460
+ if (ext.length > 0) {
1461
+ return ext;
1462
+ }
1463
+ return entry.type === "html" ? "html" : "js";
1464
+ }
1465
+ function createCandidateValidationSource(candidates) {
1466
+ return [...new Set(candidates)].sort().join("\n");
1467
+ }
1468
+ function removeCandidateSet(candidateCountByClass, runtimeSet, candidates) {
1469
+ for (const className of candidates) {
1470
+ const count = candidateCountByClass.get(className);
1471
+ if (count == null) {
1472
+ continue;
1473
+ }
1474
+ if (count <= 1) {
1475
+ candidateCountByClass.delete(className);
1476
+ runtimeSet.delete(className);
1477
+ continue;
1478
+ }
1479
+ candidateCountByClass.set(className, count - 1);
1480
+ }
1481
+ }
1482
+ function addCandidateSet(candidateCountByClass, runtimeSet, candidates) {
1483
+ for (const className of candidates) {
1484
+ const nextCount = (candidateCountByClass.get(className) ?? 0) + 1;
1485
+ candidateCountByClass.set(className, nextCount);
1486
+ runtimeSet.add(className);
1487
+ }
1488
+ }
1489
+ function createBundleRuntimeClassSetManager(options = {}) {
1490
+ const customExtractCandidates = options.extractCandidates;
1491
+ const extractCandidates = customExtractCandidates ?? extractValidCandidates;
1492
+ const extractRawCandidates = options.extractRawCandidates ?? extractRawCandidatesWithPositions;
1493
+ const runtimeSet = /* @__PURE__ */ new Set();
1494
+ const candidateCountByClass = /* @__PURE__ */ new Map();
1495
+ const candidatesByFile = /* @__PURE__ */ new Map();
1496
+ const candidateValidityCache = /* @__PURE__ */ new Map();
1497
+ let runtimeSignature;
1498
+ let resolvedTempRoot;
1499
+ let validationContext;
1500
+ let designSystemPromise;
1501
+ async function reset() {
1502
+ runtimeSet.clear();
1503
+ candidateCountByClass.clear();
1504
+ candidatesByFile.clear();
1505
+ candidateValidityCache.clear();
1506
+ runtimeSignature = void 0;
1507
+ validationContext = void 0;
1508
+ designSystemPromise = void 0;
1509
+ if (resolvedTempRoot) {
1510
+ await rm(resolvedTempRoot, { recursive: true, force: true });
1511
+ resolvedTempRoot = void 0;
1512
+ }
1513
+ }
1514
+ async function resolveValidationContextCached(patcher) {
1515
+ if (!validationContext) {
1516
+ validationContext = await resolveTailwindCssSource(patcher);
1517
+ }
1518
+ return validationContext;
1519
+ }
1520
+ async function loadDesignSystem(context) {
1521
+ if (!designSystemPromise) {
1522
+ designSystemPromise = (async () => {
1523
+ const { __unstable__loadDesignSystem } = await importTailwindNodeModule();
1524
+ let lastError;
1525
+ for (const base of [context.base, ...context.baseFallbacks]) {
1526
+ try {
1527
+ return await __unstable__loadDesignSystem(context.css, { base });
1528
+ } catch (error) {
1529
+ lastError = error;
1530
+ }
1531
+ }
1532
+ throw lastError instanceof Error ? lastError : new Error("Failed to load Tailwind CSS design system for incremental runtime validation.");
1533
+ })();
1534
+ }
1535
+ return designSystemPromise;
1536
+ }
1537
+ function populateCandidateValidityCacheFromDesignSystem(designSystem, unknownCandidates) {
1538
+ const parsedCandidates = [...unknownCandidates].filter((candidate) => designSystem.parseCandidate(candidate).length > 0);
1539
+ const cssByCandidate = parsedCandidates.length > 0 ? designSystem.candidatesToCss(parsedCandidates) : [];
1540
+ const validCandidates = /* @__PURE__ */ new Set();
1541
+ for (let index = 0; index < parsedCandidates.length; index += 1) {
1542
+ const candidate = parsedCandidates[index];
1543
+ const css = cssByCandidate[index];
1544
+ if (candidate && typeof css === "string" && css.trim().length > 0) {
1545
+ validCandidates.add(candidate);
1546
+ }
1547
+ }
1548
+ for (const candidate of unknownCandidates) {
1549
+ candidateValidityCache.set(candidate, validCandidates.has(candidate));
1550
+ }
1551
+ }
1552
+ async function validateUnknownCandidates(patcher, tempRoot, unknownCandidates) {
1553
+ if (unknownCandidates.size === 0) {
1554
+ return;
1555
+ }
1556
+ const context = await resolveValidationContextCached(patcher);
1557
+ if (!customExtractCandidates) {
1558
+ try {
1559
+ const designSystem = await loadDesignSystem(context);
1560
+ populateCandidateValidityCacheFromDesignSystem(designSystem, unknownCandidates);
1561
+ return;
1562
+ } catch (error) {
1563
+ debug("incremental design-system validation failed, fallback to extractValidCandidates: %O", error);
1564
+ designSystemPromise = void 0;
1565
+ }
1566
+ }
1567
+ const source = createCandidateValidationSource(unknownCandidates);
1568
+ const pattern = await writeTempEntryFile(tempRoot, VALIDATION_FILE_NAME, source);
1569
+ const validCandidates = new Set(await extractCandidates(createExtractOptions(context, tempRoot, pattern)));
1570
+ for (const candidate of unknownCandidates) {
1571
+ candidateValidityCache.set(candidate, validCandidates.has(candidate));
1572
+ }
1573
+ }
1574
+ async function extractEntryRawCandidates(entry) {
1575
+ const matches = await extractRawCandidates(entry.source, resolveEntryExtension(entry));
1576
+ const candidates = /* @__PURE__ */ new Set();
1577
+ for (const match of matches) {
1578
+ const candidate = match?.rawCandidate;
1579
+ if (typeof candidate === "string" && candidate.length > 0) {
1580
+ candidates.add(candidate);
1581
+ }
1582
+ }
1583
+ return candidates;
1584
+ }
1585
+ async function sync(patcher, snapshot) {
1586
+ const nextSignature = getRuntimeClassSetSignature(patcher) ?? "runtime:missing";
1587
+ const runtimeEntries = createRuntimeEntries(snapshot);
1588
+ const runtimeEntriesByFile = new Map(runtimeEntries.map((entry) => [entry.file, entry]));
1589
+ const currentRuntimeFiles = new Set(runtimeEntriesByFile.keys());
1590
+ const fullRebuild = runtimeSignature !== nextSignature || candidatesByFile.size === 0;
1591
+ if (runtimeSignature !== nextSignature) {
1592
+ debug("runtime signature changed, reset incremental runtime set: %s", nextSignature);
1593
+ await reset();
1594
+ }
1595
+ runtimeSignature = nextSignature;
1596
+ const projectRoot = getProjectRoot(patcher);
1597
+ resolvedTempRoot = options.tempRoot ?? path3.join(
1598
+ projectRoot,
1599
+ "node_modules",
1600
+ ".cache",
1601
+ "weapp-tailwindcss",
1602
+ "vite-runtime-set"
1603
+ );
1604
+ for (const [file, previousCandidates] of candidatesByFile) {
1605
+ if (currentRuntimeFiles.has(file)) {
1606
+ continue;
1607
+ }
1608
+ removeCandidateSet(candidateCountByClass, runtimeSet, previousCandidates);
1609
+ candidatesByFile.delete(file);
1610
+ }
1611
+ const changedRuntimeFiles = fullRebuild ? [...runtimeEntriesByFile.keys()] : [...collectChangedRuntimeFiles(snapshot)];
1612
+ if (changedRuntimeFiles.length === 0) {
1613
+ return new Set(runtimeSet);
1614
+ }
1615
+ const rawCandidatesByFile = /* @__PURE__ */ new Map();
1616
+ const unknownCandidates = /* @__PURE__ */ new Set();
1617
+ await Promise.all(changedRuntimeFiles.map(async (file) => {
1618
+ const entry = runtimeEntriesByFile.get(file);
1619
+ if (!entry) {
1620
+ return;
1621
+ }
1622
+ const candidates = await extractEntryRawCandidates(entry);
1623
+ rawCandidatesByFile.set(file, candidates);
1624
+ for (const candidate of candidates) {
1625
+ if (!candidateValidityCache.has(candidate)) {
1626
+ unknownCandidates.add(candidate);
1627
+ }
1628
+ }
1629
+ }));
1630
+ await validateUnknownCandidates(patcher, resolvedTempRoot, unknownCandidates);
1631
+ let rawCandidateCount = 0;
1632
+ for (const file of changedRuntimeFiles) {
1633
+ const nextRawCandidates = rawCandidatesByFile.get(file);
1634
+ const previousCandidates = candidatesByFile.get(file);
1635
+ if (previousCandidates) {
1636
+ removeCandidateSet(candidateCountByClass, runtimeSet, previousCandidates);
1637
+ }
1638
+ if (!nextRawCandidates || nextRawCandidates.size === 0) {
1639
+ candidatesByFile.delete(file);
1640
+ continue;
1641
+ }
1642
+ rawCandidateCount += nextRawCandidates.size;
1643
+ const nextCandidates = new Set(
1644
+ [...nextRawCandidates].filter((candidate) => candidateValidityCache.get(candidate) === true)
1645
+ );
1646
+ if (nextCandidates.size === 0) {
1647
+ candidatesByFile.delete(file);
1648
+ continue;
1649
+ }
1650
+ addCandidateSet(candidateCountByClass, runtimeSet, nextCandidates);
1651
+ candidatesByFile.set(file, nextCandidates);
1652
+ }
1653
+ debug(
1654
+ "incremental runtime set synced, changedFiles=%d rawCandidates=%d validateMisses=%d runtimeSize=%d trackedFiles=%d",
1655
+ changedRuntimeFiles.length,
1656
+ rawCandidateCount,
1657
+ unknownCandidates.size,
1658
+ runtimeSet.size,
1659
+ candidatesByFile.size
1660
+ );
1661
+ return new Set(runtimeSet);
1662
+ }
1663
+ return {
1664
+ sync,
1665
+ reset
1177
1666
  };
1178
1667
  }
1179
1668
 
@@ -1240,9 +1729,35 @@ function createRewriteCssImportsPlugins(options) {
1240
1729
  }
1241
1730
 
1242
1731
  // src/bundlers/vite/index.ts
1243
- var debug = createDebug();
1732
+ var debug2 = createDebug();
1244
1733
  var weappTailwindcssPackageDir = resolvePackageDir("weapp-tailwindcss");
1245
1734
  var weappTailwindcssDirPosix = slash(weappTailwindcssPackageDir);
1735
+ var PACKAGE_JSON_FILE = "package.json";
1736
+ function resolveImplicitTailwindcssBasedirFromViteRoot(root) {
1737
+ const resolvedRoot = path4.resolve(root);
1738
+ if (!existsSync(resolvedRoot)) {
1739
+ return resolvedRoot;
1740
+ }
1741
+ const searchRoots = [];
1742
+ let current = resolvedRoot;
1743
+ while (true) {
1744
+ searchRoots.push(current);
1745
+ const parent = path4.dirname(current);
1746
+ if (parent === current) {
1747
+ break;
1748
+ }
1749
+ current = parent;
1750
+ }
1751
+ const tailwindConfigPath = findTailwindConfig(searchRoots);
1752
+ if (tailwindConfigPath) {
1753
+ return path4.dirname(tailwindConfigPath);
1754
+ }
1755
+ const packageRoot = findNearestPackageRoot(resolvedRoot);
1756
+ if (packageRoot && existsSync(path4.join(packageRoot, PACKAGE_JSON_FILE))) {
1757
+ return packageRoot;
1758
+ }
1759
+ return resolvedRoot;
1760
+ }
1246
1761
  function UnifiedViteWeappTailwindcssPlugin(options = {}) {
1247
1762
  const rewriteCssImportsSpecified = Object.hasOwn(options, "rewriteCssImports");
1248
1763
  const hasExplicitTailwindcssBasedir = typeof options.tailwindcssBasedir === "string" && options.tailwindcssBasedir.trim().length > 0;
@@ -1274,7 +1789,7 @@ function UnifiedViteWeappTailwindcssPlugin(options = {}) {
1274
1789
  const customAttributesEntities = toCustomAttributesEntities(customAttributes);
1275
1790
  const patchRecorderState = setupPatchRecorder(initialTwPatcher, opts.tailwindcssBasedir, {
1276
1791
  source: "runtime",
1277
- cwd: opts.tailwindcssBasedir ?? process3.cwd()
1792
+ cwd: opts.tailwindcssBasedir ?? process4.cwd()
1278
1793
  });
1279
1794
  const runtimeState = {
1280
1795
  twPatcher: initialTwPatcher,
@@ -1287,8 +1802,9 @@ function UnifiedViteWeappTailwindcssPlugin(options = {}) {
1287
1802
  let resolvedConfig;
1288
1803
  let runtimeRefreshSignature;
1289
1804
  let runtimeRefreshOptionsKey;
1805
+ const bundleRuntimeClassSetManager = createBundleRuntimeClassSetManager();
1290
1806
  function resolveRuntimeRefreshOptions() {
1291
- const configPath = runtimeState.twPatcher.options?.tailwind?.config;
1807
+ const configPath = resolveTailwindcssOptions(runtimeState.twPatcher.options)?.config;
1292
1808
  const signature = getRuntimeClassSetSignature(runtimeState.twPatcher);
1293
1809
  const optionsKey = JSON.stringify({
1294
1810
  appType,
@@ -1315,7 +1831,7 @@ function UnifiedViteWeappTailwindcssPlugin(options = {}) {
1315
1831
  clearCache: force || invalidation.changed
1316
1832
  });
1317
1833
  if (invalidation.changed) {
1318
- debug("runtime signature changed, refresh triggered. signature: %s", invalidation.signature);
1834
+ debug2("runtime signature changed, refresh triggered. signature: %s", invalidation.signature);
1319
1835
  }
1320
1836
  if (refreshed) {
1321
1837
  runtimeSet = void 0;
@@ -1323,7 +1839,7 @@ function UnifiedViteWeappTailwindcssPlugin(options = {}) {
1323
1839
  }
1324
1840
  }
1325
1841
  async function ensureRuntimeClassSet(force = false) {
1326
- const forceRuntimeRefresh = force || process3.env.WEAPP_TW_VITE_FORCE_RUNTIME_REFRESH === "1";
1842
+ const forceRuntimeRefresh = force || process4.env.WEAPP_TW_VITE_FORCE_RUNTIME_REFRESH === "1";
1327
1843
  await refreshRuntimeState(force);
1328
1844
  await runtimeState.patchPromise;
1329
1845
  if (!forceRuntimeRefresh && runtimeSet) {
@@ -1348,6 +1864,46 @@ function UnifiedViteWeappTailwindcssPlugin(options = {}) {
1348
1864
  }
1349
1865
  }
1350
1866
  }
1867
+ async function ensureBundleRuntimeClassSet(snapshot, forceRefresh = false) {
1868
+ const forceRuntimeRefresh = forceRefresh || process4.env.WEAPP_TW_VITE_FORCE_RUNTIME_REFRESH === "1";
1869
+ const invalidation = resolveRuntimeRefreshOptions();
1870
+ const shouldRefreshPatcher = forceRuntimeRefresh || invalidation.changed;
1871
+ const forceCollectBySource = snapshot.runtimeAffectingChangedByType.html.size > 0 || snapshot.runtimeAffectingChangedByType.js.size > 0;
1872
+ await refreshRuntimeState(shouldRefreshPatcher);
1873
+ await runtimeState.patchPromise;
1874
+ if (shouldRefreshPatcher) {
1875
+ runtimeSet = void 0;
1876
+ runtimeSetPromise = void 0;
1877
+ await bundleRuntimeClassSetManager.reset();
1878
+ }
1879
+ if (runtimeState.twPatcher.majorVersion === 4 && !forceRuntimeRefresh) {
1880
+ try {
1881
+ const nextRuntimeSet = await bundleRuntimeClassSetManager.sync(runtimeState.twPatcher, snapshot);
1882
+ runtimeSet = nextRuntimeSet;
1883
+ return nextRuntimeSet;
1884
+ } catch (error) {
1885
+ debug2("incremental runtime set sync failed, fallback to full collect: %O", error);
1886
+ await bundleRuntimeClassSetManager.reset();
1887
+ }
1888
+ }
1889
+ if (!forceRuntimeRefresh && !invalidation.changed && !forceCollectBySource && runtimeSet) {
1890
+ return runtimeSet;
1891
+ }
1892
+ const task = collectRuntimeClassSet(runtimeState.twPatcher, {
1893
+ force: forceRuntimeRefresh || invalidation.changed || forceCollectBySource,
1894
+ skipRefresh: forceRuntimeRefresh,
1895
+ clearCache: forceRuntimeRefresh || invalidation.changed
1896
+ });
1897
+ runtimeSetPromise = task;
1898
+ try {
1899
+ runtimeSet = await task;
1900
+ return runtimeSet;
1901
+ } finally {
1902
+ if (runtimeSetPromise === task) {
1903
+ runtimeSetPromise = void 0;
1904
+ }
1905
+ }
1906
+ }
1351
1907
  onLoad();
1352
1908
  const getResolvedConfig = () => resolvedConfig;
1353
1909
  const utsPlatform = resolveUniUtsPlatform();
@@ -1371,12 +1927,19 @@ function UnifiedViteWeappTailwindcssPlugin(options = {}) {
1371
1927
  enforce: "post",
1372
1928
  async configResolved(config) {
1373
1929
  resolvedConfig = config;
1374
- const resolvedRoot = config.root ? path3.resolve(config.root) : void 0;
1375
- if (!hasExplicitTailwindcssBasedir && resolvedRoot && opts.tailwindcssBasedir !== resolvedRoot) {
1376
- const previousBasedir = opts.tailwindcssBasedir;
1377
- opts.tailwindcssBasedir = resolvedRoot;
1378
- debug("align tailwindcss basedir with vite root: %s -> %s", previousBasedir ?? "undefined", resolvedRoot);
1379
- await refreshRuntimeState(true);
1930
+ const resolvedRoot = config.root ? path4.resolve(config.root) : void 0;
1931
+ if (!hasExplicitTailwindcssBasedir && resolvedRoot) {
1932
+ const nextTailwindcssBasedir = resolveImplicitTailwindcssBasedirFromViteRoot(resolvedRoot);
1933
+ if (opts.tailwindcssBasedir !== nextTailwindcssBasedir) {
1934
+ const previousBasedir = opts.tailwindcssBasedir;
1935
+ opts.tailwindcssBasedir = nextTailwindcssBasedir;
1936
+ debug2(
1937
+ "align tailwindcss basedir with vite root: %s -> %s",
1938
+ previousBasedir ?? "undefined",
1939
+ nextTailwindcssBasedir
1940
+ );
1941
+ await refreshRuntimeState(true);
1942
+ }
1380
1943
  }
1381
1944
  if (typeof config.css.postcss === "object" && Array.isArray(config.css.postcss.plugins)) {
1382
1945
  const postcssPlugins = config.css.postcss.plugins;
@@ -1386,7 +1949,7 @@ function UnifiedViteWeappTailwindcssPlugin(options = {}) {
1386
1949
  ));
1387
1950
  if (idx > -1) {
1388
1951
  postcssPlugins.splice(idx, 1, postcssHtmlTransform());
1389
- debug("remove postcss-html-transform plugin from vite config");
1952
+ debug2("remove postcss-html-transform plugin from vite config");
1390
1953
  }
1391
1954
  }
1392
1955
  },
@@ -1394,7 +1957,8 @@ function UnifiedViteWeappTailwindcssPlugin(options = {}) {
1394
1957
  opts,
1395
1958
  runtimeState,
1396
1959
  ensureRuntimeClassSet,
1397
- debug,
1960
+ ensureBundleRuntimeClassSet,
1961
+ debug: debug2,
1398
1962
  getResolvedConfig
1399
1963
  })
1400
1964
  }