tailwindcss-patch 8.6.0 → 8.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4743 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2;// ../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_tsx@4.21.0_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js
2
+ var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
3
+ var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
4
+
5
+ // src/logger.ts
6
+ var _consola = require('consola');
7
+ var logger = _consola.createConsola.call(void 0, );
8
+ var logger_default = logger;
9
+
10
+ // src/cache/store.ts
11
+ var _process = require('process'); var _process2 = _interopRequireDefault(_process);
12
+ var _fsextra = require('fs-extra'); var _fsextra2 = _interopRequireDefault(_fsextra);
13
+
14
+ // src/cache/context.ts
15
+ var _crypto = require('crypto');
16
+
17
+
18
+ var _pathe = require('pathe'); var _pathe2 = _interopRequireDefault(_pathe);
19
+
20
+ // package.json
21
+ var package_default = {
22
+ name: "tailwindcss-patch",
23
+ version: "8.7.0",
24
+ description: "patch tailwindcss for exposing context and extract classes",
25
+ author: "ice breaker <1324318532@qq.com>",
26
+ license: "MIT",
27
+ homepage: "https://mangle.icebreaker.top/",
28
+ repository: {
29
+ type: "git",
30
+ url: "git+https://github.com/sonofmagic/tailwindcss-mangle.git",
31
+ directory: "packages/tailwindcss-patch"
32
+ },
33
+ bugs: {
34
+ url: "https://github.com/sonofmagic/tailwindcss-mangle/issues"
35
+ },
36
+ keywords: [
37
+ "tailwindcss",
38
+ "patch",
39
+ "extract",
40
+ "class"
41
+ ],
42
+ exports: {
43
+ ".": {
44
+ types: "./src/index.ts",
45
+ import: "./src/index.ts",
46
+ require: "./src/index.ts"
47
+ },
48
+ "./migration-report.schema.json": "./schema/migration-report.schema.json",
49
+ "./restore-result.schema.json": "./schema/restore-result.schema.json",
50
+ "./validate-result.schema.json": "./schema/validate-result.schema.json"
51
+ },
52
+ main: "./src/index.ts",
53
+ module: "./src/index.ts",
54
+ types: "./src/index.ts",
55
+ bin: {
56
+ "tw-patch": "dev/bin.ts",
57
+ "tailwindcss-patch": "dev/bin.ts"
58
+ },
59
+ files: [
60
+ "bin",
61
+ "dist",
62
+ "schema"
63
+ ],
64
+ scripts: {
65
+ dev: "tsup --watch --sourcemap",
66
+ build: "tsup",
67
+ test: "vitest run",
68
+ "test:dev": "vitest",
69
+ patch: "tsx dev/bin.ts install",
70
+ r0: "tsx dev/bin.ts extract",
71
+ r1: "tsx dev/bin.ts extract --css index.css"
72
+ },
73
+ publishConfig: {
74
+ access: "public",
75
+ registry: "https://registry.npmjs.org/",
76
+ bin: {
77
+ "tw-patch": "bin/tw-patch.js",
78
+ "tailwindcss-patch": "bin/tw-patch.js"
79
+ },
80
+ exports: {
81
+ ".": {
82
+ types: "./dist/index.d.ts",
83
+ import: "./dist/index.mjs",
84
+ require: "./dist/index.js"
85
+ },
86
+ "./migration-report.schema.json": "./schema/migration-report.schema.json",
87
+ "./restore-result.schema.json": "./schema/restore-result.schema.json",
88
+ "./validate-result.schema.json": "./schema/validate-result.schema.json"
89
+ },
90
+ main: "./dist/index.js",
91
+ module: "./dist/index.mjs",
92
+ types: "./dist/index.d.ts"
93
+ },
94
+ peerDependencies: {
95
+ tailwindcss: ">=2.0.0"
96
+ },
97
+ peerDependenciesMeta: {
98
+ tailwindcss: {
99
+ optional: true
100
+ }
101
+ },
102
+ dependencies: {
103
+ "@babel/generator": "^7.29.1",
104
+ "@babel/parser": "^7.29.0",
105
+ "@babel/traverse": "^7.29.0",
106
+ "@babel/types": "^7.29.0",
107
+ "@tailwindcss-mangle/config": "workspace:*",
108
+ "@tailwindcss/node": "^4.1.18",
109
+ cac: "^6.7.14",
110
+ consola: "^3.4.2",
111
+ "fs-extra": "^11.3.3",
112
+ "local-pkg": "^1.1.2",
113
+ pathe: "^2.0.3",
114
+ postcss: "^8.5.6",
115
+ semver: "^7.7.4",
116
+ "tailwindcss-config": "^1.1.4"
117
+ },
118
+ devDependencies: {
119
+ "@tailwindcss/oxide": "^4.1.18",
120
+ "@tailwindcss/postcss": "^4.1.18",
121
+ "@tailwindcss/vite": "^4.1.18",
122
+ tailwindcss: "catalog:tailwindcss4",
123
+ "tailwindcss-3": "catalog:tailwindcss3",
124
+ "tailwindcss-4": "catalog:tailwindcss4"
125
+ }
126
+ };
127
+
128
+ // src/constants.ts
129
+ var pkgName = "tailwindcss-patch";
130
+ var pkgVersion = package_default.version;
131
+
132
+ // src/cache/types.ts
133
+ var CACHE_SCHEMA_VERSION = 2;
134
+ var CACHE_FINGERPRINT_VERSION = 1;
135
+
136
+ // src/cache/context.ts
137
+ var DEFAULT_TAILWIND_CONFIG_FILES = [
138
+ "tailwind.config.js",
139
+ "tailwind.config.cjs",
140
+ "tailwind.config.mjs",
141
+ "tailwind.config.ts",
142
+ "tailwind.config.cts",
143
+ "tailwind.config.mts"
144
+ ];
145
+ function normalizePathname(value) {
146
+ return _pathe2.default.normalize(value).replaceAll("\\", "/");
147
+ }
148
+ function resolveRealpathSyncSafe(value) {
149
+ const resolved = _pathe2.default.resolve(value);
150
+ try {
151
+ return normalizePathname(_fsextra2.default.realpathSync(resolved));
152
+ } catch (e2) {
153
+ return normalizePathname(resolved);
154
+ }
155
+ }
156
+ function resolveFileMtimeMsSync(value) {
157
+ if (!value) {
158
+ return void 0;
159
+ }
160
+ try {
161
+ const stat = _fsextra2.default.statSync(value);
162
+ if (!stat.isFile()) {
163
+ return void 0;
164
+ }
165
+ return stat.mtimeMs;
166
+ } catch (e3) {
167
+ return void 0;
168
+ }
169
+ }
170
+ function resolveTailwindConfigPath(options, majorVersion) {
171
+ const tailwind = options.tailwind;
172
+ const baseDir = _nullishCoalesce(tailwind.cwd, () => ( options.projectRoot));
173
+ const configured = (() => {
174
+ if (majorVersion === 2 && _optionalChain([tailwind, 'access', _ => _.v2, 'optionalAccess', _2 => _2.config])) {
175
+ return tailwind.v2.config;
176
+ }
177
+ if (majorVersion === 3 && _optionalChain([tailwind, 'access', _3 => _3.v3, 'optionalAccess', _4 => _4.config])) {
178
+ return tailwind.v3.config;
179
+ }
180
+ return tailwind.config;
181
+ })();
182
+ if (configured) {
183
+ const absolute = _pathe2.default.isAbsolute(configured) ? configured : _pathe2.default.resolve(baseDir, configured);
184
+ if (_fsextra2.default.pathExistsSync(absolute)) {
185
+ return resolveRealpathSyncSafe(absolute);
186
+ }
187
+ }
188
+ for (const candidate of DEFAULT_TAILWIND_CONFIG_FILES) {
189
+ const absolute = _pathe2.default.resolve(baseDir, candidate);
190
+ if (_fsextra2.default.pathExistsSync(absolute)) {
191
+ return resolveRealpathSyncSafe(absolute);
192
+ }
193
+ }
194
+ return void 0;
195
+ }
196
+ function stableSerialize(input) {
197
+ if (input === null) {
198
+ return "null";
199
+ }
200
+ if (typeof input === "string") {
201
+ return JSON.stringify(input);
202
+ }
203
+ if (typeof input === "number" || typeof input === "boolean") {
204
+ return JSON.stringify(input);
205
+ }
206
+ if (Array.isArray(input)) {
207
+ return `[${input.map((item) => stableSerialize(item)).join(",")}]`;
208
+ }
209
+ if (typeof input === "object") {
210
+ const entries = Object.entries(input).filter(([, value]) => value !== void 0).sort(([a], [b]) => a.localeCompare(b)).map(([key, value]) => `${JSON.stringify(key)}:${stableSerialize(value)}`);
211
+ return `{${entries.join(",")}}`;
212
+ }
213
+ return JSON.stringify(String(input));
214
+ }
215
+ function hash(input) {
216
+ return _crypto.createHash.call(void 0, "sha256").update(input).digest("hex");
217
+ }
218
+ function toFingerprintOptions(normalized) {
219
+ return {
220
+ overwrite: normalized.overwrite,
221
+ output: {
222
+ removeUniversalSelector: normalized.output.removeUniversalSelector,
223
+ format: normalized.output.format
224
+ },
225
+ features: normalized.features,
226
+ tailwind: {
227
+ packageName: normalized.tailwind.packageName,
228
+ cwd: normalized.tailwind.cwd,
229
+ config: normalized.tailwind.config,
230
+ postcssPlugin: normalized.tailwind.postcssPlugin,
231
+ versionHint: normalized.tailwind.versionHint,
232
+ v2: normalized.tailwind.v2,
233
+ v3: normalized.tailwind.v3,
234
+ v4: normalized.tailwind.v4
235
+ }
236
+ };
237
+ }
238
+ function createCacheContextDescriptor(options, packageInfo, majorVersion) {
239
+ const projectRootRealpath = resolveRealpathSyncSafe(options.projectRoot);
240
+ const processCwdRealpath = resolveRealpathSyncSafe(_process2.default.cwd());
241
+ const cacheCwdRealpath = resolveRealpathSyncSafe(options.cache.cwd);
242
+ const tailwindPackageRootRealpath = resolveRealpathSyncSafe(packageInfo.rootPath);
243
+ const tailwindConfigPath = resolveTailwindConfigPath(options, majorVersion);
244
+ const tailwindConfigMtimeMs = resolveFileMtimeMsSync(tailwindConfigPath);
245
+ const optionsHash = hash(stableSerialize(toFingerprintOptions(options)));
246
+ const metadata = {
247
+ fingerprintVersion: CACHE_FINGERPRINT_VERSION,
248
+ projectRootRealpath,
249
+ processCwdRealpath,
250
+ cacheCwdRealpath,
251
+ ...tailwindConfigPath === void 0 ? {} : { tailwindConfigPath },
252
+ ...tailwindConfigMtimeMs === void 0 ? {} : { tailwindConfigMtimeMs },
253
+ tailwindPackageRootRealpath,
254
+ tailwindPackageVersion: _nullishCoalesce(packageInfo.version, () => ( "unknown")),
255
+ patcherVersion: pkgVersion,
256
+ majorVersion,
257
+ optionsHash
258
+ };
259
+ const fingerprint = hash(stableSerialize(metadata));
260
+ return {
261
+ fingerprint,
262
+ metadata
263
+ };
264
+ }
265
+ function explainContextMismatch(current, cached) {
266
+ const reasons = [];
267
+ if (current.projectRootRealpath !== cached.projectRootRealpath) {
268
+ reasons.push(`project-root changed: ${cached.projectRootRealpath} -> ${current.projectRootRealpath}`);
269
+ }
270
+ if (current.processCwdRealpath !== cached.processCwdRealpath) {
271
+ reasons.push(`process-cwd changed: ${cached.processCwdRealpath} -> ${current.processCwdRealpath}`);
272
+ }
273
+ if (current.cacheCwdRealpath !== cached.cacheCwdRealpath) {
274
+ reasons.push(`cache-cwd changed: ${cached.cacheCwdRealpath} -> ${current.cacheCwdRealpath}`);
275
+ }
276
+ if ((_nullishCoalesce(current.tailwindConfigPath, () => ( ""))) !== (_nullishCoalesce(cached.tailwindConfigPath, () => ( "")))) {
277
+ reasons.push(`tailwind-config path changed: ${_nullishCoalesce(cached.tailwindConfigPath, () => ( "<none>"))} -> ${_nullishCoalesce(current.tailwindConfigPath, () => ( "<none>"))}`);
278
+ }
279
+ if ((_nullishCoalesce(current.tailwindConfigMtimeMs, () => ( -1))) !== (_nullishCoalesce(cached.tailwindConfigMtimeMs, () => ( -1)))) {
280
+ reasons.push("tailwind-config mtime changed");
281
+ }
282
+ if (current.tailwindPackageRootRealpath !== cached.tailwindPackageRootRealpath) {
283
+ reasons.push(`tailwind-package root changed: ${cached.tailwindPackageRootRealpath} -> ${current.tailwindPackageRootRealpath}`);
284
+ }
285
+ if (current.tailwindPackageVersion !== cached.tailwindPackageVersion) {
286
+ reasons.push(`tailwind-package version changed: ${cached.tailwindPackageVersion} -> ${current.tailwindPackageVersion}`);
287
+ }
288
+ if (current.patcherVersion !== cached.patcherVersion) {
289
+ reasons.push(`patcher version changed: ${cached.patcherVersion} -> ${current.patcherVersion}`);
290
+ }
291
+ if (current.majorVersion !== cached.majorVersion) {
292
+ reasons.push(`major version changed: ${cached.majorVersion} -> ${current.majorVersion}`);
293
+ }
294
+ if (current.optionsHash !== cached.optionsHash) {
295
+ reasons.push(`patch options hash changed: ${cached.optionsHash.slice(0, 12)} -> ${current.optionsHash.slice(0, 12)}`);
296
+ }
297
+ return reasons;
298
+ }
299
+
300
+ // src/cache/store.ts
301
+ function isErrnoException(error) {
302
+ return error instanceof Error && typeof error.code === "string";
303
+ }
304
+ function isAccessDenied(error) {
305
+ return isErrnoException(error) && Boolean(error.code && ["EPERM", "EBUSY", "EACCES"].includes(error.code));
306
+ }
307
+ function toStringArray(value) {
308
+ if (!Array.isArray(value)) {
309
+ return [];
310
+ }
311
+ return value.filter((item) => typeof item === "string");
312
+ }
313
+ function asObject(value) {
314
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
315
+ return void 0;
316
+ }
317
+ return value;
318
+ }
319
+ function toReadMeta(meta) {
320
+ return {
321
+ ...meta,
322
+ details: [...meta.details]
323
+ };
324
+ }
325
+ function cloneEntry(entry) {
326
+ return {
327
+ context: {
328
+ ...entry.context
329
+ },
330
+ values: [...entry.values],
331
+ updatedAt: entry.updatedAt
332
+ };
333
+ }
334
+ var CacheStore = (_class = class {
335
+ constructor(options, context) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);
336
+ this.options = options;
337
+ this.context = context;
338
+ this.driver = _nullishCoalesce(options.driver, () => ( "file"));
339
+ this.lockPath = `${this.options.path}.lock`;
340
+ }
341
+
342
+
343
+ __init() {this.memoryCache = null}
344
+ __init2() {this.memoryIndex = null}
345
+ __init3() {this.lastReadMeta = {
346
+ hit: false,
347
+ reason: "context-not-found",
348
+ details: []
349
+ }}
350
+ isContextAware() {
351
+ return this.context !== void 0;
352
+ }
353
+ createEmptyIndex() {
354
+ return {
355
+ schemaVersion: CACHE_SCHEMA_VERSION,
356
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
357
+ contexts: {}
358
+ };
359
+ }
360
+ async ensureDir() {
361
+ await _fsextra2.default.ensureDir(this.options.dir);
362
+ }
363
+ ensureDirSync() {
364
+ _fsextra2.default.ensureDirSync(this.options.dir);
365
+ }
366
+ createTempPath() {
367
+ const uniqueSuffix = `${_process2.default.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`;
368
+ return `${this.options.path}.${uniqueSuffix}.tmp`;
369
+ }
370
+ async replaceCacheFile(tempPath) {
371
+ try {
372
+ await _fsextra2.default.rename(tempPath, this.options.path);
373
+ return true;
374
+ } catch (error) {
375
+ if (isErrnoException(error) && (error.code === "EEXIST" || error.code === "EPERM")) {
376
+ try {
377
+ await _fsextra2.default.remove(this.options.path);
378
+ } catch (removeError) {
379
+ if (isAccessDenied(removeError)) {
380
+ logger_default.debug("Tailwind class cache locked or read-only, skipping update.", removeError);
381
+ return false;
382
+ }
383
+ if (!isErrnoException(removeError) || removeError.code !== "ENOENT") {
384
+ throw removeError;
385
+ }
386
+ }
387
+ await _fsextra2.default.rename(tempPath, this.options.path);
388
+ return true;
389
+ }
390
+ throw error;
391
+ }
392
+ }
393
+ replaceCacheFileSync(tempPath) {
394
+ try {
395
+ _fsextra2.default.renameSync(tempPath, this.options.path);
396
+ return true;
397
+ } catch (error) {
398
+ if (isErrnoException(error) && (error.code === "EEXIST" || error.code === "EPERM")) {
399
+ try {
400
+ _fsextra2.default.removeSync(this.options.path);
401
+ } catch (removeError) {
402
+ if (isAccessDenied(removeError)) {
403
+ logger_default.debug("Tailwind class cache locked or read-only, skipping update.", removeError);
404
+ return false;
405
+ }
406
+ if (!isErrnoException(removeError) || removeError.code !== "ENOENT") {
407
+ throw removeError;
408
+ }
409
+ }
410
+ _fsextra2.default.renameSync(tempPath, this.options.path);
411
+ return true;
412
+ }
413
+ throw error;
414
+ }
415
+ }
416
+ async cleanupTempFile(tempPath) {
417
+ try {
418
+ await _fsextra2.default.remove(tempPath);
419
+ } catch (e4) {
420
+ }
421
+ }
422
+ cleanupTempFileSync(tempPath) {
423
+ try {
424
+ _fsextra2.default.removeSync(tempPath);
425
+ } catch (e5) {
426
+ }
427
+ }
428
+ async delay(ms) {
429
+ await new Promise((resolve) => setTimeout(resolve, ms));
430
+ }
431
+ async acquireLock() {
432
+ await _fsextra2.default.ensureDir(this.options.dir);
433
+ const maxAttempts = 40;
434
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
435
+ try {
436
+ await _fsextra2.default.writeFile(this.lockPath, `${_process2.default.pid}
437
+ ${Date.now()}`, { flag: "wx" });
438
+ return true;
439
+ } catch (error) {
440
+ if (!isErrnoException(error) || error.code !== "EEXIST") {
441
+ logger_default.debug("Unable to acquire cache lock.", error);
442
+ return false;
443
+ }
444
+ try {
445
+ const stat = await _fsextra2.default.stat(this.lockPath);
446
+ if (Date.now() - stat.mtimeMs > 3e4) {
447
+ await _fsextra2.default.remove(this.lockPath);
448
+ continue;
449
+ }
450
+ } catch (e6) {
451
+ }
452
+ await this.delay(25);
453
+ }
454
+ }
455
+ logger_default.debug("Timed out while waiting for cache lock; skipping cache mutation.");
456
+ return false;
457
+ }
458
+ releaseLockSyncOrAsync(sync) {
459
+ if (sync) {
460
+ try {
461
+ _fsextra2.default.removeSync(this.lockPath);
462
+ } catch (e7) {
463
+ }
464
+ return;
465
+ }
466
+ return _fsextra2.default.remove(this.lockPath).catch(() => void 0);
467
+ }
468
+ acquireLockSync() {
469
+ _fsextra2.default.ensureDirSync(this.options.dir);
470
+ const maxAttempts = 40;
471
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
472
+ try {
473
+ _fsextra2.default.writeFileSync(this.lockPath, `${_process2.default.pid}
474
+ ${Date.now()}`, { flag: "wx" });
475
+ return true;
476
+ } catch (error) {
477
+ if (!isErrnoException(error) || error.code !== "EEXIST") {
478
+ logger_default.debug("Unable to acquire cache lock.", error);
479
+ return false;
480
+ }
481
+ try {
482
+ const stat = _fsextra2.default.statSync(this.lockPath);
483
+ if (Date.now() - stat.mtimeMs > 3e4) {
484
+ _fsextra2.default.removeSync(this.lockPath);
485
+ continue;
486
+ }
487
+ } catch (e8) {
488
+ }
489
+ const start = Date.now();
490
+ while (Date.now() - start < 25) {
491
+ }
492
+ }
493
+ }
494
+ logger_default.debug("Timed out while waiting for cache lock; skipping cache mutation.");
495
+ return false;
496
+ }
497
+ async withFileLock(fn) {
498
+ const locked = await this.acquireLock();
499
+ if (!locked) {
500
+ return void 0;
501
+ }
502
+ try {
503
+ return await fn();
504
+ } finally {
505
+ await this.releaseLockSyncOrAsync(false);
506
+ }
507
+ }
508
+ withFileLockSync(fn) {
509
+ const locked = this.acquireLockSync();
510
+ if (!locked) {
511
+ return void 0;
512
+ }
513
+ try {
514
+ return fn();
515
+ } finally {
516
+ this.releaseLockSyncOrAsync(true);
517
+ }
518
+ }
519
+ normalizeContextEntry(value) {
520
+ const record = asObject(value);
521
+ if (!record) {
522
+ return void 0;
523
+ }
524
+ const values = toStringArray(record["values"]);
525
+ if (values.length === 0) {
526
+ return void 0;
527
+ }
528
+ const contextRecord = asObject(record["context"]);
529
+ if (!contextRecord) {
530
+ return void 0;
531
+ }
532
+ const {
533
+ fingerprintVersion,
534
+ projectRootRealpath,
535
+ processCwdRealpath,
536
+ cacheCwdRealpath,
537
+ tailwindConfigPath,
538
+ tailwindConfigMtimeMs,
539
+ tailwindPackageRootRealpath,
540
+ tailwindPackageVersion,
541
+ patcherVersion,
542
+ majorVersion,
543
+ optionsHash
544
+ } = contextRecord;
545
+ if (fingerprintVersion !== 1 || typeof projectRootRealpath !== "string" || typeof processCwdRealpath !== "string" || typeof cacheCwdRealpath !== "string" || typeof tailwindPackageRootRealpath !== "string" || typeof tailwindPackageVersion !== "string" || typeof patcherVersion !== "string" || majorVersion !== 2 && majorVersion !== 3 && majorVersion !== 4 || typeof optionsHash !== "string") {
546
+ return void 0;
547
+ }
548
+ const normalized = {
549
+ context: {
550
+ fingerprintVersion,
551
+ projectRootRealpath,
552
+ processCwdRealpath,
553
+ cacheCwdRealpath,
554
+ ...typeof tailwindConfigPath === "string" ? { tailwindConfigPath } : {},
555
+ ...typeof tailwindConfigMtimeMs === "number" ? { tailwindConfigMtimeMs } : {},
556
+ tailwindPackageRootRealpath,
557
+ tailwindPackageVersion,
558
+ patcherVersion,
559
+ majorVersion,
560
+ optionsHash
561
+ },
562
+ values,
563
+ updatedAt: typeof record["updatedAt"] === "string" ? record["updatedAt"] : (/* @__PURE__ */ new Date(0)).toISOString()
564
+ };
565
+ return normalized;
566
+ }
567
+ normalizeIndexFile(payload) {
568
+ if (Array.isArray(payload)) {
569
+ return {
570
+ kind: "legacy",
571
+ data: toStringArray(payload)
572
+ };
573
+ }
574
+ const record = asObject(payload);
575
+ if (!record) {
576
+ return { kind: "invalid" };
577
+ }
578
+ if (record["schemaVersion"] !== CACHE_SCHEMA_VERSION) {
579
+ return { kind: "invalid" };
580
+ }
581
+ const contextsRecord = asObject(record["contexts"]);
582
+ if (!contextsRecord) {
583
+ return { kind: "invalid" };
584
+ }
585
+ const contexts = {};
586
+ for (const [fingerprint, value] of Object.entries(contextsRecord)) {
587
+ if (typeof fingerprint !== "string" || !fingerprint) {
588
+ continue;
589
+ }
590
+ const entry = this.normalizeContextEntry(value);
591
+ if (!entry) {
592
+ continue;
593
+ }
594
+ contexts[fingerprint] = entry;
595
+ }
596
+ return {
597
+ kind: "v2",
598
+ data: {
599
+ schemaVersion: CACHE_SCHEMA_VERSION,
600
+ updatedAt: typeof record["updatedAt"] === "string" ? record["updatedAt"] : (/* @__PURE__ */ new Date(0)).toISOString(),
601
+ contexts
602
+ }
603
+ };
604
+ }
605
+ async readParsedCacheFile(cleanupInvalid) {
606
+ try {
607
+ if (!await _fsextra2.default.pathExists(this.options.path)) {
608
+ return { kind: "empty" };
609
+ }
610
+ const payload = await _fsextra2.default.readJSON(this.options.path);
611
+ const normalized = this.normalizeIndexFile(payload);
612
+ if (normalized.kind !== "invalid") {
613
+ return normalized;
614
+ }
615
+ if (cleanupInvalid) {
616
+ logger_default.warn("Unable to read Tailwind class cache index, removing invalid file.");
617
+ await _fsextra2.default.remove(this.options.path);
618
+ }
619
+ return { kind: "invalid" };
620
+ } catch (error) {
621
+ if (isErrnoException(error) && error.code === "ENOENT") {
622
+ return { kind: "empty" };
623
+ }
624
+ logger_default.warn("Unable to read Tailwind class cache index, removing invalid file.", error);
625
+ if (cleanupInvalid) {
626
+ try {
627
+ await _fsextra2.default.remove(this.options.path);
628
+ } catch (cleanupError) {
629
+ logger_default.error("Failed to clean up invalid cache file", cleanupError);
630
+ }
631
+ }
632
+ return { kind: "invalid" };
633
+ }
634
+ }
635
+ readParsedCacheFileSync(cleanupInvalid) {
636
+ try {
637
+ if (!_fsextra2.default.pathExistsSync(this.options.path)) {
638
+ return { kind: "empty" };
639
+ }
640
+ const payload = _fsextra2.default.readJSONSync(this.options.path);
641
+ const normalized = this.normalizeIndexFile(payload);
642
+ if (normalized.kind !== "invalid") {
643
+ return normalized;
644
+ }
645
+ if (cleanupInvalid) {
646
+ logger_default.warn("Unable to read Tailwind class cache index, removing invalid file.");
647
+ _fsextra2.default.removeSync(this.options.path);
648
+ }
649
+ return { kind: "invalid" };
650
+ } catch (error) {
651
+ if (isErrnoException(error) && error.code === "ENOENT") {
652
+ return { kind: "empty" };
653
+ }
654
+ logger_default.warn("Unable to read Tailwind class cache index, removing invalid file.", error);
655
+ if (cleanupInvalid) {
656
+ try {
657
+ _fsextra2.default.removeSync(this.options.path);
658
+ } catch (cleanupError) {
659
+ logger_default.error("Failed to clean up invalid cache file", cleanupError);
660
+ }
661
+ }
662
+ return { kind: "invalid" };
663
+ }
664
+ }
665
+ findProjectMatch(index) {
666
+ if (!this.context) {
667
+ return void 0;
668
+ }
669
+ const current = this.context.metadata.projectRootRealpath;
670
+ return Object.entries(index.contexts).find(([, entry]) => entry.context.projectRootRealpath === current);
671
+ }
672
+ async writeIndexFile(index) {
673
+ const tempPath = this.createTempPath();
674
+ try {
675
+ await this.ensureDir();
676
+ await _fsextra2.default.writeJSON(tempPath, index);
677
+ const replaced = await this.replaceCacheFile(tempPath);
678
+ if (replaced) {
679
+ return this.options.path;
680
+ }
681
+ await this.cleanupTempFile(tempPath);
682
+ return void 0;
683
+ } catch (error) {
684
+ await this.cleanupTempFile(tempPath);
685
+ logger_default.error("Unable to persist Tailwind class cache", error);
686
+ return void 0;
687
+ }
688
+ }
689
+ writeIndexFileSync(index) {
690
+ const tempPath = this.createTempPath();
691
+ try {
692
+ this.ensureDirSync();
693
+ _fsextra2.default.writeJSONSync(tempPath, index);
694
+ const replaced = this.replaceCacheFileSync(tempPath);
695
+ if (replaced) {
696
+ return this.options.path;
697
+ }
698
+ this.cleanupTempFileSync(tempPath);
699
+ return void 0;
700
+ } catch (error) {
701
+ this.cleanupTempFileSync(tempPath);
702
+ logger_default.error("Unable to persist Tailwind class cache", error);
703
+ return void 0;
704
+ }
705
+ }
706
+ async write(data) {
707
+ if (!this.options.enabled) {
708
+ return void 0;
709
+ }
710
+ if (this.driver === "noop") {
711
+ return void 0;
712
+ }
713
+ if (this.driver === "memory") {
714
+ if (!this.isContextAware()) {
715
+ this.memoryCache = new Set(data);
716
+ return "memory";
717
+ }
718
+ const index = _nullishCoalesce(this.memoryIndex, () => ( this.createEmptyIndex()));
719
+ if (!this.context) {
720
+ return "memory";
721
+ }
722
+ index.contexts[this.context.fingerprint] = {
723
+ context: {
724
+ ...this.context.metadata
725
+ },
726
+ values: Array.from(data),
727
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
728
+ };
729
+ index.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
730
+ this.memoryIndex = index;
731
+ return "memory";
732
+ }
733
+ if (!this.isContextAware()) {
734
+ const tempPath = this.createTempPath();
735
+ try {
736
+ await this.ensureDir();
737
+ await _fsextra2.default.writeJSON(tempPath, Array.from(data));
738
+ const replaced = await this.replaceCacheFile(tempPath);
739
+ if (replaced) {
740
+ return this.options.path;
741
+ }
742
+ await this.cleanupTempFile(tempPath);
743
+ return void 0;
744
+ } catch (error) {
745
+ await this.cleanupTempFile(tempPath);
746
+ logger_default.error("Unable to persist Tailwind class cache", error);
747
+ return void 0;
748
+ }
749
+ }
750
+ const result = await this.withFileLock(async () => {
751
+ const parsed = await this.readParsedCacheFile(false);
752
+ const index = parsed.kind === "v2" ? parsed.data : this.createEmptyIndex();
753
+ if (this.context) {
754
+ index.contexts[this.context.fingerprint] = {
755
+ context: {
756
+ ...this.context.metadata
757
+ },
758
+ values: Array.from(data),
759
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
760
+ };
761
+ }
762
+ index.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
763
+ return this.writeIndexFile(index);
764
+ });
765
+ return result;
766
+ }
767
+ writeSync(data) {
768
+ if (!this.options.enabled) {
769
+ return void 0;
770
+ }
771
+ if (this.driver === "noop") {
772
+ return void 0;
773
+ }
774
+ if (this.driver === "memory") {
775
+ if (!this.isContextAware()) {
776
+ this.memoryCache = new Set(data);
777
+ return "memory";
778
+ }
779
+ const index = _nullishCoalesce(this.memoryIndex, () => ( this.createEmptyIndex()));
780
+ if (!this.context) {
781
+ return "memory";
782
+ }
783
+ index.contexts[this.context.fingerprint] = {
784
+ context: {
785
+ ...this.context.metadata
786
+ },
787
+ values: Array.from(data),
788
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
789
+ };
790
+ index.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
791
+ this.memoryIndex = index;
792
+ return "memory";
793
+ }
794
+ if (!this.isContextAware()) {
795
+ const tempPath = this.createTempPath();
796
+ try {
797
+ this.ensureDirSync();
798
+ _fsextra2.default.writeJSONSync(tempPath, Array.from(data));
799
+ const replaced = this.replaceCacheFileSync(tempPath);
800
+ if (replaced) {
801
+ return this.options.path;
802
+ }
803
+ this.cleanupTempFileSync(tempPath);
804
+ return void 0;
805
+ } catch (error) {
806
+ this.cleanupTempFileSync(tempPath);
807
+ logger_default.error("Unable to persist Tailwind class cache", error);
808
+ return void 0;
809
+ }
810
+ }
811
+ const result = this.withFileLockSync(() => {
812
+ const parsed = this.readParsedCacheFileSync(false);
813
+ const index = parsed.kind === "v2" ? parsed.data : this.createEmptyIndex();
814
+ if (this.context) {
815
+ index.contexts[this.context.fingerprint] = {
816
+ context: {
817
+ ...this.context.metadata
818
+ },
819
+ values: Array.from(data),
820
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
821
+ };
822
+ }
823
+ index.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
824
+ return this.writeIndexFileSync(index);
825
+ });
826
+ return result;
827
+ }
828
+ async readWithMeta() {
829
+ if (!this.options.enabled) {
830
+ return {
831
+ data: /* @__PURE__ */ new Set(),
832
+ meta: {
833
+ hit: false,
834
+ reason: "cache-disabled",
835
+ details: ["cache disabled"]
836
+ }
837
+ };
838
+ }
839
+ if (this.driver === "noop") {
840
+ return {
841
+ data: /* @__PURE__ */ new Set(),
842
+ meta: {
843
+ hit: false,
844
+ reason: "noop-driver",
845
+ details: ["cache driver is noop"]
846
+ }
847
+ };
848
+ }
849
+ if (this.driver === "memory") {
850
+ if (!this.isContextAware()) {
851
+ const cache = new Set(_nullishCoalesce(this.memoryCache, () => ( [])));
852
+ return {
853
+ data: cache,
854
+ meta: {
855
+ hit: cache.size > 0,
856
+ reason: cache.size > 0 ? "hit" : "context-not-found",
857
+ details: cache.size > 0 ? ["memory cache hit"] : ["memory cache miss"]
858
+ }
859
+ };
860
+ }
861
+ const index = this.memoryIndex;
862
+ if (!index || !this.context) {
863
+ return {
864
+ data: /* @__PURE__ */ new Set(),
865
+ meta: {
866
+ hit: false,
867
+ reason: "context-not-found",
868
+ ..._optionalChain([this, 'access', _5 => _5.context, 'optionalAccess', _6 => _6.fingerprint]) === void 0 ? {} : { fingerprint: this.context.fingerprint },
869
+ schemaVersion: CACHE_SCHEMA_VERSION,
870
+ details: ["no in-memory cache index for current context"]
871
+ }
872
+ };
873
+ }
874
+ const entry2 = index.contexts[this.context.fingerprint];
875
+ if (entry2) {
876
+ return {
877
+ data: new Set(entry2.values),
878
+ meta: {
879
+ hit: true,
880
+ reason: "hit",
881
+ fingerprint: this.context.fingerprint,
882
+ schemaVersion: CACHE_SCHEMA_VERSION,
883
+ details: ["memory cache hit"]
884
+ }
885
+ };
886
+ }
887
+ const projectMatch2 = this.findProjectMatch(index);
888
+ if (projectMatch2 && this.context) {
889
+ const [, matchedEntry] = projectMatch2;
890
+ return {
891
+ data: /* @__PURE__ */ new Set(),
892
+ meta: {
893
+ hit: false,
894
+ reason: "context-mismatch",
895
+ fingerprint: this.context.fingerprint,
896
+ schemaVersion: CACHE_SCHEMA_VERSION,
897
+ details: explainContextMismatch(this.context.metadata, matchedEntry.context)
898
+ }
899
+ };
900
+ }
901
+ return {
902
+ data: /* @__PURE__ */ new Set(),
903
+ meta: {
904
+ hit: false,
905
+ reason: "context-not-found",
906
+ fingerprint: this.context.fingerprint,
907
+ schemaVersion: CACHE_SCHEMA_VERSION,
908
+ details: ["context fingerprint not found in memory cache index"]
909
+ }
910
+ };
911
+ }
912
+ const parsed = await this.readParsedCacheFile(true);
913
+ if (parsed.kind === "empty") {
914
+ return {
915
+ data: /* @__PURE__ */ new Set(),
916
+ meta: {
917
+ hit: false,
918
+ reason: "file-missing",
919
+ details: ["cache file not found"]
920
+ }
921
+ };
922
+ }
923
+ if (parsed.kind === "invalid") {
924
+ return {
925
+ data: /* @__PURE__ */ new Set(),
926
+ meta: {
927
+ hit: false,
928
+ reason: "invalid-schema",
929
+ details: ["cache schema invalid and has been reset"]
930
+ }
931
+ };
932
+ }
933
+ if (!this.isContextAware()) {
934
+ if (parsed.kind === "legacy") {
935
+ return {
936
+ data: new Set(parsed.data),
937
+ meta: {
938
+ hit: parsed.data.length > 0,
939
+ reason: parsed.data.length > 0 ? "hit" : "context-not-found",
940
+ details: ["legacy cache format"]
941
+ }
942
+ };
943
+ }
944
+ const union = Object.values(parsed.data.contexts).flatMap((entry2) => entry2.values);
945
+ return {
946
+ data: new Set(union),
947
+ meta: {
948
+ hit: union.length > 0,
949
+ reason: union.length > 0 ? "hit" : "context-not-found",
950
+ schemaVersion: parsed.data.schemaVersion,
951
+ details: ["context-less read merged all cache entries"]
952
+ }
953
+ };
954
+ }
955
+ if (parsed.kind === "legacy") {
956
+ return {
957
+ data: /* @__PURE__ */ new Set(),
958
+ meta: {
959
+ hit: false,
960
+ reason: "legacy-schema",
961
+ ..._optionalChain([this, 'access', _7 => _7.context, 'optionalAccess', _8 => _8.fingerprint]) === void 0 ? {} : { fingerprint: this.context.fingerprint },
962
+ details: ["legacy cache schema detected; rebuilding cache with context fingerprint"]
963
+ }
964
+ };
965
+ }
966
+ if (!this.context) {
967
+ return {
968
+ data: /* @__PURE__ */ new Set(),
969
+ meta: {
970
+ hit: false,
971
+ reason: "context-not-found",
972
+ details: ["cache context missing"]
973
+ }
974
+ };
975
+ }
976
+ const entry = parsed.data.contexts[this.context.fingerprint];
977
+ if (entry) {
978
+ const mismatchReasons = explainContextMismatch(this.context.metadata, entry.context);
979
+ if (mismatchReasons.length === 0) {
980
+ return {
981
+ data: new Set(entry.values),
982
+ meta: {
983
+ hit: true,
984
+ reason: "hit",
985
+ fingerprint: this.context.fingerprint,
986
+ schemaVersion: parsed.data.schemaVersion,
987
+ details: [`context fingerprint ${this.context.fingerprint.slice(0, 12)} matched`]
988
+ }
989
+ };
990
+ }
991
+ return {
992
+ data: /* @__PURE__ */ new Set(),
993
+ meta: {
994
+ hit: false,
995
+ reason: "context-mismatch",
996
+ fingerprint: this.context.fingerprint,
997
+ schemaVersion: parsed.data.schemaVersion,
998
+ details: mismatchReasons
999
+ }
1000
+ };
1001
+ }
1002
+ const projectMatch = this.findProjectMatch(parsed.data);
1003
+ if (projectMatch) {
1004
+ const [matchedFingerprint, matchedEntry] = projectMatch;
1005
+ return {
1006
+ data: /* @__PURE__ */ new Set(),
1007
+ meta: {
1008
+ hit: false,
1009
+ reason: "context-mismatch",
1010
+ fingerprint: this.context.fingerprint,
1011
+ schemaVersion: parsed.data.schemaVersion,
1012
+ details: [
1013
+ `nearest context fingerprint: ${matchedFingerprint.slice(0, 12)}`,
1014
+ ...explainContextMismatch(this.context.metadata, matchedEntry.context)
1015
+ ]
1016
+ }
1017
+ };
1018
+ }
1019
+ return {
1020
+ data: /* @__PURE__ */ new Set(),
1021
+ meta: {
1022
+ hit: false,
1023
+ reason: "context-not-found",
1024
+ fingerprint: this.context.fingerprint,
1025
+ schemaVersion: parsed.data.schemaVersion,
1026
+ details: ["context fingerprint not found in cache index"]
1027
+ }
1028
+ };
1029
+ }
1030
+ readWithMetaSync() {
1031
+ if (!this.options.enabled) {
1032
+ return {
1033
+ data: /* @__PURE__ */ new Set(),
1034
+ meta: {
1035
+ hit: false,
1036
+ reason: "cache-disabled",
1037
+ details: ["cache disabled"]
1038
+ }
1039
+ };
1040
+ }
1041
+ if (this.driver === "noop") {
1042
+ return {
1043
+ data: /* @__PURE__ */ new Set(),
1044
+ meta: {
1045
+ hit: false,
1046
+ reason: "noop-driver",
1047
+ details: ["cache driver is noop"]
1048
+ }
1049
+ };
1050
+ }
1051
+ if (this.driver === "memory") {
1052
+ if (!this.isContextAware()) {
1053
+ const cache = new Set(_nullishCoalesce(this.memoryCache, () => ( [])));
1054
+ return {
1055
+ data: cache,
1056
+ meta: {
1057
+ hit: cache.size > 0,
1058
+ reason: cache.size > 0 ? "hit" : "context-not-found",
1059
+ details: cache.size > 0 ? ["memory cache hit"] : ["memory cache miss"]
1060
+ }
1061
+ };
1062
+ }
1063
+ const index = this.memoryIndex;
1064
+ if (!index || !this.context) {
1065
+ return {
1066
+ data: /* @__PURE__ */ new Set(),
1067
+ meta: {
1068
+ hit: false,
1069
+ reason: "context-not-found",
1070
+ ..._optionalChain([this, 'access', _9 => _9.context, 'optionalAccess', _10 => _10.fingerprint]) === void 0 ? {} : { fingerprint: this.context.fingerprint },
1071
+ schemaVersion: CACHE_SCHEMA_VERSION,
1072
+ details: ["no in-memory cache index for current context"]
1073
+ }
1074
+ };
1075
+ }
1076
+ const entry2 = index.contexts[this.context.fingerprint];
1077
+ if (entry2) {
1078
+ return {
1079
+ data: new Set(entry2.values),
1080
+ meta: {
1081
+ hit: true,
1082
+ reason: "hit",
1083
+ fingerprint: this.context.fingerprint,
1084
+ schemaVersion: CACHE_SCHEMA_VERSION,
1085
+ details: ["memory cache hit"]
1086
+ }
1087
+ };
1088
+ }
1089
+ const projectMatch2 = this.findProjectMatch(index);
1090
+ if (projectMatch2 && this.context) {
1091
+ const [, matchedEntry] = projectMatch2;
1092
+ return {
1093
+ data: /* @__PURE__ */ new Set(),
1094
+ meta: {
1095
+ hit: false,
1096
+ reason: "context-mismatch",
1097
+ fingerprint: this.context.fingerprint,
1098
+ schemaVersion: CACHE_SCHEMA_VERSION,
1099
+ details: explainContextMismatch(this.context.metadata, matchedEntry.context)
1100
+ }
1101
+ };
1102
+ }
1103
+ return {
1104
+ data: /* @__PURE__ */ new Set(),
1105
+ meta: {
1106
+ hit: false,
1107
+ reason: "context-not-found",
1108
+ fingerprint: this.context.fingerprint,
1109
+ schemaVersion: CACHE_SCHEMA_VERSION,
1110
+ details: ["context fingerprint not found in memory cache index"]
1111
+ }
1112
+ };
1113
+ }
1114
+ const parsed = this.readParsedCacheFileSync(true);
1115
+ if (parsed.kind === "empty") {
1116
+ return {
1117
+ data: /* @__PURE__ */ new Set(),
1118
+ meta: {
1119
+ hit: false,
1120
+ reason: "file-missing",
1121
+ details: ["cache file not found"]
1122
+ }
1123
+ };
1124
+ }
1125
+ if (parsed.kind === "invalid") {
1126
+ return {
1127
+ data: /* @__PURE__ */ new Set(),
1128
+ meta: {
1129
+ hit: false,
1130
+ reason: "invalid-schema",
1131
+ details: ["cache schema invalid and has been reset"]
1132
+ }
1133
+ };
1134
+ }
1135
+ if (!this.isContextAware()) {
1136
+ if (parsed.kind === "legacy") {
1137
+ return {
1138
+ data: new Set(parsed.data),
1139
+ meta: {
1140
+ hit: parsed.data.length > 0,
1141
+ reason: parsed.data.length > 0 ? "hit" : "context-not-found",
1142
+ details: ["legacy cache format"]
1143
+ }
1144
+ };
1145
+ }
1146
+ const union = Object.values(parsed.data.contexts).flatMap((entry2) => entry2.values);
1147
+ return {
1148
+ data: new Set(union),
1149
+ meta: {
1150
+ hit: union.length > 0,
1151
+ reason: union.length > 0 ? "hit" : "context-not-found",
1152
+ schemaVersion: parsed.data.schemaVersion,
1153
+ details: ["context-less read merged all cache entries"]
1154
+ }
1155
+ };
1156
+ }
1157
+ if (parsed.kind === "legacy") {
1158
+ return {
1159
+ data: /* @__PURE__ */ new Set(),
1160
+ meta: {
1161
+ hit: false,
1162
+ reason: "legacy-schema",
1163
+ ..._optionalChain([this, 'access', _11 => _11.context, 'optionalAccess', _12 => _12.fingerprint]) === void 0 ? {} : { fingerprint: this.context.fingerprint },
1164
+ details: ["legacy cache schema detected; rebuilding cache with context fingerprint"]
1165
+ }
1166
+ };
1167
+ }
1168
+ if (!this.context) {
1169
+ return {
1170
+ data: /* @__PURE__ */ new Set(),
1171
+ meta: {
1172
+ hit: false,
1173
+ reason: "context-not-found",
1174
+ details: ["cache context missing"]
1175
+ }
1176
+ };
1177
+ }
1178
+ const entry = parsed.data.contexts[this.context.fingerprint];
1179
+ if (entry) {
1180
+ const mismatchReasons = explainContextMismatch(this.context.metadata, entry.context);
1181
+ if (mismatchReasons.length === 0) {
1182
+ return {
1183
+ data: new Set(entry.values),
1184
+ meta: {
1185
+ hit: true,
1186
+ reason: "hit",
1187
+ fingerprint: this.context.fingerprint,
1188
+ schemaVersion: parsed.data.schemaVersion,
1189
+ details: [`context fingerprint ${this.context.fingerprint.slice(0, 12)} matched`]
1190
+ }
1191
+ };
1192
+ }
1193
+ return {
1194
+ data: /* @__PURE__ */ new Set(),
1195
+ meta: {
1196
+ hit: false,
1197
+ reason: "context-mismatch",
1198
+ fingerprint: this.context.fingerprint,
1199
+ schemaVersion: parsed.data.schemaVersion,
1200
+ details: mismatchReasons
1201
+ }
1202
+ };
1203
+ }
1204
+ const projectMatch = this.findProjectMatch(parsed.data);
1205
+ if (projectMatch) {
1206
+ const [matchedFingerprint, matchedEntry] = projectMatch;
1207
+ return {
1208
+ data: /* @__PURE__ */ new Set(),
1209
+ meta: {
1210
+ hit: false,
1211
+ reason: "context-mismatch",
1212
+ fingerprint: this.context.fingerprint,
1213
+ schemaVersion: parsed.data.schemaVersion,
1214
+ details: [
1215
+ `nearest context fingerprint: ${matchedFingerprint.slice(0, 12)}`,
1216
+ ...explainContextMismatch(this.context.metadata, matchedEntry.context)
1217
+ ]
1218
+ }
1219
+ };
1220
+ }
1221
+ return {
1222
+ data: /* @__PURE__ */ new Set(),
1223
+ meta: {
1224
+ hit: false,
1225
+ reason: "context-not-found",
1226
+ fingerprint: this.context.fingerprint,
1227
+ schemaVersion: parsed.data.schemaVersion,
1228
+ details: ["context fingerprint not found in cache index"]
1229
+ }
1230
+ };
1231
+ }
1232
+ async read() {
1233
+ const result = await this.readWithMeta();
1234
+ this.lastReadMeta = toReadMeta(result.meta);
1235
+ return new Set(result.data);
1236
+ }
1237
+ readSync() {
1238
+ const result = this.readWithMetaSync();
1239
+ this.lastReadMeta = toReadMeta(result.meta);
1240
+ return new Set(result.data);
1241
+ }
1242
+ getLastReadMeta() {
1243
+ return toReadMeta(this.lastReadMeta);
1244
+ }
1245
+ countEntriesFromParsed(parsed) {
1246
+ if (parsed.kind === "legacy") {
1247
+ return {
1248
+ contexts: parsed.data.length ? 1 : 0,
1249
+ entries: parsed.data.length
1250
+ };
1251
+ }
1252
+ if (parsed.kind === "v2") {
1253
+ const values = Object.values(parsed.data.contexts);
1254
+ return {
1255
+ contexts: values.length,
1256
+ entries: values.reduce((acc, item) => acc + item.values.length, 0)
1257
+ };
1258
+ }
1259
+ return {
1260
+ contexts: 0,
1261
+ entries: 0
1262
+ };
1263
+ }
1264
+ async clear(options) {
1265
+ const scope = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _13 => _13.scope]), () => ( "current"));
1266
+ if (!this.options.enabled || this.driver === "noop") {
1267
+ return {
1268
+ scope,
1269
+ filesRemoved: 0,
1270
+ entriesRemoved: 0,
1271
+ contextsRemoved: 0
1272
+ };
1273
+ }
1274
+ if (this.driver === "memory") {
1275
+ if (!this.isContextAware() || scope === "all") {
1276
+ const entriesRemoved2 = _nullishCoalesce(_optionalChain([this, 'access', _14 => _14.memoryCache, 'optionalAccess', _15 => _15.size]), () => ( (this.memoryIndex ? this.countEntriesFromParsed({ kind: "v2", data: this.memoryIndex }).entries : 0)));
1277
+ const contextsRemoved = this.memoryIndex ? Object.keys(this.memoryIndex.contexts).length : _optionalChain([this, 'access', _16 => _16.memoryCache, 'optionalAccess', _17 => _17.size]) ? 1 : 0;
1278
+ this.memoryCache = null;
1279
+ this.memoryIndex = null;
1280
+ return {
1281
+ scope,
1282
+ filesRemoved: 0,
1283
+ entriesRemoved: entriesRemoved2,
1284
+ contextsRemoved
1285
+ };
1286
+ }
1287
+ if (!this.context || !this.memoryIndex) {
1288
+ return {
1289
+ scope,
1290
+ filesRemoved: 0,
1291
+ entriesRemoved: 0,
1292
+ contextsRemoved: 0
1293
+ };
1294
+ }
1295
+ const entry = this.memoryIndex.contexts[this.context.fingerprint];
1296
+ if (!entry) {
1297
+ return {
1298
+ scope,
1299
+ filesRemoved: 0,
1300
+ entriesRemoved: 0,
1301
+ contextsRemoved: 0
1302
+ };
1303
+ }
1304
+ const entriesRemoved = entry.values.length;
1305
+ delete this.memoryIndex.contexts[this.context.fingerprint];
1306
+ return {
1307
+ scope,
1308
+ filesRemoved: 0,
1309
+ entriesRemoved,
1310
+ contextsRemoved: 1
1311
+ };
1312
+ }
1313
+ const result = await this.withFileLock(async () => {
1314
+ const parsed = await this.readParsedCacheFile(false);
1315
+ if (parsed.kind === "empty") {
1316
+ return {
1317
+ scope,
1318
+ filesRemoved: 0,
1319
+ entriesRemoved: 0,
1320
+ contextsRemoved: 0
1321
+ };
1322
+ }
1323
+ if (!this.isContextAware() || scope === "all") {
1324
+ const counts = this.countEntriesFromParsed(parsed);
1325
+ await _fsextra2.default.remove(this.options.path);
1326
+ return {
1327
+ scope,
1328
+ filesRemoved: 1,
1329
+ entriesRemoved: counts.entries,
1330
+ contextsRemoved: counts.contexts
1331
+ };
1332
+ }
1333
+ if (parsed.kind !== "v2" || !this.context) {
1334
+ const counts = this.countEntriesFromParsed(parsed);
1335
+ await _fsextra2.default.remove(this.options.path);
1336
+ return {
1337
+ scope,
1338
+ filesRemoved: 1,
1339
+ entriesRemoved: counts.entries,
1340
+ contextsRemoved: counts.contexts
1341
+ };
1342
+ }
1343
+ const entry = parsed.data.contexts[this.context.fingerprint];
1344
+ if (!entry) {
1345
+ return {
1346
+ scope,
1347
+ filesRemoved: 0,
1348
+ entriesRemoved: 0,
1349
+ contextsRemoved: 0
1350
+ };
1351
+ }
1352
+ const entriesRemoved = entry.values.length;
1353
+ delete parsed.data.contexts[this.context.fingerprint];
1354
+ const remain = Object.keys(parsed.data.contexts).length;
1355
+ if (remain === 0) {
1356
+ await _fsextra2.default.remove(this.options.path);
1357
+ return {
1358
+ scope,
1359
+ filesRemoved: 1,
1360
+ entriesRemoved,
1361
+ contextsRemoved: 1
1362
+ };
1363
+ }
1364
+ parsed.data.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1365
+ await this.writeIndexFile(parsed.data);
1366
+ return {
1367
+ scope,
1368
+ filesRemoved: 0,
1369
+ entriesRemoved,
1370
+ contextsRemoved: 1
1371
+ };
1372
+ });
1373
+ return _nullishCoalesce(result, () => ( {
1374
+ scope,
1375
+ filesRemoved: 0,
1376
+ entriesRemoved: 0,
1377
+ contextsRemoved: 0
1378
+ }));
1379
+ }
1380
+ clearSync(options) {
1381
+ const scope = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _18 => _18.scope]), () => ( "current"));
1382
+ if (!this.options.enabled || this.driver === "noop") {
1383
+ return {
1384
+ scope,
1385
+ filesRemoved: 0,
1386
+ entriesRemoved: 0,
1387
+ contextsRemoved: 0
1388
+ };
1389
+ }
1390
+ if (this.driver === "memory") {
1391
+ if (!this.isContextAware() || scope === "all") {
1392
+ const entriesRemoved2 = _nullishCoalesce(_optionalChain([this, 'access', _19 => _19.memoryCache, 'optionalAccess', _20 => _20.size]), () => ( (this.memoryIndex ? this.countEntriesFromParsed({ kind: "v2", data: this.memoryIndex }).entries : 0)));
1393
+ const contextsRemoved = this.memoryIndex ? Object.keys(this.memoryIndex.contexts).length : _optionalChain([this, 'access', _21 => _21.memoryCache, 'optionalAccess', _22 => _22.size]) ? 1 : 0;
1394
+ this.memoryCache = null;
1395
+ this.memoryIndex = null;
1396
+ return {
1397
+ scope,
1398
+ filesRemoved: 0,
1399
+ entriesRemoved: entriesRemoved2,
1400
+ contextsRemoved
1401
+ };
1402
+ }
1403
+ if (!this.context || !this.memoryIndex) {
1404
+ return {
1405
+ scope,
1406
+ filesRemoved: 0,
1407
+ entriesRemoved: 0,
1408
+ contextsRemoved: 0
1409
+ };
1410
+ }
1411
+ const entry = this.memoryIndex.contexts[this.context.fingerprint];
1412
+ if (!entry) {
1413
+ return {
1414
+ scope,
1415
+ filesRemoved: 0,
1416
+ entriesRemoved: 0,
1417
+ contextsRemoved: 0
1418
+ };
1419
+ }
1420
+ const entriesRemoved = entry.values.length;
1421
+ delete this.memoryIndex.contexts[this.context.fingerprint];
1422
+ return {
1423
+ scope,
1424
+ filesRemoved: 0,
1425
+ entriesRemoved,
1426
+ contextsRemoved: 1
1427
+ };
1428
+ }
1429
+ const result = this.withFileLockSync(() => {
1430
+ const parsed = this.readParsedCacheFileSync(false);
1431
+ if (parsed.kind === "empty") {
1432
+ return {
1433
+ scope,
1434
+ filesRemoved: 0,
1435
+ entriesRemoved: 0,
1436
+ contextsRemoved: 0
1437
+ };
1438
+ }
1439
+ if (!this.isContextAware() || scope === "all") {
1440
+ const counts = this.countEntriesFromParsed(parsed);
1441
+ _fsextra2.default.removeSync(this.options.path);
1442
+ return {
1443
+ scope,
1444
+ filesRemoved: 1,
1445
+ entriesRemoved: counts.entries,
1446
+ contextsRemoved: counts.contexts
1447
+ };
1448
+ }
1449
+ if (parsed.kind !== "v2" || !this.context) {
1450
+ const counts = this.countEntriesFromParsed(parsed);
1451
+ _fsextra2.default.removeSync(this.options.path);
1452
+ return {
1453
+ scope,
1454
+ filesRemoved: 1,
1455
+ entriesRemoved: counts.entries,
1456
+ contextsRemoved: counts.contexts
1457
+ };
1458
+ }
1459
+ const entry = parsed.data.contexts[this.context.fingerprint];
1460
+ if (!entry) {
1461
+ return {
1462
+ scope,
1463
+ filesRemoved: 0,
1464
+ entriesRemoved: 0,
1465
+ contextsRemoved: 0
1466
+ };
1467
+ }
1468
+ const entriesRemoved = entry.values.length;
1469
+ delete parsed.data.contexts[this.context.fingerprint];
1470
+ const remain = Object.keys(parsed.data.contexts).length;
1471
+ if (remain === 0) {
1472
+ _fsextra2.default.removeSync(this.options.path);
1473
+ return {
1474
+ scope,
1475
+ filesRemoved: 1,
1476
+ entriesRemoved,
1477
+ contextsRemoved: 1
1478
+ };
1479
+ }
1480
+ parsed.data.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1481
+ this.writeIndexFileSync(parsed.data);
1482
+ return {
1483
+ scope,
1484
+ filesRemoved: 0,
1485
+ entriesRemoved,
1486
+ contextsRemoved: 1
1487
+ };
1488
+ });
1489
+ return _nullishCoalesce(result, () => ( {
1490
+ scope,
1491
+ filesRemoved: 0,
1492
+ entriesRemoved: 0,
1493
+ contextsRemoved: 0
1494
+ }));
1495
+ }
1496
+ readIndexSnapshot() {
1497
+ if (this.driver === "memory") {
1498
+ return this.memoryIndex ? {
1499
+ ...this.memoryIndex,
1500
+ contexts: Object.fromEntries(Object.entries(this.memoryIndex.contexts).map(([key, value]) => [key, cloneEntry(value)]))
1501
+ } : void 0;
1502
+ }
1503
+ const parsed = this.readParsedCacheFileSync(false);
1504
+ if (parsed.kind !== "v2") {
1505
+ return void 0;
1506
+ }
1507
+ return {
1508
+ ...parsed.data,
1509
+ contexts: Object.fromEntries(Object.entries(parsed.data.contexts).map(([key, value]) => [key, cloneEntry(value)]))
1510
+ };
1511
+ }
1512
+ }, _class);
1513
+
1514
+ // src/extraction/candidate-extractor.ts
1515
+ var _fs = require('fs');
1516
+
1517
+
1518
+ async function importNode() {
1519
+ return Promise.resolve().then(() => _interopRequireWildcard(require("@tailwindcss/node")));
1520
+ }
1521
+ async function importOxide() {
1522
+ return Promise.resolve().then(() => _interopRequireWildcard(require("@tailwindcss/oxide")));
1523
+ }
1524
+ async function loadDesignSystem(css, bases) {
1525
+ const uniqueBases = Array.from(new Set(bases.filter(Boolean)));
1526
+ if (uniqueBases.length === 0) {
1527
+ throw new Error("No base directories provided for Tailwind CSS design system.");
1528
+ }
1529
+ const { __unstable__loadDesignSystem } = await importNode();
1530
+ let lastError;
1531
+ for (const base of uniqueBases) {
1532
+ try {
1533
+ return await __unstable__loadDesignSystem(css, { base });
1534
+ } catch (error) {
1535
+ lastError = error;
1536
+ }
1537
+ }
1538
+ if (lastError instanceof Error) {
1539
+ throw lastError;
1540
+ }
1541
+ throw new Error("Failed to load Tailwind CSS design system.");
1542
+ }
1543
+ async function extractRawCandidatesWithPositions(content, extension = "html") {
1544
+ const { Scanner } = await importOxide();
1545
+ const scanner = new Scanner({});
1546
+ const result = scanner.getCandidatesWithPositions({ content, extension });
1547
+ return result.map(({ candidate, position }) => ({
1548
+ rawCandidate: candidate,
1549
+ start: position,
1550
+ end: position + candidate.length
1551
+ }));
1552
+ }
1553
+ async function extractRawCandidates(sources) {
1554
+ const { Scanner } = await importOxide();
1555
+ const scanner = new Scanner(sources === void 0 ? {} : { sources });
1556
+ return scanner.scan();
1557
+ }
1558
+ async function extractValidCandidates(options) {
1559
+ const providedOptions = _nullishCoalesce(options, () => ( {}));
1560
+ const defaultCwd = _nullishCoalesce(providedOptions.cwd, () => ( _process2.default.cwd()));
1561
+ const base = _nullishCoalesce(providedOptions.base, () => ( defaultCwd));
1562
+ const baseFallbacks = _nullishCoalesce(providedOptions.baseFallbacks, () => ( []));
1563
+ const css = _nullishCoalesce(providedOptions.css, () => ( '@import "tailwindcss";'));
1564
+ const sources = (_nullishCoalesce(providedOptions.sources, () => ( [
1565
+ {
1566
+ base: defaultCwd,
1567
+ pattern: "**/*",
1568
+ negated: false
1569
+ }
1570
+ ]))).map((source) => ({
1571
+ base: _nullishCoalesce(source.base, () => ( defaultCwd)),
1572
+ pattern: source.pattern,
1573
+ negated: source.negated
1574
+ }));
1575
+ const designSystem = await loadDesignSystem(css, [base, ...baseFallbacks]);
1576
+ const candidates = await extractRawCandidates(sources);
1577
+ const parsedCandidates = candidates.filter(
1578
+ (rawCandidate) => designSystem.parseCandidate(rawCandidate).length > 0
1579
+ );
1580
+ if (parsedCandidates.length === 0) {
1581
+ return parsedCandidates;
1582
+ }
1583
+ const cssByCandidate = designSystem.candidatesToCss(parsedCandidates);
1584
+ const validCandidates = [];
1585
+ for (let index = 0; index < parsedCandidates.length; index++) {
1586
+ const candidate = parsedCandidates[index];
1587
+ if (candidate === void 0) {
1588
+ continue;
1589
+ }
1590
+ const css2 = cssByCandidate[index];
1591
+ if (typeof css2 === "string" && css2.trim().length > 0) {
1592
+ validCandidates.push(candidate);
1593
+ }
1594
+ }
1595
+ return validCandidates;
1596
+ }
1597
+ function normalizeSources(sources, cwd) {
1598
+ const baseSources = _optionalChain([sources, 'optionalAccess', _23 => _23.length]) ? sources : [
1599
+ {
1600
+ base: cwd,
1601
+ pattern: "**/*",
1602
+ negated: false
1603
+ }
1604
+ ];
1605
+ return baseSources.map((source) => ({
1606
+ base: _nullishCoalesce(source.base, () => ( cwd)),
1607
+ pattern: source.pattern,
1608
+ negated: source.negated
1609
+ }));
1610
+ }
1611
+ function buildLineOffsets(content) {
1612
+ const offsets = [0];
1613
+ for (let i = 0; i < content.length; i++) {
1614
+ if (content[i] === "\n") {
1615
+ offsets.push(i + 1);
1616
+ }
1617
+ }
1618
+ if (offsets[offsets.length - 1] !== content.length) {
1619
+ offsets.push(content.length);
1620
+ }
1621
+ return offsets;
1622
+ }
1623
+ function resolveLineMeta(content, offsets, index) {
1624
+ let low = 0;
1625
+ let high = offsets.length - 1;
1626
+ while (low <= high) {
1627
+ const mid = Math.floor((low + high) / 2);
1628
+ const start = offsets[mid];
1629
+ if (start === void 0) {
1630
+ break;
1631
+ }
1632
+ const nextStart = _nullishCoalesce(offsets[mid + 1], () => ( content.length));
1633
+ if (index < start) {
1634
+ high = mid - 1;
1635
+ continue;
1636
+ }
1637
+ if (index >= nextStart) {
1638
+ low = mid + 1;
1639
+ continue;
1640
+ }
1641
+ const line = mid + 1;
1642
+ const column = index - start + 1;
1643
+ const lineEnd = content.indexOf("\n", start);
1644
+ const lineText = content.slice(start, lineEnd === -1 ? content.length : lineEnd);
1645
+ return { line, column, lineText };
1646
+ }
1647
+ const lastStart = _nullishCoalesce(offsets[offsets.length - 2], () => ( 0));
1648
+ return {
1649
+ line: offsets.length - 1,
1650
+ column: index - lastStart + 1,
1651
+ lineText: content.slice(lastStart)
1652
+ };
1653
+ }
1654
+ function toExtension(filename) {
1655
+ const ext = _pathe2.default.extname(filename).replace(/^\./, "");
1656
+ return ext || "txt";
1657
+ }
1658
+ function toRelativeFile(cwd, filename) {
1659
+ const relative = _pathe2.default.relative(cwd, filename);
1660
+ return relative === "" ? _pathe2.default.basename(filename) : relative;
1661
+ }
1662
+ async function extractProjectCandidatesWithPositions(options) {
1663
+ const cwd = _optionalChain([options, 'optionalAccess', _24 => _24.cwd]) ? _pathe2.default.resolve(options.cwd) : _process2.default.cwd();
1664
+ const normalizedSources = normalizeSources(_optionalChain([options, 'optionalAccess', _25 => _25.sources]), cwd);
1665
+ const { Scanner } = await importOxide();
1666
+ const scanner = new Scanner({
1667
+ sources: normalizedSources
1668
+ });
1669
+ const files = _nullishCoalesce(scanner.files, () => ( []));
1670
+ const entries = [];
1671
+ const skipped = [];
1672
+ for (const file of files) {
1673
+ let content;
1674
+ try {
1675
+ content = await _fs.promises.readFile(file, "utf8");
1676
+ } catch (error) {
1677
+ skipped.push({
1678
+ file,
1679
+ reason: error instanceof Error ? error.message : "Unknown error"
1680
+ });
1681
+ continue;
1682
+ }
1683
+ const extension = toExtension(file);
1684
+ const matches = scanner.getCandidatesWithPositions({
1685
+ file,
1686
+ content,
1687
+ extension
1688
+ });
1689
+ if (!matches.length) {
1690
+ continue;
1691
+ }
1692
+ const offsets = buildLineOffsets(content);
1693
+ const relativeFile = toRelativeFile(cwd, file);
1694
+ for (const match of matches) {
1695
+ const info = resolveLineMeta(content, offsets, match.position);
1696
+ entries.push({
1697
+ rawCandidate: match.candidate,
1698
+ file,
1699
+ relativeFile,
1700
+ extension,
1701
+ start: match.position,
1702
+ end: match.position + match.candidate.length,
1703
+ length: match.candidate.length,
1704
+ line: info.line,
1705
+ column: info.column,
1706
+ lineText: info.lineText
1707
+ });
1708
+ }
1709
+ }
1710
+ return {
1711
+ entries,
1712
+ filesScanned: files.length,
1713
+ skippedFiles: skipped,
1714
+ sources: normalizedSources
1715
+ };
1716
+ }
1717
+ function groupTokensByFile(report, options) {
1718
+ const key = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _26 => _26.key]), () => ( "relative"));
1719
+ const stripAbsolute = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _27 => _27.stripAbsolutePaths]), () => ( key !== "absolute"));
1720
+ return report.entries.reduce((acc, entry) => {
1721
+ const bucketKey = key === "absolute" ? entry.file : entry.relativeFile;
1722
+ if (!acc[bucketKey]) {
1723
+ acc[bucketKey] = [];
1724
+ }
1725
+ const value = stripAbsolute ? {
1726
+ ...entry,
1727
+ file: entry.relativeFile
1728
+ } : entry;
1729
+ acc[bucketKey].push(value);
1730
+ return acc;
1731
+ }, {});
1732
+ }
1733
+
1734
+ // src/options/normalize.ts
1735
+
1736
+
1737
+
1738
+ var hasWarnedDeprecatedOptions = false;
1739
+ var deprecatedOptionMapping = {
1740
+ cwd: "projectRoot",
1741
+ overwrite: "apply.overwrite",
1742
+ tailwind: "tailwindcss",
1743
+ features: "apply",
1744
+ output: "extract"
1745
+ };
1746
+ function resolveRealpathSafe(value) {
1747
+ const resolved = _pathe2.default.resolve(value);
1748
+ try {
1749
+ return _pathe2.default.normalize(_fsextra2.default.realpathSync(resolved));
1750
+ } catch (e9) {
1751
+ return _pathe2.default.normalize(resolved);
1752
+ }
1753
+ }
1754
+ function toPrettyValue(value) {
1755
+ if (typeof value === "number") {
1756
+ return value > 0 ? value : false;
1757
+ }
1758
+ if (value === true) {
1759
+ return 2;
1760
+ }
1761
+ return false;
1762
+ }
1763
+ function normalizeCacheDriver(driver) {
1764
+ if (driver === "memory" || driver === "noop") {
1765
+ return driver;
1766
+ }
1767
+ return "file";
1768
+ }
1769
+ function normalizeCacheOptions(cache, projectRoot) {
1770
+ let enabled = false;
1771
+ let cwd = resolveRealpathSafe(projectRoot);
1772
+ let dir = _pathe2.default.resolve(cwd, "node_modules/.cache", pkgName);
1773
+ let file = "class-cache.json";
1774
+ let strategy = "merge";
1775
+ let driver = "file";
1776
+ if (typeof cache === "boolean") {
1777
+ enabled = cache;
1778
+ } else if (typeof cache === "object" && cache) {
1779
+ enabled = _nullishCoalesce(cache.enabled, () => ( true));
1780
+ cwd = cache.cwd ? resolveRealpathSafe(cache.cwd) : cwd;
1781
+ dir = cache.dir ? _pathe2.default.resolve(cache.dir) : _pathe2.default.resolve(cwd, "node_modules/.cache", pkgName);
1782
+ file = _nullishCoalesce(cache.file, () => ( file));
1783
+ strategy = _nullishCoalesce(cache.strategy, () => ( strategy));
1784
+ driver = normalizeCacheDriver(cache.driver);
1785
+ }
1786
+ const filename = _pathe2.default.resolve(dir, file);
1787
+ return {
1788
+ enabled,
1789
+ cwd,
1790
+ dir,
1791
+ file,
1792
+ path: filename,
1793
+ strategy,
1794
+ driver
1795
+ };
1796
+ }
1797
+ function normalizeOutputOptions(output) {
1798
+ const enabled = _nullishCoalesce(_optionalChain([output, 'optionalAccess', _28 => _28.write]), () => ( true));
1799
+ const file = _nullishCoalesce(_optionalChain([output, 'optionalAccess', _29 => _29.file]), () => ( ".tw-patch/tw-class-list.json"));
1800
+ const format = _nullishCoalesce(_optionalChain([output, 'optionalAccess', _30 => _30.format]), () => ( "json"));
1801
+ const pretty = toPrettyValue(_nullishCoalesce(_optionalChain([output, 'optionalAccess', _31 => _31.pretty]), () => ( true)));
1802
+ const removeUniversalSelector = _nullishCoalesce(_optionalChain([output, 'optionalAccess', _32 => _32.removeUniversalSelector]), () => ( true));
1803
+ return {
1804
+ enabled,
1805
+ file,
1806
+ format,
1807
+ pretty,
1808
+ removeUniversalSelector
1809
+ };
1810
+ }
1811
+ function normalizeExposeContextOptions(exposeContext) {
1812
+ if (exposeContext === false) {
1813
+ return {
1814
+ enabled: false,
1815
+ refProperty: "contextRef"
1816
+ };
1817
+ }
1818
+ if (typeof exposeContext === "object" && exposeContext) {
1819
+ return {
1820
+ enabled: true,
1821
+ refProperty: _nullishCoalesce(exposeContext.refProperty, () => ( "contextRef"))
1822
+ };
1823
+ }
1824
+ return {
1825
+ enabled: true,
1826
+ refProperty: "contextRef"
1827
+ };
1828
+ }
1829
+ function normalizeExtendLengthUnitsOptions(extend) {
1830
+ if (extend === false || extend === void 0) {
1831
+ return null;
1832
+ }
1833
+ if (extend.enabled === false) {
1834
+ return null;
1835
+ }
1836
+ const base = {
1837
+ units: ["rpx"],
1838
+ overwrite: true
1839
+ };
1840
+ return {
1841
+ ...base,
1842
+ ...extend,
1843
+ enabled: _nullishCoalesce(extend.enabled, () => ( true)),
1844
+ units: _nullishCoalesce(extend.units, () => ( base.units)),
1845
+ overwrite: _nullishCoalesce(extend.overwrite, () => ( base.overwrite))
1846
+ };
1847
+ }
1848
+ function normalizeTailwindV4Options(v4, fallbackBase) {
1849
+ const configuredBase = _optionalChain([v4, 'optionalAccess', _33 => _33.base]) ? _pathe2.default.resolve(v4.base) : void 0;
1850
+ const base = _nullishCoalesce(configuredBase, () => ( fallbackBase));
1851
+ const cssEntries = Array.isArray(_optionalChain([v4, 'optionalAccess', _34 => _34.cssEntries])) ? v4.cssEntries.filter((entry) => Boolean(entry)).map((entry) => _pathe2.default.resolve(entry)) : [];
1852
+ const userSources = _optionalChain([v4, 'optionalAccess', _35 => _35.sources]);
1853
+ const hasUserDefinedSources = Boolean(_optionalChain([userSources, 'optionalAccess', _36 => _36.length]));
1854
+ const sources = hasUserDefinedSources ? userSources : [
1855
+ {
1856
+ base: fallbackBase,
1857
+ pattern: "**/*",
1858
+ negated: false
1859
+ }
1860
+ ];
1861
+ return {
1862
+ base,
1863
+ ...configuredBase === void 0 ? {} : { configuredBase },
1864
+ ..._optionalChain([v4, 'optionalAccess', _37 => _37.css]) === void 0 ? {} : { css: v4.css },
1865
+ cssEntries,
1866
+ sources,
1867
+ hasUserDefinedSources
1868
+ };
1869
+ }
1870
+ function normalizeTailwindOptions(tailwind, projectRoot) {
1871
+ const packageName = _nullishCoalesce(_optionalChain([tailwind, 'optionalAccess', _38 => _38.packageName]), () => ( "tailwindcss"));
1872
+ const versionHint = _optionalChain([tailwind, 'optionalAccess', _39 => _39.version]);
1873
+ const resolve = _optionalChain([tailwind, 'optionalAccess', _40 => _40.resolve]);
1874
+ const cwd = _nullishCoalesce(_optionalChain([tailwind, 'optionalAccess', _41 => _41.cwd]), () => ( projectRoot));
1875
+ const config = _optionalChain([tailwind, 'optionalAccess', _42 => _42.config]);
1876
+ const postcssPlugin = _optionalChain([tailwind, 'optionalAccess', _43 => _43.postcssPlugin]);
1877
+ const v4 = normalizeTailwindV4Options(_optionalChain([tailwind, 'optionalAccess', _44 => _44.v4]), cwd);
1878
+ return {
1879
+ packageName,
1880
+ cwd,
1881
+ ...versionHint === void 0 ? {} : { versionHint },
1882
+ ...resolve === void 0 ? {} : { resolve },
1883
+ ...config === void 0 ? {} : { config },
1884
+ ...postcssPlugin === void 0 ? {} : { postcssPlugin },
1885
+ ..._optionalChain([tailwind, 'optionalAccess', _45 => _45.v2]) === void 0 ? {} : { v2: tailwind.v2 },
1886
+ ..._optionalChain([tailwind, 'optionalAccess', _46 => _46.v3]) === void 0 ? {} : { v3: tailwind.v3 },
1887
+ v4
1888
+ };
1889
+ }
1890
+ function resolveOptionSlices(options) {
1891
+ const projectRoot = _nullishCoalesce(options.projectRoot, () => ( options.cwd));
1892
+ const overwrite = _nullishCoalesce(_optionalChain([options, 'access', _47 => _47.apply, 'optionalAccess', _48 => _48.overwrite]), () => ( options.overwrite));
1893
+ const tailwind = _nullishCoalesce(options.tailwindcss, () => ( options.tailwind));
1894
+ const exposeContext = _optionalChain([options, 'access', _49 => _49.apply, 'optionalAccess', _50 => _50.exposeContext]) !== void 0 ? options.apply.exposeContext : _optionalChain([options, 'access', _51 => _51.features, 'optionalAccess', _52 => _52.exposeContext]);
1895
+ const extendLengthUnits = _optionalChain([options, 'access', _53 => _53.apply, 'optionalAccess', _54 => _54.extendLengthUnits]) !== void 0 ? options.apply.extendLengthUnits : _optionalChain([options, 'access', _55 => _55.features, 'optionalAccess', _56 => _56.extendLengthUnits]);
1896
+ const write = _nullishCoalesce(_optionalChain([options, 'access', _57 => _57.extract, 'optionalAccess', _58 => _58.write]), () => ( _optionalChain([options, 'access', _59 => _59.output, 'optionalAccess', _60 => _60.enabled])));
1897
+ const file = _nullishCoalesce(_optionalChain([options, 'access', _61 => _61.extract, 'optionalAccess', _62 => _62.file]), () => ( _optionalChain([options, 'access', _63 => _63.output, 'optionalAccess', _64 => _64.file])));
1898
+ const format = _nullishCoalesce(_optionalChain([options, 'access', _65 => _65.extract, 'optionalAccess', _66 => _66.format]), () => ( _optionalChain([options, 'access', _67 => _67.output, 'optionalAccess', _68 => _68.format])));
1899
+ const pretty = _nullishCoalesce(_optionalChain([options, 'access', _69 => _69.extract, 'optionalAccess', _70 => _70.pretty]), () => ( _optionalChain([options, 'access', _71 => _71.output, 'optionalAccess', _72 => _72.pretty])));
1900
+ const removeUniversalSelector = _nullishCoalesce(_optionalChain([options, 'access', _73 => _73.extract, 'optionalAccess', _74 => _74.removeUniversalSelector]), () => ( _optionalChain([options, 'access', _75 => _75.output, 'optionalAccess', _76 => _76.removeUniversalSelector])));
1901
+ const extract = {
1902
+ ...write === void 0 ? {} : { write },
1903
+ ...file === void 0 ? {} : { file },
1904
+ ...format === void 0 ? {} : { format },
1905
+ ...pretty === void 0 ? {} : { pretty },
1906
+ ...removeUniversalSelector === void 0 ? {} : { removeUniversalSelector }
1907
+ };
1908
+ return {
1909
+ ...projectRoot === void 0 ? {} : { projectRoot },
1910
+ ...overwrite === void 0 ? {} : { overwrite },
1911
+ ...tailwind === void 0 ? {} : { tailwind },
1912
+ ...Object.keys(extract).length === 0 ? {} : { extract },
1913
+ ...exposeContext === void 0 ? {} : { exposeContext },
1914
+ ...extendLengthUnits === void 0 ? {} : { extendLengthUnits }
1915
+ };
1916
+ }
1917
+ function findUsedDeprecatedOptions(options) {
1918
+ const result = [];
1919
+ for (const key of Object.keys(deprecatedOptionMapping)) {
1920
+ if (options[key] !== void 0) {
1921
+ result.push(key);
1922
+ }
1923
+ }
1924
+ return result;
1925
+ }
1926
+ function warnDeprecatedOptionsIfNeeded(options) {
1927
+ if (hasWarnedDeprecatedOptions) {
1928
+ return;
1929
+ }
1930
+ const used = findUsedDeprecatedOptions(options);
1931
+ if (used.length === 0) {
1932
+ return;
1933
+ }
1934
+ hasWarnedDeprecatedOptions = true;
1935
+ const mapping = used.map((key) => `${key} -> ${deprecatedOptionMapping[key]}`).join(", ");
1936
+ logger_default.warn(
1937
+ `[deprecated] TailwindcssPatcher options (${used.join(", ")}) are deprecated and will be removed in the next major version. Please migrate to: ${mapping}.`
1938
+ );
1939
+ }
1940
+ function normalizeOptions(options = {}) {
1941
+ warnDeprecatedOptionsIfNeeded(options);
1942
+ const resolved = resolveOptionSlices(options);
1943
+ const projectRoot = resolveRealpathSafe(resolved.projectRoot ? _pathe2.default.resolve(resolved.projectRoot) : _process2.default.cwd());
1944
+ const overwrite = _nullishCoalesce(resolved.overwrite, () => ( true));
1945
+ const output = normalizeOutputOptions(resolved.extract);
1946
+ const cache = normalizeCacheOptions(options.cache, projectRoot);
1947
+ const tailwind = normalizeTailwindOptions(resolved.tailwind, projectRoot);
1948
+ const exposeContext = normalizeExposeContextOptions(resolved.exposeContext);
1949
+ const extendLengthUnits = normalizeExtendLengthUnitsOptions(resolved.extendLengthUnits);
1950
+ const filter = (className) => {
1951
+ if (output.removeUniversalSelector && className === "*") {
1952
+ return false;
1953
+ }
1954
+ if (typeof options.filter === "function") {
1955
+ return options.filter(className) !== false;
1956
+ }
1957
+ return true;
1958
+ };
1959
+ return {
1960
+ projectRoot,
1961
+ overwrite,
1962
+ tailwind,
1963
+ features: {
1964
+ exposeContext,
1965
+ extendLengthUnits
1966
+ },
1967
+ output,
1968
+ cache,
1969
+ filter
1970
+ };
1971
+ }
1972
+
1973
+ // src/patching/status.ts
1974
+ var _types = require('@babel/types'); var t4 = _interopRequireWildcard(_types); var t = _interopRequireWildcard(_types); var t2 = _interopRequireWildcard(_types); var t3 = _interopRequireWildcard(_types); var t5 = _interopRequireWildcard(_types);
1975
+
1976
+
1977
+
1978
+ // src/babel/index.ts
1979
+ var _generator = require('@babel/generator'); var _generator2 = _interopRequireDefault(_generator);
1980
+ var _traverse = require('@babel/traverse'); var _traverse2 = _interopRequireDefault(_traverse);
1981
+ var _parser = require('@babel/parser');
1982
+ function _interopDefaultCompat(e) {
1983
+ return e && typeof e === "object" && "default" in e ? e.default : e;
1984
+ }
1985
+ var generate = _interopDefaultCompat(_generator2.default);
1986
+ var traverse = _interopDefaultCompat(_traverse2.default);
1987
+
1988
+ // src/patching/operations/export-context/postcss-v2.ts
1989
+
1990
+ var IDENTIFIER_RE = /^[A-Z_$][\w$]*$/i;
1991
+ function toIdentifierName(property) {
1992
+ if (!property) {
1993
+ return "contextRef";
1994
+ }
1995
+ const sanitized = property.replace(/[^\w$]/gu, "_");
1996
+ if (/^\d/.test(sanitized)) {
1997
+ return `_${sanitized}`;
1998
+ }
1999
+ return sanitized || "contextRef";
2000
+ }
2001
+ function createExportsMember(property) {
2002
+ if (IDENTIFIER_RE.test(property)) {
2003
+ return t.memberExpression(t.identifier("exports"), t.identifier(property));
2004
+ }
2005
+ return t.memberExpression(t.identifier("exports"), t.stringLiteral(property), true);
2006
+ }
2007
+ function transformProcessTailwindFeaturesReturnContextV2(content) {
2008
+ const ast = _parser.parse.call(void 0, content, {
2009
+ sourceType: "unambiguous"
2010
+ });
2011
+ let hasPatched = false;
2012
+ traverse(ast, {
2013
+ FunctionDeclaration(path13) {
2014
+ const node = path13.node;
2015
+ if (_optionalChain([node, 'access', _77 => _77.id, 'optionalAccess', _78 => _78.name]) !== "processTailwindFeatures" || node.body.body.length !== 1 || !t.isReturnStatement(node.body.body[0])) {
2016
+ return;
2017
+ }
2018
+ const returnStatement3 = node.body.body[0];
2019
+ if (!t.isFunctionExpression(returnStatement3.argument)) {
2020
+ return;
2021
+ }
2022
+ const body = returnStatement3.argument.body.body;
2023
+ const lastStatement = body[body.length - 1];
2024
+ const alreadyReturnsContext = Boolean(
2025
+ t.isReturnStatement(lastStatement) && t.isIdentifier(lastStatement.argument) && lastStatement.argument.name === "context"
2026
+ );
2027
+ hasPatched = alreadyReturnsContext;
2028
+ if (!alreadyReturnsContext) {
2029
+ body.push(t.returnStatement(t.identifier("context")));
2030
+ }
2031
+ }
2032
+ });
2033
+ return {
2034
+ code: hasPatched ? content : generate(ast).code,
2035
+ hasPatched
2036
+ };
2037
+ }
2038
+ function transformPostcssPluginV2(content, options) {
2039
+ const refIdentifier = t.identifier(toIdentifierName(options.refProperty));
2040
+ const exportMember = createExportsMember(options.refProperty);
2041
+ const valueMember = t.memberExpression(refIdentifier, t.identifier("value"));
2042
+ const ast = _parser.parse.call(void 0, content);
2043
+ let hasPatched = false;
2044
+ traverse(ast, {
2045
+ Program(path13) {
2046
+ const program = path13.node;
2047
+ const index = program.body.findIndex((statement) => {
2048
+ return t.isFunctionDeclaration(statement) && _optionalChain([statement, 'access', _79 => _79.id, 'optionalAccess', _80 => _80.name]) === "_default";
2049
+ });
2050
+ if (index === -1) {
2051
+ return;
2052
+ }
2053
+ const previous = program.body[index - 1];
2054
+ const beforePrevious = program.body[index - 2];
2055
+ const alreadyHasVariable = Boolean(
2056
+ previous && t.isVariableDeclaration(previous) && previous.declarations.length === 1 && t.isIdentifier(previous.declarations[0].id) && previous.declarations[0].id.name === refIdentifier.name
2057
+ );
2058
+ const alreadyAssignsExports = Boolean(
2059
+ beforePrevious && t.isExpressionStatement(beforePrevious) && t.isAssignmentExpression(beforePrevious.expression) && t.isMemberExpression(beforePrevious.expression.left) && t.isIdentifier(beforePrevious.expression.right) && beforePrevious.expression.right.name === refIdentifier.name && generate(beforePrevious.expression.left).code === generate(exportMember).code
2060
+ );
2061
+ hasPatched = alreadyHasVariable && alreadyAssignsExports;
2062
+ if (!alreadyHasVariable) {
2063
+ program.body.splice(
2064
+ index,
2065
+ 0,
2066
+ t.variableDeclaration("var", [
2067
+ t.variableDeclarator(
2068
+ refIdentifier,
2069
+ t.objectExpression([
2070
+ t.objectProperty(t.identifier("value"), t.arrayExpression())
2071
+ ])
2072
+ )
2073
+ ]),
2074
+ t.expressionStatement(
2075
+ t.assignmentExpression("=", exportMember, refIdentifier)
2076
+ )
2077
+ );
2078
+ }
2079
+ },
2080
+ FunctionDeclaration(path13) {
2081
+ if (hasPatched) {
2082
+ return;
2083
+ }
2084
+ const fn = path13.node;
2085
+ if (_optionalChain([fn, 'access', _81 => _81.id, 'optionalAccess', _82 => _82.name]) !== "_default") {
2086
+ return;
2087
+ }
2088
+ if (fn.body.body.length !== 1 || !t.isReturnStatement(fn.body.body[0])) {
2089
+ return;
2090
+ }
2091
+ const returnStatement3 = fn.body.body[0];
2092
+ if (!t.isCallExpression(returnStatement3.argument) || !t.isMemberExpression(returnStatement3.argument.callee) || !t.isArrayExpression(returnStatement3.argument.callee.object)) {
2093
+ return;
2094
+ }
2095
+ const fnExpression = returnStatement3.argument.callee.object.elements[1];
2096
+ if (!fnExpression || !t.isFunctionExpression(fnExpression)) {
2097
+ return;
2098
+ }
2099
+ const block = fnExpression.body;
2100
+ const statements = block.body;
2101
+ if (t.isExpressionStatement(statements[0]) && t.isAssignmentExpression(statements[0].expression) && t.isNumericLiteral(statements[0].expression.right)) {
2102
+ hasPatched = true;
2103
+ return;
2104
+ }
2105
+ const lastStatement = statements[statements.length - 1];
2106
+ if (lastStatement && t.isExpressionStatement(lastStatement)) {
2107
+ statements[statements.length - 1] = t.expressionStatement(
2108
+ t.callExpression(
2109
+ t.memberExpression(valueMember, t.identifier("push")),
2110
+ [lastStatement.expression]
2111
+ )
2112
+ );
2113
+ }
2114
+ const index = statements.findIndex((statement) => t.isIfStatement(statement));
2115
+ if (index > -1) {
2116
+ const ifStatement = statements[index];
2117
+ if (t.isBlockStatement(ifStatement.consequent) && ifStatement.consequent.body[1] && t.isForOfStatement(ifStatement.consequent.body[1])) {
2118
+ const forOf = ifStatement.consequent.body[1];
2119
+ if (t.isBlockStatement(forOf.body) && forOf.body.body.length === 1) {
2120
+ const nestedIf = forOf.body.body[0];
2121
+ if (nestedIf && t.isIfStatement(nestedIf) && t.isBlockStatement(nestedIf.consequent) && nestedIf.consequent.body.length === 1 && t.isExpressionStatement(nestedIf.consequent.body[0])) {
2122
+ nestedIf.consequent.body[0] = t.expressionStatement(
2123
+ t.callExpression(
2124
+ t.memberExpression(valueMember, t.identifier("push")),
2125
+ [nestedIf.consequent.body[0].expression]
2126
+ )
2127
+ );
2128
+ }
2129
+ }
2130
+ }
2131
+ }
2132
+ statements.unshift(
2133
+ t.expressionStatement(
2134
+ t.assignmentExpression(
2135
+ "=",
2136
+ t.memberExpression(valueMember, t.identifier("length")),
2137
+ t.numericLiteral(0)
2138
+ )
2139
+ )
2140
+ );
2141
+ }
2142
+ });
2143
+ return {
2144
+ code: hasPatched ? content : generate(ast).code,
2145
+ hasPatched
2146
+ };
2147
+ }
2148
+
2149
+ // src/patching/operations/export-context/postcss-v3.ts
2150
+
2151
+ var IDENTIFIER_RE2 = /^[A-Z_$][\w$]*$/i;
2152
+ function toIdentifierName2(property) {
2153
+ if (!property) {
2154
+ return "contextRef";
2155
+ }
2156
+ const sanitized = property.replace(/[^\w$]/gu, "_");
2157
+ if (/^\d/.test(sanitized)) {
2158
+ return `_${sanitized}`;
2159
+ }
2160
+ return sanitized || "contextRef";
2161
+ }
2162
+ function createModuleExportsMember(property) {
2163
+ const object = t2.memberExpression(t2.identifier("module"), t2.identifier("exports"));
2164
+ if (IDENTIFIER_RE2.test(property)) {
2165
+ return t2.memberExpression(object, t2.identifier(property));
2166
+ }
2167
+ return t2.memberExpression(object, t2.stringLiteral(property), true);
2168
+ }
2169
+ function transformProcessTailwindFeaturesReturnContext(content) {
2170
+ const ast = _parser.parse.call(void 0, content);
2171
+ let hasPatched = false;
2172
+ traverse(ast, {
2173
+ FunctionDeclaration(path13) {
2174
+ const node = path13.node;
2175
+ if (_optionalChain([node, 'access', _83 => _83.id, 'optionalAccess', _84 => _84.name]) !== "processTailwindFeatures" || node.body.body.length !== 1) {
2176
+ return;
2177
+ }
2178
+ const [returnStatement3] = node.body.body;
2179
+ if (!t2.isReturnStatement(returnStatement3) || !t2.isFunctionExpression(returnStatement3.argument)) {
2180
+ return;
2181
+ }
2182
+ const expression = returnStatement3.argument;
2183
+ const body = expression.body.body;
2184
+ const lastStatement = body[body.length - 1];
2185
+ const alreadyReturnsContext = Boolean(
2186
+ t2.isReturnStatement(lastStatement) && t2.isIdentifier(lastStatement.argument) && lastStatement.argument.name === "context"
2187
+ );
2188
+ hasPatched = alreadyReturnsContext;
2189
+ if (!alreadyReturnsContext) {
2190
+ body.push(t2.returnStatement(t2.identifier("context")));
2191
+ }
2192
+ }
2193
+ });
2194
+ return {
2195
+ code: hasPatched ? content : generate(ast).code,
2196
+ hasPatched
2197
+ };
2198
+ }
2199
+ function transformPostcssPlugin(content, { refProperty }) {
2200
+ const ast = _parser.parse.call(void 0, content);
2201
+ const refIdentifier = t2.identifier(toIdentifierName2(refProperty));
2202
+ const moduleExportsMember = createModuleExportsMember(refProperty);
2203
+ const valueMember = t2.memberExpression(refIdentifier, t2.identifier("value"));
2204
+ let hasPatched = false;
2205
+ traverse(ast, {
2206
+ Program(path13) {
2207
+ const program = path13.node;
2208
+ const index = program.body.findIndex((statement) => {
2209
+ return t2.isExpressionStatement(statement) && t2.isAssignmentExpression(statement.expression) && t2.isMemberExpression(statement.expression.left) && t2.isFunctionExpression(statement.expression.right) && _optionalChain([statement, 'access', _85 => _85.expression, 'access', _86 => _86.right, 'access', _87 => _87.id, 'optionalAccess', _88 => _88.name]) === "tailwindcss";
2210
+ });
2211
+ if (index === -1) {
2212
+ return;
2213
+ }
2214
+ const previousStatement = program.body[index - 1];
2215
+ const lastStatement = program.body[program.body.length - 1];
2216
+ const alreadyHasVariable = Boolean(
2217
+ previousStatement && t2.isVariableDeclaration(previousStatement) && previousStatement.declarations.length === 1 && t2.isIdentifier(previousStatement.declarations[0].id) && previousStatement.declarations[0].id.name === refIdentifier.name
2218
+ );
2219
+ const alreadyAssignsModuleExports = Boolean(
2220
+ t2.isExpressionStatement(lastStatement) && t2.isAssignmentExpression(lastStatement.expression) && t2.isMemberExpression(lastStatement.expression.left) && t2.isIdentifier(lastStatement.expression.right) && lastStatement.expression.right.name === refIdentifier.name && generate(lastStatement.expression.left).code === generate(moduleExportsMember).code
2221
+ );
2222
+ hasPatched = alreadyHasVariable && alreadyAssignsModuleExports;
2223
+ if (!alreadyHasVariable) {
2224
+ program.body.splice(
2225
+ index,
2226
+ 0,
2227
+ t2.variableDeclaration("const", [
2228
+ t2.variableDeclarator(
2229
+ refIdentifier,
2230
+ t2.objectExpression([
2231
+ t2.objectProperty(t2.identifier("value"), t2.arrayExpression())
2232
+ ])
2233
+ )
2234
+ ])
2235
+ );
2236
+ }
2237
+ if (!alreadyAssignsModuleExports) {
2238
+ program.body.push(
2239
+ t2.expressionStatement(
2240
+ t2.assignmentExpression("=", moduleExportsMember, refIdentifier)
2241
+ )
2242
+ );
2243
+ }
2244
+ },
2245
+ FunctionExpression(path13) {
2246
+ if (hasPatched) {
2247
+ return;
2248
+ }
2249
+ const fn = path13.node;
2250
+ if (_optionalChain([fn, 'access', _89 => _89.id, 'optionalAccess', _90 => _90.name]) !== "tailwindcss" || fn.body.body.length !== 1) {
2251
+ return;
2252
+ }
2253
+ const [returnStatement3] = fn.body.body;
2254
+ if (!returnStatement3 || !t2.isReturnStatement(returnStatement3) || !t2.isObjectExpression(returnStatement3.argument)) {
2255
+ return;
2256
+ }
2257
+ const properties = returnStatement3.argument.properties;
2258
+ if (properties.length !== 2) {
2259
+ return;
2260
+ }
2261
+ const pluginsProperty = properties.find(
2262
+ (prop) => t2.isObjectProperty(prop) && t2.isIdentifier(prop.key) && prop.key.name === "plugins"
2263
+ );
2264
+ if (!pluginsProperty || !t2.isObjectProperty(pluginsProperty) || !t2.isCallExpression(pluginsProperty.value) || !t2.isMemberExpression(pluginsProperty.value.callee) || !t2.isArrayExpression(pluginsProperty.value.callee.object)) {
2265
+ return;
2266
+ }
2267
+ const pluginsArray = pluginsProperty.value.callee.object.elements;
2268
+ const targetPlugin = pluginsArray[1];
2269
+ if (!targetPlugin || !t2.isFunctionExpression(targetPlugin)) {
2270
+ return;
2271
+ }
2272
+ const block = targetPlugin.body;
2273
+ const statements = block.body;
2274
+ const last = statements[statements.length - 1];
2275
+ if (last && t2.isExpressionStatement(last)) {
2276
+ statements[statements.length - 1] = t2.expressionStatement(
2277
+ t2.callExpression(
2278
+ t2.memberExpression(valueMember, t2.identifier("push")),
2279
+ [last.expression]
2280
+ )
2281
+ );
2282
+ }
2283
+ const index = statements.findIndex((s) => t2.isIfStatement(s));
2284
+ if (index > -1) {
2285
+ const ifStatement = statements[index];
2286
+ if (t2.isBlockStatement(ifStatement.consequent)) {
2287
+ const [, second] = ifStatement.consequent.body;
2288
+ if (second && t2.isForOfStatement(second) && t2.isBlockStatement(second.body)) {
2289
+ const bodyStatement = second.body.body[0];
2290
+ if (bodyStatement && t2.isIfStatement(bodyStatement) && t2.isBlockStatement(bodyStatement.consequent) && bodyStatement.consequent.body.length === 1 && t2.isExpressionStatement(bodyStatement.consequent.body[0])) {
2291
+ bodyStatement.consequent.body[0] = t2.expressionStatement(
2292
+ t2.callExpression(
2293
+ t2.memberExpression(valueMember, t2.identifier("push")),
2294
+ [bodyStatement.consequent.body[0].expression]
2295
+ )
2296
+ );
2297
+ }
2298
+ }
2299
+ }
2300
+ }
2301
+ statements.unshift(
2302
+ t2.expressionStatement(
2303
+ t2.assignmentExpression(
2304
+ "=",
2305
+ t2.memberExpression(valueMember, t2.identifier("length")),
2306
+ t2.numericLiteral(0)
2307
+ )
2308
+ )
2309
+ );
2310
+ }
2311
+ });
2312
+ return {
2313
+ code: hasPatched ? content : generate(ast).code,
2314
+ hasPatched
2315
+ };
2316
+ }
2317
+
2318
+ // src/patching/operations/extend-length-units.ts
2319
+
2320
+
2321
+
2322
+
2323
+ // src/utils.ts
2324
+ function isObject(val) {
2325
+ return val !== null && typeof val === "object" && Array.isArray(val) === false;
2326
+ }
2327
+ function spliceChangesIntoString(str, changes) {
2328
+ if (!changes[0]) {
2329
+ return str;
2330
+ }
2331
+ changes.sort((a, b) => {
2332
+ return a.end - b.end || a.start - b.start;
2333
+ });
2334
+ let result = "";
2335
+ let previous = changes[0];
2336
+ result += str.slice(0, previous.start);
2337
+ result += previous.replacement;
2338
+ for (let i = 1; i < changes.length; ++i) {
2339
+ const change = changes[i];
2340
+ result += str.slice(previous.end, change.start);
2341
+ result += change.replacement;
2342
+ previous = change;
2343
+ }
2344
+ result += str.slice(previous.end);
2345
+ return result;
2346
+ }
2347
+
2348
+ // src/patching/operations/extend-length-units.ts
2349
+ function updateLengthUnitsArray(content, options) {
2350
+ const { variableName = "lengthUnits", units } = options;
2351
+ const ast = _parser.parse.call(void 0, content);
2352
+ let arrayRef;
2353
+ let changed = false;
2354
+ traverse(ast, {
2355
+ Identifier(path13) {
2356
+ if (path13.node.name === variableName && t3.isVariableDeclarator(path13.parent) && t3.isArrayExpression(path13.parent.init)) {
2357
+ arrayRef = path13.parent.init;
2358
+ const existing = new Set(
2359
+ path13.parent.init.elements.map((element) => t3.isStringLiteral(element) ? element.value : void 0).filter(Boolean)
2360
+ );
2361
+ for (const unit of units) {
2362
+ if (!existing.has(unit)) {
2363
+ path13.parent.init.elements = path13.parent.init.elements.map((element) => {
2364
+ if (t3.isStringLiteral(element)) {
2365
+ return t3.stringLiteral(element.value);
2366
+ }
2367
+ return element;
2368
+ });
2369
+ path13.parent.init.elements.push(t3.stringLiteral(unit));
2370
+ changed = true;
2371
+ }
2372
+ }
2373
+ }
2374
+ }
2375
+ });
2376
+ return {
2377
+ ...arrayRef === void 0 ? {} : { arrayRef },
2378
+ changed
2379
+ };
2380
+ }
2381
+ function applyExtendLengthUnitsPatchV3(rootDir, options) {
2382
+ if (!options.enabled) {
2383
+ return { changed: false, code: void 0 };
2384
+ }
2385
+ const opts = {
2386
+ ...options,
2387
+ lengthUnitsFilePath: _nullishCoalesce(options.lengthUnitsFilePath, () => ( "lib/util/dataTypes.js")),
2388
+ variableName: _nullishCoalesce(options.variableName, () => ( "lengthUnits"))
2389
+ };
2390
+ const dataTypesFilePath = _pathe2.default.resolve(rootDir, opts.lengthUnitsFilePath);
2391
+ const exists = _fsextra2.default.existsSync(dataTypesFilePath);
2392
+ if (!exists) {
2393
+ return { changed: false, code: void 0 };
2394
+ }
2395
+ const content = _fsextra2.default.readFileSync(dataTypesFilePath, "utf8");
2396
+ const { arrayRef, changed } = updateLengthUnitsArray(content, opts);
2397
+ if (!arrayRef || !changed) {
2398
+ return { changed: false, code: void 0 };
2399
+ }
2400
+ const { code } = generate(arrayRef, {
2401
+ jsescOption: { quotes: "single" }
2402
+ });
2403
+ if (arrayRef.start != null && arrayRef.end != null) {
2404
+ const nextCode = `${content.slice(0, arrayRef.start)}${code}${content.slice(arrayRef.end)}`;
2405
+ if (opts.overwrite) {
2406
+ const target = opts.destPath ? _pathe2.default.resolve(opts.destPath) : dataTypesFilePath;
2407
+ _fsextra2.default.writeFileSync(target, nextCode, "utf8");
2408
+ logger_default.success("Patched Tailwind CSS length unit list (v3).");
2409
+ }
2410
+ return {
2411
+ changed: true,
2412
+ code: nextCode
2413
+ };
2414
+ }
2415
+ return {
2416
+ changed: false,
2417
+ code: void 0
2418
+ };
2419
+ }
2420
+ function applyExtendLengthUnitsPatchV4(rootDir, options) {
2421
+ if (!options.enabled) {
2422
+ return { files: [], changed: false };
2423
+ }
2424
+ const opts = { ...options };
2425
+ const distDir = _pathe2.default.resolve(rootDir, "dist");
2426
+ if (!_fsextra2.default.existsSync(distDir)) {
2427
+ return { files: [], changed: false };
2428
+ }
2429
+ const entries = _fsextra2.default.readdirSync(distDir);
2430
+ const chunkNames = entries.filter((entry) => entry.endsWith(".js") || entry.endsWith(".mjs"));
2431
+ const pattern = /\[\s*["']cm["'],\s*["']mm["'],[\w,"']+\]/;
2432
+ const candidates = chunkNames.map((chunkName) => {
2433
+ const file = _pathe2.default.join(distDir, chunkName);
2434
+ const code = _fsextra2.default.readFileSync(file, "utf8");
2435
+ const match = pattern.exec(code);
2436
+ if (!match) {
2437
+ return null;
2438
+ }
2439
+ return {
2440
+ file,
2441
+ code,
2442
+ match,
2443
+ hasPatched: false
2444
+ };
2445
+ }).filter((candidate) => candidate !== null);
2446
+ for (const item of candidates) {
2447
+ const { code, file, match } = item;
2448
+ const ast = _parser.parse.call(void 0, match[0], { sourceType: "unambiguous" });
2449
+ traverse(ast, {
2450
+ ArrayExpression(path13) {
2451
+ for (const unit of opts.units) {
2452
+ if (path13.node.elements.some((element) => t3.isStringLiteral(element) && element.value === unit)) {
2453
+ item.hasPatched = true;
2454
+ return;
2455
+ }
2456
+ path13.node.elements.push(t3.stringLiteral(unit));
2457
+ }
2458
+ }
2459
+ });
2460
+ if (item.hasPatched) {
2461
+ continue;
2462
+ }
2463
+ const { code: replacement } = generate(ast, { minified: true });
2464
+ const start = _nullishCoalesce(match.index, () => ( 0));
2465
+ const end = start + match[0].length;
2466
+ item.code = spliceChangesIntoString(code, [
2467
+ {
2468
+ start,
2469
+ end,
2470
+ replacement: replacement.endsWith(";") ? replacement.slice(0, -1) : replacement
2471
+ }
2472
+ ]);
2473
+ if (opts.overwrite) {
2474
+ _fsextra2.default.writeFileSync(file, item.code, "utf8");
2475
+ }
2476
+ }
2477
+ if (candidates.some((file) => !file.hasPatched)) {
2478
+ logger_default.success("Patched Tailwind CSS length unit list (v4).");
2479
+ }
2480
+ return {
2481
+ changed: candidates.some((file) => !file.hasPatched),
2482
+ files: candidates
2483
+ };
2484
+ }
2485
+
2486
+ // src/patching/status.ts
2487
+ function inspectLengthUnitsArray(content, variableName, units) {
2488
+ const ast = _parser.parse.call(void 0, content);
2489
+ let found = false;
2490
+ let missingUnits = [];
2491
+ traverse(ast, {
2492
+ Identifier(path13) {
2493
+ if (path13.node.name === variableName && t4.isVariableDeclarator(path13.parent) && t4.isArrayExpression(path13.parent.init)) {
2494
+ found = true;
2495
+ const existing = new Set(
2496
+ path13.parent.init.elements.map((element) => t4.isStringLiteral(element) ? element.value : void 0).filter(Boolean)
2497
+ );
2498
+ missingUnits = units.filter((unit) => !existing.has(unit));
2499
+ path13.stop();
2500
+ }
2501
+ }
2502
+ });
2503
+ return {
2504
+ found,
2505
+ missingUnits
2506
+ };
2507
+ }
2508
+ function checkExposeContextPatch(context) {
2509
+ const { packageInfo, options, majorVersion } = context;
2510
+ const refProperty = options.features.exposeContext.refProperty;
2511
+ if (!options.features.exposeContext.enabled) {
2512
+ return {
2513
+ name: "exposeContext",
2514
+ status: "skipped",
2515
+ reason: "exposeContext feature disabled",
2516
+ files: []
2517
+ };
2518
+ }
2519
+ if (majorVersion === 4) {
2520
+ return {
2521
+ name: "exposeContext",
2522
+ status: "unsupported",
2523
+ reason: "Context export patch is only required for Tailwind v2/v3",
2524
+ files: []
2525
+ };
2526
+ }
2527
+ const checks = [];
2528
+ function inspectFile(relative, transform) {
2529
+ const filePath = _pathe2.default.resolve(packageInfo.rootPath, relative);
2530
+ if (!_fsextra2.default.existsSync(filePath)) {
2531
+ checks.push({ relative, exists: false, patched: false });
2532
+ return;
2533
+ }
2534
+ const content = _fsextra2.default.readFileSync(filePath, "utf8");
2535
+ const { hasPatched } = transform(content);
2536
+ checks.push({
2537
+ relative,
2538
+ exists: true,
2539
+ patched: hasPatched
2540
+ });
2541
+ }
2542
+ if (majorVersion === 3) {
2543
+ inspectFile("lib/processTailwindFeatures.js", transformProcessTailwindFeaturesReturnContext);
2544
+ const pluginCandidates = ["lib/plugin.js", "lib/index.js"];
2545
+ const pluginRelative = pluginCandidates.find((candidate) => _fsextra2.default.existsSync(_pathe2.default.resolve(packageInfo.rootPath, candidate)));
2546
+ if (pluginRelative) {
2547
+ inspectFile(pluginRelative, (content) => transformPostcssPlugin(content, { refProperty }));
2548
+ } else {
2549
+ checks.push({ relative: "lib/plugin.js", exists: false, patched: false });
2550
+ }
2551
+ } else {
2552
+ inspectFile("lib/jit/processTailwindFeatures.js", transformProcessTailwindFeaturesReturnContextV2);
2553
+ inspectFile("lib/jit/index.js", (content) => transformPostcssPluginV2(content, { refProperty }));
2554
+ }
2555
+ const files = checks.filter((check) => check.exists).map((check) => check.relative);
2556
+ const missingFiles = checks.filter((check) => !check.exists);
2557
+ const unpatchedFiles = checks.filter((check) => check.exists && !check.patched);
2558
+ const reasons = [];
2559
+ if (missingFiles.length) {
2560
+ reasons.push(`missing files: ${missingFiles.map((item) => item.relative).join(", ")}`);
2561
+ }
2562
+ if (unpatchedFiles.length) {
2563
+ reasons.push(`unpatched files: ${unpatchedFiles.map((item) => item.relative).join(", ")}`);
2564
+ }
2565
+ return {
2566
+ name: "exposeContext",
2567
+ status: reasons.length ? "not-applied" : "applied",
2568
+ ...reasons.length ? { reason: reasons.join("; ") } : {},
2569
+ files
2570
+ };
2571
+ }
2572
+ function checkExtendLengthUnitsV3(rootDir, options) {
2573
+ const lengthUnitsFilePath = _nullishCoalesce(options.lengthUnitsFilePath, () => ( "lib/util/dataTypes.js"));
2574
+ const variableName = _nullishCoalesce(options.variableName, () => ( "lengthUnits"));
2575
+ const target = _pathe2.default.resolve(rootDir, lengthUnitsFilePath);
2576
+ const files = _fsextra2.default.existsSync(target) ? [_pathe2.default.relative(rootDir, target)] : [];
2577
+ if (!_fsextra2.default.existsSync(target)) {
2578
+ return {
2579
+ name: "extendLengthUnits",
2580
+ status: "not-applied",
2581
+ reason: `missing ${lengthUnitsFilePath}`,
2582
+ files
2583
+ };
2584
+ }
2585
+ const content = _fsextra2.default.readFileSync(target, "utf8");
2586
+ const { found, missingUnits } = inspectLengthUnitsArray(content, variableName, options.units);
2587
+ if (!found) {
2588
+ return {
2589
+ name: "extendLengthUnits",
2590
+ status: "not-applied",
2591
+ reason: `could not locate ${variableName} array in ${lengthUnitsFilePath}`,
2592
+ files
2593
+ };
2594
+ }
2595
+ if (missingUnits.length) {
2596
+ return {
2597
+ name: "extendLengthUnits",
2598
+ status: "not-applied",
2599
+ reason: `missing units: ${missingUnits.join(", ")}`,
2600
+ files
2601
+ };
2602
+ }
2603
+ return {
2604
+ name: "extendLengthUnits",
2605
+ status: "applied",
2606
+ files
2607
+ };
2608
+ }
2609
+ function checkExtendLengthUnitsV4(rootDir, options) {
2610
+ const distDir = _pathe2.default.resolve(rootDir, "dist");
2611
+ if (!_fsextra2.default.existsSync(distDir)) {
2612
+ return {
2613
+ name: "extendLengthUnits",
2614
+ status: "not-applied",
2615
+ reason: "dist directory not found for Tailwind v4 package",
2616
+ files: []
2617
+ };
2618
+ }
2619
+ const result = applyExtendLengthUnitsPatchV4(rootDir, {
2620
+ ...options,
2621
+ enabled: true,
2622
+ overwrite: false
2623
+ });
2624
+ if (result.files.length === 0) {
2625
+ return {
2626
+ name: "extendLengthUnits",
2627
+ status: "not-applied",
2628
+ reason: "no bundle chunks matched the length unit pattern",
2629
+ files: []
2630
+ };
2631
+ }
2632
+ const files = result.files.map((file) => _pathe2.default.relative(rootDir, file.file));
2633
+ const pending = result.files.filter((file) => !file.hasPatched);
2634
+ if (pending.length) {
2635
+ return {
2636
+ name: "extendLengthUnits",
2637
+ status: "not-applied",
2638
+ reason: `missing units in ${pending.length} bundle${pending.length > 1 ? "s" : ""}`,
2639
+ files: pending.map((file) => _pathe2.default.relative(rootDir, file.file))
2640
+ };
2641
+ }
2642
+ return {
2643
+ name: "extendLengthUnits",
2644
+ status: "applied",
2645
+ files
2646
+ };
2647
+ }
2648
+ function checkExtendLengthUnitsPatch(context) {
2649
+ const { packageInfo, options, majorVersion } = context;
2650
+ if (!options.features.extendLengthUnits) {
2651
+ return {
2652
+ name: "extendLengthUnits",
2653
+ status: "skipped",
2654
+ reason: "extendLengthUnits feature disabled",
2655
+ files: []
2656
+ };
2657
+ }
2658
+ if (majorVersion === 2) {
2659
+ return {
2660
+ name: "extendLengthUnits",
2661
+ status: "unsupported",
2662
+ reason: "length unit extension is only applied for Tailwind v3/v4",
2663
+ files: []
2664
+ };
2665
+ }
2666
+ if (majorVersion === 3) {
2667
+ return checkExtendLengthUnitsV3(packageInfo.rootPath, options.features.extendLengthUnits);
2668
+ }
2669
+ return checkExtendLengthUnitsV4(packageInfo.rootPath, options.features.extendLengthUnits);
2670
+ }
2671
+ function getPatchStatusReport(context) {
2672
+ return {
2673
+ package: {
2674
+ name: _nullishCoalesce(context.packageInfo.name, () => ( _optionalChain([context, 'access', _91 => _91.packageInfo, 'access', _92 => _92.packageJson, 'optionalAccess', _93 => _93.name]))),
2675
+ version: context.packageInfo.version,
2676
+ root: context.packageInfo.rootPath
2677
+ },
2678
+ majorVersion: context.majorVersion,
2679
+ entries: [
2680
+ checkExposeContextPatch(context),
2681
+ checkExtendLengthUnitsPatch(context)
2682
+ ]
2683
+ };
2684
+ }
2685
+
2686
+ // src/runtime/class-collector.ts
2687
+
2688
+
2689
+
2690
+ function collectClassesFromContexts(contexts, filter) {
2691
+ const set = /* @__PURE__ */ new Set();
2692
+ for (const context of contexts) {
2693
+ if (!isObject(context) || !context.classCache) {
2694
+ continue;
2695
+ }
2696
+ for (const key of context.classCache.keys()) {
2697
+ const className = key.toString();
2698
+ if (filter(className)) {
2699
+ set.add(className);
2700
+ }
2701
+ }
2702
+ }
2703
+ return set;
2704
+ }
2705
+ async function collectClassesFromTailwindV4(options) {
2706
+ const set = /* @__PURE__ */ new Set();
2707
+ const v4Options = options.tailwind.v4;
2708
+ if (!v4Options) {
2709
+ return set;
2710
+ }
2711
+ const toAbsolute = (value) => {
2712
+ if (!value) {
2713
+ return void 0;
2714
+ }
2715
+ return _pathe2.default.isAbsolute(value) ? value : _pathe2.default.resolve(options.projectRoot, value);
2716
+ };
2717
+ const resolvedConfiguredBase = toAbsolute(v4Options.configuredBase);
2718
+ const resolvedDefaultBase = _nullishCoalesce(toAbsolute(v4Options.base), () => ( _process2.default.cwd()));
2719
+ const resolveSources = (base) => {
2720
+ if (!_optionalChain([v4Options, 'access', _94 => _94.sources, 'optionalAccess', _95 => _95.length])) {
2721
+ return void 0;
2722
+ }
2723
+ return v4Options.sources.map((source) => ({
2724
+ base: _nullishCoalesce(source.base, () => ( base)),
2725
+ pattern: source.pattern,
2726
+ negated: source.negated
2727
+ }));
2728
+ };
2729
+ if (v4Options.cssEntries.length > 0) {
2730
+ for (const entry of v4Options.cssEntries) {
2731
+ const filePath = _pathe2.default.isAbsolute(entry) ? entry : _pathe2.default.resolve(options.projectRoot, entry);
2732
+ if (!await _fsextra2.default.pathExists(filePath)) {
2733
+ continue;
2734
+ }
2735
+ const css = await _fsextra2.default.readFile(filePath, "utf8");
2736
+ const entryDir = _pathe2.default.dirname(filePath);
2737
+ const designSystemBases = resolvedConfiguredBase && resolvedConfiguredBase !== entryDir ? [entryDir, resolvedConfiguredBase] : [entryDir];
2738
+ const sourcesBase = _nullishCoalesce(resolvedConfiguredBase, () => ( entryDir));
2739
+ const sources = resolveSources(sourcesBase);
2740
+ const firstBase = _nullishCoalesce(designSystemBases[0], () => ( entryDir));
2741
+ const extractOptions = {
2742
+ cwd: options.projectRoot,
2743
+ base: firstBase,
2744
+ baseFallbacks: designSystemBases.slice(1),
2745
+ css,
2746
+ ...sources === void 0 ? {} : { sources }
2747
+ };
2748
+ const candidates = await extractValidCandidates(extractOptions);
2749
+ for (const candidate of candidates) {
2750
+ if (options.filter(candidate)) {
2751
+ set.add(candidate);
2752
+ }
2753
+ }
2754
+ }
2755
+ } else {
2756
+ const baseForCss = _nullishCoalesce(resolvedConfiguredBase, () => ( resolvedDefaultBase));
2757
+ const sources = resolveSources(baseForCss);
2758
+ const extractOptions = {
2759
+ cwd: options.projectRoot,
2760
+ base: baseForCss,
2761
+ ...v4Options.css === void 0 ? {} : { css: v4Options.css },
2762
+ ...sources === void 0 ? {} : { sources }
2763
+ };
2764
+ const candidates = await extractValidCandidates(extractOptions);
2765
+ for (const candidate of candidates) {
2766
+ if (options.filter(candidate)) {
2767
+ set.add(candidate);
2768
+ }
2769
+ }
2770
+ }
2771
+ return set;
2772
+ }
2773
+
2774
+ // src/runtime/context-registry.ts
2775
+ var _module = require('module');
2776
+
2777
+
2778
+ var require2 = _module.createRequire.call(void 0, importMetaUrl);
2779
+ function resolveRuntimeEntry(packageInfo, majorVersion) {
2780
+ const root = packageInfo.rootPath;
2781
+ if (majorVersion === 2) {
2782
+ const jitIndex = _pathe2.default.join(root, "lib/jit/index.js");
2783
+ if (_fsextra2.default.existsSync(jitIndex)) {
2784
+ return jitIndex;
2785
+ }
2786
+ } else if (majorVersion === 3) {
2787
+ const plugin = _pathe2.default.join(root, "lib/plugin.js");
2788
+ const index = _pathe2.default.join(root, "lib/index.js");
2789
+ if (_fsextra2.default.existsSync(plugin)) {
2790
+ return plugin;
2791
+ }
2792
+ if (_fsextra2.default.existsSync(index)) {
2793
+ return index;
2794
+ }
2795
+ }
2796
+ return void 0;
2797
+ }
2798
+ function loadRuntimeContexts(packageInfo, majorVersion, refProperty) {
2799
+ if (majorVersion === 4) {
2800
+ return [];
2801
+ }
2802
+ const entry = resolveRuntimeEntry(packageInfo, majorVersion);
2803
+ if (!entry) {
2804
+ return [];
2805
+ }
2806
+ const moduleExports = require2(entry);
2807
+ if (!moduleExports) {
2808
+ return [];
2809
+ }
2810
+ const ref = moduleExports[refProperty];
2811
+ if (!ref) {
2812
+ return [];
2813
+ }
2814
+ if (Array.isArray(ref)) {
2815
+ return ref;
2816
+ }
2817
+ if (typeof ref === "object" && Array.isArray(ref.value)) {
2818
+ return ref.value;
2819
+ }
2820
+ return [];
2821
+ }
2822
+
2823
+ // src/runtime/process-tailwindcss.ts
2824
+
2825
+
2826
+ var _postcss = require('postcss'); var _postcss2 = _interopRequireDefault(_postcss);
2827
+ var _tailwindcssconfig = require('tailwindcss-config');
2828
+ var require3 = _module.createRequire.call(void 0, importMetaUrl);
2829
+ async function resolveConfigPath(options) {
2830
+ if (options.config && _pathe2.default.isAbsolute(options.config)) {
2831
+ return options.config;
2832
+ }
2833
+ const result = await _tailwindcssconfig.loadConfig.call(void 0, { cwd: options.cwd });
2834
+ if (!result) {
2835
+ throw new Error(`Unable to locate Tailwind CSS config from ${options.cwd}`);
2836
+ }
2837
+ return result.filepath;
2838
+ }
2839
+ async function runTailwindBuild(options) {
2840
+ const configPath = await resolveConfigPath(options);
2841
+ const pluginName = _nullishCoalesce(options.postcssPlugin, () => ( (options.majorVersion === 4 ? "@tailwindcss/postcss" : "tailwindcss")));
2842
+ if (options.majorVersion === 4) {
2843
+ return _postcss2.default.call(void 0, [
2844
+ require3(pluginName)({
2845
+ config: configPath
2846
+ })
2847
+ ]).process("@import 'tailwindcss';", {
2848
+ from: void 0
2849
+ });
2850
+ }
2851
+ return _postcss2.default.call(void 0, [
2852
+ require3(pluginName)({
2853
+ config: configPath
2854
+ })
2855
+ ]).process("@tailwind base;@tailwind components;@tailwind utilities;", {
2856
+ from: void 0
2857
+ });
2858
+ }
2859
+
2860
+ // src/api/tailwindcss-patcher.ts
2861
+
2862
+
2863
+ var _localpkg = require('local-pkg');
2864
+
2865
+ var _semver = require('semver');
2866
+
2867
+ // src/options/legacy.ts
2868
+ function normalizeLegacyFeatures(patch) {
2869
+ const apply = _optionalChain([patch, 'optionalAccess', _96 => _96.applyPatches]);
2870
+ const extend = _optionalChain([apply, 'optionalAccess', _97 => _97.extendLengthUnits]);
2871
+ let extendOption = false;
2872
+ if (extend && typeof extend === "object") {
2873
+ extendOption = {
2874
+ ...extend,
2875
+ enabled: true
2876
+ };
2877
+ } else if (extend === true) {
2878
+ extendOption = {
2879
+ enabled: true,
2880
+ units: ["rpx"],
2881
+ ..._optionalChain([patch, 'optionalAccess', _98 => _98.overwrite]) === void 0 ? {} : { overwrite: patch.overwrite }
2882
+ };
2883
+ }
2884
+ return {
2885
+ exposeContext: _nullishCoalesce(_optionalChain([apply, 'optionalAccess', _99 => _99.exportContext]), () => ( true)),
2886
+ extendLengthUnits: extendOption
2887
+ };
2888
+ }
2889
+ function fromLegacyOptions(options) {
2890
+ if (!options) {
2891
+ return {};
2892
+ }
2893
+ const patch = options.patch;
2894
+ const features = normalizeLegacyFeatures(patch);
2895
+ const output = _optionalChain([patch, 'optionalAccess', _100 => _100.output]);
2896
+ const tailwindConfig = _optionalChain([patch, 'optionalAccess', _101 => _101.tailwindcss]);
2897
+ const tailwindVersion = _optionalChain([tailwindConfig, 'optionalAccess', _102 => _102.version]);
2898
+ const tailwindV2 = _optionalChain([tailwindConfig, 'optionalAccess', _103 => _103.v2]);
2899
+ const tailwindV3 = _optionalChain([tailwindConfig, 'optionalAccess', _104 => _104.v3]);
2900
+ const tailwindV4 = _optionalChain([tailwindConfig, 'optionalAccess', _105 => _105.v4]);
2901
+ const tailwindConfigPath = _nullishCoalesce(_optionalChain([tailwindV3, 'optionalAccess', _106 => _106.config]), () => ( _optionalChain([tailwindV2, 'optionalAccess', _107 => _107.config])));
2902
+ const tailwindCwd = _nullishCoalesce(_nullishCoalesce(_optionalChain([tailwindV3, 'optionalAccess', _108 => _108.cwd]), () => ( _optionalChain([tailwindV2, 'optionalAccess', _109 => _109.cwd]))), () => ( _optionalChain([patch, 'optionalAccess', _110 => _110.cwd])));
2903
+ const normalizedExtract = output ? {
2904
+ ...output.filename === void 0 ? {} : { file: output.filename },
2905
+ pretty: output.loose ? 2 : false,
2906
+ ...output.removeUniversalSelector === void 0 ? {} : { removeUniversalSelector: output.removeUniversalSelector }
2907
+ } : void 0;
2908
+ const normalizedTailwindcss = {
2909
+ ..._optionalChain([patch, 'optionalAccess', _111 => _111.packageName]) === void 0 ? {} : { packageName: patch.packageName },
2910
+ ...tailwindVersion === void 0 ? {} : { version: tailwindVersion },
2911
+ ..._optionalChain([patch, 'optionalAccess', _112 => _112.resolve]) === void 0 ? {} : { resolve: patch.resolve },
2912
+ ...tailwindConfigPath === void 0 ? {} : { config: tailwindConfigPath },
2913
+ ...tailwindCwd === void 0 ? {} : { cwd: tailwindCwd },
2914
+ ...tailwindV2 === void 0 ? {} : { v2: tailwindV2 },
2915
+ ...tailwindV3 === void 0 ? {} : { v3: tailwindV3 },
2916
+ ...tailwindV4 === void 0 ? {} : { v4: tailwindV4 }
2917
+ };
2918
+ const normalizedCache = typeof options.cache === "boolean" ? options.cache : options.cache ? {
2919
+ ...options.cache,
2920
+ enabled: _nullishCoalesce(options.cache.enabled, () => ( true))
2921
+ } : void 0;
2922
+ const normalizedApply = {
2923
+ ..._optionalChain([patch, 'optionalAccess', _113 => _113.overwrite]) === void 0 ? {} : { overwrite: patch.overwrite },
2924
+ exposeContext: features.exposeContext,
2925
+ extendLengthUnits: features.extendLengthUnits
2926
+ };
2927
+ return {
2928
+ ..._optionalChain([patch, 'optionalAccess', _114 => _114.cwd]) === void 0 ? {} : { projectRoot: patch.cwd },
2929
+ ..._optionalChain([patch, 'optionalAccess', _115 => _115.filter]) === void 0 ? {} : { filter: patch.filter },
2930
+ ...normalizedCache === void 0 ? {} : { cache: normalizedCache },
2931
+ ...normalizedExtract === void 0 ? {} : { extract: normalizedExtract },
2932
+ ...Object.keys(normalizedTailwindcss).length === 0 ? {} : { tailwindcss: normalizedTailwindcss },
2933
+ apply: normalizedApply
2934
+ };
2935
+ }
2936
+ function fromUnifiedConfig(registry) {
2937
+ if (!registry) {
2938
+ return {};
2939
+ }
2940
+ const tailwind = _nullishCoalesce(registry.tailwindcss, () => ( registry.tailwind));
2941
+ const modernExtract = registry.extract;
2942
+ const legacyOutput = registry.output;
2943
+ const pretty = (() => {
2944
+ const value = _nullishCoalesce(_optionalChain([modernExtract, 'optionalAccess', _116 => _116.pretty]), () => ( _optionalChain([legacyOutput, 'optionalAccess', _117 => _117.pretty])));
2945
+ if (value === void 0) {
2946
+ return void 0;
2947
+ }
2948
+ if (typeof value === "boolean") {
2949
+ return value ? 2 : false;
2950
+ }
2951
+ return value;
2952
+ })();
2953
+ const removeUniversalSelector = _nullishCoalesce(_optionalChain([modernExtract, 'optionalAccess', _118 => _118.removeUniversalSelector]), () => ( _optionalChain([legacyOutput, 'optionalAccess', _119 => _119.stripUniversalSelector])));
2954
+ const outputFile = _nullishCoalesce(_optionalChain([modernExtract, 'optionalAccess', _120 => _120.file]), () => ( _optionalChain([legacyOutput, 'optionalAccess', _121 => _121.file])));
2955
+ const normalizedExtract = modernExtract || legacyOutput ? {
2956
+ ..._optionalChain([modernExtract, 'optionalAccess', _122 => _122.write]) === void 0 ? {} : { write: modernExtract.write },
2957
+ ...outputFile === void 0 ? {} : { file: outputFile },
2958
+ ...pretty === void 0 ? {} : { pretty },
2959
+ ...removeUniversalSelector === void 0 ? {} : { removeUniversalSelector },
2960
+ ..._optionalChain([modernExtract, 'optionalAccess', _123 => _123.format]) === void 0 ? {} : { format: modernExtract.format }
2961
+ } : void 0;
2962
+ const normalizedTailwindcss = tailwind ? {
2963
+ ...tailwind.version === void 0 ? {} : { version: tailwind.version },
2964
+ ...tailwind.packageName === void 0 ? tailwind.package === void 0 ? {} : { packageName: tailwind.package } : { packageName: tailwind.packageName },
2965
+ ...tailwind.resolve === void 0 ? {} : { resolve: tailwind.resolve },
2966
+ ...tailwind.config === void 0 ? {} : { config: tailwind.config },
2967
+ ...tailwind.cwd === void 0 ? {} : { cwd: tailwind.cwd },
2968
+ ...tailwind.v2 === void 0 ? tailwind.legacy === void 0 ? {} : { v2: tailwind.legacy } : { v2: tailwind.v2 },
2969
+ ...tailwind.v3 === void 0 ? tailwind.classic === void 0 ? {} : { v3: tailwind.classic } : { v3: tailwind.v3 },
2970
+ ...tailwind.v4 === void 0 ? tailwind.next === void 0 ? {} : { v4: tailwind.next } : { v4: tailwind.v4 }
2971
+ } : void 0;
2972
+ const normalizedApply = registry.apply ? {
2973
+ ...registry.apply.overwrite === void 0 ? {} : { overwrite: registry.apply.overwrite },
2974
+ ...registry.apply.exposeContext === void 0 ? {} : { exposeContext: registry.apply.exposeContext },
2975
+ ...registry.apply.extendLengthUnits === void 0 ? {} : { extendLengthUnits: registry.apply.extendLengthUnits }
2976
+ } : void 0;
2977
+ return {
2978
+ ...registry.projectRoot === void 0 ? {} : { projectRoot: registry.projectRoot },
2979
+ ...normalizedApply === void 0 ? {} : { apply: normalizedApply },
2980
+ ...registry.cache === void 0 ? {} : { cache: registry.cache },
2981
+ ...registry.filter === void 0 ? {} : { filter: registry.filter },
2982
+ ...normalizedExtract === void 0 ? {} : { extract: normalizedExtract },
2983
+ ...normalizedTailwindcss === void 0 ? {} : { tailwindcss: normalizedTailwindcss }
2984
+ };
2985
+ }
2986
+
2987
+ // src/patching/operations/export-context/index.ts
2988
+
2989
+
2990
+ function writeFileIfRequired(filePath, code, overwrite, successMessage) {
2991
+ if (!overwrite) {
2992
+ return;
2993
+ }
2994
+ _fsextra2.default.writeFileSync(filePath, code, {
2995
+ encoding: "utf8"
2996
+ });
2997
+ logger_default.success(successMessage);
2998
+ }
2999
+ function applyExposeContextPatch(params) {
3000
+ const { rootDir, refProperty, overwrite, majorVersion } = params;
3001
+ const result = {
3002
+ applied: false,
3003
+ files: {}
3004
+ };
3005
+ if (majorVersion === 3) {
3006
+ const processFileRelative = "lib/processTailwindFeatures.js";
3007
+ const processFilePath = _pathe2.default.resolve(rootDir, processFileRelative);
3008
+ if (_fsextra2.default.existsSync(processFilePath)) {
3009
+ const content = _fsextra2.default.readFileSync(processFilePath, "utf8");
3010
+ const { code, hasPatched } = transformProcessTailwindFeaturesReturnContext(content);
3011
+ result.files[processFileRelative] = code;
3012
+ if (!hasPatched) {
3013
+ writeFileIfRequired(
3014
+ processFilePath,
3015
+ code,
3016
+ overwrite,
3017
+ "Patched Tailwind CSS processTailwindFeatures to expose runtime context."
3018
+ );
3019
+ result.applied = true;
3020
+ }
3021
+ }
3022
+ const pluginCandidates = ["lib/plugin.js", "lib/index.js"];
3023
+ const pluginRelative = pluginCandidates.find((candidate) => _fsextra2.default.existsSync(_pathe2.default.resolve(rootDir, candidate)));
3024
+ if (pluginRelative) {
3025
+ const pluginPath = _pathe2.default.resolve(rootDir, pluginRelative);
3026
+ const content = _fsextra2.default.readFileSync(pluginPath, "utf8");
3027
+ const { code, hasPatched } = transformPostcssPlugin(content, { refProperty });
3028
+ result.files[pluginRelative] = code;
3029
+ if (!hasPatched) {
3030
+ writeFileIfRequired(
3031
+ pluginPath,
3032
+ code,
3033
+ overwrite,
3034
+ "Patched Tailwind CSS plugin entry to collect runtime contexts."
3035
+ );
3036
+ result.applied = true;
3037
+ }
3038
+ }
3039
+ } else if (majorVersion === 2) {
3040
+ const processFileRelative = "lib/jit/processTailwindFeatures.js";
3041
+ const processFilePath = _pathe2.default.resolve(rootDir, processFileRelative);
3042
+ if (_fsextra2.default.existsSync(processFilePath)) {
3043
+ const content = _fsextra2.default.readFileSync(processFilePath, "utf8");
3044
+ const { code, hasPatched } = transformProcessTailwindFeaturesReturnContextV2(content);
3045
+ result.files[processFileRelative] = code;
3046
+ if (!hasPatched) {
3047
+ writeFileIfRequired(
3048
+ processFilePath,
3049
+ code,
3050
+ overwrite,
3051
+ "Patched Tailwind CSS JIT processTailwindFeatures to expose runtime context."
3052
+ );
3053
+ result.applied = true;
3054
+ }
3055
+ }
3056
+ const pluginRelative = "lib/jit/index.js";
3057
+ const pluginPath = _pathe2.default.resolve(rootDir, pluginRelative);
3058
+ if (_fsextra2.default.existsSync(pluginPath)) {
3059
+ const content = _fsextra2.default.readFileSync(pluginPath, "utf8");
3060
+ const { code, hasPatched } = transformPostcssPluginV2(content, { refProperty });
3061
+ result.files[pluginRelative] = code;
3062
+ if (!hasPatched) {
3063
+ writeFileIfRequired(
3064
+ pluginPath,
3065
+ code,
3066
+ overwrite,
3067
+ "Patched Tailwind CSS JIT entry to collect runtime contexts."
3068
+ );
3069
+ result.applied = true;
3070
+ }
3071
+ }
3072
+ }
3073
+ return result;
3074
+ }
3075
+
3076
+ // src/patching/patch-runner.ts
3077
+ function applyTailwindPatches(context) {
3078
+ const { packageInfo, options, majorVersion } = context;
3079
+ const results = {};
3080
+ if (options.features.exposeContext.enabled && (majorVersion === 2 || majorVersion === 3)) {
3081
+ results.exposeContext = applyExposeContextPatch({
3082
+ rootDir: packageInfo.rootPath,
3083
+ refProperty: options.features.exposeContext.refProperty,
3084
+ overwrite: options.overwrite,
3085
+ majorVersion
3086
+ });
3087
+ }
3088
+ if (_optionalChain([options, 'access', _124 => _124.features, 'access', _125 => _125.extendLengthUnits, 'optionalAccess', _126 => _126.enabled])) {
3089
+ if (majorVersion === 3) {
3090
+ results.extendLengthUnits = applyExtendLengthUnitsPatchV3(
3091
+ packageInfo.rootPath,
3092
+ options.features.extendLengthUnits
3093
+ );
3094
+ } else if (majorVersion === 4) {
3095
+ results.extendLengthUnits = applyExtendLengthUnitsPatchV4(
3096
+ packageInfo.rootPath,
3097
+ options.features.extendLengthUnits
3098
+ );
3099
+ }
3100
+ }
3101
+ return results;
3102
+ }
3103
+
3104
+ // src/api/tailwindcss-patcher.ts
3105
+ function resolveMajorVersion(version, hint) {
3106
+ if (hint && [2, 3, 4].includes(hint)) {
3107
+ return hint;
3108
+ }
3109
+ if (version) {
3110
+ const coerced = _semver.coerce.call(void 0, version);
3111
+ if (coerced) {
3112
+ const major = coerced.major;
3113
+ if (major === 2 || major === 3 || major === 4) {
3114
+ return major;
3115
+ }
3116
+ if (major >= 4) {
3117
+ return 4;
3118
+ }
3119
+ }
3120
+ }
3121
+ return 3;
3122
+ }
3123
+ function resolveTailwindExecutionOptions(normalized, majorVersion) {
3124
+ const base = normalized.tailwind;
3125
+ if (majorVersion === 2 && base.v2) {
3126
+ return {
3127
+ cwd: _nullishCoalesce(_nullishCoalesce(base.v2.cwd, () => ( base.cwd)), () => ( normalized.projectRoot)),
3128
+ config: _nullishCoalesce(base.v2.config, () => ( base.config)),
3129
+ postcssPlugin: _nullishCoalesce(base.v2.postcssPlugin, () => ( base.postcssPlugin))
3130
+ };
3131
+ }
3132
+ if (majorVersion === 3 && base.v3) {
3133
+ return {
3134
+ cwd: _nullishCoalesce(_nullishCoalesce(base.v3.cwd, () => ( base.cwd)), () => ( normalized.projectRoot)),
3135
+ config: _nullishCoalesce(base.v3.config, () => ( base.config)),
3136
+ postcssPlugin: _nullishCoalesce(base.v3.postcssPlugin, () => ( base.postcssPlugin))
3137
+ };
3138
+ }
3139
+ return {
3140
+ cwd: _nullishCoalesce(base.cwd, () => ( normalized.projectRoot)),
3141
+ config: base.config,
3142
+ postcssPlugin: base.postcssPlugin
3143
+ };
3144
+ }
3145
+ var TailwindcssPatcher = (_class2 = class {
3146
+
3147
+
3148
+
3149
+
3150
+
3151
+ constructor(options = {}) {;_class2.prototype.__init4.call(this);
3152
+ const resolvedOptions = options && typeof options === "object" && "patch" in options ? fromLegacyOptions(options) : options;
3153
+ this.options = normalizeOptions(resolvedOptions);
3154
+ const packageInfo = _localpkg.getPackageInfoSync.call(void 0,
3155
+ this.options.tailwind.packageName,
3156
+ this.options.tailwind.resolve
3157
+ );
3158
+ if (!packageInfo) {
3159
+ throw new Error(`Unable to locate Tailwind CSS package "${this.options.tailwind.packageName}".`);
3160
+ }
3161
+ this.packageInfo = packageInfo;
3162
+ this.majorVersion = resolveMajorVersion(
3163
+ this.packageInfo.version,
3164
+ this.options.tailwind.versionHint
3165
+ );
3166
+ this.cacheContext = createCacheContextDescriptor(
3167
+ this.options,
3168
+ this.packageInfo,
3169
+ this.majorVersion
3170
+ );
3171
+ this.cacheStore = new CacheStore(this.options.cache, this.cacheContext);
3172
+ }
3173
+ async patch() {
3174
+ return applyTailwindPatches({
3175
+ packageInfo: this.packageInfo,
3176
+ options: this.options,
3177
+ majorVersion: this.majorVersion
3178
+ });
3179
+ }
3180
+ async getPatchStatus() {
3181
+ return getPatchStatusReport({
3182
+ packageInfo: this.packageInfo,
3183
+ options: this.options,
3184
+ majorVersion: this.majorVersion
3185
+ });
3186
+ }
3187
+ getContexts() {
3188
+ return loadRuntimeContexts(
3189
+ this.packageInfo,
3190
+ this.majorVersion,
3191
+ this.options.features.exposeContext.refProperty
3192
+ );
3193
+ }
3194
+ async runTailwindBuildIfNeeded() {
3195
+ if (this.majorVersion === 2 || this.majorVersion === 3) {
3196
+ const executionOptions = resolveTailwindExecutionOptions(this.options, this.majorVersion);
3197
+ const buildOptions = {
3198
+ cwd: executionOptions.cwd,
3199
+ majorVersion: this.majorVersion,
3200
+ ...executionOptions.config === void 0 ? {} : { config: executionOptions.config },
3201
+ ...executionOptions.postcssPlugin === void 0 ? {} : { postcssPlugin: executionOptions.postcssPlugin }
3202
+ };
3203
+ await runTailwindBuild(buildOptions);
3204
+ }
3205
+ }
3206
+ async collectClassSet() {
3207
+ if (this.majorVersion === 4) {
3208
+ return collectClassesFromTailwindV4(this.options);
3209
+ }
3210
+ const contexts = this.getContexts();
3211
+ return collectClassesFromContexts(contexts, this.options.filter);
3212
+ }
3213
+ debugCacheRead(meta) {
3214
+ if (meta.hit) {
3215
+ logger_default.debug(
3216
+ `[cache] hit fingerprint=${_nullishCoalesce(_optionalChain([meta, 'access', _127 => _127.fingerprint, 'optionalAccess', _128 => _128.slice, 'call', _129 => _129(0, 12)]), () => ( "n/a"))} schema=${_nullishCoalesce(meta.schemaVersion, () => ( "legacy"))} ${meta.details.join("; ")}`
3217
+ );
3218
+ return;
3219
+ }
3220
+ logger_default.debug(
3221
+ `[cache] miss reason=${meta.reason} fingerprint=${_nullishCoalesce(_optionalChain([meta, 'access', _130 => _130.fingerprint, 'optionalAccess', _131 => _131.slice, 'call', _132 => _132(0, 12)]), () => ( "n/a"))} schema=${_nullishCoalesce(meta.schemaVersion, () => ( "legacy"))} ${meta.details.join("; ")}`
3222
+ );
3223
+ }
3224
+ async mergeWithCache(set) {
3225
+ if (!this.options.cache.enabled) {
3226
+ return set;
3227
+ }
3228
+ const { data: existing, meta } = await this.cacheStore.readWithMeta();
3229
+ this.debugCacheRead(meta);
3230
+ if (this.options.cache.strategy === "merge") {
3231
+ for (const value of existing) {
3232
+ set.add(value);
3233
+ }
3234
+ const writeTarget = await this.cacheStore.write(set);
3235
+ if (writeTarget) {
3236
+ logger_default.debug(`[cache] stored ${set.size} classes -> ${writeTarget}`);
3237
+ }
3238
+ } else {
3239
+ if (set.size > 0) {
3240
+ const writeTarget = await this.cacheStore.write(set);
3241
+ if (writeTarget) {
3242
+ logger_default.debug(`[cache] stored ${set.size} classes -> ${writeTarget}`);
3243
+ }
3244
+ } else {
3245
+ return existing;
3246
+ }
3247
+ }
3248
+ return set;
3249
+ }
3250
+ mergeWithCacheSync(set) {
3251
+ if (!this.options.cache.enabled) {
3252
+ return set;
3253
+ }
3254
+ const { data: existing, meta } = this.cacheStore.readWithMetaSync();
3255
+ this.debugCacheRead(meta);
3256
+ if (this.options.cache.strategy === "merge") {
3257
+ for (const value of existing) {
3258
+ set.add(value);
3259
+ }
3260
+ const writeTarget = this.cacheStore.writeSync(set);
3261
+ if (writeTarget) {
3262
+ logger_default.debug(`[cache] stored ${set.size} classes -> ${writeTarget}`);
3263
+ }
3264
+ } else {
3265
+ if (set.size > 0) {
3266
+ const writeTarget = this.cacheStore.writeSync(set);
3267
+ if (writeTarget) {
3268
+ logger_default.debug(`[cache] stored ${set.size} classes -> ${writeTarget}`);
3269
+ }
3270
+ } else {
3271
+ return existing;
3272
+ }
3273
+ }
3274
+ return set;
3275
+ }
3276
+ async getClassSet() {
3277
+ await this.runTailwindBuildIfNeeded();
3278
+ const set = await this.collectClassSet();
3279
+ return this.mergeWithCache(set);
3280
+ }
3281
+ getClassSetSync() {
3282
+ if (this.majorVersion === 4) {
3283
+ throw new Error("getClassSetSync is not supported for Tailwind CSS v4 projects. Use getClassSet instead.");
3284
+ }
3285
+ const contexts = this.getContexts();
3286
+ const set = collectClassesFromContexts(contexts, this.options.filter);
3287
+ const merged = this.mergeWithCacheSync(set);
3288
+ if (contexts.length === 0 && merged.size === 0) {
3289
+ return void 0;
3290
+ }
3291
+ return merged;
3292
+ }
3293
+ async extract(options) {
3294
+ const shouldWrite = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _133 => _133.write]), () => ( this.options.output.enabled));
3295
+ const classSet = await this.getClassSet();
3296
+ const classList = Array.from(classSet);
3297
+ const result = {
3298
+ classList,
3299
+ classSet
3300
+ };
3301
+ if (!shouldWrite || !this.options.output.file) {
3302
+ return result;
3303
+ }
3304
+ const target = _pathe2.default.resolve(this.options.output.file);
3305
+ await _fsextra2.default.ensureDir(_pathe2.default.dirname(target));
3306
+ if (this.options.output.format === "json") {
3307
+ const spaces = typeof this.options.output.pretty === "number" ? this.options.output.pretty : void 0;
3308
+ await _fsextra2.default.writeJSON(target, classList, { spaces });
3309
+ } else {
3310
+ await _fsextra2.default.writeFile(target, `${classList.join("\n")}
3311
+ `, "utf8");
3312
+ }
3313
+ logger_default.success(`Tailwind CSS class list saved to ${target.replace(_process2.default.cwd(), ".")}`);
3314
+ return {
3315
+ ...result,
3316
+ filename: target
3317
+ };
3318
+ }
3319
+ async clearCache(options) {
3320
+ const result = await this.cacheStore.clear(options);
3321
+ logger_default.debug(
3322
+ `[cache] clear scope=${result.scope} contexts=${result.contextsRemoved} entries=${result.entriesRemoved} files=${result.filesRemoved}`
3323
+ );
3324
+ return result;
3325
+ }
3326
+ // Backwards compatibility helper used by tests and API consumers.
3327
+ __init4() {this.extractValidCandidates = exports.extractValidCandidates = extractValidCandidates}
3328
+ async collectContentTokens(options) {
3329
+ return extractProjectCandidatesWithPositions({
3330
+ cwd: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _134 => _134.cwd]), () => ( this.options.projectRoot)),
3331
+ sources: _nullishCoalesce(_nullishCoalesce(_optionalChain([options, 'optionalAccess', _135 => _135.sources]), () => ( _optionalChain([this, 'access', _136 => _136.options, 'access', _137 => _137.tailwind, 'access', _138 => _138.v4, 'optionalAccess', _139 => _139.sources]))), () => ( []))
3332
+ });
3333
+ }
3334
+ async collectContentTokensByFile(options) {
3335
+ const collectContentOptions = {
3336
+ ..._optionalChain([options, 'optionalAccess', _140 => _140.cwd]) === void 0 ? {} : { cwd: options.cwd },
3337
+ ..._optionalChain([options, 'optionalAccess', _141 => _141.sources]) === void 0 ? {} : { sources: options.sources }
3338
+ };
3339
+ const report = await this.collectContentTokens(collectContentOptions);
3340
+ const groupOptions = {
3341
+ ..._optionalChain([options, 'optionalAccess', _142 => _142.key]) === void 0 ? {} : { key: options.key },
3342
+ ..._optionalChain([options, 'optionalAccess', _143 => _143.stripAbsolutePaths]) === void 0 ? {} : { stripAbsolutePaths: options.stripAbsolutePaths }
3343
+ };
3344
+ return groupTokensByFile(report, groupOptions);
3345
+ }
3346
+ }, _class2);
3347
+
3348
+ // src/cli/migrate-config.ts
3349
+
3350
+
3351
+
3352
+
3353
+
3354
+ var DEFAULT_CONFIG_FILENAMES = [
3355
+ "tailwindcss-patch.config.ts",
3356
+ "tailwindcss-patch.config.js",
3357
+ "tailwindcss-patch.config.mjs",
3358
+ "tailwindcss-patch.config.cjs",
3359
+ "tailwindcss-mangle.config.ts",
3360
+ "tailwindcss-mangle.config.js",
3361
+ "tailwindcss-mangle.config.mjs",
3362
+ "tailwindcss-mangle.config.cjs"
3363
+ ];
3364
+ var DEFAULT_CONFIG_FILENAME_SET = new Set(DEFAULT_CONFIG_FILENAMES);
3365
+ var DEFAULT_WORKSPACE_IGNORED_DIRS = /* @__PURE__ */ new Set([
3366
+ ".git",
3367
+ ".idea",
3368
+ ".turbo",
3369
+ ".vscode",
3370
+ ".yarn",
3371
+ "coverage",
3372
+ "dist",
3373
+ "node_modules",
3374
+ "tmp"
3375
+ ]);
3376
+ var DEFAULT_WORKSPACE_MAX_DEPTH = 6;
3377
+ var MIGRATION_REPORT_KIND = "tw-patch-migrate-report";
3378
+ var MIGRATION_REPORT_SCHEMA_VERSION = 1;
3379
+ var ROOT_LEGACY_KEYS = ["cwd", "overwrite", "tailwind", "features", "output", "applyPatches"];
3380
+ function getPropertyKeyName(property) {
3381
+ if (!property.computed && t5.isIdentifier(property.key)) {
3382
+ return property.key.name;
3383
+ }
3384
+ if (t5.isStringLiteral(property.key)) {
3385
+ return property.key.value;
3386
+ }
3387
+ return void 0;
3388
+ }
3389
+ function findObjectProperty(objectExpression4, name) {
3390
+ for (const property of objectExpression4.properties) {
3391
+ if (!t5.isObjectProperty(property)) {
3392
+ continue;
3393
+ }
3394
+ if (getPropertyKeyName(property) === name) {
3395
+ return property;
3396
+ }
3397
+ }
3398
+ return void 0;
3399
+ }
3400
+ function findObjectExpressionProperty(objectExpression4, name) {
3401
+ const property = findObjectProperty(objectExpression4, name);
3402
+ if (!property) {
3403
+ return void 0;
3404
+ }
3405
+ if (t5.isObjectExpression(property.value)) {
3406
+ return property.value;
3407
+ }
3408
+ return void 0;
3409
+ }
3410
+ function removeObjectProperty(objectExpression4, property) {
3411
+ const index = objectExpression4.properties.indexOf(property);
3412
+ if (index >= 0) {
3413
+ objectExpression4.properties.splice(index, 1);
3414
+ }
3415
+ }
3416
+ function hasObjectProperty(objectExpression4, name) {
3417
+ return findObjectProperty(objectExpression4, name) !== void 0;
3418
+ }
3419
+ function keyAsIdentifier(name) {
3420
+ return t5.identifier(name);
3421
+ }
3422
+ function mergeObjectProperties(target, source) {
3423
+ let changed = false;
3424
+ for (const sourceProperty of source.properties) {
3425
+ if (t5.isSpreadElement(sourceProperty)) {
3426
+ target.properties.push(sourceProperty);
3427
+ changed = true;
3428
+ continue;
3429
+ }
3430
+ const sourceKey = getPropertyKeyName(sourceProperty);
3431
+ if (!sourceKey) {
3432
+ target.properties.push(sourceProperty);
3433
+ changed = true;
3434
+ continue;
3435
+ }
3436
+ if (hasObjectProperty(target, sourceKey)) {
3437
+ continue;
3438
+ }
3439
+ target.properties.push(sourceProperty);
3440
+ changed = true;
3441
+ }
3442
+ return changed;
3443
+ }
3444
+ function moveProperty(objectExpression4, from, to, changes, scope) {
3445
+ const source = findObjectProperty(objectExpression4, from);
3446
+ if (!source) {
3447
+ return false;
3448
+ }
3449
+ const target = findObjectProperty(objectExpression4, to);
3450
+ if (!target) {
3451
+ source.key = keyAsIdentifier(to);
3452
+ source.computed = false;
3453
+ source.shorthand = false;
3454
+ changes.add(`${scope}.${from} -> ${scope}.${to}`);
3455
+ return true;
3456
+ }
3457
+ if (t5.isObjectExpression(source.value) && t5.isObjectExpression(target.value)) {
3458
+ const merged = mergeObjectProperties(target.value, source.value);
3459
+ if (merged) {
3460
+ changes.add(`${scope}.${from} merged into ${scope}.${to}`);
3461
+ }
3462
+ }
3463
+ removeObjectProperty(objectExpression4, source);
3464
+ changes.add(`${scope}.${from} removed (preferred ${scope}.${to})`);
3465
+ return true;
3466
+ }
3467
+ function migrateExtractOptions(extract, changes, scope) {
3468
+ let changed = false;
3469
+ changed = moveProperty(extract, "enabled", "write", changes, scope) || changed;
3470
+ changed = moveProperty(extract, "stripUniversalSelector", "removeUniversalSelector", changes, scope) || changed;
3471
+ return changed;
3472
+ }
3473
+ function migrateTailwindOptions(tailwindcss, changes, scope) {
3474
+ let changed = false;
3475
+ changed = moveProperty(tailwindcss, "package", "packageName", changes, scope) || changed;
3476
+ changed = moveProperty(tailwindcss, "legacy", "v2", changes, scope) || changed;
3477
+ changed = moveProperty(tailwindcss, "classic", "v3", changes, scope) || changed;
3478
+ changed = moveProperty(tailwindcss, "next", "v4", changes, scope) || changed;
3479
+ return changed;
3480
+ }
3481
+ function migrateApplyOptions(apply, changes, scope) {
3482
+ return moveProperty(apply, "exportContext", "exposeContext", changes, scope);
3483
+ }
3484
+ function ensureObjectExpressionProperty(objectExpression4, name, changes, scope) {
3485
+ const existing = findObjectProperty(objectExpression4, name);
3486
+ if (existing) {
3487
+ return t5.isObjectExpression(existing.value) ? existing.value : void 0;
3488
+ }
3489
+ const value = t5.objectExpression([]);
3490
+ objectExpression4.properties.push(t5.objectProperty(keyAsIdentifier(name), value));
3491
+ changes.add(`${scope}.${name} created`);
3492
+ return value;
3493
+ }
3494
+ function moveOverwriteToApply(objectExpression4, changes, scope) {
3495
+ const overwrite = findObjectProperty(objectExpression4, "overwrite");
3496
+ if (!overwrite) {
3497
+ return false;
3498
+ }
3499
+ const apply = ensureObjectExpressionProperty(objectExpression4, "apply", changes, scope);
3500
+ if (!apply) {
3501
+ return false;
3502
+ }
3503
+ const hasApplyOverwrite = hasObjectProperty(apply, "overwrite");
3504
+ if (!hasApplyOverwrite) {
3505
+ apply.properties.push(
3506
+ t5.objectProperty(keyAsIdentifier("overwrite"), overwrite.value)
3507
+ );
3508
+ changes.add(`${scope}.overwrite -> ${scope}.apply.overwrite`);
3509
+ }
3510
+ removeObjectProperty(objectExpression4, overwrite);
3511
+ return true;
3512
+ }
3513
+ function hasAnyRootLegacyKeys(objectExpression4) {
3514
+ return ROOT_LEGACY_KEYS.some((key) => hasObjectProperty(objectExpression4, key));
3515
+ }
3516
+ function migrateOptionObject(objectExpression4, scope, changes) {
3517
+ let changed = false;
3518
+ changed = moveProperty(objectExpression4, "cwd", "projectRoot", changes, scope) || changed;
3519
+ changed = moveProperty(objectExpression4, "tailwind", "tailwindcss", changes, scope) || changed;
3520
+ changed = moveProperty(objectExpression4, "features", "apply", changes, scope) || changed;
3521
+ changed = moveProperty(objectExpression4, "applyPatches", "apply", changes, scope) || changed;
3522
+ changed = moveProperty(objectExpression4, "output", "extract", changes, scope) || changed;
3523
+ changed = moveOverwriteToApply(objectExpression4, changes, scope) || changed;
3524
+ const extract = findObjectExpressionProperty(objectExpression4, "extract");
3525
+ if (extract) {
3526
+ changed = migrateExtractOptions(extract, changes, scope) || changed;
3527
+ }
3528
+ const tailwindcss = findObjectExpressionProperty(objectExpression4, "tailwindcss");
3529
+ if (tailwindcss) {
3530
+ changed = migrateTailwindOptions(tailwindcss, changes, scope) || changed;
3531
+ }
3532
+ const apply = findObjectExpressionProperty(objectExpression4, "apply");
3533
+ if (apply) {
3534
+ changed = migrateApplyOptions(apply, changes, scope) || changed;
3535
+ }
3536
+ return changed;
3537
+ }
3538
+ function unwrapExpression(node) {
3539
+ let current = node;
3540
+ while (t5.isTSAsExpression(current) || t5.isTSSatisfiesExpression(current) || t5.isTSTypeAssertion(current) || t5.isParenthesizedExpression(current)) {
3541
+ current = current.expression;
3542
+ }
3543
+ return current;
3544
+ }
3545
+ function resolveObjectExpressionFromExpression(expression) {
3546
+ const unwrapped = unwrapExpression(expression);
3547
+ if (t5.isObjectExpression(unwrapped)) {
3548
+ return unwrapped;
3549
+ }
3550
+ if (t5.isCallExpression(unwrapped)) {
3551
+ const [firstArg] = unwrapped.arguments;
3552
+ if (!firstArg || !t5.isExpression(firstArg)) {
3553
+ return void 0;
3554
+ }
3555
+ const firstArgUnwrapped = unwrapExpression(firstArg);
3556
+ if (t5.isObjectExpression(firstArgUnwrapped)) {
3557
+ return firstArgUnwrapped;
3558
+ }
3559
+ }
3560
+ return void 0;
3561
+ }
3562
+ function resolveObjectExpressionFromProgram(program, name) {
3563
+ for (const statement of program.body) {
3564
+ if (!t5.isVariableDeclaration(statement)) {
3565
+ continue;
3566
+ }
3567
+ for (const declaration of statement.declarations) {
3568
+ if (!t5.isIdentifier(declaration.id) || declaration.id.name !== name || !declaration.init) {
3569
+ continue;
3570
+ }
3571
+ const objectExpression4 = resolveObjectExpressionFromExpression(declaration.init);
3572
+ if (objectExpression4) {
3573
+ return objectExpression4;
3574
+ }
3575
+ }
3576
+ }
3577
+ return void 0;
3578
+ }
3579
+ function resolveRootConfigObjectExpression(program) {
3580
+ for (const statement of program.body) {
3581
+ if (!t5.isExportDefaultDeclaration(statement)) {
3582
+ continue;
3583
+ }
3584
+ const declaration = statement.declaration;
3585
+ if (t5.isIdentifier(declaration)) {
3586
+ return resolveObjectExpressionFromProgram(program, declaration.name);
3587
+ }
3588
+ const objectExpression4 = resolveObjectExpressionFromExpression(declaration);
3589
+ if (objectExpression4) {
3590
+ return objectExpression4;
3591
+ }
3592
+ }
3593
+ return void 0;
3594
+ }
3595
+ function migrateConfigSource(source) {
3596
+ const ast = _parser.parse.call(void 0, source, {
3597
+ sourceType: "module",
3598
+ plugins: ["typescript", "jsx"]
3599
+ });
3600
+ const root = resolveRootConfigObjectExpression(ast.program);
3601
+ if (!root) {
3602
+ return {
3603
+ changed: false,
3604
+ code: source,
3605
+ changes: []
3606
+ };
3607
+ }
3608
+ const changes = /* @__PURE__ */ new Set();
3609
+ let changed = false;
3610
+ const registry = findObjectExpressionProperty(root, "registry");
3611
+ if (registry) {
3612
+ changed = migrateOptionObject(registry, "registry", changes) || changed;
3613
+ }
3614
+ const patch = findObjectExpressionProperty(root, "patch");
3615
+ if (patch) {
3616
+ changed = migrateOptionObject(patch, "patch", changes) || changed;
3617
+ }
3618
+ if (hasAnyRootLegacyKeys(root)) {
3619
+ changed = migrateOptionObject(root, "root", changes) || changed;
3620
+ }
3621
+ if (!changed) {
3622
+ return {
3623
+ changed: false,
3624
+ code: source,
3625
+ changes: []
3626
+ };
3627
+ }
3628
+ const generated = _generator2.default.call(void 0, ast, {
3629
+ comments: true
3630
+ }).code;
3631
+ const code = source.endsWith("\n") ? `${generated}
3632
+ ` : generated;
3633
+ return {
3634
+ changed: true,
3635
+ code,
3636
+ changes: [...changes]
3637
+ };
3638
+ }
3639
+ function resolveTargetFiles(cwd, files) {
3640
+ const candidates = files && files.length > 0 ? files : [...DEFAULT_CONFIG_FILENAMES];
3641
+ const resolved = /* @__PURE__ */ new Set();
3642
+ for (const file of candidates) {
3643
+ resolved.add(_pathe2.default.resolve(cwd, file));
3644
+ }
3645
+ return [...resolved];
3646
+ }
3647
+ async function collectWorkspaceConfigFiles(cwd, maxDepth) {
3648
+ const files = /* @__PURE__ */ new Set();
3649
+ const queue = [{ dir: cwd, depth: 0 }];
3650
+ while (queue.length > 0) {
3651
+ const current = queue.shift();
3652
+ if (!current) {
3653
+ continue;
3654
+ }
3655
+ const { dir, depth } = current;
3656
+ let entries;
3657
+ try {
3658
+ entries = await _fsextra2.default.readdir(dir, { withFileTypes: true });
3659
+ } catch (e10) {
3660
+ continue;
3661
+ }
3662
+ for (const entry of entries) {
3663
+ const absolutePath = _pathe2.default.resolve(dir, entry.name);
3664
+ if (entry.isFile() && DEFAULT_CONFIG_FILENAME_SET.has(entry.name)) {
3665
+ files.add(absolutePath);
3666
+ continue;
3667
+ }
3668
+ if (!entry.isDirectory()) {
3669
+ continue;
3670
+ }
3671
+ if (DEFAULT_WORKSPACE_IGNORED_DIRS.has(entry.name)) {
3672
+ continue;
3673
+ }
3674
+ if (depth >= maxDepth) {
3675
+ continue;
3676
+ }
3677
+ queue.push({ dir: absolutePath, depth: depth + 1 });
3678
+ }
3679
+ }
3680
+ return [...files].sort((a, b) => a.localeCompare(b));
3681
+ }
3682
+ function resolveBackupRelativePath(cwd, file) {
3683
+ const relative = _pathe2.default.relative(cwd, file);
3684
+ const isExternal = relative.startsWith("..") || _pathe2.default.isAbsolute(relative);
3685
+ if (isExternal) {
3686
+ const sanitized = file.replace(/[:/\\]+/g, "_");
3687
+ return _pathe2.default.join("__external__", `${sanitized}.bak`);
3688
+ }
3689
+ return `${relative}.bak`;
3690
+ }
3691
+ function normalizePattern(pattern) {
3692
+ return pattern.replace(/\\/g, "/").replace(/^\.\/+/, "").replace(/^\/+/, "");
3693
+ }
3694
+ function globToRegExp(globPattern) {
3695
+ const normalized = normalizePattern(globPattern);
3696
+ let pattern = "";
3697
+ for (let i = 0; i < normalized.length; i += 1) {
3698
+ const char = normalized[i];
3699
+ if (char === "*") {
3700
+ if (normalized[i + 1] === "*") {
3701
+ pattern += ".*";
3702
+ i += 1;
3703
+ } else {
3704
+ pattern += "[^/]*";
3705
+ }
3706
+ continue;
3707
+ }
3708
+ if (char === "?") {
3709
+ pattern += "[^/]";
3710
+ continue;
3711
+ }
3712
+ if ("\\^$+?.()|{}[]".includes(char)) {
3713
+ pattern += `\\${char}`;
3714
+ continue;
3715
+ }
3716
+ pattern += char;
3717
+ }
3718
+ return new RegExp(`^${pattern}$`);
3719
+ }
3720
+ function toPatternList(patterns) {
3721
+ if (!patterns || patterns.length === 0) {
3722
+ return [];
3723
+ }
3724
+ return patterns.map((pattern) => pattern.trim()).filter(Boolean).map(globToRegExp);
3725
+ }
3726
+ function normalizeFileForPattern(file, cwd) {
3727
+ const relative = _pathe2.default.relative(cwd, file);
3728
+ if (!relative.startsWith("..") && !_pathe2.default.isAbsolute(relative)) {
3729
+ return relative.replace(/\\/g, "/");
3730
+ }
3731
+ return file.replace(/\\/g, "/");
3732
+ }
3733
+ function filterTargetFiles(targetFiles, cwd, include, exclude) {
3734
+ const includePatterns = toPatternList(include);
3735
+ const excludePatterns = toPatternList(exclude);
3736
+ if (includePatterns.length === 0 && excludePatterns.length === 0) {
3737
+ return targetFiles;
3738
+ }
3739
+ return targetFiles.filter((file) => {
3740
+ const normalized = normalizeFileForPattern(file, cwd);
3741
+ const inInclude = includePatterns.length === 0 || includePatterns.some((pattern) => pattern.test(normalized));
3742
+ if (!inInclude) {
3743
+ return false;
3744
+ }
3745
+ const inExclude = excludePatterns.some((pattern) => pattern.test(normalized));
3746
+ return !inExclude;
3747
+ });
3748
+ }
3749
+ async function migrateConfigFiles(options) {
3750
+ const cwd = _pathe2.default.resolve(options.cwd);
3751
+ const dryRun = _nullishCoalesce(options.dryRun, () => ( false));
3752
+ const rollbackOnError = _nullishCoalesce(options.rollbackOnError, () => ( true));
3753
+ const backupDirectory = options.backupDir ? _pathe2.default.resolve(cwd, options.backupDir) : void 0;
3754
+ const maxDepth = _nullishCoalesce(options.maxDepth, () => ( DEFAULT_WORKSPACE_MAX_DEPTH));
3755
+ const discoveredTargetFiles = options.files && options.files.length > 0 ? resolveTargetFiles(cwd, options.files) : options.workspace ? await collectWorkspaceConfigFiles(cwd, maxDepth) : resolveTargetFiles(cwd);
3756
+ const targetFiles = filterTargetFiles(discoveredTargetFiles, cwd, options.include, options.exclude);
3757
+ const entries = [];
3758
+ let scannedFiles = 0;
3759
+ let changedFiles = 0;
3760
+ let writtenFiles = 0;
3761
+ let backupsWritten = 0;
3762
+ let unchangedFiles = 0;
3763
+ let missingFiles = 0;
3764
+ const wroteEntries = [];
3765
+ for (const file of targetFiles) {
3766
+ const exists = await _fsextra2.default.pathExists(file);
3767
+ if (!exists) {
3768
+ missingFiles += 1;
3769
+ continue;
3770
+ }
3771
+ scannedFiles += 1;
3772
+ const source = await _fsextra2.default.readFile(file, "utf8");
3773
+ const migrated = migrateConfigSource(source);
3774
+ const entry = {
3775
+ file,
3776
+ changed: migrated.changed,
3777
+ written: false,
3778
+ rolledBack: false,
3779
+ changes: migrated.changes
3780
+ };
3781
+ entries.push(entry);
3782
+ if (migrated.changed) {
3783
+ changedFiles += 1;
3784
+ if (!dryRun) {
3785
+ try {
3786
+ if (backupDirectory) {
3787
+ const backupRelativePath = resolveBackupRelativePath(cwd, file);
3788
+ const backupFile = _pathe2.default.resolve(backupDirectory, backupRelativePath);
3789
+ await _fsextra2.default.ensureDir(_pathe2.default.dirname(backupFile));
3790
+ await _fsextra2.default.writeFile(backupFile, source, "utf8");
3791
+ entry.backupFile = backupFile;
3792
+ backupsWritten += 1;
3793
+ }
3794
+ await _fsextra2.default.writeFile(file, migrated.code, "utf8");
3795
+ entry.written = true;
3796
+ wroteEntries.push({ file, source, entry });
3797
+ writtenFiles += 1;
3798
+ } catch (error) {
3799
+ let rollbackCount = 0;
3800
+ if (rollbackOnError && wroteEntries.length > 0) {
3801
+ for (const written of [...wroteEntries].reverse()) {
3802
+ try {
3803
+ await _fsextra2.default.writeFile(written.file, written.source, "utf8");
3804
+ written.entry.written = false;
3805
+ written.entry.rolledBack = true;
3806
+ rollbackCount += 1;
3807
+ } catch (e11) {
3808
+ }
3809
+ }
3810
+ writtenFiles = Math.max(0, writtenFiles - rollbackCount);
3811
+ }
3812
+ const reason = error instanceof Error ? error.message : String(error);
3813
+ const rollbackHint = rollbackOnError && rollbackCount > 0 ? ` Rolled back ${rollbackCount} previously written file(s).` : "";
3814
+ throw new Error(`Failed to write migrated config "${file}": ${reason}.${rollbackHint}`);
3815
+ }
3816
+ }
3817
+ } else {
3818
+ unchangedFiles += 1;
3819
+ }
3820
+ }
3821
+ return {
3822
+ reportKind: MIGRATION_REPORT_KIND,
3823
+ schemaVersion: MIGRATION_REPORT_SCHEMA_VERSION,
3824
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
3825
+ tool: {
3826
+ name: pkgName,
3827
+ version: pkgVersion
3828
+ },
3829
+ cwd,
3830
+ dryRun,
3831
+ rollbackOnError,
3832
+ ...backupDirectory ? { backupDirectory } : {},
3833
+ scannedFiles,
3834
+ changedFiles,
3835
+ writtenFiles,
3836
+ backupsWritten,
3837
+ unchangedFiles,
3838
+ missingFiles,
3839
+ entries
3840
+ };
3841
+ }
3842
+ async function restoreConfigFiles(options) {
3843
+ const cwd = _pathe2.default.resolve(options.cwd);
3844
+ const dryRun = _nullishCoalesce(options.dryRun, () => ( false));
3845
+ const strict = _nullishCoalesce(options.strict, () => ( false));
3846
+ const reportFile = _pathe2.default.resolve(cwd, options.reportFile);
3847
+ const report = await _fsextra2.default.readJSON(reportFile);
3848
+ if (report.reportKind !== void 0 && report.reportKind !== MIGRATION_REPORT_KIND) {
3849
+ throw new Error(`Unsupported report kind "${report.reportKind}" in ${reportFile}.`);
3850
+ }
3851
+ if (report.schemaVersion !== void 0 && (!Number.isInteger(report.schemaVersion) || report.schemaVersion > MIGRATION_REPORT_SCHEMA_VERSION)) {
3852
+ throw new Error(
3853
+ `Unsupported report schema version "${String(report.schemaVersion)}" in ${reportFile}. Current supported version is ${MIGRATION_REPORT_SCHEMA_VERSION}.`
3854
+ );
3855
+ }
3856
+ const entries = Array.isArray(report.entries) ? report.entries : [];
3857
+ let scannedEntries = 0;
3858
+ let restorableEntries = 0;
3859
+ let restoredFiles = 0;
3860
+ let missingBackups = 0;
3861
+ let skippedEntries = 0;
3862
+ const restored = [];
3863
+ for (const entry of entries) {
3864
+ scannedEntries += 1;
3865
+ const targetFile = entry.file ? _pathe2.default.resolve(entry.file) : void 0;
3866
+ const backupFile = entry.backupFile ? _pathe2.default.resolve(entry.backupFile) : void 0;
3867
+ if (!targetFile || !backupFile) {
3868
+ skippedEntries += 1;
3869
+ continue;
3870
+ }
3871
+ restorableEntries += 1;
3872
+ const backupExists = await _fsextra2.default.pathExists(backupFile);
3873
+ if (!backupExists) {
3874
+ missingBackups += 1;
3875
+ continue;
3876
+ }
3877
+ if (!dryRun) {
3878
+ const backupContent = await _fsextra2.default.readFile(backupFile, "utf8");
3879
+ await _fsextra2.default.ensureDir(_pathe2.default.dirname(targetFile));
3880
+ await _fsextra2.default.writeFile(targetFile, backupContent, "utf8");
3881
+ }
3882
+ restoredFiles += 1;
3883
+ restored.push(targetFile);
3884
+ }
3885
+ if (strict && missingBackups > 0) {
3886
+ throw new Error(`Restore failed: ${missingBackups} backup file(s) missing in report ${reportFile}.`);
3887
+ }
3888
+ return {
3889
+ cwd,
3890
+ reportFile,
3891
+ ...report.reportKind === void 0 ? {} : { reportKind: report.reportKind },
3892
+ ...report.schemaVersion === void 0 ? {} : { reportSchemaVersion: report.schemaVersion },
3893
+ dryRun,
3894
+ strict,
3895
+ scannedEntries,
3896
+ restorableEntries,
3897
+ restoredFiles,
3898
+ missingBackups,
3899
+ skippedEntries,
3900
+ restored
3901
+ };
3902
+ }
3903
+
3904
+ // src/cli/commands.ts
3905
+
3906
+ var _config = require('@tailwindcss-mangle/config');
3907
+
3908
+ // ../../node_modules/.pnpm/defu@6.1.4/node_modules/defu/dist/defu.mjs
3909
+ function isPlainObject(value) {
3910
+ if (value === null || typeof value !== "object") {
3911
+ return false;
3912
+ }
3913
+ const prototype = Object.getPrototypeOf(value);
3914
+ if (prototype !== null && prototype !== Object.prototype && Object.getPrototypeOf(prototype) !== null) {
3915
+ return false;
3916
+ }
3917
+ if (Symbol.iterator in value) {
3918
+ return false;
3919
+ }
3920
+ if (Symbol.toStringTag in value) {
3921
+ return Object.prototype.toString.call(value) === "[object Module]";
3922
+ }
3923
+ return true;
3924
+ }
3925
+ function _defu(baseObject, defaults, namespace = ".", merger) {
3926
+ if (!isPlainObject(defaults)) {
3927
+ return _defu(baseObject, {}, namespace, merger);
3928
+ }
3929
+ const object = Object.assign({}, defaults);
3930
+ for (const key in baseObject) {
3931
+ if (key === "__proto__" || key === "constructor") {
3932
+ continue;
3933
+ }
3934
+ const value = baseObject[key];
3935
+ if (value === null || value === void 0) {
3936
+ continue;
3937
+ }
3938
+ if (merger && merger(object, key, value, namespace)) {
3939
+ continue;
3940
+ }
3941
+ if (Array.isArray(value) && Array.isArray(object[key])) {
3942
+ object[key] = [...value, ...object[key]];
3943
+ } else if (isPlainObject(value) && isPlainObject(object[key])) {
3944
+ object[key] = _defu(
3945
+ value,
3946
+ object[key],
3947
+ (namespace ? `${namespace}.` : "") + key.toString(),
3948
+ merger
3949
+ );
3950
+ } else {
3951
+ object[key] = value;
3952
+ }
3953
+ }
3954
+ return object;
3955
+ }
3956
+ function createDefu(merger) {
3957
+ return (...arguments_) => (
3958
+ // eslint-disable-next-line unicorn/no-array-reduce
3959
+ arguments_.reduce((p, c) => _defu(p, c, "", merger), {})
3960
+ );
3961
+ }
3962
+ var defu = createDefu();
3963
+ var defuFn = createDefu((object, key, currentValue) => {
3964
+ if (object[key] !== void 0 && typeof currentValue === "function") {
3965
+ object[key] = currentValue(object[key]);
3966
+ return true;
3967
+ }
3968
+ });
3969
+ var defuArrayFn = createDefu((object, key, currentValue) => {
3970
+ if (Array.isArray(object[key]) && typeof currentValue === "function") {
3971
+ object[key] = currentValue(object[key]);
3972
+ return true;
3973
+ }
3974
+ });
3975
+
3976
+ // ../shared/src/utils.ts
3977
+ var defuOverrideArray = createDefu((obj, key, value) => {
3978
+ if (Array.isArray(obj[key]) && Array.isArray(value)) {
3979
+ obj[key] = value;
3980
+ return true;
3981
+ }
3982
+ });
3983
+ var preserveClassNames = [
3984
+ // https://tailwindcss.com/docs/transition-timing-function start
3985
+ // https://github.com/sonofmagic/tailwindcss-mangle/issues/21
3986
+ "ease-out",
3987
+ "ease-linear",
3988
+ "ease-in",
3989
+ "ease-in-out"
3990
+ // https://tailwindcss.com/docs/transition-timing-function end
3991
+ ];
3992
+ var preserveClassNamesMap = preserveClassNames.reduce((acc, cur) => {
3993
+ acc[cur] = true;
3994
+ return acc;
3995
+ }, {});
3996
+ var acceptChars = [..."abcdefghijklmnopqrstuvwxyz"];
3997
+
3998
+ // src/cli/commands.ts
3999
+ var _cac = require('cac'); var _cac2 = _interopRequireDefault(_cac);
4000
+
4001
+
4002
+ var tailwindcssPatchCommands = ["install", "extract", "tokens", "init", "migrate", "restore", "validate", "status"];
4003
+ var VALIDATE_EXIT_CODES = {
4004
+ OK: 0,
4005
+ REPORT_INCOMPATIBLE: 21,
4006
+ MISSING_BACKUPS: 22,
4007
+ IO_ERROR: 23,
4008
+ UNKNOWN_ERROR: 24
4009
+ };
4010
+ var VALIDATE_FAILURE_REASONS = [
4011
+ "report-incompatible",
4012
+ "missing-backups",
4013
+ "io-error",
4014
+ "unknown-error"
4015
+ ];
4016
+ var IO_ERROR_CODES = /* @__PURE__ */ new Set(["ENOENT", "EACCES", "EPERM", "EISDIR", "ENOTDIR", "EMFILE", "ENFILE"]);
4017
+ function isNodeError(error) {
4018
+ return !!error && typeof error === "object" && ("code" in error || "message" in error);
4019
+ }
4020
+ function classifyValidateError(error) {
4021
+ const message = error instanceof Error ? error.message : String(error);
4022
+ if (message.startsWith("Unsupported report kind") || message.startsWith("Unsupported report schema version")) {
4023
+ return {
4024
+ reason: "report-incompatible",
4025
+ exitCode: VALIDATE_EXIT_CODES.REPORT_INCOMPATIBLE,
4026
+ message
4027
+ };
4028
+ }
4029
+ if (message.startsWith("Restore failed:")) {
4030
+ return {
4031
+ reason: "missing-backups",
4032
+ exitCode: VALIDATE_EXIT_CODES.MISSING_BACKUPS,
4033
+ message
4034
+ };
4035
+ }
4036
+ if (isNodeError(error) && typeof error.code === "string" && IO_ERROR_CODES.has(error.code)) {
4037
+ return {
4038
+ reason: "io-error",
4039
+ exitCode: VALIDATE_EXIT_CODES.IO_ERROR,
4040
+ message
4041
+ };
4042
+ }
4043
+ return {
4044
+ reason: "unknown-error",
4045
+ exitCode: VALIDATE_EXIT_CODES.UNKNOWN_ERROR,
4046
+ message
4047
+ };
4048
+ }
4049
+ var ValidateCommandError = class extends Error {
4050
+
4051
+
4052
+ constructor(summary, options) {
4053
+ super(summary.message, options);
4054
+ this.name = "ValidateCommandError";
4055
+ this.reason = summary.reason;
4056
+ this.exitCode = summary.exitCode;
4057
+ }
4058
+ };
4059
+ var TOKEN_FORMATS = ["json", "lines", "grouped-json"];
4060
+ var DEFAULT_TOKEN_REPORT = ".tw-patch/tw-token-report.json";
4061
+ function formatTokenLine(entry) {
4062
+ return `${entry.relativeFile}:${entry.line}:${entry.column} ${entry.rawCandidate} (${entry.start}-${entry.end})`;
4063
+ }
4064
+ function formatGroupedPreview(map, limit = 3) {
4065
+ const files = Object.keys(map);
4066
+ if (!files.length) {
4067
+ return { preview: "", moreFiles: 0 };
4068
+ }
4069
+ const lines = files.slice(0, limit).map((file) => {
4070
+ const tokens = _nullishCoalesce(map[file], () => ( []));
4071
+ const sample = tokens.slice(0, 3).map((token) => token.rawCandidate).join(", ");
4072
+ const suffix = tokens.length > 3 ? ", \u2026" : "";
4073
+ return `${file}: ${tokens.length} tokens (${sample}${suffix})`;
4074
+ });
4075
+ return {
4076
+ preview: lines.join("\n"),
4077
+ moreFiles: Math.max(0, files.length - limit)
4078
+ };
4079
+ }
4080
+ function resolveCwd(rawCwd) {
4081
+ if (!rawCwd) {
4082
+ return _process2.default.cwd();
4083
+ }
4084
+ return _pathe2.default.resolve(rawCwd);
4085
+ }
4086
+ function createDefaultRunner(factory) {
4087
+ let promise;
4088
+ return () => {
4089
+ if (!promise) {
4090
+ promise = factory();
4091
+ }
4092
+ return promise;
4093
+ };
4094
+ }
4095
+ async function loadPatchOptionsForCwd(cwd, overrides) {
4096
+ const { config } = await _config.getConfig.call(void 0, cwd);
4097
+ const legacyConfig = config;
4098
+ const base = _optionalChain([config, 'optionalAccess', _144 => _144.registry]) ? fromUnifiedConfig(config.registry) : _optionalChain([legacyConfig, 'optionalAccess', _145 => _145.patch]) ? fromLegacyOptions({ patch: legacyConfig.patch }) : {};
4099
+ const merged = defu(_nullishCoalesce(overrides, () => ( {})), base);
4100
+ return merged;
4101
+ }
4102
+ function createCommandContext(cli, command, commandName, args, cwd) {
4103
+ let cachedOptions;
4104
+ let cachedPatcher;
4105
+ let cachedConfig;
4106
+ const loadPatchOptionsForContext = (overrides) => {
4107
+ if (overrides) {
4108
+ return loadPatchOptionsForCwd(cwd, overrides);
4109
+ }
4110
+ if (!cachedOptions) {
4111
+ cachedOptions = loadPatchOptionsForCwd(cwd);
4112
+ }
4113
+ return cachedOptions;
4114
+ };
4115
+ const createPatcherForContext = async (overrides) => {
4116
+ if (overrides) {
4117
+ const patchOptions = await loadPatchOptionsForCwd(cwd, overrides);
4118
+ return new TailwindcssPatcher(patchOptions);
4119
+ }
4120
+ if (!cachedPatcher) {
4121
+ cachedPatcher = loadPatchOptionsForContext().then((options) => new TailwindcssPatcher(options));
4122
+ }
4123
+ return cachedPatcher;
4124
+ };
4125
+ return {
4126
+ cli,
4127
+ command,
4128
+ commandName,
4129
+ args,
4130
+ cwd,
4131
+ logger: logger_default,
4132
+ loadConfig: () => {
4133
+ if (!cachedConfig) {
4134
+ cachedConfig = _config.getConfig.call(void 0, cwd);
4135
+ }
4136
+ return cachedConfig;
4137
+ },
4138
+ loadPatchOptions: loadPatchOptionsForContext,
4139
+ createPatcher: createPatcherForContext
4140
+ };
4141
+ }
4142
+ function createCwdOptionDefinition(description = "Working directory") {
4143
+ return {
4144
+ flags: "--cwd <dir>",
4145
+ description,
4146
+ config: { default: _process2.default.cwd() }
4147
+ };
4148
+ }
4149
+ function buildDefaultCommandDefinitions() {
4150
+ return {
4151
+ install: {
4152
+ description: "Apply Tailwind CSS runtime patches",
4153
+ optionDefs: [createCwdOptionDefinition()]
4154
+ },
4155
+ extract: {
4156
+ description: "Collect generated class names into a cache file",
4157
+ optionDefs: [
4158
+ createCwdOptionDefinition(),
4159
+ { flags: "--output <file>", description: "Override output file path" },
4160
+ { flags: "--format <format>", description: "Output format (json|lines)" },
4161
+ { flags: "--css <file>", description: "Tailwind CSS entry CSS when using v4" },
4162
+ { flags: "--no-write", description: "Skip writing to disk" }
4163
+ ]
4164
+ },
4165
+ tokens: {
4166
+ description: "Extract Tailwind tokens with file/position metadata",
4167
+ optionDefs: [
4168
+ createCwdOptionDefinition(),
4169
+ { flags: "--output <file>", description: "Override output file path", config: { default: DEFAULT_TOKEN_REPORT } },
4170
+ {
4171
+ flags: "--format <format>",
4172
+ description: "Output format (json|lines|grouped-json)",
4173
+ config: { default: "json" }
4174
+ },
4175
+ {
4176
+ flags: "--group-key <key>",
4177
+ description: "Grouping key for grouped-json output (relative|absolute)",
4178
+ config: { default: "relative" }
4179
+ },
4180
+ { flags: "--no-write", description: "Skip writing to disk" }
4181
+ ]
4182
+ },
4183
+ init: {
4184
+ description: "Generate a tailwindcss-patch config file",
4185
+ optionDefs: [createCwdOptionDefinition()]
4186
+ },
4187
+ migrate: {
4188
+ description: "Migrate deprecated config fields to modern options",
4189
+ optionDefs: [
4190
+ createCwdOptionDefinition(),
4191
+ { flags: "--config <file>", description: "Migrate a specific config file path" },
4192
+ { flags: "--workspace", description: "Scan workspace recursively for config files" },
4193
+ { flags: "--max-depth <n>", description: "Maximum recursion depth for --workspace", config: { default: 6 } },
4194
+ { flags: "--include <glob>", description: "Only migrate files that match this glob (repeatable)" },
4195
+ { flags: "--exclude <glob>", description: "Skip files that match this glob (repeatable)" },
4196
+ { flags: "--report-file <file>", description: "Write migration report JSON to a file" },
4197
+ { flags: "--backup-dir <dir>", description: "Write pre-migration backups into this directory" },
4198
+ { flags: "--check", description: "Exit with an error when migration changes are required" },
4199
+ { flags: "--json", description: "Print the migration report as JSON" },
4200
+ { flags: "--dry-run", description: "Preview changes without writing files" }
4201
+ ]
4202
+ },
4203
+ restore: {
4204
+ description: "Restore config files from a previous migration report backup snapshot",
4205
+ optionDefs: [
4206
+ createCwdOptionDefinition(),
4207
+ { flags: "--report-file <file>", description: "Migration report file generated by migrate" },
4208
+ { flags: "--dry-run", description: "Preview restore targets without writing files" },
4209
+ { flags: "--strict", description: "Fail when any backup file is missing" },
4210
+ { flags: "--json", description: "Print the restore result as JSON" }
4211
+ ]
4212
+ },
4213
+ validate: {
4214
+ description: "Validate migration report compatibility without modifying files",
4215
+ optionDefs: [
4216
+ createCwdOptionDefinition(),
4217
+ { flags: "--report-file <file>", description: "Migration report file to validate" },
4218
+ { flags: "--strict", description: "Fail when any backup file is missing" },
4219
+ { flags: "--json", description: "Print validation result as JSON" }
4220
+ ]
4221
+ },
4222
+ status: {
4223
+ description: "Check which Tailwind patches are applied",
4224
+ optionDefs: [
4225
+ createCwdOptionDefinition(),
4226
+ { flags: "--json", description: "Print a JSON report of patch status" }
4227
+ ]
4228
+ }
4229
+ };
4230
+ }
4231
+ function addPrefixIfMissing(value, prefix) {
4232
+ if (!prefix || value.startsWith(prefix)) {
4233
+ return value;
4234
+ }
4235
+ return `${prefix}${value}`;
4236
+ }
4237
+ function resolveCommandNames(command, mountOptions, prefix) {
4238
+ const override = _optionalChain([mountOptions, 'access', _146 => _146.commandOptions, 'optionalAccess', _147 => _147[command]]);
4239
+ const baseName = _nullishCoalesce(_optionalChain([override, 'optionalAccess', _148 => _148.name]), () => ( command));
4240
+ const name = addPrefixIfMissing(baseName, prefix);
4241
+ const aliases = (_nullishCoalesce(_optionalChain([override, 'optionalAccess', _149 => _149.aliases]), () => ( []))).map((alias) => addPrefixIfMissing(alias, prefix));
4242
+ return { name, aliases };
4243
+ }
4244
+ function resolveOptionDefinitions(defaults, override) {
4245
+ if (!override) {
4246
+ return defaults;
4247
+ }
4248
+ const appendDefaults = _nullishCoalesce(override.appendDefaultOptions, () => ( true));
4249
+ const customDefs = _nullishCoalesce(override.optionDefs, () => ( []));
4250
+ if (!appendDefaults) {
4251
+ return customDefs;
4252
+ }
4253
+ if (customDefs.length === 0) {
4254
+ return defaults;
4255
+ }
4256
+ return [...defaults, ...customDefs];
4257
+ }
4258
+ function applyCommandOptions(command, optionDefs) {
4259
+ for (const option of optionDefs) {
4260
+ command.option(option.flags, _nullishCoalesce(option.description, () => ( "")), option.config);
4261
+ }
4262
+ }
4263
+ function runWithCommandHandler(cli, command, commandName, args, handler, defaultHandler) {
4264
+ const cwd = resolveCwd(args.cwd);
4265
+ const context = createCommandContext(cli, command, commandName, args, cwd);
4266
+ const runDefault = createDefaultRunner(() => defaultHandler(context));
4267
+ if (!handler) {
4268
+ return runDefault();
4269
+ }
4270
+ return handler(context, runDefault);
4271
+ }
4272
+ function resolveCommandMetadata(command, mountOptions, prefix, defaults) {
4273
+ const names = resolveCommandNames(command, mountOptions, prefix);
4274
+ const definition = defaults[command];
4275
+ const override = _optionalChain([mountOptions, 'access', _150 => _150.commandOptions, 'optionalAccess', _151 => _151[command]]);
4276
+ const description = _nullishCoalesce(_optionalChain([override, 'optionalAccess', _152 => _152.description]), () => ( definition.description));
4277
+ const optionDefs = resolveOptionDefinitions(definition.optionDefs, override);
4278
+ return { ...names, description, optionDefs };
4279
+ }
4280
+ async function installCommandDefaultHandler(ctx) {
4281
+ const patcher = await ctx.createPatcher();
4282
+ await patcher.patch();
4283
+ logger_default.success("Tailwind CSS runtime patched successfully.");
4284
+ }
4285
+ async function extractCommandDefaultHandler(ctx) {
4286
+ const { args } = ctx;
4287
+ const overrides = {};
4288
+ let hasOverrides = false;
4289
+ if (args.output || args.format) {
4290
+ overrides.extract = {
4291
+ ...args.output === void 0 ? {} : { file: args.output },
4292
+ ...args.format === void 0 ? {} : { format: args.format }
4293
+ };
4294
+ hasOverrides = true;
4295
+ }
4296
+ if (args.css) {
4297
+ overrides.tailwindcss = {
4298
+ v4: {
4299
+ cssEntries: [args.css]
4300
+ }
4301
+ };
4302
+ hasOverrides = true;
4303
+ }
4304
+ const patcher = await ctx.createPatcher(hasOverrides ? overrides : void 0);
4305
+ const extractOptions = args.write === void 0 ? {} : { write: args.write };
4306
+ const result = await patcher.extract(extractOptions);
4307
+ if (result.filename) {
4308
+ logger_default.success(`Collected ${result.classList.length} classes \u2192 ${result.filename}`);
4309
+ } else {
4310
+ logger_default.success(`Collected ${result.classList.length} classes.`);
4311
+ }
4312
+ return result;
4313
+ }
4314
+ async function tokensCommandDefaultHandler(ctx) {
4315
+ const { args } = ctx;
4316
+ const patcher = await ctx.createPatcher();
4317
+ const report = await patcher.collectContentTokens();
4318
+ const shouldWrite = _nullishCoalesce(args.write, () => ( true));
4319
+ let format = _nullishCoalesce(args.format, () => ( "json"));
4320
+ if (!TOKEN_FORMATS.includes(format)) {
4321
+ format = "json";
4322
+ }
4323
+ const targetFile = _nullishCoalesce(args.output, () => ( DEFAULT_TOKEN_REPORT));
4324
+ const groupKey = args.groupKey === "absolute" ? "absolute" : "relative";
4325
+ const buildGrouped = () => groupTokensByFile(report, {
4326
+ key: groupKey,
4327
+ stripAbsolutePaths: groupKey !== "absolute"
4328
+ });
4329
+ const grouped = format === "grouped-json" ? buildGrouped() : null;
4330
+ const resolveGrouped = () => _nullishCoalesce(grouped, () => ( buildGrouped()));
4331
+ if (shouldWrite) {
4332
+ const target = _pathe2.default.resolve(targetFile);
4333
+ await _fsextra2.default.ensureDir(_pathe2.default.dirname(target));
4334
+ if (format === "json") {
4335
+ await _fsextra2.default.writeJSON(target, report, { spaces: 2 });
4336
+ } else if (format === "grouped-json") {
4337
+ await _fsextra2.default.writeJSON(target, resolveGrouped(), { spaces: 2 });
4338
+ } else {
4339
+ const lines = report.entries.map(formatTokenLine);
4340
+ await _fsextra2.default.writeFile(target, `${lines.join("\n")}
4341
+ `, "utf8");
4342
+ }
4343
+ logger_default.success(`Collected ${report.entries.length} tokens (${format}) \u2192 ${target.replace(_process2.default.cwd(), ".")}`);
4344
+ } else {
4345
+ logger_default.success(`Collected ${report.entries.length} tokens from ${report.filesScanned} files.`);
4346
+ if (format === "lines") {
4347
+ const preview = report.entries.slice(0, 5).map(formatTokenLine).join("\n");
4348
+ if (preview) {
4349
+ logger_default.log("");
4350
+ logger_default.info(preview);
4351
+ if (report.entries.length > 5) {
4352
+ logger_default.info(`\u2026and ${report.entries.length - 5} more.`);
4353
+ }
4354
+ }
4355
+ } else if (format === "grouped-json") {
4356
+ const map = resolveGrouped();
4357
+ const { preview, moreFiles } = formatGroupedPreview(map);
4358
+ if (preview) {
4359
+ logger_default.log("");
4360
+ logger_default.info(preview);
4361
+ if (moreFiles > 0) {
4362
+ logger_default.info(`\u2026and ${moreFiles} more files.`);
4363
+ }
4364
+ }
4365
+ } else {
4366
+ const previewEntries = report.entries.slice(0, 3);
4367
+ if (previewEntries.length) {
4368
+ logger_default.log("");
4369
+ logger_default.info(JSON.stringify(previewEntries, null, 2));
4370
+ }
4371
+ }
4372
+ }
4373
+ if (report.skippedFiles.length) {
4374
+ logger_default.warn("Skipped files:");
4375
+ for (const skipped of report.skippedFiles) {
4376
+ logger_default.warn(` \u2022 ${skipped.file} (${skipped.reason})`);
4377
+ }
4378
+ }
4379
+ return report;
4380
+ }
4381
+ async function initCommandDefaultHandler(ctx) {
4382
+ await _config.initConfig.call(void 0, ctx.cwd);
4383
+ logger_default.success(`\u2728 ${_config.CONFIG_NAME}.config.ts initialized!`);
4384
+ }
4385
+ async function migrateCommandDefaultHandler(ctx) {
4386
+ const { args } = ctx;
4387
+ const normalizePatternArgs = (value) => {
4388
+ if (!value) {
4389
+ return void 0;
4390
+ }
4391
+ const raw = Array.isArray(value) ? value : [value];
4392
+ const values = raw.flatMap((item) => item.split(",")).map((item) => item.trim()).filter(Boolean);
4393
+ return values.length > 0 ? values : void 0;
4394
+ };
4395
+ const include = normalizePatternArgs(args.include);
4396
+ const exclude = normalizePatternArgs(args.exclude);
4397
+ const parsedMaxDepth = args.maxDepth === void 0 ? void 0 : Number(args.maxDepth);
4398
+ const maxDepth = parsedMaxDepth !== void 0 && Number.isFinite(parsedMaxDepth) && parsedMaxDepth >= 0 ? Math.floor(parsedMaxDepth) : void 0;
4399
+ const checkMode = _nullishCoalesce(args.check, () => ( false));
4400
+ const dryRun = _nullishCoalesce(args.dryRun, () => ( checkMode));
4401
+ if (args.workspace && args.maxDepth !== void 0 && maxDepth === void 0) {
4402
+ logger_default.warn(`Invalid --max-depth value "${String(args.maxDepth)}", fallback to default depth.`);
4403
+ }
4404
+ const report = await migrateConfigFiles({
4405
+ cwd: ctx.cwd,
4406
+ dryRun,
4407
+ ...args.config ? { files: [args.config] } : {},
4408
+ ...args.workspace ? { workspace: true } : {},
4409
+ ...args.workspace && maxDepth !== void 0 ? { maxDepth } : {},
4410
+ ...args.backupDir ? { backupDir: args.backupDir } : {},
4411
+ ...include ? { include } : {},
4412
+ ...exclude ? { exclude } : {}
4413
+ });
4414
+ if (args.reportFile) {
4415
+ const reportPath = _pathe2.default.resolve(ctx.cwd, args.reportFile);
4416
+ await _fsextra2.default.ensureDir(_pathe2.default.dirname(reportPath));
4417
+ await _fsextra2.default.writeJSON(reportPath, report, { spaces: 2 });
4418
+ logger_default.info(`Migration report written: ${reportPath.replace(_process2.default.cwd(), ".")}`);
4419
+ }
4420
+ if (args.json) {
4421
+ logger_default.log(JSON.stringify(report, null, 2));
4422
+ if (checkMode && report.changedFiles > 0) {
4423
+ throw new Error(`Migration check failed: ${report.changedFiles} file(s) still need migration.`);
4424
+ }
4425
+ if (report.scannedFiles === 0) {
4426
+ logger_default.warn("No config files found for migration.");
4427
+ }
4428
+ return report;
4429
+ }
4430
+ if (report.scannedFiles === 0) {
4431
+ logger_default.warn("No config files found for migration.");
4432
+ return report;
4433
+ }
4434
+ for (const entry of report.entries) {
4435
+ const fileLabel = entry.file.replace(_process2.default.cwd(), ".");
4436
+ if (!entry.changed) {
4437
+ logger_default.info(`No changes: ${fileLabel}`);
4438
+ continue;
4439
+ }
4440
+ if (dryRun) {
4441
+ logger_default.info(`[dry-run] ${fileLabel}`);
4442
+ } else {
4443
+ logger_default.success(`Migrated: ${fileLabel}`);
4444
+ }
4445
+ for (const change of entry.changes) {
4446
+ logger_default.info(` - ${change}`);
4447
+ }
4448
+ if (entry.backupFile) {
4449
+ logger_default.info(` - backup: ${entry.backupFile.replace(_process2.default.cwd(), ".")}`);
4450
+ }
4451
+ }
4452
+ logger_default.info(
4453
+ `Migration summary: scanned=${report.scannedFiles}, changed=${report.changedFiles}, written=${report.writtenFiles}, backups=${report.backupsWritten}, missing=${report.missingFiles}, unchanged=${report.unchangedFiles}`
4454
+ );
4455
+ if (checkMode && report.changedFiles > 0) {
4456
+ throw new Error(`Migration check failed: ${report.changedFiles} file(s) still need migration.`);
4457
+ }
4458
+ return report;
4459
+ }
4460
+ async function restoreCommandDefaultHandler(ctx) {
4461
+ const { args } = ctx;
4462
+ const reportFile = _nullishCoalesce(args.reportFile, () => ( ".tw-patch/migrate-report.json"));
4463
+ const result = await restoreConfigFiles({
4464
+ cwd: ctx.cwd,
4465
+ reportFile,
4466
+ dryRun: _nullishCoalesce(args.dryRun, () => ( false)),
4467
+ strict: _nullishCoalesce(args.strict, () => ( false))
4468
+ });
4469
+ if (args.json) {
4470
+ logger_default.log(JSON.stringify(result, null, 2));
4471
+ return result;
4472
+ }
4473
+ logger_default.info(
4474
+ `Restore summary: scanned=${result.scannedEntries}, restorable=${result.restorableEntries}, restored=${result.restoredFiles}, missingBackups=${result.missingBackups}, skipped=${result.skippedEntries}`
4475
+ );
4476
+ if (result.restored.length > 0) {
4477
+ const preview = result.restored.slice(0, 5);
4478
+ for (const file of preview) {
4479
+ logger_default.info(` - ${file.replace(_process2.default.cwd(), ".")}`);
4480
+ }
4481
+ if (result.restored.length > preview.length) {
4482
+ logger_default.info(` ...and ${result.restored.length - preview.length} more`);
4483
+ }
4484
+ }
4485
+ return result;
4486
+ }
4487
+ async function validateCommandDefaultHandler(ctx) {
4488
+ const { args } = ctx;
4489
+ const reportFile = _nullishCoalesce(args.reportFile, () => ( ".tw-patch/migrate-report.json"));
4490
+ try {
4491
+ const result = await restoreConfigFiles({
4492
+ cwd: ctx.cwd,
4493
+ reportFile,
4494
+ dryRun: true,
4495
+ strict: _nullishCoalesce(args.strict, () => ( false))
4496
+ });
4497
+ if (args.json) {
4498
+ const payload = {
4499
+ ok: true,
4500
+ ...result
4501
+ };
4502
+ logger_default.log(JSON.stringify(payload, null, 2));
4503
+ return result;
4504
+ }
4505
+ logger_default.success(
4506
+ `Migration report validated: scanned=${result.scannedEntries}, restorable=${result.restorableEntries}, missingBackups=${result.missingBackups}, skipped=${result.skippedEntries}`
4507
+ );
4508
+ if (result.reportKind || result.reportSchemaVersion !== void 0) {
4509
+ const kind = _nullishCoalesce(result.reportKind, () => ( "unknown"));
4510
+ const schema = result.reportSchemaVersion === void 0 ? "unknown" : String(result.reportSchemaVersion);
4511
+ logger_default.info(` metadata: kind=${kind}, schema=${schema}`);
4512
+ }
4513
+ return result;
4514
+ } catch (error) {
4515
+ const summary = classifyValidateError(error);
4516
+ if (args.json) {
4517
+ const payload = {
4518
+ ok: false,
4519
+ reason: summary.reason,
4520
+ exitCode: summary.exitCode,
4521
+ message: summary.message
4522
+ };
4523
+ logger_default.log(JSON.stringify(payload, null, 2));
4524
+ } else {
4525
+ logger_default.error(`Validation failed [${summary.reason}] (exit ${summary.exitCode}): ${summary.message}`);
4526
+ }
4527
+ throw new ValidateCommandError(summary, { cause: error });
4528
+ }
4529
+ }
4530
+ function formatFilesHint(entry) {
4531
+ if (!entry.files.length) {
4532
+ return "";
4533
+ }
4534
+ return ` (${entry.files.join(", ")})`;
4535
+ }
4536
+ async function statusCommandDefaultHandler(ctx) {
4537
+ const patcher = await ctx.createPatcher();
4538
+ const report = await patcher.getPatchStatus();
4539
+ if (ctx.args.json) {
4540
+ logger_default.log(JSON.stringify(report, null, 2));
4541
+ return report;
4542
+ }
4543
+ const applied = report.entries.filter((entry) => entry.status === "applied");
4544
+ const pending = report.entries.filter((entry) => entry.status === "not-applied");
4545
+ const skipped = report.entries.filter((entry) => entry.status === "skipped" || entry.status === "unsupported");
4546
+ const packageLabel = `${_nullishCoalesce(report.package.name, () => ( "tailwindcss"))}@${_nullishCoalesce(report.package.version, () => ( "unknown"))}`;
4547
+ logger_default.info(`Patch status for ${packageLabel} (v${report.majorVersion})`);
4548
+ if (applied.length) {
4549
+ logger_default.success("Applied:");
4550
+ applied.forEach((entry) => logger_default.success(` \u2022 ${entry.name}${formatFilesHint(entry)}`));
4551
+ }
4552
+ if (pending.length) {
4553
+ logger_default.warn("Needs attention:");
4554
+ pending.forEach((entry) => {
4555
+ const details = entry.reason ? ` \u2013 ${entry.reason}` : "";
4556
+ logger_default.warn(` \u2022 ${entry.name}${formatFilesHint(entry)}${details}`);
4557
+ });
4558
+ } else {
4559
+ logger_default.success("All applicable patches are applied.");
4560
+ }
4561
+ if (skipped.length) {
4562
+ logger_default.info("Skipped:");
4563
+ skipped.forEach((entry) => {
4564
+ const details = entry.reason ? ` \u2013 ${entry.reason}` : "";
4565
+ logger_default.info(` \u2022 ${entry.name}${details}`);
4566
+ });
4567
+ }
4568
+ return report;
4569
+ }
4570
+ function mountTailwindcssPatchCommands(cli, options = {}) {
4571
+ const prefix = _nullishCoalesce(options.commandPrefix, () => ( ""));
4572
+ const selectedCommands = _nullishCoalesce(options.commands, () => ( tailwindcssPatchCommands));
4573
+ const defaultDefinitions = buildDefaultCommandDefinitions();
4574
+ const registrars = {
4575
+ install: () => {
4576
+ const metadata = resolveCommandMetadata("install", options, prefix, defaultDefinitions);
4577
+ const command = cli.command(metadata.name, metadata.description);
4578
+ applyCommandOptions(command, metadata.optionDefs);
4579
+ command.action(async (args) => {
4580
+ return runWithCommandHandler(
4581
+ cli,
4582
+ command,
4583
+ "install",
4584
+ args,
4585
+ _optionalChain([options, 'access', _153 => _153.commandHandlers, 'optionalAccess', _154 => _154.install]),
4586
+ installCommandDefaultHandler
4587
+ );
4588
+ });
4589
+ metadata.aliases.forEach((alias) => command.alias(alias));
4590
+ },
4591
+ extract: () => {
4592
+ const metadata = resolveCommandMetadata("extract", options, prefix, defaultDefinitions);
4593
+ const command = cli.command(metadata.name, metadata.description);
4594
+ applyCommandOptions(command, metadata.optionDefs);
4595
+ command.action(async (args) => {
4596
+ return runWithCommandHandler(
4597
+ cli,
4598
+ command,
4599
+ "extract",
4600
+ args,
4601
+ _optionalChain([options, 'access', _155 => _155.commandHandlers, 'optionalAccess', _156 => _156.extract]),
4602
+ extractCommandDefaultHandler
4603
+ );
4604
+ });
4605
+ metadata.aliases.forEach((alias) => command.alias(alias));
4606
+ },
4607
+ tokens: () => {
4608
+ const metadata = resolveCommandMetadata("tokens", options, prefix, defaultDefinitions);
4609
+ const command = cli.command(metadata.name, metadata.description);
4610
+ applyCommandOptions(command, metadata.optionDefs);
4611
+ command.action(async (args) => {
4612
+ return runWithCommandHandler(
4613
+ cli,
4614
+ command,
4615
+ "tokens",
4616
+ args,
4617
+ _optionalChain([options, 'access', _157 => _157.commandHandlers, 'optionalAccess', _158 => _158.tokens]),
4618
+ tokensCommandDefaultHandler
4619
+ );
4620
+ });
4621
+ metadata.aliases.forEach((alias) => command.alias(alias));
4622
+ },
4623
+ init: () => {
4624
+ const metadata = resolveCommandMetadata("init", options, prefix, defaultDefinitions);
4625
+ const command = cli.command(metadata.name, metadata.description);
4626
+ applyCommandOptions(command, metadata.optionDefs);
4627
+ command.action(async (args) => {
4628
+ return runWithCommandHandler(
4629
+ cli,
4630
+ command,
4631
+ "init",
4632
+ args,
4633
+ _optionalChain([options, 'access', _159 => _159.commandHandlers, 'optionalAccess', _160 => _160.init]),
4634
+ initCommandDefaultHandler
4635
+ );
4636
+ });
4637
+ metadata.aliases.forEach((alias) => command.alias(alias));
4638
+ },
4639
+ migrate: () => {
4640
+ const metadata = resolveCommandMetadata("migrate", options, prefix, defaultDefinitions);
4641
+ const command = cli.command(metadata.name, metadata.description);
4642
+ applyCommandOptions(command, metadata.optionDefs);
4643
+ command.action(async (args) => {
4644
+ return runWithCommandHandler(
4645
+ cli,
4646
+ command,
4647
+ "migrate",
4648
+ args,
4649
+ _optionalChain([options, 'access', _161 => _161.commandHandlers, 'optionalAccess', _162 => _162.migrate]),
4650
+ migrateCommandDefaultHandler
4651
+ );
4652
+ });
4653
+ metadata.aliases.forEach((alias) => command.alias(alias));
4654
+ },
4655
+ restore: () => {
4656
+ const metadata = resolveCommandMetadata("restore", options, prefix, defaultDefinitions);
4657
+ const command = cli.command(metadata.name, metadata.description);
4658
+ applyCommandOptions(command, metadata.optionDefs);
4659
+ command.action(async (args) => {
4660
+ return runWithCommandHandler(
4661
+ cli,
4662
+ command,
4663
+ "restore",
4664
+ args,
4665
+ _optionalChain([options, 'access', _163 => _163.commandHandlers, 'optionalAccess', _164 => _164.restore]),
4666
+ restoreCommandDefaultHandler
4667
+ );
4668
+ });
4669
+ metadata.aliases.forEach((alias) => command.alias(alias));
4670
+ },
4671
+ validate: () => {
4672
+ const metadata = resolveCommandMetadata("validate", options, prefix, defaultDefinitions);
4673
+ const command = cli.command(metadata.name, metadata.description);
4674
+ applyCommandOptions(command, metadata.optionDefs);
4675
+ command.action(async (args) => {
4676
+ return runWithCommandHandler(
4677
+ cli,
4678
+ command,
4679
+ "validate",
4680
+ args,
4681
+ _optionalChain([options, 'access', _165 => _165.commandHandlers, 'optionalAccess', _166 => _166.validate]),
4682
+ validateCommandDefaultHandler
4683
+ );
4684
+ });
4685
+ metadata.aliases.forEach((alias) => command.alias(alias));
4686
+ },
4687
+ status: () => {
4688
+ const metadata = resolveCommandMetadata("status", options, prefix, defaultDefinitions);
4689
+ const command = cli.command(metadata.name, metadata.description);
4690
+ applyCommandOptions(command, metadata.optionDefs);
4691
+ command.action(async (args) => {
4692
+ return runWithCommandHandler(
4693
+ cli,
4694
+ command,
4695
+ "status",
4696
+ args,
4697
+ _optionalChain([options, 'access', _167 => _167.commandHandlers, 'optionalAccess', _168 => _168.status]),
4698
+ statusCommandDefaultHandler
4699
+ );
4700
+ });
4701
+ metadata.aliases.forEach((alias) => command.alias(alias));
4702
+ }
4703
+ };
4704
+ for (const name of selectedCommands) {
4705
+ const register = registrars[name];
4706
+ if (register) {
4707
+ register();
4708
+ }
4709
+ }
4710
+ return cli;
4711
+ }
4712
+ function createTailwindcssPatchCli(options = {}) {
4713
+ const cli = _cac2.default.call(void 0, _nullishCoalesce(options.name, () => ( "tw-patch")));
4714
+ mountTailwindcssPatchCommands(cli, options.mountOptions);
4715
+ return cli;
4716
+ }
4717
+
4718
+
4719
+
4720
+
4721
+
4722
+
4723
+
4724
+
4725
+
4726
+
4727
+
4728
+
4729
+
4730
+
4731
+
4732
+
4733
+
4734
+
4735
+
4736
+
4737
+
4738
+
4739
+
4740
+
4741
+
4742
+
4743
+ exports.logger_default = logger_default; exports.CacheStore = CacheStore; exports.extractRawCandidatesWithPositions = extractRawCandidatesWithPositions; exports.extractRawCandidates = extractRawCandidates; exports.extractValidCandidates = extractValidCandidates; exports.extractProjectCandidatesWithPositions = extractProjectCandidatesWithPositions; exports.groupTokensByFile = groupTokensByFile; exports.normalizeOptions = normalizeOptions; exports.getPatchStatusReport = getPatchStatusReport; exports.collectClassesFromContexts = collectClassesFromContexts; exports.collectClassesFromTailwindV4 = collectClassesFromTailwindV4; exports.loadRuntimeContexts = loadRuntimeContexts; exports.runTailwindBuild = runTailwindBuild; exports.TailwindcssPatcher = TailwindcssPatcher; exports.MIGRATION_REPORT_KIND = MIGRATION_REPORT_KIND; exports.MIGRATION_REPORT_SCHEMA_VERSION = MIGRATION_REPORT_SCHEMA_VERSION; exports.migrateConfigFiles = migrateConfigFiles; exports.restoreConfigFiles = restoreConfigFiles; exports.tailwindcssPatchCommands = tailwindcssPatchCommands; exports.VALIDATE_EXIT_CODES = VALIDATE_EXIT_CODES; exports.VALIDATE_FAILURE_REASONS = VALIDATE_FAILURE_REASONS; exports.ValidateCommandError = ValidateCommandError; exports.mountTailwindcssPatchCommands = mountTailwindcssPatchCommands; exports.createTailwindcssPatchCli = createTailwindcssPatchCli;