tailwindcss-patch 7.1.5 → 8.0.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,1316 @@
1
+ // src/logger.ts
2
+ import { createConsola } from "consola";
3
+ var logger = createConsola();
4
+ var logger_default = logger;
5
+
6
+ // src/cache/store.ts
7
+ import fs from "fs-extra";
8
+ var CacheStore = class {
9
+ constructor(options) {
10
+ this.options = options;
11
+ }
12
+ async ensureDir() {
13
+ await fs.ensureDir(this.options.dir);
14
+ }
15
+ async write(data) {
16
+ if (!this.options.enabled) {
17
+ return void 0;
18
+ }
19
+ try {
20
+ await this.ensureDir();
21
+ await fs.writeJSON(this.options.path, Array.from(data));
22
+ return this.options.path;
23
+ } catch (error) {
24
+ logger_default.error("Unable to persist Tailwind class cache", error);
25
+ return void 0;
26
+ }
27
+ }
28
+ async read() {
29
+ if (!this.options.enabled) {
30
+ return /* @__PURE__ */ new Set();
31
+ }
32
+ try {
33
+ const exists = await fs.pathExists(this.options.path);
34
+ if (!exists) {
35
+ return /* @__PURE__ */ new Set();
36
+ }
37
+ const data = await fs.readJSON(this.options.path);
38
+ if (Array.isArray(data)) {
39
+ return new Set(data.filter((item) => typeof item === "string"));
40
+ }
41
+ } catch (error) {
42
+ logger_default.warn("Unable to read Tailwind class cache, removing invalid file.", error);
43
+ try {
44
+ await fs.remove(this.options.path);
45
+ } catch (cleanupError) {
46
+ logger_default.error("Failed to clean up invalid cache file", cleanupError);
47
+ }
48
+ }
49
+ return /* @__PURE__ */ new Set();
50
+ }
51
+ };
52
+
53
+ // src/extraction/candidate-extractor.ts
54
+ import process from "process";
55
+ async function importNode() {
56
+ return import("@tailwindcss/node");
57
+ }
58
+ async function importOxide() {
59
+ return import("@tailwindcss/oxide");
60
+ }
61
+ async function extractRawCandidatesWithPositions(content, extension = "html") {
62
+ const { Scanner } = await importOxide();
63
+ const scanner = new Scanner({});
64
+ const result = scanner.getCandidatesWithPositions({ content, extension });
65
+ return result.map(({ candidate, position }) => ({
66
+ rawCandidate: candidate,
67
+ start: position,
68
+ end: position + candidate.length
69
+ }));
70
+ }
71
+ async function extractRawCandidates(sources) {
72
+ const { Scanner } = await importOxide();
73
+ const scanner = new Scanner({
74
+ sources
75
+ });
76
+ return scanner.scan();
77
+ }
78
+ async function extractValidCandidates(options) {
79
+ const providedOptions = options ?? {};
80
+ const defaultCwd = providedOptions.cwd ?? process.cwd();
81
+ const base = providedOptions.base ?? defaultCwd;
82
+ const css = providedOptions.css ?? '@import "tailwindcss";';
83
+ const sources = (providedOptions.sources ?? [
84
+ {
85
+ base: defaultCwd,
86
+ pattern: "**/*",
87
+ negated: false
88
+ }
89
+ ]).map((source) => ({
90
+ base: source.base ?? defaultCwd,
91
+ pattern: source.pattern,
92
+ negated: source.negated
93
+ }));
94
+ const { __unstable__loadDesignSystem } = await importNode();
95
+ const designSystem = await __unstable__loadDesignSystem(css, { base });
96
+ const candidates = await extractRawCandidates(sources);
97
+ const validCandidates = candidates.filter(
98
+ (rawCandidate) => designSystem.parseCandidate(rawCandidate).length > 0
99
+ );
100
+ return validCandidates;
101
+ }
102
+
103
+ // src/options/legacy.ts
104
+ function normalizeLegacyFeatures(patch) {
105
+ const apply = patch?.applyPatches;
106
+ const extend = apply?.extendLengthUnits;
107
+ let extendOption = false;
108
+ if (extend && typeof extend === "object") {
109
+ extendOption = {
110
+ ...extend,
111
+ enabled: true
112
+ };
113
+ } else if (extend === true) {
114
+ extendOption = {
115
+ enabled: true,
116
+ units: ["rpx"],
117
+ overwrite: patch?.overwrite
118
+ };
119
+ }
120
+ return {
121
+ exposeContext: apply?.exportContext ?? true,
122
+ extendLengthUnits: extendOption
123
+ };
124
+ }
125
+ function fromLegacyOptions(options) {
126
+ if (!options) {
127
+ return {};
128
+ }
129
+ const patch = options.patch;
130
+ const features = normalizeLegacyFeatures(patch);
131
+ const output = patch?.output;
132
+ const tailwindConfig = patch?.tailwindcss;
133
+ const tailwindVersion = tailwindConfig?.version;
134
+ const tailwindV2 = tailwindConfig?.v2;
135
+ const tailwindV3 = tailwindConfig?.v3;
136
+ const tailwindV4 = tailwindConfig?.v4;
137
+ const tailwindConfigPath = tailwindV3?.config ?? tailwindV2?.config;
138
+ const tailwindCwd = tailwindV3?.cwd ?? tailwindV2?.cwd ?? patch?.cwd;
139
+ return {
140
+ cwd: patch?.cwd,
141
+ overwrite: patch?.overwrite,
142
+ filter: patch?.filter,
143
+ cache: typeof options.cache === "boolean" ? options.cache : options.cache ? {
144
+ ...options.cache,
145
+ enabled: options.cache.enabled ?? true
146
+ } : void 0,
147
+ output: output ? {
148
+ file: output.filename,
149
+ pretty: output.loose ? 2 : false,
150
+ removeUniversalSelector: output.removeUniversalSelector
151
+ } : void 0,
152
+ tailwind: {
153
+ packageName: patch?.packageName,
154
+ version: tailwindVersion,
155
+ resolve: patch?.resolve,
156
+ config: tailwindConfigPath,
157
+ cwd: tailwindCwd,
158
+ v2: tailwindV2,
159
+ v3: tailwindV3,
160
+ v4: tailwindV4
161
+ },
162
+ features: {
163
+ exposeContext: features.exposeContext,
164
+ extendLengthUnits: features.extendLengthUnits
165
+ }
166
+ };
167
+ }
168
+ function fromUnifiedConfig(registry) {
169
+ if (!registry) {
170
+ return {};
171
+ }
172
+ const tailwind = registry.tailwind;
173
+ const output = registry.output;
174
+ const pretty = (() => {
175
+ if (output?.pretty === void 0) {
176
+ return void 0;
177
+ }
178
+ if (typeof output.pretty === "boolean") {
179
+ return output.pretty ? 2 : false;
180
+ }
181
+ return output.pretty;
182
+ })();
183
+ return {
184
+ output: output ? {
185
+ file: output.file,
186
+ pretty,
187
+ removeUniversalSelector: output.stripUniversalSelector
188
+ } : void 0,
189
+ tailwind: tailwind ? {
190
+ version: tailwind.version,
191
+ packageName: tailwind.package,
192
+ resolve: tailwind.resolve,
193
+ config: tailwind.config,
194
+ cwd: tailwind.cwd,
195
+ v2: tailwind.legacy,
196
+ v3: tailwind.classic,
197
+ v4: tailwind.next
198
+ } : void 0
199
+ };
200
+ }
201
+
202
+ // src/options/normalize.ts
203
+ import process2 from "process";
204
+ import path from "pathe";
205
+
206
+ // src/constants.ts
207
+ var pkgName = "tailwindcss-patch";
208
+
209
+ // src/options/normalize.ts
210
+ function toPrettyValue(value) {
211
+ if (typeof value === "number") {
212
+ return value > 0 ? value : false;
213
+ }
214
+ if (value === true) {
215
+ return 2;
216
+ }
217
+ return false;
218
+ }
219
+ function normalizeCacheOptions(cache, projectRoot) {
220
+ let enabled = false;
221
+ let cwd = projectRoot;
222
+ let dir = path.resolve(cwd, "node_modules/.cache", pkgName);
223
+ let file = "class-cache.json";
224
+ let strategy = "merge";
225
+ if (typeof cache === "boolean") {
226
+ enabled = cache;
227
+ } else if (typeof cache === "object" && cache) {
228
+ enabled = cache.enabled ?? true;
229
+ cwd = cache.cwd ?? cwd;
230
+ dir = cache.dir ? path.resolve(cache.dir) : path.resolve(cwd, "node_modules/.cache", pkgName);
231
+ file = cache.file ?? file;
232
+ strategy = cache.strategy ?? strategy;
233
+ }
234
+ const filename = path.resolve(dir, file);
235
+ return {
236
+ enabled,
237
+ cwd,
238
+ dir,
239
+ file,
240
+ path: filename,
241
+ strategy
242
+ };
243
+ }
244
+ function normalizeOutputOptions(output) {
245
+ const enabled = output?.enabled ?? true;
246
+ const file = output?.file ?? ".tw-patch/tw-class-list.json";
247
+ const format = output?.format ?? "json";
248
+ const pretty = toPrettyValue(output?.pretty ?? true);
249
+ const removeUniversalSelector = output?.removeUniversalSelector ?? true;
250
+ return {
251
+ enabled,
252
+ file,
253
+ format,
254
+ pretty,
255
+ removeUniversalSelector
256
+ };
257
+ }
258
+ function normalizeExposeContextOptions(features) {
259
+ if (features?.exposeContext === false) {
260
+ return {
261
+ enabled: false,
262
+ refProperty: "contextRef"
263
+ };
264
+ }
265
+ if (typeof features?.exposeContext === "object" && features.exposeContext) {
266
+ return {
267
+ enabled: true,
268
+ refProperty: features.exposeContext.refProperty ?? "contextRef"
269
+ };
270
+ }
271
+ return {
272
+ enabled: true,
273
+ refProperty: "contextRef"
274
+ };
275
+ }
276
+ function normalizeExtendLengthUnitsOptions(features) {
277
+ const extend = features?.extendLengthUnits;
278
+ if (extend === false || extend === void 0) {
279
+ return null;
280
+ }
281
+ if (extend.enabled === false) {
282
+ return null;
283
+ }
284
+ const base = {
285
+ units: ["rpx"],
286
+ overwrite: true
287
+ };
288
+ return {
289
+ ...base,
290
+ ...extend,
291
+ enabled: extend.enabled ?? true,
292
+ units: extend.units ?? base.units,
293
+ overwrite: extend.overwrite ?? base.overwrite
294
+ };
295
+ }
296
+ function normalizeTailwindV4Options(v4, fallbackBase) {
297
+ const base = v4?.base ? path.resolve(v4.base) : fallbackBase;
298
+ const cssEntries = Array.isArray(v4?.cssEntries) ? v4.cssEntries.filter((entry) => Boolean(entry)).map((entry) => path.resolve(entry)) : [];
299
+ const sources = v4?.sources?.length ? v4.sources : [
300
+ {
301
+ base,
302
+ pattern: "**/*",
303
+ negated: false
304
+ }
305
+ ];
306
+ return {
307
+ base,
308
+ css: v4?.css,
309
+ cssEntries,
310
+ sources
311
+ };
312
+ }
313
+ function normalizeTailwindOptions(tailwind, projectRoot) {
314
+ const packageName = tailwind?.packageName ?? "tailwindcss";
315
+ const versionHint = tailwind?.version;
316
+ const resolve = tailwind?.resolve;
317
+ const cwd = tailwind?.cwd ?? projectRoot;
318
+ const config = tailwind?.config;
319
+ const postcssPlugin = tailwind?.postcssPlugin;
320
+ const v4 = normalizeTailwindV4Options(tailwind?.v4, cwd);
321
+ return {
322
+ packageName,
323
+ versionHint,
324
+ resolve,
325
+ cwd,
326
+ config,
327
+ postcssPlugin,
328
+ v2: tailwind?.v2,
329
+ v3: tailwind?.v3,
330
+ v4
331
+ };
332
+ }
333
+ function normalizeOptions(options = {}) {
334
+ const projectRoot = options.cwd ? path.resolve(options.cwd) : process2.cwd();
335
+ const overwrite = options.overwrite ?? true;
336
+ const output = normalizeOutputOptions(options.output);
337
+ const cache = normalizeCacheOptions(options.cache, projectRoot);
338
+ const tailwind = normalizeTailwindOptions(options.tailwind, projectRoot);
339
+ const exposeContext = normalizeExposeContextOptions(options.features);
340
+ const extendLengthUnits = normalizeExtendLengthUnitsOptions(options.features);
341
+ const filter = (className) => {
342
+ if (output.removeUniversalSelector && className === "*") {
343
+ return false;
344
+ }
345
+ if (typeof options.filter === "function") {
346
+ return options.filter(className) !== false;
347
+ }
348
+ return true;
349
+ };
350
+ return {
351
+ projectRoot,
352
+ overwrite,
353
+ tailwind,
354
+ features: {
355
+ exposeContext,
356
+ extendLengthUnits
357
+ },
358
+ output,
359
+ cache,
360
+ filter
361
+ };
362
+ }
363
+
364
+ // src/runtime/class-collector.ts
365
+ import process3 from "process";
366
+ import fs2 from "fs-extra";
367
+ import path2 from "pathe";
368
+
369
+ // src/utils.ts
370
+ function isObject(val) {
371
+ return val !== null && typeof val === "object" && Array.isArray(val) === false;
372
+ }
373
+ function spliceChangesIntoString(str, changes) {
374
+ if (!changes[0]) {
375
+ return str;
376
+ }
377
+ changes.sort((a, b) => {
378
+ return a.end - b.end || a.start - b.start;
379
+ });
380
+ let result = "";
381
+ let previous = changes[0];
382
+ result += str.slice(0, previous.start);
383
+ result += previous.replacement;
384
+ for (let i = 1; i < changes.length; ++i) {
385
+ const change = changes[i];
386
+ result += str.slice(previous.end, change.start);
387
+ result += change.replacement;
388
+ previous = change;
389
+ }
390
+ result += str.slice(previous.end);
391
+ return result;
392
+ }
393
+
394
+ // src/runtime/class-collector.ts
395
+ function collectClassesFromContexts(contexts, filter) {
396
+ const set = /* @__PURE__ */ new Set();
397
+ for (const context of contexts) {
398
+ if (!isObject(context) || !context.classCache) {
399
+ continue;
400
+ }
401
+ for (const key of context.classCache.keys()) {
402
+ const className = key.toString();
403
+ if (filter(className)) {
404
+ set.add(className);
405
+ }
406
+ }
407
+ }
408
+ return set;
409
+ }
410
+ async function collectClassesFromTailwindV4(options) {
411
+ const set = /* @__PURE__ */ new Set();
412
+ const v4Options = options.tailwind.v4;
413
+ if (!v4Options) {
414
+ return set;
415
+ }
416
+ const sources = v4Options.sources?.map((source) => {
417
+ return {
418
+ base: source.base ?? v4Options.base ?? process3.cwd(),
419
+ pattern: source.pattern,
420
+ negated: source.negated
421
+ };
422
+ });
423
+ if (v4Options.cssEntries.length > 0) {
424
+ for (const entry of v4Options.cssEntries) {
425
+ const filePath = path2.isAbsolute(entry) ? entry : path2.resolve(options.projectRoot, entry);
426
+ if (!await fs2.pathExists(filePath)) {
427
+ continue;
428
+ }
429
+ const css = await fs2.readFile(filePath, "utf8");
430
+ const candidates = await extractValidCandidates({
431
+ cwd: options.projectRoot,
432
+ base: v4Options.base,
433
+ css,
434
+ sources
435
+ });
436
+ for (const candidate of candidates) {
437
+ if (options.filter(candidate)) {
438
+ set.add(candidate);
439
+ }
440
+ }
441
+ }
442
+ } else {
443
+ const candidates = await extractValidCandidates({
444
+ cwd: options.projectRoot,
445
+ base: v4Options.base,
446
+ css: v4Options.css,
447
+ sources
448
+ });
449
+ for (const candidate of candidates) {
450
+ if (options.filter(candidate)) {
451
+ set.add(candidate);
452
+ }
453
+ }
454
+ }
455
+ return set;
456
+ }
457
+
458
+ // src/runtime/context-registry.ts
459
+ import { createRequire } from "module";
460
+ import fs3 from "fs-extra";
461
+ import path3 from "pathe";
462
+ var require2 = createRequire(import.meta.url);
463
+ function resolveRuntimeEntry(packageInfo, majorVersion) {
464
+ const root = packageInfo.rootPath;
465
+ if (majorVersion === 2) {
466
+ const jitIndex = path3.join(root, "lib/jit/index.js");
467
+ if (fs3.existsSync(jitIndex)) {
468
+ return jitIndex;
469
+ }
470
+ } else if (majorVersion === 3) {
471
+ const plugin = path3.join(root, "lib/plugin.js");
472
+ const index = path3.join(root, "lib/index.js");
473
+ if (fs3.existsSync(plugin)) {
474
+ return plugin;
475
+ }
476
+ if (fs3.existsSync(index)) {
477
+ return index;
478
+ }
479
+ }
480
+ return void 0;
481
+ }
482
+ function loadRuntimeContexts(packageInfo, majorVersion, refProperty) {
483
+ if (majorVersion === 4) {
484
+ return [];
485
+ }
486
+ const entry = resolveRuntimeEntry(packageInfo, majorVersion);
487
+ if (!entry) {
488
+ return [];
489
+ }
490
+ const moduleExports = require2(entry);
491
+ if (!moduleExports) {
492
+ return [];
493
+ }
494
+ const ref = moduleExports[refProperty];
495
+ if (!ref) {
496
+ return [];
497
+ }
498
+ if (Array.isArray(ref)) {
499
+ return ref;
500
+ }
501
+ if (typeof ref === "object" && Array.isArray(ref.value)) {
502
+ return ref.value;
503
+ }
504
+ return [];
505
+ }
506
+
507
+ // src/runtime/process-tailwindcss.ts
508
+ import { createRequire as createRequire2 } from "module";
509
+ import path4 from "pathe";
510
+ import postcss from "postcss";
511
+ import { loadConfig } from "tailwindcss-config";
512
+ var require3 = createRequire2(import.meta.url);
513
+ async function resolveConfigPath(options) {
514
+ if (options.config && path4.isAbsolute(options.config)) {
515
+ return options.config;
516
+ }
517
+ const result = await loadConfig({ cwd: options.cwd });
518
+ if (!result) {
519
+ throw new Error(`Unable to locate Tailwind CSS config from ${options.cwd}`);
520
+ }
521
+ return result.filepath;
522
+ }
523
+ async function runTailwindBuild(options) {
524
+ const configPath = await resolveConfigPath(options);
525
+ const pluginName = options.postcssPlugin ?? (options.majorVersion === 4 ? "@tailwindcss/postcss" : "tailwindcss");
526
+ if (options.majorVersion === 4) {
527
+ return postcss([
528
+ require3(pluginName)({
529
+ config: configPath
530
+ })
531
+ ]).process("@import 'tailwindcss';", {
532
+ from: void 0
533
+ });
534
+ }
535
+ return postcss([
536
+ require3(pluginName)({
537
+ config: configPath
538
+ })
539
+ ]).process("@tailwind base;@tailwind components;@tailwind utilities;", {
540
+ from: void 0
541
+ });
542
+ }
543
+
544
+ // src/api/tailwindcss-patcher.ts
545
+ import process4 from "process";
546
+ import fs6 from "fs-extra";
547
+ import { getPackageInfoSync } from "local-pkg";
548
+ import path7 from "pathe";
549
+ import { coerce } from "semver";
550
+
551
+ // src/patching/operations/export-context/index.ts
552
+ import fs4 from "fs-extra";
553
+ import path5 from "pathe";
554
+
555
+ // src/patching/operations/export-context/postcss-v2.ts
556
+ import * as t from "@babel/types";
557
+
558
+ // src/babel/index.ts
559
+ import _babelGenerate from "@babel/generator";
560
+ import _babelTraverse from "@babel/traverse";
561
+ import { parse, parseExpression } from "@babel/parser";
562
+ function _interopDefaultCompat(e) {
563
+ return e && typeof e === "object" && "default" in e ? e.default : e;
564
+ }
565
+ var generate = _interopDefaultCompat(_babelGenerate);
566
+ var traverse = _interopDefaultCompat(_babelTraverse);
567
+
568
+ // src/patching/operations/export-context/postcss-v2.ts
569
+ var IDENTIFIER_RE = /^[A-Z_$][\w$]*$/i;
570
+ function toIdentifierName(property) {
571
+ if (!property) {
572
+ return "contextRef";
573
+ }
574
+ const sanitized = property.replace(/[^\w$]/gu, "_");
575
+ if (/^\d/.test(sanitized)) {
576
+ return `_${sanitized}`;
577
+ }
578
+ return sanitized || "contextRef";
579
+ }
580
+ function createExportsMember(property) {
581
+ if (IDENTIFIER_RE.test(property)) {
582
+ return t.memberExpression(t.identifier("exports"), t.identifier(property));
583
+ }
584
+ return t.memberExpression(t.identifier("exports"), t.stringLiteral(property), true);
585
+ }
586
+ function transformProcessTailwindFeaturesReturnContextV2(content) {
587
+ const ast = parse(content, {
588
+ sourceType: "unambiguous"
589
+ });
590
+ let hasPatched = false;
591
+ traverse(ast, {
592
+ FunctionDeclaration(path8) {
593
+ const node = path8.node;
594
+ if (node.id?.name !== "processTailwindFeatures" || node.body.body.length !== 1 || !t.isReturnStatement(node.body.body[0])) {
595
+ return;
596
+ }
597
+ const returnStatement3 = node.body.body[0];
598
+ if (!t.isFunctionExpression(returnStatement3.argument)) {
599
+ return;
600
+ }
601
+ const body = returnStatement3.argument.body.body;
602
+ const lastStatement = body[body.length - 1];
603
+ const alreadyReturnsContext = Boolean(
604
+ t.isReturnStatement(lastStatement) && t.isIdentifier(lastStatement.argument) && lastStatement.argument.name === "context"
605
+ );
606
+ hasPatched = alreadyReturnsContext;
607
+ if (!alreadyReturnsContext) {
608
+ body.push(t.returnStatement(t.identifier("context")));
609
+ }
610
+ }
611
+ });
612
+ return {
613
+ code: hasPatched ? content : generate(ast).code,
614
+ hasPatched
615
+ };
616
+ }
617
+ function transformPostcssPluginV2(content, options) {
618
+ const refIdentifier = t.identifier(toIdentifierName(options.refProperty));
619
+ const exportMember = createExportsMember(options.refProperty);
620
+ const valueMember = t.memberExpression(refIdentifier, t.identifier("value"));
621
+ const ast = parse(content);
622
+ let hasPatched = false;
623
+ traverse(ast, {
624
+ Program(path8) {
625
+ const program = path8.node;
626
+ const index = program.body.findIndex((statement) => {
627
+ return t.isFunctionDeclaration(statement) && statement.id?.name === "_default";
628
+ });
629
+ if (index === -1) {
630
+ return;
631
+ }
632
+ const previous = program.body[index - 1];
633
+ const beforePrevious = program.body[index - 2];
634
+ const alreadyHasVariable = Boolean(
635
+ previous && t.isVariableDeclaration(previous) && previous.declarations.length === 1 && t.isIdentifier(previous.declarations[0].id) && previous.declarations[0].id.name === refIdentifier.name
636
+ );
637
+ const alreadyAssignsExports = Boolean(
638
+ 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
639
+ );
640
+ hasPatched = alreadyHasVariable && alreadyAssignsExports;
641
+ if (!alreadyHasVariable) {
642
+ program.body.splice(
643
+ index,
644
+ 0,
645
+ t.variableDeclaration("var", [
646
+ t.variableDeclarator(
647
+ refIdentifier,
648
+ t.objectExpression([
649
+ t.objectProperty(t.identifier("value"), t.arrayExpression())
650
+ ])
651
+ )
652
+ ]),
653
+ t.expressionStatement(
654
+ t.assignmentExpression("=", exportMember, refIdentifier)
655
+ )
656
+ );
657
+ }
658
+ },
659
+ FunctionDeclaration(path8) {
660
+ if (hasPatched) {
661
+ return;
662
+ }
663
+ const fn = path8.node;
664
+ if (fn.id?.name !== "_default") {
665
+ return;
666
+ }
667
+ if (fn.body.body.length !== 1 || !t.isReturnStatement(fn.body.body[0])) {
668
+ return;
669
+ }
670
+ const returnStatement3 = fn.body.body[0];
671
+ if (!t.isCallExpression(returnStatement3.argument) || !t.isMemberExpression(returnStatement3.argument.callee) || !t.isArrayExpression(returnStatement3.argument.callee.object)) {
672
+ return;
673
+ }
674
+ const fnExpression = returnStatement3.argument.callee.object.elements[1];
675
+ if (!fnExpression || !t.isFunctionExpression(fnExpression)) {
676
+ return;
677
+ }
678
+ const block = fnExpression.body;
679
+ const statements = block.body;
680
+ if (t.isExpressionStatement(statements[0]) && t.isAssignmentExpression(statements[0].expression) && t.isNumericLiteral(statements[0].expression.right)) {
681
+ hasPatched = true;
682
+ return;
683
+ }
684
+ const lastStatement = statements[statements.length - 1];
685
+ if (lastStatement && t.isExpressionStatement(lastStatement)) {
686
+ statements[statements.length - 1] = t.expressionStatement(
687
+ t.callExpression(
688
+ t.memberExpression(valueMember, t.identifier("push")),
689
+ [lastStatement.expression]
690
+ )
691
+ );
692
+ }
693
+ const index = statements.findIndex((statement) => t.isIfStatement(statement));
694
+ if (index > -1) {
695
+ const ifStatement = statements[index];
696
+ if (t.isBlockStatement(ifStatement.consequent) && ifStatement.consequent.body[1] && t.isForOfStatement(ifStatement.consequent.body[1])) {
697
+ const forOf = ifStatement.consequent.body[1];
698
+ if (t.isBlockStatement(forOf.body) && forOf.body.body.length === 1) {
699
+ const nestedIf = forOf.body.body[0];
700
+ if (nestedIf && t.isIfStatement(nestedIf) && t.isBlockStatement(nestedIf.consequent) && nestedIf.consequent.body.length === 1 && t.isExpressionStatement(nestedIf.consequent.body[0])) {
701
+ nestedIf.consequent.body[0] = t.expressionStatement(
702
+ t.callExpression(
703
+ t.memberExpression(valueMember, t.identifier("push")),
704
+ [nestedIf.consequent.body[0].expression]
705
+ )
706
+ );
707
+ }
708
+ }
709
+ }
710
+ }
711
+ statements.unshift(
712
+ t.expressionStatement(
713
+ t.assignmentExpression(
714
+ "=",
715
+ t.memberExpression(valueMember, t.identifier("length")),
716
+ t.numericLiteral(0)
717
+ )
718
+ )
719
+ );
720
+ }
721
+ });
722
+ return {
723
+ code: hasPatched ? content : generate(ast).code,
724
+ hasPatched
725
+ };
726
+ }
727
+
728
+ // src/patching/operations/export-context/postcss-v3.ts
729
+ import * as t2 from "@babel/types";
730
+ var IDENTIFIER_RE2 = /^[A-Z_$][\w$]*$/i;
731
+ function toIdentifierName2(property) {
732
+ if (!property) {
733
+ return "contextRef";
734
+ }
735
+ const sanitized = property.replace(/[^\w$]/gu, "_");
736
+ if (/^\d/.test(sanitized)) {
737
+ return `_${sanitized}`;
738
+ }
739
+ return sanitized || "contextRef";
740
+ }
741
+ function createModuleExportsMember(property) {
742
+ const object = t2.memberExpression(t2.identifier("module"), t2.identifier("exports"));
743
+ if (IDENTIFIER_RE2.test(property)) {
744
+ return t2.memberExpression(object, t2.identifier(property));
745
+ }
746
+ return t2.memberExpression(object, t2.stringLiteral(property), true);
747
+ }
748
+ function transformProcessTailwindFeaturesReturnContext(content) {
749
+ const ast = parse(content);
750
+ let hasPatched = false;
751
+ traverse(ast, {
752
+ FunctionDeclaration(path8) {
753
+ const node = path8.node;
754
+ if (node.id?.name !== "processTailwindFeatures" || node.body.body.length !== 1) {
755
+ return;
756
+ }
757
+ const [returnStatement3] = node.body.body;
758
+ if (!t2.isReturnStatement(returnStatement3) || !t2.isFunctionExpression(returnStatement3.argument)) {
759
+ return;
760
+ }
761
+ const expression = returnStatement3.argument;
762
+ const body = expression.body.body;
763
+ const lastStatement = body[body.length - 1];
764
+ const alreadyReturnsContext = Boolean(
765
+ t2.isReturnStatement(lastStatement) && t2.isIdentifier(lastStatement.argument) && lastStatement.argument.name === "context"
766
+ );
767
+ hasPatched = alreadyReturnsContext;
768
+ if (!alreadyReturnsContext) {
769
+ body.push(t2.returnStatement(t2.identifier("context")));
770
+ }
771
+ }
772
+ });
773
+ return {
774
+ code: hasPatched ? content : generate(ast).code,
775
+ hasPatched
776
+ };
777
+ }
778
+ function transformPostcssPlugin(content, { refProperty }) {
779
+ const ast = parse(content);
780
+ const refIdentifier = t2.identifier(toIdentifierName2(refProperty));
781
+ const moduleExportsMember = createModuleExportsMember(refProperty);
782
+ const valueMember = t2.memberExpression(refIdentifier, t2.identifier("value"));
783
+ let hasPatched = false;
784
+ traverse(ast, {
785
+ Program(path8) {
786
+ const program = path8.node;
787
+ const index = program.body.findIndex((statement) => {
788
+ return t2.isExpressionStatement(statement) && t2.isAssignmentExpression(statement.expression) && t2.isMemberExpression(statement.expression.left) && t2.isFunctionExpression(statement.expression.right) && statement.expression.right.id?.name === "tailwindcss";
789
+ });
790
+ if (index === -1) {
791
+ return;
792
+ }
793
+ const previousStatement = program.body[index - 1];
794
+ const lastStatement = program.body[program.body.length - 1];
795
+ const alreadyHasVariable = Boolean(
796
+ previousStatement && t2.isVariableDeclaration(previousStatement) && previousStatement.declarations.length === 1 && t2.isIdentifier(previousStatement.declarations[0].id) && previousStatement.declarations[0].id.name === refIdentifier.name
797
+ );
798
+ const alreadyAssignsModuleExports = Boolean(
799
+ 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
800
+ );
801
+ hasPatched = alreadyHasVariable && alreadyAssignsModuleExports;
802
+ if (!alreadyHasVariable) {
803
+ program.body.splice(
804
+ index,
805
+ 0,
806
+ t2.variableDeclaration("const", [
807
+ t2.variableDeclarator(
808
+ refIdentifier,
809
+ t2.objectExpression([
810
+ t2.objectProperty(t2.identifier("value"), t2.arrayExpression())
811
+ ])
812
+ )
813
+ ])
814
+ );
815
+ }
816
+ if (!alreadyAssignsModuleExports) {
817
+ program.body.push(
818
+ t2.expressionStatement(
819
+ t2.assignmentExpression("=", moduleExportsMember, refIdentifier)
820
+ )
821
+ );
822
+ }
823
+ },
824
+ FunctionExpression(path8) {
825
+ if (hasPatched) {
826
+ return;
827
+ }
828
+ const fn = path8.node;
829
+ if (fn.id?.name !== "tailwindcss" || fn.body.body.length !== 1) {
830
+ return;
831
+ }
832
+ const [returnStatement3] = fn.body.body;
833
+ if (!returnStatement3 || !t2.isReturnStatement(returnStatement3) || !t2.isObjectExpression(returnStatement3.argument)) {
834
+ return;
835
+ }
836
+ const properties = returnStatement3.argument.properties;
837
+ if (properties.length !== 2) {
838
+ return;
839
+ }
840
+ const pluginsProperty = properties.find(
841
+ (prop) => t2.isObjectProperty(prop) && t2.isIdentifier(prop.key) && prop.key.name === "plugins"
842
+ );
843
+ if (!pluginsProperty || !t2.isObjectProperty(pluginsProperty) || !t2.isCallExpression(pluginsProperty.value) || !t2.isMemberExpression(pluginsProperty.value.callee) || !t2.isArrayExpression(pluginsProperty.value.callee.object)) {
844
+ return;
845
+ }
846
+ const pluginsArray = pluginsProperty.value.callee.object.elements;
847
+ const targetPlugin = pluginsArray[1];
848
+ if (!targetPlugin || !t2.isFunctionExpression(targetPlugin)) {
849
+ return;
850
+ }
851
+ const block = targetPlugin.body;
852
+ const statements = block.body;
853
+ const last = statements[statements.length - 1];
854
+ if (last && t2.isExpressionStatement(last)) {
855
+ statements[statements.length - 1] = t2.expressionStatement(
856
+ t2.callExpression(
857
+ t2.memberExpression(valueMember, t2.identifier("push")),
858
+ [last.expression]
859
+ )
860
+ );
861
+ }
862
+ const index = statements.findIndex((s) => t2.isIfStatement(s));
863
+ if (index > -1) {
864
+ const ifStatement = statements[index];
865
+ if (t2.isBlockStatement(ifStatement.consequent)) {
866
+ const [, second] = ifStatement.consequent.body;
867
+ if (second && t2.isForOfStatement(second) && t2.isBlockStatement(second.body)) {
868
+ const bodyStatement = second.body.body[0];
869
+ if (bodyStatement && t2.isIfStatement(bodyStatement) && t2.isBlockStatement(bodyStatement.consequent) && bodyStatement.consequent.body.length === 1 && t2.isExpressionStatement(bodyStatement.consequent.body[0])) {
870
+ bodyStatement.consequent.body[0] = t2.expressionStatement(
871
+ t2.callExpression(
872
+ t2.memberExpression(valueMember, t2.identifier("push")),
873
+ [bodyStatement.consequent.body[0].expression]
874
+ )
875
+ );
876
+ }
877
+ }
878
+ }
879
+ }
880
+ statements.unshift(
881
+ t2.expressionStatement(
882
+ t2.assignmentExpression(
883
+ "=",
884
+ t2.memberExpression(valueMember, t2.identifier("length")),
885
+ t2.numericLiteral(0)
886
+ )
887
+ )
888
+ );
889
+ }
890
+ });
891
+ return {
892
+ code: hasPatched ? content : generate(ast).code,
893
+ hasPatched
894
+ };
895
+ }
896
+
897
+ // src/patching/operations/export-context/index.ts
898
+ function writeFileIfRequired(filePath, code, overwrite, successMessage) {
899
+ if (!overwrite) {
900
+ return;
901
+ }
902
+ fs4.writeFileSync(filePath, code, {
903
+ encoding: "utf8"
904
+ });
905
+ logger_default.success(successMessage);
906
+ }
907
+ function applyExposeContextPatch(params) {
908
+ const { rootDir, refProperty, overwrite, majorVersion } = params;
909
+ const result = {
910
+ applied: false,
911
+ files: {}
912
+ };
913
+ if (majorVersion === 3) {
914
+ const processFileRelative = "lib/processTailwindFeatures.js";
915
+ const processFilePath = path5.resolve(rootDir, processFileRelative);
916
+ if (fs4.existsSync(processFilePath)) {
917
+ const content = fs4.readFileSync(processFilePath, "utf8");
918
+ const { code, hasPatched } = transformProcessTailwindFeaturesReturnContext(content);
919
+ result.files[processFileRelative] = code;
920
+ if (!hasPatched) {
921
+ writeFileIfRequired(
922
+ processFilePath,
923
+ code,
924
+ overwrite,
925
+ "Patched Tailwind CSS processTailwindFeatures to expose runtime context."
926
+ );
927
+ result.applied = true;
928
+ }
929
+ }
930
+ const pluginCandidates = ["lib/plugin.js", "lib/index.js"];
931
+ const pluginRelative = pluginCandidates.find((candidate) => fs4.existsSync(path5.resolve(rootDir, candidate)));
932
+ if (pluginRelative) {
933
+ const pluginPath = path5.resolve(rootDir, pluginRelative);
934
+ const content = fs4.readFileSync(pluginPath, "utf8");
935
+ const { code, hasPatched } = transformPostcssPlugin(content, { refProperty });
936
+ result.files[pluginRelative] = code;
937
+ if (!hasPatched) {
938
+ writeFileIfRequired(
939
+ pluginPath,
940
+ code,
941
+ overwrite,
942
+ "Patched Tailwind CSS plugin entry to collect runtime contexts."
943
+ );
944
+ result.applied = true;
945
+ }
946
+ }
947
+ } else if (majorVersion === 2) {
948
+ const processFileRelative = "lib/jit/processTailwindFeatures.js";
949
+ const processFilePath = path5.resolve(rootDir, processFileRelative);
950
+ if (fs4.existsSync(processFilePath)) {
951
+ const content = fs4.readFileSync(processFilePath, "utf8");
952
+ const { code, hasPatched } = transformProcessTailwindFeaturesReturnContextV2(content);
953
+ result.files[processFileRelative] = code;
954
+ if (!hasPatched) {
955
+ writeFileIfRequired(
956
+ processFilePath,
957
+ code,
958
+ overwrite,
959
+ "Patched Tailwind CSS JIT processTailwindFeatures to expose runtime context."
960
+ );
961
+ result.applied = true;
962
+ }
963
+ }
964
+ const pluginRelative = "lib/jit/index.js";
965
+ const pluginPath = path5.resolve(rootDir, pluginRelative);
966
+ if (fs4.existsSync(pluginPath)) {
967
+ const content = fs4.readFileSync(pluginPath, "utf8");
968
+ const { code, hasPatched } = transformPostcssPluginV2(content, { refProperty });
969
+ result.files[pluginRelative] = code;
970
+ if (!hasPatched) {
971
+ writeFileIfRequired(
972
+ pluginPath,
973
+ code,
974
+ overwrite,
975
+ "Patched Tailwind CSS JIT entry to collect runtime contexts."
976
+ );
977
+ result.applied = true;
978
+ }
979
+ }
980
+ }
981
+ return result;
982
+ }
983
+
984
+ // src/patching/operations/extend-length-units.ts
985
+ import * as t3 from "@babel/types";
986
+ import fs5 from "fs-extra";
987
+ import path6 from "pathe";
988
+ function updateLengthUnitsArray(content, options) {
989
+ const { variableName = "lengthUnits", units } = options;
990
+ const ast = parse(content);
991
+ let arrayRef;
992
+ let changed = false;
993
+ traverse(ast, {
994
+ Identifier(path8) {
995
+ if (path8.node.name === variableName && t3.isVariableDeclarator(path8.parent) && t3.isArrayExpression(path8.parent.init)) {
996
+ arrayRef = path8.parent.init;
997
+ const existing = new Set(
998
+ path8.parent.init.elements.map((element) => t3.isStringLiteral(element) ? element.value : void 0).filter(Boolean)
999
+ );
1000
+ for (const unit of units) {
1001
+ if (!existing.has(unit)) {
1002
+ path8.parent.init.elements = path8.parent.init.elements.map((element) => {
1003
+ if (t3.isStringLiteral(element)) {
1004
+ return t3.stringLiteral(element.value);
1005
+ }
1006
+ return element;
1007
+ });
1008
+ path8.parent.init.elements.push(t3.stringLiteral(unit));
1009
+ changed = true;
1010
+ }
1011
+ }
1012
+ }
1013
+ }
1014
+ });
1015
+ return {
1016
+ arrayRef,
1017
+ changed
1018
+ };
1019
+ }
1020
+ function applyExtendLengthUnitsPatchV3(rootDir, options) {
1021
+ if (!options.enabled) {
1022
+ return { changed: false, code: void 0 };
1023
+ }
1024
+ const opts = {
1025
+ ...options,
1026
+ lengthUnitsFilePath: options.lengthUnitsFilePath ?? "lib/util/dataTypes.js",
1027
+ variableName: options.variableName ?? "lengthUnits"
1028
+ };
1029
+ const dataTypesFilePath = path6.resolve(rootDir, opts.lengthUnitsFilePath);
1030
+ const exists = fs5.existsSync(dataTypesFilePath);
1031
+ if (!exists) {
1032
+ return { changed: false, code: void 0 };
1033
+ }
1034
+ const content = fs5.readFileSync(dataTypesFilePath, "utf8");
1035
+ const { arrayRef, changed } = updateLengthUnitsArray(content, opts);
1036
+ if (!arrayRef || !changed) {
1037
+ return { changed: false, code: void 0 };
1038
+ }
1039
+ const { code } = generate(arrayRef, {
1040
+ jsescOption: { quotes: "single" }
1041
+ });
1042
+ if (arrayRef.start != null && arrayRef.end != null) {
1043
+ const nextCode = `${content.slice(0, arrayRef.start)}${code}${content.slice(arrayRef.end)}`;
1044
+ if (opts.overwrite) {
1045
+ const target = opts.destPath ? path6.resolve(opts.destPath) : dataTypesFilePath;
1046
+ fs5.writeFileSync(target, nextCode, "utf8");
1047
+ logger_default.success("Patched Tailwind CSS length unit list (v3).");
1048
+ }
1049
+ return {
1050
+ changed: true,
1051
+ code: nextCode
1052
+ };
1053
+ }
1054
+ return {
1055
+ changed: false,
1056
+ code: void 0
1057
+ };
1058
+ }
1059
+ function applyExtendLengthUnitsPatchV4(rootDir, options) {
1060
+ if (!options.enabled) {
1061
+ return { files: [], changed: false };
1062
+ }
1063
+ const opts = { ...options };
1064
+ const distDir = path6.resolve(rootDir, "dist");
1065
+ if (!fs5.existsSync(distDir)) {
1066
+ return { files: [], changed: false };
1067
+ }
1068
+ const entries = fs5.readdirSync(distDir);
1069
+ const chunkNames = entries.filter((entry) => entry.endsWith(".js") || entry.endsWith(".mjs"));
1070
+ const pattern = /\[\s*["']cm["'],\s*["']mm["'],[\w,"']+\]/;
1071
+ const candidates = chunkNames.map((chunkName) => {
1072
+ const file = path6.join(distDir, chunkName);
1073
+ const code = fs5.readFileSync(file, "utf8");
1074
+ const match = pattern.exec(code);
1075
+ if (!match) {
1076
+ return null;
1077
+ }
1078
+ return {
1079
+ file,
1080
+ code,
1081
+ match,
1082
+ hasPatched: false
1083
+ };
1084
+ }).filter((candidate) => candidate !== null);
1085
+ for (const item of candidates) {
1086
+ const { code, file, match } = item;
1087
+ const ast = parse(match[0], { sourceType: "unambiguous" });
1088
+ traverse(ast, {
1089
+ ArrayExpression(path8) {
1090
+ for (const unit of opts.units) {
1091
+ if (path8.node.elements.some((element) => t3.isStringLiteral(element) && element.value === unit)) {
1092
+ item.hasPatched = true;
1093
+ return;
1094
+ }
1095
+ path8.node.elements.push(t3.stringLiteral(unit));
1096
+ }
1097
+ }
1098
+ });
1099
+ if (item.hasPatched) {
1100
+ continue;
1101
+ }
1102
+ const { code: replacement } = generate(ast, { minified: true });
1103
+ const start = match.index ?? 0;
1104
+ const end = start + match[0].length;
1105
+ item.code = spliceChangesIntoString(code, [
1106
+ {
1107
+ start,
1108
+ end,
1109
+ replacement: replacement.endsWith(";") ? replacement.slice(0, -1) : replacement
1110
+ }
1111
+ ]);
1112
+ if (opts.overwrite) {
1113
+ fs5.writeFileSync(file, item.code, "utf8");
1114
+ }
1115
+ }
1116
+ if (candidates.some((file) => !file.hasPatched)) {
1117
+ logger_default.success("Patched Tailwind CSS length unit list (v4).");
1118
+ }
1119
+ return {
1120
+ changed: candidates.some((file) => !file.hasPatched),
1121
+ files: candidates
1122
+ };
1123
+ }
1124
+
1125
+ // src/patching/patch-runner.ts
1126
+ function applyTailwindPatches(context) {
1127
+ const { packageInfo, options, majorVersion } = context;
1128
+ const results = {};
1129
+ if (options.features.exposeContext.enabled && (majorVersion === 2 || majorVersion === 3)) {
1130
+ results.exposeContext = applyExposeContextPatch({
1131
+ rootDir: packageInfo.rootPath,
1132
+ refProperty: options.features.exposeContext.refProperty,
1133
+ overwrite: options.overwrite,
1134
+ majorVersion
1135
+ });
1136
+ }
1137
+ if (options.features.extendLengthUnits?.enabled) {
1138
+ if (majorVersion === 3) {
1139
+ results.extendLengthUnits = applyExtendLengthUnitsPatchV3(
1140
+ packageInfo.rootPath,
1141
+ options.features.extendLengthUnits
1142
+ );
1143
+ } else if (majorVersion === 4) {
1144
+ results.extendLengthUnits = applyExtendLengthUnitsPatchV4(
1145
+ packageInfo.rootPath,
1146
+ options.features.extendLengthUnits
1147
+ );
1148
+ }
1149
+ }
1150
+ return results;
1151
+ }
1152
+
1153
+ // src/api/tailwindcss-patcher.ts
1154
+ function resolveMajorVersion(version, hint) {
1155
+ if (hint && [2, 3, 4].includes(hint)) {
1156
+ return hint;
1157
+ }
1158
+ if (version) {
1159
+ const coerced = coerce(version);
1160
+ if (coerced) {
1161
+ const major = coerced.major;
1162
+ if (major === 2 || major === 3 || major === 4) {
1163
+ return major;
1164
+ }
1165
+ if (major >= 4) {
1166
+ return 4;
1167
+ }
1168
+ }
1169
+ }
1170
+ return 3;
1171
+ }
1172
+ function resolveTailwindExecutionOptions(normalized, majorVersion) {
1173
+ const base = normalized.tailwind;
1174
+ if (majorVersion === 2 && base.v2) {
1175
+ return {
1176
+ cwd: base.v2.cwd ?? base.cwd ?? normalized.projectRoot,
1177
+ config: base.v2.config ?? base.config,
1178
+ postcssPlugin: base.v2.postcssPlugin ?? base.postcssPlugin
1179
+ };
1180
+ }
1181
+ if (majorVersion === 3 && base.v3) {
1182
+ return {
1183
+ cwd: base.v3.cwd ?? base.cwd ?? normalized.projectRoot,
1184
+ config: base.v3.config ?? base.config,
1185
+ postcssPlugin: base.v3.postcssPlugin ?? base.postcssPlugin
1186
+ };
1187
+ }
1188
+ return {
1189
+ cwd: base.cwd ?? normalized.projectRoot,
1190
+ config: base.config,
1191
+ postcssPlugin: base.postcssPlugin
1192
+ };
1193
+ }
1194
+ var TailwindcssPatcher = class {
1195
+ options;
1196
+ packageInfo;
1197
+ majorVersion;
1198
+ cacheStore;
1199
+ constructor(options = {}) {
1200
+ const resolvedOptions = options && typeof options === "object" && "patch" in options ? fromLegacyOptions(options) : options;
1201
+ this.options = normalizeOptions(resolvedOptions);
1202
+ const packageInfo = getPackageInfoSync(
1203
+ this.options.tailwind.packageName,
1204
+ this.options.tailwind.resolve
1205
+ );
1206
+ if (!packageInfo) {
1207
+ throw new Error(`Unable to locate Tailwind CSS package "${this.options.tailwind.packageName}".`);
1208
+ }
1209
+ this.packageInfo = packageInfo;
1210
+ this.majorVersion = resolveMajorVersion(
1211
+ this.packageInfo.version,
1212
+ this.options.tailwind.versionHint
1213
+ );
1214
+ this.cacheStore = new CacheStore(this.options.cache);
1215
+ }
1216
+ async patch() {
1217
+ return applyTailwindPatches({
1218
+ packageInfo: this.packageInfo,
1219
+ options: this.options,
1220
+ majorVersion: this.majorVersion
1221
+ });
1222
+ }
1223
+ getContexts() {
1224
+ return loadRuntimeContexts(
1225
+ this.packageInfo,
1226
+ this.majorVersion,
1227
+ this.options.features.exposeContext.refProperty
1228
+ );
1229
+ }
1230
+ async runTailwindBuildIfNeeded() {
1231
+ if (this.majorVersion === 2 || this.majorVersion === 3) {
1232
+ const executionOptions = resolveTailwindExecutionOptions(this.options, this.majorVersion);
1233
+ await runTailwindBuild({
1234
+ cwd: executionOptions.cwd,
1235
+ config: executionOptions.config,
1236
+ majorVersion: this.majorVersion,
1237
+ postcssPlugin: executionOptions.postcssPlugin
1238
+ });
1239
+ }
1240
+ }
1241
+ async collectClassSet() {
1242
+ if (this.majorVersion === 4) {
1243
+ return collectClassesFromTailwindV4(this.options);
1244
+ }
1245
+ const contexts = this.getContexts();
1246
+ return collectClassesFromContexts(contexts, this.options.filter);
1247
+ }
1248
+ async mergeWithCache(set) {
1249
+ if (!this.options.cache.enabled) {
1250
+ return set;
1251
+ }
1252
+ const existing = await this.cacheStore.read();
1253
+ if (this.options.cache.strategy === "merge") {
1254
+ for (const value of existing) {
1255
+ set.add(value);
1256
+ }
1257
+ await this.cacheStore.write(set);
1258
+ } else {
1259
+ if (set.size > 0) {
1260
+ await this.cacheStore.write(set);
1261
+ } else {
1262
+ return existing;
1263
+ }
1264
+ }
1265
+ return set;
1266
+ }
1267
+ async getClassSet() {
1268
+ await this.runTailwindBuildIfNeeded();
1269
+ const set = await this.collectClassSet();
1270
+ return this.mergeWithCache(set);
1271
+ }
1272
+ async extract(options) {
1273
+ const shouldWrite = options?.write ?? this.options.output.enabled;
1274
+ const classSet = await this.getClassSet();
1275
+ const classList = Array.from(classSet);
1276
+ const result = {
1277
+ classList,
1278
+ classSet
1279
+ };
1280
+ if (!shouldWrite || !this.options.output.file) {
1281
+ return result;
1282
+ }
1283
+ const target = path7.resolve(this.options.output.file);
1284
+ await fs6.ensureDir(path7.dirname(target));
1285
+ if (this.options.output.format === "json") {
1286
+ const spaces = typeof this.options.output.pretty === "number" ? this.options.output.pretty : void 0;
1287
+ await fs6.writeJSON(target, classList, { spaces });
1288
+ } else {
1289
+ await fs6.writeFile(target, `${classList.join("\n")}
1290
+ `, "utf8");
1291
+ }
1292
+ logger_default.success(`Tailwind CSS class list saved to ${target.replace(process4.cwd(), ".")}`);
1293
+ return {
1294
+ ...result,
1295
+ filename: target
1296
+ };
1297
+ }
1298
+ // Backwards compatibility helper used by tests and API consumers.
1299
+ extractValidCandidates = extractValidCandidates;
1300
+ };
1301
+
1302
+ export {
1303
+ logger_default,
1304
+ CacheStore,
1305
+ extractRawCandidatesWithPositions,
1306
+ extractRawCandidates,
1307
+ extractValidCandidates,
1308
+ fromLegacyOptions,
1309
+ fromUnifiedConfig,
1310
+ normalizeOptions,
1311
+ collectClassesFromContexts,
1312
+ collectClassesFromTailwindV4,
1313
+ loadRuntimeContexts,
1314
+ runTailwindBuild,
1315
+ TailwindcssPatcher
1316
+ };