@csszyx/unplugin 0.14.5 → 0.15.1
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 +4 -3
- package/dist/index.cjs +8 -7
- package/dist/index.d.cts +70 -3
- package/dist/index.d.mts +70 -3
- package/dist/index.mjs +4 -4
- package/dist/next-config.d.cts +1 -2
- package/dist/next-config.d.mts +1 -2
- package/dist/next-prebuild.cjs +9 -5
- package/dist/next-prebuild.d.cts +4 -2
- package/dist/next-prebuild.d.mts +4 -2
- package/dist/next-prebuild.mjs +8 -4
- package/dist/next-turbo-loader.cjs +20 -14
- package/dist/next-turbo-loader.d.cts +1 -1
- package/dist/next-turbo-loader.d.mts +1 -1
- package/dist/next-turbo-loader.mjs +19 -13
- package/dist/next-watcher.cjs +2 -2
- package/dist/next-watcher.d.cts +2 -2
- package/dist/next-watcher.d.mts +2 -2
- package/dist/next-watcher.mjs +2 -2
- package/dist/postcss.cjs +124 -0
- package/dist/postcss.d.cts +42 -0
- package/dist/postcss.d.mts +42 -0
- package/dist/postcss.mjs +107 -0
- package/dist/shared/{unplugin.RGzhYt-D.cjs → unplugin.8KYddE6x.cjs} +394 -226
- package/dist/shared/{unplugin.CPEWNSA0.d.cts → unplugin.BGog1Bib.d.cts} +9 -6
- package/dist/shared/{unplugin.CPEWNSA0.d.mts → unplugin.BGog1Bib.d.mts} +9 -6
- package/dist/shared/{unplugin.BU0O4IkX.mjs → unplugin.BLptVbUe.mjs} +22 -61
- package/dist/shared/{unplugin.BXYakiXt.d.cts → unplugin.BT7PqYuK.d.cts} +53 -55
- package/dist/shared/{unplugin.BXYakiXt.d.mts → unplugin.BT7PqYuK.d.mts} +53 -55
- package/dist/shared/{unplugin.Cji6O5jv.cjs → unplugin.BWnmKv07.cjs} +32 -69
- package/dist/shared/{unplugin.NlPvn5P4.mjs → unplugin.Bk9o8_RZ.mjs} +2 -6
- package/dist/shared/{unplugin.VtXstzEh.cjs → unplugin.BzF0V2kw.cjs} +6 -11
- package/dist/shared/{unplugin.CdZxp0x-.d.mts → unplugin.COlI0dJs.d.mts} +1 -1
- package/dist/shared/{unplugin.BnRf0Tvd.mjs → unplugin.D68hyqgb.mjs} +347 -178
- package/dist/shared/{unplugin.DN95k991.mjs → unplugin.DAzgbtuZ.mjs} +2 -2
- package/dist/shared/unplugin.DDSWQJYX.cjs +289 -0
- package/dist/shared/unplugin.DH_ij6cf.mjs +258 -0
- package/dist/shared/{unplugin.BZPdvVcj.mjs → unplugin.DK0b4fr7.mjs} +105 -127
- package/dist/shared/{unplugin.D8BxOOkA.cjs → unplugin.J6ue_lRJ.cjs} +121 -142
- package/dist/shared/{unplugin.DVbPNK3W.cjs → unplugin.gksolKh2.cjs} +6 -6
- package/dist/shared/{unplugin.xeED_qwh.d.cts → unplugin.rWOMecQs.d.cts} +1 -1
- package/dist/vite.cjs +4 -4
- package/dist/vite.d.cts +2 -2
- package/dist/vite.d.mts +1 -1
- package/dist/vite.mjs +4 -4
- package/dist/webpack.cjs +4 -4
- package/dist/webpack.d.cts +2 -1
- package/dist/webpack.d.mts +1 -1
- package/dist/webpack.mjs +4 -4
- package/package.json +19 -9
- package/dist/shared/unplugin.B3XoSRB8.mjs +0 -40
- package/dist/shared/unplugin.BkRah5Ot.cjs +0 -48
|
@@ -9,8 +9,17 @@ interface NextCacheIdentity {
|
|
|
9
9
|
generation: string;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
/** Options for atomic file writes that need to survive Windows file scanners. */
|
|
13
|
+
interface AtomicWriteOptions {
|
|
14
|
+
maxRetries?: number;
|
|
15
|
+
retryDelayMs?: number;
|
|
16
|
+
renameSync?: (from: string, to: string) => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
12
19
|
/** Files used by the Next Turbopack safelist state machine. */
|
|
13
20
|
interface NextSafelistStatePaths {
|
|
21
|
+
/** Project root the safelist and cache live under. */
|
|
22
|
+
rootDir: string;
|
|
14
23
|
cacheDir: string;
|
|
15
24
|
shardsDir: string;
|
|
16
25
|
snapshotPath: string;
|
|
@@ -23,12 +32,6 @@ interface NextSafelistMaterializeResult {
|
|
|
23
32
|
tombstonedSourceCount: number;
|
|
24
33
|
shardCount: number;
|
|
25
34
|
}
|
|
26
|
-
/** Options for atomic file writes that need to survive Windows file scanners. */
|
|
27
|
-
interface AtomicWriteOptions {
|
|
28
|
-
maxRetries?: number;
|
|
29
|
-
retryDelayMs?: number;
|
|
30
|
-
renameSync?: (from: string, to: string) => void;
|
|
31
|
-
}
|
|
32
35
|
/** Options used when acquiring a state lock. */
|
|
33
36
|
interface NextSafelistStateLockOptions {
|
|
34
37
|
pid?: number;
|
|
@@ -9,8 +9,17 @@ interface NextCacheIdentity {
|
|
|
9
9
|
generation: string;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
/** Options for atomic file writes that need to survive Windows file scanners. */
|
|
13
|
+
interface AtomicWriteOptions {
|
|
14
|
+
maxRetries?: number;
|
|
15
|
+
retryDelayMs?: number;
|
|
16
|
+
renameSync?: (from: string, to: string) => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
12
19
|
/** Files used by the Next Turbopack safelist state machine. */
|
|
13
20
|
interface NextSafelistStatePaths {
|
|
21
|
+
/** Project root the safelist and cache live under. */
|
|
22
|
+
rootDir: string;
|
|
14
23
|
cacheDir: string;
|
|
15
24
|
shardsDir: string;
|
|
16
25
|
snapshotPath: string;
|
|
@@ -23,12 +32,6 @@ interface NextSafelistMaterializeResult {
|
|
|
23
32
|
tombstonedSourceCount: number;
|
|
24
33
|
shardCount: number;
|
|
25
34
|
}
|
|
26
|
-
/** Options for atomic file writes that need to survive Windows file scanners. */
|
|
27
|
-
interface AtomicWriteOptions {
|
|
28
|
-
maxRetries?: number;
|
|
29
|
-
retryDelayMs?: number;
|
|
30
|
-
renameSync?: (from: string, to: string) => void;
|
|
31
|
-
}
|
|
32
35
|
/** Options used when acquiring a state lock. */
|
|
33
36
|
interface NextSafelistStateLockOptions {
|
|
34
37
|
pid?: number;
|
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import * as path from 'node:path';
|
|
2
2
|
import * as fs from 'node:fs';
|
|
3
|
+
import { S as SAFELIST_FILE, d as atomicWriteFileSync, s as sortStrings, r as renderSafelistFile, e as removeLegacySafelists, g as assertNoLegacySourceStylesheet } from './unplugin.DH_ij6cf.mjs';
|
|
3
4
|
import { createHash, randomUUID } from 'node:crypto';
|
|
4
5
|
import { hostname } from 'node:os';
|
|
5
6
|
import lockfile from 'proper-lockfile';
|
|
6
|
-
import { s as sortStrings, e as escapeHtmlAttribute, r as renderTailwindScannerCandidates } from './unplugin.B3XoSRB8.mjs';
|
|
7
7
|
|
|
8
|
-
const DEFAULT_RENAME_RETRIES = 5;
|
|
9
|
-
const DEFAULT_RENAME_RETRY_DELAY_MS = 10;
|
|
10
8
|
const DEFAULT_STALE_LOCK_MS = 3e4;
|
|
11
9
|
const STALE_RECOVERY_DISABLED_MS = 2147483647;
|
|
12
|
-
function resolveNextSafelistStatePaths(rootDir, cacheDir = ".csszyx/cache", outputFile =
|
|
10
|
+
function resolveNextSafelistStatePaths(rootDir, cacheDir = ".csszyx/cache", outputFile = SAFELIST_FILE) {
|
|
13
11
|
const resolvedCacheDir = path.resolve(rootDir, cacheDir);
|
|
14
12
|
return {
|
|
13
|
+
rootDir: path.resolve(rootDir),
|
|
15
14
|
cacheDir: resolvedCacheDir,
|
|
16
15
|
shardsDir: path.join(resolvedCacheDir, "safelist-shards"),
|
|
17
16
|
snapshotPath: path.join(resolvedCacheDir, "safelist.snapshot.json"),
|
|
@@ -48,7 +47,8 @@ function materializeNextSafelist(paths, options = {}) {
|
|
|
48
47
|
version: 1,
|
|
49
48
|
sources: sortedSources.map(([sourcePath, classSet]) => [sourcePath, classSet])
|
|
50
49
|
};
|
|
51
|
-
atomicWriteFileSync(paths.outputPath,
|
|
50
|
+
atomicWriteFileSync(paths.outputPath, renderSafelistFile(classNames), options);
|
|
51
|
+
removeLegacySafelists(paths.rootDir, console.warn);
|
|
52
52
|
atomicWriteFileSync(paths.snapshotPath, `${JSON.stringify(snapshot, null, 2)}
|
|
53
53
|
`, options);
|
|
54
54
|
return {
|
|
@@ -80,14 +80,14 @@ function acquireNextSafelistStateLock(lockPath, pidOrOptions = {}) {
|
|
|
80
80
|
} catch (error) {
|
|
81
81
|
const existing2 = readLockMetadata(lockPath);
|
|
82
82
|
if (existing2) {
|
|
83
|
-
throw new
|
|
83
|
+
throw new NextSafelistStateLockedError(existing2);
|
|
84
84
|
}
|
|
85
85
|
throw error;
|
|
86
86
|
}
|
|
87
87
|
const existing = readLockMetadata(lockPath);
|
|
88
88
|
if (existing && isLockLive(existing, options)) {
|
|
89
89
|
releaseAdvisory();
|
|
90
|
-
throw new
|
|
90
|
+
throw new NextSafelistStateLockedError(existing);
|
|
91
91
|
}
|
|
92
92
|
try {
|
|
93
93
|
atomicWriteFileSync(lockPath, `${JSON.stringify(metadata, null, 2)}
|
|
@@ -128,40 +128,6 @@ function acquireNextSafelistStateLock(lockPath, pidOrOptions = {}) {
|
|
|
128
128
|
}
|
|
129
129
|
};
|
|
130
130
|
}
|
|
131
|
-
function atomicWriteFileSync(file, content, options = {}) {
|
|
132
|
-
const dir = path.dirname(file);
|
|
133
|
-
const tmp = path.join(
|
|
134
|
-
dir,
|
|
135
|
-
`.tmp-${path.basename(file)}-${process.pid}-${Date.now()}-${randomUUID()}`
|
|
136
|
-
);
|
|
137
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
138
|
-
fs.writeFileSync(tmp, content, "utf8");
|
|
139
|
-
try {
|
|
140
|
-
atomicRenameWithRetry(tmp, file, options);
|
|
141
|
-
} catch (error) {
|
|
142
|
-
try {
|
|
143
|
-
fs.rmSync(tmp, { force: true });
|
|
144
|
-
} catch {
|
|
145
|
-
}
|
|
146
|
-
throw error;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
function atomicRenameWithRetry(from, to, options = {}) {
|
|
150
|
-
const maxRetries = options.maxRetries ?? DEFAULT_RENAME_RETRIES;
|
|
151
|
-
const retryDelayMs = options.retryDelayMs ?? DEFAULT_RENAME_RETRY_DELAY_MS;
|
|
152
|
-
const renameSync = options.renameSync ?? fs.renameSync;
|
|
153
|
-
for (let attempt = 0; ; attempt++) {
|
|
154
|
-
try {
|
|
155
|
-
renameSync(from, to);
|
|
156
|
-
return;
|
|
157
|
-
} catch (error) {
|
|
158
|
-
if (!isRetryableRenameError(error) || attempt >= maxRetries) {
|
|
159
|
-
throw error;
|
|
160
|
-
}
|
|
161
|
-
sleepSync(retryDelayMs);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
131
|
function isExistingShardEquivalent(filePath, shard) {
|
|
166
132
|
try {
|
|
167
133
|
const parsed = JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
@@ -232,15 +198,6 @@ function normalizeShardRecord(filePath, data) {
|
|
|
232
198
|
})
|
|
233
199
|
};
|
|
234
200
|
}
|
|
235
|
-
function renderTailwindSourceHtml(classNames) {
|
|
236
|
-
if (classNames.length === 0) {
|
|
237
|
-
return "<!-- csszyx Next safelist: empty -->\n";
|
|
238
|
-
}
|
|
239
|
-
const structuralHtml = classNames.map((className) => `<div class="${escapeHtmlAttribute(className)}"></div>`).join("\n");
|
|
240
|
-
const scannerCandidates = renderTailwindScannerCandidates(classNames);
|
|
241
|
-
return `${structuralHtml}
|
|
242
|
-
${scannerCandidates}`;
|
|
243
|
-
}
|
|
244
201
|
function createLockMetadata(options) {
|
|
245
202
|
const now = new Date(options.now ?? Date.now()).toISOString();
|
|
246
203
|
const pid = options.pid ?? process.pid;
|
|
@@ -337,6 +294,18 @@ function isProcessAlive(pid) {
|
|
|
337
294
|
return false;
|
|
338
295
|
}
|
|
339
296
|
}
|
|
297
|
+
class NextSafelistStateLockedError extends Error {
|
|
298
|
+
holder;
|
|
299
|
+
/**
|
|
300
|
+
* @param holder - metadata read from the lock file.
|
|
301
|
+
*/
|
|
302
|
+
constructor(holder) {
|
|
303
|
+
super(formatLiveLockError(holder));
|
|
304
|
+
this.name = "NextSafelistStateLockedError";
|
|
305
|
+
this.holder = holder;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
const NEXT_WATCH_LOCK_COMMAND = "csszyx next watch";
|
|
340
309
|
function formatLiveLockError(metadata) {
|
|
341
310
|
return [
|
|
342
311
|
`csszyx Next safelist state is already locked by process ${metadata.pid}.`,
|
|
@@ -346,15 +315,6 @@ function formatLiveLockError(metadata) {
|
|
|
346
315
|
`updatedAt=${metadata.updatedAt}`
|
|
347
316
|
].join(" ");
|
|
348
317
|
}
|
|
349
|
-
function isRetryableRenameError(error) {
|
|
350
|
-
return typeof error === "object" && error !== null && "code" in error && (error.code === "EBUSY" || error.code === "EPERM" || error.code === "EACCES");
|
|
351
|
-
}
|
|
352
|
-
function sleepSync(ms) {
|
|
353
|
-
if (ms <= 0) {
|
|
354
|
-
return;
|
|
355
|
-
}
|
|
356
|
-
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
357
|
-
}
|
|
358
318
|
|
|
359
319
|
function createNextCacheIdentity(input) {
|
|
360
320
|
const configHash = hashString(stableStringify(input.config));
|
|
@@ -515,6 +475,7 @@ function isNestedPackageRoot(parentRoot, candidateRoot) {
|
|
|
515
475
|
|
|
516
476
|
function createNextStateContext(input) {
|
|
517
477
|
const rootResolution = resolveNextAppRoot(input);
|
|
478
|
+
assertNoLegacySourceStylesheet(rootResolution.root);
|
|
518
479
|
const cacheDir = resolveNextAppCacheDir(rootResolution.root, input.cacheDir);
|
|
519
480
|
const identity = createNextCacheIdentity({
|
|
520
481
|
root: rootResolution.root,
|
|
@@ -578,7 +539,7 @@ function runNextWatcherCycle(context, options = {}) {
|
|
|
578
539
|
const lock = acquireNextSafelistStateLock(lockPath, {
|
|
579
540
|
root: context.root,
|
|
580
541
|
mode: context.manifestExpectation.mode,
|
|
581
|
-
command:
|
|
542
|
+
command: NEXT_WATCH_LOCK_COMMAND,
|
|
582
543
|
...options.lockOptions
|
|
583
544
|
});
|
|
584
545
|
try {
|
|
@@ -612,4 +573,4 @@ function runNextWatcherCycle(context, options = {}) {
|
|
|
612
573
|
}
|
|
613
574
|
}
|
|
614
575
|
|
|
615
|
-
export {
|
|
576
|
+
export { NextSafelistStateLockedError as N, NEXT_WATCH_LOCK_COMMAND as a, readNextGenerationManifest as b, createNextStateContext as c, runNextWatcherCycle as r, validateNextGenerationManifest as v, writeNextSafelistShard as w };
|
|
@@ -421,6 +421,45 @@ declare function hasTokens(theme: ParsedTheme): boolean;
|
|
|
421
421
|
*/
|
|
422
422
|
declare function scanCustomPropertyNames(block: string): string[];
|
|
423
423
|
|
|
424
|
+
/**
|
|
425
|
+
* A per-key store whose merged view is built when read, not when written.
|
|
426
|
+
*
|
|
427
|
+
* The plugin keeps two aggregates over "what each file contributed": the CSS
|
|
428
|
+
* variable mangle map and the variable hoisting metrics. Both were rebuilt in
|
|
429
|
+
* full — a sort over every file, then a merge — on EVERY write, and a write
|
|
430
|
+
* happens once per module in the prescan and again in the transform hook. That
|
|
431
|
+
* made recording a module cost as much as every module before it: 18 000
|
|
432
|
+
* files with `mangleVars` on spent 77 s here, a 12× build-time regression that
|
|
433
|
+
* the flag's own benchmarks never showed because their fixtures emitted no
|
|
434
|
+
* variables.
|
|
435
|
+
*
|
|
436
|
+
* Readers (`buildEnd`, the virtual map module, the manifest) run after the
|
|
437
|
+
* writes, so building on read costs one merge per build instead of one per
|
|
438
|
+
* file, and a write followed by a read still sees the write.
|
|
439
|
+
*
|
|
440
|
+
* @module
|
|
441
|
+
*/
|
|
442
|
+
/** A per-key store with a lazily rebuilt merged view. */
|
|
443
|
+
interface LazyAggregate<Entry, Aggregate> {
|
|
444
|
+
/** Contributions by key, in insertion order. */
|
|
445
|
+
readonly entries: ReadonlyMap<string, Entry>;
|
|
446
|
+
/**
|
|
447
|
+
* Record one key's contribution, replacing what it held before.
|
|
448
|
+
*
|
|
449
|
+
* @param key Contribution owner (a normalized filename).
|
|
450
|
+
* @param entry What the owner contributes.
|
|
451
|
+
*/
|
|
452
|
+
set(key: string, entry: Entry): void;
|
|
453
|
+
/**
|
|
454
|
+
* Drop one key's contribution.
|
|
455
|
+
*
|
|
456
|
+
* @param key Contribution owner.
|
|
457
|
+
*/
|
|
458
|
+
delete(key: string): void;
|
|
459
|
+
/** @returns The merged view, rebuilt only if a write happened since the last read. */
|
|
460
|
+
get(): Aggregate;
|
|
461
|
+
}
|
|
462
|
+
|
|
424
463
|
/**
|
|
425
464
|
* Plugin state for mangle map management.
|
|
426
465
|
*/
|
|
@@ -454,6 +493,13 @@ interface PluginState {
|
|
|
454
493
|
* emit their CSS (no entry → the classes resolve to no styles, silently).
|
|
455
494
|
*/
|
|
456
495
|
sawTailwindEntry: boolean;
|
|
496
|
+
/**
|
|
497
|
+
* Absolute paths of every CSS file seen importing `tailwindcss`, without
|
|
498
|
+
* their query. These are the modules whose generated CSS changes when the
|
|
499
|
+
* safelist does, which is what lets a dev server hot-update instead of
|
|
500
|
+
* reloading — see the `hotUpdate` safelist branch.
|
|
501
|
+
*/
|
|
502
|
+
tailwindEntryFiles: Set<string>;
|
|
457
503
|
/**
|
|
458
504
|
* True once ANY CSS file passed through the transform hook. The missing-entry
|
|
459
505
|
* warning only fires when csszyx actually observed the CSS pipeline but found
|
|
@@ -516,10 +562,12 @@ interface PluginState {
|
|
|
516
562
|
*/
|
|
517
563
|
classesCapped: boolean;
|
|
518
564
|
mangleMap: Record<string, string>;
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
cssVarMetrics
|
|
565
|
+
/** CSS variable mangle entries per file; `varMangleMap` is merged from them on read. */
|
|
566
|
+
varMangleEntriesByFile: LazyAggregate<Array<[string, string]>, Record<string, CssVariableMangleValue>>;
|
|
567
|
+
readonly varMangleMap: Record<string, CssVariableMangleValue>;
|
|
568
|
+
/** CSS variable hoisting metrics per file; `cssVarMetrics` is totalled from them on read. */
|
|
569
|
+
cssVarMetricsByFile: LazyAggregate<CSSVariableMetrics, CSSVariableMetrics>;
|
|
570
|
+
readonly cssVarMetrics: CSSVariableMetrics;
|
|
523
571
|
checksum: string;
|
|
524
572
|
finalized: boolean;
|
|
525
573
|
rootDir: string;
|
|
@@ -558,41 +606,6 @@ interface CSSVariableMetrics {
|
|
|
558
606
|
* @returns A stable identity string, or a sentinel when unresolvable.
|
|
559
607
|
*/
|
|
560
608
|
declare function resolveNativeCacheIdentity(): string;
|
|
561
|
-
/**
|
|
562
|
-
* Appends an `@source "<relPath>";` directive to a CSS module so Tailwind v4
|
|
563
|
-
* scans the csszyx-generated safelist file.
|
|
564
|
-
*
|
|
565
|
-
* `@source` is position-independent in Tailwind v4 — it can appear anywhere in
|
|
566
|
-
* the compiled CSS — so the directive is **appended as its own statement**
|
|
567
|
-
* rather than spliced next to the `@import "tailwindcss…"` line. Matching the
|
|
568
|
-
* import syntax is the source of a real defect: the split / manual Tailwind v4
|
|
569
|
-
* setup (`@import "tailwindcss/utilities.css" layer(…)` or `… source(…)`, or an
|
|
570
|
-
* import without a trailing `;`) does not match an import-anchored regex, so the
|
|
571
|
-
* injection silently no-ops and every csszyx-only class (e.g. the static
|
|
572
|
-
* `bg-primary/50` produced by `sz={{ bg: { color, op } }}`) gets no CSS while a
|
|
573
|
-
* raw `className` still works. Appending is correct for every import form.
|
|
574
|
-
*
|
|
575
|
-
* @param code - CSS module source already known to import tailwindcss.
|
|
576
|
-
* @param relPath - safelist path relative to this CSS file (posix, `./`-prefixed).
|
|
577
|
-
* @returns the code with the directive appended, or `null` if it is already
|
|
578
|
-
* present (idempotent — re-running the transform must not stack directives).
|
|
579
|
-
*/
|
|
580
|
-
declare function appendTailwindSourceDirective(code: string, relPath: string): string | null;
|
|
581
|
-
/**
|
|
582
|
-
* Whether a CSS module actually imports the `tailwindcss` package, so the
|
|
583
|
-
* `@source` directive should be appended.
|
|
584
|
-
*
|
|
585
|
-
* Tighter than a substring check on purpose: block comments are stripped first
|
|
586
|
-
* (a commented-out `@import` must not trigger injection), and the package name
|
|
587
|
-
* must end at a quote or a `/` subpath so a different package whose name merely
|
|
588
|
-
* starts with `tailwindcss` (e.g. `tailwindcss-animate`) does not match. Import
|
|
589
|
-
* options after the closing quote (`layer(…)`, `source(…)`) are irrelevant — the
|
|
590
|
-
* match ends at the quote — so every real Tailwind v4 import form is covered.
|
|
591
|
-
*
|
|
592
|
-
* @param code - CSS module source.
|
|
593
|
-
* @returns true if the module imports tailwindcss (exact or a subpath).
|
|
594
|
-
*/
|
|
595
|
-
declare function cssImportsTailwind(code: string): boolean;
|
|
596
609
|
/**
|
|
597
610
|
* Whether the discovered class set contains at least one real Tailwind
|
|
598
611
|
* candidate worth injecting an `@source` for — at least two characters and
|
|
@@ -929,21 +942,6 @@ declare function watchModeMangleMessage(): string;
|
|
|
929
942
|
* @returns the warning text.
|
|
930
943
|
*/
|
|
931
944
|
declare function realContentHashDisabledMessage(): string;
|
|
932
|
-
/**
|
|
933
|
-
* Computes the `@source` target path for a CSS module: the location of the
|
|
934
|
-
* generated safelist file relative to the CSS file, in posix form and always
|
|
935
|
-
* `./`- or `../`-prefixed so Tailwind treats it as a relative path.
|
|
936
|
-
*
|
|
937
|
-
* This is the real-world failure surface — a wrong relative path makes Tailwind
|
|
938
|
-
* silently scan nothing (no error, no CSS), the same symptom as a missing
|
|
939
|
-
* directive — so it is extracted and unit-tested rather than left inline.
|
|
940
|
-
*
|
|
941
|
-
* @param rootDir - project root where the safelist file is written.
|
|
942
|
-
* @param safelistFilename - the safelist file name (e.g. `csszyx-classes.html`).
|
|
943
|
-
* @param cssId - absolute path of the CSS module receiving the directive.
|
|
944
|
-
* @returns the posix relative path from the CSS file to the safelist file.
|
|
945
|
-
*/
|
|
946
|
-
declare function computeSafelistRelPath(rootDir: string, safelistFilename: string, cssId: string): string;
|
|
947
945
|
/**
|
|
948
946
|
* Whether transformed source text must be retained for global-var alias
|
|
949
947
|
* validation. Retention is only consumed when `production.mangleGlobalVars`
|
|
@@ -1044,5 +1042,5 @@ declare const rollupPlugin: (options?: PartialCsszyxConfig) => InputPluginOption
|
|
|
1044
1042
|
*/
|
|
1045
1043
|
declare const esbuildPlugin: (options?: PartialCsszyxConfig) => Plugin;
|
|
1046
1044
|
|
|
1047
|
-
export {
|
|
1045
|
+
export { lateMangleCensusMessage as $, deleteRSCModuleRecord as A, emitMissingCssFallback as B, esbuildPlugin as D, extractGlobalVarAliasesForManifest as E, fileMayContainSafelistableSz as F, findLocalImportSources as H, findRSCBoundaryViolation as I, findRSCGraphViolation as J, hasInjectableTailwindCandidate as K, hasTokens as L, hasUseClientDirective as N, hasUseServerDirective as O, isAdvisoryDiagnostic as T, isCompileSourceOptedIn as U, isHardIgnoredPath as W, isMangleableCssId as X, isMonorepoPackage as Y, isPackagesSkippedSource as Z, isRSCServerModule as _, mangleCodeClassesSync as a0, mangleEligibleClasses as a1, mangleHybridHazardMessage as a2, mergeThemes as a3, missingTailwindEntryMessage as a4, normalizeGlobalVarAliasesForCache as a5, parseThemeBlocks as a6, parseUtilityBlocks as a7, realContentHashDisabledMessage as a8, recordGlobalVarSourceFile as a9, resolveCompileSourceDirs as aa, resolveNativeCacheIdentity as ab, resolveQuietMode as ac, rollupPlugin as ad, scanCustomPropertyNames as ae, shouldEmitMissingCssFallback as af, shouldEmitWarning as ag, shouldTrackGlobalVarSources as ah, shouldWarnMissingTailwindEntry as ai, shouldWarnUnscopedMonorepo as aj, skippedSzFilesMessage as ak, suppressedAdvisoryMessage as al, unscopedMonorepoMessage as am, vitePlugin as an, watchModeMangleMessage as ao, webpackPlugin as ap, allocateMangleTokens as s, assertNoRSCBoundaryViolation as t, assertNoRSCGraphViolation as u, collectMangleHybridHazards as v, createGlobalVarMapAssetSource as w, createRSCModuleRecord as x, cssHasContentScope as y, unplugin as z };
|
|
1048
1046
|
export type { CssVarScanResult as C, GlobalVarScanCacheKeyInput as G, MangleHybridHazards as M, PlanGlobalVarAliasesInput as P, QuietMode as Q, RewriteGlobalVarCssAliasesOptions as R, ScanGlobalVarCssOptions as S, ValidateGlobalVarAliasInputsOptions as V, GlobalVarAliasPlan as a, GlobalVarCssAliasRewriteResult as b, CreateGlobalVarAliasValidationOptionsInput as c, GlobalVarAliasValidationResult as d, CssVarDefinition as e, CssVarLocation as f, CssVarReference as g, GlobalVarAliasDiagnostic as h, GlobalVarAliasDiagnosticSeverity as i, GlobalVarAliasEntry as j, GlobalVarCodeSource as k, GlobalVarCssAssetSource as l, GlobalVarCssSource as m, GlobalVarScanCacheEntry as n, ParsedTheme as o, ParsedUtilities as p, RSCBoundaryViolation as q, RSCModuleRecord as r };
|
|
@@ -421,6 +421,45 @@ declare function hasTokens(theme: ParsedTheme): boolean;
|
|
|
421
421
|
*/
|
|
422
422
|
declare function scanCustomPropertyNames(block: string): string[];
|
|
423
423
|
|
|
424
|
+
/**
|
|
425
|
+
* A per-key store whose merged view is built when read, not when written.
|
|
426
|
+
*
|
|
427
|
+
* The plugin keeps two aggregates over "what each file contributed": the CSS
|
|
428
|
+
* variable mangle map and the variable hoisting metrics. Both were rebuilt in
|
|
429
|
+
* full — a sort over every file, then a merge — on EVERY write, and a write
|
|
430
|
+
* happens once per module in the prescan and again in the transform hook. That
|
|
431
|
+
* made recording a module cost as much as every module before it: 18 000
|
|
432
|
+
* files with `mangleVars` on spent 77 s here, a 12× build-time regression that
|
|
433
|
+
* the flag's own benchmarks never showed because their fixtures emitted no
|
|
434
|
+
* variables.
|
|
435
|
+
*
|
|
436
|
+
* Readers (`buildEnd`, the virtual map module, the manifest) run after the
|
|
437
|
+
* writes, so building on read costs one merge per build instead of one per
|
|
438
|
+
* file, and a write followed by a read still sees the write.
|
|
439
|
+
*
|
|
440
|
+
* @module
|
|
441
|
+
*/
|
|
442
|
+
/** A per-key store with a lazily rebuilt merged view. */
|
|
443
|
+
interface LazyAggregate<Entry, Aggregate> {
|
|
444
|
+
/** Contributions by key, in insertion order. */
|
|
445
|
+
readonly entries: ReadonlyMap<string, Entry>;
|
|
446
|
+
/**
|
|
447
|
+
* Record one key's contribution, replacing what it held before.
|
|
448
|
+
*
|
|
449
|
+
* @param key Contribution owner (a normalized filename).
|
|
450
|
+
* @param entry What the owner contributes.
|
|
451
|
+
*/
|
|
452
|
+
set(key: string, entry: Entry): void;
|
|
453
|
+
/**
|
|
454
|
+
* Drop one key's contribution.
|
|
455
|
+
*
|
|
456
|
+
* @param key Contribution owner.
|
|
457
|
+
*/
|
|
458
|
+
delete(key: string): void;
|
|
459
|
+
/** @returns The merged view, rebuilt only if a write happened since the last read. */
|
|
460
|
+
get(): Aggregate;
|
|
461
|
+
}
|
|
462
|
+
|
|
424
463
|
/**
|
|
425
464
|
* Plugin state for mangle map management.
|
|
426
465
|
*/
|
|
@@ -454,6 +493,13 @@ interface PluginState {
|
|
|
454
493
|
* emit their CSS (no entry → the classes resolve to no styles, silently).
|
|
455
494
|
*/
|
|
456
495
|
sawTailwindEntry: boolean;
|
|
496
|
+
/**
|
|
497
|
+
* Absolute paths of every CSS file seen importing `tailwindcss`, without
|
|
498
|
+
* their query. These are the modules whose generated CSS changes when the
|
|
499
|
+
* safelist does, which is what lets a dev server hot-update instead of
|
|
500
|
+
* reloading — see the `hotUpdate` safelist branch.
|
|
501
|
+
*/
|
|
502
|
+
tailwindEntryFiles: Set<string>;
|
|
457
503
|
/**
|
|
458
504
|
* True once ANY CSS file passed through the transform hook. The missing-entry
|
|
459
505
|
* warning only fires when csszyx actually observed the CSS pipeline but found
|
|
@@ -516,10 +562,12 @@ interface PluginState {
|
|
|
516
562
|
*/
|
|
517
563
|
classesCapped: boolean;
|
|
518
564
|
mangleMap: Record<string, string>;
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
cssVarMetrics
|
|
565
|
+
/** CSS variable mangle entries per file; `varMangleMap` is merged from them on read. */
|
|
566
|
+
varMangleEntriesByFile: LazyAggregate<Array<[string, string]>, Record<string, CssVariableMangleValue>>;
|
|
567
|
+
readonly varMangleMap: Record<string, CssVariableMangleValue>;
|
|
568
|
+
/** CSS variable hoisting metrics per file; `cssVarMetrics` is totalled from them on read. */
|
|
569
|
+
cssVarMetricsByFile: LazyAggregate<CSSVariableMetrics, CSSVariableMetrics>;
|
|
570
|
+
readonly cssVarMetrics: CSSVariableMetrics;
|
|
523
571
|
checksum: string;
|
|
524
572
|
finalized: boolean;
|
|
525
573
|
rootDir: string;
|
|
@@ -558,41 +606,6 @@ interface CSSVariableMetrics {
|
|
|
558
606
|
* @returns A stable identity string, or a sentinel when unresolvable.
|
|
559
607
|
*/
|
|
560
608
|
declare function resolveNativeCacheIdentity(): string;
|
|
561
|
-
/**
|
|
562
|
-
* Appends an `@source "<relPath>";` directive to a CSS module so Tailwind v4
|
|
563
|
-
* scans the csszyx-generated safelist file.
|
|
564
|
-
*
|
|
565
|
-
* `@source` is position-independent in Tailwind v4 — it can appear anywhere in
|
|
566
|
-
* the compiled CSS — so the directive is **appended as its own statement**
|
|
567
|
-
* rather than spliced next to the `@import "tailwindcss…"` line. Matching the
|
|
568
|
-
* import syntax is the source of a real defect: the split / manual Tailwind v4
|
|
569
|
-
* setup (`@import "tailwindcss/utilities.css" layer(…)` or `… source(…)`, or an
|
|
570
|
-
* import without a trailing `;`) does not match an import-anchored regex, so the
|
|
571
|
-
* injection silently no-ops and every csszyx-only class (e.g. the static
|
|
572
|
-
* `bg-primary/50` produced by `sz={{ bg: { color, op } }}`) gets no CSS while a
|
|
573
|
-
* raw `className` still works. Appending is correct for every import form.
|
|
574
|
-
*
|
|
575
|
-
* @param code - CSS module source already known to import tailwindcss.
|
|
576
|
-
* @param relPath - safelist path relative to this CSS file (posix, `./`-prefixed).
|
|
577
|
-
* @returns the code with the directive appended, or `null` if it is already
|
|
578
|
-
* present (idempotent — re-running the transform must not stack directives).
|
|
579
|
-
*/
|
|
580
|
-
declare function appendTailwindSourceDirective(code: string, relPath: string): string | null;
|
|
581
|
-
/**
|
|
582
|
-
* Whether a CSS module actually imports the `tailwindcss` package, so the
|
|
583
|
-
* `@source` directive should be appended.
|
|
584
|
-
*
|
|
585
|
-
* Tighter than a substring check on purpose: block comments are stripped first
|
|
586
|
-
* (a commented-out `@import` must not trigger injection), and the package name
|
|
587
|
-
* must end at a quote or a `/` subpath so a different package whose name merely
|
|
588
|
-
* starts with `tailwindcss` (e.g. `tailwindcss-animate`) does not match. Import
|
|
589
|
-
* options after the closing quote (`layer(…)`, `source(…)`) are irrelevant — the
|
|
590
|
-
* match ends at the quote — so every real Tailwind v4 import form is covered.
|
|
591
|
-
*
|
|
592
|
-
* @param code - CSS module source.
|
|
593
|
-
* @returns true if the module imports tailwindcss (exact or a subpath).
|
|
594
|
-
*/
|
|
595
|
-
declare function cssImportsTailwind(code: string): boolean;
|
|
596
609
|
/**
|
|
597
610
|
* Whether the discovered class set contains at least one real Tailwind
|
|
598
611
|
* candidate worth injecting an `@source` for — at least two characters and
|
|
@@ -929,21 +942,6 @@ declare function watchModeMangleMessage(): string;
|
|
|
929
942
|
* @returns the warning text.
|
|
930
943
|
*/
|
|
931
944
|
declare function realContentHashDisabledMessage(): string;
|
|
932
|
-
/**
|
|
933
|
-
* Computes the `@source` target path for a CSS module: the location of the
|
|
934
|
-
* generated safelist file relative to the CSS file, in posix form and always
|
|
935
|
-
* `./`- or `../`-prefixed so Tailwind treats it as a relative path.
|
|
936
|
-
*
|
|
937
|
-
* This is the real-world failure surface — a wrong relative path makes Tailwind
|
|
938
|
-
* silently scan nothing (no error, no CSS), the same symptom as a missing
|
|
939
|
-
* directive — so it is extracted and unit-tested rather than left inline.
|
|
940
|
-
*
|
|
941
|
-
* @param rootDir - project root where the safelist file is written.
|
|
942
|
-
* @param safelistFilename - the safelist file name (e.g. `csszyx-classes.html`).
|
|
943
|
-
* @param cssId - absolute path of the CSS module receiving the directive.
|
|
944
|
-
* @returns the posix relative path from the CSS file to the safelist file.
|
|
945
|
-
*/
|
|
946
|
-
declare function computeSafelistRelPath(rootDir: string, safelistFilename: string, cssId: string): string;
|
|
947
945
|
/**
|
|
948
946
|
* Whether transformed source text must be retained for global-var alias
|
|
949
947
|
* validation. Retention is only consumed when `production.mangleGlobalVars`
|
|
@@ -1044,5 +1042,5 @@ declare const rollupPlugin: (options?: PartialCsszyxConfig) => InputPluginOption
|
|
|
1044
1042
|
*/
|
|
1045
1043
|
declare const esbuildPlugin: (options?: PartialCsszyxConfig) => Plugin;
|
|
1046
1044
|
|
|
1047
|
-
export {
|
|
1045
|
+
export { lateMangleCensusMessage as $, deleteRSCModuleRecord as A, emitMissingCssFallback as B, esbuildPlugin as D, extractGlobalVarAliasesForManifest as E, fileMayContainSafelistableSz as F, findLocalImportSources as H, findRSCBoundaryViolation as I, findRSCGraphViolation as J, hasInjectableTailwindCandidate as K, hasTokens as L, hasUseClientDirective as N, hasUseServerDirective as O, isAdvisoryDiagnostic as T, isCompileSourceOptedIn as U, isHardIgnoredPath as W, isMangleableCssId as X, isMonorepoPackage as Y, isPackagesSkippedSource as Z, isRSCServerModule as _, mangleCodeClassesSync as a0, mangleEligibleClasses as a1, mangleHybridHazardMessage as a2, mergeThemes as a3, missingTailwindEntryMessage as a4, normalizeGlobalVarAliasesForCache as a5, parseThemeBlocks as a6, parseUtilityBlocks as a7, realContentHashDisabledMessage as a8, recordGlobalVarSourceFile as a9, resolveCompileSourceDirs as aa, resolveNativeCacheIdentity as ab, resolveQuietMode as ac, rollupPlugin as ad, scanCustomPropertyNames as ae, shouldEmitMissingCssFallback as af, shouldEmitWarning as ag, shouldTrackGlobalVarSources as ah, shouldWarnMissingTailwindEntry as ai, shouldWarnUnscopedMonorepo as aj, skippedSzFilesMessage as ak, suppressedAdvisoryMessage as al, unscopedMonorepoMessage as am, vitePlugin as an, watchModeMangleMessage as ao, webpackPlugin as ap, allocateMangleTokens as s, assertNoRSCBoundaryViolation as t, assertNoRSCGraphViolation as u, collectMangleHybridHazards as v, createGlobalVarMapAssetSource as w, createRSCModuleRecord as x, cssHasContentScope as y, unplugin as z };
|
|
1048
1046
|
export type { CssVarScanResult as C, GlobalVarScanCacheKeyInput as G, MangleHybridHazards as M, PlanGlobalVarAliasesInput as P, QuietMode as Q, RewriteGlobalVarCssAliasesOptions as R, ScanGlobalVarCssOptions as S, ValidateGlobalVarAliasInputsOptions as V, GlobalVarAliasPlan as a, GlobalVarCssAliasRewriteResult as b, CreateGlobalVarAliasValidationOptionsInput as c, GlobalVarAliasValidationResult as d, CssVarDefinition as e, CssVarLocation as f, CssVarReference as g, GlobalVarAliasDiagnostic as h, GlobalVarAliasDiagnosticSeverity as i, GlobalVarAliasEntry as j, GlobalVarCodeSource as k, GlobalVarCssAssetSource as l, GlobalVarCssSource as m, GlobalVarScanCacheEntry as n, ParsedTheme as o, ParsedUtilities as p, RSCBoundaryViolation as q, RSCModuleRecord as r };
|