@csszyx/unplugin 0.15.0 → 0.15.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/index.cjs +4 -4
  2. package/dist/index.d.cts +2 -2
  3. package/dist/index.d.mts +2 -2
  4. package/dist/index.mjs +4 -4
  5. package/dist/next-prebuild.cjs +4 -4
  6. package/dist/next-prebuild.d.cts +2 -2
  7. package/dist/next-prebuild.d.mts +2 -2
  8. package/dist/next-prebuild.mjs +4 -4
  9. package/dist/next-turbo-loader.cjs +5 -5
  10. package/dist/next-turbo-loader.d.cts +1 -1
  11. package/dist/next-turbo-loader.d.mts +1 -1
  12. package/dist/next-turbo-loader.mjs +5 -5
  13. package/dist/next-watcher.cjs +2 -2
  14. package/dist/next-watcher.d.cts +2 -2
  15. package/dist/next-watcher.d.mts +2 -2
  16. package/dist/next-watcher.mjs +2 -2
  17. package/dist/shared/{unplugin.C2ilavL1.d.cts → unplugin.BGog1Bib.d.cts} +7 -6
  18. package/dist/shared/{unplugin.C2ilavL1.d.mts → unplugin.BGog1Bib.d.mts} +7 -6
  19. package/dist/shared/{unplugin.DmCOQc-b.mjs → unplugin.BLptVbUe.mjs} +1 -46
  20. package/dist/shared/{unplugin.BHfqCocB.d.cts → unplugin.BT7PqYuK.d.cts} +1 -1
  21. package/dist/shared/{unplugin.BHfqCocB.d.mts → unplugin.BT7PqYuK.d.mts} +1 -1
  22. package/dist/shared/{unplugin.Dai5wlZ3.cjs → unplugin.BWnmKv07.cjs} +7 -52
  23. package/dist/shared/{unplugin.AGR7mihU.mjs → unplugin.Bk9o8_RZ.mjs} +1 -1
  24. package/dist/shared/{unplugin.BGufkSFT.mjs → unplugin.BxsTa17g.mjs} +67 -15
  25. package/dist/shared/{unplugin.DX3rYT4P.cjs → unplugin.BzF0V2kw.cjs} +1 -1
  26. package/dist/shared/{unplugin.CXCaQ3-s.d.cts → unplugin.COlI0dJs.d.mts} +1 -1
  27. package/dist/shared/{unplugin.Dbc26ty6.mjs → unplugin.DAzgbtuZ.mjs} +2 -2
  28. package/dist/shared/{unplugin.KnDCM-sr.cjs → unplugin.DDSWQJYX.cjs} +48 -0
  29. package/dist/shared/{unplugin.CqJS0BbD.mjs → unplugin.DH_ij6cf.mjs} +48 -1
  30. package/dist/shared/{unplugin.BourSpnZ.mjs → unplugin.DK0b4fr7.mjs} +1 -1
  31. package/dist/shared/{unplugin.C7i0agiO.cjs → unplugin.J6ue_lRJ.cjs} +1 -1
  32. package/dist/shared/{unplugin.BLbrShMZ.cjs → unplugin.dz3AdzsO.cjs} +68 -16
  33. package/dist/shared/{unplugin.BbBYWFGT.cjs → unplugin.gksolKh2.cjs} +2 -2
  34. package/dist/shared/{unplugin.CbNydVwv.d.mts → unplugin.rWOMecQs.d.cts} +1 -1
  35. package/dist/vite.cjs +4 -4
  36. package/dist/vite.d.cts +1 -1
  37. package/dist/vite.d.mts +1 -1
  38. package/dist/vite.mjs +4 -4
  39. package/dist/webpack.cjs +4 -4
  40. package/dist/webpack.d.cts +1 -1
  41. package/dist/webpack.d.mts +1 -1
  42. package/dist/webpack.mjs +4 -4
  43. package/package.json +16 -16
@@ -6,17 +6,17 @@ import * as path from 'node:path';
6
6
  import path__default, { dirname } from 'node:path';
7
7
  import { performance } from 'node:perf_hooks';
8
8
  import { fileURLToPath } from 'node:url';
9
- import { scanGlobalVarUsages, sortStrings as sortStrings$1, szFallbackConsequenceOf, isWasmTransformAvailable, isRustTransformAvailable, ensureRustTransformAvailable, transformRust, transformWasm, ASTBudgetExceededError, transformRustBatch, transform } from '@csszyx/compiler';
9
+ import { scanGlobalVarUsages, sortStrings as sortStrings$1, szFallbackConsequenceOf, ensureRustTransformAvailable, isWasmTransformAvailable, isRustTransformAvailable, transformRust, transformWasm, ASTBudgetExceededError, transformRustBatch, transform } from '@csszyx/compiler';
10
10
  import { encode, compute_mangle_checksum } from '@csszyx/core';
11
11
  import { getNativePackageName } from '@csszyx/core/native';
12
12
  import { preprocess as preprocess$1 } from '@csszyx/svelte-adapter';
13
13
  import { isTailwindReservedCustomProperty, CSSZYX_GLOBAL_ALIAS_PREFIX, isCsszyxGlobalAliasCustomProperty, DEFAULT_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 { 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.AGR7mihU.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 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.BourSpnZ.mjs';
19
- import { s as sortStrings, n as normalizePathSeparators, g as stripCssBlockComments, S as SAFELIST_FILE, h as findLegacySourceDirective, l as legacySourceMessage, b as cssImportsTailwind, c as computeSafelistRelPath, a as appendTailwindSourceDirective, r as renderSafelistFile, d as removeLegacySafelists } from './unplugin.CqJS0BbD.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';
@@ -2158,6 +2158,7 @@ function findOpeningTag(source, tag) {
2158
2158
  }
2159
2159
  }
2160
2160
  const _warnedClassNameAuthors = /* @__PURE__ */ new Set();
2161
+ const _warnedSafelistWriteFailures = /* @__PURE__ */ new Set();
2161
2162
  let _hasWarnedTsConfig = false;
2162
2163
  let _hasWarnedTransformCacheVersion = false;
2163
2164
  let _hasWarnedNativeFallback = false;
@@ -2859,6 +2860,17 @@ function normalizeSourceFilename(filename) {
2859
2860
  return normalizePathSeparators(filename);
2860
2861
  }
2861
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
+ ];
2862
2874
  const SOURCE_MODULE_EXTENSIONS = [...SCRIPT_ID_EXTENSIONS, ".cts", ".mts", ".cjs", ".mjs"];
2863
2875
  function matchesScriptExtension(id, extensions) {
2864
2876
  return extensions.some((ext) => id.endsWith(ext) || id.includes(`${ext}?`));
@@ -3031,7 +3043,14 @@ function mangleCodeClassesSync(code, mangleMap) {
3031
3043
  result = out + result.slice(copiedTo);
3032
3044
  }
3033
3045
  }
3034
- result = result.replace(/([,(]|&&)(\s*)"([^"]+)"/g, (match, sep, ws, inner) => {
3046
+ const objectKeyColon = /\s*:/y;
3047
+ result = result.replace(/([,([{]|&&)(\s*)"([^"]+)"/g, (match, sep, ws, inner, offset) => {
3048
+ if (sep === "{") {
3049
+ objectKeyColon.lastIndex = offset + match.length;
3050
+ if (!objectKeyColon.test(result)) {
3051
+ return match;
3052
+ }
3053
+ }
3035
3054
  const tokens = inner.split(/\s+/).filter(Boolean);
3036
3055
  if (tokens.length === 0) {
3037
3056
  return match;
@@ -3646,11 +3665,18 @@ function createCsszyxPlugins(options = {}) {
3646
3665
  }
3647
3666
  }
3648
3667
  if (existing !== content) {
3649
- fs.mkdirSync(path.dirname(safelistPath), { recursive: true });
3650
- fs.writeFileSync(safelistPath, content);
3668
+ atomicWriteFileSync(safelistPath, content);
3651
3669
  removeLegacySafelists(state.rootDir, console.warn);
3652
3670
  }
3653
- } catch {
3671
+ } catch (error) {
3672
+ if (_warnedSafelistWriteFailures.has(safelistPath)) {
3673
+ return;
3674
+ }
3675
+ _warnedSafelistWriteFailures.add(safelistPath);
3676
+ const reason = error instanceof Error ? error.message : String(error);
3677
+ console.warn(
3678
+ `[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.`
3679
+ );
3654
3680
  }
3655
3681
  }
3656
3682
  function recordPackagesSkipIfSz(filePath) {
@@ -4185,7 +4211,9 @@ function createCsszyxPlugins(options = {}) {
4185
4211
  if (!cssImportsTailwind(code)) return null;
4186
4212
  state.sawTailwindEntry = true;
4187
4213
  const [entryFile] = id.split("?");
4188
- state.tailwindEntryFiles.add(entryFile);
4214
+ if (STYLESHEET_FILE_EXTENSIONS.some((ext) => entryFile.endsWith(ext))) {
4215
+ state.tailwindEntryFiles.add(entryFile);
4216
+ }
4189
4217
  if (cssHasContentScope(code)) state.tailwindEntryScoped = true;
4190
4218
  if (!hasInjectableTailwindCandidate(state.classes)) return null;
4191
4219
  const relPath = computeSafelistRelPath(state.rootDir, SAFELIST_FILENAME, id);
@@ -4649,13 +4677,35 @@ ${transformedCode}`;
4649
4677
  /**
4650
4678
  * Vite HMR hook: re-runs theme scan when a watched CSS file changes,
4651
4679
  * and incrementally updates the safelist when a source file gains new sz classes.
4652
- * @param ctx - HMR context containing the changed file
4680
+ *
4681
+ * `hotUpdate` rather than `handleHotUpdate` because the safelist
4682
+ * can arrive as a CREATE. `writeSafelistFile` returns early on an
4683
+ * empty class set, so a project with no `sz` at prescan has no
4684
+ * safelist file, and the first `sz` edit makes one. Vite routes a
4685
+ * create to `hotUpdate` only — its `handleHotUpdate` branch runs
4686
+ * for `type === 'update'` and nothing else — so the legacy hook
4687
+ * left that one event to `@tailwindcss/vite`, which answers a
4688
+ * scanned file whose only modules are asset nodes with an
4689
+ * unaddressed `full-reload`.
4690
+ *
4691
+ * @param this - Vite's plugin context for the pass being run.
4692
+ * @param this.environment - The environment this pass belongs to,
4693
+ * absent when a host calls the hook without one.
4694
+ * @param this.environment.name - `client` for the pass that owns
4695
+ * the page; `ssr` and any custom environment follow it.
4696
+ * @param this.environment.moduleGraph - That environment's own
4697
+ * graph, the one Vite replaces with this hook's answer.
4698
+ * @param ctx - HMR context: the changed file, why it changed, and
4699
+ * the dev server.
4653
4700
  * @returns The modules a safelist write affects, so Vite hot-updates
4654
4701
  * the stylesheet instead of reloading the page; undefined otherwise,
4655
4702
  * which leaves Vite's own handling in place.
4656
4703
  */
4657
- handleHotUpdate(ctx) {
4658
- prescanResultHandoff.clear();
4704
+ hotUpdate(ctx) {
4705
+ const isClientPass = (this.environment?.name ?? "client") === "client";
4706
+ if (isClientPass) {
4707
+ prescanResultHandoff.clear();
4708
+ }
4659
4709
  const scanCss = options.build?.scanCss;
4660
4710
  const reloadThemeGroupsModule = () => {
4661
4711
  const themeGroupsModule = ctx.server.moduleGraph.getModuleById(
@@ -4665,7 +4715,7 @@ ${transformedCode}`;
4665
4715
  ctx.server.moduleGraph.invalidateModule(themeGroupsModule);
4666
4716
  }
4667
4717
  };
4668
- if (ctx.file.endsWith(".css")) {
4718
+ if (isClientPass && ctx.file.endsWith(".css")) {
4669
4719
  const root = ctx.server.config.root || process.cwd();
4670
4720
  const before = createThemeGroupsModule(themeGroupTokens());
4671
4721
  if (scanCss && matchesAnyPattern(ctx.file, scanCss, root)) {
@@ -4678,9 +4728,11 @@ ${transformedCode}`;
4678
4728
  }
4679
4729
  }
4680
4730
  if (normalizePathSeparators(ctx.file) === normalizePathSeparators(path.join(state.rootDir, SAFELIST_FILENAME))) {
4681
- return tailwindEntryModules(ctx.server.moduleGraph);
4731
+ return tailwindEntryModules(
4732
+ this.environment?.moduleGraph ?? ctx.server.environments.client.moduleGraph
4733
+ );
4682
4734
  }
4683
- discoverHotFileClasses(ctx.file, ctx.server.watcher);
4735
+ if (isClientPass) discoverHotFileClasses(ctx.file, ctx.server.watcher);
4684
4736
  return void 0;
4685
4737
  },
4686
4738
  transformIndexHtml: {
@@ -2,7 +2,7 @@
2
2
 
3
3
  const path = require('node:path');
4
4
  const compiler = require('@csszyx/compiler');
5
- const safelistSource = require('./unplugin.KnDCM-sr.cjs');
5
+ const safelistSource = require('./unplugin.DDSWQJYX.cjs');
6
6
  const fs = require('node:fs');
7
7
  const node_crypto = require('node:crypto');
8
8
 
@@ -1,4 +1,4 @@
1
- import { a as NextSafelistMaterializeResult, b as NextSafelistStateLockOptions, A as AtomicWriteOptions } from './unplugin.C2ilavL1.cjs';
1
+ import { a as NextSafelistMaterializeResult, b as NextSafelistStateLockOptions, A as AtomicWriteOptions } from './unplugin.BGog1Bib.mjs';
2
2
 
3
3
  /** Options for one synchronous watcher materialization cycle. */
4
4
  interface NextWatcherCycleOptions {
@@ -2,8 +2,8 @@ import { readFileSync } from 'node:fs';
2
2
  import * as path from 'node:path';
3
3
  import { extractCrossModuleForwards, extractCrossModuleRegistryEntries, ensureRustTransformAvailable, transformRust, transformWasm, transform } from '@csszyx/compiler';
4
4
  import { DEFAULT_IMPORTED_STATIC_SZ } from '@csszyx/types';
5
- import { c as collectSpecifierAliases, i as importedSpecifiersIn, s as specifierBases, a as resolveProviderPathWith, b as recordResolvedEntry, f as forwardVisitKey, M as MAX_FORWARD_HOPS, d as isReadableProviderFile, e as createTransformCacheKey, g as readTransformCache, w as writeTransformCache } from './unplugin.AGR7mihU.mjs';
6
- import { n as normalizePathSeparators, s as sortStrings } from './unplugin.CqJS0BbD.mjs';
5
+ import { c as collectSpecifierAliases, i as importedSpecifiersIn, s as specifierBases, a as resolveProviderPathWith, b as recordResolvedEntry, f as forwardVisitKey, M as MAX_FORWARD_HOPS, d as isReadableProviderFile, e as createTransformCacheKey, g as readTransformCache, w as writeTransformCache } from './unplugin.Bk9o8_RZ.mjs';
6
+ import { n as normalizePathSeparators, s as sortStrings } from './unplugin.DH_ij6cf.mjs';
7
7
  import { createHash } from 'node:crypto';
8
8
 
9
9
  function resolveImportedStaticSz(value) {
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
 
3
+ const node_crypto = require('node:crypto');
3
4
  const fs = require('node:fs');
4
5
  const path = require('node:path');
5
6
 
@@ -31,6 +32,52 @@ function normalizePathSeparators(value) {
31
32
  return value.split(WINDOWS_PATH_SEPARATOR).join("/");
32
33
  }
33
34
 
35
+ const DEFAULT_RENAME_RETRIES = 5;
36
+ const DEFAULT_RENAME_RETRY_DELAY_MS = 10;
37
+ function isRetryableRenameError(error) {
38
+ return typeof error === "object" && error !== null && "code" in error && (error.code === "EBUSY" || error.code === "EPERM" || error.code === "EACCES");
39
+ }
40
+ function sleepSync(ms) {
41
+ if (ms <= 0) {
42
+ return;
43
+ }
44
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
45
+ }
46
+ function atomicRenameWithRetry(from, to, options = {}) {
47
+ const maxRetries = options.maxRetries ?? DEFAULT_RENAME_RETRIES;
48
+ const retryDelayMs = options.retryDelayMs ?? DEFAULT_RENAME_RETRY_DELAY_MS;
49
+ const renameSync = options.renameSync ?? fs__namespace.renameSync;
50
+ for (let attempt = 0; ; attempt++) {
51
+ try {
52
+ renameSync(from, to);
53
+ return;
54
+ } catch (error) {
55
+ if (!isRetryableRenameError(error) || attempt >= maxRetries) {
56
+ throw error;
57
+ }
58
+ sleepSync(retryDelayMs);
59
+ }
60
+ }
61
+ }
62
+ function atomicWriteFileSync(file, content, options = {}) {
63
+ const dir = path__namespace.dirname(file);
64
+ const tmp = path__namespace.join(
65
+ dir,
66
+ `.tmp-${path__namespace.basename(file)}-${process.pid}-${Date.now()}-${node_crypto.randomUUID()}`
67
+ );
68
+ fs__namespace.mkdirSync(dir, { recursive: true });
69
+ fs__namespace.writeFileSync(tmp, content, "utf8");
70
+ try {
71
+ atomicRenameWithRetry(tmp, file, options);
72
+ } catch (error) {
73
+ try {
74
+ fs__namespace.rmSync(tmp, { force: true });
75
+ } catch {
76
+ }
77
+ throw error;
78
+ }
79
+ }
80
+
34
81
  const SAFELIST_HEADER = "# Auto-generated by csszyx \u2014 DO NOT EDIT\n# Tailwind scans this file for class names, one per line.\n";
35
82
  function renderSafelistFile(classNames) {
36
83
  if (classNames.length === 0) {
@@ -228,6 +275,7 @@ function cssImportsTailwind(code) {
228
275
  exports.SAFELIST_FILE = SAFELIST_FILE;
229
276
  exports.appendTailwindSourceDirective = appendTailwindSourceDirective;
230
277
  exports.assertNoLegacySourceStylesheet = assertNoLegacySourceStylesheet;
278
+ exports.atomicWriteFileSync = atomicWriteFileSync;
231
279
  exports.computeSafelistRelPath = computeSafelistRelPath;
232
280
  exports.cssImportsTailwind = cssImportsTailwind;
233
281
  exports.findLegacySourceDirective = findLegacySourceDirective;
@@ -1,3 +1,4 @@
1
+ import { randomUUID } from 'node:crypto';
1
2
  import * as fs from 'node:fs';
2
3
  import * as path from 'node:path';
3
4
 
@@ -14,6 +15,52 @@ function normalizePathSeparators(value) {
14
15
  return value.split(WINDOWS_PATH_SEPARATOR).join("/");
15
16
  }
16
17
 
18
+ const DEFAULT_RENAME_RETRIES = 5;
19
+ const DEFAULT_RENAME_RETRY_DELAY_MS = 10;
20
+ function isRetryableRenameError(error) {
21
+ return typeof error === "object" && error !== null && "code" in error && (error.code === "EBUSY" || error.code === "EPERM" || error.code === "EACCES");
22
+ }
23
+ function sleepSync(ms) {
24
+ if (ms <= 0) {
25
+ return;
26
+ }
27
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
28
+ }
29
+ function atomicRenameWithRetry(from, to, options = {}) {
30
+ const maxRetries = options.maxRetries ?? DEFAULT_RENAME_RETRIES;
31
+ const retryDelayMs = options.retryDelayMs ?? DEFAULT_RENAME_RETRY_DELAY_MS;
32
+ const renameSync = options.renameSync ?? fs.renameSync;
33
+ for (let attempt = 0; ; attempt++) {
34
+ try {
35
+ renameSync(from, to);
36
+ return;
37
+ } catch (error) {
38
+ if (!isRetryableRenameError(error) || attempt >= maxRetries) {
39
+ throw error;
40
+ }
41
+ sleepSync(retryDelayMs);
42
+ }
43
+ }
44
+ }
45
+ function atomicWriteFileSync(file, content, options = {}) {
46
+ const dir = path.dirname(file);
47
+ const tmp = path.join(
48
+ dir,
49
+ `.tmp-${path.basename(file)}-${process.pid}-${Date.now()}-${randomUUID()}`
50
+ );
51
+ fs.mkdirSync(dir, { recursive: true });
52
+ fs.writeFileSync(tmp, content, "utf8");
53
+ try {
54
+ atomicRenameWithRetry(tmp, file, options);
55
+ } catch (error) {
56
+ try {
57
+ fs.rmSync(tmp, { force: true });
58
+ } catch {
59
+ }
60
+ throw error;
61
+ }
62
+ }
63
+
17
64
  const SAFELIST_HEADER = "# Auto-generated by csszyx \u2014 DO NOT EDIT\n# Tailwind scans this file for class names, one per line.\n";
18
65
  function renderSafelistFile(classNames) {
19
66
  if (classNames.length === 0) {
@@ -208,4 +255,4 @@ function cssImportsTailwind(code) {
208
255
  return TAILWIND_IMPORT.test(stripCssBlockComments(code));
209
256
  }
210
257
 
211
- export { SAFELIST_FILE as S, appendTailwindSourceDirective as a, cssImportsTailwind as b, computeSafelistRelPath as c, removeLegacySafelists as d, assertNoLegacySourceStylesheet as e, findPostcssConfigWithoutCsszyx as f, stripCssBlockComments as g, findLegacySourceDirective as h, legacySourceMessage as l, missingPostcssPluginMessage as m, normalizePathSeparators as n, renderSafelistFile as r, sortStrings as s };
258
+ export { SAFELIST_FILE as S, appendTailwindSourceDirective as a, cssImportsTailwind as b, computeSafelistRelPath as c, atomicWriteFileSync as d, removeLegacySafelists as e, findPostcssConfigWithoutCsszyx as f, assertNoLegacySourceStylesheet as g, stripCssBlockComments as h, findLegacySourceDirective as i, legacySourceMessage as l, missingPostcssPluginMessage as m, normalizePathSeparators as n, renderSafelistFile as r, sortStrings as s };
@@ -1,6 +1,6 @@
1
1
  import fs__default from 'node:fs';
2
2
  import path__default from 'node:path';
3
- import { s as sortStrings } from './unplugin.CqJS0BbD.mjs';
3
+ import { s as sortStrings } from './unplugin.DH_ij6cf.mjs';
4
4
 
5
5
  const EMPTY_THEME = {
6
6
  colors: [],
@@ -2,7 +2,7 @@
2
2
 
3
3
  const fs = require('node:fs');
4
4
  const path = require('node:path');
5
- const safelistSource = require('./unplugin.KnDCM-sr.cjs');
5
+ const safelistSource = require('./unplugin.DDSWQJYX.cjs');
6
6
 
7
7
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
8
8
 
@@ -13,10 +13,10 @@ 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.DX3rYT4P.cjs');
16
+ const safelistSource = require('./unplugin.DDSWQJYX.cjs');
17
+ const transformCache = require('./unplugin.BzF0V2kw.cjs');
17
18
  const cssMangler = require('../css-mangler.cjs');
18
- const themeGroupsFile = require('./unplugin.C7i0agiO.cjs');
19
- const safelistSource = require('./unplugin.KnDCM-sr.cjs');
19
+ const themeGroupsFile = require('./unplugin.J6ue_lRJ.cjs');
20
20
  const node_zlib = require('node:zlib');
21
21
  const postcss = require('postcss');
22
22
  const valueParser = require('postcss-value-parser');
@@ -2180,13 +2180,14 @@ function findOpeningTag(source, tag) {
2180
2180
  }
2181
2181
  }
2182
2182
  const _warnedClassNameAuthors = /* @__PURE__ */ new Set();
2183
+ const _warnedSafelistWriteFailures = /* @__PURE__ */ new Set();
2183
2184
  let _hasWarnedTsConfig = false;
2184
2185
  let _hasWarnedTransformCacheVersion = false;
2185
2186
  let _hasWarnedNativeFallback = false;
2186
2187
  const _loggedActiveParsers = /* @__PURE__ */ new Set();
2187
- 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.BLbrShMZ.cjs', document.baseURI).href)));
2188
+ 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.dz3AdzsO.cjs', document.baseURI).href)));
2188
2189
  const PLUGIN_VERSION = findPackageVersionFromFile(
2189
- node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('shared/unplugin.BLbrShMZ.cjs', document.baseURI).href))),
2190
+ node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('shared/unplugin.dz3AdzsO.cjs', document.baseURI).href))),
2190
2191
  UNKNOWN_PACKAGE_VERSION
2191
2192
  );
2192
2193
  const COMPILER_VERSION = findPackageVersionFromModule("@csszyx/compiler", UNKNOWN_PACKAGE_VERSION);
@@ -2881,6 +2882,17 @@ function normalizeSourceFilename(filename) {
2881
2882
  return safelistSource.normalizePathSeparators(filename);
2882
2883
  }
2883
2884
  const SCRIPT_ID_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx"];
2885
+ const STYLESHEET_FILE_EXTENSIONS = [
2886
+ ".css",
2887
+ ".pcss",
2888
+ ".postcss",
2889
+ ".scss",
2890
+ ".sass",
2891
+ ".less",
2892
+ ".styl",
2893
+ ".stylus",
2894
+ ".sss"
2895
+ ];
2884
2896
  const SOURCE_MODULE_EXTENSIONS = [...SCRIPT_ID_EXTENSIONS, ".cts", ".mts", ".cjs", ".mjs"];
2885
2897
  function matchesScriptExtension(id, extensions) {
2886
2898
  return extensions.some((ext) => id.endsWith(ext) || id.includes(`${ext}?`));
@@ -3053,7 +3065,14 @@ function mangleCodeClassesSync(code, mangleMap) {
3053
3065
  result = out + result.slice(copiedTo);
3054
3066
  }
3055
3067
  }
3056
- result = result.replace(/([,(]|&&)(\s*)"([^"]+)"/g, (match, sep, ws, inner) => {
3068
+ const objectKeyColon = /\s*:/y;
3069
+ result = result.replace(/([,([{]|&&)(\s*)"([^"]+)"/g, (match, sep, ws, inner, offset) => {
3070
+ if (sep === "{") {
3071
+ objectKeyColon.lastIndex = offset + match.length;
3072
+ if (!objectKeyColon.test(result)) {
3073
+ return match;
3074
+ }
3075
+ }
3057
3076
  const tokens = inner.split(/\s+/).filter(Boolean);
3058
3077
  if (tokens.length === 0) {
3059
3078
  return match;
@@ -3668,11 +3687,18 @@ function createCsszyxPlugins(options = {}) {
3668
3687
  }
3669
3688
  }
3670
3689
  if (existing !== content) {
3671
- fs__namespace.mkdirSync(path__namespace.dirname(safelistPath), { recursive: true });
3672
- fs__namespace.writeFileSync(safelistPath, content);
3690
+ safelistSource.atomicWriteFileSync(safelistPath, content);
3673
3691
  safelistSource.removeLegacySafelists(state.rootDir, console.warn);
3674
3692
  }
3675
- } catch {
3693
+ } catch (error) {
3694
+ if (_warnedSafelistWriteFailures.has(safelistPath)) {
3695
+ return;
3696
+ }
3697
+ _warnedSafelistWriteFailures.add(safelistPath);
3698
+ const reason = error instanceof Error ? error.message : String(error);
3699
+ console.warn(
3700
+ `[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.`
3701
+ );
3676
3702
  }
3677
3703
  }
3678
3704
  function recordPackagesSkipIfSz(filePath) {
@@ -4207,7 +4233,9 @@ function createCsszyxPlugins(options = {}) {
4207
4233
  if (!safelistSource.cssImportsTailwind(code)) return null;
4208
4234
  state.sawTailwindEntry = true;
4209
4235
  const [entryFile] = id.split("?");
4210
- state.tailwindEntryFiles.add(entryFile);
4236
+ if (STYLESHEET_FILE_EXTENSIONS.some((ext) => entryFile.endsWith(ext))) {
4237
+ state.tailwindEntryFiles.add(entryFile);
4238
+ }
4211
4239
  if (cssHasContentScope(code)) state.tailwindEntryScoped = true;
4212
4240
  if (!hasInjectableTailwindCandidate(state.classes)) return null;
4213
4241
  const relPath = safelistSource.computeSafelistRelPath(state.rootDir, SAFELIST_FILENAME, id);
@@ -4671,13 +4699,35 @@ ${transformedCode}`;
4671
4699
  /**
4672
4700
  * Vite HMR hook: re-runs theme scan when a watched CSS file changes,
4673
4701
  * and incrementally updates the safelist when a source file gains new sz classes.
4674
- * @param ctx - HMR context containing the changed file
4702
+ *
4703
+ * `hotUpdate` rather than `handleHotUpdate` because the safelist
4704
+ * can arrive as a CREATE. `writeSafelistFile` returns early on an
4705
+ * empty class set, so a project with no `sz` at prescan has no
4706
+ * safelist file, and the first `sz` edit makes one. Vite routes a
4707
+ * create to `hotUpdate` only — its `handleHotUpdate` branch runs
4708
+ * for `type === 'update'` and nothing else — so the legacy hook
4709
+ * left that one event to `@tailwindcss/vite`, which answers a
4710
+ * scanned file whose only modules are asset nodes with an
4711
+ * unaddressed `full-reload`.
4712
+ *
4713
+ * @param this - Vite's plugin context for the pass being run.
4714
+ * @param this.environment - The environment this pass belongs to,
4715
+ * absent when a host calls the hook without one.
4716
+ * @param this.environment.name - `client` for the pass that owns
4717
+ * the page; `ssr` and any custom environment follow it.
4718
+ * @param this.environment.moduleGraph - That environment's own
4719
+ * graph, the one Vite replaces with this hook's answer.
4720
+ * @param ctx - HMR context: the changed file, why it changed, and
4721
+ * the dev server.
4675
4722
  * @returns The modules a safelist write affects, so Vite hot-updates
4676
4723
  * the stylesheet instead of reloading the page; undefined otherwise,
4677
4724
  * which leaves Vite's own handling in place.
4678
4725
  */
4679
- handleHotUpdate(ctx) {
4680
- prescanResultHandoff.clear();
4726
+ hotUpdate(ctx) {
4727
+ const isClientPass = (this.environment?.name ?? "client") === "client";
4728
+ if (isClientPass) {
4729
+ prescanResultHandoff.clear();
4730
+ }
4681
4731
  const scanCss = options.build?.scanCss;
4682
4732
  const reloadThemeGroupsModule = () => {
4683
4733
  const themeGroupsModule = ctx.server.moduleGraph.getModuleById(
@@ -4687,7 +4737,7 @@ ${transformedCode}`;
4687
4737
  ctx.server.moduleGraph.invalidateModule(themeGroupsModule);
4688
4738
  }
4689
4739
  };
4690
- if (ctx.file.endsWith(".css")) {
4740
+ if (isClientPass && ctx.file.endsWith(".css")) {
4691
4741
  const root = ctx.server.config.root || process.cwd();
4692
4742
  const before = themeGroupsFile.createThemeGroupsModule(themeGroupTokens());
4693
4743
  if (scanCss && matchesAnyPattern(ctx.file, scanCss, root)) {
@@ -4700,9 +4750,11 @@ ${transformedCode}`;
4700
4750
  }
4701
4751
  }
4702
4752
  if (safelistSource.normalizePathSeparators(ctx.file) === safelistSource.normalizePathSeparators(path__namespace.join(state.rootDir, SAFELIST_FILENAME))) {
4703
- return tailwindEntryModules(ctx.server.moduleGraph);
4753
+ return tailwindEntryModules(
4754
+ this.environment?.moduleGraph ?? ctx.server.environments.client.moduleGraph
4755
+ );
4704
4756
  }
4705
- discoverHotFileClasses(ctx.file, ctx.server.watcher);
4757
+ if (isClientPass) discoverHotFileClasses(ctx.file, ctx.server.watcher);
4706
4758
  return void 0;
4707
4759
  },
4708
4760
  transformIndexHtml: {
@@ -4,8 +4,8 @@ const fs = require('node:fs');
4
4
  const path = require('node:path');
5
5
  const compiler = require('@csszyx/compiler');
6
6
  const types = require('@csszyx/types');
7
- const transformCache = require('./unplugin.DX3rYT4P.cjs');
8
- const safelistSource = require('./unplugin.KnDCM-sr.cjs');
7
+ const transformCache = require('./unplugin.BzF0V2kw.cjs');
8
+ const safelistSource = require('./unplugin.DDSWQJYX.cjs');
9
9
  const node_crypto = require('node:crypto');
10
10
 
11
11
  function _interopNamespaceCompat(e) {
@@ -1,4 +1,4 @@
1
- import { a as NextSafelistMaterializeResult, b as NextSafelistStateLockOptions, A as AtomicWriteOptions } from './unplugin.C2ilavL1.mjs';
1
+ import { a as NextSafelistMaterializeResult, b as NextSafelistStateLockOptions, A as AtomicWriteOptions } from './unplugin.BGog1Bib.cjs';
2
2
 
3
3
  /** Options for one synchronous watcher materialization cycle. */
4
4
  interface NextWatcherCycleOptions {
package/dist/vite.cjs CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- const unplugin = require('./shared/unplugin.BLbrShMZ.cjs');
5
+ const unplugin = require('./shared/unplugin.dz3AdzsO.cjs');
6
6
  require('node:crypto');
7
7
  require('node:fs');
8
8
  require('node:module');
@@ -16,12 +16,12 @@ require('@csszyx/svelte-adapter');
16
16
  require('@csszyx/types');
17
17
  require('@csszyx/vue-adapter');
18
18
  require('unplugin');
19
- require('./shared/unplugin.DX3rYT4P.cjs');
20
- require('./shared/unplugin.KnDCM-sr.cjs');
19
+ require('./shared/unplugin.DDSWQJYX.cjs');
20
+ require('./shared/unplugin.BzF0V2kw.cjs');
21
21
  require('./css-mangler.cjs');
22
22
  require('postcss');
23
23
  require('postcss-selector-parser');
24
- require('./shared/unplugin.C7i0agiO.cjs');
24
+ require('./shared/unplugin.J6ue_lRJ.cjs');
25
25
  require('node:zlib');
26
26
  require('postcss-value-parser');
27
27
 
package/dist/vite.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { an } from './shared/unplugin.BHfqCocB.cjs';
1
+ import { an } from './shared/unplugin.BT7PqYuK.cjs';
2
2
  export = an;
3
3
  import '@csszyx/compiler';
4
4
  import '@csszyx/types';
package/dist/vite.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- export { an as default } from './shared/unplugin.BHfqCocB.mjs';
1
+ export { an as default } from './shared/unplugin.BT7PqYuK.mjs';
2
2
  import '@csszyx/compiler';
3
3
  import '@csszyx/types';
4
4
  import 'esbuild';
package/dist/vite.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { a1 as default } from './shared/unplugin.BGufkSFT.mjs';
1
+ export { a1 as default } from './shared/unplugin.BxsTa17g.mjs';
2
2
  import 'node:crypto';
3
3
  import 'node:fs';
4
4
  import 'node:module';
@@ -12,11 +12,11 @@ import '@csszyx/svelte-adapter';
12
12
  import '@csszyx/types';
13
13
  import '@csszyx/vue-adapter';
14
14
  import 'unplugin';
15
- import './shared/unplugin.AGR7mihU.mjs';
16
- import './shared/unplugin.CqJS0BbD.mjs';
15
+ import './shared/unplugin.DH_ij6cf.mjs';
16
+ import './shared/unplugin.Bk9o8_RZ.mjs';
17
17
  import './css-mangler.mjs';
18
18
  import 'postcss';
19
19
  import 'postcss-selector-parser';
20
- import './shared/unplugin.BourSpnZ.mjs';
20
+ import './shared/unplugin.DK0b4fr7.mjs';
21
21
  import 'node:zlib';
22
22
  import 'postcss-value-parser';
package/dist/webpack.cjs CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- const unplugin = require('./shared/unplugin.BLbrShMZ.cjs');
5
+ const unplugin = require('./shared/unplugin.dz3AdzsO.cjs');
6
6
  require('node:crypto');
7
7
  require('node:fs');
8
8
  require('node:module');
@@ -16,12 +16,12 @@ require('@csszyx/svelte-adapter');
16
16
  require('@csszyx/types');
17
17
  require('@csszyx/vue-adapter');
18
18
  require('unplugin');
19
- require('./shared/unplugin.DX3rYT4P.cjs');
20
- require('./shared/unplugin.KnDCM-sr.cjs');
19
+ require('./shared/unplugin.DDSWQJYX.cjs');
20
+ require('./shared/unplugin.BzF0V2kw.cjs');
21
21
  require('./css-mangler.cjs');
22
22
  require('postcss');
23
23
  require('postcss-selector-parser');
24
- require('./shared/unplugin.C7i0agiO.cjs');
24
+ require('./shared/unplugin.J6ue_lRJ.cjs');
25
25
  require('node:zlib');
26
26
  require('postcss-value-parser');
27
27
 
@@ -1,4 +1,4 @@
1
- import { ap } from './shared/unplugin.BHfqCocB.cjs';
1
+ import { ap } from './shared/unplugin.BT7PqYuK.cjs';
2
2
  export = ap;
3
3
  import '@csszyx/compiler';
4
4
  import '@csszyx/types';
@@ -1,4 +1,4 @@
1
- export { ap as default } from './shared/unplugin.BHfqCocB.mjs';
1
+ export { ap as default } from './shared/unplugin.BT7PqYuK.mjs';
2
2
  import '@csszyx/compiler';
3
3
  import '@csszyx/types';
4
4
  import 'esbuild';
package/dist/webpack.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { a3 as default } from './shared/unplugin.BGufkSFT.mjs';
1
+ export { a3 as default } from './shared/unplugin.BxsTa17g.mjs';
2
2
  import 'node:crypto';
3
3
  import 'node:fs';
4
4
  import 'node:module';
@@ -12,11 +12,11 @@ import '@csszyx/svelte-adapter';
12
12
  import '@csszyx/types';
13
13
  import '@csszyx/vue-adapter';
14
14
  import 'unplugin';
15
- import './shared/unplugin.AGR7mihU.mjs';
16
- import './shared/unplugin.CqJS0BbD.mjs';
15
+ import './shared/unplugin.DH_ij6cf.mjs';
16
+ import './shared/unplugin.Bk9o8_RZ.mjs';
17
17
  import './css-mangler.mjs';
18
18
  import 'postcss';
19
19
  import 'postcss-selector-parser';
20
- import './shared/unplugin.BourSpnZ.mjs';
20
+ import './shared/unplugin.DK0b4fr7.mjs';
21
21
  import 'node:zlib';
22
22
  import 'postcss-value-parser';