@csszyx/unplugin 0.11.11 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +1 -1
  2. package/dist/index.cjs +11 -7
  3. package/dist/index.d.cts +4 -4
  4. package/dist/index.d.mts +4 -4
  5. package/dist/index.mjs +4 -3
  6. package/dist/next-config.cjs +3 -0
  7. package/dist/next-config.d.cts +10 -0
  8. package/dist/next-config.d.mts +10 -0
  9. package/dist/next-config.mjs +3 -0
  10. package/dist/next-prebuild.cjs +12 -5
  11. package/dist/next-prebuild.d.cts +7 -0
  12. package/dist/next-prebuild.d.mts +7 -0
  13. package/dist/next-prebuild.mjs +12 -5
  14. package/dist/next-turbo-loader.cjs +29 -59
  15. package/dist/next-turbo-loader.d.cts +10 -0
  16. package/dist/next-turbo-loader.d.mts +10 -0
  17. package/dist/next-turbo-loader.mjs +28 -58
  18. package/dist/next-watcher.cjs +1 -1
  19. package/dist/next-watcher.mjs +1 -1
  20. package/dist/shared/unplugin.4du3qMst.cjs +529 -0
  21. package/dist/shared/unplugin.5l4RHMQh.mjs +578 -0
  22. package/dist/shared/unplugin.BB0iWSds.mjs +495 -0
  23. package/dist/shared/{unplugin.DMcbmP01.mjs → unplugin.BU0O4IkX.mjs} +4 -1
  24. package/dist/shared/{unplugin.CJcFsJcf.cjs → unplugin.Bf4fNbp7.cjs} +452 -504
  25. package/dist/shared/{unplugin.BZq6FKn2.cjs → unplugin.CUTa6bY9.cjs} +89 -1
  26. package/dist/shared/{unplugin.DblMogcN.cjs → unplugin.Cji6O5jv.cjs} +4 -1
  27. package/dist/shared/{unplugin.-yLpX1Ck.mjs → unplugin.CogPHmDs.mjs} +73 -3
  28. package/dist/shared/{unplugin.BK7BIeBn.d.cts → unplugin.DCT7DDG6.d.cts} +88 -26
  29. package/dist/shared/{unplugin.BK7BIeBn.d.mts → unplugin.DCT7DDG6.d.mts} +88 -26
  30. package/dist/shared/unplugin.X9a9SL_s.cjs +612 -0
  31. package/dist/shared/{unplugin.B2RUVK6Z.mjs → unplugin.ymMe428s.mjs} +426 -477
  32. package/dist/vite.cjs +4 -3
  33. package/dist/vite.d.cts +2 -2
  34. package/dist/vite.d.mts +1 -1
  35. package/dist/vite.mjs +4 -3
  36. package/dist/webpack.cjs +4 -3
  37. package/dist/webpack.d.cts +2 -2
  38. package/dist/webpack.d.mts +1 -1
  39. package/dist/webpack.mjs +4 -3
  40. package/package.json +13 -11
  41. package/dist/shared/unplugin.CKIOVNOg.cjs +0 -241
  42. package/dist/shared/unplugin.Cnxm1DcC.cjs +0 -53
  43. package/dist/shared/unplugin.Lhzkcj-A.mjs +0 -49
  44. package/dist/shared/unplugin.fOnGXWgS.mjs +0 -217
@@ -13,10 +13,11 @@ const svelteAdapter = require('@csszyx/svelte-adapter');
13
13
  const types = require('@csszyx/types');
14
14
  const vueAdapter = require('@csszyx/vue-adapter');
15
15
  const unplugin$1 = require('unplugin');
16
- const transformCache = require('./unplugin.CKIOVNOg.cjs');
16
+ const transformCache = require('./unplugin.4du3qMst.cjs');
17
17
  const cssMangler = require('../css-mangler.cjs');
18
- const runtimeImportScan = require('./unplugin.Cnxm1DcC.cjs');
18
+ const themeGroupsFile = require('./unplugin.X9a9SL_s.cjs');
19
19
  const htmlEscape = require('./unplugin.BkRah5Ot.cjs');
20
+ const node_zlib = require('node:zlib');
20
21
  const postcss = require('postcss');
21
22
  const valueParser = require('postcss-value-parser');
22
23
 
@@ -311,7 +312,7 @@ function validateCandidates(candidates, definitions, reserved, aliasPrefix) {
311
312
  code: "registered-property",
312
313
  severity: "error",
313
314
  name,
314
- message: `Registered custom property ${name} is not aliasable in Phase H v1.`,
315
+ message: `Registered custom property ${name} cannot be aliased: @property gives it a type and inheritance behaviour that an alias would not carry.`,
315
316
  location: registeredDefinition
316
317
  });
317
318
  }
@@ -1131,237 +1132,6 @@ function maskBlockComment(code, start) {
1131
1132
  return { end, value };
1132
1133
  }
1133
1134
 
1134
- const EMPTY_THEME = {
1135
- colors: [],
1136
- spacings: [],
1137
- fonts: [],
1138
- textSizes: [],
1139
- fontWeights: [],
1140
- radii: [],
1141
- shadows: [],
1142
- breakpoints: []
1143
- };
1144
- function findMatchingBrace(source, openBrace) {
1145
- let depth = 0;
1146
- for (let index = openBrace; index < source.length; index++) {
1147
- if (source[index] === "{") {
1148
- depth++;
1149
- } else if (source[index] === "}") {
1150
- depth--;
1151
- if (depth === 0) {
1152
- return index;
1153
- }
1154
- }
1155
- }
1156
- return -1;
1157
- }
1158
- function stripLayerWrappers(css) {
1159
- let result = "";
1160
- let i = 0;
1161
- while (i < css.length) {
1162
- const layerIdx = css.indexOf("@layer", i);
1163
- if (layerIdx === -1) {
1164
- result += css.slice(i);
1165
- break;
1166
- }
1167
- result += css.slice(i, layerIdx);
1168
- const openBrace = css.indexOf("{", layerIdx);
1169
- if (openBrace === -1) {
1170
- result += css.slice(layerIdx);
1171
- break;
1172
- }
1173
- const closeBrace = findMatchingBrace(css, openBrace);
1174
- if (closeBrace === -1) {
1175
- result += css.slice(openBrace);
1176
- break;
1177
- }
1178
- result += css.slice(openBrace + 1, closeBrace);
1179
- i = closeBrace + 1;
1180
- }
1181
- return result;
1182
- }
1183
- function themePreludeStart(css, at) {
1184
- const cursor = at + "@theme".length;
1185
- const next = css[cursor];
1186
- const validBoundary = next === "{" || next === " " || next === " " || next === "\n" || next === "\r";
1187
- return validBoundary ? cursor : null;
1188
- }
1189
- function readThemeBlock(css, start) {
1190
- for (let cursor = start; cursor < css.length; cursor++) {
1191
- const character = css[cursor];
1192
- if (character === "{") {
1193
- const close = findMatchingBrace(css, cursor);
1194
- return {
1195
- body: close === -1 ? null : css.slice(cursor + 1, close),
1196
- end: close === -1 ? cursor : close
1197
- };
1198
- }
1199
- if (character === ";" || character === "}" || character === "@") {
1200
- return { body: null, end: cursor };
1201
- }
1202
- }
1203
- return { body: null, end: css.length };
1204
- }
1205
- function extractThemeBlocks(css) {
1206
- const blocks = [];
1207
- let searchFrom = 0;
1208
- for (; ; ) {
1209
- const at = css.indexOf("@theme", searchFrom);
1210
- if (at === -1) {
1211
- break;
1212
- }
1213
- const preludeStart = themePreludeStart(css, at);
1214
- if (preludeStart === null) {
1215
- searchFrom = at + "@theme".length;
1216
- continue;
1217
- }
1218
- const match = readThemeBlock(css, preludeStart);
1219
- if (match.body !== null) blocks.push(match.body);
1220
- searchFrom = Math.max(match.end, at + "@theme".length);
1221
- }
1222
- return blocks;
1223
- }
1224
- function categorizeProperty(prop) {
1225
- const categoryMap = [
1226
- ["color-", "colors"],
1227
- ["spacing-", "spacings"],
1228
- // `font-weight-` MUST precede `font-`: startsWith would otherwise route
1229
- // `font-weight-chunky` into font FAMILIES as token "weight-chunky".
1230
- ["font-weight-", "fontWeights"],
1231
- ["font-", "fonts"],
1232
- // `--text-*` defines font-size utilities (text-huge) in Tailwind v4.
1233
- ["text-", "textSizes"],
1234
- ["radius-", "radii"],
1235
- ["shadow-", "shadows"],
1236
- ["breakpoint-", "breakpoints"]
1237
- ];
1238
- for (const [prefix, category] of categoryMap) {
1239
- if (prop.startsWith(prefix)) {
1240
- let token = prop.slice(prefix.length);
1241
- if (category !== "breakpoints") {
1242
- token = token.replace(/-\d+$/, "");
1243
- }
1244
- if (token) {
1245
- return { category, token };
1246
- }
1247
- }
1248
- }
1249
- return null;
1250
- }
1251
- function parseThemeBlocks(cssContent) {
1252
- const result = {
1253
- colors: /* @__PURE__ */ new Set(),
1254
- spacings: /* @__PURE__ */ new Set(),
1255
- fonts: /* @__PURE__ */ new Set(),
1256
- textSizes: /* @__PURE__ */ new Set(),
1257
- fontWeights: /* @__PURE__ */ new Set(),
1258
- radii: /* @__PURE__ */ new Set(),
1259
- shadows: /* @__PURE__ */ new Set(),
1260
- breakpoints: /* @__PURE__ */ new Set()
1261
- };
1262
- const stripped = stripLayerWrappers(cssContent);
1263
- const blocks = extractThemeBlocks(stripped);
1264
- for (const block of blocks) {
1265
- for (const name of scanCustomPropertyNames(block)) {
1266
- const categorized = categorizeProperty(name);
1267
- if (categorized) {
1268
- result[categorized.category].add(categorized.token);
1269
- }
1270
- }
1271
- }
1272
- return {
1273
- colors: htmlEscape.sortStrings(result.colors),
1274
- spacings: htmlEscape.sortStrings(result.spacings),
1275
- fonts: htmlEscape.sortStrings(result.fonts),
1276
- textSizes: htmlEscape.sortStrings(result.textSizes),
1277
- fontWeights: htmlEscape.sortStrings(result.fontWeights),
1278
- radii: htmlEscape.sortStrings(result.radii),
1279
- shadows: htmlEscape.sortStrings(result.shadows),
1280
- breakpoints: htmlEscape.sortStrings(result.breakpoints)
1281
- };
1282
- }
1283
- function mergeThemes(themes) {
1284
- if (themes.length === 0) {
1285
- return { ...EMPTY_THEME };
1286
- }
1287
- const merged = {
1288
- colors: /* @__PURE__ */ new Set(),
1289
- spacings: /* @__PURE__ */ new Set(),
1290
- fonts: /* @__PURE__ */ new Set(),
1291
- textSizes: /* @__PURE__ */ new Set(),
1292
- fontWeights: /* @__PURE__ */ new Set(),
1293
- radii: /* @__PURE__ */ new Set(),
1294
- shadows: /* @__PURE__ */ new Set(),
1295
- breakpoints: /* @__PURE__ */ new Set()
1296
- };
1297
- for (const theme of themes) {
1298
- for (const cat of Object.keys(merged)) {
1299
- for (const token of theme[cat]) {
1300
- merged[cat].add(token);
1301
- }
1302
- }
1303
- }
1304
- return {
1305
- colors: htmlEscape.sortStrings(merged.colors),
1306
- spacings: htmlEscape.sortStrings(merged.spacings),
1307
- fonts: htmlEscape.sortStrings(merged.fonts),
1308
- textSizes: htmlEscape.sortStrings(merged.textSizes),
1309
- fontWeights: htmlEscape.sortStrings(merged.fontWeights),
1310
- radii: htmlEscape.sortStrings(merged.radii),
1311
- shadows: htmlEscape.sortStrings(merged.shadows),
1312
- breakpoints: htmlEscape.sortStrings(merged.breakpoints)
1313
- };
1314
- }
1315
- function hasTokens(theme) {
1316
- return Object.values(theme).some((arr) => arr.length > 0);
1317
- }
1318
- function readCustomPropertyName(block, dashes) {
1319
- let end = dashes + 2;
1320
- if (end >= block.length || !/[a-z]/.test(block[end])) {
1321
- return null;
1322
- }
1323
- end++;
1324
- while (end < block.length && /[a-z0-9-]/.test(block[end])) {
1325
- end++;
1326
- }
1327
- return { name: block.slice(dashes + 2, end), end };
1328
- }
1329
- function findCustomPropertyDeclarationEnd(block, nameEnd) {
1330
- let cursor = nameEnd;
1331
- while (cursor < block.length && /\s/.test(block[cursor])) {
1332
- cursor++;
1333
- }
1334
- if (block[cursor] === ":") {
1335
- const valueStart = cursor + 1;
1336
- const semicolon = block.indexOf(";", valueStart);
1337
- return semicolon > valueStart ? semicolon + 1 : -1;
1338
- }
1339
- return block[nameEnd] === ";" ? nameEnd + 1 : -1;
1340
- }
1341
- function scanCustomPropertyNames(block) {
1342
- const names = [];
1343
- let i = 0;
1344
- while (i < block.length) {
1345
- const dashes = block.indexOf("--", i);
1346
- if (dashes === -1) {
1347
- break;
1348
- }
1349
- const property = readCustomPropertyName(block, dashes);
1350
- if (!property) {
1351
- i = dashes + 1;
1352
- continue;
1353
- }
1354
- const matchEnd = findCustomPropertyDeclarationEnd(block, property.end);
1355
- if (matchEnd === -1) {
1356
- i = dashes + 1;
1357
- continue;
1358
- }
1359
- names.push(property.name);
1360
- i = matchEnd;
1361
- }
1362
- return names;
1363
- }
1364
-
1365
1135
  const REGEX_PREFIXES = new Set("([{:,;=!?&|+-*%^~<>/");
1366
1136
  const REGEX_PREFIX_KEYWORDS = /* @__PURE__ */ new Set([
1367
1137
  "await",
@@ -1731,6 +1501,78 @@ function collectAuthoredClassNames(source) {
1731
1501
  return classes;
1732
1502
  }
1733
1503
 
1504
+ const KNOWN_TOP_LEVEL_KEYS = /* @__PURE__ */ new Set([
1505
+ "include",
1506
+ "exclude",
1507
+ "compileSources",
1508
+ "contentScopeCheck",
1509
+ "quiet",
1510
+ "mode",
1511
+ "development",
1512
+ "production",
1513
+ "build",
1514
+ "hydration"
1515
+ ]);
1516
+ const RENAMED_KEYS = {
1517
+ // Replaced by the path-based form: package NAMES could not express a
1518
+ // sibling directory outside the project root, and resolving them meant
1519
+ // guessing at workspace layout.
1520
+ compilePackages: "compileSources"
1521
+ };
1522
+ function nearestKnownConfigKey(key) {
1523
+ const lower = key.toLowerCase();
1524
+ let best = null;
1525
+ let bestDistance = Number.POSITIVE_INFINITY;
1526
+ for (const candidate of KNOWN_TOP_LEVEL_KEYS) {
1527
+ const distance = editDistance(lower, candidate.toLowerCase());
1528
+ if (distance < bestDistance) {
1529
+ bestDistance = distance;
1530
+ best = candidate;
1531
+ }
1532
+ }
1533
+ return best !== null && bestDistance <= Math.max(1, Math.floor(key.length / 4)) ? best : null;
1534
+ }
1535
+ function editDistance(a, b) {
1536
+ let previous = Array.from({ length: b.length + 1 }, (_, index) => index);
1537
+ for (let i = 1; i <= a.length; i += 1) {
1538
+ const current = [i];
1539
+ for (let j = 1; j <= b.length; j += 1) {
1540
+ const substitution = previous[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1);
1541
+ current.push(Math.min(substitution, previous[j] + 1, current[j - 1] + 1));
1542
+ }
1543
+ previous = current;
1544
+ }
1545
+ return previous[b.length];
1546
+ }
1547
+ function findUnknownConfigKeys(options) {
1548
+ if (options === null || typeof options !== "object" || Array.isArray(options)) {
1549
+ return [];
1550
+ }
1551
+ const unknown = [];
1552
+ for (const key of Object.keys(options)) {
1553
+ if (KNOWN_TOP_LEVEL_KEYS.has(key)) continue;
1554
+ const renamedTo = RENAMED_KEYS[key];
1555
+ if (renamedTo !== void 0) {
1556
+ unknown.push({ key, renamedTo });
1557
+ continue;
1558
+ }
1559
+ const suggestion = nearestKnownConfigKey(key);
1560
+ unknown.push(suggestion === null ? { key } : { key, suggestion });
1561
+ }
1562
+ return unknown;
1563
+ }
1564
+ function unknownConfigKeysMessage(unknown) {
1565
+ const lines = unknown.map((entry) => {
1566
+ if (entry.renamedTo !== void 0) {
1567
+ return ` - \`${entry.key}\` was replaced by \`${entry.renamedTo}\``;
1568
+ }
1569
+ return entry.suggestion === void 0 ? ` - \`${entry.key}\`` : ` - \`${entry.key}\` \u2014 did you mean \`${entry.suggestion}\`?`;
1570
+ });
1571
+ return `[csszyx] ${unknown.length} plugin option(s) are not recognized and have no effect:
1572
+ ${lines.join("\n")}
1573
+ An unread option is silent, so whatever you configured it for is not happening.`;
1574
+ }
1575
+
1734
1576
  const GLOB_MAGIC_RE = /[*?[\]{}]/;
1735
1577
  const DEFAULT_IGNORED_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git", ".next", ".turbo", "dist", "build"]);
1736
1578
  function normalizeFileId(id) {
@@ -1883,17 +1725,19 @@ function injectMangleMapScript(html, mangleMap, options = {}) {
1883
1725
  const {
1884
1726
  prettyPrint = false,
1885
1727
  varMangleMap = {},
1886
- globalVarAliasPrefix = types.CSSZYX_GLOBAL_ALIAS_PREFIX
1728
+ globalVarAliasPrefix = types.CSSZYX_GLOBAL_ALIAS_PREFIX,
1729
+ installRuntimeObject = true
1887
1730
  } = options;
1888
1731
  const checksumMap = createHydrationMangleMap(mangleMap, varMangleMap);
1889
1732
  const jsonContent = safeJsonForScriptTag(checksumMap, prettyPrint);
1890
- const classMapContent = safeJsonForScriptTag(mangleMap);
1891
1733
  const varMapContent = safeJsonForScriptTag(varMangleMap);
1734
+ const reuseChecksumPayload = Object.keys(varMangleMap).length === 0;
1735
+ const classMapExpr = reuseChecksumPayload ? '(function(){var e=document.getElementById("__CSSZYX_MANGLE_MAP__");return e?JSON.parse(e.textContent):{}})()' : safeJsonForScriptTag(mangleMap);
1892
1736
  const scriptTag = `<script id="__CSSZYX_MANGLE_MAP__" type="application/json">${jsonContent}<\/script>`;
1893
1737
  const prefixContent = safeJsonForScriptTag(globalVarAliasPrefix);
1894
- 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>`;
1895
- const combined = `${scriptTag}
1896
- ${debugScript}`;
1738
+ 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>`;
1739
+ const combined = installRuntimeObject ? `${scriptTag}
1740
+ ${debugScript}` : scriptTag;
1897
1741
  if (html.includes("</head>")) {
1898
1742
  return html.replace("</head>", `${combined}
1899
1743
  </head>`);
@@ -1998,6 +1842,42 @@ function escapeForDoubleQuotedString(value) {
1998
1842
  return htmlEscape.escapeDoubleQuotedString(value);
1999
1843
  }
2000
1844
 
1845
+ function createMangleSizeAccount() {
1846
+ return { cssGzBefore: 0, cssGzAfter: 0, channels: /* @__PURE__ */ new Set() };
1847
+ }
1848
+ function resetMangleSizeAccount(account) {
1849
+ account.cssGzBefore = 0;
1850
+ account.cssGzAfter = 0;
1851
+ account.channels.clear();
1852
+ }
1853
+ function gzipBytes(text) {
1854
+ if (text.length === 0) return 0;
1855
+ return node_zlib.gzipSync(Buffer.from(text, "utf8")).length;
1856
+ }
1857
+ function recordCssPair(account, before, after) {
1858
+ if (before === after) {
1859
+ const bytes = gzipBytes(before);
1860
+ account.cssGzBefore += bytes;
1861
+ account.cssGzAfter += bytes;
1862
+ return;
1863
+ }
1864
+ account.cssGzBefore += gzipBytes(before);
1865
+ account.cssGzAfter += gzipBytes(after);
1866
+ }
1867
+ function computeMangleSizeVerdict(account, mapPayload) {
1868
+ const channels = htmlEscape.sortStrings(account.channels);
1869
+ const mapCost = gzipBytes(mapPayload) * channels.length;
1870
+ const cssSaving = account.cssGzBefore - account.cssGzAfter;
1871
+ return { mapCost, cssSaving, net: mapCost - cssSaving, channels };
1872
+ }
1873
+ function mangleSizeMessage(verdict) {
1874
+ if (verdict.channels.length === 0) return null;
1875
+ if (verdict.net <= 0) return null;
1876
+ 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)`;
1877
+ const channelPart = verdict.channels.length > 1 ? `${verdict.channels.join(" + ")} (${verdict.channels.length} copies)` : verdict.channels[0];
1878
+ 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.)`;
1879
+ }
1880
+
2001
1881
  function isParserMode(value) {
2002
1882
  return value === "rust" || value === "oxc" || value === "babel";
2003
1883
  }
@@ -2113,127 +1993,6 @@ function writeThemeDts(opts) {
2113
1993
  fs.writeFileSync(opts.outputPath, content, "utf-8");
2114
1994
  }
2115
1995
 
2116
- const VIRTUAL_MODULE_ID = "virtual:csszyx/mangle-map";
2117
- const RESOLVED_VIRTUAL_MODULE_ID = `\0${VIRTUAL_MODULE_ID}`;
2118
- const THEME_GROUPS_VIRTUAL_ID = "virtual:csszyx/theme-groups";
2119
- const RESOLVED_THEME_GROUPS_VIRTUAL_ID = `\0${THEME_GROUPS_VIRTUAL_ID}`;
2120
- const VIRTUAL_CHECKSUM_ID = "virtual:csszyx/checksum";
2121
- const RESOLVED_VIRTUAL_CHECKSUM_ID = `\0${VIRTUAL_CHECKSUM_ID}`;
2122
- function createMangleMapModule(mangleMap, checksum, varMangleMap = {}, cssVarMetrics = null) {
2123
- return `/**
2124
- * Auto-generated mangle map for csszyx.
2125
- * This module is generated at build time and contains the mapping
2126
- * from original class names and CSS variable names to mangled names.
2127
- *
2128
- * @generated
2129
- */
2130
-
2131
- export const mangleMap = ${JSON.stringify(mangleMap, null, 2)};
2132
-
2133
- export const varMangleMap = ${JSON.stringify(varMangleMap, null, 2)};
2134
-
2135
- export const cssVarMetrics = ${JSON.stringify(cssVarMetrics, null, 2)};
2136
-
2137
- export const checksum = ${JSON.stringify(checksum)};
2138
-
2139
- export default {
2140
- mangleMap,
2141
- varMangleMap,
2142
- cssVarMetrics,
2143
- checksum,
2144
- };
2145
- `;
2146
- }
2147
- function createChecksumModule(checksum) {
2148
- return `/**
2149
- * Auto-generated checksum for csszyx mangle map.
2150
- *
2151
- * @generated
2152
- */
2153
-
2154
- export const checksum = ${JSON.stringify(checksum)};
2155
-
2156
- export default checksum;
2157
- `;
2158
- }
2159
- function isVirtualModule(id) {
2160
- return id === VIRTUAL_MODULE_ID || id === VIRTUAL_CHECKSUM_ID || id === THEME_GROUPS_VIRTUAL_ID || id === MANGLE_RUNTIME_VIRTUAL_ID;
2161
- }
2162
- function resolveVirtualModule(id) {
2163
- if (id === VIRTUAL_MODULE_ID) {
2164
- return RESOLVED_VIRTUAL_MODULE_ID;
2165
- }
2166
- if (id === VIRTUAL_CHECKSUM_ID) {
2167
- return RESOLVED_VIRTUAL_CHECKSUM_ID;
2168
- }
2169
- if (id === THEME_GROUPS_VIRTUAL_ID) {
2170
- return RESOLVED_THEME_GROUPS_VIRTUAL_ID;
2171
- }
2172
- if (id === MANGLE_RUNTIME_VIRTUAL_ID) {
2173
- return RESOLVED_MANGLE_RUNTIME_VIRTUAL_ID;
2174
- }
2175
- return void 0;
2176
- }
2177
- const MANGLE_RUNTIME_VIRTUAL_ID = "virtual:csszyx/mangle-runtime";
2178
- const RESOLVED_MANGLE_RUNTIME_VIRTUAL_ID = `\0${MANGLE_RUNTIME_VIRTUAL_ID}`;
2179
- const MANGLE_MAP_PLACEHOLDER = "___CSSZYX_MANGLE_MAP___";
2180
- const VAR_MANGLE_MAP_PLACEHOLDER = "___CSSZYX_VAR_MANGLE_MAP___";
2181
- const CHECKSUM_PLACEHOLDER = "___CSSZYX_CHECKSUM___";
2182
- function createMangleRuntimeModule(globalVarAliasPrefix) {
2183
- return `/**
2184
- * Auto-generated by csszyx: installs the runtime mangle map from the bundle.
2185
- *
2186
- * @generated
2187
- */
2188
-
2189
- const m = ${MANGLE_MAP_PLACEHOLDER};
2190
- const vm = ${VAR_MANGLE_MAP_PLACEHOLDER};
2191
- const gp = ${JSON.stringify(globalVarAliasPrefix)};
2192
- const checksum = "${CHECKSUM_PLACEHOLDER}";
2193
-
2194
- if (typeof window !== 'undefined' && !window.__csszyx) {
2195
- const r = {};
2196
- const vr = {};
2197
- for (const k in m) r[m[k]] = k;
2198
- for (const vk in vm) {
2199
- const vv = vm[vk];
2200
- const vs = Array.isArray(vv) ? vv : [vv];
2201
- for (const v of vs) (vr[v] || (vr[v] = [])).push(vk);
2202
- }
2203
- window.__csszyx = {
2204
- mangleMap: m,
2205
- varMangleMap: vm,
2206
- checksum,
2207
- decode: (c) => r[c],
2208
- encode: (c) => m[c],
2209
- decodeVar: (v) => vr[v] || [],
2210
- encodeVar: (v) => vm[v],
2211
- decodeGlobalVar: (v) => {
2212
- const a = vr[v] || [];
2213
- return v.indexOf(gp) === 0 ? a[0] : undefined;
2214
- },
2215
- decodeAll: (el) => (el.className || '').split(' ').map((c) => r[c] || c),
2216
- };
2217
- }
2218
-
2219
- export {};
2220
- `;
2221
- }
2222
- function createThemeGroupsModule(tokens) {
2223
- const payload = JSON.stringify({
2224
- colors: tokens.colors,
2225
- textSizes: tokens.textSizes,
2226
- fontFamilies: tokens.fontFamilies,
2227
- fontWeights: tokens.fontWeights
2228
- });
2229
- return [
2230
- "// Auto-generated by csszyx from the @theme blocks in scanned CSS.",
2231
- "import { registerSzcnGroups } from '@csszyx/runtime';",
2232
- `registerSzcnGroups(${payload});`,
2233
- "export {};"
2234
- ].join("\n");
2235
- }
2236
-
2237
1996
  function registerWebpackAssetProcessor(compiler, processAssets) {
2238
1997
  compiler.hooks.compilation.tap("csszyx:post", (compilation) => {
2239
1998
  const stage = compiler.webpack?.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE || compilation.constructor.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE;
@@ -2276,9 +2035,9 @@ let _hasWarnedTransformCacheVersion = false;
2276
2035
  let _hasWarnedNativeFallback = false;
2277
2036
  const _loggedActiveParsers = /* @__PURE__ */ new Set();
2278
2037
  const _babelFallbackFiles = /* @__PURE__ */ new Set();
2279
- const requireFromHere = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('shared/unplugin.CJcFsJcf.cjs', document.baseURI).href)));
2038
+ const requireFromHere = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('shared/unplugin.Bf4fNbp7.cjs', document.baseURI).href)));
2280
2039
  const PLUGIN_VERSION = findPackageVersionFromFile(
2281
- node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('shared/unplugin.CJcFsJcf.cjs', document.baseURI).href))),
2040
+ node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('shared/unplugin.Bf4fNbp7.cjs', document.baseURI).href))),
2282
2041
  UNKNOWN_PACKAGE_VERSION
2283
2042
  );
2284
2043
  const COMPILER_VERSION = findPackageVersionFromModule("@csszyx/compiler", UNKNOWN_PACKAGE_VERSION);
@@ -2422,15 +2181,28 @@ function shouldWarnUnscopedMonorepo(sawTailwindEntry, tailwindEntryScoped, inMon
2422
2181
  function unscopedMonorepoMessage() {
2423
2182
  return '[csszyx] Tailwind content detection is UNSCOPED in a monorepo. Tailwind v4 climbs to the workspace root and scans sibling packages + docs (.md/.mdx/.txt are not ignored), which can generate phantom or broken url() classes and fail the build. Scope it in your Tailwind CSS entry:\n @import "tailwindcss" source(none);\n @source "."; /* this package, relative to the CSS file */\ncsszyx auto-injects @source for its generated classes, so only your own templates need listing. Guide: https://csszyx.com/docs/monorepo-content-scope/\nSilence (if a broad scan is intentional): csszyx({ contentScopeCheck: false }).';
2424
2183
  }
2184
+ function resolveQuietMode(quiet) {
2185
+ if (quiet === true || quiet === "all") return "all";
2186
+ if (quiet === "nudges") return "nudges";
2187
+ return "off";
2188
+ }
2425
2189
  function shouldEmitWarning(quiet, devOnly, isProduction) {
2426
- if (quiet) {
2190
+ const mode = resolveQuietMode(quiet);
2191
+ if (mode === "all") {
2427
2192
  return false;
2428
2193
  }
2429
- if (devOnly && isProduction) {
2194
+ if (devOnly && (isProduction || mode === "nudges")) {
2430
2195
  return false;
2431
2196
  }
2432
2197
  return true;
2433
2198
  }
2199
+ function shouldEmitMissingCssFallback(quiet, message) {
2200
+ return resolveQuietMode(quiet) !== "all" && compiler.szFallbackConsequenceOf(message) === "missing-css";
2201
+ }
2202
+ function emitMissingCssFallback(quiet, message, id, emit) {
2203
+ if (shouldEmitMissingCssFallback(quiet, message)) emit(`[csszyx] ${id}
2204
+ ${message}`);
2205
+ }
2434
2206
  function normalizeForMatch(p) {
2435
2207
  const n = transformCache.normalizePathSeparators(p);
2436
2208
  return n.length > 1 && n.endsWith("/") ? n.slice(0, -1) : n;
@@ -2535,11 +2307,13 @@ function isPackagesSkippedSource(id, sourceDirs = []) {
2535
2307
  }
2536
2308
  return !isCompileSourceOptedIn(p, sourceDirs);
2537
2309
  }
2538
- function skippedSzFilesMessage(files) {
2310
+ function skippedSzFilesMessage(files, szvExportFiles = []) {
2539
2311
  const list = files.map((file) => ` - ${file}`).join("\n");
2540
- return `[csszyx] ${files.length} file(s) under packages/ contain \`sz\` but were skipped by ignore rules:
2312
+ const registryClause = szvExportFiles.length === 0 ? "" : `
2313
+ ${szvExportFiles.length} of them may export \`szv\` factories, so they stay out of the cross-module registry and every importer falls back to the runtime path.`;
2314
+ return `[csszyx] ${files.length} file(s) under packages/ use csszyx but were skipped by ignore rules:
2541
2315
  ${list}
2542
- Add the package directory to \`compileSources\` (or move the file out of packages/) \u2014 otherwise their \`sz\` produces no CSS.`;
2316
+ Add the package directory to \`compileSources\` (or move the file out of packages/) \u2014 otherwise their classes never reach the safelist.` + registryClause;
2543
2317
  }
2544
2318
  function computeSafelistRelPath(rootDir, safelistFilename, cssId) {
2545
2319
  const safelistPath = transformCache.normalizePathSeparators(path__namespace.join(rootDir, safelistFilename));
@@ -2863,12 +2637,12 @@ function runThemeScan(rootDir, scanCss) {
2863
2637
  }
2864
2638
  const themes = sourceFiles.map((f) => {
2865
2639
  try {
2866
- return parseThemeBlocks(readStableTextFileSnapshotSync(f).source);
2640
+ return themeGroupsFile.parseThemeBlocks(readStableTextFileSnapshotSync(f).source);
2867
2641
  } catch {
2868
2642
  return null;
2869
2643
  }
2870
2644
  }).filter((t) => t !== null);
2871
- const merged = mergeThemes(themes);
2645
+ const merged = themeGroupsFile.mergeThemes(themes);
2872
2646
  const outputPath = path__namespace.join(rootDir, ".csszyx", "theme.d.ts");
2873
2647
  writeThemeDts({ outputPath, theme: merged, sourceFiles });
2874
2648
  if (!_hasWarnedTsConfig) {
@@ -2936,7 +2710,7 @@ function matchesScriptExtension(id, extensions) {
2936
2710
  return extensions.some((ext) => id.endsWith(ext) || id.includes(`${ext}?`));
2937
2711
  }
2938
2712
  function insertRuntimeImport(code, importStmt) {
2939
- return runtimeImportScan.insertAfterUseDirective(code, importStmt);
2713
+ return themeGroupsFile.insertAfterUseDirective(code, importStmt);
2940
2714
  }
2941
2715
  function scanClassExpression(source, from) {
2942
2716
  let depth = 0;
@@ -3180,20 +2954,33 @@ ${errors.join("\n")}`
3180
2954
  if (config?.enabled === true) {
3181
2955
  if (!config.tokens || config.tokens.length === 0) {
3182
2956
  throw new Error(
3183
- "[csszyx] production.mangleGlobalVars.enabled requires explicit tokens in Phase H v1."
2957
+ "[csszyx] production.mangleGlobalVars.enabled requires explicit tokens. Aliasing a property csszyx was not told about would rename references it cannot see."
3184
2958
  );
3185
2959
  }
3186
2960
  if (config.autoPrefix !== void 0 && config.autoPrefix !== "") {
3187
2961
  throw new Error(
3188
- "[csszyx] production.mangleGlobalVars.autoPrefix requires CSS pre-scan support and is not enabled in Phase H v1."
2962
+ "[csszyx] production.mangleGlobalVars.autoPrefix is not available: choosing tokens by prefix needs a CSS pre-scan that does not exist yet. List the tokens instead."
3189
2963
  );
3190
2964
  }
3191
2965
  }
3192
2966
  }
3193
2967
  function createCsszyxPlugins(options = {}) {
3194
2968
  assertGlobalVarMangleConfig(options);
3195
- let manglingEnabled = options.production?.mangle !== false;
2969
+ let manglingEnabled = options.production?.mangle === true;
2970
+ const importedStaticSzEnabled = options.build?.importedStaticSz ?? types.DEFAULT_IMPORTED_STATIC_SZ;
2971
+ const szvCrossModuleRegistry = /* @__PURE__ */ new Map();
2972
+ const szObjectProvidersExamined = /* @__PURE__ */ new Set();
2973
+ let specifierAliases = [];
3196
2974
  const mangleReserved = new Set(options.production?.mangleExclude ?? []);
2975
+ const mangleMapDelivery = options.production?.mangleMapDelivery ?? "both";
2976
+ if (!["both", "html", "bundle"].includes(mangleMapDelivery)) {
2977
+ throw new Error(
2978
+ `[csszyx] production.mangleMapDelivery must be 'both', 'html' or 'bundle'; got ${JSON.stringify(mangleMapDelivery)}.`
2979
+ );
2980
+ }
2981
+ const deliverMapInHtml = mangleMapDelivery !== "bundle";
2982
+ const deliverMapInBundle = mangleMapDelivery !== "html";
2983
+ const sizeAccount = createMangleSizeAccount();
3197
2984
  const astBudgetOverride = options.build?.astBudgetLimit;
3198
2985
  const prescanAstBudget = astBudgetOverride ?? 5e5;
3199
2986
  const cacheRequested = (options.build?.cache ?? types.DEFAULT_BUILD_CONFIG.cache) !== false;
@@ -3215,7 +3002,11 @@ function createCsszyxPlugins(options = {}) {
3215
3002
  );
3216
3003
  }
3217
3004
  const compileSources = options.compileSources ?? [];
3218
- const quiet = options.quiet === true;
3005
+ const quiet = resolveQuietMode(options.quiet);
3006
+ const unknownConfigKeys = findUnknownConfigKeys(options);
3007
+ if (unknownConfigKeys.length > 0) {
3008
+ emitWarning(unknownConfigKeysMessage(unknownConfigKeys));
3009
+ }
3219
3010
  function emitWarning(message, opts = {}) {
3220
3011
  if (shouldEmitWarning(quiet, opts.devOnly ?? false, process.env.NODE_ENV === "production")) {
3221
3012
  console.warn(message);
@@ -3252,6 +3043,7 @@ function createCsszyxPlugins(options = {}) {
3252
3043
  const state = {
3253
3044
  classes: /* @__PURE__ */ new Set(),
3254
3045
  parsedTheme: null,
3046
+ scanCssTheme: null,
3255
3047
  autoThemeCssFiles: [],
3256
3048
  sawTailwindEntry: false,
3257
3049
  sawAnyCss: false,
@@ -3260,6 +3052,7 @@ function createCsszyxPlugins(options = {}) {
3260
3052
  contentScopeWarningEmitted: false,
3261
3053
  spreadWarnings: /* @__PURE__ */ new Set(),
3262
3054
  skippedSzFiles: /* @__PURE__ */ new Set(),
3055
+ skippedSzvExportFiles: /* @__PURE__ */ new Set(),
3263
3056
  skipWarningEmitted: false,
3264
3057
  classesCapped: false,
3265
3058
  ownedClasses: /* @__PURE__ */ new Set(),
@@ -3354,56 +3147,14 @@ function createCsszyxPlugins(options = {}) {
3354
3147
  }
3355
3148
  }
3356
3149
  function runAutoThemeScan(rootDir) {
3357
- if (options.build?.scanCss) {
3358
- return;
3359
- }
3360
3150
  refreshCompileSourceDirs();
3361
- const cssFiles = [];
3362
- const walk = (dir) => {
3363
- let entries;
3364
- try {
3365
- entries = fs__namespace.readdirSync(dir, { withFileTypes: true });
3366
- } catch {
3367
- return;
3368
- }
3369
- for (const entry of entries) {
3370
- if (entry.isDirectory()) {
3371
- if (!IGNORE_DIRS.has(entry.name) && !entry.name.startsWith(".")) {
3372
- walk(path__namespace.join(dir, entry.name));
3373
- }
3374
- continue;
3375
- }
3376
- if (entry.name.endsWith(".css")) {
3377
- cssFiles.push(path__namespace.join(dir, entry.name));
3378
- }
3379
- }
3380
- };
3381
- walk(rootDir);
3382
- const normRoot = normalizeForMatch(rootDir);
3383
- for (const sourceDir of compileSourceDirs) {
3384
- if (sourceDir === normRoot || sourceDir.startsWith(`${normRoot}/`)) {
3385
- continue;
3386
- }
3387
- walk(sourceDir);
3388
- }
3389
- const themes = [];
3390
- const themeFiles = [];
3391
- for (const file of cssFiles) {
3392
- let content;
3393
- try {
3394
- content = fs__namespace.readFileSync(file, "utf-8");
3395
- } catch {
3396
- continue;
3397
- }
3398
- if (!content.includes("@theme")) {
3399
- continue;
3400
- }
3401
- themes.push(parseThemeBlocks(content));
3402
- themeFiles.push(file);
3403
- }
3404
- state.autoThemeCssFiles = themeFiles;
3405
- if (themes.length > 0) {
3406
- state.parsedTheme = mergeThemes(themes);
3151
+ const discovered = themeGroupsFile.discoverProjectTheme(rootDir, [...compileSourceDirs]);
3152
+ state.autoThemeCssFiles = discovered.files;
3153
+ const sources = [state.scanCssTheme, discovered.theme].filter(
3154
+ (theme) => theme !== null
3155
+ );
3156
+ if (sources.length > 0) {
3157
+ state.parsedTheme = themeGroupsFile.mergeThemes(sources);
3407
3158
  }
3408
3159
  }
3409
3160
  function isHardIgnored(id) {
@@ -3419,6 +3170,18 @@ function createCsszyxPlugins(options = {}) {
3419
3170
  function transformConfiguredSource(source, filename, astBudget) {
3420
3171
  const compilerOptions = createCompilerOptions(astBudget);
3421
3172
  const effectiveFilename = normalizeSourceFilename(filename);
3173
+ const crossModuleStatics = transformCache.resolveCrossModuleStaticsFor(
3174
+ szvCrossModuleRegistry,
3175
+ filename,
3176
+ source,
3177
+ specifierAliases
3178
+ );
3179
+ if (crossModuleStatics.szvConfigs !== void 0) {
3180
+ compilerOptions.crossModuleStatics = crossModuleStatics.szvConfigs;
3181
+ }
3182
+ if (crossModuleStatics.szObjects !== void 0) {
3183
+ compilerOptions.crossModuleSzObjects = crossModuleStatics.szObjects;
3184
+ }
3422
3185
  const cacheRoot = transformCache.resolveTransformCacheDir(state.rootDir, options.build?.cacheDir);
3423
3186
  if (cacheEnabled) {
3424
3187
  evictTransformCacheOnce();
@@ -3530,6 +3293,11 @@ function createCsszyxPlugins(options = {}) {
3530
3293
  mangleVars: compilerOptions.mangleVars,
3531
3294
  mangleVarHoistMaxDepth: compilerOptions.mangleVarHoistMaxDepth,
3532
3295
  globalVarAliases: normalizeGlobalVarAliasesForCache(compilerOptions.globalVarAliases),
3296
+ // The registry entries fed to this file are part of its identity:
3297
+ // module A's config change must miss B's cached transform, or the
3298
+ // cache serves a stale table.
3299
+ crossModuleStatics: compilerOptions.crossModuleStatics === void 0 ? void 0 : JSON.stringify(compilerOptions.crossModuleStatics),
3300
+ crossModuleSzObjects: compilerOptions.crossModuleSzObjects === void 0 ? void 0 : JSON.stringify(compilerOptions.crossModuleSzObjects),
3533
3301
  filename: effectiveFilename,
3534
3302
  source
3535
3303
  };
@@ -3538,19 +3306,35 @@ function createCsszyxPlugins(options = {}) {
3538
3306
  if (parserMode !== "rust" || files.length <= 1) {
3539
3307
  return transformPrescanSourcesIndividually(files);
3540
3308
  }
3309
+ const perFile = [];
3310
+ const batchable = [];
3311
+ for (const file of files) {
3312
+ (hasCrossModuleStatics(file) ? perFile : batchable).push(file);
3313
+ }
3314
+ const individual = transformPrescanSourcesIndividually(perFile);
3541
3315
  const compilerOptions = createCompilerOptions(prescanAstBudget);
3542
3316
  const cacheRoot = transformCache.resolveTransformCacheDir(state.rootDir, options.build?.cacheDir);
3543
3317
  const results = /* @__PURE__ */ new Map();
3544
3318
  if (cacheEnabled) evictTransformCacheOnce();
3545
3319
  compiler.ensureRustTransformAvailable();
3546
- const misses = collectRustPrescanMisses(files, compilerOptions, cacheRoot, results);
3547
- if (misses.length === 0) return orderPrescanResults(files, results);
3548
- try {
3549
- runRustPrescanBatch(misses, compilerOptions, cacheRoot, results);
3550
- } catch {
3551
- runRustPrescanFallback(misses, results);
3320
+ const misses = collectRustPrescanMisses(batchable, compilerOptions, cacheRoot, results);
3321
+ if (misses.length > 0) {
3322
+ try {
3323
+ runRustPrescanBatch(misses, compilerOptions, cacheRoot, results);
3324
+ } catch {
3325
+ runRustPrescanFallback(misses, results);
3326
+ }
3552
3327
  }
3553
- return orderPrescanResults(files, results);
3328
+ return [...individual, ...orderPrescanResults(batchable, results)];
3329
+ }
3330
+ function hasCrossModuleStatics(file) {
3331
+ const resolved = transformCache.resolveCrossModuleStaticsFor(
3332
+ szvCrossModuleRegistry,
3333
+ file.filePath,
3334
+ file.content,
3335
+ specifierAliases
3336
+ );
3337
+ return resolved.szvConfigs !== void 0 || resolved.szObjects !== void 0;
3554
3338
  }
3555
3339
  function collectRustPrescanMisses(files, compilerOptions, cacheRoot, results) {
3556
3340
  const misses = [];
@@ -3698,7 +3482,7 @@ function createCsszyxPlugins(options = {}) {
3698
3482
  }
3699
3483
  }
3700
3484
  function recordPackagesSkipIfSz(filePath) {
3701
- if (!isPackagesSkippedSource(filePath, compileSourceDirs)) {
3485
+ if (state.skippedSzFiles.has(filePath) || !isPackagesSkippedSource(filePath, compileSourceDirs)) {
3702
3486
  return;
3703
3487
  }
3704
3488
  let content;
@@ -3707,8 +3491,12 @@ function createCsszyxPlugins(options = {}) {
3707
3491
  } catch {
3708
3492
  return;
3709
3493
  }
3710
- if (content.includes("sz=") || content.includes("szs=") || content.includes("sz:")) {
3711
- state.skippedSzFiles.add(filePath);
3494
+ if (!fileMayContainSafelistableSz(content)) {
3495
+ return;
3496
+ }
3497
+ state.skippedSzFiles.add(filePath);
3498
+ if (transformCache.mayExportSzvFactories(content)) {
3499
+ state.skippedSzvExportFiles.add(filePath);
3712
3500
  }
3713
3501
  }
3714
3502
  function processPrescanTransform(filePath, content, result, discoveredClasses, rawDiscoveredClasses) {
@@ -3739,12 +3527,73 @@ function createCsszyxPlugins(options = {}) {
3739
3527
  }
3740
3528
  collectPrescanResult(result, filePath, discoveredClasses, rawDiscoveredClasses);
3741
3529
  }
3530
+ function refreshSzvRegistryEntry(filePath, content) {
3531
+ if (!shouldProcessSource(filePath)) return;
3532
+ if (content === null) {
3533
+ szvCrossModuleRegistry.delete(transformCache.normalizePathSeparators(filePath));
3534
+ return;
3535
+ }
3536
+ transformCache.recordSzvRegistryFile(szvCrossModuleRegistry, filePath, content);
3537
+ if (importedStaticSzEnabled) {
3538
+ transformCache.recordSzObjectRegistryFile(szvCrossModuleRegistry, filePath, content);
3539
+ szObjectProvidersExamined.add(transformCache.normalizePathSeparators(filePath));
3540
+ recordProvidersDemandedBy(filePath, content);
3541
+ }
3542
+ }
3543
+ function recordProvidersDemandedBy(filePath, content) {
3544
+ if (!fileMayContainSafelistableSz(content)) return;
3545
+ const directory = path__namespace.dirname(filePath);
3546
+ for (const specifier of transformCache.importedSpecifiersIn(content)) {
3547
+ for (const base of transformCache.specifierBases(specifier, directory, specifierAliases)) {
3548
+ const providerPath = transformCache.resolveProviderPathWith(base, transformCache.isReadableProviderFile);
3549
+ if (providerPath === void 0) continue;
3550
+ const key = transformCache.normalizePathSeparators(providerPath);
3551
+ if (!szObjectProvidersExamined.has(key)) {
3552
+ szObjectProvidersExamined.add(key);
3553
+ readAndRecordSzObjectProvider(providerPath);
3554
+ }
3555
+ break;
3556
+ }
3557
+ }
3558
+ }
3559
+ function readAndRecordSzObjectProvider(providerPath) {
3560
+ let content;
3561
+ try {
3562
+ content = fs__namespace.readFileSync(providerPath, "utf-8");
3563
+ } catch {
3564
+ return;
3565
+ }
3566
+ transformCache.recordSzObjectRegistryFile(szvCrossModuleRegistry, providerPath, content);
3567
+ }
3568
+ function recordDemandedSzObjectProviders(seenSourcePaths, demand) {
3569
+ for (const base of demand) {
3570
+ const providerPath = transformCache.resolveProviderPath(seenSourcePaths, base);
3571
+ if (providerPath === void 0) continue;
3572
+ szObjectProvidersExamined.add(transformCache.normalizePathSeparators(providerPath));
3573
+ readAndRecordSzObjectProvider(providerPath);
3574
+ }
3575
+ }
3576
+ function refreshSzvRegistryEntryFromDisk(filePath) {
3577
+ if (!shouldProcessSource(filePath)) return;
3578
+ let content;
3579
+ try {
3580
+ content = fs__namespace.readFileSync(filePath, "utf-8");
3581
+ } catch {
3582
+ refreshSzvRegistryEntry(filePath, null);
3583
+ return;
3584
+ }
3585
+ refreshSzvRegistryEntry(filePath, content);
3586
+ }
3742
3587
  function prescanAndWriteClasses() {
3743
3588
  refreshCompileSourceDirs();
3589
+ szvCrossModuleRegistry.clear();
3590
+ szObjectProvidersExamined.clear();
3744
3591
  const prescanStarted = node_perf_hooks.performance.now();
3745
3592
  const discoveredClasses = /* @__PURE__ */ new Set();
3746
3593
  const rawDiscoveredClasses = /* @__PURE__ */ new Set();
3747
3594
  const prescanSources = [];
3595
+ const seenSourcePaths = /* @__PURE__ */ new Set();
3596
+ const szObjectDemand = /* @__PURE__ */ new Set();
3748
3597
  function collectPrescanSource(filePath) {
3749
3598
  if (!shouldProcessSource(filePath)) {
3750
3599
  recordPackagesSkipIfSz(filePath);
@@ -3757,10 +3606,25 @@ function createCsszyxPlugins(options = {}) {
3757
3606
  return;
3758
3607
  }
3759
3608
  recordAuthoredClasses(content);
3609
+ recordSzvRegistryEntries(filePath, content);
3610
+ seenSourcePaths.add(transformCache.normalizePathSeparators(filePath));
3760
3611
  if (fileMayContainSafelistableSz(content)) {
3761
3612
  prescanSources.push({ filePath, content });
3613
+ recordSzObjectDemand(filePath, content);
3762
3614
  }
3763
3615
  }
3616
+ function recordSzObjectDemand(filePath, content) {
3617
+ if (!importedStaticSzEnabled) return;
3618
+ const directory = path__namespace.dirname(filePath);
3619
+ for (const specifier of transformCache.importedSpecifiersIn(content)) {
3620
+ for (const base of transformCache.specifierBases(specifier, directory, specifierAliases)) {
3621
+ szObjectDemand.add(base);
3622
+ }
3623
+ }
3624
+ }
3625
+ function recordSzvRegistryEntries(filePath, content) {
3626
+ transformCache.recordSzvRegistryFile(szvCrossModuleRegistry, filePath, content);
3627
+ }
3764
3628
  function scanDir(dir) {
3765
3629
  let entries;
3766
3630
  try {
@@ -3788,6 +3652,7 @@ function createCsszyxPlugins(options = {}) {
3788
3652
  }
3789
3653
  scanDir(sourceDir);
3790
3654
  }
3655
+ recordDemandedSzObjectProviders(seenSourcePaths, szObjectDemand);
3791
3656
  const prescanContentByPath = new Map(
3792
3657
  prescanSources.map((file) => [file.filePath, file.content])
3793
3658
  );
@@ -3957,19 +3822,19 @@ function createCsszyxPlugins(options = {}) {
3957
3822
  }
3958
3823
  function replacePlaceholders(code) {
3959
3824
  let result = code;
3960
- if (result.includes(CHECKSUM_PLACEHOLDER)) {
3961
- result = result.split(CHECKSUM_PLACEHOLDER).join(state.checksum);
3825
+ if (result.includes(themeGroupsFile.CHECKSUM_PLACEHOLDER)) {
3826
+ result = result.split(themeGroupsFile.CHECKSUM_PLACEHOLDER).join(state.checksum);
3962
3827
  }
3963
3828
  const isEvalWrapped = result.includes("eval(") && result.includes("sourceURL=webpack");
3964
- if (result.includes(MANGLE_MAP_PLACEHOLDER)) {
3829
+ if (result.includes(themeGroupsFile.MANGLE_MAP_PLACEHOLDER)) {
3965
3830
  const jsonMap = escapeJsonForInlineScript(JSON.stringify(state.mangleMap));
3966
3831
  const escapedMap = isEvalWrapped ? escapeForDoubleQuotedString(jsonMap) : jsonMap;
3967
- result = result.split(MANGLE_MAP_PLACEHOLDER).join(escapedMap);
3832
+ result = result.split(themeGroupsFile.MANGLE_MAP_PLACEHOLDER).join(escapedMap);
3968
3833
  }
3969
- if (result.includes(VAR_MANGLE_MAP_PLACEHOLDER)) {
3834
+ if (result.includes(themeGroupsFile.VAR_MANGLE_MAP_PLACEHOLDER)) {
3970
3835
  const jsonMap = escapeJsonForInlineScript(JSON.stringify(state.varMangleMap));
3971
3836
  const escapedMap = isEvalWrapped ? escapeForDoubleQuotedString(jsonMap) : jsonMap;
3972
- result = result.split(VAR_MANGLE_MAP_PLACEHOLDER).join(escapedMap);
3837
+ result = result.split(themeGroupsFile.VAR_MANGLE_MAP_PLACEHOLDER).join(escapedMap);
3973
3838
  }
3974
3839
  return result;
3975
3840
  }
@@ -3981,6 +3846,9 @@ function createCsszyxPlugins(options = {}) {
3981
3846
  usesMerge: false,
3982
3847
  usesSzcn: false,
3983
3848
  usesSzPart: false,
3849
+ usesSzvPick: false,
3850
+ usesSzvPick1: false,
3851
+ szPartArgsProvable: true,
3984
3852
  usesColorVar: false,
3985
3853
  usesSpacingVar: false,
3986
3854
  usesUnitVar: false
@@ -4001,16 +3869,20 @@ function createCsszyxPlugins(options = {}) {
4001
3869
  if (message.includes("unresolvable sz spread")) {
4002
3870
  state.spreadWarnings.add(`${id}
4003
3871
  ${message}`);
4004
- } else if (message.includes("AST budget exceeded")) {
3872
+ continue;
3873
+ }
3874
+ if (message.includes("AST budget exceeded")) {
4005
3875
  console.warn(`[csszyx] ${id}
4006
3876
  ${message}`);
3877
+ continue;
4007
3878
  }
3879
+ emitMissingCssFallback(quiet, message, id, console.warn);
4008
3880
  }
4009
- if (quiet || result.diagnostics.length === 0 || process.env.NODE_ENV === "production") {
3881
+ if (quiet !== "off" || result.diagnostics.length === 0 || process.env.NODE_ENV === "production") {
4010
3882
  return;
4011
3883
  }
4012
3884
  for (const message of result.diagnostics) {
4013
- if (message.includes("unresolvable sz spread") || message.includes("AST budget exceeded")) {
3885
+ if (message.includes("unresolvable sz spread") || message.includes("AST budget exceeded") || compiler.szFallbackConsequenceOf(message) === "missing-css") {
4014
3886
  continue;
4015
3887
  }
4016
3888
  warn(`[csszyx] ${id}
@@ -4025,6 +3897,9 @@ function createCsszyxPlugins(options = {}) {
4025
3897
  usesMerge: result.usesMerge,
4026
3898
  usesSzcn: result.usesSzcn,
4027
3899
  usesSzPart: result.usesSzPart,
3900
+ usesSzvPick: result.usesSzvPick,
3901
+ usesSzvPick1: result.usesSzvPick1,
3902
+ szPartArgsProvable: result.szPartArgsProvable,
4028
3903
  usesColorVar: result.usesColorVar,
4029
3904
  usesSpacingVar: result.usesSpacingVar,
4030
3905
  usesUnitVar: result.usesUnitVar,
@@ -4057,9 +3932,9 @@ function createCsszyxPlugins(options = {}) {
4057
3932
  const attrName = options.production?.minify ? "data-sz-cs" : "data-sz-checksum";
4058
3933
  const htmlTag = findOpeningTag(transformedCode, "html");
4059
3934
  if (htmlTag) {
4060
- transformedCode = `${transformedCode.slice(0, htmlTag.close)} ${attrName}="${CHECKSUM_PLACEHOLDER}"${transformedCode.slice(htmlTag.close)}`;
3935
+ transformedCode = `${transformedCode.slice(0, htmlTag.close)} ${attrName}="${themeGroupsFile.CHECKSUM_PLACEHOLDER}"${transformedCode.slice(htmlTag.close)}`;
4061
3936
  }
4062
- const debugScript = `<script dangerouslySetInnerHTML={{__html: \`(function(){var m=${MANGLE_MAP_PLACEHOLDER};var vm=${VAR_MANGLE_MAP_PLACEHOLDER};var gp=decodeURIComponent(${escapeJsonForInlineScript(JSON.stringify(encodedGlobalVarAliasPrefix))});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)}window.__csszyx={mangleMap:m,varMangleMap:vm,checksum:"${CHECKSUM_PLACEHOLDER}",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})}}})()\`}} />`;
3937
+ const debugScript = `<script dangerouslySetInnerHTML={{__html: \`(function(){var m=${themeGroupsFile.MANGLE_MAP_PLACEHOLDER};var vm=${themeGroupsFile.VAR_MANGLE_MAP_PLACEHOLDER};var gp=decodeURIComponent(${escapeJsonForInlineScript(JSON.stringify(encodedGlobalVarAliasPrefix))});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)}window.__csszyx={mangleMap:m,varMangleMap:vm,checksum:"${themeGroupsFile.CHECKSUM_PLACEHOLDER}",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})}}})()\`}} />`;
4063
3938
  const bodyTag = findOpeningTag(transformedCode, "body");
4064
3939
  if (bodyTag) {
4065
3940
  transformedCode = `${transformedCode.slice(0, bodyTag.close + 1)}${debugScript}${transformedCode.slice(bodyTag.close + 1)}`;
@@ -4067,37 +3942,59 @@ function createCsszyxPlugins(options = {}) {
4067
3942
  return transformedCode;
4068
3943
  }
4069
3944
  function requiredRuntimeHelpers(output) {
4070
- const helpers = [];
4071
- if (output.usesRuntime) helpers.push("_sz");
4072
- if (output.usesMerge) helpers.push("_szMerge");
4073
- if (output.usesSzcn) helpers.push("_szcn");
4074
- if (output.usesSzPart) helpers.push("_szPart");
4075
- if (output.usesColorVar) helpers.push("__szColorVar");
4076
- if (output.usesSpacingVar) helpers.push("__szSpacingVar");
4077
- if (output.usesUnitVar) helpers.push("__szUnitVar");
4078
- return helpers;
3945
+ return themeGroupsFile.runtimeHelperGroupsFromUsage(output);
4079
3946
  }
4080
3947
  function injectRuntimeHelpers(code, output) {
4081
- const imports = requiredRuntimeHelpers(output);
4082
- const hasRuntimeImport = imports.length > 0 && code.includes("@csszyx/runtime");
4083
- const needed = hasRuntimeImport ? imports.filter((name) => !runtimeImportScan.importsRuntimeHelper(code, name)) : imports;
4084
- if (needed.length === 0) return null;
4085
- const existingImport = runtimeImportScan.findRuntimeImportClause(code);
3948
+ const groups = requiredRuntimeHelpers(output);
3949
+ let result = null;
3950
+ let current = code;
3951
+ if (groups.merge.length > 0 && !current.includes("@csszyx/runtime/merge")) {
3952
+ current = insertRuntimeImport(
3953
+ current,
3954
+ `import { ${groups.merge.join(", ")} } from '@csszyx/runtime/merge';
3955
+ `
3956
+ );
3957
+ result = current;
3958
+ }
3959
+ const imports = groups.barrel;
3960
+ const hasRuntimeImport = imports.length > 0 && current.includes("@csszyx/runtime");
3961
+ const needed = hasRuntimeImport ? imports.filter((name) => !themeGroupsFile.importsRuntimeHelper(current, name)) : imports;
3962
+ if (needed.length === 0) return result;
3963
+ const existingImport = themeGroupsFile.findRuntimeImportClause(current);
4086
3964
  if (existingImport) {
4087
- return code.replace(
3965
+ return current.replace(
4088
3966
  existingImport.statement,
4089
3967
  `${existingImport.prefixWithBody}, ${needed.join(", ")} } from '@csszyx/runtime'`
4090
3968
  );
4091
3969
  }
4092
3970
  const importStatement = `import { ${needed.join(", ")} } from '@csszyx/runtime';
4093
3971
  `;
4094
- return insertRuntimeImport(code, importStatement);
3972
+ return insertRuntimeImport(current, importStatement);
3973
+ }
3974
+ function themeGroupTokens() {
3975
+ const theme = state.parsedTheme;
3976
+ return {
3977
+ colors: theme?.colors ?? [],
3978
+ textSizes: theme?.textSizes ?? [],
3979
+ fontFamilies: theme?.fonts ?? [],
3980
+ fontWeights: theme?.fontWeights ?? []
3981
+ };
4095
3982
  }
4096
3983
  function injectThemeGroups(code, transformedCode, id, usesSzcn) {
4097
- if (!usesSzcn && !/\bszcn\s*\(/.test(code) || transformedCode.includes(THEME_GROUPS_VIRTUAL_ID) || !shouldProcessSource(id)) {
3984
+ if (!usesSzcn && !/\bszcn\s*\(/.test(code) || transformedCode.includes(themeGroupsFile.THEME_GROUPS_VIRTUAL_ID) || transformedCode.includes(themeGroupsFile.THEME_GROUPS_FILE_MARKER) || !shouldProcessSource(id)) {
4098
3985
  return null;
4099
3986
  }
4100
- return `import '${THEME_GROUPS_VIRTUAL_ID}';
3987
+ if (activeFramework === "webpack") {
3988
+ const groups = themeGroupsFile.ensureThemeGroupsFile(
3989
+ state.rootDir,
3990
+ path__namespace.join(state.rootDir, ".csszyx")
3991
+ );
3992
+ if (groups.file === null) return null;
3993
+ const [from] = id.split("?");
3994
+ return `import '${themeGroupsFile.themeGroupsSpecifier(from, groups.file)}';
3995
+ ${transformedCode}`;
3996
+ }
3997
+ return `import '${themeGroupsFile.THEME_GROUPS_VIRTUAL_ID}';
4101
3998
  ${transformedCode}`;
4102
3999
  }
4103
4000
  const MANGLE_RUNTIME_CONSUMER_RE = /from\s*['"](?:csszyx|@csszyx\/runtime)['"]/;
@@ -4106,10 +4003,10 @@ ${transformedCode}`;
4106
4003
  if (activeFramework !== "vite" && activeFramework !== "rollup") {
4107
4004
  return null;
4108
4005
  }
4109
- if (!manglingEnabled || !shouldProcessSource(id) || !MANGLE_RUNTIME_CONSUMER_RE.test(transformedCode) || transformedCode.includes(MANGLE_RUNTIME_VIRTUAL_ID)) {
4006
+ if (!manglingEnabled || !deliverMapInBundle || !shouldProcessSource(id) || !MANGLE_RUNTIME_CONSUMER_RE.test(transformedCode) || transformedCode.includes(themeGroupsFile.MANGLE_RUNTIME_VIRTUAL_ID)) {
4110
4007
  return null;
4111
4008
  }
4112
- return insertRuntimeImport(transformedCode, `import '${MANGLE_RUNTIME_VIRTUAL_ID}';
4009
+ return insertRuntimeImport(transformedCode, `import '${themeGroupsFile.MANGLE_RUNTIME_VIRTUAL_ID}';
4113
4010
  `);
4114
4011
  }
4115
4012
  function collectPreTransformClasses(output) {
@@ -4136,8 +4033,8 @@ ${transformedCode}`;
4136
4033
  * @returns resolved ID if virtual, null otherwise
4137
4034
  */
4138
4035
  resolveId(id) {
4139
- if (isVirtualModule(id)) {
4140
- return resolveVirtualModule(id);
4036
+ if (themeGroupsFile.isVirtualModule(id)) {
4037
+ return themeGroupsFile.resolveVirtualModule(id);
4141
4038
  }
4142
4039
  return null;
4143
4040
  },
@@ -4154,7 +4051,7 @@ ${transformedCode}`;
4154
4051
  * @returns true only for csszyx virtual modules
4155
4052
  */
4156
4053
  loadInclude(id) {
4157
- return id === RESOLVED_VIRTUAL_MODULE_ID || id === RESOLVED_VIRTUAL_CHECKSUM_ID || id === RESOLVED_THEME_GROUPS_VIRTUAL_ID || id === RESOLVED_MANGLE_RUNTIME_VIRTUAL_ID;
4054
+ return id === themeGroupsFile.RESOLVED_VIRTUAL_MODULE_ID || id === themeGroupsFile.RESOLVED_VIRTUAL_CHECKSUM_ID || id === themeGroupsFile.RESOLVED_THEME_GROUPS_VIRTUAL_ID || id === themeGroupsFile.RESOLVED_MANGLE_RUNTIME_VIRTUAL_ID;
4158
4055
  },
4159
4056
  /**
4160
4057
  * Loads virtual module content — generates mangle map or checksum module code.
@@ -4162,30 +4059,25 @@ ${transformedCode}`;
4162
4059
  * @returns generated module source if virtual, null otherwise
4163
4060
  */
4164
4061
  load(id) {
4165
- if (id === RESOLVED_VIRTUAL_MODULE_ID) {
4062
+ if (id === themeGroupsFile.RESOLVED_VIRTUAL_MODULE_ID) {
4166
4063
  finalizeMangleMap();
4167
- return createMangleMapModule(
4064
+ return themeGroupsFile.createMangleMapModule(
4168
4065
  state.mangleMap,
4169
4066
  state.checksum,
4170
4067
  state.varMangleMap,
4171
4068
  state.cssVarMetrics
4172
4069
  );
4173
4070
  }
4174
- if (id === RESOLVED_VIRTUAL_CHECKSUM_ID) {
4071
+ if (id === themeGroupsFile.RESOLVED_VIRTUAL_CHECKSUM_ID) {
4175
4072
  finalizeMangleMap();
4176
- return createChecksumModule(state.checksum);
4073
+ return themeGroupsFile.createChecksumModule(state.checksum);
4177
4074
  }
4178
- if (id === RESOLVED_MANGLE_RUNTIME_VIRTUAL_ID) {
4179
- return createMangleRuntimeModule(globalVarAliasPrefix);
4075
+ if (id === themeGroupsFile.RESOLVED_MANGLE_RUNTIME_VIRTUAL_ID) {
4076
+ sizeAccount.channels.add("bundle");
4077
+ return themeGroupsFile.createMangleRuntimeModule(globalVarAliasPrefix);
4180
4078
  }
4181
- if (id === RESOLVED_THEME_GROUPS_VIRTUAL_ID) {
4182
- const theme = state.parsedTheme;
4183
- return createThemeGroupsModule({
4184
- colors: theme?.colors ?? [],
4185
- textSizes: theme?.textSizes ?? [],
4186
- fontFamilies: theme?.fonts ?? [],
4187
- fontWeights: theme?.fontWeights ?? []
4188
- });
4079
+ if (id === themeGroupsFile.RESOLVED_THEME_GROUPS_VIRTUAL_ID) {
4080
+ return themeGroupsFile.createThemeGroupsModule(themeGroupTokens());
4189
4081
  }
4190
4082
  return null;
4191
4083
  },
@@ -4199,7 +4091,11 @@ ${transformedCode}`;
4199
4091
  if (shouldProcessCss(id)) {
4200
4092
  return true;
4201
4093
  }
4202
- return shouldProcessSource(id);
4094
+ if (shouldProcessSource(id)) {
4095
+ return true;
4096
+ }
4097
+ recordPackagesSkipIfSz(id);
4098
+ return false;
4203
4099
  },
4204
4100
  /**
4205
4101
  * Core transform: detects sz prop, compiles to className, injects runtime, collects classes.
@@ -4223,7 +4119,12 @@ ${transformedCode}`;
4223
4119
  if (matchesScriptExtension(id, [".css"])) {
4224
4120
  return transformTailwindCssEntry(code, id);
4225
4121
  }
4226
- const hasSzProp = code.includes("sz=") || code.includes("szs=") || /\bsz\s*:\s*["'{]/.test(code) || code.includes('sz: "');
4122
+ 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
4123
+ // compiler entirely — which also skipped the szr import
4124
+ // rewrite AND the szr fallback diagnostics. The substring is
4125
+ // deliberately loose; a false positive only costs one file
4126
+ // the compiler pass, which then changes nothing.
4127
+ code.includes("szr(");
4227
4128
  const output = hasSzProp ? transformSzSource(code, id, (message) => this.warn(message)) : unchangedPreTransform(code);
4228
4129
  if (!hasSzProp && shouldProcessSource(id)) {
4229
4130
  recordFileVarMangleEntries(state, id, []);
@@ -4281,9 +4182,13 @@ ${transformedCode}`;
4281
4182
  }
4282
4183
  if (!state.skipWarningEmitted && state.skippedSzFiles.size > 0) {
4283
4184
  state.skipWarningEmitted = true;
4284
- emitWarning(skippedSzFilesMessage(compiler.sortStrings(state.skippedSzFiles)), {
4285
- devOnly: true
4286
- });
4185
+ emitWarning(
4186
+ skippedSzFilesMessage(
4187
+ compiler.sortStrings(state.skippedSzFiles),
4188
+ compiler.sortStrings(state.skippedSzvExportFiles)
4189
+ ),
4190
+ { devOnly: state.skippedSzvExportFiles.size === 0 }
4191
+ );
4287
4192
  }
4288
4193
  if (state.classesCapped) {
4289
4194
  emitWarning(
@@ -4305,7 +4210,10 @@ ${transformedCode}`;
4305
4210
  recordGlobalVarSourceFile(state, id, null);
4306
4211
  recordFileVarMangleEntries(state, id, []);
4307
4212
  recordFileCSSVariableMetrics(state, id, null);
4213
+ refreshSzvRegistryEntry(id, null);
4214
+ return;
4308
4215
  }
4216
+ refreshSzvRegistryEntryFromDisk(id);
4309
4217
  },
4310
4218
  /**
4311
4219
  * Webpack hook: pre-scans source files before compilation for Tailwind class discovery.
@@ -4313,18 +4221,37 @@ ${transformedCode}`;
4313
4221
  */
4314
4222
  webpack(compiler) {
4315
4223
  activeFramework = "webpack";
4224
+ compiler.hooks?.beforeCompile?.tap?.("csszyx:theme-groups", () => {
4225
+ const root = compiler.context || process.cwd();
4226
+ themeGroupsFile.ensureThemeGroupsFile(root, path__namespace.join(root, ".csszyx"));
4227
+ });
4316
4228
  if (compiler.options?.mode === "development") {
4317
4229
  manglingEnabled = false;
4318
4230
  }
4231
+ if (manglingEnabled && mangleMapDelivery !== "both") {
4232
+ console.warn(
4233
+ `[csszyx] production.mangleMapDelivery: '${mangleMapDelivery}' has no effect on the webpack lane \u2014 map delivery only narrows on vite/rollup builds.`
4234
+ );
4235
+ }
4319
4236
  compiler.hooks.beforeCompile.tap("csszyx:prescan", () => {
4320
4237
  announceActiveParser();
4321
4238
  const root = compiler.context || process.cwd();
4322
4239
  state.rootDir = root;
4240
+ specifierAliases = transformCache.collectSpecifierAliases(
4241
+ root,
4242
+ compiler.options?.resolve?.alias
4243
+ );
4323
4244
  evictTransformCacheOnce();
4324
4245
  if (state.classes.size === 0) {
4325
4246
  prescanAndWriteClasses();
4326
4247
  }
4327
- state.parsedTheme = runThemeScan(root, options.build?.scanCss) ?? state.parsedTheme;
4248
+ for (const changed of compiler.modifiedFiles ?? []) {
4249
+ refreshSzvRegistryEntryFromDisk(changed);
4250
+ }
4251
+ for (const removed of compiler.removedFiles ?? []) {
4252
+ refreshSzvRegistryEntry(removed, null);
4253
+ }
4254
+ state.scanCssTheme = runThemeScan(root, options.build?.scanCss) ?? state.scanCssTheme;
4328
4255
  runAutoThemeScan(root);
4329
4256
  });
4330
4257
  if (options.build?.scanCss) {
@@ -4353,12 +4280,13 @@ ${transformedCode}`;
4353
4280
  announceActiveParser();
4354
4281
  const root = config.root || process.cwd();
4355
4282
  state.rootDir = root;
4283
+ specifierAliases = transformCache.collectSpecifierAliases(root, config.resolve?.alias);
4356
4284
  if (config.command === "serve") {
4357
4285
  manglingEnabled = false;
4358
4286
  }
4359
4287
  evictTransformCacheOnce();
4360
4288
  prescanAndWriteClasses();
4361
- state.parsedTheme = runThemeScan(root, options.build?.scanCss) ?? state.parsedTheme;
4289
+ state.scanCssTheme = runThemeScan(root, options.build?.scanCss) ?? state.scanCssTheme;
4362
4290
  runAutoThemeScan(root);
4363
4291
  },
4364
4292
  /**
@@ -4371,21 +4299,23 @@ ${transformedCode}`;
4371
4299
  const scanCss = options.build?.scanCss;
4372
4300
  const reloadThemeGroupsModule = () => {
4373
4301
  const themeGroupsModule = ctx.server.moduleGraph.getModuleById(
4374
- RESOLVED_THEME_GROUPS_VIRTUAL_ID
4302
+ themeGroupsFile.RESOLVED_THEME_GROUPS_VIRTUAL_ID
4375
4303
  );
4376
4304
  if (themeGroupsModule) {
4377
4305
  ctx.server.moduleGraph.invalidateModule(themeGroupsModule);
4378
4306
  }
4379
4307
  };
4380
- if (scanCss) {
4308
+ if (ctx.file.endsWith(".css")) {
4381
4309
  const root = ctx.server.config.root || process.cwd();
4382
- if (matchesAnyPattern(ctx.file, scanCss, root)) {
4383
- state.parsedTheme = runThemeScan(root, scanCss) ?? state.parsedTheme;
4384
- reloadThemeGroupsModule();
4310
+ const before = themeGroupsFile.createThemeGroupsModule(themeGroupTokens());
4311
+ if (scanCss && matchesAnyPattern(ctx.file, scanCss, root)) {
4312
+ state.scanCssTheme = runThemeScan(root, scanCss) ?? state.scanCssTheme;
4385
4313
  }
4386
- } else if (ctx.file.endsWith(".css")) {
4387
- runAutoThemeScan(ctx.server.config.root || process.cwd());
4314
+ runAutoThemeScan(root);
4388
4315
  reloadThemeGroupsModule();
4316
+ if (themeGroupsFile.createThemeGroupsModule(themeGroupTokens()) !== before) {
4317
+ ctx.server.ws.send({ type: "full-reload" });
4318
+ }
4389
4319
  }
4390
4320
  if (!shouldProcessSource(ctx.file)) {
4391
4321
  return;
@@ -4394,8 +4324,10 @@ ${transformedCode}`;
4394
4324
  try {
4395
4325
  fileContent = fs__namespace.readFileSync(ctx.file, "utf-8");
4396
4326
  } catch {
4327
+ refreshSzvRegistryEntry(ctx.file, null);
4397
4328
  return;
4398
4329
  }
4330
+ refreshSzvRegistryEntry(ctx.file, fileContent);
4399
4331
  if (!fileContent.includes("sz=") && !fileContent.includes("szs=") && !/\bsz\s*:\s*["'{]/.test(fileContent)) {
4400
4332
  trackGlobalVarSourceFile(ctx.file, fileContent);
4401
4333
  recordFileVarMangleEntries(state, ctx.file, []);
@@ -4456,8 +4388,12 @@ ${transformedCode}`;
4456
4388
  mode: "script",
4457
4389
  minify: process.env.NODE_ENV === "production",
4458
4390
  varMangleMap: state.varMangleMap,
4459
- globalVarAliasPrefix
4391
+ globalVarAliasPrefix,
4392
+ installRuntimeObject: deliverMapInHtml
4460
4393
  });
4394
+ if (manglingEnabled) {
4395
+ sizeAccount.channels.add("html");
4396
+ }
4461
4397
  if (state.recoveryTokens.size > 0) {
4462
4398
  const isProduction = process.env.NODE_ENV === "production";
4463
4399
  const { manifest, strippedDevOnlyPaths } = buildRecoveryManifest(
@@ -4506,7 +4442,7 @@ ${transformedCode}`;
4506
4442
  return manifest;
4507
4443
  }
4508
4444
  function rewriteOutputCss(source, file, shouldMangle, mangledSources, externalClasses) {
4509
- let css = rewriteCssWithValidatedGlobalVarPlan(
4445
+ const css = rewriteCssWithValidatedGlobalVarPlan(
4510
4446
  source,
4511
4447
  file,
4512
4448
  state.globalVarValidationResult
@@ -4519,8 +4455,9 @@ ${transformedCode}`;
4519
4455
  });
4520
4456
  for (const className of result.mangledClasses) mangledSources.add(className);
4521
4457
  for (const className of result.unmangledClasses) externalClasses.add(className);
4522
- if (result.transformedCount > 0) css = result.css;
4523
- return css;
4458
+ const mangled = result.transformedCount > 0 ? result.css : css;
4459
+ recordCssPair(sizeAccount, css, mangled);
4460
+ return mangled;
4524
4461
  } catch (error) {
4525
4462
  if (isCssSyntaxError(error)) return css;
4526
4463
  throw error;
@@ -4532,6 +4469,16 @@ ${transformedCode}`;
4532
4469
  collectMangleHybridHazards(state.mangleMap, mangledSources, externalClasses)
4533
4470
  );
4534
4471
  if (message) console.warn(message);
4472
+ reportMangleSize();
4473
+ }
4474
+ function reportMangleSize() {
4475
+ const verdict = computeMangleSizeVerdict(
4476
+ sizeAccount,
4477
+ JSON.stringify(createHydrationMangleMap(state.mangleMap, state.varMangleMap))
4478
+ );
4479
+ const message = mangleSizeMessage(verdict);
4480
+ if (message) console.warn(message);
4481
+ resetMangleSizeAccount(sizeAccount);
4535
4482
  }
4536
4483
  function rewriteWebpackCodeAsset(file, source, shouldMangle, compilation, compiler) {
4537
4484
  if (shouldMangle && file.endsWith(".html")) {
@@ -4615,7 +4562,9 @@ ${transformedCode}`;
4615
4562
  collectRollupGlobalVarCssAssets(bundle)
4616
4563
  );
4617
4564
  const shouldMangle = manglingEnabled && Object.keys(state.mangleMap).length > 0;
4618
- emitAsset("csszyx-manifest.json", JSON.stringify(createBundleManifest(shouldMangle)));
4565
+ if (options.build?.emitManifest === true) {
4566
+ emitAsset("csszyx-manifest.json", JSON.stringify(createBundleManifest(shouldMangle)));
4567
+ }
4619
4568
  if (shouldEmitGlobalVarMapAsset(globalVarMangleConfig)) {
4620
4569
  const globalVarMap = createGlobalVarMapAssetSource(
4621
4570
  state.varMangleMap,
@@ -4729,6 +4678,7 @@ exports.createRSCModuleRecord = createRSCModuleRecord;
4729
4678
  exports.cssHasContentScope = cssHasContentScope;
4730
4679
  exports.cssImportsTailwind = cssImportsTailwind;
4731
4680
  exports.deleteRSCModuleRecord = deleteRSCModuleRecord;
4681
+ exports.emitMissingCssFallback = emitMissingCssFallback;
4732
4682
  exports.esbuildPlugin = esbuildPlugin;
4733
4683
  exports.extractGlobalVarAliasesForManifest = extractGlobalVarAliasesForManifest;
4734
4684
  exports.fileMayContainSafelistableSz = fileMayContainSafelistableSz;
@@ -4736,7 +4686,6 @@ exports.findLocalImportSources = findLocalImportSources;
4736
4686
  exports.findRSCBoundaryViolation = findRSCBoundaryViolation;
4737
4687
  exports.findRSCGraphViolation = findRSCGraphViolation;
4738
4688
  exports.hasInjectableTailwindCandidate = hasInjectableTailwindCandidate;
4739
- exports.hasTokens = hasTokens;
4740
4689
  exports.hasUseClientDirective = hasUseClientDirective;
4741
4690
  exports.hasUseServerDirective = hasUseServerDirective;
4742
4691
  exports.isCompileSourceOptedIn = isCompileSourceOptedIn;
@@ -4748,20 +4697,19 @@ exports.isTailwindReservedGlobalVar = isTailwindReservedGlobalVar;
4748
4697
  exports.mangleCodeClassesSync = mangleCodeClassesSync;
4749
4698
  exports.mangleEligibleClasses = mangleEligibleClasses;
4750
4699
  exports.mangleHybridHazardMessage = mangleHybridHazardMessage;
4751
- exports.mergeThemes = mergeThemes;
4752
4700
  exports.missingTailwindEntryMessage = missingTailwindEntryMessage;
4753
4701
  exports.normalizeGlobalVarAliasesForCache = normalizeGlobalVarAliasesForCache;
4754
- exports.parseThemeBlocks = parseThemeBlocks;
4755
4702
  exports.planGlobalVarAliases = planGlobalVarAliases;
4756
4703
  exports.readGlobalVarScanCache = readGlobalVarScanCache;
4757
4704
  exports.recordGlobalVarSourceFile = recordGlobalVarSourceFile;
4758
4705
  exports.resolveCompileSourceDirs = resolveCompileSourceDirs;
4759
4706
  exports.resolveGlobalVarScanCacheDir = resolveGlobalVarScanCacheDir;
4760
4707
  exports.resolveNativeCacheIdentity = resolveNativeCacheIdentity;
4708
+ exports.resolveQuietMode = resolveQuietMode;
4761
4709
  exports.rewriteGlobalVarCssAliases = rewriteGlobalVarCssAliases;
4762
4710
  exports.rollupPlugin = rollupPlugin;
4763
- exports.scanCustomPropertyNames = scanCustomPropertyNames;
4764
4711
  exports.scanGlobalVarCss = scanGlobalVarCss;
4712
+ exports.shouldEmitMissingCssFallback = shouldEmitMissingCssFallback;
4765
4713
  exports.shouldEmitWarning = shouldEmitWarning;
4766
4714
  exports.shouldTrackGlobalVarSources = shouldTrackGlobalVarSources;
4767
4715
  exports.shouldWarnMissingTailwindEntry = shouldWarnMissingTailwindEntry;