@csszyx/unplugin 0.11.6 → 0.11.8
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/README.md +6 -1
- package/dist/css-mangler.cjs +44 -41
- package/dist/css-mangler.mjs +44 -41
- package/dist/index.cjs +5 -4
- package/dist/index.d.cts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +4 -4
- package/dist/next-config.cjs +1 -1
- package/dist/next-config.mjs +1 -1
- package/dist/next-prebuild.cjs +5 -5
- package/dist/next-prebuild.mjs +5 -5
- package/dist/next-turbo-loader.cjs +13 -12
- package/dist/next-turbo-loader.mjs +13 -12
- package/dist/next-watcher.cjs +2 -2
- package/dist/next-watcher.mjs +2 -2
- package/dist/shared/{unplugin.BFN_Ueyx.cjs → unplugin.C9dMG7ye.cjs} +7 -5
- package/dist/shared/{unplugin.PhOFTQpB.d.cts → unplugin.CNwV3RrQ.d.cts} +18 -5
- package/dist/shared/{unplugin.PhOFTQpB.d.mts → unplugin.CNwV3RrQ.d.mts} +18 -5
- package/dist/shared/unplugin.CcA7jP1r.cjs +48 -0
- package/dist/shared/{unplugin.ByzV6iZE.mjs → unplugin.D-K57LNR.mjs} +13 -7
- package/dist/shared/{unplugin.D0N9bprz.cjs → unplugin.DVCQC5wq.cjs} +12 -5
- package/dist/shared/{unplugin.CBKZoxQ1.cjs → unplugin.DdtOZANG.cjs} +51 -50
- package/dist/shared/{unplugin.ChwZMl_w.mjs → unplugin.Dg1tGPSd.mjs} +8 -6
- package/dist/shared/{unplugin.Rov-j_Wm.cjs → unplugin.DmuOKVS4.cjs} +21 -0
- package/dist/shared/{unplugin.CP2cz9bA.cjs → unplugin.DtPQz8Kg.cjs} +1291 -938
- package/dist/shared/{unplugin.BS60onPk.mjs → unplugin.DtYxS8M8.mjs} +1290 -938
- package/dist/shared/{unplugin.B3cvNxnk.mjs → unplugin.Rl8sIkHi.mjs} +51 -50
- package/dist/shared/unplugin.TtmP77BS.mjs +40 -0
- package/dist/shared/unplugin.nnsa7OVW.mjs +49 -0
- package/dist/vite.cjs +4 -4
- package/dist/vite.d.cts +2 -25
- package/dist/vite.d.mts +1 -25
- package/dist/vite.mjs +4 -8
- package/dist/webpack.cjs +4 -4
- package/dist/webpack.d.cts +2 -5
- package/dist/webpack.d.mts +1 -5
- package/dist/webpack.mjs +4 -8
- package/package.json +7 -7
- package/dist/shared/unplugin.B1mblcm-.mjs +0 -9
- package/dist/shared/unplugin.B3RHYokB.mjs +0 -29
- package/dist/shared/unplugin.BCwRIUs_.cjs +0 -12
|
@@ -6,7 +6,7 @@ import * as path from 'node:path';
|
|
|
6
6
|
import { 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, ensureRustTransformAvailable, transformSourceCode, transformRust, transformOxc,
|
|
9
|
+
import { scanGlobalVarUsages, sortStrings as sortStrings$1, ensureRustTransformAvailable, transformSourceCode, transformRust, transformOxc, ASTBudgetExceededError, transformRustBatch, transform, isRustTransformAvailable } 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 { mangleCSSSync } from '../css-mangler.mjs';
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
17
|
+
import { i as importsRuntimeHelper, f as findRuntimeImportClause, a as insertAfterUseDirective } from './unplugin.nnsa7OVW.mjs';
|
|
18
|
+
import { n as normalizePathSeparators, r as resolveTransformCacheDir, c as createTransformCacheKey, w as writeTransformCache, e as evictOldTransformCacheEntries, a as readTransformCache, b as evictMemoryCacheToBudget } from './unplugin.D-K57LNR.mjs';
|
|
19
|
+
import { s as sortStrings, a as replaceEveryLiteral, u as unicodeEscape, b as escapeDoubleQuotedString, c as escapeSingleQuotedString, e as escapeHtmlAttribute, r as renderTailwindScannerCandidates } from './unplugin.TtmP77BS.mjs';
|
|
20
20
|
import postcss from 'postcss';
|
|
21
21
|
import valueParser from 'postcss-value-parser';
|
|
22
22
|
|
|
@@ -96,7 +96,8 @@ function buildScopeId(node) {
|
|
|
96
96
|
}
|
|
97
97
|
current = current.parent;
|
|
98
98
|
}
|
|
99
|
-
|
|
99
|
+
parts.reverse();
|
|
100
|
+
return parts.join(" > ") || DEFAULT_SCOPE_ID;
|
|
100
101
|
}
|
|
101
102
|
|
|
102
103
|
const VAR_REFERENCE_RE = /var\(\s*(--[\w-]+)/g;
|
|
@@ -369,7 +370,7 @@ function rewriteGlobalVarValue(value, aliases) {
|
|
|
369
370
|
return;
|
|
370
371
|
}
|
|
371
372
|
const firstArgument = node.nodes.find((child) => child.type !== "space");
|
|
372
|
-
if (
|
|
373
|
+
if (firstArgument?.type !== "word") {
|
|
373
374
|
return;
|
|
374
375
|
}
|
|
375
376
|
const alias = aliases.get(firstArgument.value);
|
|
@@ -519,8 +520,8 @@ function createRSCModuleRecord(code, id) {
|
|
|
519
520
|
}
|
|
520
521
|
function deleteRSCModuleRecord(records, id) {
|
|
521
522
|
const normalized = normalizeModuleId(id);
|
|
522
|
-
const clean = id.split("?")[0]
|
|
523
|
-
const resolved = path.resolve(clean)
|
|
523
|
+
const clean = normalizePathSeparators(id.split("?")[0] ?? id);
|
|
524
|
+
const resolved = normalizePathSeparators(path.resolve(clean));
|
|
524
525
|
pruneRSCModulePathCaches(/* @__PURE__ */ new Set([normalized, resolved, clean]));
|
|
525
526
|
let deleted = records.delete(normalized);
|
|
526
527
|
if (resolved !== normalized) {
|
|
@@ -566,7 +567,7 @@ const APP_ROUTER_ENTRIES = /* @__PURE__ */ new Set([
|
|
|
566
567
|
"route"
|
|
567
568
|
]);
|
|
568
569
|
function isNextAppRouterEntry(id) {
|
|
569
|
-
const clean = id.split("?")[0]
|
|
570
|
+
const clean = normalizePathSeparators(id.split("?")[0] ?? id);
|
|
570
571
|
if (!clean.includes("/app/") && !clean.startsWith("app/")) return false;
|
|
571
572
|
const basename = clean.split("/").pop() ?? "";
|
|
572
573
|
const dotIdx = basename.indexOf(".");
|
|
@@ -615,38 +616,41 @@ function walkRSCGraph(current, records, chain, seen) {
|
|
|
615
616
|
}
|
|
616
617
|
return null;
|
|
617
618
|
}
|
|
619
|
+
function findDirectiveQuoteEnd(code, start, quote) {
|
|
620
|
+
let escaped = false;
|
|
621
|
+
for (let index = start + 1; index < code.length; index++) {
|
|
622
|
+
const char = code[index];
|
|
623
|
+
if (escaped) {
|
|
624
|
+
escaped = false;
|
|
625
|
+
} else if (char === "\\") {
|
|
626
|
+
escaped = true;
|
|
627
|
+
} else if (char === quote) {
|
|
628
|
+
return index;
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
return -1;
|
|
632
|
+
}
|
|
633
|
+
function findDirectiveStatementEnd(code, start) {
|
|
634
|
+
let end = start;
|
|
635
|
+
while (end < code.length && /[ \t\r\n]/.test(code[end])) {
|
|
636
|
+
end++;
|
|
637
|
+
}
|
|
638
|
+
return code[end] === ";" ? end + 1 : end;
|
|
639
|
+
}
|
|
618
640
|
function readDirectivePrologue(code) {
|
|
619
641
|
const out = [];
|
|
620
|
-
let i = code
|
|
642
|
+
let i = readCodePoint(code, 0) === 65279 ? 1 : 0;
|
|
621
643
|
while (i < code.length) {
|
|
622
644
|
i = skipWhitespaceAndComments(code, i);
|
|
623
645
|
const quote = code[i];
|
|
624
646
|
if (quote !== '"' && quote !== "'") {
|
|
625
647
|
break;
|
|
626
648
|
}
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
while (j < code.length) {
|
|
630
|
-
const ch = code[j];
|
|
631
|
-
if (escaped) {
|
|
632
|
-
escaped = false;
|
|
633
|
-
} else if (ch === "\\") {
|
|
634
|
-
escaped = true;
|
|
635
|
-
} else if (ch === quote) {
|
|
636
|
-
break;
|
|
637
|
-
}
|
|
638
|
-
j++;
|
|
639
|
-
}
|
|
640
|
-
if (j >= code.length) {
|
|
649
|
+
const quoteEnd = findDirectiveQuoteEnd(code, i, quote);
|
|
650
|
+
if (quoteEnd === -1) {
|
|
641
651
|
break;
|
|
642
652
|
}
|
|
643
|
-
|
|
644
|
-
while (end < code.length && /[ \t\r\n]/.test(code[end])) {
|
|
645
|
-
end++;
|
|
646
|
-
}
|
|
647
|
-
if (code[end] === ";") {
|
|
648
|
-
end++;
|
|
649
|
-
}
|
|
653
|
+
const end = findDirectiveStatementEnd(code, quoteEnd + 1);
|
|
650
654
|
out.push(code.slice(i, end).trim());
|
|
651
655
|
i = end;
|
|
652
656
|
}
|
|
@@ -702,55 +706,50 @@ function findStaticImports(code) {
|
|
|
702
706
|
let cursor = 0;
|
|
703
707
|
while (cursor < code.length) {
|
|
704
708
|
const importStart = code.indexOf("import", cursor);
|
|
705
|
-
if (importStart === -1)
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
if (importStart > 0 && isIdentifierPart(code.charCodeAt(importStart - 1)) || isIdentifierPart(code.charCodeAt(cursor))) {
|
|
710
|
-
continue;
|
|
711
|
-
}
|
|
712
|
-
let position = skipAsciiWhitespace(code, cursor);
|
|
713
|
-
const opener = code.charAt(position);
|
|
714
|
-
if (opener === "(") {
|
|
715
|
-
continue;
|
|
716
|
-
}
|
|
717
|
-
if (opener === '"' || opener === "'") {
|
|
718
|
-
const literal2 = readQuotedString(code, position);
|
|
719
|
-
if (literal2) {
|
|
720
|
-
imports.push({ clause: null, source: literal2.value });
|
|
721
|
-
cursor = literal2.end;
|
|
722
|
-
}
|
|
723
|
-
continue;
|
|
724
|
-
}
|
|
725
|
-
const clauseStart = position;
|
|
726
|
-
let fromStart = -1;
|
|
727
|
-
while (position < code.length) {
|
|
728
|
-
if (code.startsWith("from", position) && (position === clauseStart || !isIdentifierPart(code.charCodeAt(position - 1))) && !isIdentifierPart(code.charCodeAt(position + 4))) {
|
|
729
|
-
fromStart = position;
|
|
730
|
-
break;
|
|
731
|
-
}
|
|
732
|
-
if (code.charAt(position) === ";") {
|
|
733
|
-
break;
|
|
734
|
-
}
|
|
735
|
-
position += 1;
|
|
736
|
-
}
|
|
737
|
-
if (fromStart === -1) {
|
|
738
|
-
continue;
|
|
739
|
-
}
|
|
740
|
-
const clause = code.slice(clauseStart, fromStart).trim();
|
|
741
|
-
if (splitAsciiWhitespace(clause)[0] === "type") {
|
|
742
|
-
cursor = fromStart + 4;
|
|
743
|
-
continue;
|
|
744
|
-
}
|
|
745
|
-
position = skipAsciiWhitespace(code, fromStart + 4);
|
|
746
|
-
const literal = readQuotedString(code, position);
|
|
747
|
-
if (literal) {
|
|
748
|
-
imports.push({ clause, source: literal.value });
|
|
749
|
-
cursor = literal.end;
|
|
750
|
-
}
|
|
709
|
+
if (importStart === -1) break;
|
|
710
|
+
const result = scanStaticImport(code, importStart);
|
|
711
|
+
cursor = result.nextCursor;
|
|
712
|
+
if (result.value) imports.push(result.value);
|
|
751
713
|
}
|
|
752
714
|
return imports;
|
|
753
715
|
}
|
|
716
|
+
function scanStaticImport(code, importStart) {
|
|
717
|
+
const afterKeyword = importStart + 6;
|
|
718
|
+
if (importStart > 0 && isIdentifierPart(readCodePoint(code, importStart - 1)) || isIdentifierPart(readCodePoint(code, afterKeyword))) {
|
|
719
|
+
return { nextCursor: afterKeyword };
|
|
720
|
+
}
|
|
721
|
+
const clauseStart = skipAsciiWhitespace(code, afterKeyword);
|
|
722
|
+
const opener = code.charAt(clauseStart);
|
|
723
|
+
if (opener === "(") return { nextCursor: afterKeyword };
|
|
724
|
+
if (opener === '"' || opener === "'") {
|
|
725
|
+
return scanSideEffectImport(code, clauseStart, afterKeyword);
|
|
726
|
+
}
|
|
727
|
+
return scanImportClause(code, clauseStart, afterKeyword);
|
|
728
|
+
}
|
|
729
|
+
function scanSideEffectImport(code, literalStart, fallbackCursor) {
|
|
730
|
+
const literal = readQuotedString(code, literalStart);
|
|
731
|
+
return literal ? { nextCursor: literal.end, value: { clause: null, source: literal.value } } : { nextCursor: fallbackCursor };
|
|
732
|
+
}
|
|
733
|
+
function scanImportClause(code, clauseStart, fallbackCursor) {
|
|
734
|
+
const fromStart = findImportFromKeyword(code, clauseStart);
|
|
735
|
+
if (fromStart === -1) return { nextCursor: fallbackCursor };
|
|
736
|
+
const clause = code.slice(clauseStart, fromStart).trim();
|
|
737
|
+
if (splitAsciiWhitespace(clause)[0] === "type") {
|
|
738
|
+
return { nextCursor: fromStart + 4 };
|
|
739
|
+
}
|
|
740
|
+
const literalStart = skipAsciiWhitespace(code, fromStart + 4);
|
|
741
|
+
const literal = readQuotedString(code, literalStart);
|
|
742
|
+
return literal ? { nextCursor: literal.end, value: { clause, source: literal.value } } : { nextCursor: fallbackCursor };
|
|
743
|
+
}
|
|
744
|
+
function findImportFromKeyword(code, clauseStart) {
|
|
745
|
+
for (let position = clauseStart; position < code.length; position += 1) {
|
|
746
|
+
if (code.charAt(position) === ";") return -1;
|
|
747
|
+
if (code.startsWith("from", position) && (position === clauseStart || !isIdentifierPart(readCodePoint(code, position - 1))) && !isIdentifierPart(readCodePoint(code, position + 4))) {
|
|
748
|
+
return position;
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
return -1;
|
|
752
|
+
}
|
|
754
753
|
function readQuotedString(code, start) {
|
|
755
754
|
const quote = code.charAt(start);
|
|
756
755
|
if (quote !== '"' && quote !== "'") {
|
|
@@ -778,7 +777,7 @@ function readQuotedString(code, start) {
|
|
|
778
777
|
function skipAsciiWhitespace(code, start) {
|
|
779
778
|
let index = start;
|
|
780
779
|
while (index < code.length) {
|
|
781
|
-
const charCode = code
|
|
780
|
+
const charCode = readCodePoint(code, index);
|
|
782
781
|
if (charCode !== 9 && charCode !== 10 && charCode !== 13 && charCode !== 32) {
|
|
783
782
|
break;
|
|
784
783
|
}
|
|
@@ -923,9 +922,9 @@ function normalizeModuleId(id) {
|
|
|
923
922
|
}
|
|
924
923
|
let normalized;
|
|
925
924
|
try {
|
|
926
|
-
normalized = fs.realpathSync.native(clean)
|
|
925
|
+
normalized = normalizePathSeparators(fs.realpathSync.native(clean));
|
|
927
926
|
} catch {
|
|
928
|
-
normalized = path.resolve(clean)
|
|
927
|
+
normalized = normalizePathSeparators(path.resolve(clean));
|
|
929
928
|
}
|
|
930
929
|
normalizedModuleIdCache.set(clean, normalized);
|
|
931
930
|
return normalized;
|
|
@@ -971,7 +970,7 @@ function resolveLocalModule(importer, source) {
|
|
|
971
970
|
}
|
|
972
971
|
function pruneRSCModulePathCaches(moduleIds) {
|
|
973
972
|
for (const [key, value] of normalizedModuleIdCache) {
|
|
974
|
-
const normalizedKey = key
|
|
973
|
+
const normalizedKey = normalizePathSeparators(key);
|
|
975
974
|
if (moduleIds.has(value) || moduleIds.has(normalizedKey)) {
|
|
976
975
|
normalizedModuleIdCache.delete(key);
|
|
977
976
|
}
|
|
@@ -982,43 +981,44 @@ function pruneRSCModulePathCaches(moduleIds) {
|
|
|
982
981
|
}
|
|
983
982
|
}
|
|
984
983
|
}
|
|
985
|
-
function
|
|
986
|
-
const symbols = [];
|
|
984
|
+
function readNamedImportedSymbols(clause) {
|
|
987
985
|
const openBrace = clause.indexOf("{");
|
|
988
986
|
const closeBrace = openBrace === -1 ? -1 : clause.indexOf("}", openBrace);
|
|
989
|
-
if (openBrace
|
|
990
|
-
|
|
991
|
-
for (const part of namedPart.split(",")) {
|
|
992
|
-
const trimmed = part.trim();
|
|
993
|
-
if (!trimmed || trimmed.startsWith("type ")) {
|
|
994
|
-
continue;
|
|
995
|
-
}
|
|
996
|
-
const sourceName = trimmed.replace(/^type[ \t]+/, "").split(/(?<![ \t])[ \t]+as[ \t]+/)[0]?.trim();
|
|
997
|
-
if (sourceName) {
|
|
998
|
-
symbols.push(sourceName);
|
|
999
|
-
}
|
|
1000
|
-
}
|
|
1001
|
-
}
|
|
1002
|
-
const namespaceParts = splitAsciiWhitespace(clause);
|
|
1003
|
-
if (namespaceParts.length >= 3 && namespaceParts[0] === "*" && namespaceParts[1] === "as" && isIdentifier(namespaceParts[2] ?? "")) {
|
|
1004
|
-
symbols.push(...FORBIDDEN_SYMBOLS);
|
|
987
|
+
if (openBrace === -1 || closeBrace === -1) {
|
|
988
|
+
return [];
|
|
1005
989
|
}
|
|
990
|
+
return clause.slice(openBrace + 1, closeBrace).split(",").map((part) => part.trim()).filter((part) => part !== "" && !part.startsWith("type ")).map(
|
|
991
|
+
(part) => part.replace(/^type[ \t]+/, "").split(/(?<![ \t])[ \t]+as[ \t]+/)[0]?.trim()
|
|
992
|
+
).filter((symbol) => Boolean(symbol));
|
|
993
|
+
}
|
|
994
|
+
function readForbiddenDefaultSymbol(clause) {
|
|
1006
995
|
const braceStart = clause.indexOf("{");
|
|
1007
996
|
const braceEnd = clause.indexOf("}", braceStart);
|
|
1008
997
|
const stripped = braceStart !== -1 && braceEnd !== -1 ? clause.slice(0, braceStart) + clause.slice(braceEnd + 1) : clause;
|
|
1009
|
-
const
|
|
1010
|
-
|
|
1011
|
-
|
|
998
|
+
const candidate = stripped.trimStart().split(",", 1)[0]?.trim() ?? "";
|
|
999
|
+
return isIdentifier(candidate) && FORBIDDEN_SYMBOLS.has(candidate) ? candidate : null;
|
|
1000
|
+
}
|
|
1001
|
+
function hasNamespaceImport(clause) {
|
|
1002
|
+
const parts = splitAsciiWhitespace(clause);
|
|
1003
|
+
return parts.length >= 3 && parts[0] === "*" && parts[1] === "as" && isIdentifier(parts[2] ?? "");
|
|
1004
|
+
}
|
|
1005
|
+
function readImportedSymbols(clause) {
|
|
1006
|
+
const symbols = readNamedImportedSymbols(clause);
|
|
1007
|
+
if (hasNamespaceImport(clause)) {
|
|
1008
|
+
symbols.push(...FORBIDDEN_SYMBOLS);
|
|
1009
|
+
}
|
|
1010
|
+
const defaultSymbol = readForbiddenDefaultSymbol(clause);
|
|
1011
|
+
if (defaultSymbol) {
|
|
1012
1012
|
symbols.push(defaultSymbol);
|
|
1013
1013
|
}
|
|
1014
1014
|
return symbols;
|
|
1015
1015
|
}
|
|
1016
1016
|
function isIdentifier(value) {
|
|
1017
|
-
if (value.length === 0 || !isIdentifierStart(value
|
|
1017
|
+
if (value.length === 0 || !isIdentifierStart(readCodePoint(value, 0))) {
|
|
1018
1018
|
return false;
|
|
1019
1019
|
}
|
|
1020
1020
|
for (let index = 1; index < value.length; index += 1) {
|
|
1021
|
-
const code = value
|
|
1021
|
+
const code = readCodePoint(value, index);
|
|
1022
1022
|
if (!isIdentifierStart(code) && (code < 48 || code > 57)) {
|
|
1023
1023
|
return false;
|
|
1024
1024
|
}
|
|
@@ -1028,11 +1028,14 @@ function isIdentifier(value) {
|
|
|
1028
1028
|
function isIdentifierStart(code) {
|
|
1029
1029
|
return code === 36 || code === 95 || code >= 65 && code <= 90 || code >= 97 && code <= 122;
|
|
1030
1030
|
}
|
|
1031
|
+
function readCodePoint(value, index) {
|
|
1032
|
+
return value.codePointAt(index) ?? -1;
|
|
1033
|
+
}
|
|
1031
1034
|
function splitAsciiWhitespace(value) {
|
|
1032
1035
|
const parts = [];
|
|
1033
1036
|
let start = -1;
|
|
1034
1037
|
for (let index = 0; index <= value.length; index += 1) {
|
|
1035
|
-
const code = index < value.length ? value
|
|
1038
|
+
const code = index < value.length ? readCodePoint(value, index) : 32;
|
|
1036
1039
|
const whitespace = code === 9 || code === 10 || code === 13 || code === 32;
|
|
1037
1040
|
if (whitespace) {
|
|
1038
1041
|
if (start !== -1) {
|
|
@@ -1055,13 +1058,7 @@ function stripCommentsForImportScan(code) {
|
|
|
1055
1058
|
const next = code[i + 1];
|
|
1056
1059
|
if (quote) {
|
|
1057
1060
|
out += ch;
|
|
1058
|
-
|
|
1059
|
-
escaped = false;
|
|
1060
|
-
} else if (ch === "\\") {
|
|
1061
|
-
escaped = true;
|
|
1062
|
-
} else if (ch === quote) {
|
|
1063
|
-
quote = null;
|
|
1064
|
-
}
|
|
1061
|
+
({ quote, escaped } = advanceQuotedImportScan(ch, quote, escaped));
|
|
1065
1062
|
i++;
|
|
1066
1063
|
continue;
|
|
1067
1064
|
}
|
|
@@ -1072,28 +1069,15 @@ function stripCommentsForImportScan(code) {
|
|
|
1072
1069
|
continue;
|
|
1073
1070
|
}
|
|
1074
1071
|
if (ch === "/" && next === "/") {
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
out += " ";
|
|
1079
|
-
i++;
|
|
1080
|
-
}
|
|
1072
|
+
const masked = maskLineComment(code, i);
|
|
1073
|
+
out += masked.value;
|
|
1074
|
+
i = masked.end;
|
|
1081
1075
|
continue;
|
|
1082
1076
|
}
|
|
1083
1077
|
if (ch === "/" && next === "*") {
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
const blockCh = code[i];
|
|
1088
|
-
const blockNext = code[i + 1];
|
|
1089
|
-
if (blockCh === "*" && blockNext === "/") {
|
|
1090
|
-
out += " ";
|
|
1091
|
-
i += 2;
|
|
1092
|
-
break;
|
|
1093
|
-
}
|
|
1094
|
-
out += blockCh === "\n" ? "\n" : " ";
|
|
1095
|
-
i++;
|
|
1096
|
-
}
|
|
1078
|
+
const masked = maskBlockComment(code, i);
|
|
1079
|
+
out += masked.value;
|
|
1080
|
+
i = masked.end;
|
|
1097
1081
|
continue;
|
|
1098
1082
|
}
|
|
1099
1083
|
out += ch;
|
|
@@ -1101,6 +1085,31 @@ function stripCommentsForImportScan(code) {
|
|
|
1101
1085
|
}
|
|
1102
1086
|
return out;
|
|
1103
1087
|
}
|
|
1088
|
+
function advanceQuotedImportScan(character, quote, escaped) {
|
|
1089
|
+
if (escaped) return { quote, escaped: false };
|
|
1090
|
+
if (character === "\\") return { quote, escaped: true };
|
|
1091
|
+
return { quote: character === quote ? null : quote, escaped: false };
|
|
1092
|
+
}
|
|
1093
|
+
function maskLineComment(code, start) {
|
|
1094
|
+
const newline = code.indexOf("\n", start + 2);
|
|
1095
|
+
const end = newline === -1 ? code.length : newline;
|
|
1096
|
+
return { end, value: " ".repeat(end - start) };
|
|
1097
|
+
}
|
|
1098
|
+
function maskBlockComment(code, start) {
|
|
1099
|
+
let end = start + 2;
|
|
1100
|
+
while (end < code.length) {
|
|
1101
|
+
if (code.charAt(end) === "*" && code.charAt(end + 1) === "/") {
|
|
1102
|
+
end += 2;
|
|
1103
|
+
break;
|
|
1104
|
+
}
|
|
1105
|
+
end += 1;
|
|
1106
|
+
}
|
|
1107
|
+
let value = "";
|
|
1108
|
+
for (let index = start; index < end; index += 1) {
|
|
1109
|
+
value += code.charAt(index) === "\n" ? "\n" : " ";
|
|
1110
|
+
}
|
|
1111
|
+
return { end, value };
|
|
1112
|
+
}
|
|
1104
1113
|
|
|
1105
1114
|
const EMPTY_THEME = {
|
|
1106
1115
|
colors: [],
|
|
@@ -1112,6 +1121,20 @@ const EMPTY_THEME = {
|
|
|
1112
1121
|
shadows: [],
|
|
1113
1122
|
breakpoints: []
|
|
1114
1123
|
};
|
|
1124
|
+
function findMatchingBrace(source, openBrace) {
|
|
1125
|
+
let depth = 0;
|
|
1126
|
+
for (let index = openBrace; index < source.length; index++) {
|
|
1127
|
+
if (source[index] === "{") {
|
|
1128
|
+
depth++;
|
|
1129
|
+
} else if (source[index] === "}") {
|
|
1130
|
+
depth--;
|
|
1131
|
+
if (depth === 0) {
|
|
1132
|
+
return index;
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
return -1;
|
|
1137
|
+
}
|
|
1115
1138
|
function stripLayerWrappers(css) {
|
|
1116
1139
|
let result = "";
|
|
1117
1140
|
let i = 0;
|
|
@@ -1127,26 +1150,13 @@ function stripLayerWrappers(css) {
|
|
|
1127
1150
|
result += css.slice(layerIdx);
|
|
1128
1151
|
break;
|
|
1129
1152
|
}
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
while (j < css.length) {
|
|
1133
|
-
if (css[j] === "{") {
|
|
1134
|
-
depth++;
|
|
1135
|
-
}
|
|
1136
|
-
if (css[j] === "}") {
|
|
1137
|
-
depth--;
|
|
1138
|
-
if (depth === 0) {
|
|
1139
|
-
result += css.slice(openBrace + 1, j);
|
|
1140
|
-
i = j + 1;
|
|
1141
|
-
break;
|
|
1142
|
-
}
|
|
1143
|
-
}
|
|
1144
|
-
j++;
|
|
1145
|
-
}
|
|
1146
|
-
if (depth !== 0) {
|
|
1153
|
+
const closeBrace = findMatchingBrace(css, openBrace);
|
|
1154
|
+
if (closeBrace === -1) {
|
|
1147
1155
|
result += css.slice(openBrace);
|
|
1148
1156
|
break;
|
|
1149
1157
|
}
|
|
1158
|
+
result += css.slice(openBrace + 1, closeBrace);
|
|
1159
|
+
i = closeBrace + 1;
|
|
1150
1160
|
}
|
|
1151
1161
|
return result;
|
|
1152
1162
|
}
|
|
@@ -1155,20 +1165,9 @@ function extractThemeBlocks(css) {
|
|
|
1155
1165
|
const themeStart = /@theme\s+(?:inline\s+)?\{|@theme\{/g;
|
|
1156
1166
|
for (const match of css.matchAll(themeStart)) {
|
|
1157
1167
|
const openPos = css.indexOf("{", match.index);
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
if (css[j] === "{") {
|
|
1162
|
-
depth++;
|
|
1163
|
-
}
|
|
1164
|
-
if (css[j] === "}") {
|
|
1165
|
-
depth--;
|
|
1166
|
-
if (depth === 0) {
|
|
1167
|
-
blocks.push(css.slice(openPos + 1, j));
|
|
1168
|
-
break;
|
|
1169
|
-
}
|
|
1170
|
-
}
|
|
1171
|
-
j++;
|
|
1168
|
+
const closePos = findMatchingBrace(css, openPos);
|
|
1169
|
+
if (closePos !== -1) {
|
|
1170
|
+
blocks.push(css.slice(openPos + 1, closePos));
|
|
1172
1171
|
}
|
|
1173
1172
|
}
|
|
1174
1173
|
return blocks;
|
|
@@ -1267,6 +1266,29 @@ function mergeThemes(themes) {
|
|
|
1267
1266
|
function hasTokens(theme) {
|
|
1268
1267
|
return Object.values(theme).some((arr) => arr.length > 0);
|
|
1269
1268
|
}
|
|
1269
|
+
function readCustomPropertyName(block, dashes) {
|
|
1270
|
+
let end = dashes + 2;
|
|
1271
|
+
if (end >= block.length || !/[a-z]/.test(block[end])) {
|
|
1272
|
+
return null;
|
|
1273
|
+
}
|
|
1274
|
+
end++;
|
|
1275
|
+
while (end < block.length && /[a-z0-9-]/.test(block[end])) {
|
|
1276
|
+
end++;
|
|
1277
|
+
}
|
|
1278
|
+
return { name: block.slice(dashes + 2, end), end };
|
|
1279
|
+
}
|
|
1280
|
+
function findCustomPropertyDeclarationEnd(block, nameEnd) {
|
|
1281
|
+
let cursor = nameEnd;
|
|
1282
|
+
while (cursor < block.length && /\s/.test(block[cursor])) {
|
|
1283
|
+
cursor++;
|
|
1284
|
+
}
|
|
1285
|
+
if (block[cursor] === ":") {
|
|
1286
|
+
const valueStart = cursor + 1;
|
|
1287
|
+
const semicolon = block.indexOf(";", valueStart);
|
|
1288
|
+
return semicolon > valueStart ? semicolon + 1 : -1;
|
|
1289
|
+
}
|
|
1290
|
+
return block[nameEnd] === ";" ? nameEnd + 1 : -1;
|
|
1291
|
+
}
|
|
1270
1292
|
function scanCustomPropertyNames(block) {
|
|
1271
1293
|
const names = [];
|
|
1272
1294
|
let i = 0;
|
|
@@ -1275,48 +1297,392 @@ function scanCustomPropertyNames(block) {
|
|
|
1275
1297
|
if (dashes === -1) {
|
|
1276
1298
|
break;
|
|
1277
1299
|
}
|
|
1278
|
-
|
|
1279
|
-
if (
|
|
1300
|
+
const property = readCustomPropertyName(block, dashes);
|
|
1301
|
+
if (!property) {
|
|
1280
1302
|
i = dashes + 1;
|
|
1281
1303
|
continue;
|
|
1282
1304
|
}
|
|
1283
|
-
end
|
|
1284
|
-
|
|
1285
|
-
|
|
1305
|
+
const matchEnd = findCustomPropertyDeclarationEnd(block, property.end);
|
|
1306
|
+
if (matchEnd === -1) {
|
|
1307
|
+
i = dashes + 1;
|
|
1308
|
+
continue;
|
|
1309
|
+
}
|
|
1310
|
+
names.push(property.name);
|
|
1311
|
+
i = matchEnd;
|
|
1312
|
+
}
|
|
1313
|
+
return names;
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1316
|
+
const REGEX_PREFIXES = new Set("([{:,;=!?&|+-*%^~<>/");
|
|
1317
|
+
const REGEX_PREFIX_KEYWORDS = /* @__PURE__ */ new Set([
|
|
1318
|
+
"await",
|
|
1319
|
+
"case",
|
|
1320
|
+
"delete",
|
|
1321
|
+
"do",
|
|
1322
|
+
"else",
|
|
1323
|
+
"in",
|
|
1324
|
+
"instanceof",
|
|
1325
|
+
"of",
|
|
1326
|
+
"return",
|
|
1327
|
+
"throw",
|
|
1328
|
+
"typeof",
|
|
1329
|
+
"void",
|
|
1330
|
+
"yield"
|
|
1331
|
+
]);
|
|
1332
|
+
const SIMPLE_ESCAPES = {
|
|
1333
|
+
b: "\b",
|
|
1334
|
+
f: "\f",
|
|
1335
|
+
n: "\n",
|
|
1336
|
+
r: "\r",
|
|
1337
|
+
t: " ",
|
|
1338
|
+
v: "\v",
|
|
1339
|
+
"0": "\0"
|
|
1340
|
+
};
|
|
1341
|
+
function isFixedHex(value, width) {
|
|
1342
|
+
if (value.length !== width) return false;
|
|
1343
|
+
for (const character of value) {
|
|
1344
|
+
if (!"0123456789abcdefABCDEF".includes(character)) return false;
|
|
1345
|
+
}
|
|
1346
|
+
return true;
|
|
1347
|
+
}
|
|
1348
|
+
function decodeEscape(value, cursor) {
|
|
1349
|
+
const escaped = value[cursor];
|
|
1350
|
+
if (SIMPLE_ESCAPES[escaped] !== void 0) {
|
|
1351
|
+
return { value: SIMPLE_ESCAPES[escaped], cursor };
|
|
1352
|
+
}
|
|
1353
|
+
if (escaped === "\r" && value[cursor + 1] === "\n") {
|
|
1354
|
+
return { value: "", cursor: cursor + 1 };
|
|
1355
|
+
}
|
|
1356
|
+
if (escaped === "u" && value[cursor + 1] === "{") {
|
|
1357
|
+
const close = value.indexOf("}", cursor + 2);
|
|
1358
|
+
const hex2 = close === -1 ? "" : value.slice(cursor + 2, close);
|
|
1359
|
+
const codePoint = hex2 && /^[\dA-F]+$/i.test(hex2) ? Number.parseInt(hex2, 16) : -1;
|
|
1360
|
+
if (codePoint >= 0 && codePoint <= 1114111) {
|
|
1361
|
+
return { value: String.fromCodePoint(codePoint), cursor: close };
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
let width = 0;
|
|
1365
|
+
if (escaped === "x") width = 2;
|
|
1366
|
+
else if (escaped === "u") width = 4;
|
|
1367
|
+
const hex = value.slice(cursor + 1, cursor + width + 1);
|
|
1368
|
+
if (width > 0 && isFixedHex(hex, width)) {
|
|
1369
|
+
return {
|
|
1370
|
+
value: String.fromCodePoint(Number.parseInt(hex, 16)),
|
|
1371
|
+
cursor: cursor + width
|
|
1372
|
+
};
|
|
1373
|
+
}
|
|
1374
|
+
const decoded = escaped === "\n" || escaped === "\r" ? "" : escaped;
|
|
1375
|
+
return { value: decoded, cursor };
|
|
1376
|
+
}
|
|
1377
|
+
function decodeJavaScriptString(value) {
|
|
1378
|
+
let output = "";
|
|
1379
|
+
let cursor = 0;
|
|
1380
|
+
while (cursor < value.length) {
|
|
1381
|
+
if (value[cursor] !== "\\" || cursor + 1 >= value.length) {
|
|
1382
|
+
output += value[cursor++];
|
|
1383
|
+
continue;
|
|
1384
|
+
}
|
|
1385
|
+
const decoded = decodeEscape(value, cursor + 1);
|
|
1386
|
+
output += decoded.value;
|
|
1387
|
+
cursor = decoded.cursor + 1;
|
|
1388
|
+
}
|
|
1389
|
+
return output;
|
|
1390
|
+
}
|
|
1391
|
+
function decodeAttributeWhitespace(value) {
|
|
1392
|
+
return value.replace(
|
|
1393
|
+
/&#(?:(\d+)|x([\da-f]+));|&(?:Tab|NewLine);/gi,
|
|
1394
|
+
(entity, decimal, hexadecimal) => {
|
|
1395
|
+
if (!decimal && !hexadecimal) return " ";
|
|
1396
|
+
const codePoint = Number.parseInt(decimal ?? hexadecimal ?? "", decimal ? 10 : 16);
|
|
1397
|
+
return [9, 10, 12, 13, 32].includes(codePoint) ? " " : entity;
|
|
1398
|
+
}
|
|
1399
|
+
);
|
|
1400
|
+
}
|
|
1401
|
+
function collectClassTokens(target, value) {
|
|
1402
|
+
for (const className of value.split(/\s+/)) {
|
|
1403
|
+
if (className) target.add(className);
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
function quotedEnd(source, start, quote) {
|
|
1407
|
+
let cursor = start + 1;
|
|
1408
|
+
while (cursor < source.length) {
|
|
1409
|
+
if (source[cursor] === "\\") cursor += 2;
|
|
1410
|
+
else if (source[cursor++] === quote) break;
|
|
1411
|
+
}
|
|
1412
|
+
return cursor;
|
|
1413
|
+
}
|
|
1414
|
+
function commentEnd(source, start) {
|
|
1415
|
+
if (source[start + 1] === "/") {
|
|
1416
|
+
const end2 = source.indexOf("\n", start + 2);
|
|
1417
|
+
return end2 === -1 ? source.length : end2 + 1;
|
|
1418
|
+
}
|
|
1419
|
+
const end = source.indexOf("*/", start + 2);
|
|
1420
|
+
return end === -1 ? source.length : end + 2;
|
|
1421
|
+
}
|
|
1422
|
+
function isRegexStart(source, start) {
|
|
1423
|
+
let cursor = start - 1;
|
|
1424
|
+
while (cursor >= 0 && /\s/.test(source[cursor])) cursor--;
|
|
1425
|
+
if (source[cursor] === "<" && /[A-Z]/i.test(source[start + 1] ?? "")) return false;
|
|
1426
|
+
if (cursor < 0 || REGEX_PREFIXES.has(source[cursor])) return true;
|
|
1427
|
+
if (!/[\w$]/.test(source[cursor])) return false;
|
|
1428
|
+
const end = cursor + 1;
|
|
1429
|
+
while (cursor >= 0 && /[\w$]/.test(source[cursor])) cursor--;
|
|
1430
|
+
return REGEX_PREFIX_KEYWORDS.has(source.slice(cursor + 1, end));
|
|
1431
|
+
}
|
|
1432
|
+
function regexEnd(source, start) {
|
|
1433
|
+
let cursor = start + 1;
|
|
1434
|
+
let inCharacterClass = false;
|
|
1435
|
+
while (cursor < source.length) {
|
|
1436
|
+
const character = source[cursor];
|
|
1437
|
+
if (character === "\\") cursor += 2;
|
|
1438
|
+
else if (character === "[") {
|
|
1439
|
+
inCharacterClass = true;
|
|
1440
|
+
cursor++;
|
|
1441
|
+
} else if (character === "]") {
|
|
1442
|
+
inCharacterClass = false;
|
|
1443
|
+
cursor++;
|
|
1444
|
+
} else if (character === "/" && !inCharacterClass) {
|
|
1445
|
+
cursor++;
|
|
1446
|
+
while (/[A-Z]/i.test(source[cursor] ?? "")) cursor++;
|
|
1447
|
+
break;
|
|
1448
|
+
} else cursor++;
|
|
1449
|
+
}
|
|
1450
|
+
return cursor;
|
|
1451
|
+
}
|
|
1452
|
+
function templateEnd(source, start) {
|
|
1453
|
+
let cursor = start + 1;
|
|
1454
|
+
while (cursor < source.length) {
|
|
1455
|
+
if (source[cursor] === "\\") cursor += 2;
|
|
1456
|
+
else if (source[cursor] === "`") return cursor + 1;
|
|
1457
|
+
else if (source[cursor] === "$" && source[cursor + 1] === "{") {
|
|
1458
|
+
cursor = findBalancedCodeEnd(source, cursor + 2);
|
|
1459
|
+
} else cursor++;
|
|
1460
|
+
}
|
|
1461
|
+
return source.length;
|
|
1462
|
+
}
|
|
1463
|
+
function lexicalRegionEnd(source, start) {
|
|
1464
|
+
const character = source[start];
|
|
1465
|
+
if (character === '"' || character === "'") return quotedEnd(source, start, character);
|
|
1466
|
+
if (character === "`") return templateEnd(source, start);
|
|
1467
|
+
if (character === "/" && (source[start + 1] === "/" || source[start + 1] === "*")) {
|
|
1468
|
+
return commentEnd(source, start);
|
|
1469
|
+
}
|
|
1470
|
+
if (character === "/" && isRegexStart(source, start)) return regexEnd(source, start);
|
|
1471
|
+
return start;
|
|
1472
|
+
}
|
|
1473
|
+
function findBalancedCodeEnd(source, bodyStart) {
|
|
1474
|
+
let depth = 1;
|
|
1475
|
+
let cursor = bodyStart;
|
|
1476
|
+
while (cursor < source.length) {
|
|
1477
|
+
const regionEnd = lexicalRegionEnd(source, cursor);
|
|
1478
|
+
if (regionEnd !== cursor) {
|
|
1479
|
+
cursor = regionEnd;
|
|
1480
|
+
continue;
|
|
1481
|
+
}
|
|
1482
|
+
if (source[cursor] === "{") depth++;
|
|
1483
|
+
else if (source[cursor] === "}" && --depth === 0) return cursor;
|
|
1484
|
+
cursor++;
|
|
1485
|
+
}
|
|
1486
|
+
return source.length;
|
|
1487
|
+
}
|
|
1488
|
+
function collectTemplateTokens(target, source, start) {
|
|
1489
|
+
let cursor = start + 1;
|
|
1490
|
+
let quasiStart = cursor;
|
|
1491
|
+
while (cursor < source.length) {
|
|
1492
|
+
if (source[cursor] === "\\") {
|
|
1493
|
+
cursor += 2;
|
|
1494
|
+
continue;
|
|
1495
|
+
}
|
|
1496
|
+
if (source[cursor] === "`") {
|
|
1497
|
+
collectClassTokens(target, decodeJavaScriptString(source.slice(quasiStart, cursor)));
|
|
1498
|
+
return cursor + 1;
|
|
1499
|
+
}
|
|
1500
|
+
if (source[cursor] === "$" && source[cursor + 1] === "{") {
|
|
1501
|
+
collectClassTokens(target, decodeJavaScriptString(source.slice(quasiStart, cursor)));
|
|
1502
|
+
const expressionEnd = findBalancedCodeEnd(source, cursor + 2);
|
|
1503
|
+
collectExpressionTokens(target, source.slice(cursor + 2, expressionEnd));
|
|
1504
|
+
cursor = expressionEnd + 1;
|
|
1505
|
+
quasiStart = cursor;
|
|
1506
|
+
continue;
|
|
1507
|
+
}
|
|
1508
|
+
cursor++;
|
|
1509
|
+
}
|
|
1510
|
+
collectClassTokens(target, decodeJavaScriptString(source.slice(quasiStart)));
|
|
1511
|
+
return source.length;
|
|
1512
|
+
}
|
|
1513
|
+
function collectExpressionTokens(target, expression) {
|
|
1514
|
+
let cursor = 0;
|
|
1515
|
+
let pendingLiteral = "";
|
|
1516
|
+
let previousLiteralEnd = -1;
|
|
1517
|
+
const flushPending = () => {
|
|
1518
|
+
if (pendingLiteral) collectClassTokens(target, pendingLiteral);
|
|
1519
|
+
pendingLiteral = "";
|
|
1520
|
+
};
|
|
1521
|
+
while (cursor < expression.length) {
|
|
1522
|
+
const character = expression[cursor];
|
|
1523
|
+
if (character === "/" && (expression[cursor + 1] === "/" || expression[cursor + 1] === "*")) {
|
|
1524
|
+
cursor = commentEnd(expression, cursor);
|
|
1525
|
+
continue;
|
|
1526
|
+
}
|
|
1527
|
+
if (character === "/" && isRegexStart(expression, cursor)) {
|
|
1528
|
+
cursor = regexEnd(expression, cursor);
|
|
1529
|
+
continue;
|
|
1530
|
+
}
|
|
1531
|
+
if (character === "`") {
|
|
1532
|
+
flushPending();
|
|
1533
|
+
cursor = collectTemplateTokens(target, expression, cursor);
|
|
1534
|
+
previousLiteralEnd = -1;
|
|
1535
|
+
continue;
|
|
1286
1536
|
}
|
|
1287
|
-
|
|
1288
|
-
let matchEnd = -1;
|
|
1289
|
-
let cursor = end;
|
|
1290
|
-
while (cursor < block.length && /\s/.test(block[cursor])) {
|
|
1537
|
+
if (character !== '"' && character !== "'") {
|
|
1291
1538
|
cursor++;
|
|
1539
|
+
continue;
|
|
1292
1540
|
}
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1541
|
+
const end = quotedEnd(expression, cursor, character);
|
|
1542
|
+
const decoded = decodeJavaScriptString(expression.slice(cursor + 1, end - 1));
|
|
1543
|
+
const joinsPrevious = previousLiteralEnd >= 0 && expression.slice(previousLiteralEnd, cursor).trim() === "+";
|
|
1544
|
+
if (!joinsPrevious) flushPending();
|
|
1545
|
+
pendingLiteral += decoded;
|
|
1546
|
+
previousLiteralEnd = end;
|
|
1547
|
+
cursor = end;
|
|
1548
|
+
}
|
|
1549
|
+
flushPending();
|
|
1550
|
+
}
|
|
1551
|
+
function triviaEnd(source, start) {
|
|
1552
|
+
let cursor = start;
|
|
1553
|
+
while (cursor < source.length) {
|
|
1554
|
+
if (/\s/.test(source[cursor])) cursor++;
|
|
1555
|
+
else if (source[cursor] === "/" && (source[cursor + 1] === "/" || source[cursor + 1] === "*")) {
|
|
1556
|
+
cursor = commentEnd(source, cursor);
|
|
1557
|
+
} else break;
|
|
1558
|
+
}
|
|
1559
|
+
return cursor;
|
|
1560
|
+
}
|
|
1561
|
+
function propertyExpressionEnd(source, start) {
|
|
1562
|
+
let cursor = start;
|
|
1563
|
+
let parenDepth = 0;
|
|
1564
|
+
let bracketDepth = 0;
|
|
1565
|
+
let braceDepth = 0;
|
|
1566
|
+
while (cursor < source.length) {
|
|
1567
|
+
const regionEnd = lexicalRegionEnd(source, cursor);
|
|
1568
|
+
if (regionEnd !== cursor) {
|
|
1569
|
+
cursor = regionEnd;
|
|
1570
|
+
continue;
|
|
1299
1571
|
}
|
|
1300
|
-
|
|
1301
|
-
|
|
1572
|
+
const character = source[cursor];
|
|
1573
|
+
if (character === "(") parenDepth++;
|
|
1574
|
+
else if (character === ")") parenDepth--;
|
|
1575
|
+
else if (character === "[") bracketDepth++;
|
|
1576
|
+
else if (character === "]") bracketDepth--;
|
|
1577
|
+
else if (character === "{") braceDepth++;
|
|
1578
|
+
else if (character === "}" && braceDepth > 0) braceDepth--;
|
|
1579
|
+
else if ((character === "," || character === ";" || character === "}") && parenDepth === 0 && bracketDepth === 0 && braceDepth === 0)
|
|
1580
|
+
return cursor;
|
|
1581
|
+
cursor++;
|
|
1582
|
+
}
|
|
1583
|
+
return source.length;
|
|
1584
|
+
}
|
|
1585
|
+
function isClassSink(source, start, end) {
|
|
1586
|
+
const name = source.slice(start, end);
|
|
1587
|
+
if (name !== "class" && name !== "className") return false;
|
|
1588
|
+
let previous = start - 1;
|
|
1589
|
+
while (previous >= 0 && /\s/.test(source[previous])) previous--;
|
|
1590
|
+
return source[previous] !== "." && source[previous] !== "-";
|
|
1591
|
+
}
|
|
1592
|
+
function collectClassDirective(target, source, sinkStart, valueStart) {
|
|
1593
|
+
if (!/[\w$-]/.test(source[valueStart] ?? "")) return null;
|
|
1594
|
+
let directiveEnd = valueStart;
|
|
1595
|
+
while (/[\w$-]/.test(source[directiveEnd] ?? "")) directiveEnd++;
|
|
1596
|
+
const equals = triviaEnd(source, directiveEnd);
|
|
1597
|
+
if (source[equals] !== "=") {
|
|
1598
|
+
const insideMarkupTag = source.lastIndexOf("<", sinkStart) > source.lastIndexOf(">", sinkStart);
|
|
1599
|
+
const next = source[equals] ?? "";
|
|
1600
|
+
const continuesMarkupTag = next === "/" || next === ">" || next === "{" || /[A-Z_:]/i.test(next);
|
|
1601
|
+
if (!insideMarkupTag || !continuesMarkupTag) return null;
|
|
1602
|
+
collectClassTokens(target, source.slice(valueStart, directiveEnd));
|
|
1603
|
+
return directiveEnd;
|
|
1604
|
+
}
|
|
1605
|
+
const directive = source.slice(valueStart, directiveEnd);
|
|
1606
|
+
const directiveValueStart = triviaEnd(source, equals + 1);
|
|
1607
|
+
const directiveQuote = source[directiveValueStart];
|
|
1608
|
+
if (directive !== "list") collectClassTokens(target, directive);
|
|
1609
|
+
if (directiveQuote === "{") {
|
|
1610
|
+
const end = findBalancedCodeEnd(source, directiveValueStart + 1);
|
|
1611
|
+
if (directive === "list") {
|
|
1612
|
+
collectExpressionTokens(target, source.slice(directiveValueStart + 1, end));
|
|
1613
|
+
}
|
|
1614
|
+
return end + 1;
|
|
1615
|
+
}
|
|
1616
|
+
if (directive === "list" && (directiveQuote === '"' || directiveQuote === "'")) {
|
|
1617
|
+
const end = quotedEnd(source, directiveValueStart, directiveQuote);
|
|
1618
|
+
collectExpressionTokens(target, source.slice(directiveValueStart, end));
|
|
1619
|
+
return end;
|
|
1620
|
+
}
|
|
1621
|
+
return directiveValueStart;
|
|
1622
|
+
}
|
|
1623
|
+
function collectClassSink(target, source, start, nameEnd) {
|
|
1624
|
+
const operatorStart = triviaEnd(source, nameEnd);
|
|
1625
|
+
const operator = source[operatorStart];
|
|
1626
|
+
if (operator !== "=" && operator !== ":") return nameEnd;
|
|
1627
|
+
const valueStart = triviaEnd(source, operatorStart + 1);
|
|
1628
|
+
const quote = source[valueStart];
|
|
1629
|
+
const vueBinding = operator === "=" && source.slice(Math.max(0, start - 1), start) === ":";
|
|
1630
|
+
if (operator === ":" && valueStart === operatorStart + 1) {
|
|
1631
|
+
const directiveEnd = collectClassDirective(target, source, start, valueStart);
|
|
1632
|
+
if (directiveEnd !== null) return directiveEnd;
|
|
1633
|
+
}
|
|
1634
|
+
if (quote === '"' || quote === "'") {
|
|
1635
|
+
const end = quotedEnd(source, valueStart, quote);
|
|
1636
|
+
const value = source.slice(valueStart + 1, end - 1);
|
|
1637
|
+
if (vueBinding) collectExpressionTokens(target, decodeAttributeWhitespace(value));
|
|
1638
|
+
else collectClassTokens(target, decodeAttributeWhitespace(value));
|
|
1639
|
+
return end;
|
|
1640
|
+
}
|
|
1641
|
+
if (operator === "=" && quote === "{") {
|
|
1642
|
+
const end = findBalancedCodeEnd(source, valueStart + 1);
|
|
1643
|
+
collectExpressionTokens(target, source.slice(valueStart + 1, end));
|
|
1644
|
+
return end + 1;
|
|
1645
|
+
}
|
|
1646
|
+
if (operator === ":") {
|
|
1647
|
+
const end = propertyExpressionEnd(source, valueStart);
|
|
1648
|
+
collectExpressionTokens(target, source.slice(valueStart, end));
|
|
1649
|
+
return end;
|
|
1650
|
+
}
|
|
1651
|
+
return valueStart;
|
|
1652
|
+
}
|
|
1653
|
+
function collectAuthoredClassNames(source) {
|
|
1654
|
+
const classes = /* @__PURE__ */ new Set();
|
|
1655
|
+
let cursor = 0;
|
|
1656
|
+
while (cursor < source.length) {
|
|
1657
|
+
if (source[cursor] === '"' || source[cursor] === "'") {
|
|
1658
|
+
const keyEnd = quotedEnd(source, cursor, source[cursor]);
|
|
1659
|
+
const key = decodeJavaScriptString(source.slice(cursor + 1, keyEnd - 1));
|
|
1660
|
+
cursor = key === "class" || key === "className" ? collectClassSink(classes, source, cursor, keyEnd) : keyEnd;
|
|
1661
|
+
continue;
|
|
1302
1662
|
}
|
|
1303
|
-
|
|
1304
|
-
|
|
1663
|
+
const regionEnd = lexicalRegionEnd(source, cursor);
|
|
1664
|
+
if (regionEnd !== cursor) {
|
|
1665
|
+
cursor = regionEnd;
|
|
1305
1666
|
continue;
|
|
1306
1667
|
}
|
|
1307
|
-
|
|
1308
|
-
|
|
1668
|
+
if (!/[A-Z_$]/i.test(source[cursor])) {
|
|
1669
|
+
cursor++;
|
|
1670
|
+
continue;
|
|
1671
|
+
}
|
|
1672
|
+
let nameEnd = cursor + 1;
|
|
1673
|
+
while (/[\w$]/.test(source[nameEnd] ?? "")) nameEnd++;
|
|
1674
|
+
cursor = isClassSink(source, cursor, nameEnd) ? collectClassSink(classes, source, cursor, nameEnd) : nameEnd;
|
|
1309
1675
|
}
|
|
1310
|
-
return
|
|
1676
|
+
return classes;
|
|
1311
1677
|
}
|
|
1312
1678
|
|
|
1313
1679
|
const GLOB_MAGIC_RE = /[*?[\]{}]/;
|
|
1314
1680
|
const DEFAULT_IGNORED_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git", ".next", ".turbo", "dist", "build"]);
|
|
1315
1681
|
function normalizeFileId(id) {
|
|
1316
|
-
return id.split(/[?#]/, 1)[0]
|
|
1682
|
+
return normalizePathSeparators(id.split(/[?#]/, 1)[0]);
|
|
1317
1683
|
}
|
|
1318
1684
|
function normalizeRoot(rootDir) {
|
|
1319
|
-
return path.resolve(rootDir)
|
|
1685
|
+
return normalizePathSeparators(path.resolve(rootDir));
|
|
1320
1686
|
}
|
|
1321
1687
|
function hasGlobMagic(pattern) {
|
|
1322
1688
|
return GLOB_MAGIC_RE.test(pattern);
|
|
@@ -1325,7 +1691,7 @@ function escapeRegExp(ch) {
|
|
|
1325
1691
|
return /[|\\{}()[\]^$+?.]/.test(ch) ? `\\${ch}` : ch;
|
|
1326
1692
|
}
|
|
1327
1693
|
function globToRegExp(pattern) {
|
|
1328
|
-
const normalized = pattern
|
|
1694
|
+
const normalized = normalizePathSeparators(pattern);
|
|
1329
1695
|
let out = "^";
|
|
1330
1696
|
for (let i = 0; i < normalized.length; i++) {
|
|
1331
1697
|
const ch = normalized[i];
|
|
@@ -1348,7 +1714,7 @@ function globToRegExp(pattern) {
|
|
|
1348
1714
|
function relativeToRoot(file, rootDir) {
|
|
1349
1715
|
const root = normalizeRoot(rootDir);
|
|
1350
1716
|
const normalizedFile = normalizeFileId(file);
|
|
1351
|
-
return path.posix.relative(root, normalizedFile)
|
|
1717
|
+
return normalizePathSeparators(path.posix.relative(root, normalizedFile));
|
|
1352
1718
|
}
|
|
1353
1719
|
function matchesPattern(id, pattern, rootDir) {
|
|
1354
1720
|
const file = normalizeFileId(id);
|
|
@@ -1357,7 +1723,7 @@ function matchesPattern(id, pattern, rootDir) {
|
|
|
1357
1723
|
pattern.lastIndex = 0;
|
|
1358
1724
|
return pattern.test(file) || pattern.test(relative);
|
|
1359
1725
|
}
|
|
1360
|
-
const normalizedPattern = pattern
|
|
1726
|
+
const normalizedPattern = normalizePathSeparators(pattern);
|
|
1361
1727
|
if (hasGlobMagic(normalizedPattern)) {
|
|
1362
1728
|
const re = globToRegExp(normalizedPattern);
|
|
1363
1729
|
return re.test(file) || re.test(relative);
|
|
@@ -1372,27 +1738,36 @@ function matchesAnyPattern(id, patterns, rootDir) {
|
|
|
1372
1738
|
const list = Array.isArray(patterns) ? patterns : [patterns];
|
|
1373
1739
|
return list.some((pattern) => matchesPattern(id, pattern, rootDir));
|
|
1374
1740
|
}
|
|
1741
|
+
function collectDirectoryFiles(dir, files) {
|
|
1742
|
+
let entries;
|
|
1743
|
+
try {
|
|
1744
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
1745
|
+
} catch {
|
|
1746
|
+
return;
|
|
1747
|
+
}
|
|
1748
|
+
for (const entry of entries) {
|
|
1749
|
+
const full = path.join(dir, entry.name);
|
|
1750
|
+
if (entry.isDirectory()) {
|
|
1751
|
+
if (!DEFAULT_IGNORED_DIRS.has(entry.name) && !entry.name.startsWith(".")) {
|
|
1752
|
+
collectDirectoryFiles(full, files);
|
|
1753
|
+
}
|
|
1754
|
+
} else {
|
|
1755
|
+
files.add(path.resolve(full));
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
}
|
|
1759
|
+
function isExpandedPatternMatch(file, patterns, rootDir) {
|
|
1760
|
+
return patterns.some((pattern) => {
|
|
1761
|
+
if (hasGlobMagic(pattern)) {
|
|
1762
|
+
return matchesPattern(file, pattern, rootDir);
|
|
1763
|
+
}
|
|
1764
|
+
const resolved = path.isAbsolute(pattern) ? pattern : path.join(rootDir, pattern);
|
|
1765
|
+
return normalizeFileId(path.resolve(resolved)) === normalizeFileId(file);
|
|
1766
|
+
});
|
|
1767
|
+
}
|
|
1375
1768
|
function expandFilePatterns(rootDir, patterns) {
|
|
1376
1769
|
const list = Array.isArray(patterns) ? patterns : [patterns];
|
|
1377
1770
|
const files = /* @__PURE__ */ new Set();
|
|
1378
|
-
const walk = (dir) => {
|
|
1379
|
-
let entries;
|
|
1380
|
-
try {
|
|
1381
|
-
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
1382
|
-
} catch {
|
|
1383
|
-
return;
|
|
1384
|
-
}
|
|
1385
|
-
for (const entry of entries) {
|
|
1386
|
-
const full = path.join(dir, entry.name);
|
|
1387
|
-
if (entry.isDirectory()) {
|
|
1388
|
-
if (!DEFAULT_IGNORED_DIRS.has(entry.name) && !entry.name.startsWith(".")) {
|
|
1389
|
-
walk(full);
|
|
1390
|
-
}
|
|
1391
|
-
} else {
|
|
1392
|
-
files.add(path.resolve(full));
|
|
1393
|
-
}
|
|
1394
|
-
}
|
|
1395
|
-
};
|
|
1396
1771
|
let needsWalk = false;
|
|
1397
1772
|
for (const pattern of list) {
|
|
1398
1773
|
const resolved = path.isAbsolute(pattern) ? pattern : path.join(rootDir, pattern);
|
|
@@ -1405,30 +1780,25 @@ function expandFilePatterns(rootDir, patterns) {
|
|
|
1405
1780
|
}
|
|
1406
1781
|
}
|
|
1407
1782
|
if (needsWalk) {
|
|
1408
|
-
|
|
1783
|
+
collectDirectoryFiles(rootDir, files);
|
|
1409
1784
|
for (const file of Array.from(files)) {
|
|
1410
|
-
if (!list
|
|
1411
|
-
(
|
|
1412
|
-
)) {
|
|
1413
|
-
const isLiteralMatch = list.some((pattern) => {
|
|
1414
|
-
if (hasGlobMagic(pattern)) {
|
|
1415
|
-
return false;
|
|
1416
|
-
}
|
|
1417
|
-
const resolved = path.isAbsolute(pattern) ? pattern : path.join(rootDir, pattern);
|
|
1418
|
-
return normalizeFileId(path.resolve(resolved)) === normalizeFileId(file);
|
|
1419
|
-
});
|
|
1420
|
-
if (!isLiteralMatch) {
|
|
1421
|
-
files.delete(file);
|
|
1422
|
-
}
|
|
1785
|
+
if (!isExpandedPatternMatch(file, list, rootDir)) {
|
|
1786
|
+
files.delete(file);
|
|
1423
1787
|
}
|
|
1424
1788
|
}
|
|
1425
1789
|
}
|
|
1426
1790
|
return sortStrings(files);
|
|
1427
1791
|
}
|
|
1428
1792
|
|
|
1793
|
+
const LINE_SEPARATOR$1 = String.fromCodePoint(8232);
|
|
1794
|
+
const PARAGRAPH_SEPARATOR$1 = String.fromCodePoint(8233);
|
|
1429
1795
|
function safeJsonForScriptTag(value, prettyPrint = false) {
|
|
1430
1796
|
const json = prettyPrint ? JSON.stringify(value, null, 2) : JSON.stringify(value);
|
|
1431
|
-
|
|
1797
|
+
let escaped = replaceEveryLiteral(json, "<", unicodeEscape("003C"));
|
|
1798
|
+
escaped = replaceEveryLiteral(escaped, ">", unicodeEscape("003E"));
|
|
1799
|
+
escaped = replaceEveryLiteral(escaped, "&", unicodeEscape("0026"));
|
|
1800
|
+
escaped = replaceEveryLiteral(escaped, LINE_SEPARATOR$1, unicodeEscape("2028"));
|
|
1801
|
+
return replaceEveryLiteral(escaped, PARAGRAPH_SEPARATOR$1, unicodeEscape("2029"));
|
|
1432
1802
|
}
|
|
1433
1803
|
function injectHtmlOpeningAttr(html, attr) {
|
|
1434
1804
|
const lower = html.toLowerCase();
|
|
@@ -1560,11 +1930,17 @@ function injectRecoveryManifest(html, manifest) {
|
|
|
1560
1930
|
return html + scriptTag;
|
|
1561
1931
|
}
|
|
1562
1932
|
|
|
1933
|
+
const LINE_SEPARATOR = String.fromCodePoint(8232);
|
|
1934
|
+
const PARAGRAPH_SEPARATOR = String.fromCodePoint(8233);
|
|
1563
1935
|
function escapeJsonForInlineScript(json) {
|
|
1564
|
-
|
|
1936
|
+
let escaped = replaceEveryLiteral(json, "`", unicodeEscape("0060"));
|
|
1937
|
+
escaped = replaceEveryLiteral(escaped, "$", unicodeEscape("0024"));
|
|
1938
|
+
escaped = replaceEveryLiteral(escaped, "<", unicodeEscape("003c"));
|
|
1939
|
+
escaped = replaceEveryLiteral(escaped, LINE_SEPARATOR, unicodeEscape("2028"));
|
|
1940
|
+
return replaceEveryLiteral(escaped, PARAGRAPH_SEPARATOR, unicodeEscape("2029"));
|
|
1565
1941
|
}
|
|
1566
1942
|
function escapeForDoubleQuotedString(value) {
|
|
1567
|
-
return value
|
|
1943
|
+
return escapeDoubleQuotedString(value);
|
|
1568
1944
|
}
|
|
1569
1945
|
|
|
1570
1946
|
function isParserMode(value) {
|
|
@@ -1611,15 +1987,13 @@ function isSameFileVersion(before, after) {
|
|
|
1611
1987
|
return before.dev === after.dev && before.ino === after.ino && before.size === after.size && before.mtimeNs === after.mtimeNs && before.ctimeNs === after.ctimeNs;
|
|
1612
1988
|
}
|
|
1613
1989
|
|
|
1614
|
-
function escapeTsString(value) {
|
|
1615
|
-
return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/\r/g, "\\r").replace(/\n/g, "\\n");
|
|
1616
|
-
}
|
|
1617
1990
|
function generateThemeDts(opts) {
|
|
1618
1991
|
const { theme, sourceFiles } = opts;
|
|
1619
1992
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
1620
|
-
const
|
|
1621
|
-
const
|
|
1622
|
-
const
|
|
1993
|
+
const withoutCarriageReturns = replaceEveryLiteral(sourceFiles.join(", "), "\r", " ");
|
|
1994
|
+
const sources = replaceEveryLiteral(withoutCarriageReturns, "\n", " ");
|
|
1995
|
+
const toUnion = (tokens) => tokens.map((t) => `'${escapeSingleQuotedString(t)}'`).join(" | ");
|
|
1996
|
+
const quoteKey = (key) => /^[a-z_$][\w$]*$/i.test(key) ? key : `'${escapeSingleQuotedString(key)}'`;
|
|
1623
1997
|
const entries = [];
|
|
1624
1998
|
if (theme.colors.length > 0) {
|
|
1625
1999
|
entries.push(` colors: ${toUnion(theme.colors)};`);
|
|
@@ -1757,6 +2131,15 @@ function createThemeGroupsModule(tokens) {
|
|
|
1757
2131
|
].join("\n");
|
|
1758
2132
|
}
|
|
1759
2133
|
|
|
2134
|
+
function registerWebpackAssetProcessor(compiler, processAssets) {
|
|
2135
|
+
compiler.hooks.compilation.tap("csszyx:post", (compilation) => {
|
|
2136
|
+
const stage = compiler.webpack?.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE || compilation.constructor.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE;
|
|
2137
|
+
compilation.hooks.processAssets.tap(
|
|
2138
|
+
{ name: "csszyx:post", stage: stage || 400 },
|
|
2139
|
+
(assets) => processAssets(assets, compilation, compiler)
|
|
2140
|
+
);
|
|
2141
|
+
});
|
|
2142
|
+
}
|
|
1760
2143
|
const CHECKSUM_PLACEHOLDER = "___CSSZYX_CHECKSUM___";
|
|
1761
2144
|
const MANGLE_MAP_PLACEHOLDER = "___CSSZYX_MANGLE_MAP___";
|
|
1762
2145
|
const VAR_MANGLE_MAP_PLACEHOLDER = "___CSSZYX_VAR_MANGLE_MAP___";
|
|
@@ -1768,7 +2151,6 @@ const TRANSFORM_MEMORY_CACHE_MAX_CODE_CHARS = 32e6;
|
|
|
1768
2151
|
const MAX_SAFELIST_CLASSES = 1e5;
|
|
1769
2152
|
const DEFAULT_VAR_MANGLE_MAP_MAX_BYTES = 100 * 1024;
|
|
1770
2153
|
const GLOBAL_VAR_ALIAS_MAP_OWNER = "\0csszyx:global-var-aliases";
|
|
1771
|
-
const DIRECTIVE_PROLOGUE_PREFIX_RE = /^((?:\s|\/\/[^\n]*\n|\/\*(?:[^*]|\*(?!\/))*\*\/)*)(['"]use (?:client|server)['"];?\s*)/;
|
|
1772
2154
|
function findOpeningTag(source, tag) {
|
|
1773
2155
|
const lower = source.toLowerCase();
|
|
1774
2156
|
const marker = `<${tag}`;
|
|
@@ -1841,10 +2223,10 @@ function stripCssBlockComments(code) {
|
|
|
1841
2223
|
let i = 0;
|
|
1842
2224
|
const n = code.length;
|
|
1843
2225
|
while (i < n) {
|
|
1844
|
-
if (code.
|
|
2226
|
+
if (code.codePointAt(i) === SLASH && code.codePointAt(i + 1) === STAR) {
|
|
1845
2227
|
out += code.slice(last, i);
|
|
1846
2228
|
i += 2;
|
|
1847
|
-
while (i < n && !(code.
|
|
2229
|
+
while (i < n && !(code.codePointAt(i) === STAR && code.codePointAt(i + 1) === SLASH)) {
|
|
1848
2230
|
i++;
|
|
1849
2231
|
}
|
|
1850
2232
|
i += 2;
|
|
@@ -1950,9 +2332,17 @@ function shouldEmitWarning(quiet, devOnly, isProduction) {
|
|
|
1950
2332
|
return true;
|
|
1951
2333
|
}
|
|
1952
2334
|
function normalizeForMatch(p) {
|
|
1953
|
-
const n = p
|
|
2335
|
+
const n = normalizePathSeparators(p);
|
|
1954
2336
|
return n.length > 1 && n.endsWith("/") ? n.slice(0, -1) : n;
|
|
1955
2337
|
}
|
|
2338
|
+
function findJsxExpressionEnd(code, bodyStart) {
|
|
2339
|
+
return findBalancedCodeEnd(code, bodyStart);
|
|
2340
|
+
}
|
|
2341
|
+
function warnPrescanBudgetSkip(filePath) {
|
|
2342
|
+
console.warn(
|
|
2343
|
+
`[csszyx] prescan skipped ${filePath}: the file exceeds the AST node budget, so NONE of its classes reached the safelist and their CSS will not be generated. Raise \`build.astBudgetLimit\` in the csszyx plugin options, or split the file.`
|
|
2344
|
+
);
|
|
2345
|
+
}
|
|
1956
2346
|
function resolveCompileSourceDirs(root, sources, realpathDir = (p) => {
|
|
1957
2347
|
try {
|
|
1958
2348
|
const real = fs.realpathSync(p);
|
|
@@ -2005,6 +2395,9 @@ function fileMayContainSafelistableSz(content) {
|
|
|
2005
2395
|
// engine-parity harness caught its classes missing on all engines.
|
|
2006
2396
|
content.includes("dynamic(");
|
|
2007
2397
|
}
|
|
2398
|
+
function mangleEligibleClasses(ownedClasses, authoredClasses) {
|
|
2399
|
+
return sortStrings$1([...ownedClasses].filter((className) => !authoredClasses.has(className)));
|
|
2400
|
+
}
|
|
2008
2401
|
function isPackagesSkippedSource(id, sourceDirs = []) {
|
|
2009
2402
|
const p = normalizeForMatch(id);
|
|
2010
2403
|
if (p.includes("node_modules")) {
|
|
@@ -2025,8 +2418,8 @@ ${list}
|
|
|
2025
2418
|
Add the package directory to \`compileSources\` (or move the file out of packages/) \u2014 otherwise their \`sz\` produces no CSS.`;
|
|
2026
2419
|
}
|
|
2027
2420
|
function computeSafelistRelPath(rootDir, safelistFilename, cssId) {
|
|
2028
|
-
const safelistPath = path.join(rootDir, safelistFilename)
|
|
2029
|
-
const cssDir = path.dirname(cssId)
|
|
2421
|
+
const safelistPath = normalizePathSeparators(path.join(rootDir, safelistFilename));
|
|
2422
|
+
const cssDir = normalizePathSeparators(path.dirname(cssId));
|
|
2030
2423
|
let relPath = path.posix.relative(cssDir, safelistPath);
|
|
2031
2424
|
if (!relPath.startsWith(".")) {
|
|
2032
2425
|
relPath = `./${relPath}`;
|
|
@@ -2200,7 +2593,10 @@ function normalizeGlobalVarAliasesForCache(aliases) {
|
|
|
2200
2593
|
if (!aliases) {
|
|
2201
2594
|
return [];
|
|
2202
2595
|
}
|
|
2203
|
-
|
|
2596
|
+
let entries;
|
|
2597
|
+
if (aliases instanceof Map) entries = aliases.entries();
|
|
2598
|
+
else if (Array.isArray(aliases)) entries = aliases;
|
|
2599
|
+
else entries = Object.entries(aliases);
|
|
2204
2600
|
const normalized = /* @__PURE__ */ new Map();
|
|
2205
2601
|
for (const [original, alias] of entries) {
|
|
2206
2602
|
if (original.startsWith("--") && alias.startsWith("--")) {
|
|
@@ -2405,7 +2801,7 @@ function findPackageVersionFromFile(file, fallback) {
|
|
|
2405
2801
|
}
|
|
2406
2802
|
}
|
|
2407
2803
|
function normalizeSourceFilename(filename) {
|
|
2408
|
-
return filename
|
|
2804
|
+
return normalizePathSeparators(filename);
|
|
2409
2805
|
}
|
|
2410
2806
|
const SCRIPT_ID_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx"];
|
|
2411
2807
|
const SOURCE_MODULE_EXTENSIONS = [...SCRIPT_ID_EXTENSIONS, ".cts", ".mts", ".cjs", ".mjs"];
|
|
@@ -2413,11 +2809,26 @@ function matchesScriptExtension(id, extensions) {
|
|
|
2413
2809
|
return extensions.some((ext) => id.endsWith(ext) || id.includes(`${ext}?`));
|
|
2414
2810
|
}
|
|
2415
2811
|
function insertRuntimeImport(code, importStmt) {
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2812
|
+
return insertAfterUseDirective(code, importStmt);
|
|
2813
|
+
}
|
|
2814
|
+
function scanClassExpression(source, from) {
|
|
2815
|
+
let depth = 0;
|
|
2816
|
+
let index = from;
|
|
2817
|
+
while (index < source.length) {
|
|
2818
|
+
const char = source[index];
|
|
2819
|
+
if (char === "(" || char === "[") {
|
|
2820
|
+
depth++;
|
|
2821
|
+
} else if (char === ")" || char === "]") {
|
|
2822
|
+
if (depth === 0) {
|
|
2823
|
+
break;
|
|
2824
|
+
}
|
|
2825
|
+
depth--;
|
|
2826
|
+
} else if (depth === 0 && (char === "," || char === ";" || char === "\n" || char === "}")) {
|
|
2827
|
+
break;
|
|
2828
|
+
}
|
|
2829
|
+
index++;
|
|
2419
2830
|
}
|
|
2420
|
-
return
|
|
2831
|
+
return index;
|
|
2421
2832
|
}
|
|
2422
2833
|
function mangleCodeClassesSync(code, mangleMap) {
|
|
2423
2834
|
function mangleClassString(classString) {
|
|
@@ -2425,6 +2836,58 @@ function mangleCodeClassesSync(code, mangleMap) {
|
|
|
2425
2836
|
return mangleMap[cls.replace(/\\(.)/g, "$1")] || cls;
|
|
2426
2837
|
}).join(" ");
|
|
2427
2838
|
}
|
|
2839
|
+
function mangleClassTemplate(fullMatch, templateContent) {
|
|
2840
|
+
let changed = false;
|
|
2841
|
+
let output = "";
|
|
2842
|
+
let cursor = 0;
|
|
2843
|
+
while (cursor < templateContent.length) {
|
|
2844
|
+
const interpolationStart = templateContent.indexOf("${", cursor);
|
|
2845
|
+
const quasiEnd = interpolationStart === -1 ? templateContent.length : interpolationStart;
|
|
2846
|
+
const quasi = mangleTemplateQuasi(templateContent.slice(cursor, quasiEnd));
|
|
2847
|
+
output += quasi.value;
|
|
2848
|
+
changed ||= quasi.changed;
|
|
2849
|
+
if (interpolationStart === -1) break;
|
|
2850
|
+
const interpolationEnd = findTemplateInterpolationEnd(
|
|
2851
|
+
templateContent,
|
|
2852
|
+
interpolationStart + 2
|
|
2853
|
+
);
|
|
2854
|
+
const inner = templateContent.slice(interpolationStart + 2, interpolationEnd - 1);
|
|
2855
|
+
const interpolation = mangleTemplateInterpolation(inner);
|
|
2856
|
+
output += `\${${interpolation.value}}`;
|
|
2857
|
+
changed ||= interpolation.changed;
|
|
2858
|
+
cursor = interpolationEnd;
|
|
2859
|
+
}
|
|
2860
|
+
return changed ? `className:\`${output}\`` : fullMatch;
|
|
2861
|
+
}
|
|
2862
|
+
function mangleTemplateQuasi(quasi) {
|
|
2863
|
+
const trimmed = quasi.trim();
|
|
2864
|
+
if (!trimmed) return { value: quasi, changed: false };
|
|
2865
|
+
const mangled = mangleClassString(trimmed);
|
|
2866
|
+
return {
|
|
2867
|
+
value: mangled === trimmed ? quasi : quasi.replace(trimmed, mangled),
|
|
2868
|
+
changed: mangled !== trimmed
|
|
2869
|
+
};
|
|
2870
|
+
}
|
|
2871
|
+
function findTemplateInterpolationEnd(templateContent, bodyStart) {
|
|
2872
|
+
let depth = 0;
|
|
2873
|
+
for (let cursor = bodyStart; cursor < templateContent.length; cursor++) {
|
|
2874
|
+
if (templateContent[cursor] === "{") depth++;
|
|
2875
|
+
else if (templateContent[cursor] === "}" && depth-- === 0) return cursor + 1;
|
|
2876
|
+
}
|
|
2877
|
+
return templateContent.length;
|
|
2878
|
+
}
|
|
2879
|
+
function mangleTemplateInterpolation(inner) {
|
|
2880
|
+
let changed = false;
|
|
2881
|
+
const value = inner.replace(/"([^"]*)"/g, (quoted, classString) => {
|
|
2882
|
+
const parts = classString.split(/\s+/).filter(Boolean);
|
|
2883
|
+
if (parts.length === 0) return quoted;
|
|
2884
|
+
const mangled = parts.map((className) => mangleMap[className] || className).join(" ");
|
|
2885
|
+
if (mangled === classString) return quoted;
|
|
2886
|
+
changed = true;
|
|
2887
|
+
return `"${mangled}"`;
|
|
2888
|
+
});
|
|
2889
|
+
return { value, changed };
|
|
2890
|
+
}
|
|
2428
2891
|
let result = code.replace(/(?:class(?:Name)?|sz)[:=]\s*"((?:[^"\\]|\\.)*)"/g, (match, classes) => {
|
|
2429
2892
|
const mangled = mangleClassString(classes);
|
|
2430
2893
|
if (mangled === classes) {
|
|
@@ -2438,92 +2901,7 @@ function mangleCodeClassesSync(code, mangleMap) {
|
|
|
2438
2901
|
}
|
|
2439
2902
|
return match.replace(classes, mangled);
|
|
2440
2903
|
});
|
|
2441
|
-
result = result.replace(/className:\s*`([^`]+)`/g,
|
|
2442
|
-
let changed = false;
|
|
2443
|
-
let out = "";
|
|
2444
|
-
let i = 0;
|
|
2445
|
-
while (i < tplContent.length) {
|
|
2446
|
-
const interStart = tplContent.indexOf("${", i);
|
|
2447
|
-
if (interStart === -1) {
|
|
2448
|
-
const quasi2 = tplContent.slice(i);
|
|
2449
|
-
const trimmed2 = quasi2.trim();
|
|
2450
|
-
if (trimmed2) {
|
|
2451
|
-
const m = mangleClassString(trimmed2);
|
|
2452
|
-
if (m !== trimmed2) {
|
|
2453
|
-
changed = true;
|
|
2454
|
-
out += quasi2.replace(trimmed2, m);
|
|
2455
|
-
} else {
|
|
2456
|
-
out += quasi2;
|
|
2457
|
-
}
|
|
2458
|
-
} else {
|
|
2459
|
-
out += quasi2;
|
|
2460
|
-
}
|
|
2461
|
-
break;
|
|
2462
|
-
}
|
|
2463
|
-
const quasi = tplContent.slice(i, interStart);
|
|
2464
|
-
const trimmed = quasi.trim();
|
|
2465
|
-
if (trimmed) {
|
|
2466
|
-
const m = mangleClassString(trimmed);
|
|
2467
|
-
if (m !== trimmed) {
|
|
2468
|
-
changed = true;
|
|
2469
|
-
out += quasi.replace(trimmed, m);
|
|
2470
|
-
} else {
|
|
2471
|
-
out += quasi;
|
|
2472
|
-
}
|
|
2473
|
-
} else {
|
|
2474
|
-
out += quasi;
|
|
2475
|
-
}
|
|
2476
|
-
let j = interStart + 2;
|
|
2477
|
-
let depth = 0;
|
|
2478
|
-
while (j < tplContent.length) {
|
|
2479
|
-
if (tplContent[j] === "{") {
|
|
2480
|
-
depth++;
|
|
2481
|
-
} else if (tplContent[j] === "}") {
|
|
2482
|
-
if (depth === 0) {
|
|
2483
|
-
j++;
|
|
2484
|
-
break;
|
|
2485
|
-
}
|
|
2486
|
-
depth--;
|
|
2487
|
-
}
|
|
2488
|
-
j++;
|
|
2489
|
-
}
|
|
2490
|
-
const interInner = tplContent.slice(interStart + 2, j - 1);
|
|
2491
|
-
const mangledInner = interInner.replace(/"([^"]*)"/g, (qm, inner) => {
|
|
2492
|
-
const parts = inner.split(/\s+/).filter(Boolean);
|
|
2493
|
-
if (parts.length === 0) {
|
|
2494
|
-
return qm;
|
|
2495
|
-
}
|
|
2496
|
-
const m = parts.map((p) => mangleMap[p] || p).join(" ");
|
|
2497
|
-
if (m === inner) {
|
|
2498
|
-
return qm;
|
|
2499
|
-
}
|
|
2500
|
-
changed = true;
|
|
2501
|
-
return `"${m}"`;
|
|
2502
|
-
});
|
|
2503
|
-
out += `\${${mangledInner}}`;
|
|
2504
|
-
i = j;
|
|
2505
|
-
}
|
|
2506
|
-
return changed ? `className:\`${out}\`` : fullMatch;
|
|
2507
|
-
});
|
|
2508
|
-
function scanClassExpression(source, from) {
|
|
2509
|
-
let depth = 0;
|
|
2510
|
-
let j = from;
|
|
2511
|
-
while (j < source.length) {
|
|
2512
|
-
const ch = source[j];
|
|
2513
|
-
if (ch === "(" || ch === "[") {
|
|
2514
|
-
depth++;
|
|
2515
|
-
} else if (ch === ")" || ch === "]") {
|
|
2516
|
-
if (depth === 0) {
|
|
2517
|
-
break;
|
|
2518
|
-
}
|
|
2519
|
-
depth--;
|
|
2520
|
-
} else if (depth === 0 && (ch === "," || ch === ";" || ch === "\n" || ch === "}")) {
|
|
2521
|
-
break;
|
|
2522
|
-
}
|
|
2523
|
-
j++;
|
|
2524
|
-
}
|
|
2525
|
-
return j;
|
|
2526
|
-
}
|
|
2904
|
+
result = result.replace(/className:\s*`([^`]+)`/g, mangleClassTemplate);
|
|
2527
2905
|
function mangleTernaryClassStrings(expr) {
|
|
2528
2906
|
const qIdx = expr.indexOf("?");
|
|
2529
2907
|
if (qIdx === -1 || !expr.slice(qIdx).includes(":")) {
|
|
@@ -2731,7 +3109,12 @@ function createCsszyxPlugins(options = {}) {
|
|
|
2731
3109
|
}
|
|
2732
3110
|
if (!_loggedActiveParsers.has(parserMode)) {
|
|
2733
3111
|
_loggedActiveParsers.add(parserMode);
|
|
2734
|
-
|
|
3112
|
+
let detail = parserMode;
|
|
3113
|
+
if (parserDegraded) {
|
|
3114
|
+
detail = "oxc (degraded from default `rust`: no native binary for this platform)";
|
|
3115
|
+
} else if (parserMode === "rust") {
|
|
3116
|
+
detail = "rust (native engine)";
|
|
3117
|
+
}
|
|
2735
3118
|
console.warn(`[csszyx] active parser: ${detail}`);
|
|
2736
3119
|
}
|
|
2737
3120
|
}
|
|
@@ -2752,6 +3135,7 @@ function createCsszyxPlugins(options = {}) {
|
|
|
2752
3135
|
skipWarningEmitted: false,
|
|
2753
3136
|
classesCapped: false,
|
|
2754
3137
|
ownedClasses: /* @__PURE__ */ new Set(),
|
|
3138
|
+
authoredClasses: /* @__PURE__ */ new Set(),
|
|
2755
3139
|
mangleMap: {},
|
|
2756
3140
|
varMangleEntriesByFile: /* @__PURE__ */ new Map(),
|
|
2757
3141
|
varMangleMap: Object.fromEntries(earlyGlobalVarAliasEntries),
|
|
@@ -2868,53 +3252,76 @@ function createCsszyxPlugins(options = {}) {
|
|
|
2868
3252
|
}
|
|
2869
3253
|
const cacheKey = cacheEnabled ? createTransformCacheKey(cacheInput) : null;
|
|
2870
3254
|
if (cacheEnabled && cacheKey) {
|
|
2871
|
-
const
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
if (cached)
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
3255
|
+
const cached = findConfiguredTransformCacheEntry(
|
|
3256
|
+
cacheRoot,
|
|
3257
|
+
cacheInput,
|
|
3258
|
+
cacheKey,
|
|
3259
|
+
effectiveFilename,
|
|
3260
|
+
astBudget
|
|
3261
|
+
);
|
|
3262
|
+
if (cached) return cached;
|
|
3263
|
+
}
|
|
3264
|
+
const execution = runConfiguredParser(source, effectiveFilename, compilerOptions);
|
|
3265
|
+
if (cacheEnabled && cacheKey && execution.cacheable) {
|
|
3266
|
+
writeTransformCache(cacheRoot, cacheInput, execution.result, cacheKey);
|
|
3267
|
+
rememberTransformCacheEntry(cacheKey.key, execution.result);
|
|
3268
|
+
}
|
|
3269
|
+
return execution.result;
|
|
3270
|
+
}
|
|
3271
|
+
function findConfiguredTransformCacheEntry(cacheRoot, cacheInput, cacheKey, effectiveFilename, astBudget) {
|
|
3272
|
+
const memoryCached = transformMemoryCache.get(cacheKey.key);
|
|
3273
|
+
if (memoryCached) {
|
|
3274
|
+
transformMemoryCache.delete(cacheKey.key);
|
|
3275
|
+
transformMemoryCache.set(cacheKey.key, memoryCached);
|
|
3276
|
+
return memoryCached;
|
|
3277
|
+
}
|
|
3278
|
+
const diskCached = readTransformCache(cacheRoot, cacheInput, cacheKey);
|
|
3279
|
+
if (diskCached) {
|
|
3280
|
+
rememberTransformCacheEntry(cacheKey.key, diskCached);
|
|
3281
|
+
return diskCached;
|
|
3282
|
+
}
|
|
3283
|
+
if (astBudget !== void 0) return null;
|
|
3284
|
+
const handoff = prescanResultHandoff.get(effectiveFilename);
|
|
3285
|
+
if (!handoff) return null;
|
|
3286
|
+
prescanResultHandoff.delete(effectiveFilename);
|
|
3287
|
+
return handoff.inputSha256 === cacheKey.inputSha256 ? handoff.result : null;
|
|
3288
|
+
}
|
|
3289
|
+
function runConfiguredParser(source, effectiveFilename, compilerOptions) {
|
|
2893
3290
|
if (parserMode === "babel") {
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
try {
|
|
2899
|
-
result = transformOxc(source, effectiveFilename, compilerOptions);
|
|
2900
|
-
} catch (err) {
|
|
2901
|
-
result = transformSourceCode(source, effectiveFilename, compilerOptions);
|
|
2902
|
-
const reason = err instanceof Error ? err.message : String(err);
|
|
2903
|
-
result.diagnostics.push(
|
|
2904
|
-
`[csszyx] oxc parser fell back to Babel for ${effectiveFilename}: ${reason}`
|
|
2905
|
-
);
|
|
2906
|
-
if (!_babelFallbackFiles.has(effectiveFilename)) {
|
|
2907
|
-
_babelFallbackFiles.add(effectiveFilename);
|
|
2908
|
-
console.warn(
|
|
2909
|
-
`[csszyx] oxc parser fell back to Babel for ${effectiveFilename}: ${reason} (${_babelFallbackFiles.size} file(s) so far). Output is still correct; this usually means the file uses a syntax the oxc lane does not yet handle.`
|
|
2910
|
-
);
|
|
2911
|
-
}
|
|
2912
|
-
return result;
|
|
2913
|
-
}
|
|
3291
|
+
return {
|
|
3292
|
+
result: transformSourceCode(source, effectiveFilename, compilerOptions),
|
|
3293
|
+
cacheable: true
|
|
3294
|
+
};
|
|
2914
3295
|
}
|
|
2915
|
-
if (
|
|
2916
|
-
|
|
2917
|
-
|
|
3296
|
+
if (parserMode === "rust") {
|
|
3297
|
+
return {
|
|
3298
|
+
result: transformRust(source, effectiveFilename, compilerOptions),
|
|
3299
|
+
cacheable: true
|
|
3300
|
+
};
|
|
3301
|
+
}
|
|
3302
|
+
try {
|
|
3303
|
+
return {
|
|
3304
|
+
result: transformOxc(source, effectiveFilename, compilerOptions),
|
|
3305
|
+
cacheable: true
|
|
3306
|
+
};
|
|
3307
|
+
} catch (error) {
|
|
3308
|
+
return {
|
|
3309
|
+
result: runBabelFallback(source, effectiveFilename, compilerOptions, error),
|
|
3310
|
+
cacheable: false
|
|
3311
|
+
};
|
|
3312
|
+
}
|
|
3313
|
+
}
|
|
3314
|
+
function runBabelFallback(source, effectiveFilename, compilerOptions, error) {
|
|
3315
|
+
const result = transformSourceCode(source, effectiveFilename, compilerOptions);
|
|
3316
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
3317
|
+
result.diagnostics.push(
|
|
3318
|
+
`[csszyx] oxc parser fell back to Babel for ${effectiveFilename}: ${reason}`
|
|
3319
|
+
);
|
|
3320
|
+
if (!_babelFallbackFiles.has(effectiveFilename)) {
|
|
3321
|
+
_babelFallbackFiles.add(effectiveFilename);
|
|
3322
|
+
console.warn(
|
|
3323
|
+
`[csszyx] oxc parser fell back to Babel for ${effectiveFilename}: ${reason} (${_babelFallbackFiles.size} file(s) so far). Output is still correct; this usually means the file uses a syntax the oxc lane does not yet handle.`
|
|
3324
|
+
);
|
|
2918
3325
|
}
|
|
2919
3326
|
return result;
|
|
2920
3327
|
}
|
|
@@ -2953,11 +3360,19 @@ function createCsszyxPlugins(options = {}) {
|
|
|
2953
3360
|
const compilerOptions = createCompilerOptions(prescanAstBudget);
|
|
2954
3361
|
const cacheRoot = resolveTransformCacheDir(state.rootDir, options.build?.cacheDir);
|
|
2955
3362
|
const results = /* @__PURE__ */ new Map();
|
|
2956
|
-
|
|
2957
|
-
if (cacheEnabled) {
|
|
2958
|
-
evictTransformCacheOnce();
|
|
2959
|
-
}
|
|
3363
|
+
if (cacheEnabled) evictTransformCacheOnce();
|
|
2960
3364
|
ensureRustTransformAvailable();
|
|
3365
|
+
const misses = collectRustPrescanMisses(files, compilerOptions, cacheRoot, results);
|
|
3366
|
+
if (misses.length === 0) return orderPrescanResults(files, results);
|
|
3367
|
+
try {
|
|
3368
|
+
runRustPrescanBatch(misses, compilerOptions, cacheRoot, results);
|
|
3369
|
+
} catch {
|
|
3370
|
+
runRustPrescanFallback(misses, results);
|
|
3371
|
+
}
|
|
3372
|
+
return orderPrescanResults(files, results);
|
|
3373
|
+
}
|
|
3374
|
+
function collectRustPrescanMisses(files, compilerOptions, cacheRoot, results) {
|
|
3375
|
+
const misses = [];
|
|
2961
3376
|
for (const file of files) {
|
|
2962
3377
|
const effectiveFilename = normalizeSourceFilename(file.filePath);
|
|
2963
3378
|
const cacheInput = createConfiguredTransformCacheInput(
|
|
@@ -2966,79 +3381,54 @@ function createCsszyxPlugins(options = {}) {
|
|
|
2966
3381
|
compilerOptions
|
|
2967
3382
|
);
|
|
2968
3383
|
const cacheKey = cacheEnabled ? createTransformCacheKey(cacheInput) : null;
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
if (memoryCached) {
|
|
2972
|
-
transformMemoryCache.delete(cacheKey.key);
|
|
2973
|
-
transformMemoryCache.set(cacheKey.key, memoryCached);
|
|
2974
|
-
results.set(file.filePath, memoryCached);
|
|
2975
|
-
continue;
|
|
2976
|
-
}
|
|
2977
|
-
const cached = readTransformCache(cacheRoot, cacheInput, cacheKey);
|
|
2978
|
-
if (cached) {
|
|
2979
|
-
rememberTransformCacheEntry(cacheKey.key, cached);
|
|
2980
|
-
results.set(file.filePath, cached);
|
|
2981
|
-
continue;
|
|
2982
|
-
}
|
|
2983
|
-
}
|
|
2984
|
-
misses.push({
|
|
2985
|
-
filePath: file.filePath,
|
|
2986
|
-
effectiveFilename,
|
|
2987
|
-
content: file.content,
|
|
3384
|
+
const cached = cacheKey ? findConfiguredTransformCacheEntry(
|
|
3385
|
+
cacheRoot,
|
|
2988
3386
|
cacheInput,
|
|
2989
|
-
cacheKey
|
|
2990
|
-
|
|
3387
|
+
cacheKey,
|
|
3388
|
+
effectiveFilename,
|
|
3389
|
+
prescanAstBudget
|
|
3390
|
+
) : null;
|
|
3391
|
+
if (cached) results.set(file.filePath, cached);
|
|
3392
|
+
else misses.push({ ...file, effectiveFilename, cacheInput, cacheKey });
|
|
2991
3393
|
}
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
3394
|
+
return misses;
|
|
3395
|
+
}
|
|
3396
|
+
function runRustPrescanBatch(misses, compilerOptions, cacheRoot, results) {
|
|
3397
|
+
const batchResults = transformRustBatch(
|
|
3398
|
+
misses.map((file) => ({ filename: file.effectiveFilename, source: file.content })),
|
|
3399
|
+
compilerOptions
|
|
3400
|
+
);
|
|
3401
|
+
for (let index = 0; index < misses.length; index++) {
|
|
3402
|
+
const miss = misses[index];
|
|
3403
|
+
const result = batchResults[index];
|
|
3404
|
+
if (!miss || !result) continue;
|
|
3405
|
+
cacheRustPrescanResult(miss, result, cacheRoot);
|
|
3406
|
+
results.set(miss.filePath, result);
|
|
2997
3407
|
}
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
const
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
if (cacheEnabled && miss.cacheKey) {
|
|
3013
|
-
writeTransformCache(cacheRoot, miss.cacheInput, result, miss.cacheKey);
|
|
3014
|
-
rememberTransformCacheEntry(miss.cacheKey.key, result);
|
|
3015
|
-
}
|
|
3408
|
+
}
|
|
3409
|
+
function cacheRustPrescanResult(miss, result, cacheRoot) {
|
|
3410
|
+
if (!cacheEnabled || !miss.cacheKey) return;
|
|
3411
|
+
writeTransformCache(cacheRoot, miss.cacheInput, result, miss.cacheKey);
|
|
3412
|
+
rememberTransformCacheEntry(miss.cacheKey.key, result);
|
|
3413
|
+
}
|
|
3414
|
+
function runRustPrescanFallback(misses, results) {
|
|
3415
|
+
for (const miss of misses) {
|
|
3416
|
+
try {
|
|
3417
|
+
const result = transformConfiguredSource(
|
|
3418
|
+
miss.content,
|
|
3419
|
+
miss.effectiveFilename,
|
|
3420
|
+
prescanAstBudget
|
|
3421
|
+
);
|
|
3016
3422
|
results.set(miss.filePath, result);
|
|
3017
|
-
}
|
|
3018
|
-
} catch {
|
|
3019
|
-
for (const miss of misses) {
|
|
3020
|
-
try {
|
|
3021
|
-
results.set(
|
|
3022
|
-
miss.filePath,
|
|
3023
|
-
transformConfiguredSource(
|
|
3024
|
-
miss.content,
|
|
3025
|
-
miss.effectiveFilename,
|
|
3026
|
-
prescanAstBudget
|
|
3027
|
-
)
|
|
3028
|
-
);
|
|
3029
|
-
} catch {
|
|
3030
|
-
}
|
|
3423
|
+
} catch {
|
|
3031
3424
|
}
|
|
3032
3425
|
}
|
|
3033
|
-
return files.map((file) => {
|
|
3034
|
-
const result = results.get(file.filePath);
|
|
3035
|
-
return result ? { filePath: file.filePath, result } : null;
|
|
3036
|
-
}).filter((entry) => entry !== null);
|
|
3037
3426
|
}
|
|
3038
|
-
function
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3427
|
+
function orderPrescanResults(files, results) {
|
|
3428
|
+
return files.flatMap((file) => {
|
|
3429
|
+
const result = results.get(file.filePath);
|
|
3430
|
+
return result ? [{ filePath: file.filePath, result }] : [];
|
|
3431
|
+
});
|
|
3042
3432
|
}
|
|
3043
3433
|
function transformPrescanSourcesIndividually(files) {
|
|
3044
3434
|
const results = [];
|
|
@@ -3105,11 +3495,12 @@ function createCsszyxPlugins(options = {}) {
|
|
|
3105
3495
|
return;
|
|
3106
3496
|
}
|
|
3107
3497
|
const safelistPath = path.join(state.rootDir, SAFELIST_FILENAME);
|
|
3108
|
-
const
|
|
3498
|
+
const classNames = Array.from(classes);
|
|
3499
|
+
const classList = escapeHtmlAttribute(classNames.join(" "));
|
|
3109
3500
|
const content = `<!-- Auto-generated by csszyx \u2014 DO NOT EDIT -->
|
|
3110
3501
|
<!-- Tailwind CSS scans this file for class name detection -->
|
|
3111
3502
|
<div class="${classList}"><div class="${classList}">x</div><div class="${classList}">x</div></div>
|
|
3112
|
-
|
|
3503
|
+
` + renderTailwindScannerCandidates(classNames);
|
|
3113
3504
|
try {
|
|
3114
3505
|
let existing = "";
|
|
3115
3506
|
try {
|
|
@@ -3139,12 +3530,56 @@ function createCsszyxPlugins(options = {}) {
|
|
|
3139
3530
|
state.skippedSzFiles.add(filePath);
|
|
3140
3531
|
}
|
|
3141
3532
|
}
|
|
3533
|
+
function processPrescanTransform(filePath, content, result, discoveredClasses, rawDiscoveredClasses) {
|
|
3534
|
+
const budgetExceeded = result.diagnostics.some(
|
|
3535
|
+
(diagnostic) => diagnostic.includes("AST budget exceeded")
|
|
3536
|
+
);
|
|
3537
|
+
if (cacheEnabled && !budgetExceeded && content !== void 0) {
|
|
3538
|
+
prescanResultHandoff.set(normalizeSourceFilename(filePath), {
|
|
3539
|
+
inputSha256: createHash("sha256").update(content).digest("hex"),
|
|
3540
|
+
result
|
|
3541
|
+
});
|
|
3542
|
+
}
|
|
3543
|
+
if (budgetExceeded) {
|
|
3544
|
+
warnPrescanBudgetSkip(filePath);
|
|
3545
|
+
return;
|
|
3546
|
+
}
|
|
3547
|
+
const parseFailed = result.diagnostics.some(
|
|
3548
|
+
(diagnostic) => diagnostic.includes("[csszyx] parse error in ")
|
|
3549
|
+
);
|
|
3550
|
+
if (result.classes.size === 0 && result.rawClassNames.size === 0 && parseFailed) {
|
|
3551
|
+
console.warn(
|
|
3552
|
+
`[csszyx] prescan skipped ${filePath}: the file failed to parse, so none of its classes reached the safelist. Fix the syntax error (or check the file extension matches its contents).`
|
|
3553
|
+
);
|
|
3554
|
+
return;
|
|
3555
|
+
}
|
|
3556
|
+
if (!result.transformed && result.classes.size === 0) {
|
|
3557
|
+
return;
|
|
3558
|
+
}
|
|
3559
|
+
collectPrescanResult(result, filePath, discoveredClasses, rawDiscoveredClasses);
|
|
3560
|
+
}
|
|
3142
3561
|
function prescanAndWriteClasses() {
|
|
3143
3562
|
refreshCompileSourceDirs();
|
|
3144
3563
|
const prescanStarted = performance.now();
|
|
3145
3564
|
const discoveredClasses = /* @__PURE__ */ new Set();
|
|
3146
3565
|
const rawDiscoveredClasses = /* @__PURE__ */ new Set();
|
|
3147
3566
|
const prescanSources = [];
|
|
3567
|
+
function collectPrescanSource(filePath) {
|
|
3568
|
+
if (!shouldProcessSource(filePath)) {
|
|
3569
|
+
recordPackagesSkipIfSz(filePath);
|
|
3570
|
+
return;
|
|
3571
|
+
}
|
|
3572
|
+
let content;
|
|
3573
|
+
try {
|
|
3574
|
+
content = fs.readFileSync(filePath, "utf-8");
|
|
3575
|
+
} catch {
|
|
3576
|
+
return;
|
|
3577
|
+
}
|
|
3578
|
+
recordAuthoredClasses(content);
|
|
3579
|
+
if (fileMayContainSafelistableSz(content)) {
|
|
3580
|
+
prescanSources.push({ filePath, content });
|
|
3581
|
+
}
|
|
3582
|
+
}
|
|
3148
3583
|
function scanDir(dir) {
|
|
3149
3584
|
let entries;
|
|
3150
3585
|
try {
|
|
@@ -3157,22 +3592,10 @@ function createCsszyxPlugins(options = {}) {
|
|
|
3157
3592
|
if (!IGNORE_DIRS.has(entry.name) && !entry.name.startsWith(".")) {
|
|
3158
3593
|
scanDir(path.join(dir, entry.name));
|
|
3159
3594
|
}
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
continue;
|
|
3165
|
-
}
|
|
3166
|
-
let content;
|
|
3167
|
-
try {
|
|
3168
|
-
content = fs.readFileSync(filePath, "utf-8");
|
|
3169
|
-
} catch {
|
|
3170
|
-
continue;
|
|
3171
|
-
}
|
|
3172
|
-
if (!fileMayContainSafelistableSz(content)) {
|
|
3173
|
-
continue;
|
|
3174
|
-
}
|
|
3175
|
-
prescanSources.push({ filePath, content });
|
|
3595
|
+
continue;
|
|
3596
|
+
}
|
|
3597
|
+
if (SOURCE_EXTENSIONS.has(path.extname(entry.name))) {
|
|
3598
|
+
collectPrescanSource(path.join(dir, entry.name));
|
|
3176
3599
|
}
|
|
3177
3600
|
}
|
|
3178
3601
|
}
|
|
@@ -3188,29 +3611,13 @@ function createCsszyxPlugins(options = {}) {
|
|
|
3188
3611
|
prescanSources.map((file) => [file.filePath, file.content])
|
|
3189
3612
|
);
|
|
3190
3613
|
for (const { filePath, result } of transformPrescanSources(prescanSources)) {
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
}
|
|
3199
|
-
}
|
|
3200
|
-
if (result.diagnostics.some((d) => d.includes("AST budget exceeded"))) {
|
|
3201
|
-
warnPrescanBudgetSkip(filePath);
|
|
3202
|
-
continue;
|
|
3203
|
-
}
|
|
3204
|
-
if (result.classes.size === 0 && result.rawClassNames.size === 0 && result.diagnostics.some((d) => d.includes("[csszyx] parse error in "))) {
|
|
3205
|
-
console.warn(
|
|
3206
|
-
`[csszyx] prescan skipped ${filePath}: the file failed to parse, so none of its classes reached the safelist. Fix the syntax error (or check the file extension matches its contents).`
|
|
3207
|
-
);
|
|
3208
|
-
continue;
|
|
3209
|
-
}
|
|
3210
|
-
if (!result.transformed && result.classes.size === 0) {
|
|
3211
|
-
continue;
|
|
3212
|
-
}
|
|
3213
|
-
collectPrescanResult(result, filePath, discoveredClasses, rawDiscoveredClasses);
|
|
3614
|
+
processPrescanTransform(
|
|
3615
|
+
filePath,
|
|
3616
|
+
prescanContentByPath.get(filePath),
|
|
3617
|
+
result,
|
|
3618
|
+
discoveredClasses,
|
|
3619
|
+
rawDiscoveredClasses
|
|
3620
|
+
);
|
|
3214
3621
|
}
|
|
3215
3622
|
for (const cls of discoveredClasses) {
|
|
3216
3623
|
addSafelistClass(cls);
|
|
@@ -3271,7 +3678,7 @@ function createCsszyxPlugins(options = {}) {
|
|
|
3271
3678
|
for (const kv of objStr.matchAll(numKv)) {
|
|
3272
3679
|
try {
|
|
3273
3680
|
collectTransformClasses(
|
|
3274
|
-
transform({ [kv[1]]: parseFloat(kv[2]) }),
|
|
3681
|
+
transform({ [kv[1]]: Number.parseFloat(kv[2]) }),
|
|
3275
3682
|
discoveredClasses
|
|
3276
3683
|
);
|
|
3277
3684
|
} catch {
|
|
@@ -3295,51 +3702,51 @@ function createCsszyxPlugins(options = {}) {
|
|
|
3295
3702
|
discoveredClasses.add(cls);
|
|
3296
3703
|
}
|
|
3297
3704
|
}
|
|
3298
|
-
function
|
|
3299
|
-
const
|
|
3300
|
-
|
|
3301
|
-
for (const classPattern of [dqPattern, sqPattern]) {
|
|
3302
|
-
for (const match of code.matchAll(classPattern)) {
|
|
3303
|
-
const classes = match[1].split(/\s+/).filter(Boolean);
|
|
3304
|
-
for (const cls of classes) {
|
|
3305
|
-
addSafelistClass(cls);
|
|
3306
|
-
}
|
|
3307
|
-
}
|
|
3705
|
+
function addSafelistClasses(value) {
|
|
3706
|
+
for (const className of value.split(/\s+/).filter(Boolean)) {
|
|
3707
|
+
addSafelistClass(className);
|
|
3308
3708
|
}
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
}
|
|
3319
|
-
i++;
|
|
3709
|
+
}
|
|
3710
|
+
function collectQuotedAttributeClasses(code) {
|
|
3711
|
+
const patterns = [
|
|
3712
|
+
/(?:class(?:Name)?|sz)[:=]\s*"([^"]*)"/g,
|
|
3713
|
+
/(?:class(?:Name)?|sz)[:=]\s*'([^']*)'/g
|
|
3714
|
+
];
|
|
3715
|
+
for (const pattern of patterns) {
|
|
3716
|
+
for (const match of code.matchAll(pattern)) {
|
|
3717
|
+
addSafelistClasses(match[1] ?? "");
|
|
3320
3718
|
}
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3719
|
+
}
|
|
3720
|
+
}
|
|
3721
|
+
function collectExpressionClasses(code) {
|
|
3722
|
+
for (const match of code.matchAll(/className=\{/g)) {
|
|
3723
|
+
const bodyStart = (match.index ?? 0) + match[0].length;
|
|
3724
|
+
const expression = code.slice(bodyStart, findJsxExpressionEnd(code, bodyStart));
|
|
3725
|
+
for (const stringMatch of expression.matchAll(/"([^"]+)"|'([^']+)'/g)) {
|
|
3726
|
+
addSafelistClasses(stringMatch[1] ?? stringMatch[2] ?? "");
|
|
3329
3727
|
}
|
|
3330
3728
|
}
|
|
3331
3729
|
}
|
|
3730
|
+
function extractClasses(code) {
|
|
3731
|
+
collectQuotedAttributeClasses(code);
|
|
3732
|
+
collectExpressionClasses(code);
|
|
3733
|
+
}
|
|
3734
|
+
function recordAuthoredClasses(code) {
|
|
3735
|
+
for (const className of collectAuthoredClassNames(code)) {
|
|
3736
|
+
addSafelistClass(className);
|
|
3737
|
+
state.authoredClasses.add(className);
|
|
3738
|
+
}
|
|
3739
|
+
}
|
|
3332
3740
|
function finalizeMangleMap() {
|
|
3333
|
-
const sortedClasses = Array.from(state.ownedClasses);
|
|
3334
3741
|
const newMap = {};
|
|
3335
3742
|
let tokenIndex = 0;
|
|
3336
|
-
for (
|
|
3743
|
+
for (const className of mangleEligibleClasses(state.ownedClasses, state.authoredClasses)) {
|
|
3337
3744
|
let token = encode(tokenIndex);
|
|
3338
|
-
while (mangleReserved.has(token)) {
|
|
3745
|
+
while (mangleReserved.has(token) || state.authoredClasses.has(token)) {
|
|
3339
3746
|
tokenIndex++;
|
|
3340
3747
|
token = encode(tokenIndex);
|
|
3341
3748
|
}
|
|
3342
|
-
newMap[
|
|
3749
|
+
newMap[className] = token;
|
|
3343
3750
|
tokenIndex++;
|
|
3344
3751
|
}
|
|
3345
3752
|
state.mangleMap = newMap;
|
|
@@ -3352,6 +3759,24 @@ function createCsszyxPlugins(options = {}) {
|
|
|
3352
3759
|
function mangleCodeClasses(code) {
|
|
3353
3760
|
return mangleCodeClassesSync(code, state.mangleMap);
|
|
3354
3761
|
}
|
|
3762
|
+
function mangleHtmlClassList(classes) {
|
|
3763
|
+
const output = [];
|
|
3764
|
+
for (const className of classes.split(/\s+/)) {
|
|
3765
|
+
if (className) output.push(state.mangleMap[className] || className);
|
|
3766
|
+
}
|
|
3767
|
+
return output.join(" ");
|
|
3768
|
+
}
|
|
3769
|
+
function replaceDoubleQuotedHtmlClass(match, classes) {
|
|
3770
|
+
const output = mangleHtmlClassList(classes);
|
|
3771
|
+
return output !== classes ? `class="${output}"` : match;
|
|
3772
|
+
}
|
|
3773
|
+
function replaceSingleQuotedHtmlClass(match, classes) {
|
|
3774
|
+
const output = mangleHtmlClassList(classes);
|
|
3775
|
+
return output !== classes ? `class='${output}'` : match;
|
|
3776
|
+
}
|
|
3777
|
+
function mangleHtmlClasses(source) {
|
|
3778
|
+
return source.replace(/\bclass="([^"]*)"/g, replaceDoubleQuotedHtmlClass).replace(/\bclass='([^']*)'/g, replaceSingleQuotedHtmlClass);
|
|
3779
|
+
}
|
|
3355
3780
|
function replacePlaceholders(code) {
|
|
3356
3781
|
let result = code;
|
|
3357
3782
|
if (result.includes(CHECKSUM_PLACEHOLDER)) {
|
|
@@ -3369,6 +3794,147 @@ function createCsszyxPlugins(options = {}) {
|
|
|
3369
3794
|
}
|
|
3370
3795
|
return result;
|
|
3371
3796
|
}
|
|
3797
|
+
function unchangedPreTransform(code) {
|
|
3798
|
+
return {
|
|
3799
|
+
code,
|
|
3800
|
+
transformed: false,
|
|
3801
|
+
usesRuntime: false,
|
|
3802
|
+
usesMerge: false,
|
|
3803
|
+
usesSzcn: false,
|
|
3804
|
+
usesSzPart: false,
|
|
3805
|
+
usesColorVar: false,
|
|
3806
|
+
usesSpacingVar: false,
|
|
3807
|
+
usesUnitVar: false
|
|
3808
|
+
};
|
|
3809
|
+
}
|
|
3810
|
+
function transformTailwindCssEntry(code, id) {
|
|
3811
|
+
state.sawAnyCss = true;
|
|
3812
|
+
if (!cssImportsTailwind(code)) return null;
|
|
3813
|
+
state.sawTailwindEntry = true;
|
|
3814
|
+
if (cssHasContentScope(code)) state.tailwindEntryScoped = true;
|
|
3815
|
+
if (!hasInjectableTailwindCandidate(state.classes)) return null;
|
|
3816
|
+
const relPath = computeSafelistRelPath(state.rootDir, SAFELIST_FILENAME, id);
|
|
3817
|
+
const transformed = appendTailwindSourceDirective(code, relPath);
|
|
3818
|
+
return transformed === null ? null : { code: transformed, map: null };
|
|
3819
|
+
}
|
|
3820
|
+
function reportTransformDiagnostics(result, id, warn) {
|
|
3821
|
+
for (const message of result.diagnostics) {
|
|
3822
|
+
if (message.includes("unresolvable sz spread")) {
|
|
3823
|
+
state.spreadWarnings.add(`${id}
|
|
3824
|
+
${message}`);
|
|
3825
|
+
} else if (message.includes("AST budget exceeded")) {
|
|
3826
|
+
console.warn(`[csszyx] ${id}
|
|
3827
|
+
${message}`);
|
|
3828
|
+
}
|
|
3829
|
+
}
|
|
3830
|
+
if (quiet || result.diagnostics.length === 0 || process.env.NODE_ENV === "production") {
|
|
3831
|
+
return;
|
|
3832
|
+
}
|
|
3833
|
+
for (const message of result.diagnostics) {
|
|
3834
|
+
if (message.includes("unresolvable sz spread") || message.includes("AST budget exceeded")) {
|
|
3835
|
+
continue;
|
|
3836
|
+
}
|
|
3837
|
+
warn(`[csszyx] ${id}
|
|
3838
|
+
${message}`);
|
|
3839
|
+
}
|
|
3840
|
+
}
|
|
3841
|
+
function compilerPreTransformOutput(result) {
|
|
3842
|
+
return {
|
|
3843
|
+
code: result.code,
|
|
3844
|
+
transformed: result.transformed,
|
|
3845
|
+
usesRuntime: result.usesRuntime,
|
|
3846
|
+
usesMerge: result.usesMerge,
|
|
3847
|
+
usesSzcn: result.usesSzcn,
|
|
3848
|
+
usesSzPart: result.usesSzPart,
|
|
3849
|
+
usesColorVar: result.usesColorVar,
|
|
3850
|
+
usesSpacingVar: result.usesSpacingVar,
|
|
3851
|
+
usesUnitVar: result.usesUnitVar,
|
|
3852
|
+
szClasses: result.classes
|
|
3853
|
+
};
|
|
3854
|
+
}
|
|
3855
|
+
function transformSzSource(code, id, warn) {
|
|
3856
|
+
if (id.endsWith(".vue")) {
|
|
3857
|
+
const result2 = preprocess(code, options);
|
|
3858
|
+
return { ...unchangedPreTransform(result2.code), transformed: result2.transformed };
|
|
3859
|
+
}
|
|
3860
|
+
if (id.endsWith(".svelte")) {
|
|
3861
|
+
const result2 = preprocess$1(code, options);
|
|
3862
|
+
return result2 ? { ...unchangedPreTransform(result2.code), transformed: true } : unchangedPreTransform(code);
|
|
3863
|
+
}
|
|
3864
|
+
const transformStarted = performance.now();
|
|
3865
|
+
const result = transformConfiguredSource(code, id);
|
|
3866
|
+
traceBenchTiming("transform-hook", id, performance.now() - transformStarted);
|
|
3867
|
+
recordFileVarMangleEntries(state, id, cssVariableEntries(result));
|
|
3868
|
+
recordFileCSSVariableMetrics(state, id, result.code);
|
|
3869
|
+
reportTransformDiagnostics(result, id, warn);
|
|
3870
|
+
for (const [token, data] of result.recoveryTokens) state.recoveryTokens.set(token, data);
|
|
3871
|
+
return compilerPreTransformOutput(result);
|
|
3872
|
+
}
|
|
3873
|
+
function injectLayoutHydration(code, id) {
|
|
3874
|
+
if (!code.includes("<html") || !/(?:layout|Root|Document|app)\.tsx?$/i.test(id)) {
|
|
3875
|
+
return null;
|
|
3876
|
+
}
|
|
3877
|
+
let transformedCode = code;
|
|
3878
|
+
const attrName = options.production?.minify ? "data-sz-cs" : "data-sz-checksum";
|
|
3879
|
+
const htmlTag = findOpeningTag(transformedCode, "html");
|
|
3880
|
+
if (htmlTag) {
|
|
3881
|
+
transformedCode = `${transformedCode.slice(0, htmlTag.close)} ${attrName}="${CHECKSUM_PLACEHOLDER}"${transformedCode.slice(htmlTag.close)}`;
|
|
3882
|
+
}
|
|
3883
|
+
const debugScript = `<script dangerouslySetInnerHTML={{__html: \`(function(){var m=${MANGLE_MAP_PLACEHOLDER};var vm=${VAR_MANGLE_MAP_PLACEHOLDER};var gp=decodeURIComponent(${escapeJsonForInlineScript(JSON.stringify(encodedGlobalVarAliasPrefix))});var r={};var vr={};for(var k in m)r[m[k]]=k;for(var vk in vm){var vv=vm[vk];var vs=Array.isArray(vv)?vv:[vv];for(var vi=0;vi<vs.length;vi++)(vr[vs[vi]]||(vr[vs[vi]]=[])).push(vk)}window.__csszyx={mangleMap:m,varMangleMap:vm,checksum:"${CHECKSUM_PLACEHOLDER}",decode:function(c){return r[c]},encode:function(c){return m[c]},decodeVar:function(v){return vr[v]||[]},encodeVar:function(v){return vm[v]},decodeGlobalVar:function(v){var a=vr[v]||[];return v.indexOf(gp)===0?a[0]:void 0},decodeAll:function(el){return(el.className||"").split(" ").map(function(c){return r[c]||c})}}})()\`}} />`;
|
|
3884
|
+
const bodyTag = findOpeningTag(transformedCode, "body");
|
|
3885
|
+
if (bodyTag) {
|
|
3886
|
+
transformedCode = `${transformedCode.slice(0, bodyTag.close + 1)}${debugScript}${transformedCode.slice(bodyTag.close + 1)}`;
|
|
3887
|
+
}
|
|
3888
|
+
return transformedCode;
|
|
3889
|
+
}
|
|
3890
|
+
function requiredRuntimeHelpers(output) {
|
|
3891
|
+
const helpers = [];
|
|
3892
|
+
if (output.usesRuntime) helpers.push("_sz");
|
|
3893
|
+
if (output.usesMerge) helpers.push("_szMerge");
|
|
3894
|
+
if (output.usesSzcn) helpers.push("_szcn");
|
|
3895
|
+
if (output.usesSzPart) helpers.push("_szPart");
|
|
3896
|
+
if (output.usesColorVar) helpers.push("__szColorVar");
|
|
3897
|
+
if (output.usesSpacingVar) helpers.push("__szSpacingVar");
|
|
3898
|
+
if (output.usesUnitVar) helpers.push("__szUnitVar");
|
|
3899
|
+
return helpers;
|
|
3900
|
+
}
|
|
3901
|
+
function injectRuntimeHelpers(code, output) {
|
|
3902
|
+
const imports = requiredRuntimeHelpers(output);
|
|
3903
|
+
const hasRuntimeImport = imports.length > 0 && code.includes("@csszyx/runtime");
|
|
3904
|
+
const needed = hasRuntimeImport ? imports.filter((name) => !importsRuntimeHelper(code, name)) : imports;
|
|
3905
|
+
if (needed.length === 0) return null;
|
|
3906
|
+
const existingImport = findRuntimeImportClause(code);
|
|
3907
|
+
if (existingImport) {
|
|
3908
|
+
return code.replace(
|
|
3909
|
+
existingImport.statement,
|
|
3910
|
+
`${existingImport.prefixWithBody}, ${needed.join(", ")} } from '@csszyx/runtime'`
|
|
3911
|
+
);
|
|
3912
|
+
}
|
|
3913
|
+
const importStatement = `import { ${needed.join(", ")} } from '@csszyx/runtime';
|
|
3914
|
+
`;
|
|
3915
|
+
return insertRuntimeImport(code, importStatement);
|
|
3916
|
+
}
|
|
3917
|
+
function injectThemeGroups(code, transformedCode, id, usesSzcn) {
|
|
3918
|
+
if (!usesSzcn && !/\bszcn\s*\(/.test(code) || transformedCode.includes(THEME_GROUPS_VIRTUAL_ID) || !shouldProcessSource(id)) {
|
|
3919
|
+
return null;
|
|
3920
|
+
}
|
|
3921
|
+
return `import '${THEME_GROUPS_VIRTUAL_ID}';
|
|
3922
|
+
${transformedCode}`;
|
|
3923
|
+
}
|
|
3924
|
+
function collectPreTransformClasses(output) {
|
|
3925
|
+
if (!output.transformed && !output.code.includes("class=") && !output.code.includes("className=")) {
|
|
3926
|
+
return null;
|
|
3927
|
+
}
|
|
3928
|
+
if (output.szClasses) {
|
|
3929
|
+
for (const className of output.szClasses) {
|
|
3930
|
+
addSafelistClass(className);
|
|
3931
|
+
state.ownedClasses.add(className);
|
|
3932
|
+
}
|
|
3933
|
+
} else {
|
|
3934
|
+
extractClasses(output.code);
|
|
3935
|
+
}
|
|
3936
|
+
return { code: output.code, map: null };
|
|
3937
|
+
}
|
|
3372
3938
|
const prePlugin = createUnplugin(
|
|
3373
3939
|
(_pluginOptions) => ({
|
|
3374
3940
|
name: "csszyx:pre",
|
|
@@ -3455,166 +4021,41 @@ function createCsszyxPlugins(options = {}) {
|
|
|
3455
4021
|
}
|
|
3456
4022
|
if (shouldProcessSource(id)) {
|
|
3457
4023
|
trackGlobalVarSourceFile(id, code);
|
|
4024
|
+
recordAuthoredClasses(code);
|
|
3458
4025
|
}
|
|
3459
4026
|
if (matchesScriptExtension(id, SCRIPT_ID_EXTENSIONS)) {
|
|
3460
4027
|
assertNoRSCBoundaryViolation(code, id);
|
|
3461
4028
|
}
|
|
3462
4029
|
if (matchesScriptExtension(id, [".css"])) {
|
|
3463
|
-
|
|
3464
|
-
if (cssImportsTailwind(code)) {
|
|
3465
|
-
state.sawTailwindEntry = true;
|
|
3466
|
-
if (cssHasContentScope(code)) {
|
|
3467
|
-
state.tailwindEntryScoped = true;
|
|
3468
|
-
}
|
|
3469
|
-
if (hasInjectableTailwindCandidate(state.classes)) {
|
|
3470
|
-
const relPath = computeSafelistRelPath(
|
|
3471
|
-
state.rootDir,
|
|
3472
|
-
SAFELIST_FILENAME,
|
|
3473
|
-
id
|
|
3474
|
-
);
|
|
3475
|
-
const transformed2 = appendTailwindSourceDirective(code, relPath);
|
|
3476
|
-
if (transformed2 !== null) {
|
|
3477
|
-
return { code: transformed2, map: null };
|
|
3478
|
-
}
|
|
3479
|
-
}
|
|
3480
|
-
}
|
|
3481
|
-
return null;
|
|
4030
|
+
return transformTailwindCssEntry(code, id);
|
|
3482
4031
|
}
|
|
3483
|
-
let transformedCode = code;
|
|
3484
|
-
let usesRuntime = false;
|
|
3485
|
-
let usesMerge = false;
|
|
3486
|
-
let usesSzcn = false;
|
|
3487
|
-
let usesSzPart = false;
|
|
3488
|
-
let usesColorVar = false;
|
|
3489
|
-
let transformed = false;
|
|
3490
|
-
let szClasses;
|
|
3491
4032
|
const hasSzProp = code.includes("sz=") || code.includes("szs=") || /\bsz\s*:\s*["'{]/.test(code) || code.includes('sz: "');
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
const result = preprocess(code, options);
|
|
3495
|
-
if (result.transformed) {
|
|
3496
|
-
transformedCode = result.code;
|
|
3497
|
-
transformed = true;
|
|
3498
|
-
}
|
|
3499
|
-
} else if (id.endsWith(".svelte")) {
|
|
3500
|
-
const result = preprocess$1(code, options);
|
|
3501
|
-
if (result) {
|
|
3502
|
-
transformedCode = result.code;
|
|
3503
|
-
transformed = true;
|
|
3504
|
-
}
|
|
3505
|
-
} else {
|
|
3506
|
-
const transformStarted = performance.now();
|
|
3507
|
-
const result = transformConfiguredSource(code, id);
|
|
3508
|
-
traceBenchTiming(
|
|
3509
|
-
"transform-hook",
|
|
3510
|
-
id,
|
|
3511
|
-
performance.now() - transformStarted
|
|
3512
|
-
);
|
|
3513
|
-
transformedCode = result.code;
|
|
3514
|
-
usesRuntime = result.usesRuntime;
|
|
3515
|
-
usesMerge = result.usesMerge;
|
|
3516
|
-
usesSzcn = result.usesSzcn;
|
|
3517
|
-
usesSzPart = result.usesSzPart;
|
|
3518
|
-
usesColorVar = result.usesColorVar;
|
|
3519
|
-
transformed = result.transformed;
|
|
3520
|
-
szClasses = result.classes;
|
|
3521
|
-
recordFileVarMangleEntries(state, id, cssVariableEntries(result));
|
|
3522
|
-
recordFileCSSVariableMetrics(state, id, result.code);
|
|
3523
|
-
for (const msg of result.diagnostics) {
|
|
3524
|
-
if (msg.includes("unresolvable sz spread")) {
|
|
3525
|
-
state.spreadWarnings.add(`${id}
|
|
3526
|
-
${msg}`);
|
|
3527
|
-
} else if (msg.includes("AST budget exceeded")) {
|
|
3528
|
-
console.warn(`[csszyx] ${id}
|
|
3529
|
-
${msg}`);
|
|
3530
|
-
}
|
|
3531
|
-
}
|
|
3532
|
-
if (!quiet && result.diagnostics.length > 0 && process.env.NODE_ENV !== "production") {
|
|
3533
|
-
for (const msg of result.diagnostics) {
|
|
3534
|
-
if (msg.includes("unresolvable sz spread") || msg.includes("AST budget exceeded")) {
|
|
3535
|
-
continue;
|
|
3536
|
-
}
|
|
3537
|
-
this.warn(`[csszyx] ${id}
|
|
3538
|
-
${msg}`);
|
|
3539
|
-
}
|
|
3540
|
-
}
|
|
3541
|
-
for (const [token, data] of result.recoveryTokens) {
|
|
3542
|
-
state.recoveryTokens.set(token, data);
|
|
3543
|
-
}
|
|
3544
|
-
}
|
|
3545
|
-
} else if (shouldProcessSource(id)) {
|
|
4033
|
+
const output = hasSzProp ? transformSzSource(code, id, (message) => this.warn(message)) : unchangedPreTransform(code);
|
|
4034
|
+
if (!hasSzProp && shouldProcessSource(id)) {
|
|
3546
4035
|
recordFileVarMangleEntries(state, id, []);
|
|
3547
4036
|
recordFileCSSVariableMetrics(state, id, null);
|
|
3548
4037
|
}
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
transformedCode = `${transformedCode.slice(0, htmlTag.close)} ${attrName}="${CHECKSUM_PLACEHOLDER}"${transformedCode.slice(htmlTag.close)}`;
|
|
3554
|
-
}
|
|
3555
|
-
const debugScript = `<script dangerouslySetInnerHTML={{__html: \`(function(){var m=${MANGLE_MAP_PLACEHOLDER};var vm=${VAR_MANGLE_MAP_PLACEHOLDER};var gp=decodeURIComponent(${escapeJsonForInlineScript(JSON.stringify(encodedGlobalVarAliasPrefix))});var r={};var vr={};for(var k in m)r[m[k]]=k;for(var vk in vm){var vv=vm[vk];var vs=Array.isArray(vv)?vv:[vv];for(var vi=0;vi<vs.length;vi++)(vr[vs[vi]]||(vr[vs[vi]]=[])).push(vk)}window.__csszyx={mangleMap:m,varMangleMap:vm,checksum:"${CHECKSUM_PLACEHOLDER}",decode:function(c){return r[c]},encode:function(c){return m[c]},decodeVar:function(v){return vr[v]||[]},encodeVar:function(v){return vm[v]},decodeGlobalVar:function(v){var a=vr[v]||[];return v.indexOf(gp)===0?a[0]:void 0},decodeAll:function(el){return(el.className||"").split(" ").map(function(c){return r[c]||c})}}})()\`}} />`;
|
|
3556
|
-
const bodyTag = findOpeningTag(transformedCode, "body");
|
|
3557
|
-
if (bodyTag) {
|
|
3558
|
-
transformedCode = `${transformedCode.slice(0, bodyTag.close + 1)}${debugScript}${transformedCode.slice(bodyTag.close + 1)}`;
|
|
3559
|
-
}
|
|
3560
|
-
transformed = true;
|
|
4038
|
+
const layoutCode = injectLayoutHydration(output.code, id);
|
|
4039
|
+
if (layoutCode !== null) {
|
|
4040
|
+
output.code = layoutCode;
|
|
4041
|
+
output.transformed = true;
|
|
3561
4042
|
}
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
}
|
|
3567
|
-
if (usesMerge) {
|
|
3568
|
-
imports.push("_szMerge");
|
|
3569
|
-
}
|
|
3570
|
-
if (usesSzcn) {
|
|
3571
|
-
imports.push("_szcn");
|
|
3572
|
-
}
|
|
3573
|
-
if (usesSzPart) {
|
|
3574
|
-
imports.push("_szPart");
|
|
3575
|
-
}
|
|
3576
|
-
if (usesColorVar) {
|
|
3577
|
-
imports.push("__szColorVar");
|
|
3578
|
-
}
|
|
3579
|
-
const hasRuntimeImport = imports.length > 0 && transformedCode.includes("@csszyx/runtime");
|
|
3580
|
-
const needed = hasRuntimeImport ? imports.filter((name) => !importsRuntimeHelper(transformedCode, name)) : imports;
|
|
3581
|
-
if (needed.length > 0) {
|
|
3582
|
-
const existingImport = findRuntimeImportClause(transformedCode);
|
|
3583
|
-
if (existingImport) {
|
|
3584
|
-
transformedCode = transformedCode.replace(
|
|
3585
|
-
existingImport.statement,
|
|
3586
|
-
`${existingImport.prefixWithBody}, ${needed.join(", ")} } from '@csszyx/runtime'`
|
|
3587
|
-
);
|
|
3588
|
-
} else {
|
|
3589
|
-
const importStmt = `import { ${needed.join(", ")} } from '@csszyx/runtime';
|
|
3590
|
-
`;
|
|
3591
|
-
transformedCode = insertRuntimeImport(transformedCode, importStmt);
|
|
3592
|
-
}
|
|
3593
|
-
transformed = true;
|
|
3594
|
-
}
|
|
4043
|
+
const runtimeCode = injectRuntimeHelpers(output.code, output);
|
|
4044
|
+
if (runtimeCode !== null) {
|
|
4045
|
+
output.code = runtimeCode;
|
|
4046
|
+
output.transformed = true;
|
|
3595
4047
|
}
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
transformed = true;
|
|
4048
|
+
const themedCode = injectThemeGroups(code, output.code, id, output.usesSzcn);
|
|
4049
|
+
if (themedCode !== null) {
|
|
4050
|
+
output.code = themedCode;
|
|
4051
|
+
output.transformed = true;
|
|
3600
4052
|
}
|
|
3601
4053
|
if (matchesScriptExtension(id, SCRIPT_ID_EXTENSIONS)) {
|
|
3602
|
-
assertNoRSCBoundaryViolation(
|
|
3603
|
-
const record = createRSCModuleRecord(
|
|
4054
|
+
assertNoRSCBoundaryViolation(output.code, id);
|
|
4055
|
+
const record = createRSCModuleRecord(output.code, id);
|
|
3604
4056
|
state.rscModules.set(record.id, record);
|
|
3605
4057
|
}
|
|
3606
|
-
|
|
3607
|
-
if (szClasses !== void 0) {
|
|
3608
|
-
for (const cls of szClasses) {
|
|
3609
|
-
addSafelistClass(cls);
|
|
3610
|
-
state.ownedClasses.add(cls);
|
|
3611
|
-
}
|
|
3612
|
-
} else {
|
|
3613
|
-
extractClasses(transformedCode);
|
|
3614
|
-
}
|
|
3615
|
-
return { code: transformedCode, map: null };
|
|
3616
|
-
}
|
|
3617
|
-
return null;
|
|
4058
|
+
return collectPreTransformClasses(output);
|
|
3618
4059
|
},
|
|
3619
4060
|
/** Finalizes the mangle map after all source modules have been processed. */
|
|
3620
4061
|
buildEnd() {
|
|
@@ -3823,6 +4264,166 @@ ${transformedCode}`;
|
|
|
3823
4264
|
}
|
|
3824
4265
|
})
|
|
3825
4266
|
);
|
|
4267
|
+
function createBundleManifest(includeMangleMap) {
|
|
4268
|
+
const manifest = {
|
|
4269
|
+
version: "0.4.0",
|
|
4270
|
+
buildId: state.checksum,
|
|
4271
|
+
classes: Object.keys(state.mangleMap)
|
|
4272
|
+
};
|
|
4273
|
+
if (includeMangleMap && Object.keys(state.mangleMap).length > 0) {
|
|
4274
|
+
manifest.mangleMap = state.mangleMap;
|
|
4275
|
+
}
|
|
4276
|
+
if (Object.keys(state.varMangleMap).length > 0) {
|
|
4277
|
+
manifest.varMangleMap = state.varMangleMap;
|
|
4278
|
+
}
|
|
4279
|
+
const globalVarAliases = extractGlobalVarAliasesForManifest(
|
|
4280
|
+
state.varMangleMap,
|
|
4281
|
+
globalVarAliasPrefix,
|
|
4282
|
+
state.globalVarValidationResult
|
|
4283
|
+
);
|
|
4284
|
+
if (Object.keys(globalVarAliases).length > 0) {
|
|
4285
|
+
manifest.globalVarAliases = globalVarAliases;
|
|
4286
|
+
}
|
|
4287
|
+
if (hasCSSVariableMetrics(state.cssVarMetrics)) {
|
|
4288
|
+
manifest.cssVarMetrics = state.cssVarMetrics;
|
|
4289
|
+
}
|
|
4290
|
+
return manifest;
|
|
4291
|
+
}
|
|
4292
|
+
function isCssSyntaxError(error) {
|
|
4293
|
+
return !!error && typeof error === "object" && "name" in error && error.name === "CssSyntaxError";
|
|
4294
|
+
}
|
|
4295
|
+
function rewriteOutputCss(source, file, shouldMangle, mangledSources, externalClasses) {
|
|
4296
|
+
let css = rewriteCssWithValidatedGlobalVarPlan(
|
|
4297
|
+
source,
|
|
4298
|
+
file,
|
|
4299
|
+
state.globalVarValidationResult
|
|
4300
|
+
);
|
|
4301
|
+
if (!shouldMangle) return css;
|
|
4302
|
+
try {
|
|
4303
|
+
const result = mangleCSSSync(css, state.mangleMap, {
|
|
4304
|
+
debug: options.development?.debug,
|
|
4305
|
+
from: file
|
|
4306
|
+
});
|
|
4307
|
+
for (const className of result.mangledClasses) mangledSources.add(className);
|
|
4308
|
+
for (const className of result.unmangledClasses) externalClasses.add(className);
|
|
4309
|
+
if (result.transformedCount > 0) css = result.css;
|
|
4310
|
+
return css;
|
|
4311
|
+
} catch (error) {
|
|
4312
|
+
if (isCssSyntaxError(error)) return css;
|
|
4313
|
+
throw error;
|
|
4314
|
+
}
|
|
4315
|
+
}
|
|
4316
|
+
function reportOutputMangleHazards(shouldMangle, mangledSources, externalClasses) {
|
|
4317
|
+
if (!shouldMangle) return;
|
|
4318
|
+
const message = mangleHybridHazardMessage(
|
|
4319
|
+
collectMangleHybridHazards(state.mangleMap, mangledSources, externalClasses)
|
|
4320
|
+
);
|
|
4321
|
+
if (message) console.warn(message);
|
|
4322
|
+
}
|
|
4323
|
+
function rewriteWebpackCodeAsset(file, source, shouldMangle, compilation, compiler) {
|
|
4324
|
+
if (shouldMangle && file.endsWith(".html")) {
|
|
4325
|
+
const mangledHtml = mangleHtmlClasses(source);
|
|
4326
|
+
if (mangledHtml !== source) {
|
|
4327
|
+
compilation.updateAsset(file, new compiler.webpack.sources.RawSource(mangledHtml));
|
|
4328
|
+
}
|
|
4329
|
+
return;
|
|
4330
|
+
}
|
|
4331
|
+
if (!file.endsWith(".js")) return;
|
|
4332
|
+
const rewritten = shouldMangle ? replacePlaceholders(mangleCodeClasses(source)) : replacePlaceholders(source);
|
|
4333
|
+
if (rewritten !== source) {
|
|
4334
|
+
compilation.updateAsset(file, new compiler.webpack.sources.RawSource(rewritten));
|
|
4335
|
+
}
|
|
4336
|
+
}
|
|
4337
|
+
function processWebpackAssets(assets, compilation, compiler) {
|
|
4338
|
+
finalizeMangleMap();
|
|
4339
|
+
state.globalVarValidationResult = validateGlobalVarBundleInputs(
|
|
4340
|
+
collectWebpackGlobalVarCssAssets(assets)
|
|
4341
|
+
);
|
|
4342
|
+
const shouldMangle = manglingEnabled && compiler.options.mode !== "development" && Object.keys(state.mangleMap).length > 0;
|
|
4343
|
+
const manifest = createBundleManifest(shouldMangle);
|
|
4344
|
+
compilation.emitAsset(
|
|
4345
|
+
"csszyx-manifest.json",
|
|
4346
|
+
new compiler.webpack.sources.RawSource(JSON.stringify(manifest))
|
|
4347
|
+
);
|
|
4348
|
+
if (shouldEmitGlobalVarMapAsset(globalVarMangleConfig)) {
|
|
4349
|
+
const globalVarMap = createGlobalVarMapAssetSource(
|
|
4350
|
+
state.varMangleMap,
|
|
4351
|
+
globalVarAliasPrefix,
|
|
4352
|
+
state.globalVarValidationResult
|
|
4353
|
+
);
|
|
4354
|
+
if (globalVarMap) {
|
|
4355
|
+
compilation.emitAsset(
|
|
4356
|
+
".csszyx/global-var-map.json",
|
|
4357
|
+
new compiler.webpack.sources.RawSource(globalVarMap)
|
|
4358
|
+
);
|
|
4359
|
+
}
|
|
4360
|
+
}
|
|
4361
|
+
const mangledSources = /* @__PURE__ */ new Set();
|
|
4362
|
+
const externalClasses = /* @__PURE__ */ new Set();
|
|
4363
|
+
for (const file in assets) {
|
|
4364
|
+
const source = assets[file].source().toString();
|
|
4365
|
+
if (file.endsWith(".css")) {
|
|
4366
|
+
const css = rewriteOutputCss(
|
|
4367
|
+
source,
|
|
4368
|
+
file,
|
|
4369
|
+
shouldMangle,
|
|
4370
|
+
mangledSources,
|
|
4371
|
+
externalClasses
|
|
4372
|
+
);
|
|
4373
|
+
if (css !== source) {
|
|
4374
|
+
compilation.updateAsset(file, new compiler.webpack.sources.RawSource(css));
|
|
4375
|
+
}
|
|
4376
|
+
} else {
|
|
4377
|
+
rewriteWebpackCodeAsset(file, source, shouldMangle, compilation, compiler);
|
|
4378
|
+
}
|
|
4379
|
+
}
|
|
4380
|
+
reportOutputMangleHazards(shouldMangle, mangledSources, externalClasses);
|
|
4381
|
+
}
|
|
4382
|
+
function rewriteViteBundleEntry(chunk, file, shouldMangle, mangledSources, externalClasses) {
|
|
4383
|
+
if (chunk.type === "asset" && chunk.fileName.endsWith(".css") && chunk.source !== void 0) {
|
|
4384
|
+
const originalCss = chunk.source.toString();
|
|
4385
|
+
const css = rewriteOutputCss(
|
|
4386
|
+
originalCss,
|
|
4387
|
+
file,
|
|
4388
|
+
shouldMangle,
|
|
4389
|
+
mangledSources,
|
|
4390
|
+
externalClasses
|
|
4391
|
+
);
|
|
4392
|
+
if (css !== originalCss) chunk.source = css;
|
|
4393
|
+
return;
|
|
4394
|
+
}
|
|
4395
|
+
if (chunk.type !== "chunk" || chunk.code === void 0) return;
|
|
4396
|
+
const rewritten = shouldMangle ? replacePlaceholders(mangleCodeClasses(chunk.code)) : replacePlaceholders(chunk.code);
|
|
4397
|
+
if (rewritten !== chunk.code) chunk.code = rewritten;
|
|
4398
|
+
}
|
|
4399
|
+
function processRollupBundle(bundle, emitAsset) {
|
|
4400
|
+
finalizeMangleMap();
|
|
4401
|
+
state.globalVarValidationResult = validateGlobalVarBundleInputs(
|
|
4402
|
+
collectRollupGlobalVarCssAssets(bundle)
|
|
4403
|
+
);
|
|
4404
|
+
const shouldMangle = manglingEnabled && Object.keys(state.mangleMap).length > 0;
|
|
4405
|
+
emitAsset("csszyx-manifest.json", JSON.stringify(createBundleManifest(shouldMangle)));
|
|
4406
|
+
if (shouldEmitGlobalVarMapAsset(globalVarMangleConfig)) {
|
|
4407
|
+
const globalVarMap = createGlobalVarMapAssetSource(
|
|
4408
|
+
state.varMangleMap,
|
|
4409
|
+
globalVarAliasPrefix,
|
|
4410
|
+
state.globalVarValidationResult
|
|
4411
|
+
);
|
|
4412
|
+
if (globalVarMap) emitAsset(".csszyx/global-var-map.json", globalVarMap);
|
|
4413
|
+
}
|
|
4414
|
+
const mangledSources = /* @__PURE__ */ new Set();
|
|
4415
|
+
const externalClasses = /* @__PURE__ */ new Set();
|
|
4416
|
+
for (const file in bundle) {
|
|
4417
|
+
rewriteViteBundleEntry(
|
|
4418
|
+
bundle[file],
|
|
4419
|
+
file,
|
|
4420
|
+
shouldMangle,
|
|
4421
|
+
mangledSources,
|
|
4422
|
+
externalClasses
|
|
4423
|
+
);
|
|
4424
|
+
}
|
|
4425
|
+
reportOutputMangleHazards(shouldMangle, mangledSources, externalClasses);
|
|
4426
|
+
}
|
|
3826
4427
|
const postPlugin = createUnplugin(() => ({
|
|
3827
4428
|
name: "csszyx:post",
|
|
3828
4429
|
enforce: "post",
|
|
@@ -3833,278 +4434,20 @@ ${transformedCode}`;
|
|
|
3833
4434
|
* @param compiler - the Webpack compiler instance
|
|
3834
4435
|
*/
|
|
3835
4436
|
webpack(compiler) {
|
|
3836
|
-
compiler
|
|
3837
|
-
const stage = compiler.webpack?.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE || compilation.constructor.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE;
|
|
3838
|
-
compilation.hooks.processAssets.tap(
|
|
3839
|
-
{
|
|
3840
|
-
name: "csszyx:post",
|
|
3841
|
-
stage: stage || 400
|
|
3842
|
-
// Fallback integer
|
|
3843
|
-
},
|
|
3844
|
-
(assets) => {
|
|
3845
|
-
finalizeMangleMap();
|
|
3846
|
-
state.globalVarValidationResult = validateGlobalVarBundleInputs(
|
|
3847
|
-
collectWebpackGlobalVarCssAssets(assets)
|
|
3848
|
-
);
|
|
3849
|
-
const isWebpackDevMode = compiler.options.mode === "development";
|
|
3850
|
-
const manifestData = {
|
|
3851
|
-
version: "0.4.0",
|
|
3852
|
-
buildId: state.checksum,
|
|
3853
|
-
classes: Object.keys(state.mangleMap)
|
|
3854
|
-
};
|
|
3855
|
-
if (manglingEnabled && !isWebpackDevMode && Object.keys(state.mangleMap).length > 0) {
|
|
3856
|
-
manifestData.mangleMap = state.mangleMap;
|
|
3857
|
-
}
|
|
3858
|
-
if (Object.keys(state.varMangleMap).length > 0) {
|
|
3859
|
-
manifestData.varMangleMap = state.varMangleMap;
|
|
3860
|
-
}
|
|
3861
|
-
const globalVarAliases = extractGlobalVarAliasesForManifest(
|
|
3862
|
-
state.varMangleMap,
|
|
3863
|
-
globalVarAliasPrefix,
|
|
3864
|
-
state.globalVarValidationResult
|
|
3865
|
-
);
|
|
3866
|
-
if (Object.keys(globalVarAliases).length > 0) {
|
|
3867
|
-
manifestData.globalVarAliases = globalVarAliases;
|
|
3868
|
-
}
|
|
3869
|
-
if (hasCSSVariableMetrics(state.cssVarMetrics)) {
|
|
3870
|
-
manifestData.cssVarMetrics = state.cssVarMetrics;
|
|
3871
|
-
}
|
|
3872
|
-
compilation.emitAsset(
|
|
3873
|
-
"csszyx-manifest.json",
|
|
3874
|
-
new compiler.webpack.sources.RawSource(JSON.stringify(manifestData))
|
|
3875
|
-
);
|
|
3876
|
-
if (shouldEmitGlobalVarMapAsset(globalVarMangleConfig)) {
|
|
3877
|
-
const globalVarMapAsset = createGlobalVarMapAssetSource(
|
|
3878
|
-
state.varMangleMap,
|
|
3879
|
-
globalVarAliasPrefix,
|
|
3880
|
-
state.globalVarValidationResult
|
|
3881
|
-
);
|
|
3882
|
-
if (globalVarMapAsset) {
|
|
3883
|
-
compilation.emitAsset(
|
|
3884
|
-
".csszyx/global-var-map.json",
|
|
3885
|
-
new compiler.webpack.sources.RawSource(globalVarMapAsset)
|
|
3886
|
-
);
|
|
3887
|
-
}
|
|
3888
|
-
}
|
|
3889
|
-
const mangledSources = /* @__PURE__ */ new Set();
|
|
3890
|
-
const externalClasses = /* @__PURE__ */ new Set();
|
|
3891
|
-
for (const file in assets) {
|
|
3892
|
-
const asset = assets[file];
|
|
3893
|
-
const source = asset.source().toString();
|
|
3894
|
-
if (file.endsWith(".css")) {
|
|
3895
|
-
let css = rewriteCssWithValidatedGlobalVarPlan(
|
|
3896
|
-
source,
|
|
3897
|
-
file,
|
|
3898
|
-
state.globalVarValidationResult
|
|
3899
|
-
);
|
|
3900
|
-
if (manglingEnabled && !isWebpackDevMode && Object.keys(state.mangleMap).length > 0) {
|
|
3901
|
-
try {
|
|
3902
|
-
const result = mangleCSSSync(css, state.mangleMap, {
|
|
3903
|
-
debug: options.development?.debug,
|
|
3904
|
-
from: file
|
|
3905
|
-
});
|
|
3906
|
-
for (const c of result.mangledClasses) {
|
|
3907
|
-
mangledSources.add(c);
|
|
3908
|
-
}
|
|
3909
|
-
for (const c of result.unmangledClasses) {
|
|
3910
|
-
externalClasses.add(c);
|
|
3911
|
-
}
|
|
3912
|
-
if (result.transformedCount > 0) {
|
|
3913
|
-
css = result.css;
|
|
3914
|
-
}
|
|
3915
|
-
} catch (e) {
|
|
3916
|
-
if (e && typeof e === "object" && "name" in e && e.name === "CssSyntaxError") ; else {
|
|
3917
|
-
throw e;
|
|
3918
|
-
}
|
|
3919
|
-
}
|
|
3920
|
-
}
|
|
3921
|
-
if (css !== source) {
|
|
3922
|
-
compilation.updateAsset(
|
|
3923
|
-
file,
|
|
3924
|
-
new compiler.webpack.sources.RawSource(css)
|
|
3925
|
-
);
|
|
3926
|
-
}
|
|
3927
|
-
continue;
|
|
3928
|
-
}
|
|
3929
|
-
if (manglingEnabled && !isWebpackDevMode && Object.keys(state.mangleMap).length > 0) {
|
|
3930
|
-
if (file.endsWith(".html")) {
|
|
3931
|
-
const mangledHtml = source.replace(
|
|
3932
|
-
/\bclass="([^"]*)"/g,
|
|
3933
|
-
(_m, cls) => {
|
|
3934
|
-
const out = cls.split(/\s+/).filter(Boolean).map((c) => state.mangleMap[c] || c).join(" ");
|
|
3935
|
-
return out !== cls ? `class="${out}"` : _m;
|
|
3936
|
-
}
|
|
3937
|
-
).replace(
|
|
3938
|
-
/\bclass='([^']*)'/g,
|
|
3939
|
-
(_m, cls) => {
|
|
3940
|
-
const out = cls.split(/\s+/).filter(Boolean).map((c) => state.mangleMap[c] || c).join(" ");
|
|
3941
|
-
return out !== cls ? `class='${out}'` : _m;
|
|
3942
|
-
}
|
|
3943
|
-
);
|
|
3944
|
-
if (mangledHtml !== source) {
|
|
3945
|
-
compilation.updateAsset(
|
|
3946
|
-
file,
|
|
3947
|
-
new compiler.webpack.sources.RawSource(mangledHtml)
|
|
3948
|
-
);
|
|
3949
|
-
continue;
|
|
3950
|
-
}
|
|
3951
|
-
} else if (file.endsWith(".js")) {
|
|
3952
|
-
let mangled = mangleCodeClasses(source);
|
|
3953
|
-
mangled = replacePlaceholders(mangled);
|
|
3954
|
-
if (mangled !== source) {
|
|
3955
|
-
compilation.updateAsset(
|
|
3956
|
-
file,
|
|
3957
|
-
new compiler.webpack.sources.RawSource(mangled)
|
|
3958
|
-
);
|
|
3959
|
-
continue;
|
|
3960
|
-
}
|
|
3961
|
-
}
|
|
3962
|
-
}
|
|
3963
|
-
if (file.endsWith(".js") && (source.includes(CHECKSUM_PLACEHOLDER) || source.includes(MANGLE_MAP_PLACEHOLDER))) {
|
|
3964
|
-
const replaced = replacePlaceholders(source);
|
|
3965
|
-
if (replaced !== source) {
|
|
3966
|
-
compilation.updateAsset(
|
|
3967
|
-
file,
|
|
3968
|
-
new compiler.webpack.sources.RawSource(replaced)
|
|
3969
|
-
);
|
|
3970
|
-
}
|
|
3971
|
-
}
|
|
3972
|
-
}
|
|
3973
|
-
if (manglingEnabled && !isWebpackDevMode && Object.keys(state.mangleMap).length > 0) {
|
|
3974
|
-
const hazardMessage = mangleHybridHazardMessage(
|
|
3975
|
-
collectMangleHybridHazards(
|
|
3976
|
-
state.mangleMap,
|
|
3977
|
-
mangledSources,
|
|
3978
|
-
externalClasses
|
|
3979
|
-
)
|
|
3980
|
-
);
|
|
3981
|
-
if (hazardMessage) {
|
|
3982
|
-
console.warn(hazardMessage);
|
|
3983
|
-
}
|
|
3984
|
-
}
|
|
3985
|
-
}
|
|
3986
|
-
);
|
|
3987
|
-
});
|
|
4437
|
+
registerWebpackAssetProcessor(compiler, processWebpackAssets);
|
|
3988
4438
|
},
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
);
|
|
4000
|
-
|
|
4001
|
-
version: "0.4.0",
|
|
4002
|
-
buildId: state.checksum,
|
|
4003
|
-
classes: Object.keys(state.mangleMap)
|
|
4004
|
-
};
|
|
4005
|
-
if (manglingEnabled && Object.keys(state.mangleMap).length > 0) {
|
|
4006
|
-
manifestData.mangleMap = state.mangleMap;
|
|
4007
|
-
}
|
|
4008
|
-
if (Object.keys(state.varMangleMap).length > 0) {
|
|
4009
|
-
manifestData.varMangleMap = state.varMangleMap;
|
|
4010
|
-
}
|
|
4011
|
-
const globalVarAliases = extractGlobalVarAliasesForManifest(
|
|
4012
|
-
state.varMangleMap,
|
|
4013
|
-
globalVarAliasPrefix,
|
|
4014
|
-
state.globalVarValidationResult
|
|
4015
|
-
);
|
|
4016
|
-
if (Object.keys(globalVarAliases).length > 0) {
|
|
4017
|
-
manifestData.globalVarAliases = globalVarAliases;
|
|
4018
|
-
}
|
|
4019
|
-
if (hasCSSVariableMetrics(state.cssVarMetrics)) {
|
|
4020
|
-
manifestData.cssVarMetrics = state.cssVarMetrics;
|
|
4021
|
-
}
|
|
4022
|
-
this.emitFile({
|
|
4023
|
-
type: "asset",
|
|
4024
|
-
fileName: "csszyx-manifest.json",
|
|
4025
|
-
source: JSON.stringify(manifestData)
|
|
4026
|
-
});
|
|
4027
|
-
if (shouldEmitGlobalVarMapAsset(globalVarMangleConfig)) {
|
|
4028
|
-
const globalVarMapAsset = createGlobalVarMapAssetSource(
|
|
4029
|
-
state.varMangleMap,
|
|
4030
|
-
globalVarAliasPrefix,
|
|
4031
|
-
state.globalVarValidationResult
|
|
4032
|
-
);
|
|
4033
|
-
if (globalVarMapAsset) {
|
|
4034
|
-
this.emitFile({
|
|
4035
|
-
type: "asset",
|
|
4036
|
-
fileName: ".csszyx/global-var-map.json",
|
|
4037
|
-
source: globalVarMapAsset
|
|
4038
|
-
});
|
|
4039
|
-
}
|
|
4040
|
-
}
|
|
4041
|
-
const mangledSources = /* @__PURE__ */ new Set();
|
|
4042
|
-
const externalClasses = /* @__PURE__ */ new Set();
|
|
4043
|
-
for (const file in bundle) {
|
|
4044
|
-
const chunk = bundle[file];
|
|
4045
|
-
if (chunk.type === "asset" && chunk.fileName.endsWith(".css")) {
|
|
4046
|
-
const originalCss = chunk.source.toString();
|
|
4047
|
-
let css = rewriteCssWithValidatedGlobalVarPlan(
|
|
4048
|
-
originalCss,
|
|
4049
|
-
file,
|
|
4050
|
-
state.globalVarValidationResult
|
|
4051
|
-
);
|
|
4052
|
-
if (manglingEnabled && Object.keys(state.mangleMap).length > 0) {
|
|
4053
|
-
try {
|
|
4054
|
-
const result = mangleCSSSync(css, state.mangleMap, {
|
|
4055
|
-
debug: options.development?.debug,
|
|
4056
|
-
from: file
|
|
4057
|
-
});
|
|
4058
|
-
for (const c of result.mangledClasses) {
|
|
4059
|
-
mangledSources.add(c);
|
|
4060
|
-
}
|
|
4061
|
-
for (const c of result.unmangledClasses) {
|
|
4062
|
-
externalClasses.add(c);
|
|
4063
|
-
}
|
|
4064
|
-
if (result.transformedCount > 0) {
|
|
4065
|
-
css = result.css;
|
|
4066
|
-
}
|
|
4067
|
-
} catch (e) {
|
|
4068
|
-
if (e && typeof e === "object" && "name" in e && e.name === "CssSyntaxError") ; else {
|
|
4069
|
-
throw e;
|
|
4070
|
-
}
|
|
4071
|
-
}
|
|
4072
|
-
}
|
|
4073
|
-
if (css !== originalCss) {
|
|
4074
|
-
chunk.source = css;
|
|
4075
|
-
}
|
|
4076
|
-
continue;
|
|
4077
|
-
}
|
|
4078
|
-
if (manglingEnabled && Object.keys(state.mangleMap).length > 0) {
|
|
4079
|
-
if (chunk.type === "chunk") {
|
|
4080
|
-
let mangledCode = mangleCodeClasses(chunk.code);
|
|
4081
|
-
mangledCode = replacePlaceholders(mangledCode);
|
|
4082
|
-
if (mangledCode !== chunk.code) {
|
|
4083
|
-
chunk.code = mangledCode;
|
|
4084
|
-
}
|
|
4085
|
-
continue;
|
|
4086
|
-
}
|
|
4087
|
-
}
|
|
4088
|
-
if (chunk.type === "chunk" && (chunk.code.includes(CHECKSUM_PLACEHOLDER) || chunk.code.includes(MANGLE_MAP_PLACEHOLDER))) {
|
|
4089
|
-
const replaced = replacePlaceholders(chunk.code);
|
|
4090
|
-
if (replaced !== chunk.code) {
|
|
4091
|
-
chunk.code = replaced;
|
|
4092
|
-
}
|
|
4093
|
-
}
|
|
4094
|
-
}
|
|
4095
|
-
if (manglingEnabled && Object.keys(state.mangleMap).length > 0) {
|
|
4096
|
-
const hazardMessage = mangleHybridHazardMessage(
|
|
4097
|
-
collectMangleHybridHazards(
|
|
4098
|
-
state.mangleMap,
|
|
4099
|
-
mangledSources,
|
|
4100
|
-
externalClasses
|
|
4101
|
-
)
|
|
4102
|
-
);
|
|
4103
|
-
if (hazardMessage) {
|
|
4104
|
-
console.warn(hazardMessage);
|
|
4105
|
-
}
|
|
4106
|
-
}
|
|
4107
|
-
}
|
|
4439
|
+
/**
|
|
4440
|
+
* Rollup-compatible hook used by both pure Rollup and Vite adapters.
|
|
4441
|
+
*
|
|
4442
|
+
* @param this Rollup-compatible output hook context.
|
|
4443
|
+
* @param this.emitFile Output asset emitter.
|
|
4444
|
+
* @param _options Output options (unused).
|
|
4445
|
+
* @param bundle Complete Rollup output bundle.
|
|
4446
|
+
*/
|
|
4447
|
+
generateBundle(_options, bundle) {
|
|
4448
|
+
processRollupBundle(bundle, (fileName, source) => {
|
|
4449
|
+
this.emitFile({ type: "asset", fileName, source });
|
|
4450
|
+
});
|
|
4108
4451
|
}
|
|
4109
4452
|
}));
|
|
4110
4453
|
return { prePlugin, postPlugin };
|
|
@@ -4136,7 +4479,16 @@ const rollupPlugin = (options = {}) => {
|
|
|
4136
4479
|
];
|
|
4137
4480
|
};
|
|
4138
4481
|
const esbuildPlugin = (options = {}) => {
|
|
4139
|
-
|
|
4482
|
+
if (options.production?.mangle === true) {
|
|
4483
|
+
console.warn(
|
|
4484
|
+
"[csszyx] production.mangle is not supported by the esbuild adapter; class mangling is disabled so emitted JS and CSS keep matching names."
|
|
4485
|
+
);
|
|
4486
|
+
}
|
|
4487
|
+
const safeOptions = {
|
|
4488
|
+
...options,
|
|
4489
|
+
production: { ...options.production, mangle: false }
|
|
4490
|
+
};
|
|
4491
|
+
const { prePlugin, postPlugin } = createCsszyxPlugins(safeOptions);
|
|
4140
4492
|
return {
|
|
4141
4493
|
name: "csszyx",
|
|
4142
4494
|
/**
|
|
@@ -4145,10 +4497,10 @@ const esbuildPlugin = (options = {}) => {
|
|
|
4145
4497
|
*/
|
|
4146
4498
|
setup(build) {
|
|
4147
4499
|
const b = build;
|
|
4148
|
-
prePlugin.esbuild(
|
|
4149
|
-
postPlugin.esbuild(
|
|
4500
|
+
prePlugin.esbuild(safeOptions).setup(b);
|
|
4501
|
+
postPlugin.esbuild(safeOptions).setup(b);
|
|
4150
4502
|
}
|
|
4151
4503
|
};
|
|
4152
4504
|
};
|
|
4153
4505
|
|
|
4154
|
-
export {
|
|
4506
|
+
export { vitePlugin as $, isPackagesSkippedSource as A, isRSCServerModule as B, isTailwindReservedGlobalVar as C, mangleCodeClassesSync as D, mangleEligibleClasses as E, mangleHybridHazardMessage as F, mergeThemes as G, missingTailwindEntryMessage as H, normalizeGlobalVarAliasesForCache as I, parseThemeBlocks as J, planGlobalVarAliases as K, readGlobalVarScanCache as L, recordGlobalVarSourceFile as M, resolveCompileSourceDirs as N, resolveGlobalVarScanCacheDir as O, resolveNativeCacheIdentity as P, rewriteGlobalVarCssAliases as Q, rollupPlugin as R, scanCustomPropertyNames as S, scanGlobalVarCss as T, shouldEmitWarning as U, shouldTrackGlobalVarSources as V, shouldWarnMissingTailwindEntry as W, shouldWarnUnscopedMonorepo as X, skippedSzFilesMessage as Y, unscopedMonorepoMessage as Z, validateGlobalVarAliasInputs as _, appendTailwindSourceDirective as a, webpackPlugin as a0, writeGlobalVarScanCache as a1, assertNoRSCBoundaryViolation as b, assertNoRSCGraphViolation as c, collectMangleHybridHazards as d, computeSafelistRelPath as e, createGlobalVarAliasValidationOptions as f, createGlobalVarMapAssetSource as g, createGlobalVarScanCacheKey as h, createRSCModuleRecord as i, cssHasContentScope as j, cssImportsTailwind as k, deleteRSCModuleRecord as l, esbuildPlugin as m, extractGlobalVarAliasesForManifest as n, fileMayContainSafelistableSz as o, findLocalImportSources as p, findRSCBoundaryViolation as q, findRSCGraphViolation as r, hasInjectableTailwindCandidate as s, hasTokens as t, unplugin as u, hasUseClientDirective as v, hasUseServerDirective as w, isCompileSourceOptedIn as x, isHardIgnoredPath as y, isMonorepoPackage as z };
|