@csszyx/unplugin 0.10.10 → 0.10.11

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.
@@ -15,7 +15,7 @@ import { createUnplugin } from 'unplugin';
15
15
  import { mangleCSSSync } from '../css-mangler.mjs';
16
16
  import { s as sortStrings, e as escapeHtmlAttribute } from './unplugin.B1mblcm-.mjs';
17
17
  import { createHash } from 'node:crypto';
18
- import { r as resolveTransformCacheDir, c as createTransformCacheKey, a as readTransformCache, w as writeTransformCache, e as evictOldTransformCacheEntries } from './unplugin.BpWUtI9U.mjs';
18
+ import { r as resolveTransformCacheDir, c as createTransformCacheKey, a as readTransformCache, w as writeTransformCache, e as evictOldTransformCacheEntries, b as evictMemoryCacheToBudget } from './unplugin.CGqFVGlB.mjs';
19
19
  import postcss from 'postcss';
20
20
  import valueParser from 'postcss-value-parser';
21
21
 
@@ -1006,6 +1006,8 @@ const EMPTY_THEME = {
1006
1006
  colors: [],
1007
1007
  spacings: [],
1008
1008
  fonts: [],
1009
+ textSizes: [],
1010
+ fontWeights: [],
1009
1011
  radii: [],
1010
1012
  shadows: [],
1011
1013
  breakpoints: []
@@ -1075,7 +1077,12 @@ function categorizeProperty(prop) {
1075
1077
  const categoryMap = [
1076
1078
  ["color-", "colors"],
1077
1079
  ["spacing-", "spacings"],
1080
+ // `font-weight-` MUST precede `font-`: startsWith would otherwise route
1081
+ // `font-weight-chunky` into font FAMILIES as token "weight-chunky".
1082
+ ["font-weight-", "fontWeights"],
1078
1083
  ["font-", "fonts"],
1084
+ // `--text-*` defines font-size utilities (text-huge) in Tailwind v4.
1085
+ ["text-", "textSizes"],
1079
1086
  ["radius-", "radii"],
1080
1087
  ["shadow-", "shadows"],
1081
1088
  ["breakpoint-", "breakpoints"]
@@ -1098,6 +1105,8 @@ function parseThemeBlocks(cssContent) {
1098
1105
  colors: /* @__PURE__ */ new Set(),
1099
1106
  spacings: /* @__PURE__ */ new Set(),
1100
1107
  fonts: /* @__PURE__ */ new Set(),
1108
+ textSizes: /* @__PURE__ */ new Set(),
1109
+ fontWeights: /* @__PURE__ */ new Set(),
1101
1110
  radii: /* @__PURE__ */ new Set(),
1102
1111
  shadows: /* @__PURE__ */ new Set(),
1103
1112
  breakpoints: /* @__PURE__ */ new Set()
@@ -1117,6 +1126,8 @@ function parseThemeBlocks(cssContent) {
1117
1126
  colors: sortStrings(result.colors),
1118
1127
  spacings: sortStrings(result.spacings),
1119
1128
  fonts: sortStrings(result.fonts),
1129
+ textSizes: sortStrings(result.textSizes),
1130
+ fontWeights: sortStrings(result.fontWeights),
1120
1131
  radii: sortStrings(result.radii),
1121
1132
  shadows: sortStrings(result.shadows),
1122
1133
  breakpoints: sortStrings(result.breakpoints)
@@ -1130,6 +1141,8 @@ function mergeThemes(themes) {
1130
1141
  colors: /* @__PURE__ */ new Set(),
1131
1142
  spacings: /* @__PURE__ */ new Set(),
1132
1143
  fonts: /* @__PURE__ */ new Set(),
1144
+ textSizes: /* @__PURE__ */ new Set(),
1145
+ fontWeights: /* @__PURE__ */ new Set(),
1133
1146
  radii: /* @__PURE__ */ new Set(),
1134
1147
  shadows: /* @__PURE__ */ new Set(),
1135
1148
  breakpoints: /* @__PURE__ */ new Set()
@@ -1145,6 +1158,8 @@ function mergeThemes(themes) {
1145
1158
  colors: sortStrings(merged.colors),
1146
1159
  spacings: sortStrings(merged.spacings),
1147
1160
  fonts: sortStrings(merged.fonts),
1161
+ textSizes: sortStrings(merged.textSizes),
1162
+ fontWeights: sortStrings(merged.fontWeights),
1148
1163
  radii: sortStrings(merged.radii),
1149
1164
  shadows: sortStrings(merged.shadows),
1150
1165
  breakpoints: sortStrings(merged.breakpoints)
@@ -1468,6 +1483,12 @@ function generateThemeDts(opts) {
1468
1483
  if (theme.fonts.length > 0) {
1469
1484
  entries.push(` fonts: ${toUnion(theme.fonts)};`);
1470
1485
  }
1486
+ if (theme.textSizes.length > 0) {
1487
+ entries.push(` textSizes: ${toUnion(theme.textSizes)};`);
1488
+ }
1489
+ if (theme.fontWeights.length > 0) {
1490
+ entries.push(` fontWeights: ${toUnion(theme.fontWeights)};`);
1491
+ }
1471
1492
  if (theme.radii.length > 0) {
1472
1493
  entries.push(` radii: ${toUnion(theme.radii)};`);
1473
1494
  }
@@ -1518,6 +1539,8 @@ function writeThemeDts(opts) {
1518
1539
 
1519
1540
  const VIRTUAL_MODULE_ID = "virtual:csszyx/mangle-map";
1520
1541
  const RESOLVED_VIRTUAL_MODULE_ID = `\0${VIRTUAL_MODULE_ID}`;
1542
+ const THEME_GROUPS_VIRTUAL_ID = "virtual:csszyx/theme-groups";
1543
+ const RESOLVED_THEME_GROUPS_VIRTUAL_ID = `\0${THEME_GROUPS_VIRTUAL_ID}`;
1521
1544
  const VIRTUAL_CHECKSUM_ID = "virtual:csszyx/checksum";
1522
1545
  const RESOLVED_VIRTUAL_CHECKSUM_ID = `\0${VIRTUAL_CHECKSUM_ID}`;
1523
1546
  function createMangleMapModule(mangleMap, checksum, varMangleMap = {}, cssVarMetrics = null) {
@@ -1558,7 +1581,7 @@ export default checksum;
1558
1581
  `;
1559
1582
  }
1560
1583
  function isVirtualModule(id) {
1561
- return id === VIRTUAL_MODULE_ID || id === VIRTUAL_CHECKSUM_ID;
1584
+ return id === VIRTUAL_MODULE_ID || id === VIRTUAL_CHECKSUM_ID || id === THEME_GROUPS_VIRTUAL_ID;
1562
1585
  }
1563
1586
  function resolveVirtualModule(id) {
1564
1587
  if (id === VIRTUAL_MODULE_ID) {
@@ -1567,8 +1590,25 @@ function resolveVirtualModule(id) {
1567
1590
  if (id === VIRTUAL_CHECKSUM_ID) {
1568
1591
  return RESOLVED_VIRTUAL_CHECKSUM_ID;
1569
1592
  }
1593
+ if (id === THEME_GROUPS_VIRTUAL_ID) {
1594
+ return RESOLVED_THEME_GROUPS_VIRTUAL_ID;
1595
+ }
1570
1596
  return void 0;
1571
1597
  }
1598
+ function createThemeGroupsModule(tokens) {
1599
+ const payload = JSON.stringify({
1600
+ colors: tokens.colors,
1601
+ textSizes: tokens.textSizes,
1602
+ fontFamilies: tokens.fontFamilies,
1603
+ fontWeights: tokens.fontWeights
1604
+ });
1605
+ return [
1606
+ "// Auto-generated by csszyx from the @theme blocks in scanned CSS.",
1607
+ "import { registerSzcnGroups } from '@csszyx/runtime';",
1608
+ `registerSzcnGroups(${payload});`,
1609
+ "export {};"
1610
+ ].join("\n");
1611
+ }
1572
1612
 
1573
1613
  const CHECKSUM_PLACEHOLDER = "___CSSZYX_CHECKSUM___";
1574
1614
  const MANGLE_MAP_PLACEHOLDER = "___CSSZYX_MANGLE_MAP___";
@@ -1577,6 +1617,7 @@ const UNKNOWN_PACKAGE_VERSION = "0.0.0";
1577
1617
  const TRANSFORM_CACHE_MAX_AGE_MS = 30 * 24 * 60 * 60 * 1e3;
1578
1618
  const TRANSFORM_CACHE_MAX_ENTRIES = 1e4;
1579
1619
  const TRANSFORM_MEMORY_CACHE_MAX_ENTRIES = 1e3;
1620
+ const TRANSFORM_MEMORY_CACHE_MAX_CODE_CHARS = 32e6;
1580
1621
  const MAX_SAFELIST_CLASSES = 1e5;
1581
1622
  const DEFAULT_VAR_MANGLE_MAP_MAX_BYTES = 100 * 1024;
1582
1623
  const GLOBAL_VAR_ALIAS_MAP_OWNER = "\0csszyx:global-var-aliases";
@@ -1589,7 +1630,7 @@ const RUNTIME_HELPER_IMPORT_RE = {
1589
1630
  let _hasWarnedTsConfig = false;
1590
1631
  let _hasWarnedTransformCacheVersion = false;
1591
1632
  let _hasWarnedNativeFallback = false;
1592
- let _hasLoggedActiveParser = false;
1633
+ const _loggedActiveParsers = /* @__PURE__ */ new Set();
1593
1634
  const _babelFallbackFiles = /* @__PURE__ */ new Set();
1594
1635
  const requireFromHere = createRequire(import.meta.url);
1595
1636
  const PLUGIN_VERSION = findPackageVersionFromFile(
@@ -1797,7 +1838,10 @@ function isHardIgnoredPath(id, sourceDirs = []) {
1797
1838
  return false;
1798
1839
  }
1799
1840
  function fileMayContainSafelistableSz(content) {
1800
- return content.includes("sz=") || content.includes("szs=") || content.includes("sz:") || content.includes("szv(");
1841
+ return content.includes("sz=") || content.includes("szs=") || content.includes("sz:") || content.includes("szv(") || content.includes("szr(") || // dynamic() literal args are extracted for the safelist, but a module
1842
+ // containing ONLY dynamic() calls never passed this gate — the
1843
+ // engine-parity harness caught its classes missing on all engines.
1844
+ content.includes("dynamic(");
1801
1845
  }
1802
1846
  function isPackagesSkippedSource(id, sourceDirs = []) {
1803
1847
  const p = normalizeForMatch(id);
@@ -1849,6 +1893,9 @@ function recordFileVarMangleEntries(state, filename, entries) {
1849
1893
  }
1850
1894
  state.varMangleMap = buildVarMangleMap(state.varMangleEntriesByFile);
1851
1895
  }
1896
+ function shouldTrackGlobalVarSources(config) {
1897
+ return config?.enabled === true;
1898
+ }
1852
1899
  function recordGlobalVarSourceFile(state, filename, code) {
1853
1900
  const normalizedFilename = normalizeSourceFilename(filename);
1854
1901
  if (!/\.[tj]sx?(?:\?.*)?$/.test(normalizedFilename)) {
@@ -2123,11 +2170,11 @@ function traceBenchTiming(label, filename, elapsedMs) {
2123
2170
  }
2124
2171
  function runThemeScan(rootDir, scanCss) {
2125
2172
  if (!scanCss) {
2126
- return;
2173
+ return null;
2127
2174
  }
2128
2175
  const sourceFiles = expandFilePatterns(rootDir, scanCss).filter((file) => file.endsWith(".css"));
2129
2176
  if (sourceFiles.length === 0) {
2130
- return;
2177
+ return null;
2131
2178
  }
2132
2179
  const themes = sourceFiles.map((f) => {
2133
2180
  try {
@@ -2167,6 +2214,7 @@ function runThemeScan(rootDir, scanCss) {
2167
2214
  } catch {
2168
2215
  }
2169
2216
  }
2217
+ return merged;
2170
2218
  }
2171
2219
  function findPackageVersionFromModule(specifier, fallback) {
2172
2220
  try {
@@ -2449,6 +2497,7 @@ function createCsszyxPlugins(options = {}) {
2449
2497
  const cacheEnabled = cacheRequested && cacheVersionsKnown;
2450
2498
  const varMangleMapMaxBytes = resolveVarMangleMapMaxBytes();
2451
2499
  const globalVarMangleConfig = options.production?.mangleGlobalVars;
2500
+ const globalVarSourceTrackingEnabled = shouldTrackGlobalVarSources(globalVarMangleConfig);
2452
2501
  const globalVarAliasPrefix = globalVarMangleConfig?.aliasPrefix ?? CSSZYX_GLOBAL_ALIAS_PREFIX;
2453
2502
  const encodedGlobalVarAliasPrefix = encodeURIComponent(globalVarAliasPrefix);
2454
2503
  const earlyGlobalVarAliasEntries = createEarlyGlobalVarAliasEntries(
@@ -2474,21 +2523,25 @@ function createCsszyxPlugins(options = {}) {
2474
2523
  defaultParser: DEFAULT_BUILD_CONFIG.parser ?? "rust",
2475
2524
  isRustAvailable: isRustTransformAvailable
2476
2525
  });
2477
- if (parserDegraded && !_hasWarnedNativeFallback) {
2478
- _hasWarnedNativeFallback = true;
2479
- console.warn(
2480
- "[csszyx] No prebuilt native binary (@csszyx/core-*) is available for this platform, so the default `rust` parser fell back to `oxc`. Output classes are identical (parity-tested); only parse speed differs. To use the native engine, install the matching @csszyx/core-<platform> package (or do not omit optional dependencies). Set `build.parser` explicitly to silence this."
2481
- );
2482
- }
2483
- if (!_hasLoggedActiveParser) {
2484
- _hasLoggedActiveParser = true;
2485
- const detail = parserDegraded ? "oxc (degraded from default `rust`: no native binary for this platform)" : parserMode === "rust" ? "rust (native engine)" : parserMode;
2486
- console.warn(`[csszyx] active parser: ${detail}`);
2526
+ function announceActiveParser() {
2527
+ if (parserDegraded && !_hasWarnedNativeFallback) {
2528
+ _hasWarnedNativeFallback = true;
2529
+ console.warn(
2530
+ "[csszyx] No prebuilt native binary (@csszyx/core-*) is available for this platform, so the default `rust` parser fell back to `oxc`. Output classes are identical (parity-tested); only parse speed differs. To use the native engine, install the matching @csszyx/core-<platform> package (or do not omit optional dependencies). Set `build.parser` explicitly to silence this."
2531
+ );
2532
+ }
2533
+ if (!_loggedActiveParsers.has(parserMode)) {
2534
+ _loggedActiveParsers.add(parserMode);
2535
+ const detail = parserDegraded ? "oxc (degraded from default `rust`: no native binary for this platform)" : parserMode === "rust" ? "rust (native engine)" : parserMode;
2536
+ console.warn(`[csszyx] active parser: ${detail}`);
2537
+ }
2487
2538
  }
2488
2539
  let evictedCacheRoot = null;
2489
2540
  const transformMemoryCache = /* @__PURE__ */ new Map();
2541
+ let transformMemoryCacheCodeChars = 0;
2490
2542
  const state = {
2491
2543
  classes: /* @__PURE__ */ new Set(),
2544
+ parsedTheme: null,
2492
2545
  sawTailwindEntry: false,
2493
2546
  sawAnyCss: false,
2494
2547
  tailwindWarningEmitted: false,
@@ -2516,7 +2569,16 @@ function createCsszyxPlugins(options = {}) {
2516
2569
  state.varMangleEntriesByFile.set(GLOBAL_VAR_ALIAS_MAP_OWNER, earlyGlobalVarAliasEntries);
2517
2570
  }
2518
2571
  const SAFELIST_FILENAME = "csszyx-classes.html";
2519
- const SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([".tsx", ".jsx", ".ts", ".js"]);
2572
+ const SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([
2573
+ ".tsx",
2574
+ ".jsx",
2575
+ ".ts",
2576
+ ".js",
2577
+ ".mjs",
2578
+ ".cjs",
2579
+ ".mts",
2580
+ ".cts"
2581
+ ]);
2520
2582
  const IGNORE_DIRS = /* @__PURE__ */ new Set(["node_modules", ".next", ".git", "dist", "build", ".turbo"]);
2521
2583
  function isUserExcluded(id) {
2522
2584
  return matchesAnyPattern(id, options.exclude, state.rootDir);
@@ -2558,6 +2620,12 @@ function createCsszyxPlugins(options = {}) {
2558
2620
  assertGlobalVarPlanMatchesEarlyAliases(result, earlyGlobalVarAliasEntries);
2559
2621
  return result;
2560
2622
  }
2623
+ function trackGlobalVarSourceFile(filename, code) {
2624
+ if (!globalVarSourceTrackingEnabled) {
2625
+ return;
2626
+ }
2627
+ recordGlobalVarSourceFile(state, filename, code);
2628
+ }
2561
2629
  let compileSourceDirs = [];
2562
2630
  let compileSourceDirsRoot = null;
2563
2631
  function refreshCompileSourceDirs() {
@@ -2578,7 +2646,7 @@ function createCsszyxPlugins(options = {}) {
2578
2646
  return isHardIgnoredPath(id, compileSourceDirs);
2579
2647
  }
2580
2648
  function shouldProcessSource(id) {
2581
- return !isHardIgnored(id) && !isUserExcluded(id) && isUserIncluded(id) && (/\.[tj]sx?(\?.*)?$/.test(id) || id.endsWith(".vue") || id.endsWith(".svelte"));
2649
+ return !isHardIgnored(id) && !isUserExcluded(id) && isUserIncluded(id) && (/\.([cm]?[tj]s|[tj]sx)(\?.*)?$/.test(id) || id.endsWith(".vue") || id.endsWith(".svelte"));
2582
2650
  }
2583
2651
  function shouldProcessCss(id) {
2584
2652
  return !isHardIgnored(id) && !isUserExcluded(id) && /\.css(\?.*)?$/.test(id);
@@ -2759,21 +2827,28 @@ function createCsszyxPlugins(options = {}) {
2759
2827
  filePath: file.filePath,
2760
2828
  result: transformConfiguredSource(file.content, file.filePath)
2761
2829
  });
2762
- } catch {
2830
+ } catch (err) {
2831
+ console.warn(
2832
+ `[csszyx] prescan skipped ${file.filePath}: transform failed, so none of its classes reached the safelist. ${err instanceof Error ? err.message : String(err)}`
2833
+ );
2763
2834
  }
2764
2835
  }
2765
2836
  return results;
2766
2837
  }
2767
2838
  function rememberTransformCacheEntry(key, result) {
2768
- transformMemoryCache.delete(key);
2769
- transformMemoryCache.set(key, result);
2770
- if (transformMemoryCache.size <= TRANSFORM_MEMORY_CACHE_MAX_ENTRIES) {
2771
- return;
2772
- }
2773
- const oldest = transformMemoryCache.keys().next().value;
2774
- if (oldest) {
2775
- transformMemoryCache.delete(oldest);
2839
+ const existing = transformMemoryCache.get(key);
2840
+ if (existing) {
2841
+ transformMemoryCacheCodeChars -= existing.code.length;
2842
+ transformMemoryCache.delete(key);
2776
2843
  }
2844
+ transformMemoryCache.set(key, result);
2845
+ transformMemoryCacheCodeChars += result.code.length;
2846
+ transformMemoryCacheCodeChars = evictMemoryCacheToBudget(
2847
+ transformMemoryCache,
2848
+ transformMemoryCacheCodeChars,
2849
+ TRANSFORM_MEMORY_CACHE_MAX_ENTRIES,
2850
+ TRANSFORM_MEMORY_CACHE_MAX_CODE_CHARS
2851
+ );
2777
2852
  }
2778
2853
  function evictTransformCacheOnce() {
2779
2854
  if (!cacheEnabled) {
@@ -2881,6 +2956,12 @@ function createCsszyxPlugins(options = {}) {
2881
2956
  scanDir(sourceDir);
2882
2957
  }
2883
2958
  for (const { filePath, result } of transformPrescanSources(prescanSources)) {
2959
+ if (result.classes.size === 0 && result.rawClassNames.size === 0 && result.diagnostics.some((d) => d.includes("[csszyx] parse error in "))) {
2960
+ console.warn(
2961
+ `[csszyx] prescan skipped ${filePath}: the file failed to parse, so none of its classes reached the safelist. Fix the syntax error (or check the file extension matches its contents).`
2962
+ );
2963
+ continue;
2964
+ }
2884
2965
  if (!result.transformed && result.classes.size === 0) {
2885
2966
  continue;
2886
2967
  }
@@ -3071,7 +3152,7 @@ function createCsszyxPlugins(options = {}) {
3071
3152
  * @returns true only for csszyx virtual modules
3072
3153
  */
3073
3154
  loadInclude(id) {
3074
- return id === RESOLVED_VIRTUAL_MODULE_ID || id === RESOLVED_VIRTUAL_CHECKSUM_ID;
3155
+ return id === RESOLVED_VIRTUAL_MODULE_ID || id === RESOLVED_VIRTUAL_CHECKSUM_ID || id === RESOLVED_THEME_GROUPS_VIRTUAL_ID;
3075
3156
  },
3076
3157
  /**
3077
3158
  * Loads virtual module content — generates mangle map or checksum module code.
@@ -3092,6 +3173,15 @@ function createCsszyxPlugins(options = {}) {
3092
3173
  finalizeMangleMap();
3093
3174
  return createChecksumModule(state.checksum);
3094
3175
  }
3176
+ if (id === RESOLVED_THEME_GROUPS_VIRTUAL_ID) {
3177
+ const theme = state.parsedTheme;
3178
+ return createThemeGroupsModule({
3179
+ colors: theme?.colors ?? [],
3180
+ textSizes: theme?.textSizes ?? [],
3181
+ fontFamilies: theme?.fonts ?? [],
3182
+ fontWeights: theme?.fontWeights ?? []
3183
+ });
3184
+ }
3095
3185
  return null;
3096
3186
  },
3097
3187
  /**
@@ -3114,11 +3204,12 @@ function createCsszyxPlugins(options = {}) {
3114
3204
  * @returns transformed code with source map, or null if no changes were made
3115
3205
  */
3116
3206
  transform(code, id) {
3207
+ announceActiveParser();
3117
3208
  if (!shouldProcessCss(id) && !shouldProcessSource(id)) {
3118
3209
  return null;
3119
3210
  }
3120
3211
  if (shouldProcessSource(id)) {
3121
- recordGlobalVarSourceFile(state, id, code);
3212
+ trackGlobalVarSourceFile(id, code);
3122
3213
  }
3123
3214
  if (/\.[tj]sx?(\?.*)?$/.test(id)) {
3124
3215
  assertNoRSCBoundaryViolation(code, id);
@@ -3248,6 +3339,11 @@ function createCsszyxPlugins(options = {}) {
3248
3339
  transformed = true;
3249
3340
  }
3250
3341
  }
3342
+ if (/\bszcn\s*\(/.test(code) && !transformedCode.includes(THEME_GROUPS_VIRTUAL_ID) && shouldProcessSource(id)) {
3343
+ transformedCode = `import '${THEME_GROUPS_VIRTUAL_ID}';
3344
+ ${transformedCode}`;
3345
+ transformed = true;
3346
+ }
3251
3347
  if (/\.[tj]sx?(\?.*)?$/.test(id)) {
3252
3348
  assertNoRSCBoundaryViolation(transformedCode, id);
3253
3349
  const record = createRSCModuleRecord(transformedCode, id);
@@ -3324,13 +3420,14 @@ function createCsszyxPlugins(options = {}) {
3324
3420
  */
3325
3421
  webpack(compiler) {
3326
3422
  compiler.hooks.beforeCompile.tap("csszyx:prescan", () => {
3423
+ announceActiveParser();
3327
3424
  const root = compiler.context || process.cwd();
3328
3425
  state.rootDir = root;
3329
3426
  evictTransformCacheOnce();
3330
3427
  if (state.classes.size === 0) {
3331
3428
  prescanAndWriteClasses();
3332
3429
  }
3333
- runThemeScan(root, options.build?.scanCss);
3430
+ state.parsedTheme = runThemeScan(root, options.build?.scanCss) ?? state.parsedTheme;
3334
3431
  });
3335
3432
  if (options.build?.scanCss) {
3336
3433
  compiler.hooks.thisCompilation.tap("csszyx:theme-deps", (compilation) => {
@@ -3348,6 +3445,7 @@ function createCsszyxPlugins(options = {}) {
3348
3445
  * @param config - the resolved Vite configuration object
3349
3446
  */
3350
3447
  configResolved(config) {
3448
+ announceActiveParser();
3351
3449
  const root = config.root || process.cwd();
3352
3450
  state.rootDir = root;
3353
3451
  if (config.command === "serve") {
@@ -3355,7 +3453,7 @@ function createCsszyxPlugins(options = {}) {
3355
3453
  }
3356
3454
  evictTransformCacheOnce();
3357
3455
  prescanAndWriteClasses();
3358
- runThemeScan(root, options.build?.scanCss);
3456
+ state.parsedTheme = runThemeScan(root, options.build?.scanCss) ?? state.parsedTheme;
3359
3457
  },
3360
3458
  /**
3361
3459
  * Vite HMR hook: re-runs theme scan when a watched CSS file changes,
@@ -3367,7 +3465,13 @@ function createCsszyxPlugins(options = {}) {
3367
3465
  if (scanCss) {
3368
3466
  const root = ctx.server.config.root || process.cwd();
3369
3467
  if (matchesAnyPattern(ctx.file, scanCss, root)) {
3370
- runThemeScan(root, scanCss);
3468
+ state.parsedTheme = runThemeScan(root, scanCss) ?? state.parsedTheme;
3469
+ const themeGroupsModule = ctx.server.moduleGraph.getModuleById(
3470
+ RESOLVED_THEME_GROUPS_VIRTUAL_ID
3471
+ );
3472
+ if (themeGroupsModule) {
3473
+ ctx.server.moduleGraph.invalidateModule(themeGroupsModule);
3474
+ }
3371
3475
  }
3372
3476
  }
3373
3477
  if (!shouldProcessSource(ctx.file)) {
@@ -3380,7 +3484,7 @@ function createCsszyxPlugins(options = {}) {
3380
3484
  return;
3381
3485
  }
3382
3486
  if (!fileContent.includes("sz=") && !fileContent.includes("szs=") && !/\bsz\s*:\s*["'{]/.test(fileContent)) {
3383
- recordGlobalVarSourceFile(state, ctx.file, fileContent);
3487
+ trackGlobalVarSourceFile(ctx.file, fileContent);
3384
3488
  recordFileVarMangleEntries(state, ctx.file, []);
3385
3489
  recordFileCSSVariableMetrics(state, ctx.file, null);
3386
3490
  return;
@@ -3394,19 +3498,19 @@ function createCsszyxPlugins(options = {}) {
3394
3498
  performance.now() - hmrTransformStarted
3395
3499
  );
3396
3500
  } catch {
3397
- recordGlobalVarSourceFile(state, ctx.file, fileContent);
3501
+ trackGlobalVarSourceFile(ctx.file, fileContent);
3398
3502
  recordFileVarMangleEntries(state, ctx.file, []);
3399
3503
  recordFileCSSVariableMetrics(state, ctx.file, null);
3400
3504
  return;
3401
3505
  }
3402
3506
  if (!result.transformed) {
3403
- recordGlobalVarSourceFile(state, ctx.file, fileContent);
3507
+ trackGlobalVarSourceFile(ctx.file, fileContent);
3404
3508
  recordFileVarMangleEntries(state, ctx.file, []);
3405
3509
  recordFileCSSVariableMetrics(state, ctx.file, null);
3406
3510
  return;
3407
3511
  }
3408
3512
  const sizeBefore = state.classes.size;
3409
- recordGlobalVarSourceFile(state, ctx.file, fileContent);
3513
+ trackGlobalVarSourceFile(ctx.file, fileContent);
3410
3514
  for (const cls of result.classes) {
3411
3515
  addSafelistClass(cls);
3412
3516
  state.ownedClasses.add(cls);
@@ -3791,4 +3895,4 @@ const esbuildPlugin = (options = {}) => {
3791
3895
  };
3792
3896
  };
3793
3897
 
3794
- export { isRSCServerModule as A, isTailwindReservedGlobalVar as B, mangleCodeClassesSync as C, mangleHybridHazardMessage as D, mergeThemes as E, missingTailwindEntryMessage as F, normalizeGlobalVarAliasesForCache as G, parseThemeBlocks as H, planGlobalVarAliases as I, readGlobalVarScanCache as J, resolveCompileSourceDirs as K, resolveGlobalVarScanCacheDir as L, resolveNativeCacheIdentity as M, rewriteGlobalVarCssAliases as N, rollupPlugin as O, scanGlobalVarCss as P, shouldEmitWarning as Q, shouldWarnMissingTailwindEntry as R, shouldWarnUnscopedMonorepo as S, skippedSzFilesMessage as T, unscopedMonorepoMessage as U, validateGlobalVarAliasInputs as V, vitePlugin as W, webpackPlugin as X, writeGlobalVarScanCache as Y, appendTailwindSourceDirective as a, assertNoRSCBoundaryViolation as b, assertNoRSCGraphViolation as c, collectMangleHybridHazards as d, computeSafelistRelPath as e, createGlobalVarAliasValidationOptions as f, createGlobalVarMapAssetSource as g, createGlobalVarScanCacheKey as h, createRSCModuleRecord as i, cssHasContentScope as j, cssImportsTailwind as k, deleteRSCModuleRecord as l, esbuildPlugin as m, extractGlobalVarAliasesForManifest as n, fileMayContainSafelistableSz as o, findRSCBoundaryViolation as p, findRSCGraphViolation as q, hasInjectableTailwindCandidate as r, hasTokens as s, hasUseClientDirective as t, unplugin as u, hasUseServerDirective as v, isCompileSourceOptedIn as w, isHardIgnoredPath as x, isMonorepoPackage as y, isPackagesSkippedSource as z };
3898
+ export { isRSCServerModule as A, isTailwindReservedGlobalVar as B, mangleCodeClassesSync as C, mangleHybridHazardMessage as D, mergeThemes as E, missingTailwindEntryMessage as F, normalizeGlobalVarAliasesForCache as G, parseThemeBlocks as H, planGlobalVarAliases as I, readGlobalVarScanCache as J, recordGlobalVarSourceFile as K, resolveCompileSourceDirs as L, resolveGlobalVarScanCacheDir as M, resolveNativeCacheIdentity as N, rewriteGlobalVarCssAliases as O, rollupPlugin as P, scanGlobalVarCss as Q, shouldEmitWarning as R, shouldTrackGlobalVarSources as S, shouldWarnMissingTailwindEntry as T, shouldWarnUnscopedMonorepo as U, skippedSzFilesMessage as V, unscopedMonorepoMessage as W, validateGlobalVarAliasInputs as X, vitePlugin as Y, webpackPlugin as Z, writeGlobalVarScanCache as _, appendTailwindSourceDirective as a, assertNoRSCBoundaryViolation as b, assertNoRSCGraphViolation as c, collectMangleHybridHazards as d, computeSafelistRelPath as e, createGlobalVarAliasValidationOptions as f, createGlobalVarMapAssetSource as g, createGlobalVarScanCacheKey as h, createRSCModuleRecord as i, cssHasContentScope as j, cssImportsTailwind as k, deleteRSCModuleRecord as l, esbuildPlugin as m, extractGlobalVarAliasesForManifest as n, fileMayContainSafelistableSz as o, findRSCBoundaryViolation as p, findRSCGraphViolation as q, hasInjectableTailwindCandidate as r, hasTokens as s, hasUseClientDirective as t, unplugin as u, hasUseServerDirective as v, isCompileSourceOptedIn as w, isHardIgnoredPath as x, isMonorepoPackage as y, isPackagesSkippedSource as z };
@@ -199,8 +199,22 @@ function listJsonFiles(dir) {
199
199
  }
200
200
  return files;
201
201
  }
202
+ function evictMemoryCacheToBudget(cache, totalCodeChars, maxEntries, maxCodeChars) {
203
+ let total = totalCodeChars;
204
+ while (cache.size > maxEntries || total > maxCodeChars && cache.size > 1) {
205
+ const oldest = cache.keys().next().value;
206
+ if (oldest === void 0) {
207
+ break;
208
+ }
209
+ const evicted = cache.get(oldest);
210
+ cache.delete(oldest);
211
+ total -= evicted?.code.length ?? 0;
212
+ }
213
+ return total;
214
+ }
202
215
 
203
216
  exports.createTransformCacheKey = createTransformCacheKey;
217
+ exports.evictMemoryCacheToBudget = evictMemoryCacheToBudget;
204
218
  exports.evictOldTransformCacheEntries = evictOldTransformCacheEntries;
205
219
  exports.readTransformCache = readTransformCache;
206
220
  exports.resolveTransformCacheDir = resolveTransformCacheDir;