@csszyx/unplugin 0.15.2 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/css-mangler.cjs +61 -63
- package/dist/css-mangler.d.cts +31 -2
- package/dist/css-mangler.d.mts +31 -2
- package/dist/css-mangler.mjs +61 -64
- package/dist/index.cjs +3 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +4 -4
- package/dist/next-prebuild.mjs +2 -2
- package/dist/next-turbo-loader.mjs +3 -3
- package/dist/shared/{unplugin.BT7PqYuK.d.cts → unplugin.Bu2rzRtv.d.mts} +41 -4
- package/dist/shared/{unplugin.Bk9o8_RZ.mjs → unplugin.C-oQU1jl.mjs} +1 -1
- package/dist/shared/{unplugin.DK0b4fr7.mjs → unplugin.Ceq-N4jI.mjs} +1 -1
- package/dist/shared/{unplugin.dz3AdzsO.cjs → unplugin.D3yBoTHP.cjs} +310 -66
- package/dist/shared/{unplugin.BxsTa17g.mjs → unplugin.Dx0ngYWw.mjs} +312 -69
- package/dist/shared/{unplugin.BT7PqYuK.d.mts → unplugin.PKo7wFzu.d.cts} +41 -4
- package/dist/shared/{unplugin.DAzgbtuZ.mjs → unplugin.Vn9x8SBP.mjs} +1 -1
- package/dist/vite.cjs +1 -1
- package/dist/vite.d.cts +4 -2
- package/dist/vite.d.mts +3 -1
- package/dist/vite.mjs +3 -3
- package/dist/webpack.cjs +1 -1
- package/dist/webpack.d.cts +4 -2
- package/dist/webpack.d.mts +3 -1
- package/dist/webpack.mjs +3 -3
- package/package.json +15 -9
|
@@ -6,7 +6,7 @@ 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,
|
|
9
|
+
import { scanGlobalVarUsages, sortStrings as sortStrings$1, szFallbackConsequenceOf, isWasmTransformAvailable, isRustTransformAvailable, ensureRustTransformAvailable, ASTBudgetExceededError, transformRustBatch, transformRust, transformWasm, 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';
|
|
@@ -14,9 +14,9 @@ import { isTailwindReservedCustomProperty, CSSZYX_GLOBAL_ALIAS_PREFIX, isCsszyxG
|
|
|
14
14
|
import { preprocess } from '@csszyx/vue-adapter';
|
|
15
15
|
import { createUnplugin } from 'unplugin';
|
|
16
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
|
|
18
|
-
import { mangleCSSSync } from '../css-mangler.mjs';
|
|
19
|
-
import { c as createMangleRuntimeModule, M as MANGLE_RUNTIME_VIRTUAL_ID,
|
|
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 resolveProviderPath, i as importedSpecifiersIn, s as specifierBases, a as resolveProviderPathWith, o as resolveCrossModuleStaticsFor, e as createTransformCacheKey, w as writeTransformCache, g as readTransformCache, p as evictMemoryCacheToBudget, d as isReadableProviderFile } from './unplugin.C-oQU1jl.mjs';
|
|
18
|
+
import { mangleCSSSync, classAttributeSelectorKey } from '../css-mangler.mjs';
|
|
19
|
+
import { c as createMangleRuntimeModule, M as MANGLE_RUNTIME_VIRTUAL_ID, 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 RESOLVED_THEME_GROUPS_VIRTUAL_ID, l as createThemeGroupsModule, 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.Ceq-N4jI.mjs';
|
|
20
20
|
import { gzipSync } from 'node:zlib';
|
|
21
21
|
import postcss from 'postcss';
|
|
22
22
|
import valueParser from 'postcss-value-parser';
|
|
@@ -1710,22 +1710,22 @@ function expandFilePatterns(rootDir, patterns) {
|
|
|
1710
1710
|
return sortStrings(files);
|
|
1711
1711
|
}
|
|
1712
1712
|
|
|
1713
|
-
const BACKSLASH = String.fromCodePoint(92);
|
|
1713
|
+
const BACKSLASH$1 = String.fromCodePoint(92);
|
|
1714
1714
|
function unicodeEscape(hexadecimal) {
|
|
1715
|
-
return `${BACKSLASH}u${hexadecimal}`;
|
|
1715
|
+
return `${BACKSLASH$1}u${hexadecimal}`;
|
|
1716
1716
|
}
|
|
1717
1717
|
function replaceEveryLiteral(value, search, replacement) {
|
|
1718
1718
|
return value.replaceAll(search, () => replacement);
|
|
1719
1719
|
}
|
|
1720
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`);
|
|
1721
|
+
let escaped = replaceEveryLiteral(value, BACKSLASH$1, BACKSLASH$1.repeat(2));
|
|
1722
|
+
escaped = replaceEveryLiteral(escaped, "'", `${BACKSLASH$1}'`);
|
|
1723
|
+
escaped = replaceEveryLiteral(escaped, "\r", `${BACKSLASH$1}r`);
|
|
1724
|
+
return replaceEveryLiteral(escaped, "\n", `${BACKSLASH$1}n`);
|
|
1725
1725
|
}
|
|
1726
1726
|
function escapeDoubleQuotedString(value) {
|
|
1727
|
-
const escaped = replaceEveryLiteral(value, BACKSLASH, BACKSLASH.repeat(2));
|
|
1728
|
-
return replaceEveryLiteral(escaped, '"', `${BACKSLASH}"`);
|
|
1727
|
+
const escaped = replaceEveryLiteral(value, BACKSLASH$1, BACKSLASH$1.repeat(2));
|
|
1728
|
+
return replaceEveryLiteral(escaped, '"', `${BACKSLASH$1}"`);
|
|
1729
1729
|
}
|
|
1730
1730
|
|
|
1731
1731
|
const LINE_SEPARATOR$1 = String.fromCodePoint(8232);
|
|
@@ -1914,6 +1914,81 @@ function removedMangleMapDeliveryMessage() {
|
|
|
1914
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
1915
|
}
|
|
1916
1916
|
|
|
1917
|
+
function utilityStart(className) {
|
|
1918
|
+
let depth = 0;
|
|
1919
|
+
let start = 0;
|
|
1920
|
+
for (let index = 0; index < className.length; index += 1) {
|
|
1921
|
+
const char = className[index];
|
|
1922
|
+
if (char === "[") depth += 1;
|
|
1923
|
+
else if (char === "]") depth = Math.max(0, depth - 1);
|
|
1924
|
+
else if (char === ":" && depth === 0) start = index + 1;
|
|
1925
|
+
}
|
|
1926
|
+
return start;
|
|
1927
|
+
}
|
|
1928
|
+
function compileManglePreserve(entries) {
|
|
1929
|
+
const list = entries ?? [];
|
|
1930
|
+
list.forEach((entry, index) => {
|
|
1931
|
+
if (typeof entry !== "string" || entry.length === 0) {
|
|
1932
|
+
throw new TypeError(
|
|
1933
|
+
`[csszyx] production.manglePreserve[${index}] must be a non-empty string (an exact class name, or a prefix ending in \`*\`); got ${describe(entry)}.`
|
|
1934
|
+
);
|
|
1935
|
+
}
|
|
1936
|
+
if (entry === "*") {
|
|
1937
|
+
throw new TypeError(
|
|
1938
|
+
"[csszyx] production.manglePreserve must not contain a lone `*`: it would keep every class and silently turn `production.mangle` into a no-op. Name a prefix (`bg-tag-*`) or set `production.mangle: false`."
|
|
1939
|
+
);
|
|
1940
|
+
}
|
|
1941
|
+
});
|
|
1942
|
+
const compiled = list.map((value) => ({
|
|
1943
|
+
value,
|
|
1944
|
+
prefix: value.endsWith("*") ? value.slice(0, -1) : void 0
|
|
1945
|
+
}));
|
|
1946
|
+
const keeps = (entry, className, utilityStartIndex) => entry.prefix === void 0 ? className === entry.value || className.length - utilityStartIndex === entry.value.length && className.startsWith(entry.value, utilityStartIndex) : className.startsWith(entry.prefix) || className.startsWith(entry.prefix, utilityStartIndex);
|
|
1947
|
+
const test = (className) => {
|
|
1948
|
+
if (list.length === 0) return false;
|
|
1949
|
+
const start = utilityStart(className);
|
|
1950
|
+
return compiled.some((entry) => keeps(entry, className, start));
|
|
1951
|
+
};
|
|
1952
|
+
return {
|
|
1953
|
+
entries: list,
|
|
1954
|
+
test,
|
|
1955
|
+
unmatched(census) {
|
|
1956
|
+
if (list.length === 0) return [];
|
|
1957
|
+
const matched = list.map(() => false);
|
|
1958
|
+
let remaining = list.length;
|
|
1959
|
+
for (const className of census) {
|
|
1960
|
+
const start = utilityStart(className);
|
|
1961
|
+
for (let index = 0; index < list.length; index += 1) {
|
|
1962
|
+
if (matched[index] || !keeps(compiled[index], className, start)) continue;
|
|
1963
|
+
matched[index] = true;
|
|
1964
|
+
remaining -= 1;
|
|
1965
|
+
}
|
|
1966
|
+
if (remaining === 0) break;
|
|
1967
|
+
}
|
|
1968
|
+
return list.filter((_, index) => !matched[index]);
|
|
1969
|
+
}
|
|
1970
|
+
};
|
|
1971
|
+
}
|
|
1972
|
+
function describe(value) {
|
|
1973
|
+
if (typeof value === "string") return "an empty string";
|
|
1974
|
+
if (value instanceof RegExp) return `a RegExp (${String(value)})`;
|
|
1975
|
+
return `${typeof value} ${JSON.stringify(value) ?? String(value)}`;
|
|
1976
|
+
}
|
|
1977
|
+
function manglePreserveNoMatchMessage(entries) {
|
|
1978
|
+
const sample = entries.slice(0, 8).join(", ");
|
|
1979
|
+
const noun = entries.length === 1 ? "entry" : "entries";
|
|
1980
|
+
return `[csszyx] production.manglePreserve: ${entries.length} ${noun} matched no csszyx class in this build (${sample}) \u2014 nothing was preserved for them. Check the spelling against the class census; an entry keeps a class only when its name is exact, or when it ends in \`*\` and the class starts with the rest.`;
|
|
1981
|
+
}
|
|
1982
|
+
const TOKEN_CHARACTERS = /^[0-9a-z]+$/i;
|
|
1983
|
+
function mangleExcludeNeverTokenEntries(entries) {
|
|
1984
|
+
return [...entries].filter((entry) => !TOKEN_CHARACTERS.test(entry));
|
|
1985
|
+
}
|
|
1986
|
+
function mangleExcludeNeverTokenMessage(entries) {
|
|
1987
|
+
const sample = entries.slice(0, 8).join(", ");
|
|
1988
|
+
const noun = entries.length === 1 ? "name" : "names";
|
|
1989
|
+
return `[csszyx] production.mangleExclude: ${entries.length} ${noun} can never be a mangle token (${sample}) \u2014 tokens are short base62 strings, so those entries do nothing. To keep a class from being renamed, list it in \`production.manglePreserve\` instead.`;
|
|
1990
|
+
}
|
|
1991
|
+
|
|
1917
1992
|
const MANGLE_RUNTIME_FILE = "mangle-runtime.mjs";
|
|
1918
1993
|
function ensureMangleRuntimeFile(outputDir, globalVarAliasPrefix, exposeDebugGlobal) {
|
|
1919
1994
|
const target = path__default.join(outputDir, MANGLE_RUNTIME_FILE);
|
|
@@ -2207,39 +2282,136 @@ function shouldWarnMissingTailwindEntry(ownedClassCount, sawTailwindEntry, sawAn
|
|
|
2207
2282
|
function missingTailwindEntryMessage(ownedClassCount) {
|
|
2208
2283
|
return `[csszyx] generated ${ownedClassCount} sz class(es) but found no CSS entry importing "tailwindcss" \u2014 those classes will produce no CSS. Import "tailwindcss" in a CSS file (csszyx auto-injects @source for the generated classes) so Tailwind emits their styles.`;
|
|
2209
2284
|
}
|
|
2210
|
-
function
|
|
2285
|
+
function asciiLower(text) {
|
|
2286
|
+
return text.replace(/[A-Z]/g, (letter) => letter.toLowerCase());
|
|
2287
|
+
}
|
|
2288
|
+
function attributeSelectorPredicates(operator, value) {
|
|
2289
|
+
const eq = (v) => (name) => name === v;
|
|
2290
|
+
const startsWith = (v) => (name) => name.startsWith(v);
|
|
2291
|
+
const endsWith = (v) => (name) => name.endsWith(v);
|
|
2292
|
+
const includes = (v) => (name) => name.includes(v);
|
|
2293
|
+
const dashPrefix = (v) => (name) => name === v || name.startsWith(`${v}-`);
|
|
2294
|
+
const segments = value.split(/[\t\n\f\r ]+/);
|
|
2295
|
+
if (segments.length === 1) {
|
|
2296
|
+
switch (operator) {
|
|
2297
|
+
case "=":
|
|
2298
|
+
case "~=":
|
|
2299
|
+
return [eq(value)];
|
|
2300
|
+
case "|=":
|
|
2301
|
+
return [dashPrefix(value)];
|
|
2302
|
+
case "^=":
|
|
2303
|
+
return [startsWith(value)];
|
|
2304
|
+
case "$=":
|
|
2305
|
+
return [endsWith(value)];
|
|
2306
|
+
case "*=":
|
|
2307
|
+
return [includes(value)];
|
|
2308
|
+
default:
|
|
2309
|
+
return [];
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
if (operator === "~=") return [];
|
|
2313
|
+
const first = segments[0];
|
|
2314
|
+
const last = segments[segments.length - 1];
|
|
2315
|
+
const predicates = [];
|
|
2316
|
+
if (first.length > 0) {
|
|
2317
|
+
predicates.push(operator === "$=" || operator === "*=" ? endsWith(first) : eq(first));
|
|
2318
|
+
}
|
|
2319
|
+
for (const middle of segments.slice(1, -1)) predicates.push(eq(middle));
|
|
2320
|
+
if (last.length > 0) {
|
|
2321
|
+
if (operator === "^=" || operator === "*=") predicates.push(startsWith(last));
|
|
2322
|
+
else if (operator === "|=") predicates.push(dashPrefix(last));
|
|
2323
|
+
else predicates.push(eq(last));
|
|
2324
|
+
}
|
|
2325
|
+
return predicates;
|
|
2326
|
+
}
|
|
2327
|
+
function renderClassAttributeSelector(selector) {
|
|
2328
|
+
const flag = selector.insensitive ? " i" : "";
|
|
2329
|
+
return `[class${selector.operator}"${selector.value}"${flag}]`;
|
|
2330
|
+
}
|
|
2331
|
+
function selectorHazardFor(mangleMap, selector) {
|
|
2332
|
+
const value = selector.insensitive ? asciiLower(selector.value) : selector.value;
|
|
2333
|
+
const predicates = attributeSelectorPredicates(selector.operator, value);
|
|
2334
|
+
if (predicates.length === 0) return null;
|
|
2335
|
+
const fold = selector.insensitive ? asciiLower : (name) => name;
|
|
2336
|
+
const matches = (name) => {
|
|
2337
|
+
const folded = fold(name);
|
|
2338
|
+
return predicates.some((predicate) => predicate(folded));
|
|
2339
|
+
};
|
|
2340
|
+
const renamed = sortStrings$1(Object.keys(mangleMap).filter(matches));
|
|
2341
|
+
const matchedTokens = sortStrings$1(Object.values(mangleMap).filter(matches));
|
|
2342
|
+
if (renamed.length === 0 && matchedTokens.length === 0) return null;
|
|
2343
|
+
return {
|
|
2344
|
+
selector: renderClassAttributeSelector(selector),
|
|
2345
|
+
value: selector.value,
|
|
2346
|
+
renamed,
|
|
2347
|
+
matchedTokens
|
|
2348
|
+
};
|
|
2349
|
+
}
|
|
2350
|
+
function collectMangleHybridHazards(mangleMap, mangledSources, externalClasses, attributeSelectors = []) {
|
|
2211
2351
|
const tokenValues = new Set(Object.values(mangleMap));
|
|
2212
2352
|
const collisions = sortStrings$1([...tokenValues].filter((token) => externalClasses.has(token)));
|
|
2213
2353
|
const orphans = sortStrings$1(
|
|
2214
2354
|
Object.keys(mangleMap).filter((source) => !mangledSources.has(source))
|
|
2215
2355
|
);
|
|
2216
|
-
|
|
2356
|
+
const hazards = /* @__PURE__ */ new Map();
|
|
2357
|
+
for (const selector of attributeSelectors) {
|
|
2358
|
+
const hazard = selectorHazardFor(mangleMap, selector);
|
|
2359
|
+
if (hazard !== null) hazards.set(hazard.selector, hazard);
|
|
2360
|
+
}
|
|
2361
|
+
const selectorMatches = sortStrings$1([...hazards.keys()]).map(
|
|
2362
|
+
(key) => hazards.get(key)
|
|
2363
|
+
);
|
|
2364
|
+
return { collisions, orphans, selectorMatches };
|
|
2365
|
+
}
|
|
2366
|
+
const BACKSLASH = String.fromCodePoint(92);
|
|
2367
|
+
const SINGLE_QUOTE = String.fromCodePoint(39);
|
|
2368
|
+
function quoteForConfig(entry) {
|
|
2369
|
+
const escaped = entry.replaceAll(BACKSLASH, BACKSLASH + BACKSLASH).replaceAll(SINGLE_QUOTE, BACKSLASH + SINGLE_QUOTE);
|
|
2370
|
+
return SINGLE_QUOTE + escaped + SINGLE_QUOTE;
|
|
2371
|
+
}
|
|
2372
|
+
function preserveEntriesFor(hazard) {
|
|
2373
|
+
const quote = quoteForConfig;
|
|
2374
|
+
const { value } = hazard;
|
|
2375
|
+
if (hazard.renamed.every((name) => name === value)) return [quote(value)];
|
|
2376
|
+
if (hazard.renamed.every((name) => name.startsWith(value))) return [quote(`${value}*`)];
|
|
2377
|
+
return hazard.renamed.map(quote);
|
|
2217
2378
|
}
|
|
2218
2379
|
function mangleHybridHazardMessage(hazards) {
|
|
2219
|
-
const { collisions, orphans } = hazards;
|
|
2220
|
-
if (collisions.length === 0 && orphans.length === 0) {
|
|
2380
|
+
const { collisions, orphans, selectorMatches = [] } = hazards;
|
|
2381
|
+
if (collisions.length === 0 && orphans.length === 0 && selectorMatches.length === 0) {
|
|
2221
2382
|
return null;
|
|
2222
2383
|
}
|
|
2384
|
+
const broken = selectorMatches.filter((hazard) => hazard.renamed.length > 0);
|
|
2385
|
+
const newlyMatched = selectorMatches.filter((hazard) => hazard.matchedTokens.length > 0);
|
|
2223
2386
|
const parts = ["[csszyx] production mangle found hybrid hazards:"];
|
|
2224
2387
|
if (collisions.length > 0) {
|
|
2225
2388
|
const sample = collisions.slice(0, 8).join(", ");
|
|
2226
2389
|
parts.push(
|
|
2227
|
-
` ${collisions.length} mangled token(s) collide with class names in non-csszyx CSS (e.g. ${sample}) \u2014 those tokens will cross-contaminate external ".${collisions[0]}" elements
|
|
2390
|
+
` ${collisions.length} mangled token(s) collide with class names in non-csszyx CSS (e.g. ${sample}) \u2014 those tokens will cross-contaminate external ".${collisions[0]}" elements.`,
|
|
2391
|
+
" HOTFIX: pass `production: { mangle: false }` to the csszyx plugin to ship now. THEN fix it: if these short names are in your OWN CSS, rename them to something specific (e.g. `.x` \u2192 `.resize-handle-x`) \u2014 short/common names also clash on specificity with other libraries. Only for names in a third-party stylesheet you cannot edit, list them in `production.mangleExclude` instead. Run `npx @csszyx/cli scan-collisions` to find every offending name."
|
|
2228
2392
|
);
|
|
2229
2393
|
}
|
|
2230
2394
|
if (orphans.length > 0) {
|
|
2231
2395
|
const sample = orphans.slice(0, 8).join(", ");
|
|
2232
2396
|
parts.push(
|
|
2233
|
-
` ${orphans.length} mangled class(es) have no emitted CSS rule (e.g. ${sample}) \u2014 those elements lose styling
|
|
2397
|
+
` ${orphans.length} mangled class(es) have no emitted CSS rule (e.g. ${sample}) \u2014 those elements lose styling.`,
|
|
2398
|
+
" Those classes are csszyx-owned but no CSS was emitted for them (e.g. a separate Tailwind plugin owns the utility CSS, or the class is not a real utility). Ensure that CSS is generated, or pass `production: { mangle: false }` to the csszyx plugin until the pipelines are reconciled."
|
|
2234
2399
|
);
|
|
2235
2400
|
}
|
|
2236
|
-
if (
|
|
2401
|
+
if (broken.length > 0) {
|
|
2402
|
+
const sample = broken.slice(0, 3).map((hazard) => `${hazard.selector} \u2192 ${hazard.renamed.slice(0, 4).join(", ")}`).join("; ");
|
|
2403
|
+
const entries = [...new Set(broken.flatMap(preserveEntriesFor))].join(", ");
|
|
2237
2404
|
parts.push(
|
|
2238
|
-
|
|
2405
|
+
` ${broken.length} attribute selector(s) match class names by text (e.g. ${sample}) \u2014 those rules stop matching once the classes are renamed, so the elements lose those styles.`,
|
|
2406
|
+
` Keep those classes readable with production.manglePreserve: [${entries}] (paste-ready), or key the rule off a data attribute, which mangling never touches. production.mangleExclude cannot help here: it reserves token names and does not keep a class from being renamed.`
|
|
2239
2407
|
);
|
|
2240
|
-
}
|
|
2408
|
+
}
|
|
2409
|
+
if (newlyMatched.length > 0) {
|
|
2410
|
+
const sample = newlyMatched.slice(0, 3).map((hazard) => `${hazard.selector} \u2192 ${hazard.matchedTokens.slice(0, 4).join(", ")}`).join("; ");
|
|
2411
|
+
const tokens = [...new Set(newlyMatched.flatMap((hazard) => hazard.matchedTokens))].map(quoteForConfig).join(", ");
|
|
2241
2412
|
parts.push(
|
|
2242
|
-
|
|
2413
|
+
` ${newlyMatched.length} attribute selector(s) would start matching mangled tokens instead (e.g. ${sample}).`,
|
|
2414
|
+
` Reserve those token names with production.mangleExclude: [${tokens}] (paste-ready) so no class is renamed to one of them, or key the rule off a data attribute, which mangling never touches; a prefix or substring selector goes on matching other tokens, so the data attribute is the durable fix.`
|
|
2243
2415
|
);
|
|
2244
2416
|
}
|
|
2245
2417
|
return parts.join("");
|
|
@@ -2311,6 +2483,9 @@ function shouldEmitWarning(quiet, devOnly, isProduction) {
|
|
|
2311
2483
|
function shouldEmitMissingCssFallback(quiet, message) {
|
|
2312
2484
|
return resolveQuietMode(quiet) !== "all" && szFallbackConsequenceOf(message) === "missing-css";
|
|
2313
2485
|
}
|
|
2486
|
+
function shouldHoldAdvisories(quiet, serving, nodeEnv) {
|
|
2487
|
+
return quiet !== "off" || !serving && nodeEnv === "production";
|
|
2488
|
+
}
|
|
2314
2489
|
function emitMissingCssFallback(quiet, message, id, emit) {
|
|
2315
2490
|
if (shouldEmitMissingCssFallback(quiet, message)) emit(`[csszyx] ${id}
|
|
2316
2491
|
${message}`);
|
|
@@ -3140,12 +3315,15 @@ ${errors.join("\n")}`
|
|
|
3140
3315
|
function createCsszyxPlugins(options = {}) {
|
|
3141
3316
|
assertGlobalVarMangleConfig(options);
|
|
3142
3317
|
let manglingEnabled = options.production?.mangle === true;
|
|
3318
|
+
let serving = false;
|
|
3143
3319
|
const importedStaticSzEnabled = options.build?.importedStaticSz ?? DEFAULT_IMPORTED_STATIC_SZ;
|
|
3144
3320
|
const szvCrossModuleRegistry = /* @__PURE__ */ new Map();
|
|
3145
3321
|
const szvCrossModuleForwards = /* @__PURE__ */ new Map();
|
|
3146
3322
|
const szObjectProvidersExamined = /* @__PURE__ */ new Set();
|
|
3147
3323
|
let specifierAliases = [];
|
|
3148
3324
|
const mangleReserved = new Set(options.production?.mangleExclude ?? []);
|
|
3325
|
+
const manglePreserve = compileManglePreserve(options.production?.manglePreserve);
|
|
3326
|
+
let manglePreserveNoMatchWarned = false;
|
|
3149
3327
|
let mangleMapFrozen = false;
|
|
3150
3328
|
let prescanSawServerModule = false;
|
|
3151
3329
|
let skipRscRecords = false;
|
|
@@ -3156,6 +3334,7 @@ function createCsszyxPlugins(options = {}) {
|
|
|
3156
3334
|
let projectCssFiles = [];
|
|
3157
3335
|
const transformMangledSources = /* @__PURE__ */ new Set();
|
|
3158
3336
|
const transformExternalClasses = /* @__PURE__ */ new Set();
|
|
3337
|
+
const transformAttributeSelectors = /* @__PURE__ */ new Map();
|
|
3159
3338
|
if (options.production?.mangleMapDelivery !== void 0) {
|
|
3160
3339
|
console.warn(removedMangleMapDeliveryMessage());
|
|
3161
3340
|
}
|
|
@@ -3185,6 +3364,10 @@ function createCsszyxPlugins(options = {}) {
|
|
|
3185
3364
|
if (unknownConfigKeys.length > 0) {
|
|
3186
3365
|
emitWarning(unknownConfigKeysMessage(unknownConfigKeys));
|
|
3187
3366
|
}
|
|
3367
|
+
const excludeNeverTokens = mangleExcludeNeverTokenEntries(mangleReserved);
|
|
3368
|
+
if (excludeNeverTokens.length > 0) {
|
|
3369
|
+
emitWarning(mangleExcludeNeverTokenMessage(excludeNeverTokens));
|
|
3370
|
+
}
|
|
3188
3371
|
function emitWarning(message, opts = {}) {
|
|
3189
3372
|
if (shouldEmitWarning(quiet, opts.devOnly ?? false, process.env.NODE_ENV === "production")) {
|
|
3190
3373
|
console.warn(message);
|
|
@@ -4045,10 +4228,15 @@ function createCsszyxPlugins(options = {}) {
|
|
|
4045
4228
|
...state.authoredClasses,
|
|
4046
4229
|
...state.ownedClasses
|
|
4047
4230
|
]);
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
forbiddenTokens
|
|
4231
|
+
const eligible = mangleEligibleClasses(state.ownedClasses, state.authoredClasses).filter(
|
|
4232
|
+
(className) => !manglePreserve.test(className)
|
|
4051
4233
|
);
|
|
4234
|
+
if (!manglePreserveNoMatchWarned && manglingEnabled && state.ownedClasses.size > 0) {
|
|
4235
|
+
manglePreserveNoMatchWarned = true;
|
|
4236
|
+
const unmatched = manglePreserve.unmatched(state.ownedClasses);
|
|
4237
|
+
if (unmatched.length > 0) emitWarning(manglePreserveNoMatchMessage(unmatched));
|
|
4238
|
+
}
|
|
4239
|
+
return allocateMangleTokens(eligible, forbiddenTokens);
|
|
4052
4240
|
}
|
|
4053
4241
|
function freezeMangleMap() {
|
|
4054
4242
|
state.mangleMap = computeMangleMap();
|
|
@@ -4201,6 +4389,38 @@ function createCsszyxPlugins(options = {}) {
|
|
|
4201
4389
|
}
|
|
4202
4390
|
return modules;
|
|
4203
4391
|
}
|
|
4392
|
+
function handleHotFile(pass, ctx) {
|
|
4393
|
+
const { isClientPass } = pass;
|
|
4394
|
+
if (isClientPass) {
|
|
4395
|
+
prescanResultHandoff.clear();
|
|
4396
|
+
}
|
|
4397
|
+
const scanCss = options.build?.scanCss;
|
|
4398
|
+
const reloadThemeGroupsModule = () => {
|
|
4399
|
+
const themeGroupsModule = ctx.server.moduleGraph.getModuleById(
|
|
4400
|
+
RESOLVED_THEME_GROUPS_VIRTUAL_ID
|
|
4401
|
+
);
|
|
4402
|
+
if (themeGroupsModule) {
|
|
4403
|
+
ctx.server.moduleGraph.invalidateModule(themeGroupsModule);
|
|
4404
|
+
}
|
|
4405
|
+
};
|
|
4406
|
+
if (isClientPass && ctx.file.endsWith(".css")) {
|
|
4407
|
+
const root = state.rootDir;
|
|
4408
|
+
const before = createThemeGroupsModule(themeGroupTokens());
|
|
4409
|
+
if (scanCss && matchesAnyPattern(ctx.file, scanCss, root)) {
|
|
4410
|
+
state.scanCssTheme = runThemeScan(root, scanCss) ?? state.scanCssTheme;
|
|
4411
|
+
}
|
|
4412
|
+
runAutoThemeScan(root);
|
|
4413
|
+
reloadThemeGroupsModule();
|
|
4414
|
+
if (createThemeGroupsModule(themeGroupTokens()) !== before) {
|
|
4415
|
+
ctx.server.ws.send({ type: "full-reload" });
|
|
4416
|
+
}
|
|
4417
|
+
}
|
|
4418
|
+
if (normalizePathSeparators(ctx.file) === normalizePathSeparators(path.join(state.rootDir, SAFELIST_FILENAME))) {
|
|
4419
|
+
return tailwindEntryModules(pass.moduleGraph());
|
|
4420
|
+
}
|
|
4421
|
+
if (isClientPass) discoverHotFileClasses(ctx.file, ctx.server.watcher);
|
|
4422
|
+
return void 0;
|
|
4423
|
+
}
|
|
4204
4424
|
function transformTailwindCssEntry(code, id) {
|
|
4205
4425
|
state.sawAnyCss = true;
|
|
4206
4426
|
const [cssFile] = id.split("?");
|
|
@@ -4236,7 +4456,7 @@ function createCsszyxPlugins(options = {}) {
|
|
|
4236
4456
|
}
|
|
4237
4457
|
const advisories = result.diagnostics.filter(isAdvisoryDiagnostic);
|
|
4238
4458
|
if (advisories.length === 0) return;
|
|
4239
|
-
if (quiet
|
|
4459
|
+
if (shouldHoldAdvisories(quiet, serving, process.env.NODE_ENV)) {
|
|
4240
4460
|
state.suppressedAdvisories += advisories.length;
|
|
4241
4461
|
return;
|
|
4242
4462
|
}
|
|
@@ -4655,6 +4875,7 @@ ${transformedCode}`;
|
|
|
4655
4875
|
specifierAliases = collectSpecifierAliases(root, config.resolve?.alias);
|
|
4656
4876
|
if (config.command === "serve") {
|
|
4657
4877
|
manglingEnabled = false;
|
|
4878
|
+
serving = true;
|
|
4658
4879
|
}
|
|
4659
4880
|
if (manglingEnabled && config.build?.watch) {
|
|
4660
4881
|
manglingEnabled = false;
|
|
@@ -4702,38 +4923,39 @@ ${transformedCode}`;
|
|
|
4702
4923
|
* which leaves Vite's own handling in place.
|
|
4703
4924
|
*/
|
|
4704
4925
|
hotUpdate(ctx) {
|
|
4705
|
-
|
|
4706
|
-
|
|
4707
|
-
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
|
|
4718
|
-
|
|
4719
|
-
|
|
4720
|
-
|
|
4721
|
-
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
|
|
4726
|
-
|
|
4727
|
-
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
|
|
4926
|
+
return handleHotFile(
|
|
4927
|
+
{
|
|
4928
|
+
isClientPass: (this.environment?.name ?? "client") === "client",
|
|
4929
|
+
// `server.moduleGraph` holds the backward-compatible
|
|
4930
|
+
// nodes Vite mapped back for the legacy hook only,
|
|
4931
|
+
// so they are the wrong objects to hand this one —
|
|
4932
|
+
// TypeScript says so too.
|
|
4933
|
+
moduleGraph: () => this.environment?.moduleGraph ?? ctx.server.environments.client.moduleGraph
|
|
4934
|
+
},
|
|
4935
|
+
ctx
|
|
4936
|
+
);
|
|
4937
|
+
},
|
|
4938
|
+
/**
|
|
4939
|
+
* The hook Vite 5 calls. Vite 6 and later never run it while
|
|
4940
|
+
* `hotUpdate` is declared, so declaring both costs nothing
|
|
4941
|
+
* there and keeps a Vite 5 dev server compiling `sz` live.
|
|
4942
|
+
*
|
|
4943
|
+
* Vite 5 routes only a file CHANGE here, never a create, so a
|
|
4944
|
+
* project with no `sz` at prescan still sees its first `sz`
|
|
4945
|
+
* edit answered by `@tailwindcss/vite`'s full reload on that
|
|
4946
|
+
* generation — the behaviour it always had there. The hook
|
|
4947
|
+
* runs once, with no environment, so it is the client pass
|
|
4948
|
+
* and answers from the server-wide graph.
|
|
4949
|
+
*
|
|
4950
|
+
* @param ctx - HMR context: the changed file and the dev server.
|
|
4951
|
+
* @returns The modules a safelist write affects; undefined
|
|
4952
|
+
* otherwise.
|
|
4953
|
+
*/
|
|
4954
|
+
handleHotUpdate(ctx) {
|
|
4955
|
+
return handleHotFile(
|
|
4956
|
+
{ isClientPass: true, moduleGraph: () => ctx.server.moduleGraph },
|
|
4957
|
+
ctx
|
|
4958
|
+
);
|
|
4737
4959
|
},
|
|
4738
4960
|
transformIndexHtml: {
|
|
4739
4961
|
order: "pre",
|
|
@@ -4822,7 +5044,7 @@ ${transformedCode}`;
|
|
|
4822
5044
|
recordCodePair(sizeAccount, before, after);
|
|
4823
5045
|
return after;
|
|
4824
5046
|
}
|
|
4825
|
-
function rewriteOutputCss(source, file, shouldMangle, mangledSources, externalClasses) {
|
|
5047
|
+
function rewriteOutputCss(source, file, shouldMangle, mangledSources, externalClasses, attributeSelectors) {
|
|
4826
5048
|
const css = rewriteCssWithValidatedGlobalVarPlan(
|
|
4827
5049
|
source,
|
|
4828
5050
|
file,
|
|
@@ -4836,6 +5058,9 @@ ${transformedCode}`;
|
|
|
4836
5058
|
});
|
|
4837
5059
|
for (const className of result.mangledClasses) mangledSources.add(className);
|
|
4838
5060
|
for (const className of result.unmangledClasses) externalClasses.add(className);
|
|
5061
|
+
for (const selector of result.classAttributeSelectors) {
|
|
5062
|
+
attributeSelectors.set(classAttributeSelectorKey(selector), selector);
|
|
5063
|
+
}
|
|
4839
5064
|
const mangled = result.transformedCount > 0 ? result.css : css;
|
|
4840
5065
|
recordCssPair(sizeAccount, css, mangled);
|
|
4841
5066
|
return mangled;
|
|
@@ -4844,10 +5069,12 @@ ${transformedCode}`;
|
|
|
4844
5069
|
throw error;
|
|
4845
5070
|
}
|
|
4846
5071
|
}
|
|
4847
|
-
function reportOutputMangleHazards(shouldMangle, mangledSources, externalClasses) {
|
|
5072
|
+
function reportOutputMangleHazards(shouldMangle, mangledSources, externalClasses, attributeSelectors) {
|
|
4848
5073
|
if (!shouldMangle) return;
|
|
4849
5074
|
const message = mangleHybridHazardMessage(
|
|
4850
|
-
collectMangleHybridHazards(state.mangleMap, mangledSources, externalClasses
|
|
5075
|
+
collectMangleHybridHazards(state.mangleMap, mangledSources, externalClasses, [
|
|
5076
|
+
...attributeSelectors.values()
|
|
5077
|
+
])
|
|
4851
5078
|
);
|
|
4852
5079
|
if (message) console.warn(message);
|
|
4853
5080
|
}
|
|
@@ -4908,6 +5135,7 @@ ${transformedCode}`;
|
|
|
4908
5135
|
}
|
|
4909
5136
|
const mangledSources = /* @__PURE__ */ new Set();
|
|
4910
5137
|
const externalClasses = /* @__PURE__ */ new Set();
|
|
5138
|
+
const attributeSelectors = /* @__PURE__ */ new Map();
|
|
4911
5139
|
for (const file in assets) {
|
|
4912
5140
|
const source = assets[file].source().toString();
|
|
4913
5141
|
if (file.endsWith(".css")) {
|
|
@@ -4916,7 +5144,8 @@ ${transformedCode}`;
|
|
|
4916
5144
|
file,
|
|
4917
5145
|
shouldMangle,
|
|
4918
5146
|
mangledSources,
|
|
4919
|
-
externalClasses
|
|
5147
|
+
externalClasses,
|
|
5148
|
+
attributeSelectors
|
|
4920
5149
|
);
|
|
4921
5150
|
if (css !== source) {
|
|
4922
5151
|
compilation.updateAsset(file, new compiler.webpack.sources.RawSource(css));
|
|
@@ -4925,10 +5154,15 @@ ${transformedCode}`;
|
|
|
4925
5154
|
rewriteWebpackCodeAsset(file, source, shouldMangle, compilation, compiler);
|
|
4926
5155
|
}
|
|
4927
5156
|
}
|
|
4928
|
-
reportOutputMangleHazards(
|
|
5157
|
+
reportOutputMangleHazards(
|
|
5158
|
+
shouldMangle,
|
|
5159
|
+
mangledSources,
|
|
5160
|
+
externalClasses,
|
|
5161
|
+
attributeSelectors
|
|
5162
|
+
);
|
|
4929
5163
|
reportBuildSummary();
|
|
4930
5164
|
}
|
|
4931
|
-
function rewriteViteBundleEntry(chunk, file, shouldMangle, mangledSources, externalClasses) {
|
|
5165
|
+
function rewriteViteBundleEntry(chunk, file, shouldMangle, mangledSources, externalClasses, attributeSelectors) {
|
|
4932
5166
|
if (chunk.type !== "asset" || !chunk.fileName.endsWith(".css") || chunk.source === void 0) {
|
|
4933
5167
|
return;
|
|
4934
5168
|
}
|
|
@@ -4938,7 +5172,8 @@ ${transformedCode}`;
|
|
|
4938
5172
|
file,
|
|
4939
5173
|
shouldMangle,
|
|
4940
5174
|
mangledSources,
|
|
4941
|
-
externalClasses
|
|
5175
|
+
externalClasses,
|
|
5176
|
+
attributeSelectors
|
|
4942
5177
|
);
|
|
4943
5178
|
if (css !== originalCss) chunk.source = css;
|
|
4944
5179
|
}
|
|
@@ -4949,7 +5184,8 @@ ${transformedCode}`;
|
|
|
4949
5184
|
id,
|
|
4950
5185
|
shouldMangle,
|
|
4951
5186
|
transformMangledSources,
|
|
4952
|
-
transformExternalClasses
|
|
5187
|
+
transformExternalClasses,
|
|
5188
|
+
transformAttributeSelectors
|
|
4953
5189
|
);
|
|
4954
5190
|
return css === code ? null : { code: css, map: null };
|
|
4955
5191
|
}
|
|
@@ -4974,6 +5210,7 @@ ${transformedCode}`;
|
|
|
4974
5210
|
}
|
|
4975
5211
|
const mangledSources = new Set(transformMangledSources);
|
|
4976
5212
|
const externalClasses = new Set(transformExternalClasses);
|
|
5213
|
+
const attributeSelectors = new Map(transformAttributeSelectors);
|
|
4977
5214
|
if (!cssRewrittenInTransform) {
|
|
4978
5215
|
for (const file in bundle) {
|
|
4979
5216
|
rewriteViteBundleEntry(
|
|
@@ -4981,11 +5218,17 @@ ${transformedCode}`;
|
|
|
4981
5218
|
file,
|
|
4982
5219
|
shouldMangle,
|
|
4983
5220
|
mangledSources,
|
|
4984
|
-
externalClasses
|
|
5221
|
+
externalClasses,
|
|
5222
|
+
attributeSelectors
|
|
4985
5223
|
);
|
|
4986
5224
|
}
|
|
4987
5225
|
}
|
|
4988
|
-
reportOutputMangleHazards(
|
|
5226
|
+
reportOutputMangleHazards(
|
|
5227
|
+
shouldMangle,
|
|
5228
|
+
mangledSources,
|
|
5229
|
+
externalClasses,
|
|
5230
|
+
attributeSelectors
|
|
5231
|
+
);
|
|
4989
5232
|
}
|
|
4990
5233
|
const postPlugin = createUnplugin(() => ({
|
|
4991
5234
|
name: "csszyx:post",
|
|
@@ -5135,4 +5378,4 @@ const esbuildPlugin = (options = {}) => {
|
|
|
5135
5378
|
};
|
|
5136
5379
|
};
|
|
5137
5380
|
|
|
5138
|
-
export {
|
|
5381
|
+
export { suppressedAdvisoryMessage 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, shouldHoldAdvisories as W, shouldTrackGlobalVarSources as X, shouldWarnMissingTailwindEntry as Y, shouldWarnUnscopedMonorepo as Z, skippedSzFilesMessage as _, allocateMangleTokens as a, unscopedMonorepoMessage as a0, validateGlobalVarAliasInputs as a1, vitePlugin as a2, watchModeMangleMessage as a3, webpackPlugin as a4, writeGlobalVarScanCache as a5, 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 };
|