@csszyx/unplugin 0.10.7 → 0.10.9

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.
@@ -1,7 +1,12 @@
1
1
  'use strict';
2
2
 
3
+ function sortStrings(values) {
4
+ return [...values].sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
5
+ }
6
+
3
7
  function escapeHtmlAttribute(value) {
4
8
  return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
5
9
  }
6
10
 
7
11
  exports.escapeHtmlAttribute = escapeHtmlAttribute;
12
+ exports.sortStrings = sortStrings;
@@ -5,7 +5,7 @@ const fs = require('node:fs');
5
5
  const node_crypto = require('node:crypto');
6
6
  const node_os = require('node:os');
7
7
  const lockfile = require('proper-lockfile');
8
- const htmlEscape = require('./unplugin.DoBHTRra.cjs');
8
+ const htmlEscape = require('./unplugin.BCwRIUs_.cjs');
9
9
 
10
10
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
11
11
 
@@ -62,8 +62,8 @@ function materializeNextSafelist(paths, options = {}) {
62
62
  recordsBySource.set(record.data.sourcePath, record);
63
63
  }
64
64
  }
65
- const sortedSources = [...recordsBySource.values()].map(({ data }) => [data.sourcePath, [...new Set(data.classes)].sort()]).sort(([left], [right]) => left.localeCompare(right));
66
- const classNames = [...new Set(sortedSources.flatMap(([, classSet]) => classSet))].sort();
65
+ const sortedSources = [...recordsBySource.values()].map(({ data }) => [data.sourcePath, htmlEscape.sortStrings(new Set(data.classes))]).sort(([left], [right]) => left.localeCompare(right));
66
+ const classNames = htmlEscape.sortStrings(new Set(sortedSources.flatMap(([, classSet]) => classSet)));
67
67
  const snapshot = {
68
68
  version: 1,
69
69
  sources: sortedSources.map(([sourcePath, classSet]) => [sourcePath, classSet])
@@ -192,9 +192,9 @@ function isExistingShardEquivalent(filePath, shard) {
192
192
  }
193
193
  function normalizeShardInput(input) {
194
194
  const sourcePath = path__namespace.resolve(input.sourcePath);
195
- const classes = [
196
- ...new Set(input.classes.map((className) => className.trim()).filter(Boolean))
197
- ].sort();
195
+ const classes = htmlEscape.sortStrings(
196
+ new Set(input.classes.map((className) => className.trim()).filter(Boolean))
197
+ );
198
198
  const cacheKey = input.cacheKey ?? node_crypto.createHash("sha256").update(sourcePath).update("\0").update(input.sourceHash).digest("hex");
199
199
  return {
200
200
  version: 1,
@@ -469,7 +469,7 @@ function stableStringify(value) {
469
469
  }
470
470
  function pickEnv(env, envKeys) {
471
471
  const selected = {};
472
- for (const key of [...new Set(envKeys)].sort()) {
472
+ for (const key of htmlEscape.sortStrings(new Set(envKeys))) {
473
473
  const value = env[key];
474
474
  if (value !== void 0) {
475
475
  selected[key] = value;
@@ -4,6 +4,7 @@ const fs = require('node:fs');
4
4
  const compiler = require('@csszyx/compiler');
5
5
  const transformCache = require('./unplugin.pmTknYLy.cjs');
6
6
  const node_crypto = require('node:crypto');
7
+ const htmlEscape = require('./unplugin.BCwRIUs_.cjs');
7
8
 
8
9
  function readPackageVersion(relativePackageJson, fromUrl) {
9
10
  try {
@@ -197,8 +198,8 @@ function collectNextTransformMetadata(result, source, sourcePath) {
197
198
  return {
198
199
  sourcePath,
199
200
  sourceHash: node_crypto.createHash("sha256").update(source).digest("hex"),
200
- classes: [...classes].sort(),
201
- rawClassNames: [...result.rawClassNames].sort(),
201
+ classes: htmlEscape.sortStrings(classes),
202
+ rawClassNames: htmlEscape.sortStrings(result.rawClassNames),
202
203
  recoveryTokenCount: result.recoveryTokens.size,
203
204
  cssVariableCount: result.cssVariableMap.size
204
205
  };
@@ -234,7 +235,7 @@ function collectRuntimeStaticClasses(result, discoveredClasses) {
234
235
  }
235
236
  }
236
237
  function collectRuntimeStringClasses(objectSource, discoveredClasses) {
237
- const stringKeyValue = /(\w+)\s*:\s*(?:"([^"]*)"|'([^']*)')/g;
238
+ const stringKeyValue = /\b(\w+)\s*:\s*(?:"([^"]*)"|'([^']*)')/g;
238
239
  for (const match of objectSource.matchAll(stringKeyValue)) {
239
240
  try {
240
241
  collectTransformClasses(
@@ -246,7 +247,7 @@ function collectRuntimeStringClasses(objectSource, discoveredClasses) {
246
247
  }
247
248
  }
248
249
  function collectRuntimeNumberClasses(objectSource, discoveredClasses) {
249
- const numberKeyValue = /(\w+)\s*:\s*(-?\d+(?:\.\d+)?)\s*(?=[,}\n])/g;
250
+ const numberKeyValue = /\b(\w+)\s*:\s*(-?\d+(?:\.\d+)?)\s*(?=[,}\n])/g;
250
251
  for (const match of objectSource.matchAll(numberKeyValue)) {
251
252
  try {
252
253
  collectTransformClasses(
@@ -258,7 +259,7 @@ function collectRuntimeNumberClasses(objectSource, discoveredClasses) {
258
259
  }
259
260
  }
260
261
  function collectRuntimeBooleanClasses(objectSource, discoveredClasses) {
261
- const booleanKeyValue = /(\w+)\s*:\s*(true|false)\s*(?=[,}\n])/g;
262
+ const booleanKeyValue = /\b(\w+)\s*:\s*(true|false)\s*(?=[,}\n])/g;
262
263
  for (const match of objectSource.matchAll(booleanKeyValue)) {
263
264
  try {
264
265
  collectTransformClasses(
@@ -285,6 +285,42 @@ declare function shouldWarnMissingTailwindEntry(ownedClassCount: number, sawTail
285
285
  * @returns the warning string.
286
286
  */
287
287
  declare function missingTailwindEntryMessage(ownedClassCount: number): string;
288
+ /**
289
+ * Hazards that make production mangling unsafe in a hybrid build (a separate
290
+ * Tailwind plugin owns the utility CSS and/or hand-written CSS uses literal class
291
+ * names). Computed from data `mangleCSSSync` already returns across every CSS
292
+ * asset, so it is free to surface.
293
+ */
294
+ interface MangleHybridHazards {
295
+ /**
296
+ * Mangled tokens that ALSO appear as a class name in non-csszyx CSS. The
297
+ * short token (e.g. `y` for `w-full`) then matches external `.y` elements and
298
+ * cross-contaminates their styles — the core hybrid-mangle failure.
299
+ */
300
+ collisions: string[];
301
+ /**
302
+ * Map sources csszyx mangled but whose class never appeared in any emitted
303
+ * CSS (e.g. a utility Tailwind never generated, or a malformed key). Their
304
+ * DOM class is rewritten to a token with no rule → the element loses styling.
305
+ */
306
+ orphans: string[];
307
+ }
308
+ /**
309
+ * Detect hybrid-mangle hazards from the accumulated per-asset mangle results.
310
+ *
311
+ * @param mangleMap - the full original→token map injected into the runtime.
312
+ * @param mangledSources - map keys that were actually found and renamed in some CSS asset.
313
+ * @param externalClasses - class names found in CSS that are NOT in the mangle map (non-csszyx).
314
+ * @returns the colliding tokens and orphan sources (each sorted, deduped).
315
+ */
316
+ declare function collectMangleHybridHazards(mangleMap: Record<string, string>, mangledSources: ReadonlySet<string>, externalClasses: ReadonlySet<string>): MangleHybridHazards;
317
+ /**
318
+ * Build the hybrid-mangle hazard warning, or null when there is nothing to warn.
319
+ *
320
+ * @param hazards - the detected collisions and orphans.
321
+ * @returns a warning string, or null when both lists are empty.
322
+ */
323
+ declare function mangleHybridHazardMessage(hazards: MangleHybridHazards): string | null;
288
324
  /**
289
325
  * Whether a CSS module scopes Tailwind's content detection — `source(none)` or
290
326
  * `source("…")` on the `@import "tailwindcss"`, or any `@source not` exclusion.
@@ -504,5 +540,5 @@ declare const rollupPlugin: (options?: PartialCsszyxConfig) => InputPluginOption
504
540
  */
505
541
  declare const esbuildPlugin: (options?: PartialCsszyxConfig) => Plugin;
506
542
 
507
- export { isMonorepoPackage as A, isPackagesSkippedSource as B, mangleCodeClassesSync as D, missingTailwindEntryMessage as E, normalizeGlobalVarAliasesForCache as F, resolveCompileSourceDirs as H, resolveNativeCacheIdentity as I, rollupPlugin as J, shouldEmitWarning as K, shouldWarnMissingTailwindEntry as L, shouldWarnUnscopedMonorepo as M, skippedSzFilesMessage as N, unscopedMonorepoMessage as O, vitePlugin as Q, webpackPlugin as T, appendTailwindSourceDirective as o, computeSafelistRelPath as p, createGlobalVarMapAssetSource as q, cssHasContentScope as r, cssImportsTailwind as s, esbuildPlugin as t, unplugin as u, extractGlobalVarAliasesForManifest as v, fileMayContainSafelistableSz as w, hasInjectableTailwindCandidate as x, isCompileSourceOptedIn as y, isHardIgnoredPath as z };
508
- export type { CssVarScanResult as C, GlobalVarScanCacheKeyInput as G, PlanGlobalVarAliasesInput as P, RewriteGlobalVarCssAliasesOptions as R, ScanGlobalVarCssOptions as S, ValidateGlobalVarAliasInputsOptions as V, GlobalVarAliasPlan as a, GlobalVarCssAliasRewriteResult as b, CreateGlobalVarAliasValidationOptionsInput as c, GlobalVarAliasValidationResult as d, CssVarDefinition as e, CssVarLocation as f, CssVarReference as g, GlobalVarAliasDiagnostic as h, GlobalVarAliasDiagnosticSeverity as i, GlobalVarAliasEntry as j, GlobalVarCodeSource as k, GlobalVarCssAssetSource as l, GlobalVarCssSource as m, GlobalVarScanCacheEntry as n };
543
+ export { isHardIgnoredPath as A, isMonorepoPackage as B, isPackagesSkippedSource as D, mangleCodeClassesSync as E, mangleHybridHazardMessage as F, missingTailwindEntryMessage as H, normalizeGlobalVarAliasesForCache as I, resolveCompileSourceDirs as J, resolveNativeCacheIdentity as K, rollupPlugin as L, shouldEmitWarning as N, shouldWarnMissingTailwindEntry as O, shouldWarnUnscopedMonorepo as Q, skippedSzFilesMessage as T, unscopedMonorepoMessage as U, vitePlugin as W, webpackPlugin as X, appendTailwindSourceDirective as o, collectMangleHybridHazards as p, computeSafelistRelPath as q, createGlobalVarMapAssetSource as r, cssHasContentScope as s, cssImportsTailwind as t, unplugin as u, esbuildPlugin as v, extractGlobalVarAliasesForManifest as w, fileMayContainSafelistableSz as x, hasInjectableTailwindCandidate as y, isCompileSourceOptedIn as z };
544
+ export type { CssVarScanResult as C, GlobalVarScanCacheKeyInput as G, MangleHybridHazards as M, PlanGlobalVarAliasesInput as P, RewriteGlobalVarCssAliasesOptions as R, ScanGlobalVarCssOptions as S, ValidateGlobalVarAliasInputsOptions as V, GlobalVarAliasPlan as a, GlobalVarCssAliasRewriteResult as b, CreateGlobalVarAliasValidationOptionsInput as c, GlobalVarAliasValidationResult as d, CssVarDefinition as e, CssVarLocation as f, CssVarReference as g, GlobalVarAliasDiagnostic as h, GlobalVarAliasDiagnosticSeverity as i, GlobalVarAliasEntry as j, GlobalVarCodeSource as k, GlobalVarCssAssetSource as l, GlobalVarCssSource as m, GlobalVarScanCacheEntry as n };
@@ -285,6 +285,42 @@ declare function shouldWarnMissingTailwindEntry(ownedClassCount: number, sawTail
285
285
  * @returns the warning string.
286
286
  */
287
287
  declare function missingTailwindEntryMessage(ownedClassCount: number): string;
288
+ /**
289
+ * Hazards that make production mangling unsafe in a hybrid build (a separate
290
+ * Tailwind plugin owns the utility CSS and/or hand-written CSS uses literal class
291
+ * names). Computed from data `mangleCSSSync` already returns across every CSS
292
+ * asset, so it is free to surface.
293
+ */
294
+ interface MangleHybridHazards {
295
+ /**
296
+ * Mangled tokens that ALSO appear as a class name in non-csszyx CSS. The
297
+ * short token (e.g. `y` for `w-full`) then matches external `.y` elements and
298
+ * cross-contaminates their styles — the core hybrid-mangle failure.
299
+ */
300
+ collisions: string[];
301
+ /**
302
+ * Map sources csszyx mangled but whose class never appeared in any emitted
303
+ * CSS (e.g. a utility Tailwind never generated, or a malformed key). Their
304
+ * DOM class is rewritten to a token with no rule → the element loses styling.
305
+ */
306
+ orphans: string[];
307
+ }
308
+ /**
309
+ * Detect hybrid-mangle hazards from the accumulated per-asset mangle results.
310
+ *
311
+ * @param mangleMap - the full original→token map injected into the runtime.
312
+ * @param mangledSources - map keys that were actually found and renamed in some CSS asset.
313
+ * @param externalClasses - class names found in CSS that are NOT in the mangle map (non-csszyx).
314
+ * @returns the colliding tokens and orphan sources (each sorted, deduped).
315
+ */
316
+ declare function collectMangleHybridHazards(mangleMap: Record<string, string>, mangledSources: ReadonlySet<string>, externalClasses: ReadonlySet<string>): MangleHybridHazards;
317
+ /**
318
+ * Build the hybrid-mangle hazard warning, or null when there is nothing to warn.
319
+ *
320
+ * @param hazards - the detected collisions and orphans.
321
+ * @returns a warning string, or null when both lists are empty.
322
+ */
323
+ declare function mangleHybridHazardMessage(hazards: MangleHybridHazards): string | null;
288
324
  /**
289
325
  * Whether a CSS module scopes Tailwind's content detection — `source(none)` or
290
326
  * `source("…")` on the `@import "tailwindcss"`, or any `@source not` exclusion.
@@ -504,5 +540,5 @@ declare const rollupPlugin: (options?: PartialCsszyxConfig) => InputPluginOption
504
540
  */
505
541
  declare const esbuildPlugin: (options?: PartialCsszyxConfig) => Plugin;
506
542
 
507
- export { isMonorepoPackage as A, isPackagesSkippedSource as B, mangleCodeClassesSync as D, missingTailwindEntryMessage as E, normalizeGlobalVarAliasesForCache as F, resolveCompileSourceDirs as H, resolveNativeCacheIdentity as I, rollupPlugin as J, shouldEmitWarning as K, shouldWarnMissingTailwindEntry as L, shouldWarnUnscopedMonorepo as M, skippedSzFilesMessage as N, unscopedMonorepoMessage as O, vitePlugin as Q, webpackPlugin as T, appendTailwindSourceDirective as o, computeSafelistRelPath as p, createGlobalVarMapAssetSource as q, cssHasContentScope as r, cssImportsTailwind as s, esbuildPlugin as t, unplugin as u, extractGlobalVarAliasesForManifest as v, fileMayContainSafelistableSz as w, hasInjectableTailwindCandidate as x, isCompileSourceOptedIn as y, isHardIgnoredPath as z };
508
- export type { CssVarScanResult as C, GlobalVarScanCacheKeyInput as G, PlanGlobalVarAliasesInput as P, RewriteGlobalVarCssAliasesOptions as R, ScanGlobalVarCssOptions as S, ValidateGlobalVarAliasInputsOptions as V, GlobalVarAliasPlan as a, GlobalVarCssAliasRewriteResult as b, CreateGlobalVarAliasValidationOptionsInput as c, GlobalVarAliasValidationResult as d, CssVarDefinition as e, CssVarLocation as f, CssVarReference as g, GlobalVarAliasDiagnostic as h, GlobalVarAliasDiagnosticSeverity as i, GlobalVarAliasEntry as j, GlobalVarCodeSource as k, GlobalVarCssAssetSource as l, GlobalVarCssSource as m, GlobalVarScanCacheEntry as n };
543
+ export { isHardIgnoredPath as A, isMonorepoPackage as B, isPackagesSkippedSource as D, mangleCodeClassesSync as E, mangleHybridHazardMessage as F, missingTailwindEntryMessage as H, normalizeGlobalVarAliasesForCache as I, resolveCompileSourceDirs as J, resolveNativeCacheIdentity as K, rollupPlugin as L, shouldEmitWarning as N, shouldWarnMissingTailwindEntry as O, shouldWarnUnscopedMonorepo as Q, skippedSzFilesMessage as T, unscopedMonorepoMessage as U, vitePlugin as W, webpackPlugin as X, appendTailwindSourceDirective as o, collectMangleHybridHazards as p, computeSafelistRelPath as q, createGlobalVarMapAssetSource as r, cssHasContentScope as s, cssImportsTailwind as t, unplugin as u, esbuildPlugin as v, extractGlobalVarAliasesForManifest as w, fileMayContainSafelistableSz as x, hasInjectableTailwindCandidate as y, isCompileSourceOptedIn as z };
544
+ export type { CssVarScanResult as C, GlobalVarScanCacheKeyInput as G, MangleHybridHazards as M, PlanGlobalVarAliasesInput as P, RewriteGlobalVarCssAliasesOptions as R, ScanGlobalVarCssOptions as S, ValidateGlobalVarAliasInputsOptions as V, GlobalVarAliasPlan as a, GlobalVarCssAliasRewriteResult as b, CreateGlobalVarAliasValidationOptionsInput as c, GlobalVarAliasValidationResult as d, CssVarDefinition as e, CssVarLocation as f, CssVarReference as g, GlobalVarAliasDiagnostic as h, GlobalVarAliasDiagnosticSeverity as i, GlobalVarAliasEntry as j, GlobalVarCodeSource as k, GlobalVarCssAssetSource as l, GlobalVarCssSource as m, GlobalVarScanCacheEntry as n };
@@ -3,7 +3,7 @@ import * as fs from 'node:fs';
3
3
  import { createHash } from 'node:crypto';
4
4
  import { hostname } from 'node:os';
5
5
  import lockfile from 'proper-lockfile';
6
- import { e as escapeHtmlAttribute } from './unplugin.3UumZ5gn.mjs';
6
+ import { s as sortStrings, e as escapeHtmlAttribute } from './unplugin.B1mblcm-.mjs';
7
7
 
8
8
  const DEFAULT_RENAME_RETRIES = 5;
9
9
  const DEFAULT_RENAME_RETRY_DELAY_MS = 10;
@@ -42,8 +42,8 @@ function materializeNextSafelist(paths, options = {}) {
42
42
  recordsBySource.set(record.data.sourcePath, record);
43
43
  }
44
44
  }
45
- const sortedSources = [...recordsBySource.values()].map(({ data }) => [data.sourcePath, [...new Set(data.classes)].sort()]).sort(([left], [right]) => left.localeCompare(right));
46
- const classNames = [...new Set(sortedSources.flatMap(([, classSet]) => classSet))].sort();
45
+ const sortedSources = [...recordsBySource.values()].map(({ data }) => [data.sourcePath, sortStrings(new Set(data.classes))]).sort(([left], [right]) => left.localeCompare(right));
46
+ const classNames = sortStrings(new Set(sortedSources.flatMap(([, classSet]) => classSet)));
47
47
  const snapshot = {
48
48
  version: 1,
49
49
  sources: sortedSources.map(([sourcePath, classSet]) => [sourcePath, classSet])
@@ -172,9 +172,9 @@ function isExistingShardEquivalent(filePath, shard) {
172
172
  }
173
173
  function normalizeShardInput(input) {
174
174
  const sourcePath = path.resolve(input.sourcePath);
175
- const classes = [
176
- ...new Set(input.classes.map((className) => className.trim()).filter(Boolean))
177
- ].sort();
175
+ const classes = sortStrings(
176
+ new Set(input.classes.map((className) => className.trim()).filter(Boolean))
177
+ );
178
178
  const cacheKey = input.cacheKey ?? createHash("sha256").update(sourcePath).update("\0").update(input.sourceHash).digest("hex");
179
179
  return {
180
180
  version: 1,
@@ -449,7 +449,7 @@ function stableStringify(value) {
449
449
  }
450
450
  function pickEnv(env, envKeys) {
451
451
  const selected = {};
452
- for (const key of [...new Set(envKeys)].sort()) {
452
+ for (const key of sortStrings(new Set(envKeys))) {
453
453
  const value = env[key];
454
454
  if (value !== void 0) {
455
455
  selected[key] = value;