@csszyx/unplugin 0.11.10 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,17 +6,18 @@ import * as path from 'node:path';
6
6
  import { dirname } from 'node:path';
7
7
  import { performance } from 'node:perf_hooks';
8
8
  import { fileURLToPath } from 'node:url';
9
- import { scanGlobalVarUsages, sortStrings as sortStrings$1, ensureRustTransformAvailable, transformSourceCode, transformRust, transformOxc, ASTBudgetExceededError, transformRustBatch, transform, isRustTransformAvailable } from '@csszyx/compiler';
9
+ import { scanGlobalVarUsages, extractSzvRegistryEntries, sortStrings as sortStrings$1, szFallbackConsequenceOf, ensureRustTransformAvailable, transformSourceCode, transformRust, transformOxc, ASTBudgetExceededError, transformRustBatch, transform, isRustTransformAvailable } from '@csszyx/compiler';
10
10
  import { encode, compute_mangle_checksum } from '@csszyx/core';
11
11
  import { getNativePackageName } from '@csszyx/core/native';
12
12
  import { preprocess as preprocess$1 } from '@csszyx/svelte-adapter';
13
13
  import { isTailwindReservedCustomProperty, CSSZYX_GLOBAL_ALIAS_PREFIX, isCsszyxGlobalAliasCustomProperty, DEFAULT_BUILD_CONFIG, validateGlobalVarMangleConfig } from '@csszyx/types';
14
14
  import { preprocess } from '@csszyx/vue-adapter';
15
15
  import { createUnplugin } from 'unplugin';
16
- import { n as normalizePathSeparators, r as resolveTransformCacheDir, c as createTransformCacheKey, w as writeTransformCache, e as evictOldTransformCacheEntries, a as readTransformCache, d as evictMemoryCacheToBudget, b as babelFallbackReason } from './unplugin.fOnGXWgS.mjs';
16
+ import { n as normalizePathSeparators, r as resolveTransformCacheDir, c as createTransformCacheKey, w as writeTransformCache, e as evictOldTransformCacheEntries, a as readTransformCache, d as evictMemoryCacheToBudget, b as babelFallbackReason } from './unplugin.CDqY7kmk.mjs';
17
17
  import { mangleCSSSync } from '../css-mangler.mjs';
18
- import { i as importsRuntimeHelper, f as findRuntimeImportClause, a as insertAfterUseDirective } from './unplugin.Lhzkcj-A.mjs';
18
+ import { a as importsRuntimeHelper, f as findRuntimeImportClause, r as runtimeHelperGroupsFromUsage, b as insertAfterUseDirective } from './unplugin.CBMJufQ8.mjs';
19
19
  import { s as sortStrings, a as replaceEveryLiteral, u as unicodeEscape, b as escapeDoubleQuotedString, c as escapeSingleQuotedString, e as escapeHtmlAttribute, r as renderTailwindScannerCandidates } from './unplugin.B3XoSRB8.mjs';
20
+ import { gzipSync } from 'node:zlib';
20
21
  import postcss from 'postcss';
21
22
  import valueParser from 'postcss-value-parser';
22
23
 
@@ -1863,17 +1864,19 @@ function injectMangleMapScript(html, mangleMap, options = {}) {
1863
1864
  const {
1864
1865
  prettyPrint = false,
1865
1866
  varMangleMap = {},
1866
- globalVarAliasPrefix = CSSZYX_GLOBAL_ALIAS_PREFIX
1867
+ globalVarAliasPrefix = CSSZYX_GLOBAL_ALIAS_PREFIX,
1868
+ installRuntimeObject = true
1867
1869
  } = options;
1868
1870
  const checksumMap = createHydrationMangleMap(mangleMap, varMangleMap);
1869
1871
  const jsonContent = safeJsonForScriptTag(checksumMap, prettyPrint);
1870
- const classMapContent = safeJsonForScriptTag(mangleMap);
1871
1872
  const varMapContent = safeJsonForScriptTag(varMangleMap);
1873
+ const reuseChecksumPayload = Object.keys(varMangleMap).length === 0;
1874
+ const classMapExpr = reuseChecksumPayload ? '(function(){var e=document.getElementById("__CSSZYX_MANGLE_MAP__");return e?JSON.parse(e.textContent):{}})()' : safeJsonForScriptTag(mangleMap);
1872
1875
  const scriptTag = `<script id="__CSSZYX_MANGLE_MAP__" type="application/json">${jsonContent}<\/script>`;
1873
1876
  const prefixContent = safeJsonForScriptTag(globalVarAliasPrefix);
1874
- const debugScript = `<script>(function(){var m=${classMapContent};var vm=${varMapContent};var gp=${prefixContent};var r={};var vr={};for(var k in m)r[m[k]]=k;for(var vk in vm){var vv=vm[vk];var vs=Array.isArray(vv)?vv:[vv];for(var vi=0;vi<vs.length;vi++)(vr[vs[vi]]||(vr[vs[vi]]=[])).push(vk)}var cs=document.documentElement.getAttribute("data-sz-checksum")||"";window.__csszyx={mangleMap:m,varMangleMap:vm,checksum:cs,decode:function(c){return r[c]},encode:function(c){return m[c]},decodeVar:function(v){return vr[v]||[]},encodeVar:function(v){return vm[v]},decodeGlobalVar:function(v){var a=vr[v]||[];return v.indexOf(gp)===0?a[0]:void 0},decodeAll:function(el){return(el.className||"").split(" ").map(function(c){return r[c]||c})}}})()<\/script>`;
1875
- const combined = `${scriptTag}
1876
- ${debugScript}`;
1877
+ const debugScript = `<script>(function(){var m=${classMapExpr};var vm=${varMapContent};var gp=${prefixContent};var r={};var vr={};for(var k in m)r[m[k]]=k;for(var vk in vm){var vv=vm[vk];var vs=Array.isArray(vv)?vv:[vv];for(var vi=0;vi<vs.length;vi++)(vr[vs[vi]]||(vr[vs[vi]]=[])).push(vk)}var cs=document.documentElement.getAttribute("data-sz-checksum")||"";window.__csszyx={mangleMap:m,varMangleMap:vm,checksum:cs,decode:function(c){return r[c]},encode:function(c){return m[c]},decodeVar:function(v){return vr[v]||[]},encodeVar:function(v){return vm[v]},decodeGlobalVar:function(v){var a=vr[v]||[];return v.indexOf(gp)===0?a[0]:void 0},decodeAll:function(el){return(el.className||"").split(" ").map(function(c){return r[c]||c})}}})()<\/script>`;
1878
+ const combined = installRuntimeObject ? `${scriptTag}
1879
+ ${debugScript}` : scriptTag;
1877
1880
  if (html.includes("</head>")) {
1878
1881
  return html.replace("</head>", `${combined}
1879
1882
  </head>`);
@@ -1978,6 +1981,42 @@ function escapeForDoubleQuotedString(value) {
1978
1981
  return escapeDoubleQuotedString(value);
1979
1982
  }
1980
1983
 
1984
+ function createMangleSizeAccount() {
1985
+ return { cssGzBefore: 0, cssGzAfter: 0, channels: /* @__PURE__ */ new Set() };
1986
+ }
1987
+ function resetMangleSizeAccount(account) {
1988
+ account.cssGzBefore = 0;
1989
+ account.cssGzAfter = 0;
1990
+ account.channels.clear();
1991
+ }
1992
+ function gzipBytes(text) {
1993
+ if (text.length === 0) return 0;
1994
+ return gzipSync(Buffer.from(text, "utf8")).length;
1995
+ }
1996
+ function recordCssPair(account, before, after) {
1997
+ if (before === after) {
1998
+ const bytes = gzipBytes(before);
1999
+ account.cssGzBefore += bytes;
2000
+ account.cssGzAfter += bytes;
2001
+ return;
2002
+ }
2003
+ account.cssGzBefore += gzipBytes(before);
2004
+ account.cssGzAfter += gzipBytes(after);
2005
+ }
2006
+ function computeMangleSizeVerdict(account, mapPayload) {
2007
+ const channels = sortStrings(account.channels);
2008
+ const mapCost = gzipBytes(mapPayload) * channels.length;
2009
+ const cssSaving = account.cssGzBefore - account.cssGzAfter;
2010
+ return { mapCost, cssSaving, net: mapCost - cssSaving, channels };
2011
+ }
2012
+ function mangleSizeMessage(verdict) {
2013
+ if (verdict.channels.length === 0) return null;
2014
+ if (verdict.net <= 0) return null;
2015
+ const cssPart = verdict.cssSaving >= 0 ? `the mangled CSS saves ${verdict.cssSaving} B` : `the mangled CSS COSTS ${-verdict.cssSaving} B (short tokens compress worse than the names they replaced)`;
2016
+ const channelPart = verdict.channels.length > 1 ? `${verdict.channels.join(" + ")} (${verdict.channels.length} copies)` : verdict.channels[0];
2017
+ return `[csszyx] production.mangle is making this build BIGGER: +${verdict.net} B gzipped. The runtime mangle map costs ${verdict.mapCost} B via ${channelPart}, while ${cssPart}. Mangling is a name-obfuscation feature; over a compressed response it does not reduce payload, because utility class names compress far better than the map they need. If you enabled it for size, set \`production.mangle: false\`. If you enabled it to hide class names, this is the expected price and you can ignore this. Narrowing \`production.mangleMapDelivery\` removes a map copy when only one channel is needed. (Measured on CSS and the map; class shortening inside JS chunks is not counted, so the real net is slightly better than this figure.)`;
2018
+ }
2019
+
1981
2020
  function isParserMode(value) {
1982
2021
  return value === "rust" || value === "oxc" || value === "babel";
1983
2022
  }
@@ -2022,6 +2061,41 @@ function isSameFileVersion(before, after) {
2022
2061
  return before.dev === after.dev && before.ino === after.ino && before.size === after.size && before.mtimeNs === after.mtimeNs && before.ctimeNs === after.ctimeNs;
2023
2062
  }
2024
2063
 
2064
+ function recordSzvRegistryFile(registry, filePath, content) {
2065
+ const key = normalizePathSeparators(filePath);
2066
+ const qualifies = content.includes("szv(") && content.includes("export");
2067
+ const entries = qualifies ? extractSzvRegistryEntries(content, filePath) : [];
2068
+ if (entries.length === 0) {
2069
+ registry.delete(key);
2070
+ return;
2071
+ }
2072
+ const byName = {};
2073
+ for (const entry of entries) {
2074
+ byName[entry.exportName] = entry.config;
2075
+ }
2076
+ registry.set(key, byName);
2077
+ }
2078
+ const SPECIFIER_PROBES = ["", ".ts", ".tsx", ".js", ".jsx", "/index.ts", "/index.tsx"];
2079
+ function resolveCrossModuleStaticsFor(registry, filename, source) {
2080
+ if (registry.size === 0 || !source.includes("from")) return void 0;
2081
+ const directory = path.dirname(filename);
2082
+ let resolved;
2083
+ for (const match of source.matchAll(/from\s*['"](\.[^'"]*)['"]/g)) {
2084
+ const specifier = match[1];
2085
+ if (resolved?.[specifier] !== void 0) continue;
2086
+ const base = normalizePathSeparators(path.resolve(directory, specifier));
2087
+ for (const probe of SPECIFIER_PROBES) {
2088
+ const entries = registry.get(`${base}${probe}`);
2089
+ if (entries !== void 0) {
2090
+ resolved ??= {};
2091
+ resolved[specifier] = entries;
2092
+ break;
2093
+ }
2094
+ }
2095
+ }
2096
+ return resolved;
2097
+ }
2098
+
2025
2099
  function generateThemeDts(opts) {
2026
2100
  const { theme, sourceFiles } = opts;
2027
2101
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
@@ -2137,7 +2211,7 @@ export default checksum;
2137
2211
  `;
2138
2212
  }
2139
2213
  function isVirtualModule(id) {
2140
- return id === VIRTUAL_MODULE_ID || id === VIRTUAL_CHECKSUM_ID || id === THEME_GROUPS_VIRTUAL_ID;
2214
+ return id === VIRTUAL_MODULE_ID || id === VIRTUAL_CHECKSUM_ID || id === THEME_GROUPS_VIRTUAL_ID || id === MANGLE_RUNTIME_VIRTUAL_ID;
2141
2215
  }
2142
2216
  function resolveVirtualModule(id) {
2143
2217
  if (id === VIRTUAL_MODULE_ID) {
@@ -2149,8 +2223,56 @@ function resolveVirtualModule(id) {
2149
2223
  if (id === THEME_GROUPS_VIRTUAL_ID) {
2150
2224
  return RESOLVED_THEME_GROUPS_VIRTUAL_ID;
2151
2225
  }
2226
+ if (id === MANGLE_RUNTIME_VIRTUAL_ID) {
2227
+ return RESOLVED_MANGLE_RUNTIME_VIRTUAL_ID;
2228
+ }
2152
2229
  return void 0;
2153
2230
  }
2231
+ const MANGLE_RUNTIME_VIRTUAL_ID = "virtual:csszyx/mangle-runtime";
2232
+ const RESOLVED_MANGLE_RUNTIME_VIRTUAL_ID = `\0${MANGLE_RUNTIME_VIRTUAL_ID}`;
2233
+ const MANGLE_MAP_PLACEHOLDER = "___CSSZYX_MANGLE_MAP___";
2234
+ const VAR_MANGLE_MAP_PLACEHOLDER = "___CSSZYX_VAR_MANGLE_MAP___";
2235
+ const CHECKSUM_PLACEHOLDER = "___CSSZYX_CHECKSUM___";
2236
+ function createMangleRuntimeModule(globalVarAliasPrefix) {
2237
+ return `/**
2238
+ * Auto-generated by csszyx: installs the runtime mangle map from the bundle.
2239
+ *
2240
+ * @generated
2241
+ */
2242
+
2243
+ const m = ${MANGLE_MAP_PLACEHOLDER};
2244
+ const vm = ${VAR_MANGLE_MAP_PLACEHOLDER};
2245
+ const gp = ${JSON.stringify(globalVarAliasPrefix)};
2246
+ const checksum = "${CHECKSUM_PLACEHOLDER}";
2247
+
2248
+ if (typeof window !== 'undefined' && !window.__csszyx) {
2249
+ const r = {};
2250
+ const vr = {};
2251
+ for (const k in m) r[m[k]] = k;
2252
+ for (const vk in vm) {
2253
+ const vv = vm[vk];
2254
+ const vs = Array.isArray(vv) ? vv : [vv];
2255
+ for (const v of vs) (vr[v] || (vr[v] = [])).push(vk);
2256
+ }
2257
+ window.__csszyx = {
2258
+ mangleMap: m,
2259
+ varMangleMap: vm,
2260
+ checksum,
2261
+ decode: (c) => r[c],
2262
+ encode: (c) => m[c],
2263
+ decodeVar: (v) => vr[v] || [],
2264
+ encodeVar: (v) => vm[v],
2265
+ decodeGlobalVar: (v) => {
2266
+ const a = vr[v] || [];
2267
+ return v.indexOf(gp) === 0 ? a[0] : undefined;
2268
+ },
2269
+ decodeAll: (el) => (el.className || '').split(' ').map((c) => r[c] || c),
2270
+ };
2271
+ }
2272
+
2273
+ export {};
2274
+ `;
2275
+ }
2154
2276
  function createThemeGroupsModule(tokens) {
2155
2277
  const payload = JSON.stringify({
2156
2278
  colors: tokens.colors,
@@ -2175,9 +2297,6 @@ function registerWebpackAssetProcessor(compiler, processAssets) {
2175
2297
  );
2176
2298
  });
2177
2299
  }
2178
- const CHECKSUM_PLACEHOLDER = "___CSSZYX_CHECKSUM___";
2179
- const MANGLE_MAP_PLACEHOLDER = "___CSSZYX_MANGLE_MAP___";
2180
- const VAR_MANGLE_MAP_PLACEHOLDER = "___CSSZYX_VAR_MANGLE_MAP___";
2181
2300
  const UNKNOWN_PACKAGE_VERSION = "0.0.0";
2182
2301
  const TRANSFORM_CACHE_MAX_AGE_MS = 30 * 24 * 60 * 60 * 1e3;
2183
2302
  const TRANSFORM_CACHE_MAX_ENTRIES = 1e4;
@@ -2366,6 +2485,13 @@ function shouldEmitWarning(quiet, devOnly, isProduction) {
2366
2485
  }
2367
2486
  return true;
2368
2487
  }
2488
+ function shouldEmitMissingCssFallback(quiet, message) {
2489
+ return !quiet && szFallbackConsequenceOf(message) === "missing-css";
2490
+ }
2491
+ function emitMissingCssFallback(quiet, message, id, emit) {
2492
+ if (shouldEmitMissingCssFallback(quiet, message)) emit(`[csszyx] ${id}
2493
+ ${message}`);
2494
+ }
2369
2495
  function normalizeForMatch(p) {
2370
2496
  const n = normalizePathSeparators(p);
2371
2497
  return n.length > 1 && n.endsWith("/") ? n.slice(0, -1) : n;
@@ -2433,6 +2559,30 @@ function fileMayContainSafelistableSz(content) {
2433
2559
  function mangleEligibleClasses(ownedClasses, authoredClasses) {
2434
2560
  return sortStrings$1([...ownedClasses].filter((className) => !authoredClasses.has(className)));
2435
2561
  }
2562
+ const tokenByIndex = [];
2563
+ function tokenAt(index) {
2564
+ const cached = tokenByIndex[index];
2565
+ if (cached !== void 0) {
2566
+ return cached;
2567
+ }
2568
+ const fresh = encode(index);
2569
+ tokenByIndex[index] = fresh;
2570
+ return fresh;
2571
+ }
2572
+ function allocateMangleTokens(eligibleClasses, forbiddenTokens) {
2573
+ const map = {};
2574
+ let tokenIndex = 0;
2575
+ for (const className of eligibleClasses) {
2576
+ let token = tokenAt(tokenIndex);
2577
+ while (forbiddenTokens.has(token)) {
2578
+ tokenIndex++;
2579
+ token = tokenAt(tokenIndex);
2580
+ }
2581
+ map[className] = token;
2582
+ tokenIndex++;
2583
+ }
2584
+ return map;
2585
+ }
2436
2586
  function isPackagesSkippedSource(id, sourceDirs = []) {
2437
2587
  const p = normalizeForMatch(id);
2438
2588
  if (p.includes("node_modules")) {
@@ -3103,8 +3253,19 @@ ${errors.join("\n")}`
3103
3253
  }
3104
3254
  function createCsszyxPlugins(options = {}) {
3105
3255
  assertGlobalVarMangleConfig(options);
3106
- let manglingEnabled = options.production?.mangle !== false;
3256
+ let manglingEnabled = options.production?.mangle === true;
3257
+ let crossModuleRegistryEnabled = process.env.NODE_ENV !== "development";
3258
+ const szvCrossModuleRegistry = /* @__PURE__ */ new Map();
3107
3259
  const mangleReserved = new Set(options.production?.mangleExclude ?? []);
3260
+ const mangleMapDelivery = options.production?.mangleMapDelivery ?? "both";
3261
+ if (!["both", "html", "bundle"].includes(mangleMapDelivery)) {
3262
+ throw new Error(
3263
+ `[csszyx] production.mangleMapDelivery must be 'both', 'html' or 'bundle'; got ${JSON.stringify(mangleMapDelivery)}.`
3264
+ );
3265
+ }
3266
+ const deliverMapInHtml = mangleMapDelivery !== "bundle";
3267
+ const deliverMapInBundle = mangleMapDelivery !== "html";
3268
+ const sizeAccount = createMangleSizeAccount();
3108
3269
  const astBudgetOverride = options.build?.astBudgetLimit;
3109
3270
  const prescanAstBudget = astBudgetOverride ?? 5e5;
3110
3271
  const cacheRequested = (options.build?.cache ?? DEFAULT_BUILD_CONFIG.cache) !== false;
@@ -3330,6 +3491,14 @@ function createCsszyxPlugins(options = {}) {
3330
3491
  function transformConfiguredSource(source, filename, astBudget) {
3331
3492
  const compilerOptions = createCompilerOptions(astBudget);
3332
3493
  const effectiveFilename = normalizeSourceFilename(filename);
3494
+ const crossModuleStatics = resolveCrossModuleStaticsFor(
3495
+ szvCrossModuleRegistry,
3496
+ filename,
3497
+ source
3498
+ );
3499
+ if (crossModuleStatics !== void 0) {
3500
+ compilerOptions.crossModuleStatics = crossModuleStatics;
3501
+ }
3333
3502
  const cacheRoot = resolveTransformCacheDir(state.rootDir, options.build?.cacheDir);
3334
3503
  if (cacheEnabled) {
3335
3504
  evictTransformCacheOnce();
@@ -3441,6 +3610,10 @@ function createCsszyxPlugins(options = {}) {
3441
3610
  mangleVars: compilerOptions.mangleVars,
3442
3611
  mangleVarHoistMaxDepth: compilerOptions.mangleVarHoistMaxDepth,
3443
3612
  globalVarAliases: normalizeGlobalVarAliasesForCache(compilerOptions.globalVarAliases),
3613
+ // The registry entries fed to this file are part of its identity:
3614
+ // module A's config change must miss B's cached transform, or the
3615
+ // cache serves a stale table.
3616
+ crossModuleStatics: compilerOptions.crossModuleStatics === void 0 ? void 0 : JSON.stringify(compilerOptions.crossModuleStatics),
3444
3617
  filename: effectiveFilename,
3445
3618
  source
3446
3619
  };
@@ -3652,6 +3825,7 @@ function createCsszyxPlugins(options = {}) {
3652
3825
  }
3653
3826
  function prescanAndWriteClasses() {
3654
3827
  refreshCompileSourceDirs();
3828
+ szvCrossModuleRegistry.clear();
3655
3829
  const prescanStarted = performance.now();
3656
3830
  const discoveredClasses = /* @__PURE__ */ new Set();
3657
3831
  const rawDiscoveredClasses = /* @__PURE__ */ new Set();
@@ -3668,10 +3842,15 @@ function createCsszyxPlugins(options = {}) {
3668
3842
  return;
3669
3843
  }
3670
3844
  recordAuthoredClasses(content);
3845
+ recordSzvRegistryEntries(filePath, content);
3671
3846
  if (fileMayContainSafelistableSz(content)) {
3672
3847
  prescanSources.push({ filePath, content });
3673
3848
  }
3674
3849
  }
3850
+ function recordSzvRegistryEntries(filePath, content) {
3851
+ if (!crossModuleRegistryEnabled) return;
3852
+ recordSzvRegistryFile(szvCrossModuleRegistry, filePath, content);
3853
+ }
3675
3854
  function scanDir(dir) {
3676
3855
  let entries;
3677
3856
  try {
@@ -3830,18 +4009,15 @@ function createCsszyxPlugins(options = {}) {
3830
4009
  }
3831
4010
  }
3832
4011
  function finalizeMangleMap() {
3833
- const newMap = {};
3834
- let tokenIndex = 0;
3835
- for (const className of mangleEligibleClasses(state.ownedClasses, state.authoredClasses)) {
3836
- let token = encode(tokenIndex);
3837
- while (mangleReserved.has(token) || state.authoredClasses.has(token)) {
3838
- tokenIndex++;
3839
- token = encode(tokenIndex);
3840
- }
3841
- newMap[className] = token;
3842
- tokenIndex++;
3843
- }
3844
- state.mangleMap = newMap;
4012
+ const forbiddenTokens = /* @__PURE__ */ new Set([
4013
+ ...mangleReserved,
4014
+ ...state.authoredClasses,
4015
+ ...state.ownedClasses
4016
+ ]);
4017
+ state.mangleMap = allocateMangleTokens(
4018
+ mangleEligibleClasses(state.ownedClasses, state.authoredClasses),
4019
+ forbiddenTokens
4020
+ );
3845
4021
  assertVarMangleMapSize(state.varMangleMap, varMangleMapMaxBytes);
3846
4022
  state.checksum = compute_mangle_checksum(
3847
4023
  createHydrationMangleMap(state.mangleMap, state.varMangleMap)
@@ -3874,14 +4050,15 @@ function createCsszyxPlugins(options = {}) {
3874
4050
  if (result.includes(CHECKSUM_PLACEHOLDER)) {
3875
4051
  result = result.split(CHECKSUM_PLACEHOLDER).join(state.checksum);
3876
4052
  }
4053
+ const isEvalWrapped = result.includes("eval(") && result.includes("sourceURL=webpack");
3877
4054
  if (result.includes(MANGLE_MAP_PLACEHOLDER)) {
3878
4055
  const jsonMap = escapeJsonForInlineScript(JSON.stringify(state.mangleMap));
3879
- const escapedMap = result.includes("eval(") ? escapeForDoubleQuotedString(jsonMap) : jsonMap;
4056
+ const escapedMap = isEvalWrapped ? escapeForDoubleQuotedString(jsonMap) : jsonMap;
3880
4057
  result = result.split(MANGLE_MAP_PLACEHOLDER).join(escapedMap);
3881
4058
  }
3882
4059
  if (result.includes(VAR_MANGLE_MAP_PLACEHOLDER)) {
3883
4060
  const jsonMap = escapeJsonForInlineScript(JSON.stringify(state.varMangleMap));
3884
- const escapedMap = result.includes("eval(") ? escapeForDoubleQuotedString(jsonMap) : jsonMap;
4061
+ const escapedMap = isEvalWrapped ? escapeForDoubleQuotedString(jsonMap) : jsonMap;
3885
4062
  result = result.split(VAR_MANGLE_MAP_PLACEHOLDER).join(escapedMap);
3886
4063
  }
3887
4064
  return result;
@@ -3894,6 +4071,9 @@ function createCsszyxPlugins(options = {}) {
3894
4071
  usesMerge: false,
3895
4072
  usesSzcn: false,
3896
4073
  usesSzPart: false,
4074
+ usesSzvPick: false,
4075
+ usesSzvPick1: false,
4076
+ szPartArgsProvable: true,
3897
4077
  usesColorVar: false,
3898
4078
  usesSpacingVar: false,
3899
4079
  usesUnitVar: false
@@ -3914,16 +4094,20 @@ function createCsszyxPlugins(options = {}) {
3914
4094
  if (message.includes("unresolvable sz spread")) {
3915
4095
  state.spreadWarnings.add(`${id}
3916
4096
  ${message}`);
3917
- } else if (message.includes("AST budget exceeded")) {
4097
+ continue;
4098
+ }
4099
+ if (message.includes("AST budget exceeded")) {
3918
4100
  console.warn(`[csszyx] ${id}
3919
4101
  ${message}`);
4102
+ continue;
3920
4103
  }
4104
+ emitMissingCssFallback(quiet, message, id, console.warn);
3921
4105
  }
3922
4106
  if (quiet || result.diagnostics.length === 0 || process.env.NODE_ENV === "production") {
3923
4107
  return;
3924
4108
  }
3925
4109
  for (const message of result.diagnostics) {
3926
- if (message.includes("unresolvable sz spread") || message.includes("AST budget exceeded")) {
4110
+ if (message.includes("unresolvable sz spread") || message.includes("AST budget exceeded") || szFallbackConsequenceOf(message) === "missing-css") {
3927
4111
  continue;
3928
4112
  }
3929
4113
  warn(`[csszyx] ${id}
@@ -3938,6 +4122,9 @@ function createCsszyxPlugins(options = {}) {
3938
4122
  usesMerge: result.usesMerge,
3939
4123
  usesSzcn: result.usesSzcn,
3940
4124
  usesSzPart: result.usesSzPart,
4125
+ usesSzvPick: result.usesSzvPick,
4126
+ usesSzvPick1: result.usesSzvPick1,
4127
+ szPartArgsProvable: result.szPartArgsProvable,
3941
4128
  usesColorVar: result.usesColorVar,
3942
4129
  usesSpacingVar: result.usesSpacingVar,
3943
4130
  usesUnitVar: result.usesUnitVar,
@@ -3980,31 +4167,34 @@ function createCsszyxPlugins(options = {}) {
3980
4167
  return transformedCode;
3981
4168
  }
3982
4169
  function requiredRuntimeHelpers(output) {
3983
- const helpers = [];
3984
- if (output.usesRuntime) helpers.push("_sz");
3985
- if (output.usesMerge) helpers.push("_szMerge");
3986
- if (output.usesSzcn) helpers.push("_szcn");
3987
- if (output.usesSzPart) helpers.push("_szPart");
3988
- if (output.usesColorVar) helpers.push("__szColorVar");
3989
- if (output.usesSpacingVar) helpers.push("__szSpacingVar");
3990
- if (output.usesUnitVar) helpers.push("__szUnitVar");
3991
- return helpers;
4170
+ return runtimeHelperGroupsFromUsage(output);
3992
4171
  }
3993
4172
  function injectRuntimeHelpers(code, output) {
3994
- const imports = requiredRuntimeHelpers(output);
3995
- const hasRuntimeImport = imports.length > 0 && code.includes("@csszyx/runtime");
3996
- const needed = hasRuntimeImport ? imports.filter((name) => !importsRuntimeHelper(code, name)) : imports;
3997
- if (needed.length === 0) return null;
3998
- const existingImport = findRuntimeImportClause(code);
4173
+ const groups = requiredRuntimeHelpers(output);
4174
+ let result = null;
4175
+ let current = code;
4176
+ if (groups.merge.length > 0 && !current.includes("@csszyx/runtime/merge")) {
4177
+ current = insertRuntimeImport(
4178
+ current,
4179
+ `import { ${groups.merge.join(", ")} } from '@csszyx/runtime/merge';
4180
+ `
4181
+ );
4182
+ result = current;
4183
+ }
4184
+ const imports = groups.barrel;
4185
+ const hasRuntimeImport = imports.length > 0 && current.includes("@csszyx/runtime");
4186
+ const needed = hasRuntimeImport ? imports.filter((name) => !importsRuntimeHelper(current, name)) : imports;
4187
+ if (needed.length === 0) return result;
4188
+ const existingImport = findRuntimeImportClause(current);
3999
4189
  if (existingImport) {
4000
- return code.replace(
4190
+ return current.replace(
4001
4191
  existingImport.statement,
4002
4192
  `${existingImport.prefixWithBody}, ${needed.join(", ")} } from '@csszyx/runtime'`
4003
4193
  );
4004
4194
  }
4005
4195
  const importStatement = `import { ${needed.join(", ")} } from '@csszyx/runtime';
4006
4196
  `;
4007
- return insertRuntimeImport(code, importStatement);
4197
+ return insertRuntimeImport(current, importStatement);
4008
4198
  }
4009
4199
  function injectThemeGroups(code, transformedCode, id, usesSzcn) {
4010
4200
  if (!usesSzcn && !/\bszcn\s*\(/.test(code) || transformedCode.includes(THEME_GROUPS_VIRTUAL_ID) || !shouldProcessSource(id)) {
@@ -4012,6 +4202,18 @@ function createCsszyxPlugins(options = {}) {
4012
4202
  }
4013
4203
  return `import '${THEME_GROUPS_VIRTUAL_ID}';
4014
4204
  ${transformedCode}`;
4205
+ }
4206
+ const MANGLE_RUNTIME_CONSUMER_RE = /from\s*['"](?:csszyx|@csszyx\/runtime)['"]/;
4207
+ let activeFramework;
4208
+ function injectMangleRuntime(transformedCode, id) {
4209
+ if (activeFramework !== "vite" && activeFramework !== "rollup") {
4210
+ return null;
4211
+ }
4212
+ if (!manglingEnabled || !deliverMapInBundle || !shouldProcessSource(id) || !MANGLE_RUNTIME_CONSUMER_RE.test(transformedCode) || transformedCode.includes(MANGLE_RUNTIME_VIRTUAL_ID)) {
4213
+ return null;
4214
+ }
4215
+ return insertRuntimeImport(transformedCode, `import '${MANGLE_RUNTIME_VIRTUAL_ID}';
4216
+ `);
4015
4217
  }
4016
4218
  function collectPreTransformClasses(output) {
4017
4219
  if (!output.transformed && !output.code.includes("class=") && !output.code.includes("className=")) {
@@ -4055,7 +4257,7 @@ ${transformedCode}`;
4055
4257
  * @returns true only for csszyx virtual modules
4056
4258
  */
4057
4259
  loadInclude(id) {
4058
- return id === RESOLVED_VIRTUAL_MODULE_ID || id === RESOLVED_VIRTUAL_CHECKSUM_ID || id === RESOLVED_THEME_GROUPS_VIRTUAL_ID;
4260
+ return id === RESOLVED_VIRTUAL_MODULE_ID || id === RESOLVED_VIRTUAL_CHECKSUM_ID || id === RESOLVED_THEME_GROUPS_VIRTUAL_ID || id === RESOLVED_MANGLE_RUNTIME_VIRTUAL_ID;
4059
4261
  },
4060
4262
  /**
4061
4263
  * Loads virtual module content — generates mangle map or checksum module code.
@@ -4076,6 +4278,10 @@ ${transformedCode}`;
4076
4278
  finalizeMangleMap();
4077
4279
  return createChecksumModule(state.checksum);
4078
4280
  }
4281
+ if (id === RESOLVED_MANGLE_RUNTIME_VIRTUAL_ID) {
4282
+ sizeAccount.channels.add("bundle");
4283
+ return createMangleRuntimeModule(globalVarAliasPrefix);
4284
+ }
4079
4285
  if (id === RESOLVED_THEME_GROUPS_VIRTUAL_ID) {
4080
4286
  const theme = state.parsedTheme;
4081
4287
  return createThemeGroupsModule({
@@ -4121,7 +4327,12 @@ ${transformedCode}`;
4121
4327
  if (matchesScriptExtension(id, [".css"])) {
4122
4328
  return transformTailwindCssEntry(code, id);
4123
4329
  }
4124
- const hasSzProp = code.includes("sz=") || code.includes("szs=") || /\bsz\s*:\s*["'{]/.test(code) || code.includes('sz: "');
4330
+ const hasSzProp = code.includes("sz=") || code.includes("szs=") || /\bsz\s*:\s*["'{]/.test(code) || code.includes('sz: "') || // szr-only modules (no sz attribute) historically skipped the
4331
+ // compiler entirely — which also skipped the szr import
4332
+ // rewrite AND the szr fallback diagnostics. The substring is
4333
+ // deliberately loose; a false positive only costs one file
4334
+ // the compiler pass, which then changes nothing.
4335
+ code.includes("szr(");
4125
4336
  const output = hasSzProp ? transformSzSource(code, id, (message) => this.warn(message)) : unchangedPreTransform(code);
4126
4337
  if (!hasSzProp && shouldProcessSource(id)) {
4127
4338
  recordFileVarMangleEntries(state, id, []);
@@ -4142,6 +4353,11 @@ ${transformedCode}`;
4142
4353
  output.code = themedCode;
4143
4354
  output.transformed = true;
4144
4355
  }
4356
+ const mangleRuntimeCode = injectMangleRuntime(output.code, id);
4357
+ if (mangleRuntimeCode !== null) {
4358
+ output.code = mangleRuntimeCode;
4359
+ output.transformed = true;
4360
+ }
4145
4361
  if (matchesScriptExtension(id, SCRIPT_ID_EXTENSIONS)) {
4146
4362
  assertNoRSCBoundaryViolation(output.code, id);
4147
4363
  const record = createRSCModuleRecord(output.code, id);
@@ -4205,6 +4421,18 @@ ${transformedCode}`;
4205
4421
  * @param compiler - the Webpack compiler instance
4206
4422
  */
4207
4423
  webpack(compiler) {
4424
+ activeFramework = "webpack";
4425
+ if (compiler.options?.mode === "development") {
4426
+ manglingEnabled = false;
4427
+ }
4428
+ if (compiler.watchMode === true || compiler.options?.watch === true) {
4429
+ crossModuleRegistryEnabled = false;
4430
+ }
4431
+ if (manglingEnabled && mangleMapDelivery !== "both") {
4432
+ console.warn(
4433
+ `[csszyx] production.mangleMapDelivery: '${mangleMapDelivery}' has no effect on the webpack lane \u2014 map delivery only narrows on vite/rollup builds.`
4434
+ );
4435
+ }
4208
4436
  compiler.hooks.beforeCompile.tap("csszyx:prescan", () => {
4209
4437
  announceActiveParser();
4210
4438
  const root = compiler.context || process.cwd();
@@ -4225,6 +4453,16 @@ ${transformedCode}`;
4225
4453
  });
4226
4454
  }
4227
4455
  },
4456
+ rollup: {
4457
+ /** Records the rollup lane for the mangle-runtime gate. */
4458
+ buildStart() {
4459
+ activeFramework = "rollup";
4460
+ const meta = this.meta;
4461
+ if (meta?.watchMode) {
4462
+ crossModuleRegistryEnabled = false;
4463
+ }
4464
+ }
4465
+ },
4228
4466
  vite: {
4229
4467
  /**
4230
4468
  * Vite hook: pre-scans source files when config is resolved.
@@ -4232,11 +4470,16 @@ ${transformedCode}`;
4232
4470
  * @param config - the resolved Vite configuration object
4233
4471
  */
4234
4472
  configResolved(config) {
4473
+ activeFramework = "vite";
4235
4474
  announceActiveParser();
4236
4475
  const root = config.root || process.cwd();
4237
4476
  state.rootDir = root;
4238
4477
  if (config.command === "serve") {
4239
4478
  manglingEnabled = false;
4479
+ crossModuleRegistryEnabled = false;
4480
+ }
4481
+ if (config.build?.watch) {
4482
+ crossModuleRegistryEnabled = false;
4240
4483
  }
4241
4484
  evictTransformCacheOnce();
4242
4485
  prescanAndWriteClasses();
@@ -4338,8 +4581,12 @@ ${transformedCode}`;
4338
4581
  mode: "script",
4339
4582
  minify: process.env.NODE_ENV === "production",
4340
4583
  varMangleMap: state.varMangleMap,
4341
- globalVarAliasPrefix
4584
+ globalVarAliasPrefix,
4585
+ installRuntimeObject: deliverMapInHtml
4342
4586
  });
4587
+ if (manglingEnabled) {
4588
+ sizeAccount.channels.add("html");
4589
+ }
4343
4590
  if (state.recoveryTokens.size > 0) {
4344
4591
  const isProduction = process.env.NODE_ENV === "production";
4345
4592
  const { manifest, strippedDevOnlyPaths } = buildRecoveryManifest(
@@ -4388,7 +4635,7 @@ ${transformedCode}`;
4388
4635
  return manifest;
4389
4636
  }
4390
4637
  function rewriteOutputCss(source, file, shouldMangle, mangledSources, externalClasses) {
4391
- let css = rewriteCssWithValidatedGlobalVarPlan(
4638
+ const css = rewriteCssWithValidatedGlobalVarPlan(
4392
4639
  source,
4393
4640
  file,
4394
4641
  state.globalVarValidationResult
@@ -4401,8 +4648,9 @@ ${transformedCode}`;
4401
4648
  });
4402
4649
  for (const className of result.mangledClasses) mangledSources.add(className);
4403
4650
  for (const className of result.unmangledClasses) externalClasses.add(className);
4404
- if (result.transformedCount > 0) css = result.css;
4405
- return css;
4651
+ const mangled = result.transformedCount > 0 ? result.css : css;
4652
+ recordCssPair(sizeAccount, css, mangled);
4653
+ return mangled;
4406
4654
  } catch (error) {
4407
4655
  if (isCssSyntaxError(error)) return css;
4408
4656
  throw error;
@@ -4414,6 +4662,16 @@ ${transformedCode}`;
4414
4662
  collectMangleHybridHazards(state.mangleMap, mangledSources, externalClasses)
4415
4663
  );
4416
4664
  if (message) console.warn(message);
4665
+ reportMangleSize();
4666
+ }
4667
+ function reportMangleSize() {
4668
+ const verdict = computeMangleSizeVerdict(
4669
+ sizeAccount,
4670
+ JSON.stringify(createHydrationMangleMap(state.mangleMap, state.varMangleMap))
4671
+ );
4672
+ const message = mangleSizeMessage(verdict);
4673
+ if (message) console.warn(message);
4674
+ resetMangleSizeAccount(sizeAccount);
4417
4675
  }
4418
4676
  function rewriteWebpackCodeAsset(file, source, shouldMangle, compilation, compiler) {
4419
4677
  if (shouldMangle && file.endsWith(".html")) {
@@ -4598,4 +4856,4 @@ const esbuildPlugin = (options = {}) => {
4598
4856
  };
4599
4857
  };
4600
4858
 
4601
- export { vitePlugin as $, isPackagesSkippedSource as A, isRSCServerModule as B, isTailwindReservedGlobalVar as C, mangleCodeClassesSync as D, mangleEligibleClasses as E, mangleHybridHazardMessage as F, mergeThemes as G, missingTailwindEntryMessage as H, normalizeGlobalVarAliasesForCache as I, parseThemeBlocks as J, planGlobalVarAliases as K, readGlobalVarScanCache as L, recordGlobalVarSourceFile as M, resolveCompileSourceDirs as N, resolveGlobalVarScanCacheDir as O, resolveNativeCacheIdentity as P, rewriteGlobalVarCssAliases as Q, rollupPlugin as R, scanCustomPropertyNames as S, scanGlobalVarCss as T, shouldEmitWarning as U, shouldTrackGlobalVarSources as V, shouldWarnMissingTailwindEntry as W, shouldWarnUnscopedMonorepo as X, skippedSzFilesMessage as Y, unscopedMonorepoMessage as Z, validateGlobalVarAliasInputs as _, appendTailwindSourceDirective as a, webpackPlugin as a0, writeGlobalVarScanCache as a1, 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, findLocalImportSources as p, findRSCBoundaryViolation as q, findRSCGraphViolation as r, hasInjectableTailwindCandidate as s, hasTokens as t, unplugin as u, hasUseClientDirective as v, hasUseServerDirective as w, isCompileSourceOptedIn as x, isHardIgnoredPath as y, isMonorepoPackage as z };
4859
+ export { skippedSzFilesMessage as $, isHardIgnoredPath as A, isMonorepoPackage as B, isPackagesSkippedSource as C, isRSCServerModule as D, isTailwindReservedGlobalVar as E, mangleCodeClassesSync as F, mangleEligibleClasses as G, mangleHybridHazardMessage as H, mergeThemes as I, missingTailwindEntryMessage as J, normalizeGlobalVarAliasesForCache as K, parseThemeBlocks as L, planGlobalVarAliases as M, readGlobalVarScanCache as N, recordGlobalVarSourceFile as O, resolveCompileSourceDirs as P, resolveGlobalVarScanCacheDir as Q, resolveNativeCacheIdentity as R, rewriteGlobalVarCssAliases as S, rollupPlugin as T, scanCustomPropertyNames as U, scanGlobalVarCss as V, shouldEmitMissingCssFallback as W, shouldEmitWarning as X, shouldTrackGlobalVarSources as Y, shouldWarnMissingTailwindEntry as Z, shouldWarnUnscopedMonorepo as _, allocateMangleTokens as a, unscopedMonorepoMessage as a0, validateGlobalVarAliasInputs as a1, vitePlugin as a2, webpackPlugin as a3, writeGlobalVarScanCache as a4, appendTailwindSourceDirective as b, assertNoRSCBoundaryViolation as c, assertNoRSCGraphViolation as d, collectMangleHybridHazards as e, computeSafelistRelPath as f, createGlobalVarAliasValidationOptions as g, createGlobalVarMapAssetSource as h, createGlobalVarScanCacheKey as i, createRSCModuleRecord as j, cssHasContentScope as k, cssImportsTailwind as l, deleteRSCModuleRecord as m, emitMissingCssFallback as n, esbuildPlugin as o, extractGlobalVarAliasesForManifest as p, fileMayContainSafelistableSz as q, findLocalImportSources as r, findRSCBoundaryViolation as s, findRSCGraphViolation as t, unplugin as u, hasInjectableTailwindCandidate as v, hasTokens as w, hasUseClientDirective as x, hasUseServerDirective as y, isCompileSourceOptedIn as z };