@csszyx/unplugin 0.9.9 → 0.9.10

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.
package/dist/index.cjs CHANGED
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  const cssMangler = require('./css-mangler.cjs');
6
- const unplugin = require('./shared/unplugin.Dfao2VkS.cjs');
6
+ const unplugin = require('./shared/unplugin.BT-U5kd1.cjs');
7
7
  const types = require('@csszyx/types');
8
8
  require('postcss');
9
9
  require('postcss-selector-parser');
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  export { createPostCSSPlugin, escapeCSSClassName, mangleCSS, mangleCSSSync, unescapeTailwindClass } from './css-mangler.mjs';
2
- export { a as assertNoRSCBoundaryViolation, b as assertNoRSCGraphViolation, c as createGlobalVarAliasValidationOptions, d as createGlobalVarMapAssetSource, e as createGlobalVarScanCacheKey, f as createRSCModuleRecord, u as default, g as deleteRSCModuleRecord, h as esbuildPlugin, i as extractGlobalVarAliasesForManifest, j as findRSCBoundaryViolation, k as findRSCGraphViolation, l as hasTokens, m as hasUseClientDirective, n as hasUseServerDirective, o as isRSCServerModule, p as isTailwindReservedGlobalVar, q as mangleCodeClassesSync, r as mergeThemes, s as normalizeGlobalVarAliasesForCache, t as parseThemeBlocks, v as planGlobalVarAliases, w as readGlobalVarScanCache, x as resolveGlobalVarScanCacheDir, y as resolveNativeCacheIdentity, z as rewriteGlobalVarCssAliases, A as rollupPlugin, B as scanGlobalVarCss, u as unplugin, C as validateGlobalVarAliasInputs, D as vitePlugin, E as webpackPlugin, F as writeGlobalVarScanCache } from './shared/unplugin.CMsKFZ-l.mjs';
2
+ export { a as assertNoRSCBoundaryViolation, b as assertNoRSCGraphViolation, c as createGlobalVarAliasValidationOptions, d as createGlobalVarMapAssetSource, e as createGlobalVarScanCacheKey, f as createRSCModuleRecord, u as default, g as deleteRSCModuleRecord, h as esbuildPlugin, i as extractGlobalVarAliasesForManifest, j as findRSCBoundaryViolation, k as findRSCGraphViolation, l as hasTokens, m as hasUseClientDirective, n as hasUseServerDirective, o as isRSCServerModule, p as isTailwindReservedGlobalVar, q as mangleCodeClassesSync, r as mergeThemes, s as normalizeGlobalVarAliasesForCache, t as parseThemeBlocks, v as planGlobalVarAliases, w as readGlobalVarScanCache, x as resolveGlobalVarScanCacheDir, y as resolveNativeCacheIdentity, z as rewriteGlobalVarCssAliases, A as rollupPlugin, B as scanGlobalVarCss, u as unplugin, C as validateGlobalVarAliasInputs, D as vitePlugin, E as webpackPlugin, F as writeGlobalVarScanCache } from './shared/unplugin.jEasXLFM.mjs';
3
3
  export { CSSZYX_GLOBAL_ALIAS_PREFIX, TAILWIND_RESERVED_PREFIXES } from '@csszyx/types';
4
4
  import 'postcss';
5
5
  import 'postcss-selector-parser';
@@ -4,7 +4,7 @@ const node_crypto = require('node:crypto');
4
4
  const fs = require('node:fs');
5
5
  const path = require('node:path');
6
6
  const nextTransformMetadata = require('./shared/unplugin.DWtXPCGo.cjs');
7
- const nextWatcherCycle = require('./shared/unplugin.s62yJbu1.cjs');
7
+ const nextWatcherCycle = require('./shared/unplugin.Bo6Kx-T6.cjs');
8
8
  const transformCache = require('./shared/unplugin.pmTknYLy.cjs');
9
9
  require('@csszyx/compiler');
10
10
  require('node:os');
@@ -2,7 +2,7 @@ import { createHash } from 'node:crypto';
2
2
  import { existsSync, readFileSync } from 'node:fs';
3
3
  import * as path from 'node:path';
4
4
  import { r as readPackageVersion, t as transformNextSource, c as collectNextTransformMetadata, a as createNextSafelistShardFromMetadata } from './shared/unplugin.C1N5i6Eg.mjs';
5
- import { c as createNextStateContext, w as writeNextSafelistShard, r as runNextWatcherCycle } from './shared/unplugin.BtQzlC2C.mjs';
5
+ import { c as createNextStateContext, w as writeNextSafelistShard, r as runNextWatcherCycle } from './shared/unplugin.VAel6lI0.mjs';
6
6
  import { r as resolveTransformCacheDir } from './shared/unplugin.BpWUtI9U.mjs';
7
7
  import '@csszyx/compiler';
8
8
  import 'node:os';
@@ -4,7 +4,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  const node_crypto = require('node:crypto');
6
6
  const path = require('node:path');
7
- const nextWatcherCycle = require('./shared/unplugin.s62yJbu1.cjs');
7
+ const nextWatcherCycle = require('./shared/unplugin.Bo6Kx-T6.cjs');
8
8
  const nextTransformMetadata = require('./shared/unplugin.DWtXPCGo.cjs');
9
9
  const transformCache = require('./shared/unplugin.pmTknYLy.cjs');
10
10
  require('node:fs');
@@ -178,7 +178,18 @@ function assertProductionManifestReady(context, options) {
178
178
  );
179
179
  if (!validation.ok) {
180
180
  throw new Error(
181
- `[csszyx] Next Turbopack production cache is not ready for ${context.root}: ${validation.reason}. Run csszyx next prebuild before next build --turbo.`
181
+ [
182
+ `[csszyx] Next Turbopack production cache is not ready for ${context.root}: ${validation.reason}.`,
183
+ "Production builds with Turbopack need the csszyx safelist seeded first:",
184
+ "",
185
+ " npx csszyx next prebuild 'app/**/*.tsx'",
186
+ "",
187
+ "Wire it into package.json so plain builds keep working:",
188
+ "",
189
+ ` "build": "csszyx next prebuild 'app/**/*.tsx' && next build"`,
190
+ "",
191
+ "Docs: https://csszyx.com/docs/installation#nextjs-turbopack-setup"
192
+ ].join("\n")
182
193
  );
183
194
  }
184
195
  }
@@ -1,6 +1,6 @@
1
1
  import { createHash } from 'node:crypto';
2
2
  import * as path from 'node:path';
3
- import { c as createNextStateContext, w as writeNextSafelistShard, r as runNextWatcherCycle, v as validateNextGenerationManifest, a as readNextGenerationManifest } from './shared/unplugin.BtQzlC2C.mjs';
3
+ import { c as createNextStateContext, w as writeNextSafelistShard, r as runNextWatcherCycle, v as validateNextGenerationManifest, a as readNextGenerationManifest } from './shared/unplugin.VAel6lI0.mjs';
4
4
  import { r as readPackageVersion, t as transformNextSource, c as collectNextTransformMetadata, a as createNextSafelistShardFromMetadata } from './shared/unplugin.C1N5i6Eg.mjs';
5
5
  import { r as resolveTransformCacheDir } from './shared/unplugin.BpWUtI9U.mjs';
6
6
  import 'node:fs';
@@ -159,7 +159,18 @@ function assertProductionManifestReady(context, options) {
159
159
  );
160
160
  if (!validation.ok) {
161
161
  throw new Error(
162
- `[csszyx] Next Turbopack production cache is not ready for ${context.root}: ${validation.reason}. Run csszyx next prebuild before next build --turbo.`
162
+ [
163
+ `[csszyx] Next Turbopack production cache is not ready for ${context.root}: ${validation.reason}.`,
164
+ "Production builds with Turbopack need the csszyx safelist seeded first:",
165
+ "",
166
+ " npx csszyx next prebuild 'app/**/*.tsx'",
167
+ "",
168
+ "Wire it into package.json so plain builds keep working:",
169
+ "",
170
+ ` "build": "csszyx next prebuild 'app/**/*.tsx' && next build"`,
171
+ "",
172
+ "Docs: https://csszyx.com/docs/installation#nextjs-turbopack-setup"
173
+ ].join("\n")
163
174
  );
164
175
  }
165
176
  }
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const path = require('node:path');
4
- const nextWatcherCycle = require('./shared/unplugin.s62yJbu1.cjs');
4
+ const nextWatcherCycle = require('./shared/unplugin.Bo6Kx-T6.cjs');
5
5
  require('node:fs');
6
6
  require('node:crypto');
7
7
  require('node:os');
@@ -1,5 +1,5 @@
1
1
  import * as path from 'node:path';
2
- import { r as runNextWatcherCycle } from './shared/unplugin.BtQzlC2C.mjs';
2
+ import { r as runNextWatcherCycle } from './shared/unplugin.VAel6lI0.mjs';
3
3
  import 'node:fs';
4
4
  import 'node:crypto';
5
5
  import 'node:os';
@@ -1562,9 +1562,9 @@ const RUNTIME_HELPER_IMPORT_RE = {
1562
1562
  };
1563
1563
  let _hasWarnedTsConfig = false;
1564
1564
  let _hasWarnedTransformCacheVersion = false;
1565
- 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.Dfao2VkS.cjs', document.baseURI).href)));
1565
+ 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.BT-U5kd1.cjs', document.baseURI).href)));
1566
1566
  const PLUGIN_VERSION = findPackageVersionFromFile(
1567
- node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('shared/unplugin.Dfao2VkS.cjs', document.baseURI).href))),
1567
+ node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('shared/unplugin.BT-U5kd1.cjs', document.baseURI).href))),
1568
1568
  UNKNOWN_PACKAGE_VERSION
1569
1569
  );
1570
1570
  const COMPILER_VERSION = findPackageVersionFromModule("@csszyx/compiler", UNKNOWN_PACKAGE_VERSION);
@@ -2055,6 +2055,45 @@ function mangleCodeClassesSync(code, mangleMap) {
2055
2055
  }
2056
2056
  return changed ? `className:\`${out}\`` : fullMatch;
2057
2057
  });
2058
+ function scanClassExpression(source, from) {
2059
+ let depth = 0;
2060
+ let j = from;
2061
+ while (j < source.length) {
2062
+ const ch = source[j];
2063
+ if (ch === "(" || ch === "[") {
2064
+ depth++;
2065
+ } else if (ch === ")" || ch === "]") {
2066
+ if (depth === 0) {
2067
+ break;
2068
+ }
2069
+ depth--;
2070
+ } else if (depth === 0 && (ch === "," || ch === ";" || ch === "\n" || ch === "}")) {
2071
+ break;
2072
+ }
2073
+ j++;
2074
+ }
2075
+ return j;
2076
+ }
2077
+ function mangleTernaryClassStrings(expr) {
2078
+ const qIdx = expr.indexOf("?");
2079
+ if (qIdx === -1 || !expr.slice(qIdx).includes(":")) {
2080
+ return null;
2081
+ }
2082
+ let changed = false;
2083
+ const mangled = expr.replace(/"([^"]*)"/g, (qm, inner) => {
2084
+ const parts = inner.split(/\s+/).filter(Boolean);
2085
+ if (parts.length === 0) {
2086
+ return qm;
2087
+ }
2088
+ const mangledStr = parts.map((p) => mangleMap[p] || p).join(" ");
2089
+ if (mangledStr !== inner) {
2090
+ changed = true;
2091
+ return `"${mangledStr}"`;
2092
+ }
2093
+ return qm;
2094
+ });
2095
+ return changed ? mangled : null;
2096
+ }
2058
2097
  {
2059
2098
  const marker = "className:";
2060
2099
  let searchFrom = 0;
@@ -2076,47 +2115,39 @@ function mangleCodeClassesSync(code, mangleMap) {
2076
2115
  searchFrom = afterColon;
2077
2116
  continue;
2078
2117
  }
2079
- let depth = 0;
2080
- let j = afterColon;
2081
- while (j < result.length) {
2082
- const ch = result[j];
2083
- if (ch === "(" || ch === "[") {
2084
- depth++;
2085
- } else if (ch === ")" || ch === "]") {
2086
- if (depth === 0) {
2087
- break;
2088
- }
2089
- depth--;
2090
- } else if (depth === 0 && (ch === "," || ch === ";" || ch === "\n" || ch === "}")) {
2091
- break;
2092
- }
2093
- j++;
2094
- }
2118
+ const j = scanClassExpression(result, afterColon);
2095
2119
  const expr = result.slice(afterColon, j);
2096
- const qIdx = expr.indexOf("?");
2097
- if (qIdx === -1 || !expr.slice(qIdx).includes(":")) {
2098
- out += expr;
2099
- searchFrom = j;
2100
- continue;
2101
- }
2102
- let changed = false;
2103
- const mangled = expr.replace(/"([^"]*)"/g, (qm, inner) => {
2104
- const parts = inner.split(/\s+/).filter(Boolean);
2105
- if (parts.length === 0) {
2106
- return qm;
2107
- }
2108
- const mangledStr = parts.map((p) => mangleMap[p] || p).join(" ");
2109
- if (mangledStr !== inner) {
2110
- changed = true;
2111
- return `"${mangledStr}"`;
2112
- }
2113
- return qm;
2114
- });
2115
- out += changed ? mangled : expr;
2120
+ out += mangleTernaryClassStrings(expr) ?? expr;
2116
2121
  searchFrom = j;
2117
2122
  }
2118
2123
  result = out;
2119
2124
  }
2125
+ {
2126
+ const markerRe = /"class(?:Name)?"\s*,\s*/g;
2127
+ let out = "";
2128
+ let copiedTo = 0;
2129
+ let m = markerRe.exec(result);
2130
+ while (m !== null) {
2131
+ const exprStart = m.index + m[0].length;
2132
+ const firstChar = result[exprStart];
2133
+ if (firstChar === '"' || firstChar === "'" || firstChar === "`") {
2134
+ m = markerRe.exec(result);
2135
+ continue;
2136
+ }
2137
+ const j = scanClassExpression(result, exprStart);
2138
+ const expr = result.slice(exprStart, j);
2139
+ const mangled = mangleTernaryClassStrings(expr);
2140
+ if (mangled !== null) {
2141
+ out += result.slice(copiedTo, exprStart) + mangled;
2142
+ copiedTo = j;
2143
+ }
2144
+ markerRe.lastIndex = j;
2145
+ m = markerRe.exec(result);
2146
+ }
2147
+ if (copiedTo > 0) {
2148
+ result = out + result.slice(copiedTo);
2149
+ }
2150
+ }
2120
2151
  result = result.replace(/(?<=(?:[,(]|&&)\s*)"([^"]+)"/g, (match, inner) => {
2121
2152
  const tokens = inner.split(/\s+/).filter(Boolean);
2122
2153
  if (tokens.length === 0) {
@@ -2688,6 +2719,21 @@ function createCsszyxPlugins(options = {}) {
2688
2719
  }
2689
2720
  return null;
2690
2721
  },
2722
+ /**
2723
+ * Restricts the load hook to csszyx's own virtual modules.
2724
+ *
2725
+ * Without this, unplugin's webpack adapter registers its load
2726
+ * loader with `type: 'javascript/auto'` for every module (its
2727
+ * include defaults to all ids when no loadInclude exists). That
2728
+ * corrupts binary asset modules (images, fonts) in webpack apps —
2729
+ * Next.js builds fail with "not a valid image file" / "Module
2730
+ * parse failed" on assets that build fine without csszyx.
2731
+ * @param id - the module ID webpack is about to load
2732
+ * @returns true only for csszyx virtual modules
2733
+ */
2734
+ loadInclude(id) {
2735
+ return id === RESOLVED_VIRTUAL_MODULE_ID || id === RESOLVED_VIRTUAL_CHECKSUM_ID;
2736
+ },
2691
2737
  /**
2692
2738
  * Loads virtual module content — generates mangle map or checksum module code.
2693
2739
  * @param id - the resolved module ID to load
@@ -27,6 +27,7 @@ const lockfile__default = /*#__PURE__*/_interopDefaultCompat(lockfile);
27
27
  const DEFAULT_RENAME_RETRIES = 5;
28
28
  const DEFAULT_RENAME_RETRY_DELAY_MS = 10;
29
29
  const DEFAULT_STALE_LOCK_MS = 3e4;
30
+ const STALE_RECOVERY_DISABLED_MS = 2147483647;
30
31
  function resolveNextSafelistStatePaths(rootDir, cacheDir = ".csszyx/cache", outputFile = "csszyx-classes.html") {
31
32
  const resolvedCacheDir = path__namespace.resolve(rootDir, cacheDir);
32
33
  return {
@@ -81,11 +82,17 @@ function acquireNextSafelistStateLock(lockPath, pidOrOptions = {}) {
81
82
  const metadata = createLockMetadata(options);
82
83
  const staleAfterMs = options.staleAfterMs ?? DEFAULT_STALE_LOCK_MS;
83
84
  fs__namespace.mkdirSync(path__namespace.dirname(lockPath), { recursive: true });
85
+ recoverStaleAdvisoryLock(lockPath, staleAfterMs);
84
86
  let releaseAdvisory;
85
87
  try {
86
88
  releaseAdvisory = lockfile__default.lockSync(lockPath, {
87
89
  realpath: false,
88
- stale: staleAfterMs,
90
+ // Disable proper-lockfile's own stale recovery: its rmdir+remake is
91
+ // not single-winner under concurrent recovery. recoverStaleAdvisoryLock
92
+ // above clears stale locks with one elected winner, so here mkdir is a
93
+ // pure single-winner mutex. A live owner keeps the advisory mtime fresh
94
+ // via `update`, so staleness is still detected — just by us, not here.
95
+ stale: STALE_RECOVERY_DISABLED_MS,
89
96
  update: Math.max(1e3, Math.floor(staleAfterMs / 2)),
90
97
  retries: 0
91
98
  });
@@ -289,6 +296,44 @@ function readLockMetadata(lockPath) {
289
296
  return null;
290
297
  }
291
298
  }
299
+ function isAdvisoryLockStale(advisoryPath, staleAfterMs) {
300
+ try {
301
+ return fs__namespace.statSync(advisoryPath).mtimeMs < Date.now() - staleAfterMs;
302
+ } catch {
303
+ return false;
304
+ }
305
+ }
306
+ function recoverStaleAdvisoryLock(lockPath, staleAfterMs) {
307
+ const advisoryPath = `${lockPath}.lock`;
308
+ if (!isAdvisoryLockStale(advisoryPath, staleAfterMs)) {
309
+ return;
310
+ }
311
+ const electionPath = `${lockPath}.recover`;
312
+ if (isAdvisoryLockStale(electionPath, staleAfterMs)) {
313
+ try {
314
+ fs__namespace.rmdirSync(electionPath);
315
+ } catch {
316
+ }
317
+ }
318
+ try {
319
+ fs__namespace.mkdirSync(electionPath);
320
+ } catch {
321
+ return;
322
+ }
323
+ try {
324
+ if (isAdvisoryLockStale(advisoryPath, staleAfterMs)) {
325
+ try {
326
+ fs__namespace.rmdirSync(advisoryPath);
327
+ } catch {
328
+ }
329
+ }
330
+ } finally {
331
+ try {
332
+ fs__namespace.rmdirSync(electionPath);
333
+ } catch {
334
+ }
335
+ }
336
+ }
292
337
  function isLockLive(metadata, options) {
293
338
  const staleAfterMs = options.staleAfterMs ?? DEFAULT_STALE_LOCK_MS;
294
339
  const updatedAt = Date.parse(metadata.updatedAt);
@@ -7,6 +7,7 @@ import lockfile from 'proper-lockfile';
7
7
  const DEFAULT_RENAME_RETRIES = 5;
8
8
  const DEFAULT_RENAME_RETRY_DELAY_MS = 10;
9
9
  const DEFAULT_STALE_LOCK_MS = 3e4;
10
+ const STALE_RECOVERY_DISABLED_MS = 2147483647;
10
11
  function resolveNextSafelistStatePaths(rootDir, cacheDir = ".csszyx/cache", outputFile = "csszyx-classes.html") {
11
12
  const resolvedCacheDir = path.resolve(rootDir, cacheDir);
12
13
  return {
@@ -61,11 +62,17 @@ function acquireNextSafelistStateLock(lockPath, pidOrOptions = {}) {
61
62
  const metadata = createLockMetadata(options);
62
63
  const staleAfterMs = options.staleAfterMs ?? DEFAULT_STALE_LOCK_MS;
63
64
  fs.mkdirSync(path.dirname(lockPath), { recursive: true });
65
+ recoverStaleAdvisoryLock(lockPath, staleAfterMs);
64
66
  let releaseAdvisory;
65
67
  try {
66
68
  releaseAdvisory = lockfile.lockSync(lockPath, {
67
69
  realpath: false,
68
- stale: staleAfterMs,
70
+ // Disable proper-lockfile's own stale recovery: its rmdir+remake is
71
+ // not single-winner under concurrent recovery. recoverStaleAdvisoryLock
72
+ // above clears stale locks with one elected winner, so here mkdir is a
73
+ // pure single-winner mutex. A live owner keeps the advisory mtime fresh
74
+ // via `update`, so staleness is still detected — just by us, not here.
75
+ stale: STALE_RECOVERY_DISABLED_MS,
69
76
  update: Math.max(1e3, Math.floor(staleAfterMs / 2)),
70
77
  retries: 0
71
78
  });
@@ -269,6 +276,44 @@ function readLockMetadata(lockPath) {
269
276
  return null;
270
277
  }
271
278
  }
279
+ function isAdvisoryLockStale(advisoryPath, staleAfterMs) {
280
+ try {
281
+ return fs.statSync(advisoryPath).mtimeMs < Date.now() - staleAfterMs;
282
+ } catch {
283
+ return false;
284
+ }
285
+ }
286
+ function recoverStaleAdvisoryLock(lockPath, staleAfterMs) {
287
+ const advisoryPath = `${lockPath}.lock`;
288
+ if (!isAdvisoryLockStale(advisoryPath, staleAfterMs)) {
289
+ return;
290
+ }
291
+ const electionPath = `${lockPath}.recover`;
292
+ if (isAdvisoryLockStale(electionPath, staleAfterMs)) {
293
+ try {
294
+ fs.rmdirSync(electionPath);
295
+ } catch {
296
+ }
297
+ }
298
+ try {
299
+ fs.mkdirSync(electionPath);
300
+ } catch {
301
+ return;
302
+ }
303
+ try {
304
+ if (isAdvisoryLockStale(advisoryPath, staleAfterMs)) {
305
+ try {
306
+ fs.rmdirSync(advisoryPath);
307
+ } catch {
308
+ }
309
+ }
310
+ } finally {
311
+ try {
312
+ fs.rmdirSync(electionPath);
313
+ } catch {
314
+ }
315
+ }
316
+ }
272
317
  function isLockLive(metadata, options) {
273
318
  const staleAfterMs = options.staleAfterMs ?? DEFAULT_STALE_LOCK_MS;
274
319
  const updatedAt = Date.parse(metadata.updatedAt);
@@ -2035,6 +2035,45 @@ function mangleCodeClassesSync(code, mangleMap) {
2035
2035
  }
2036
2036
  return changed ? `className:\`${out}\`` : fullMatch;
2037
2037
  });
2038
+ function scanClassExpression(source, from) {
2039
+ let depth = 0;
2040
+ let j = from;
2041
+ while (j < source.length) {
2042
+ const ch = source[j];
2043
+ if (ch === "(" || ch === "[") {
2044
+ depth++;
2045
+ } else if (ch === ")" || ch === "]") {
2046
+ if (depth === 0) {
2047
+ break;
2048
+ }
2049
+ depth--;
2050
+ } else if (depth === 0 && (ch === "," || ch === ";" || ch === "\n" || ch === "}")) {
2051
+ break;
2052
+ }
2053
+ j++;
2054
+ }
2055
+ return j;
2056
+ }
2057
+ function mangleTernaryClassStrings(expr) {
2058
+ const qIdx = expr.indexOf("?");
2059
+ if (qIdx === -1 || !expr.slice(qIdx).includes(":")) {
2060
+ return null;
2061
+ }
2062
+ let changed = false;
2063
+ const mangled = expr.replace(/"([^"]*)"/g, (qm, inner) => {
2064
+ const parts = inner.split(/\s+/).filter(Boolean);
2065
+ if (parts.length === 0) {
2066
+ return qm;
2067
+ }
2068
+ const mangledStr = parts.map((p) => mangleMap[p] || p).join(" ");
2069
+ if (mangledStr !== inner) {
2070
+ changed = true;
2071
+ return `"${mangledStr}"`;
2072
+ }
2073
+ return qm;
2074
+ });
2075
+ return changed ? mangled : null;
2076
+ }
2038
2077
  {
2039
2078
  const marker = "className:";
2040
2079
  let searchFrom = 0;
@@ -2056,47 +2095,39 @@ function mangleCodeClassesSync(code, mangleMap) {
2056
2095
  searchFrom = afterColon;
2057
2096
  continue;
2058
2097
  }
2059
- let depth = 0;
2060
- let j = afterColon;
2061
- while (j < result.length) {
2062
- const ch = result[j];
2063
- if (ch === "(" || ch === "[") {
2064
- depth++;
2065
- } else if (ch === ")" || ch === "]") {
2066
- if (depth === 0) {
2067
- break;
2068
- }
2069
- depth--;
2070
- } else if (depth === 0 && (ch === "," || ch === ";" || ch === "\n" || ch === "}")) {
2071
- break;
2072
- }
2073
- j++;
2074
- }
2098
+ const j = scanClassExpression(result, afterColon);
2075
2099
  const expr = result.slice(afterColon, j);
2076
- const qIdx = expr.indexOf("?");
2077
- if (qIdx === -1 || !expr.slice(qIdx).includes(":")) {
2078
- out += expr;
2079
- searchFrom = j;
2080
- continue;
2081
- }
2082
- let changed = false;
2083
- const mangled = expr.replace(/"([^"]*)"/g, (qm, inner) => {
2084
- const parts = inner.split(/\s+/).filter(Boolean);
2085
- if (parts.length === 0) {
2086
- return qm;
2087
- }
2088
- const mangledStr = parts.map((p) => mangleMap[p] || p).join(" ");
2089
- if (mangledStr !== inner) {
2090
- changed = true;
2091
- return `"${mangledStr}"`;
2092
- }
2093
- return qm;
2094
- });
2095
- out += changed ? mangled : expr;
2100
+ out += mangleTernaryClassStrings(expr) ?? expr;
2096
2101
  searchFrom = j;
2097
2102
  }
2098
2103
  result = out;
2099
2104
  }
2105
+ {
2106
+ const markerRe = /"class(?:Name)?"\s*,\s*/g;
2107
+ let out = "";
2108
+ let copiedTo = 0;
2109
+ let m = markerRe.exec(result);
2110
+ while (m !== null) {
2111
+ const exprStart = m.index + m[0].length;
2112
+ const firstChar = result[exprStart];
2113
+ if (firstChar === '"' || firstChar === "'" || firstChar === "`") {
2114
+ m = markerRe.exec(result);
2115
+ continue;
2116
+ }
2117
+ const j = scanClassExpression(result, exprStart);
2118
+ const expr = result.slice(exprStart, j);
2119
+ const mangled = mangleTernaryClassStrings(expr);
2120
+ if (mangled !== null) {
2121
+ out += result.slice(copiedTo, exprStart) + mangled;
2122
+ copiedTo = j;
2123
+ }
2124
+ markerRe.lastIndex = j;
2125
+ m = markerRe.exec(result);
2126
+ }
2127
+ if (copiedTo > 0) {
2128
+ result = out + result.slice(copiedTo);
2129
+ }
2130
+ }
2100
2131
  result = result.replace(/(?<=(?:[,(]|&&)\s*)"([^"]+)"/g, (match, inner) => {
2101
2132
  const tokens = inner.split(/\s+/).filter(Boolean);
2102
2133
  if (tokens.length === 0) {
@@ -2668,6 +2699,21 @@ function createCsszyxPlugins(options = {}) {
2668
2699
  }
2669
2700
  return null;
2670
2701
  },
2702
+ /**
2703
+ * Restricts the load hook to csszyx's own virtual modules.
2704
+ *
2705
+ * Without this, unplugin's webpack adapter registers its load
2706
+ * loader with `type: 'javascript/auto'` for every module (its
2707
+ * include defaults to all ids when no loadInclude exists). That
2708
+ * corrupts binary asset modules (images, fonts) in webpack apps —
2709
+ * Next.js builds fail with "not a valid image file" / "Module
2710
+ * parse failed" on assets that build fine without csszyx.
2711
+ * @param id - the module ID webpack is about to load
2712
+ * @returns true only for csszyx virtual modules
2713
+ */
2714
+ loadInclude(id) {
2715
+ return id === RESOLVED_VIRTUAL_MODULE_ID || id === RESOLVED_VIRTUAL_CHECKSUM_ID;
2716
+ },
2671
2717
  /**
2672
2718
  * Loads virtual module content — generates mangle map or checksum module code.
2673
2719
  * @param id - the resolved module ID to load
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.Dfao2VkS.cjs');
5
+ const unplugin = require('./shared/unplugin.BT-U5kd1.cjs');
6
6
  require('node:fs');
7
7
  require('node:module');
8
8
  require('node:path');
package/dist/vite.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { D as vitePlugin } from './shared/unplugin.CMsKFZ-l.mjs';
1
+ import { D as vitePlugin } from './shared/unplugin.jEasXLFM.mjs';
2
2
  import 'node:fs';
3
3
  import 'node:module';
4
4
  import 'node:path';
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.Dfao2VkS.cjs');
5
+ const unplugin = require('./shared/unplugin.BT-U5kd1.cjs');
6
6
  require('node:fs');
7
7
  require('node:module');
8
8
  require('node:path');
package/dist/webpack.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { E as webpackPlugin } from './shared/unplugin.CMsKFZ-l.mjs';
1
+ import { E as webpackPlugin } from './shared/unplugin.jEasXLFM.mjs';
2
2
  import 'node:fs';
3
3
  import 'node:module';
4
4
  import 'node:path';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@csszyx/unplugin",
3
- "version": "0.9.9",
3
+ "version": "0.9.10",
4
4
  "description": "Vite and Webpack integration for csszyx",
5
5
  "keywords": [
6
6
  "csszyx",
@@ -117,19 +117,19 @@
117
117
  "postcss-value-parser": "^4.2.0",
118
118
  "proper-lockfile": "^4.1.2",
119
119
  "unplugin": "^1.10.1",
120
- "@csszyx/compiler": "0.9.9",
121
- "@csszyx/svelte-adapter": "0.9.9",
122
- "@csszyx/core": "0.9.9",
123
- "@csszyx/vue-adapter": "0.9.9",
124
- "@csszyx/types": "0.9.9"
120
+ "@csszyx/compiler": "0.9.10",
121
+ "@csszyx/core": "0.9.10",
122
+ "@csszyx/svelte-adapter": "0.9.10",
123
+ "@csszyx/vue-adapter": "0.9.10",
124
+ "@csszyx/types": "0.9.10"
125
125
  },
126
126
  "peerDependencies": {
127
- "@csszyx/runtime": "^0.9.9"
127
+ "@csszyx/runtime": "^0.9.10"
128
128
  },
129
129
  "devDependencies": {
130
130
  "@types/node": "^20.11.0",
131
131
  "@types/proper-lockfile": "^4.1.4",
132
- "esbuild": "^0.27.2",
132
+ "esbuild": "^0.28.1",
133
133
  "rollup": "^4.56.0",
134
134
  "typescript": "^6.0.3",
135
135
  "unbuild": "^3.6.1",