@csszyx/unplugin 0.14.5 → 0.15.1

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 (52) hide show
  1. package/README.md +4 -3
  2. package/dist/index.cjs +8 -7
  3. package/dist/index.d.cts +70 -3
  4. package/dist/index.d.mts +70 -3
  5. package/dist/index.mjs +4 -4
  6. package/dist/next-config.d.cts +1 -2
  7. package/dist/next-config.d.mts +1 -2
  8. package/dist/next-prebuild.cjs +9 -5
  9. package/dist/next-prebuild.d.cts +4 -2
  10. package/dist/next-prebuild.d.mts +4 -2
  11. package/dist/next-prebuild.mjs +8 -4
  12. package/dist/next-turbo-loader.cjs +20 -14
  13. package/dist/next-turbo-loader.d.cts +1 -1
  14. package/dist/next-turbo-loader.d.mts +1 -1
  15. package/dist/next-turbo-loader.mjs +19 -13
  16. package/dist/next-watcher.cjs +2 -2
  17. package/dist/next-watcher.d.cts +2 -2
  18. package/dist/next-watcher.d.mts +2 -2
  19. package/dist/next-watcher.mjs +2 -2
  20. package/dist/postcss.cjs +124 -0
  21. package/dist/postcss.d.cts +42 -0
  22. package/dist/postcss.d.mts +42 -0
  23. package/dist/postcss.mjs +107 -0
  24. package/dist/shared/{unplugin.RGzhYt-D.cjs → unplugin.8KYddE6x.cjs} +394 -226
  25. package/dist/shared/{unplugin.CPEWNSA0.d.cts → unplugin.BGog1Bib.d.cts} +9 -6
  26. package/dist/shared/{unplugin.CPEWNSA0.d.mts → unplugin.BGog1Bib.d.mts} +9 -6
  27. package/dist/shared/{unplugin.BU0O4IkX.mjs → unplugin.BLptVbUe.mjs} +22 -61
  28. package/dist/shared/{unplugin.BXYakiXt.d.cts → unplugin.BT7PqYuK.d.cts} +53 -55
  29. package/dist/shared/{unplugin.BXYakiXt.d.mts → unplugin.BT7PqYuK.d.mts} +53 -55
  30. package/dist/shared/{unplugin.Cji6O5jv.cjs → unplugin.BWnmKv07.cjs} +32 -69
  31. package/dist/shared/{unplugin.NlPvn5P4.mjs → unplugin.Bk9o8_RZ.mjs} +2 -6
  32. package/dist/shared/{unplugin.VtXstzEh.cjs → unplugin.BzF0V2kw.cjs} +6 -11
  33. package/dist/shared/{unplugin.CdZxp0x-.d.mts → unplugin.COlI0dJs.d.mts} +1 -1
  34. package/dist/shared/{unplugin.BnRf0Tvd.mjs → unplugin.D68hyqgb.mjs} +347 -178
  35. package/dist/shared/{unplugin.DN95k991.mjs → unplugin.DAzgbtuZ.mjs} +2 -2
  36. package/dist/shared/unplugin.DDSWQJYX.cjs +289 -0
  37. package/dist/shared/unplugin.DH_ij6cf.mjs +258 -0
  38. package/dist/shared/{unplugin.BZPdvVcj.mjs → unplugin.DK0b4fr7.mjs} +105 -127
  39. package/dist/shared/{unplugin.D8BxOOkA.cjs → unplugin.J6ue_lRJ.cjs} +121 -142
  40. package/dist/shared/{unplugin.DVbPNK3W.cjs → unplugin.gksolKh2.cjs} +6 -6
  41. package/dist/shared/{unplugin.xeED_qwh.d.cts → unplugin.rWOMecQs.d.cts} +1 -1
  42. package/dist/vite.cjs +4 -4
  43. package/dist/vite.d.cts +2 -2
  44. package/dist/vite.d.mts +1 -1
  45. package/dist/vite.mjs +4 -4
  46. package/dist/webpack.cjs +4 -4
  47. package/dist/webpack.d.cts +2 -1
  48. package/dist/webpack.d.mts +1 -1
  49. package/dist/webpack.mjs +4 -4
  50. package/package.json +19 -9
  51. package/dist/shared/unplugin.B3XoSRB8.mjs +0 -40
  52. package/dist/shared/unplugin.BkRah5Ot.cjs +0 -48
@@ -1,9 +1,9 @@
1
1
  import { createHash } from 'node:crypto';
2
2
  import * as fs from 'node:fs';
3
- import { mkdirSync, writeFileSync } from 'node:fs';
3
+ import fs__default, { mkdirSync, writeFileSync } from 'node:fs';
4
4
  import { createRequire } from 'node:module';
5
5
  import * as path from 'node:path';
6
- import { dirname } from 'node:path';
6
+ import path__default, { dirname } from 'node:path';
7
7
  import { performance } from 'node:perf_hooks';
8
8
  import { fileURLToPath } from 'node:url';
9
9
  import { scanGlobalVarUsages, sortStrings as sortStrings$1, szFallbackConsequenceOf, isWasmTransformAvailable, isRustTransformAvailable, ensureRustTransformAvailable, transformRust, transformWasm, ASTBudgetExceededError, transformRustBatch, transform } from '@csszyx/compiler';
@@ -13,10 +13,10 @@ import { preprocess as preprocess$1 } from '@csszyx/svelte-adapter';
13
13
  import { isTailwindReservedCustomProperty, CSSZYX_GLOBAL_ALIAS_PREFIX, isCsszyxGlobalAliasCustomProperty, DEFAULT_IMPORTED_STATIC_SZ, 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, c as collectSpecifierAliases, h as recordSzvRegistryFile, j as recordCrossModuleForwards, k as recordSzObjectRegistryFile, l as resolveCrossModuleStaticsFor, r as resolveTransformCacheDir, e as createTransformCacheKey, w as writeTransformCache, m as evictOldTransformCacheEntries, o as mayExportSzvFactories, i as importedSpecifiersIn, s as specifierBases, a as resolveProviderPathWith, g as readTransformCache, p as evictMemoryCacheToBudget, q as resolveProviderPath, d as isReadableProviderFile } from './unplugin.NlPvn5P4.mjs';
16
+ import { s as sortStrings, n as normalizePathSeparators, h as stripCssBlockComments, S as SAFELIST_FILE, i as findLegacySourceDirective, l as legacySourceMessage, b as cssImportsTailwind, c as computeSafelistRelPath, a as appendTailwindSourceDirective, r as renderSafelistFile, d as atomicWriteFileSync, e as removeLegacySafelists } from './unplugin.DH_ij6cf.mjs';
17
+ import { c as collectSpecifierAliases, r as resolveTransformCacheDir, h as evictOldTransformCacheEntries, j as recordSzvRegistryFile, k as recordCrossModuleForwards, l as recordSzObjectRegistryFile, m as mayExportSzvFactories, n as resolveCrossModuleStaticsFor, e as createTransformCacheKey, w as writeTransformCache, o as resolveProviderPath, i as importedSpecifiersIn, s as specifierBases, a as resolveProviderPathWith, g as readTransformCache, p as evictMemoryCacheToBudget, d as isReadableProviderFile } from './unplugin.Bk9o8_RZ.mjs';
17
18
  import { mangleCSSSync } from '../css-mangler.mjs';
18
- import { c as createThemeGroupsModule, e as ensureThemeGroupsFile, R as RESOLVED_VIRTUAL_MODULE_ID, d as createMangleMapModule, f as RESOLVED_VIRTUAL_CHECKSUM_ID, g as createChecksumModule, j as RESOLVED_MANGLE_RUNTIME_VIRTUAL_ID, k as createMangleRuntimeModule, l as RESOLVED_THEME_GROUPS_VIRTUAL_ID, n as isVirtualModule, r as resolveVirtualModule, p as parseThemeBlocks, m as mergeThemes, o as discoverProjectTheme, C as CHECKSUM_PLACEHOLDER, M as MANGLE_MAP_PLACEHOLDER, V as VAR_MANGLE_MAP_PLACEHOLDER, q as importsRuntimeHelper, u as findRuntimeImportClause, T as THEME_GROUPS_VIRTUAL_ID, v as THEME_GROUPS_FILE_MARKER, t as themeGroupsSpecifier, w as MANGLE_RUNTIME_VIRTUAL_ID, a as parseUtilityBlocks, x as runtimeHelperGroupsFromUsage, b as insertAfterUseDirective } from './unplugin.BZPdvVcj.mjs';
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';
19
+ import { c as createMangleRuntimeModule, M as MANGLE_RUNTIME_VIRTUAL_ID, d as createThemeGroupsModule, e as ensureThemeGroupsFile, R as RESOLVED_VIRTUAL_MODULE_ID, f as createMangleMapModule, g as RESOLVED_VIRTUAL_CHECKSUM_ID, j as createChecksumModule, k as RESOLVED_MANGLE_RUNTIME_VIRTUAL_ID, l as RESOLVED_THEME_GROUPS_VIRTUAL_ID, n as isVirtualModule, r as resolveVirtualModule, p as parseThemeBlocks, m as mergeThemes, o as discoverProjectTheme, C as CHECKSUM_PLACEHOLDER, q as CENSUS_PLACEHOLDER, u as importsRuntimeHelper, v as findRuntimeImportClause, T as THEME_GROUPS_VIRTUAL_ID, w as THEME_GROUPS_FILE_MARKER, t as themeGroupsSpecifier, a as parseUtilityBlocks, x as runtimeHelperGroupsFromUsage, b as insertAfterUseDirective, y as MANGLE_MAP_PLACEHOLDER, V as VAR_MANGLE_MAP_PLACEHOLDER } from './unplugin.DK0b4fr7.mjs';
20
20
  import { gzipSync } from 'node:zlib';
21
21
  import postcss from 'postcss';
22
22
  import valueParser from 'postcss-value-parser';
@@ -1710,6 +1710,24 @@ function expandFilePatterns(rootDir, patterns) {
1710
1710
  return sortStrings(files);
1711
1711
  }
1712
1712
 
1713
+ const BACKSLASH = String.fromCodePoint(92);
1714
+ function unicodeEscape(hexadecimal) {
1715
+ return `${BACKSLASH}u${hexadecimal}`;
1716
+ }
1717
+ function replaceEveryLiteral(value, search, replacement) {
1718
+ return value.replaceAll(search, () => replacement);
1719
+ }
1720
+ function escapeSingleQuotedString(value) {
1721
+ let escaped = replaceEveryLiteral(value, BACKSLASH, BACKSLASH.repeat(2));
1722
+ escaped = replaceEveryLiteral(escaped, "'", `${BACKSLASH}'`);
1723
+ escaped = replaceEveryLiteral(escaped, "\r", `${BACKSLASH}r`);
1724
+ return replaceEveryLiteral(escaped, "\n", `${BACKSLASH}n`);
1725
+ }
1726
+ function escapeDoubleQuotedString(value) {
1727
+ const escaped = replaceEveryLiteral(value, BACKSLASH, BACKSLASH.repeat(2));
1728
+ return replaceEveryLiteral(escaped, '"', `${BACKSLASH}"`);
1729
+ }
1730
+
1713
1731
  const LINE_SEPARATOR$1 = String.fromCodePoint(8232);
1714
1732
  const PARAGRAPH_SEPARATOR$1 = String.fromCodePoint(8233);
1715
1733
  function safeJsonForScriptTag(value, prettyPrint = false) {
@@ -1744,31 +1762,22 @@ function injectChecksum(html, checksum, minify = false) {
1744
1762
  const attrName = minify ? "data-sz-cs" : "data-sz-checksum";
1745
1763
  return injectHtmlOpeningAttr(html, ` ${attrName}="${checksum}"`);
1746
1764
  }
1747
- function injectMangleMapScript(html, mangleMap, options = {}) {
1748
- const {
1749
- prettyPrint = false,
1750
- varMangleMap = {},
1751
- globalVarAliasPrefix = CSSZYX_GLOBAL_ALIAS_PREFIX,
1752
- installRuntimeObject = true
1753
- } = options;
1754
- const checksumMap = createHydrationMangleMap(mangleMap, varMangleMap);
1755
- const jsonContent = safeJsonForScriptTag(checksumMap, prettyPrint);
1756
- const varMapContent = safeJsonForScriptTag(varMangleMap);
1757
- const reuseChecksumPayload = Object.keys(varMangleMap).length === 0;
1758
- const classMapExpr = reuseChecksumPayload ? '(function(){var e=document.getElementById("__CSSZYX_MANGLE_MAP__");return e?JSON.parse(e.textContent):{}})()' : safeJsonForScriptTag(mangleMap);
1759
- const scriptTag = `<script id="__CSSZYX_MANGLE_MAP__" type="application/json">${jsonContent}<\/script>`;
1760
- const prefixContent = safeJsonForScriptTag(globalVarAliasPrefix);
1761
- 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>`;
1762
- const combined = installRuntimeObject ? `${scriptTag}
1763
- ${debugScript}` : scriptTag;
1765
+ function withScriptTag(html, scriptTag) {
1764
1766
  if (html.includes("</head>")) {
1765
- return html.replace("</head>", `${combined}
1767
+ return html.replace("</head>", `${scriptTag}
1766
1768
  </head>`);
1767
- } else if (html.includes("</html>")) {
1768
- return html.replace("</html>", `${combined}
1769
+ }
1770
+ if (html.includes("</html>")) {
1771
+ return html.replace("</html>", `${scriptTag}
1769
1772
  </html>`);
1770
1773
  }
1771
- return html + combined;
1774
+ return html + scriptTag;
1775
+ }
1776
+ function injectMangleMapScript(html, mangleMap, options = {}) {
1777
+ const { prettyPrint = false, varMangleMap = {} } = options;
1778
+ const checksumMap = createHydrationMangleMap(mangleMap, varMangleMap);
1779
+ const scriptTag = `<script id="__CSSZYX_MANGLE_MAP__" type="application/json">${safeJsonForScriptTag(checksumMap, prettyPrint)}<\/script>`;
1780
+ return withScriptTag(html, scriptTag);
1772
1781
  }
1773
1782
  function injectMangleMapAttribute(html, mangleMap, minify = false, varMangleMap = {}) {
1774
1783
  const attrName = minify ? "data-sz-m" : "data-sz-map";
@@ -1842,14 +1851,7 @@ function injectRecoveryManifest(html, manifest) {
1842
1851
  }
1843
1852
  const json = JSON.stringify(manifest);
1844
1853
  const scriptTag = `<script id="__SZ_RECOVERY_MANIFEST__" type="application/json">${json}<\/script>`;
1845
- if (html.includes("</head>")) {
1846
- return html.replace("</head>", `${scriptTag}
1847
- </head>`);
1848
- } else if (html.includes("</html>")) {
1849
- return html.replace("</html>", `${scriptTag}
1850
- </html>`);
1851
- }
1852
- return html + scriptTag;
1854
+ return withScriptTag(html, scriptTag);
1853
1855
  }
1854
1856
 
1855
1857
  const LINE_SEPARATOR = String.fromCodePoint(8232);
@@ -1861,10 +1863,87 @@ function escapeJsonForInlineScript(json) {
1861
1863
  escaped = replaceEveryLiteral(escaped, LINE_SEPARATOR, unicodeEscape("2028"));
1862
1864
  return replaceEveryLiteral(escaped, PARAGRAPH_SEPARATOR, unicodeEscape("2029"));
1863
1865
  }
1866
+ function escapeJsonForStringLiteral(json) {
1867
+ let escaped = replaceEveryLiteral(json, "\\", unicodeEscape("005c"));
1868
+ for (const [character, code] of [
1869
+ ['"', "0022"],
1870
+ ["'", "0027"],
1871
+ ["`", "0060"],
1872
+ ["$", "0024"],
1873
+ ["<", "003c"],
1874
+ [">", "003e"],
1875
+ [LINE_SEPARATOR, "2028"],
1876
+ [PARAGRAPH_SEPARATOR, "2029"]
1877
+ ]) {
1878
+ escaped = replaceEveryLiteral(escaped, character, unicodeEscape(code));
1879
+ }
1880
+ return escaped;
1881
+ }
1864
1882
  function escapeForDoubleQuotedString(value) {
1865
1883
  return escapeDoubleQuotedString(value);
1866
1884
  }
1867
1885
 
1886
+ function createLazyAggregate(build, initial) {
1887
+ const entries = /* @__PURE__ */ new Map();
1888
+ let current = initial;
1889
+ let dirty = false;
1890
+ return {
1891
+ entries,
1892
+ set(key, entry) {
1893
+ entries.set(key, entry);
1894
+ dirty = true;
1895
+ },
1896
+ delete(key) {
1897
+ if (entries.delete(key)) dirty = true;
1898
+ },
1899
+ get() {
1900
+ if (dirty) {
1901
+ current = build(entries);
1902
+ dirty = false;
1903
+ }
1904
+ return current;
1905
+ }
1906
+ };
1907
+ }
1908
+
1909
+ function needsRuntimeMangleRegistration(manglingEnabled, mangleMap) {
1910
+ if (!manglingEnabled) return false;
1911
+ return Object.keys(mangleMap).length > 0;
1912
+ }
1913
+ function removedMangleMapDeliveryMessage() {
1914
+ return "[csszyx] production.mangleMapDelivery has been removed and is ignored. The runtime mangle map is always registered from inside the JS bundle now, on every lane, so the built HTML never carries an executable inline <script> and a strict script-src 'self' policy needs no exception. Delete the option. (`window.__csszyx` is now opt-in through `production.mangleDebugGlobal`.)";
1915
+ }
1916
+
1917
+ const MANGLE_RUNTIME_FILE = "mangle-runtime.mjs";
1918
+ function ensureMangleRuntimeFile(outputDir, globalVarAliasPrefix, exposeDebugGlobal) {
1919
+ const target = path__default.join(outputDir, MANGLE_RUNTIME_FILE);
1920
+ const staging = `${target}.${process.pid}.tmp`;
1921
+ try {
1922
+ fs__default.mkdirSync(outputDir, { recursive: true });
1923
+ fs__default.writeFileSync(
1924
+ staging,
1925
+ createMangleRuntimeModule(globalVarAliasPrefix, exposeDebugGlobal),
1926
+ "utf8"
1927
+ );
1928
+ fs__default.renameSync(staging, target);
1929
+ return target;
1930
+ } catch {
1931
+ try {
1932
+ fs__default.rmSync(staging, { force: true });
1933
+ } catch {
1934
+ }
1935
+ return null;
1936
+ }
1937
+ }
1938
+ function applyMangleRuntimeEntry(compiler, context, file, onRegistered) {
1939
+ const EntryPlugin = compiler.webpack?.EntryPlugin;
1940
+ if (EntryPlugin === void 0) {
1941
+ return;
1942
+ }
1943
+ new EntryPlugin(context, file, { name: void 0 }).apply(compiler);
1944
+ onRegistered();
1945
+ }
1946
+
1868
1947
  function createMangleSizeAccount() {
1869
1948
  return { cssGzBefore: 0, cssGzAfter: 0, codeGzBefore: 0, codeGzAfter: 0, channels: /* @__PURE__ */ new Set() };
1870
1949
  }
@@ -1912,7 +1991,7 @@ function mangleSizeMessage(verdict) {
1912
1991
  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)`;
1913
1992
  const codePart = verdict.codeSaving >= 0 ? `the shortened classes in code save ${verdict.codeSaving} B` : `the shortened classes in code COST ${-verdict.codeSaving} B`;
1914
1993
  const channelPart = verdict.channels.length > 1 ? `${verdict.channels.join(" + ")} (${verdict.channels.length} copies)` : verdict.channels[0];
1915
- 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} and ${codePart}. 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.`;
1994
+ 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} and ${codePart}. 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. Two copies is not a misconfiguration: the bundle carries the map the runtime reads, and the HTML carries the same census for the hydration checksum.`;
1916
1995
  }
1917
1996
 
1918
1997
  function isParserMode(value) {
@@ -2079,6 +2158,7 @@ function findOpeningTag(source, tag) {
2079
2158
  }
2080
2159
  }
2081
2160
  const _warnedClassNameAuthors = /* @__PURE__ */ new Set();
2161
+ const _warnedSafelistWriteFailures = /* @__PURE__ */ new Set();
2082
2162
  let _hasWarnedTsConfig = false;
2083
2163
  let _hasWarnedTransformCacheVersion = false;
2084
2164
  let _hasWarnedNativeFallback = false;
@@ -2113,41 +2193,6 @@ function resolveNativeCacheIdentity() {
2113
2193
  }
2114
2194
  const BENCH_TRACE_ENABLED = process.env.CSSZYX_BENCH_TRACE === "1";
2115
2195
  const BENCH_TRACE_FILE = process.env.CSSZYX_BENCH_TRACE_FILE;
2116
- function appendTailwindSourceDirective(code, relPath) {
2117
- const directive = `@source "${relPath}";`;
2118
- if (code.includes(directive)) {
2119
- return null;
2120
- }
2121
- const separator = code.length === 0 || code.endsWith("\n") ? "" : "\n";
2122
- return `${code}${separator}${directive}
2123
- `;
2124
- }
2125
- function stripCssBlockComments(code) {
2126
- const SLASH = 47;
2127
- const STAR = 42;
2128
- let out = "";
2129
- let last = 0;
2130
- let i = 0;
2131
- const n = code.length;
2132
- while (i < n) {
2133
- if (code.codePointAt(i) === SLASH && code.codePointAt(i + 1) === STAR) {
2134
- out += code.slice(last, i);
2135
- i += 2;
2136
- while (i < n && !(code.codePointAt(i) === STAR && code.codePointAt(i + 1) === SLASH)) {
2137
- i++;
2138
- }
2139
- i += 2;
2140
- last = i;
2141
- } else {
2142
- i++;
2143
- }
2144
- }
2145
- return out + code.slice(last);
2146
- }
2147
- function cssImportsTailwind(code) {
2148
- const withoutBlockComments = stripCssBlockComments(code);
2149
- return /@import\s+["']tailwindcss(?:\/[^"']*)?["']/.test(withoutBlockComments);
2150
- }
2151
2196
  function hasInjectableTailwindCandidate(classes) {
2152
2197
  for (const c of classes) {
2153
2198
  if (c.length >= 2 && /^[a-z]/.test(c)) {
@@ -2398,15 +2443,6 @@ function watchModeMangleMessage() {
2398
2443
  function realContentHashDisabledMessage() {
2399
2444
  return "[csszyx] optimization.realContentHash is off while production.mangle is on. csszyx mangles assets after webpack computes their content hashes, and realContentHash is what recomputes those hashes from the final bytes. Without it, two builds that differ only by mangling emit the same filenames with different contents and caches keep serving the old file.";
2400
2445
  }
2401
- function computeSafelistRelPath(rootDir, safelistFilename, cssId) {
2402
- const safelistPath = normalizePathSeparators(path.join(rootDir, safelistFilename));
2403
- const cssDir = normalizePathSeparators(path.dirname(cssId));
2404
- let relPath = path.posix.relative(cssDir, safelistPath);
2405
- if (!relPath.startsWith(".")) {
2406
- relPath = `./${relPath}`;
2407
- }
2408
- return relPath;
2409
- }
2410
2446
  function cssVariableEntries(result) {
2411
2447
  const entries = [];
2412
2448
  for (const [original, value] of result.cssVariableMap ?? []) {
@@ -2427,7 +2463,6 @@ function recordFileVarMangleEntries(state, filename, entries) {
2427
2463
  } else {
2428
2464
  state.varMangleEntriesByFile.set(normalizedFilename, entries);
2429
2465
  }
2430
- state.varMangleMap = buildVarMangleMap(state.varMangleEntriesByFile);
2431
2466
  }
2432
2467
  function shouldTrackGlobalVarSources(config) {
2433
2468
  return config?.enabled === true;
@@ -2662,7 +2697,6 @@ function recordFileCSSVariableMetrics(state, filename, code) {
2662
2697
  state.cssVarMetricsByFile.delete(normalizedFilename);
2663
2698
  }
2664
2699
  }
2665
- state.cssVarMetrics = buildCSSVariableMetrics(state.cssVarMetricsByFile);
2666
2700
  }
2667
2701
  function collectCSSVariableMetrics(code) {
2668
2702
  const componentUses = /* @__PURE__ */ new Map();
@@ -2826,6 +2860,17 @@ function normalizeSourceFilename(filename) {
2826
2860
  return normalizePathSeparators(filename);
2827
2861
  }
2828
2862
  const SCRIPT_ID_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx"];
2863
+ const STYLESHEET_FILE_EXTENSIONS = [
2864
+ ".css",
2865
+ ".pcss",
2866
+ ".postcss",
2867
+ ".scss",
2868
+ ".sass",
2869
+ ".less",
2870
+ ".styl",
2871
+ ".stylus",
2872
+ ".sss"
2873
+ ];
2829
2874
  const SOURCE_MODULE_EXTENSIONS = [...SCRIPT_ID_EXTENSIONS, ".cts", ".mts", ".cjs", ".mjs"];
2830
2875
  function matchesScriptExtension(id, extensions) {
2831
2876
  return extensions.some((ext) => id.endsWith(ext) || id.includes(`${ext}?`));
@@ -3095,20 +3140,18 @@ function createCsszyxPlugins(options = {}) {
3095
3140
  let specifierAliases = [];
3096
3141
  const mangleReserved = new Set(options.production?.mangleExclude ?? []);
3097
3142
  let mangleMapFrozen = false;
3143
+ let prescanSawServerModule = false;
3144
+ let skipRscRecords = false;
3145
+ let lastPrescanCacheMisses = 0;
3098
3146
  let frozenOwnedClasses = /* @__PURE__ */ new Set();
3099
3147
  let frozenAuthoredClasses = /* @__PURE__ */ new Set();
3100
3148
  let cssRewrittenInTransform = false;
3101
3149
  let projectCssFiles = [];
3102
3150
  const transformMangledSources = /* @__PURE__ */ new Set();
3103
3151
  const transformExternalClasses = /* @__PURE__ */ new Set();
3104
- const mangleMapDelivery = options.production?.mangleMapDelivery ?? "both";
3105
- if (!["both", "html", "bundle"].includes(mangleMapDelivery)) {
3106
- throw new Error(
3107
- `[csszyx] production.mangleMapDelivery must be 'both', 'html' or 'bundle'; got ${JSON.stringify(mangleMapDelivery)}.`
3108
- );
3152
+ if (options.production?.mangleMapDelivery !== void 0) {
3153
+ console.warn(removedMangleMapDeliveryMessage());
3109
3154
  }
3110
- const deliverMapInHtml = mangleMapDelivery !== "bundle";
3111
- const deliverMapInBundle = mangleMapDelivery !== "html";
3112
3155
  const sizeAccount = createMangleSizeAccount();
3113
3156
  const astBudgetOverride = options.build?.astBudgetLimit;
3114
3157
  const prescanAstBudget = astBudgetOverride ?? 5e5;
@@ -3119,7 +3162,6 @@ function createCsszyxPlugins(options = {}) {
3119
3162
  const globalVarMangleConfig = options.production?.mangleGlobalVars;
3120
3163
  const globalVarSourceTrackingEnabled = shouldTrackGlobalVarSources(globalVarMangleConfig);
3121
3164
  const globalVarAliasPrefix = globalVarMangleConfig?.aliasPrefix ?? CSSZYX_GLOBAL_ALIAS_PREFIX;
3122
- const encodedGlobalVarAliasPrefix = encodeURIComponent(globalVarAliasPrefix);
3123
3165
  const earlyGlobalVarAliasEntries = createEarlyGlobalVarAliasEntries(
3124
3166
  globalVarMangleConfig,
3125
3167
  globalVarAliasPrefix
@@ -3174,12 +3216,21 @@ function createCsszyxPlugins(options = {}) {
3174
3216
  const transformMemoryCache = /* @__PURE__ */ new Map();
3175
3217
  let transformMemoryCacheCodeChars = 0;
3176
3218
  const prescanResultHandoff = /* @__PURE__ */ new Map();
3219
+ const varMangleEntries = createLazyAggregate(
3220
+ buildVarMangleMap,
3221
+ Object.fromEntries(earlyGlobalVarAliasEntries)
3222
+ );
3223
+ const cssVarMetricTotals = createLazyAggregate(
3224
+ buildCSSVariableMetrics,
3225
+ emptyCSSVariableMetrics()
3226
+ );
3177
3227
  const state = {
3178
3228
  classes: /* @__PURE__ */ new Set(),
3179
3229
  parsedTheme: null,
3180
3230
  scanCssTheme: null,
3181
3231
  autoThemeCssFiles: [],
3182
3232
  sawTailwindEntry: false,
3233
+ tailwindEntryFiles: /* @__PURE__ */ new Set(),
3183
3234
  sawAnyCss: false,
3184
3235
  tailwindWarningEmitted: false,
3185
3236
  tailwindEntryScoped: false,
@@ -3193,10 +3244,14 @@ function createCsszyxPlugins(options = {}) {
3193
3244
  ownedClasses: /* @__PURE__ */ new Set(),
3194
3245
  authoredClasses: /* @__PURE__ */ new Set(),
3195
3246
  mangleMap: {},
3196
- varMangleEntriesByFile: /* @__PURE__ */ new Map(),
3197
- varMangleMap: Object.fromEntries(earlyGlobalVarAliasEntries),
3198
- cssVarMetricsByFile: /* @__PURE__ */ new Map(),
3199
- cssVarMetrics: emptyCSSVariableMetrics(),
3247
+ varMangleEntriesByFile: varMangleEntries,
3248
+ get varMangleMap() {
3249
+ return varMangleEntries.get();
3250
+ },
3251
+ cssVarMetricsByFile: cssVarMetricTotals,
3252
+ get cssVarMetrics() {
3253
+ return cssVarMetricTotals.get();
3254
+ },
3200
3255
  checksum: "",
3201
3256
  finalized: false,
3202
3257
  rootDir: process.cwd(),
@@ -3208,7 +3263,7 @@ function createCsszyxPlugins(options = {}) {
3208
3263
  if (earlyGlobalVarAliasEntries.length > 0) {
3209
3264
  state.varMangleEntriesByFile.set(GLOBAL_VAR_ALIAS_MAP_OWNER, earlyGlobalVarAliasEntries);
3210
3265
  }
3211
- const SAFELIST_FILENAME = "csszyx-classes.html";
3266
+ const SAFELIST_FILENAME = SAFELIST_FILE;
3212
3267
  const SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([
3213
3268
  ".tsx",
3214
3269
  ".jsx",
@@ -3361,6 +3416,7 @@ function createCsszyxPlugins(options = {}) {
3361
3416
  );
3362
3417
  if (cached) return cached;
3363
3418
  }
3419
+ lastPrescanCacheMisses++;
3364
3420
  const execution = runConfiguredParser(source, effectiveFilename, compilerOptions);
3365
3421
  if (cacheEnabled && cacheKey && execution.cacheable) {
3366
3422
  writeTransformCache(cacheRoot, cacheInput, execution.result, cacheKey);
@@ -3447,6 +3503,7 @@ function createCsszyxPlugins(options = {}) {
3447
3503
  if (cacheEnabled) evictTransformCacheOnce();
3448
3504
  ensureRustTransformAvailable();
3449
3505
  const misses = collectRustPrescanMisses(batchable, compilerOptions, cacheRoot, results);
3506
+ lastPrescanCacheMisses += misses.length;
3450
3507
  if (misses.length > 0) {
3451
3508
  try {
3452
3509
  runRustPrescanBatch(misses, compilerOptions, cacheRoot, results);
@@ -3590,12 +3647,7 @@ function createCsszyxPlugins(options = {}) {
3590
3647
  return;
3591
3648
  }
3592
3649
  const safelistPath = path.join(state.rootDir, SAFELIST_FILENAME);
3593
- const classNames = Array.from(classes);
3594
- const classList = escapeHtmlAttribute(classNames.join(" "));
3595
- const content = `<!-- Auto-generated by csszyx \u2014 DO NOT EDIT -->
3596
- <!-- Tailwind CSS scans this file for class name detection -->
3597
- <div class="${classList}"><div class="${classList}">x</div><div class="${classList}">x</div></div>
3598
- ` + renderTailwindScannerCandidates(classNames);
3650
+ const content = renderSafelistFile(Array.from(classes));
3599
3651
  try {
3600
3652
  let existing = "";
3601
3653
  try {
@@ -3606,9 +3658,18 @@ function createCsszyxPlugins(options = {}) {
3606
3658
  }
3607
3659
  }
3608
3660
  if (existing !== content) {
3609
- fs.writeFileSync(safelistPath, content);
3661
+ atomicWriteFileSync(safelistPath, content);
3662
+ removeLegacySafelists(state.rootDir, console.warn);
3610
3663
  }
3611
- } catch {
3664
+ } catch (error) {
3665
+ if (_warnedSafelistWriteFailures.has(safelistPath)) {
3666
+ return;
3667
+ }
3668
+ _warnedSafelistWriteFailures.add(safelistPath);
3669
+ const reason = error instanceof Error ? error.message : String(error);
3670
+ console.warn(
3671
+ `[csszyx] could not write the generated safelist to ${safelistPath}: ${reason}. Tailwind scans that file for the classes csszyx found, so the CSS it generates will be missing them. Check that the directory exists and is writable.`
3672
+ );
3612
3673
  }
3613
3674
  }
3614
3675
  function recordPackagesSkipIfSz(filePath) {
@@ -3746,6 +3807,7 @@ function createCsszyxPlugins(options = {}) {
3746
3807
  szvCrossModuleRegistry.clear();
3747
3808
  szvCrossModuleForwards.clear();
3748
3809
  szObjectProvidersExamined.clear();
3810
+ prescanSawServerModule = false;
3749
3811
  const prescanStarted = performance.now();
3750
3812
  const discoveredClasses = /* @__PURE__ */ new Set();
3751
3813
  const rawDiscoveredClasses = /* @__PURE__ */ new Set();
@@ -3764,6 +3826,9 @@ function createCsszyxPlugins(options = {}) {
3764
3826
  return;
3765
3827
  }
3766
3828
  recordAuthoredClasses(content);
3829
+ if (!prescanSawServerModule && isRSCServerModule(content, filePath)) {
3830
+ prescanSawServerModule = true;
3831
+ }
3767
3832
  recordSzvRegistryEntries(filePath, content);
3768
3833
  recordCrossModuleForwards(szvCrossModuleForwards, filePath, content);
3769
3834
  seenSourcePaths.add(normalizePathSeparators(filePath));
@@ -3803,6 +3868,7 @@ function createCsszyxPlugins(options = {}) {
3803
3868
  }
3804
3869
  }
3805
3870
  }
3871
+ const walkStarted = performance.now();
3806
3872
  scanDir(state.rootDir);
3807
3873
  const normRoot = normalizeForMatch(state.rootDir);
3808
3874
  for (const sourceDir of compileSourceDirs) {
@@ -3811,7 +3877,20 @@ function createCsszyxPlugins(options = {}) {
3811
3877
  }
3812
3878
  scanDir(sourceDir);
3813
3879
  }
3880
+ traceBenchTiming(
3881
+ `prescan:walk files=${seenSourcePaths.size} sz=${prescanSources.length}`,
3882
+ state.rootDir,
3883
+ performance.now() - walkStarted
3884
+ );
3885
+ const demandStarted = performance.now();
3814
3886
  recordDemandedSzObjectProviders(seenSourcePaths, szObjectDemand);
3887
+ traceBenchTiming(
3888
+ `prescan:demand providers=${szObjectProvidersExamined.size}`,
3889
+ state.rootDir,
3890
+ performance.now() - demandStarted
3891
+ );
3892
+ const batchStarted = performance.now();
3893
+ lastPrescanCacheMisses = 0;
3815
3894
  const prescanContentByPath = new Map(
3816
3895
  prescanSources.map((file) => [file.filePath, file.content])
3817
3896
  );
@@ -3824,12 +3903,23 @@ function createCsszyxPlugins(options = {}) {
3824
3903
  rawDiscoveredClasses
3825
3904
  );
3826
3905
  }
3906
+ traceBenchTiming(
3907
+ `prescan:batch files=${prescanSources.length} misses=${lastPrescanCacheMisses}`,
3908
+ state.rootDir,
3909
+ performance.now() - batchStarted
3910
+ );
3827
3911
  for (const cls of discoveredClasses) {
3828
3912
  addSafelistClass(cls);
3829
3913
  state.ownedClasses.add(cls);
3830
3914
  }
3831
3915
  const safelistClasses = /* @__PURE__ */ new Set([...discoveredClasses, ...rawDiscoveredClasses]);
3916
+ const safelistStarted = performance.now();
3832
3917
  writeSafelistFile(safelistClasses);
3918
+ traceBenchTiming(
3919
+ `prescan:safelist classes=${safelistClasses.size}`,
3920
+ state.rootDir,
3921
+ performance.now() - safelistStarted
3922
+ );
3833
3923
  traceBenchTiming("prescan", state.rootDir, performance.now() - prescanStarted);
3834
3924
  }
3835
3925
  function collectPrescanResult(result, filePath, discoveredClasses, rawDiscoveredClasses) {
@@ -4008,6 +4098,12 @@ function createCsszyxPlugins(options = {}) {
4008
4098
  result = result.split(CHECKSUM_PLACEHOLDER).join(state.checksum);
4009
4099
  }
4010
4100
  const isEvalWrapped = result.includes("eval(") && result.includes("sourceURL=webpack");
4101
+ if (result.includes(CENSUS_PLACEHOLDER)) {
4102
+ const census = safeJsonForScriptTag(
4103
+ createHydrationMangleMap(state.mangleMap, state.varMangleMap)
4104
+ );
4105
+ result = result.split(CENSUS_PLACEHOLDER).join(escapeJsonForStringLiteral(census));
4106
+ }
4011
4107
  if (result.includes(MANGLE_MAP_PLACEHOLDER)) {
4012
4108
  const jsonMap = escapeJsonForInlineScript(JSON.stringify(state.mangleMap));
4013
4109
  const escapedMap = isEvalWrapped ? escapeForDoubleQuotedString(jsonMap) : jsonMap;
@@ -4037,10 +4133,80 @@ function createCsszyxPlugins(options = {}) {
4037
4133
  usesBoolClass: false
4038
4134
  };
4039
4135
  }
4136
+ function recordUntransformedHotFile(file, content) {
4137
+ trackGlobalVarSourceFile(file, content);
4138
+ recordFileVarMangleEntries(state, file, []);
4139
+ recordFileCSSVariableMetrics(state, file, null);
4140
+ }
4141
+ function discoverHotFileClasses(file, watcher) {
4142
+ if (!shouldProcessSource(file)) {
4143
+ return;
4144
+ }
4145
+ let fileContent, result;
4146
+ try {
4147
+ fileContent = fs.readFileSync(file, "utf-8");
4148
+ } catch {
4149
+ refreshSzvRegistryEntry(file, null);
4150
+ return;
4151
+ }
4152
+ refreshSzvRegistryEntry(file, fileContent);
4153
+ if (!fileContent.includes("sz=") && !fileContent.includes("szs=") && !/\bsz\s*:\s*["'{]/.test(fileContent)) {
4154
+ recordUntransformedHotFile(file, fileContent);
4155
+ return;
4156
+ }
4157
+ try {
4158
+ const hmrTransformStarted = performance.now();
4159
+ result = transformConfiguredSource(fileContent, file);
4160
+ traceBenchTiming("handle-hot-update", file, performance.now() - hmrTransformStarted);
4161
+ } catch {
4162
+ recordUntransformedHotFile(file, fileContent);
4163
+ return;
4164
+ }
4165
+ if (!result.transformed) {
4166
+ recordUntransformedHotFile(file, fileContent);
4167
+ return;
4168
+ }
4169
+ recordHotTransformResult(file, fileContent, result, watcher);
4170
+ }
4171
+ function recordHotTransformResult(file, fileContent, result, watcher) {
4172
+ const sizeBefore = state.classes.size;
4173
+ trackGlobalVarSourceFile(file, fileContent);
4174
+ for (const cls of result.classes) {
4175
+ addSafelistClass(cls);
4176
+ state.ownedClasses.add(cls);
4177
+ }
4178
+ recordFileVarMangleEntries(state, file, cssVariableEntries(result));
4179
+ recordFileCSSVariableMetrics(state, file, result.code);
4180
+ for (const [token, data] of result.recoveryTokens) {
4181
+ state.recoveryTokens.set(token, data);
4182
+ }
4183
+ if (state.classes.size > sizeBefore) {
4184
+ writeSafelistFile(state.classes);
4185
+ const safelistPath = path.join(state.rootDir, SAFELIST_FILENAME);
4186
+ watcher.emit("change", safelistPath);
4187
+ }
4188
+ }
4189
+ function tailwindEntryModules(moduleGraph) {
4190
+ const modules = [];
4191
+ for (const file of state.tailwindEntryFiles) {
4192
+ const found = moduleGraph.getModulesByFile(file);
4193
+ if (found) modules.push(...found);
4194
+ }
4195
+ return modules;
4196
+ }
4040
4197
  function transformTailwindCssEntry(code, id) {
4041
4198
  state.sawAnyCss = true;
4199
+ const [cssFile] = id.split("?");
4200
+ const legacy = findLegacySourceDirective(code, cssFile);
4201
+ if (legacy !== null) {
4202
+ throw new Error(legacySourceMessage(cssFile, legacy.target));
4203
+ }
4042
4204
  if (!cssImportsTailwind(code)) return null;
4043
4205
  state.sawTailwindEntry = true;
4206
+ const [entryFile] = id.split("?");
4207
+ if (STYLESHEET_FILE_EXTENSIONS.some((ext) => entryFile.endsWith(ext))) {
4208
+ state.tailwindEntryFiles.add(entryFile);
4209
+ }
4044
4210
  if (cssHasContentScope(code)) state.tailwindEntryScoped = true;
4045
4211
  if (!hasInjectableTailwindCandidate(state.classes)) return null;
4046
4212
  const relPath = computeSafelistRelPath(state.rootDir, SAFELIST_FILENAME, id);
@@ -4112,16 +4278,16 @@ function createCsszyxPlugins(options = {}) {
4112
4278
  if (!code.includes("<html") || !/(?:layout|Root|Document|app)\.tsx?$/i.test(id)) {
4113
4279
  return null;
4114
4280
  }
4115
- let transformedCode = code;
4116
4281
  const attrName = options.production?.minify ? "data-sz-cs" : "data-sz-checksum";
4117
- const htmlTag = findOpeningTag(transformedCode, "html");
4118
- if (htmlTag) {
4119
- transformedCode = `${transformedCode.slice(0, htmlTag.close)} ${attrName}="${CHECKSUM_PLACEHOLDER}"${transformedCode.slice(htmlTag.close)}`;
4282
+ const htmlTag = findOpeningTag(code, "html");
4283
+ if (!htmlTag) {
4284
+ return code;
4120
4285
  }
4121
- 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})}}})()\`}} />`;
4286
+ let transformedCode = `${code.slice(0, htmlTag.close)} ${attrName}="${CHECKSUM_PLACEHOLDER}"${code.slice(htmlTag.close)}`;
4287
+ const censusTag = `<script id="__CSSZYX_MANGLE_MAP__" type="application/json" dangerouslySetInnerHTML={{__html: \`${CENSUS_PLACEHOLDER}\`}} />`;
4122
4288
  const bodyTag = findOpeningTag(transformedCode, "body");
4123
4289
  if (bodyTag) {
4124
- transformedCode = `${transformedCode.slice(0, bodyTag.close + 1)}${debugScript}${transformedCode.slice(bodyTag.close + 1)}`;
4290
+ transformedCode = `${transformedCode.slice(0, bodyTag.close + 1)}${censusTag}${transformedCode.slice(bodyTag.close + 1)}`;
4125
4291
  }
4126
4292
  return transformedCode;
4127
4293
  }
@@ -4187,12 +4353,22 @@ ${transformedCode}`;
4187
4353
  if (activeFramework !== "vite" && activeFramework !== "rollup") {
4188
4354
  return null;
4189
4355
  }
4190
- if (!manglingEnabled || !deliverMapInBundle || !shouldProcessSource(id) || !MANGLE_RUNTIME_CONSUMER_RE.test(transformedCode) || transformedCode.includes(MANGLE_RUNTIME_VIRTUAL_ID)) {
4356
+ if (!manglingEnabled || !shouldProcessSource(id) || !MANGLE_RUNTIME_CONSUMER_RE.test(transformedCode) || transformedCode.includes(MANGLE_RUNTIME_VIRTUAL_ID)) {
4191
4357
  return null;
4192
4358
  }
4193
4359
  return insertRuntimeImport(transformedCode, `import '${MANGLE_RUNTIME_VIRTUAL_ID}';
4194
4360
  `);
4195
4361
  }
4362
+ function applyWebpackMangleRuntimeEntry(compiler) {
4363
+ const root = compiler.context;
4364
+ const file = ensureMangleRuntimeFile(
4365
+ path.join(root, ".csszyx"),
4366
+ globalVarAliasPrefix,
4367
+ options.production?.mangleDebugGlobal === true
4368
+ );
4369
+ if (file === null) return;
4370
+ applyMangleRuntimeEntry(compiler, root, file, () => sizeAccount.channels.add("bundle"));
4371
+ }
4196
4372
  function collectPreTransformClasses(output) {
4197
4373
  if (!output.transformed && !output.code.includes("class=") && !output.code.includes("className=")) {
4198
4374
  return null;
@@ -4258,7 +4434,10 @@ ${transformedCode}`;
4258
4434
  }
4259
4435
  if (id === RESOLVED_MANGLE_RUNTIME_VIRTUAL_ID) {
4260
4436
  sizeAccount.channels.add("bundle");
4261
- return createMangleRuntimeModule(globalVarAliasPrefix);
4437
+ return createMangleRuntimeModule(
4438
+ globalVarAliasPrefix,
4439
+ options.production?.mangleDebugGlobal === true
4440
+ );
4262
4441
  }
4263
4442
  if (id === RESOLVED_THEME_GROUPS_VIRTUAL_ID) {
4264
4443
  return createThemeGroupsModule(themeGroupTokens());
@@ -4336,8 +4515,10 @@ ${transformedCode}`;
4336
4515
  }
4337
4516
  if (matchesScriptExtension(id, SCRIPT_ID_EXTENSIONS)) {
4338
4517
  assertNoRSCBoundaryViolation(output.code, id);
4339
- const record = createRSCModuleRecord(output.code, id);
4340
- state.rscModules.set(record.id, record);
4518
+ if (!skipRscRecords) {
4519
+ const record = createRSCModuleRecord(output.code, id);
4520
+ state.rscModules.set(record.id, record);
4521
+ }
4341
4522
  }
4342
4523
  return collectPreTransformClasses(output);
4343
4524
  },
@@ -4414,10 +4595,8 @@ ${transformedCode}`;
4414
4595
  if (compiler.options?.mode === "development") {
4415
4596
  manglingEnabled = false;
4416
4597
  }
4417
- if (manglingEnabled && mangleMapDelivery !== "both") {
4418
- console.warn(
4419
- `[csszyx] production.mangleMapDelivery: '${mangleMapDelivery}' has no effect on the webpack lane \u2014 map delivery only narrows on vite/rollup builds.`
4420
- );
4598
+ if (manglingEnabled) {
4599
+ applyWebpackMangleRuntimeEntry(compiler);
4421
4600
  }
4422
4601
  compiler.hooks.beforeCompile.tap("csszyx:prescan", () => {
4423
4602
  announceActiveParser();
@@ -4476,6 +4655,7 @@ ${transformedCode}`;
4476
4655
  }
4477
4656
  evictTransformCacheOnce();
4478
4657
  prescanAndWriteClasses();
4658
+ skipRscRecords = config.command === "build" && !config.build?.watch && !prescanSawServerModule;
4479
4659
  state.scanCssTheme = runThemeScan(root, options.build?.scanCss) ?? state.scanCssTheme;
4480
4660
  runAutoThemeScan(root);
4481
4661
  if (config.command === "build") {
@@ -4489,11 +4669,36 @@ ${transformedCode}`;
4489
4669
  },
4490
4670
  /**
4491
4671
  * Vite HMR hook: re-runs theme scan when a watched CSS file changes,
4492
- * and incrementally updates csszyx-classes.html when a source file gains new sz classes.
4493
- * @param ctx - HMR context containing the changed file
4672
+ * and incrementally updates the safelist when a source file gains new sz classes.
4673
+ *
4674
+ * `hotUpdate` rather than `handleHotUpdate` because the safelist
4675
+ * can arrive as a CREATE. `writeSafelistFile` returns early on an
4676
+ * empty class set, so a project with no `sz` at prescan has no
4677
+ * safelist file, and the first `sz` edit makes one. Vite routes a
4678
+ * create to `hotUpdate` only — its `handleHotUpdate` branch runs
4679
+ * for `type === 'update'` and nothing else — so the legacy hook
4680
+ * left that one event to `@tailwindcss/vite`, which answers a
4681
+ * scanned file whose only modules are asset nodes with an
4682
+ * unaddressed `full-reload`.
4683
+ *
4684
+ * @param this - Vite's plugin context for the pass being run.
4685
+ * @param this.environment - The environment this pass belongs to,
4686
+ * absent when a host calls the hook without one.
4687
+ * @param this.environment.name - `client` for the pass that owns
4688
+ * the page; `ssr` and any custom environment follow it.
4689
+ * @param this.environment.moduleGraph - That environment's own
4690
+ * graph, the one Vite replaces with this hook's answer.
4691
+ * @param ctx - HMR context: the changed file, why it changed, and
4692
+ * the dev server.
4693
+ * @returns The modules a safelist write affects, so Vite hot-updates
4694
+ * the stylesheet instead of reloading the page; undefined otherwise,
4695
+ * which leaves Vite's own handling in place.
4494
4696
  */
4495
- handleHotUpdate(ctx) {
4496
- prescanResultHandoff.clear();
4697
+ hotUpdate(ctx) {
4698
+ const isClientPass = (this.environment?.name ?? "client") === "client";
4699
+ if (isClientPass) {
4700
+ prescanResultHandoff.clear();
4701
+ }
4497
4702
  const scanCss = options.build?.scanCss;
4498
4703
  const reloadThemeGroupsModule = () => {
4499
4704
  const themeGroupsModule = ctx.server.moduleGraph.getModuleById(
@@ -4503,7 +4708,7 @@ ${transformedCode}`;
4503
4708
  ctx.server.moduleGraph.invalidateModule(themeGroupsModule);
4504
4709
  }
4505
4710
  };
4506
- if (ctx.file.endsWith(".css")) {
4711
+ if (isClientPass && ctx.file.endsWith(".css")) {
4507
4712
  const root = ctx.server.config.root || process.cwd();
4508
4713
  const before = createThemeGroupsModule(themeGroupTokens());
4509
4714
  if (scanCss && matchesAnyPattern(ctx.file, scanCss, root)) {
@@ -4515,59 +4720,13 @@ ${transformedCode}`;
4515
4720
  ctx.server.ws.send({ type: "full-reload" });
4516
4721
  }
4517
4722
  }
4518
- if (!shouldProcessSource(ctx.file)) {
4519
- return;
4520
- }
4521
- let fileContent, result;
4522
- try {
4523
- fileContent = fs.readFileSync(ctx.file, "utf-8");
4524
- } catch {
4525
- refreshSzvRegistryEntry(ctx.file, null);
4526
- return;
4527
- }
4528
- refreshSzvRegistryEntry(ctx.file, fileContent);
4529
- if (!fileContent.includes("sz=") && !fileContent.includes("szs=") && !/\bsz\s*:\s*["'{]/.test(fileContent)) {
4530
- trackGlobalVarSourceFile(ctx.file, fileContent);
4531
- recordFileVarMangleEntries(state, ctx.file, []);
4532
- recordFileCSSVariableMetrics(state, ctx.file, null);
4533
- return;
4534
- }
4535
- try {
4536
- const hmrTransformStarted = performance.now();
4537
- result = transformConfiguredSource(fileContent, ctx.file);
4538
- traceBenchTiming(
4539
- "handle-hot-update",
4540
- ctx.file,
4541
- performance.now() - hmrTransformStarted
4723
+ if (normalizePathSeparators(ctx.file) === normalizePathSeparators(path.join(state.rootDir, SAFELIST_FILENAME))) {
4724
+ return tailwindEntryModules(
4725
+ this.environment?.moduleGraph ?? ctx.server.environments.client.moduleGraph
4542
4726
  );
4543
- } catch {
4544
- trackGlobalVarSourceFile(ctx.file, fileContent);
4545
- recordFileVarMangleEntries(state, ctx.file, []);
4546
- recordFileCSSVariableMetrics(state, ctx.file, null);
4547
- return;
4548
- }
4549
- if (!result.transformed) {
4550
- trackGlobalVarSourceFile(ctx.file, fileContent);
4551
- recordFileVarMangleEntries(state, ctx.file, []);
4552
- recordFileCSSVariableMetrics(state, ctx.file, null);
4553
- return;
4554
- }
4555
- const sizeBefore = state.classes.size;
4556
- trackGlobalVarSourceFile(ctx.file, fileContent);
4557
- for (const cls of result.classes) {
4558
- addSafelistClass(cls);
4559
- state.ownedClasses.add(cls);
4560
- }
4561
- recordFileVarMangleEntries(state, ctx.file, cssVariableEntries(result));
4562
- recordFileCSSVariableMetrics(state, ctx.file, result.code);
4563
- for (const [token, data] of result.recoveryTokens) {
4564
- state.recoveryTokens.set(token, data);
4565
- }
4566
- if (state.classes.size > sizeBefore) {
4567
- writeSafelistFile(state.classes);
4568
- const safelistPath = path.join(state.rootDir, SAFELIST_FILENAME);
4569
- ctx.server.watcher.emit("change", safelistPath);
4570
4727
  }
4728
+ if (isClientPass) discoverHotFileClasses(ctx.file, ctx.server.watcher);
4729
+ return void 0;
4571
4730
  },
4572
4731
  transformIndexHtml: {
4573
4732
  order: "pre",
@@ -4581,13 +4740,11 @@ ${transformedCode}`;
4581
4740
  finalizeMangleMap();
4582
4741
  const injectedMangleMap = manglingEnabled ? state.mangleMap : {};
4583
4742
  let result = transformIndexHtml(html, injectedMangleMap, state.checksum, {
4584
- // Always 'script'; the checksum itself is injected by
4585
- // injectHydrationData regardless of this mode.
4743
+ // Always 'script' the inert JSON census; the
4744
+ // checksum attribute is injected regardless.
4586
4745
  mode: "script",
4587
4746
  minify: process.env.NODE_ENV === "production",
4588
- varMangleMap: state.varMangleMap,
4589
- globalVarAliasPrefix,
4590
- installRuntimeObject: deliverMapInHtml
4747
+ varMangleMap: state.varMangleMap
4591
4748
  });
4592
4749
  if (manglingEnabled) {
4593
4750
  sizeAccount.channels.add("html");
@@ -4608,6 +4765,18 @@ ${transformedCode}`;
4608
4765
  }
4609
4766
  result = injectRecoveryManifest(result, manifest);
4610
4767
  }
4768
+ if (needsRuntimeMangleRegistration(manglingEnabled, injectedMangleMap)) {
4769
+ return {
4770
+ html: result,
4771
+ tags: [
4772
+ {
4773
+ tag: "script",
4774
+ attrs: { type: "module", src: MANGLE_RUNTIME_VIRTUAL_ID },
4775
+ injectTo: "head-prepend"
4776
+ }
4777
+ ]
4778
+ };
4779
+ }
4611
4780
  return result;
4612
4781
  }
4613
4782
  }
@@ -4959,4 +5128,4 @@ const esbuildPlugin = (options = {}) => {
4959
5128
  };
4960
5129
  };
4961
5130
 
4962
- export { shouldWarnUnscopedMonorepo as $, isHardIgnoredPath as A, isMangleableCssId as B, isMonorepoPackage as C, isPackagesSkippedSource as D, isRSCServerModule as E, isTailwindReservedGlobalVar as F, lateMangleCensusMessage as G, mangleCodeClassesSync as H, mangleEligibleClasses as I, mangleHybridHazardMessage as J, missingTailwindEntryMessage as K, normalizeGlobalVarAliasesForCache as L, planGlobalVarAliases as M, readGlobalVarScanCache as N, realContentHashDisabledMessage as O, recordGlobalVarSourceFile as P, resolveCompileSourceDirs as Q, resolveGlobalVarScanCacheDir as R, resolveNativeCacheIdentity as S, resolveQuietMode as T, rewriteGlobalVarCssAliases as U, rollupPlugin as V, scanGlobalVarCss as W, shouldEmitMissingCssFallback as X, shouldEmitWarning as Y, shouldTrackGlobalVarSources as Z, shouldWarnMissingTailwindEntry as _, allocateMangleTokens as a, skippedSzFilesMessage as a0, suppressedAdvisoryMessage as a1, unscopedMonorepoMessage as a2, validateGlobalVarAliasInputs as a3, vitePlugin as a4, watchModeMangleMessage as a5, webpackPlugin as a6, writeGlobalVarScanCache as a7, 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, hasUseClientDirective as w, hasUseServerDirective as x, isAdvisoryDiagnostic as y, isCompileSourceOptedIn as z };
5131
+ export { unscopedMonorepoMessage as $, isPackagesSkippedSource as A, isRSCServerModule as B, isTailwindReservedGlobalVar as C, lateMangleCensusMessage as D, mangleCodeClassesSync as E, mangleEligibleClasses as F, mangleHybridHazardMessage as G, missingTailwindEntryMessage as H, normalizeGlobalVarAliasesForCache as I, planGlobalVarAliases as J, readGlobalVarScanCache as K, realContentHashDisabledMessage as L, recordGlobalVarSourceFile as M, resolveCompileSourceDirs as N, resolveGlobalVarScanCacheDir as O, resolveNativeCacheIdentity as P, resolveQuietMode as Q, rewriteGlobalVarCssAliases as R, rollupPlugin as S, scanGlobalVarCss as T, shouldEmitMissingCssFallback as U, shouldEmitWarning as V, shouldTrackGlobalVarSources as W, shouldWarnMissingTailwindEntry as X, shouldWarnUnscopedMonorepo as Y, skippedSzFilesMessage as Z, suppressedAdvisoryMessage as _, allocateMangleTokens as a, validateGlobalVarAliasInputs as a0, vitePlugin as a1, watchModeMangleMessage as a2, webpackPlugin as a3, writeGlobalVarScanCache as a4, assertNoRSCBoundaryViolation as b, assertNoRSCGraphViolation as c, collectMangleHybridHazards as d, createGlobalVarAliasValidationOptions as e, createGlobalVarMapAssetSource as f, createGlobalVarScanCacheKey as g, createRSCModuleRecord as h, cssHasContentScope as i, deleteRSCModuleRecord as j, emitMissingCssFallback as k, esbuildPlugin as l, extractGlobalVarAliasesForManifest as m, fileMayContainSafelistableSz as n, findLocalImportSources as o, findRSCBoundaryViolation as p, findRSCGraphViolation as q, hasInjectableTailwindCandidate as r, hasUseClientDirective as s, hasUseServerDirective as t, unplugin as u, isAdvisoryDiagnostic as v, isCompileSourceOptedIn as w, isHardIgnoredPath as x, isMangleableCssId as y, isMonorepoPackage as z };