tailwindcss-patch 8.1.0 → 8.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -34,6 +34,9 @@ pnpm dlx tw-patch install
34
34
 
35
35
  # Extract all classes into the configured output file
36
36
  pnpm dlx tw-patch extract
37
+
38
+ # Capture every token (candidate) with file/position metadata
39
+ pnpm dlx tw-patch tokens --format lines
37
40
  ```
38
41
 
39
42
  ### Extract options
@@ -48,6 +51,16 @@ pnpm dlx tw-patch extract
48
51
 
49
52
  The CLI loads `tailwindcss-patch.config.ts` via `@tailwindcss-mangle/config`. Legacy configs continue to work; see the [migration guide](./MIGRATION.md) for hints on the new fields.
50
53
 
54
+ ### Token report options
55
+
56
+ | Flag | Description |
57
+ | ------------------------ | --------------------------------------------------------------------------- |
58
+ | `--cwd <dir>` | Use a different working directory when loading configuration. |
59
+ | `--output <file>` | Override the token report target file (defaults to `.tw-patch/tw-token-report.json`). |
60
+ | `--format <json\|lines\|grouped-json>` | Choose between a JSON payload (default), newline summaries, or JSON grouped by file path. |
61
+ | `--group-key <relative\|absolute>` | Control grouped-json keys (defaults to relative paths). |
62
+ | `--no-write` | Skip writing to disk and only print a preview. |
63
+
51
64
  ## Programmatic API
52
65
 
53
66
  ```ts
@@ -81,6 +94,12 @@ const patcher = new TailwindcssPatcher({
81
94
 
82
95
  await patcher.patch()
83
96
  const { classList, filename } = await patcher.extract()
97
+ const tokenReport = await patcher.collectContentTokens()
98
+ console.log(tokenReport.entries[0]) // { rawCandidate, file, line, column, ... }
99
+ const groupedTokens = await patcher.collectContentTokensByFile()
100
+ console.log(groupedTokens['src/button.tsx'][0].rawCandidate)
101
+ // Preserve absolute file paths:
102
+ // await patcher.collectContentTokensByFile({ key: 'absolute', stripAbsolutePaths: false })
84
103
  ```
85
104
 
86
105
  The constructor accepts either the new object shown above or the historical `patch`/`cache` shape. Conversions happen internally so existing configs remain backwards compatible.
@@ -89,6 +108,8 @@ The constructor accepts either the new object shown above or the historical `pat
89
108
 
90
109
  - `normalizeOptions` – normalise raw user input to the runtime shape.
91
110
  - `CacheStore` – read/write class caches respecting merge or overwrite semantics.
111
+ - `extractProjectCandidatesWithPositions` – gather Tailwind tokens for every configured source file with location metadata.
112
+ - `groupTokensByFile` – convert a token report into a `{ [filePath]: TailwindTokenLocation[] }` map.
92
113
  - `extractValidCandidates` – scan Tailwind v4 CSS/content sources with the Tailwind Oxide scanner.
93
114
  - `runTailwindBuild` – run the Tailwind PostCSS plugin for v2/v3 projects to prime runtime contexts.
94
115
 
@@ -94,7 +94,9 @@ var CacheStore = class {
94
94
  };
95
95
 
96
96
  // src/extraction/candidate-extractor.ts
97
+ var _fs = require('fs');
97
98
  var _process = require('process'); var _process2 = _interopRequireDefault(_process);
99
+ var _pathe = require('pathe'); var _pathe2 = _interopRequireDefault(_pathe);
98
100
  async function importNode() {
99
101
  return Promise.resolve().then(() => _interopRequireWildcard(require("@tailwindcss/node")));
100
102
  }
@@ -142,11 +144,144 @@ async function extractValidCandidates(options) {
142
144
  );
143
145
  return validCandidates;
144
146
  }
147
+ function normalizeSources(sources, cwd) {
148
+ const baseSources = _optionalChain([sources, 'optionalAccess', _ => _.length]) ? sources : [
149
+ {
150
+ base: cwd,
151
+ pattern: "**/*",
152
+ negated: false
153
+ }
154
+ ];
155
+ return baseSources.map((source) => ({
156
+ base: _nullishCoalesce(source.base, () => ( cwd)),
157
+ pattern: source.pattern,
158
+ negated: source.negated
159
+ }));
160
+ }
161
+ function buildLineOffsets(content) {
162
+ const offsets = [0];
163
+ for (let i = 0; i < content.length; i++) {
164
+ if (content[i] === "\n") {
165
+ offsets.push(i + 1);
166
+ }
167
+ }
168
+ if (offsets[offsets.length - 1] !== content.length) {
169
+ offsets.push(content.length);
170
+ }
171
+ return offsets;
172
+ }
173
+ function resolveLineMeta(content, offsets, index) {
174
+ let low = 0;
175
+ let high = offsets.length - 1;
176
+ while (low <= high) {
177
+ const mid = Math.floor((low + high) / 2);
178
+ const start = offsets[mid];
179
+ const nextStart = _nullishCoalesce(offsets[mid + 1], () => ( content.length));
180
+ if (index < start) {
181
+ high = mid - 1;
182
+ continue;
183
+ }
184
+ if (index >= nextStart) {
185
+ low = mid + 1;
186
+ continue;
187
+ }
188
+ const line = mid + 1;
189
+ const column = index - start + 1;
190
+ const lineEnd = content.indexOf("\n", start);
191
+ const lineText = content.slice(start, lineEnd === -1 ? content.length : lineEnd);
192
+ return { line, column, lineText };
193
+ }
194
+ const lastStart = _nullishCoalesce(offsets[offsets.length - 2], () => ( 0));
195
+ return {
196
+ line: offsets.length - 1,
197
+ column: index - lastStart + 1,
198
+ lineText: content.slice(lastStart)
199
+ };
200
+ }
201
+ function toExtension(filename) {
202
+ const ext = _pathe2.default.extname(filename).replace(/^\./, "");
203
+ return ext || "txt";
204
+ }
205
+ function toRelativeFile(cwd, filename) {
206
+ const relative = _pathe2.default.relative(cwd, filename);
207
+ return relative === "" ? _pathe2.default.basename(filename) : relative;
208
+ }
209
+ async function extractProjectCandidatesWithPositions(options) {
210
+ const cwd = _optionalChain([options, 'optionalAccess', _2 => _2.cwd]) ? _pathe2.default.resolve(options.cwd) : _process2.default.cwd();
211
+ const normalizedSources = normalizeSources(_optionalChain([options, 'optionalAccess', _3 => _3.sources]), cwd);
212
+ const { Scanner } = await importOxide();
213
+ const scanner = new Scanner({
214
+ sources: normalizedSources
215
+ });
216
+ const files = _nullishCoalesce(scanner.files, () => ( []));
217
+ const entries = [];
218
+ const skipped = [];
219
+ for (const file of files) {
220
+ let content;
221
+ try {
222
+ content = await _fs.promises.readFile(file, "utf8");
223
+ } catch (error) {
224
+ skipped.push({
225
+ file,
226
+ reason: error instanceof Error ? error.message : "Unknown error"
227
+ });
228
+ continue;
229
+ }
230
+ const extension = toExtension(file);
231
+ const matches = scanner.getCandidatesWithPositions({
232
+ file,
233
+ content,
234
+ extension
235
+ });
236
+ if (!matches.length) {
237
+ continue;
238
+ }
239
+ const offsets = buildLineOffsets(content);
240
+ const relativeFile = toRelativeFile(cwd, file);
241
+ for (const match of matches) {
242
+ const info = resolveLineMeta(content, offsets, match.position);
243
+ entries.push({
244
+ rawCandidate: match.candidate,
245
+ file,
246
+ relativeFile,
247
+ extension,
248
+ start: match.position,
249
+ end: match.position + match.candidate.length,
250
+ length: match.candidate.length,
251
+ line: info.line,
252
+ column: info.column,
253
+ lineText: info.lineText
254
+ });
255
+ }
256
+ }
257
+ return {
258
+ entries,
259
+ filesScanned: files.length,
260
+ skippedFiles: skipped,
261
+ sources: normalizedSources
262
+ };
263
+ }
264
+ function groupTokensByFile(report, options) {
265
+ const key = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _4 => _4.key]), () => ( "relative"));
266
+ const stripAbsolute = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _5 => _5.stripAbsolutePaths]), () => ( key !== "absolute"));
267
+ return report.entries.reduce((acc, entry) => {
268
+ const bucketKey = key === "absolute" ? entry.file : entry.relativeFile;
269
+ if (!acc[bucketKey]) {
270
+ acc[bucketKey] = [];
271
+ }
272
+ const value = stripAbsolute ? {
273
+ ...entry,
274
+ file: entry.relativeFile
275
+ } : entry;
276
+ acc[bucketKey].push(value);
277
+ return acc;
278
+ }, {});
279
+ }
145
280
 
146
281
  // src/options/legacy.ts
147
282
  function normalizeLegacyFeatures(patch) {
148
- const apply = _optionalChain([patch, 'optionalAccess', _ => _.applyPatches]);
149
- const extend = _optionalChain([apply, 'optionalAccess', _2 => _2.extendLengthUnits]);
283
+ const apply = _optionalChain([patch, 'optionalAccess', _6 => _6.applyPatches]);
284
+ const extend = _optionalChain([apply, 'optionalAccess', _7 => _7.extendLengthUnits]);
150
285
  let extendOption = false;
151
286
  if (extend && typeof extend === "object") {
152
287
  extendOption = {
@@ -157,11 +292,11 @@ function normalizeLegacyFeatures(patch) {
157
292
  extendOption = {
158
293
  enabled: true,
159
294
  units: ["rpx"],
160
- overwrite: _optionalChain([patch, 'optionalAccess', _3 => _3.overwrite])
295
+ overwrite: _optionalChain([patch, 'optionalAccess', _8 => _8.overwrite])
161
296
  };
162
297
  }
163
298
  return {
164
- exposeContext: _nullishCoalesce(_optionalChain([apply, 'optionalAccess', _4 => _4.exportContext]), () => ( true)),
299
+ exposeContext: _nullishCoalesce(_optionalChain([apply, 'optionalAccess', _9 => _9.exportContext]), () => ( true)),
165
300
  extendLengthUnits: extendOption
166
301
  };
167
302
  }
@@ -171,18 +306,18 @@ function fromLegacyOptions(options) {
171
306
  }
172
307
  const patch = options.patch;
173
308
  const features = normalizeLegacyFeatures(patch);
174
- const output = _optionalChain([patch, 'optionalAccess', _5 => _5.output]);
175
- const tailwindConfig = _optionalChain([patch, 'optionalAccess', _6 => _6.tailwindcss]);
176
- const tailwindVersion = _optionalChain([tailwindConfig, 'optionalAccess', _7 => _7.version]);
177
- const tailwindV2 = _optionalChain([tailwindConfig, 'optionalAccess', _8 => _8.v2]);
178
- const tailwindV3 = _optionalChain([tailwindConfig, 'optionalAccess', _9 => _9.v3]);
179
- const tailwindV4 = _optionalChain([tailwindConfig, 'optionalAccess', _10 => _10.v4]);
180
- const tailwindConfigPath = _nullishCoalesce(_optionalChain([tailwindV3, 'optionalAccess', _11 => _11.config]), () => ( _optionalChain([tailwindV2, 'optionalAccess', _12 => _12.config])));
181
- const tailwindCwd = _nullishCoalesce(_nullishCoalesce(_optionalChain([tailwindV3, 'optionalAccess', _13 => _13.cwd]), () => ( _optionalChain([tailwindV2, 'optionalAccess', _14 => _14.cwd]))), () => ( _optionalChain([patch, 'optionalAccess', _15 => _15.cwd])));
309
+ const output = _optionalChain([patch, 'optionalAccess', _10 => _10.output]);
310
+ const tailwindConfig = _optionalChain([patch, 'optionalAccess', _11 => _11.tailwindcss]);
311
+ const tailwindVersion = _optionalChain([tailwindConfig, 'optionalAccess', _12 => _12.version]);
312
+ const tailwindV2 = _optionalChain([tailwindConfig, 'optionalAccess', _13 => _13.v2]);
313
+ const tailwindV3 = _optionalChain([tailwindConfig, 'optionalAccess', _14 => _14.v3]);
314
+ const tailwindV4 = _optionalChain([tailwindConfig, 'optionalAccess', _15 => _15.v4]);
315
+ const tailwindConfigPath = _nullishCoalesce(_optionalChain([tailwindV3, 'optionalAccess', _16 => _16.config]), () => ( _optionalChain([tailwindV2, 'optionalAccess', _17 => _17.config])));
316
+ const tailwindCwd = _nullishCoalesce(_nullishCoalesce(_optionalChain([tailwindV3, 'optionalAccess', _18 => _18.cwd]), () => ( _optionalChain([tailwindV2, 'optionalAccess', _19 => _19.cwd]))), () => ( _optionalChain([patch, 'optionalAccess', _20 => _20.cwd])));
182
317
  return {
183
- cwd: _optionalChain([patch, 'optionalAccess', _16 => _16.cwd]),
184
- overwrite: _optionalChain([patch, 'optionalAccess', _17 => _17.overwrite]),
185
- filter: _optionalChain([patch, 'optionalAccess', _18 => _18.filter]),
318
+ cwd: _optionalChain([patch, 'optionalAccess', _21 => _21.cwd]),
319
+ overwrite: _optionalChain([patch, 'optionalAccess', _22 => _22.overwrite]),
320
+ filter: _optionalChain([patch, 'optionalAccess', _23 => _23.filter]),
186
321
  cache: typeof options.cache === "boolean" ? options.cache : options.cache ? {
187
322
  ...options.cache,
188
323
  enabled: _nullishCoalesce(options.cache.enabled, () => ( true))
@@ -193,9 +328,9 @@ function fromLegacyOptions(options) {
193
328
  removeUniversalSelector: output.removeUniversalSelector
194
329
  } : void 0,
195
330
  tailwind: {
196
- packageName: _optionalChain([patch, 'optionalAccess', _19 => _19.packageName]),
331
+ packageName: _optionalChain([patch, 'optionalAccess', _24 => _24.packageName]),
197
332
  version: tailwindVersion,
198
- resolve: _optionalChain([patch, 'optionalAccess', _20 => _20.resolve]),
333
+ resolve: _optionalChain([patch, 'optionalAccess', _25 => _25.resolve]),
199
334
  config: tailwindConfigPath,
200
335
  cwd: tailwindCwd,
201
336
  v2: tailwindV2,
@@ -215,7 +350,7 @@ function fromUnifiedConfig(registry) {
215
350
  const tailwind = registry.tailwind;
216
351
  const output = registry.output;
217
352
  const pretty = (() => {
218
- if (_optionalChain([output, 'optionalAccess', _21 => _21.pretty]) === void 0) {
353
+ if (_optionalChain([output, 'optionalAccess', _26 => _26.pretty]) === void 0) {
219
354
  return void 0;
220
355
  }
221
356
  if (typeof output.pretty === "boolean") {
@@ -244,7 +379,7 @@ function fromUnifiedConfig(registry) {
244
379
 
245
380
  // src/options/normalize.ts
246
381
 
247
- var _pathe = require('pathe'); var _pathe2 = _interopRequireDefault(_pathe);
382
+
248
383
 
249
384
  // src/constants.ts
250
385
  var pkgName = "tailwindcss-patch";
@@ -285,11 +420,11 @@ function normalizeCacheOptions(cache, projectRoot) {
285
420
  };
286
421
  }
287
422
  function normalizeOutputOptions(output) {
288
- const enabled = _nullishCoalesce(_optionalChain([output, 'optionalAccess', _22 => _22.enabled]), () => ( true));
289
- const file = _nullishCoalesce(_optionalChain([output, 'optionalAccess', _23 => _23.file]), () => ( ".tw-patch/tw-class-list.json"));
290
- const format = _nullishCoalesce(_optionalChain([output, 'optionalAccess', _24 => _24.format]), () => ( "json"));
291
- const pretty = toPrettyValue(_nullishCoalesce(_optionalChain([output, 'optionalAccess', _25 => _25.pretty]), () => ( true)));
292
- const removeUniversalSelector = _nullishCoalesce(_optionalChain([output, 'optionalAccess', _26 => _26.removeUniversalSelector]), () => ( true));
423
+ const enabled = _nullishCoalesce(_optionalChain([output, 'optionalAccess', _27 => _27.enabled]), () => ( true));
424
+ const file = _nullishCoalesce(_optionalChain([output, 'optionalAccess', _28 => _28.file]), () => ( ".tw-patch/tw-class-list.json"));
425
+ const format = _nullishCoalesce(_optionalChain([output, 'optionalAccess', _29 => _29.format]), () => ( "json"));
426
+ const pretty = toPrettyValue(_nullishCoalesce(_optionalChain([output, 'optionalAccess', _30 => _30.pretty]), () => ( true)));
427
+ const removeUniversalSelector = _nullishCoalesce(_optionalChain([output, 'optionalAccess', _31 => _31.removeUniversalSelector]), () => ( true));
293
428
  return {
294
429
  enabled,
295
430
  file,
@@ -299,13 +434,13 @@ function normalizeOutputOptions(output) {
299
434
  };
300
435
  }
301
436
  function normalizeExposeContextOptions(features) {
302
- if (_optionalChain([features, 'optionalAccess', _27 => _27.exposeContext]) === false) {
437
+ if (_optionalChain([features, 'optionalAccess', _32 => _32.exposeContext]) === false) {
303
438
  return {
304
439
  enabled: false,
305
440
  refProperty: "contextRef"
306
441
  };
307
442
  }
308
- if (typeof _optionalChain([features, 'optionalAccess', _28 => _28.exposeContext]) === "object" && features.exposeContext) {
443
+ if (typeof _optionalChain([features, 'optionalAccess', _33 => _33.exposeContext]) === "object" && features.exposeContext) {
309
444
  return {
310
445
  enabled: true,
311
446
  refProperty: _nullishCoalesce(features.exposeContext.refProperty, () => ( "contextRef"))
@@ -317,7 +452,7 @@ function normalizeExposeContextOptions(features) {
317
452
  };
318
453
  }
319
454
  function normalizeExtendLengthUnitsOptions(features) {
320
- const extend = _optionalChain([features, 'optionalAccess', _29 => _29.extendLengthUnits]);
455
+ const extend = _optionalChain([features, 'optionalAccess', _34 => _34.extendLengthUnits]);
321
456
  if (extend === false || extend === void 0) {
322
457
  return null;
323
458
  }
@@ -337,9 +472,9 @@ function normalizeExtendLengthUnitsOptions(features) {
337
472
  };
338
473
  }
339
474
  function normalizeTailwindV4Options(v4, fallbackBase) {
340
- const base = _optionalChain([v4, 'optionalAccess', _30 => _30.base]) ? _pathe2.default.resolve(v4.base) : fallbackBase;
341
- const cssEntries = Array.isArray(_optionalChain([v4, 'optionalAccess', _31 => _31.cssEntries])) ? v4.cssEntries.filter((entry) => Boolean(entry)).map((entry) => _pathe2.default.resolve(entry)) : [];
342
- const sources = _optionalChain([v4, 'optionalAccess', _32 => _32.sources, 'optionalAccess', _33 => _33.length]) ? v4.sources : [
475
+ const base = _optionalChain([v4, 'optionalAccess', _35 => _35.base]) ? _pathe2.default.resolve(v4.base) : fallbackBase;
476
+ const cssEntries = Array.isArray(_optionalChain([v4, 'optionalAccess', _36 => _36.cssEntries])) ? v4.cssEntries.filter((entry) => Boolean(entry)).map((entry) => _pathe2.default.resolve(entry)) : [];
477
+ const sources = _optionalChain([v4, 'optionalAccess', _37 => _37.sources, 'optionalAccess', _38 => _38.length]) ? v4.sources : [
343
478
  {
344
479
  base,
345
480
  pattern: "**/*",
@@ -348,19 +483,19 @@ function normalizeTailwindV4Options(v4, fallbackBase) {
348
483
  ];
349
484
  return {
350
485
  base,
351
- css: _optionalChain([v4, 'optionalAccess', _34 => _34.css]),
486
+ css: _optionalChain([v4, 'optionalAccess', _39 => _39.css]),
352
487
  cssEntries,
353
488
  sources
354
489
  };
355
490
  }
356
491
  function normalizeTailwindOptions(tailwind, projectRoot) {
357
- const packageName = _nullishCoalesce(_optionalChain([tailwind, 'optionalAccess', _35 => _35.packageName]), () => ( "tailwindcss"));
358
- const versionHint = _optionalChain([tailwind, 'optionalAccess', _36 => _36.version]);
359
- const resolve = _optionalChain([tailwind, 'optionalAccess', _37 => _37.resolve]);
360
- const cwd = _nullishCoalesce(_optionalChain([tailwind, 'optionalAccess', _38 => _38.cwd]), () => ( projectRoot));
361
- const config = _optionalChain([tailwind, 'optionalAccess', _39 => _39.config]);
362
- const postcssPlugin = _optionalChain([tailwind, 'optionalAccess', _40 => _40.postcssPlugin]);
363
- const v4 = normalizeTailwindV4Options(_optionalChain([tailwind, 'optionalAccess', _41 => _41.v4]), cwd);
492
+ const packageName = _nullishCoalesce(_optionalChain([tailwind, 'optionalAccess', _40 => _40.packageName]), () => ( "tailwindcss"));
493
+ const versionHint = _optionalChain([tailwind, 'optionalAccess', _41 => _41.version]);
494
+ const resolve = _optionalChain([tailwind, 'optionalAccess', _42 => _42.resolve]);
495
+ const cwd = _nullishCoalesce(_optionalChain([tailwind, 'optionalAccess', _43 => _43.cwd]), () => ( projectRoot));
496
+ const config = _optionalChain([tailwind, 'optionalAccess', _44 => _44.config]);
497
+ const postcssPlugin = _optionalChain([tailwind, 'optionalAccess', _45 => _45.postcssPlugin]);
498
+ const v4 = normalizeTailwindV4Options(_optionalChain([tailwind, 'optionalAccess', _46 => _46.v4]), cwd);
364
499
  return {
365
500
  packageName,
366
501
  versionHint,
@@ -368,8 +503,8 @@ function normalizeTailwindOptions(tailwind, projectRoot) {
368
503
  cwd,
369
504
  config,
370
505
  postcssPlugin,
371
- v2: _optionalChain([tailwind, 'optionalAccess', _42 => _42.v2]),
372
- v3: _optionalChain([tailwind, 'optionalAccess', _43 => _43.v3]),
506
+ v2: _optionalChain([tailwind, 'optionalAccess', _47 => _47.v2]),
507
+ v3: _optionalChain([tailwind, 'optionalAccess', _48 => _48.v3]),
373
508
  v4
374
509
  };
375
510
  }
@@ -456,7 +591,7 @@ async function collectClassesFromTailwindV4(options) {
456
591
  if (!v4Options) {
457
592
  return set;
458
593
  }
459
- const sources = _optionalChain([v4Options, 'access', _44 => _44.sources, 'optionalAccess', _45 => _45.map, 'call', _46 => _46((source) => {
594
+ const sources = _optionalChain([v4Options, 'access', _49 => _49.sources, 'optionalAccess', _50 => _50.map, 'call', _51 => _51((source) => {
460
595
  return {
461
596
  base: _nullishCoalesce(_nullishCoalesce(source.base, () => ( v4Options.base)), () => ( _process2.default.cwd())),
462
597
  pattern: source.pattern,
@@ -632,9 +767,9 @@ function transformProcessTailwindFeaturesReturnContextV2(content) {
632
767
  });
633
768
  let hasPatched = false;
634
769
  traverse(ast, {
635
- FunctionDeclaration(path8) {
636
- const node = path8.node;
637
- if (_optionalChain([node, 'access', _47 => _47.id, 'optionalAccess', _48 => _48.name]) !== "processTailwindFeatures" || node.body.body.length !== 1 || !t.isReturnStatement(node.body.body[0])) {
770
+ FunctionDeclaration(path9) {
771
+ const node = path9.node;
772
+ if (_optionalChain([node, 'access', _52 => _52.id, 'optionalAccess', _53 => _53.name]) !== "processTailwindFeatures" || node.body.body.length !== 1 || !t.isReturnStatement(node.body.body[0])) {
638
773
  return;
639
774
  }
640
775
  const returnStatement3 = node.body.body[0];
@@ -664,10 +799,10 @@ function transformPostcssPluginV2(content, options) {
664
799
  const ast = _parser.parse.call(void 0, content);
665
800
  let hasPatched = false;
666
801
  traverse(ast, {
667
- Program(path8) {
668
- const program = path8.node;
802
+ Program(path9) {
803
+ const program = path9.node;
669
804
  const index = program.body.findIndex((statement) => {
670
- return t.isFunctionDeclaration(statement) && _optionalChain([statement, 'access', _49 => _49.id, 'optionalAccess', _50 => _50.name]) === "_default";
805
+ return t.isFunctionDeclaration(statement) && _optionalChain([statement, 'access', _54 => _54.id, 'optionalAccess', _55 => _55.name]) === "_default";
671
806
  });
672
807
  if (index === -1) {
673
808
  return;
@@ -699,12 +834,12 @@ function transformPostcssPluginV2(content, options) {
699
834
  );
700
835
  }
701
836
  },
702
- FunctionDeclaration(path8) {
837
+ FunctionDeclaration(path9) {
703
838
  if (hasPatched) {
704
839
  return;
705
840
  }
706
- const fn = path8.node;
707
- if (_optionalChain([fn, 'access', _51 => _51.id, 'optionalAccess', _52 => _52.name]) !== "_default") {
841
+ const fn = path9.node;
842
+ if (_optionalChain([fn, 'access', _56 => _56.id, 'optionalAccess', _57 => _57.name]) !== "_default") {
708
843
  return;
709
844
  }
710
845
  if (fn.body.body.length !== 1 || !t.isReturnStatement(fn.body.body[0])) {
@@ -792,9 +927,9 @@ function transformProcessTailwindFeaturesReturnContext(content) {
792
927
  const ast = _parser.parse.call(void 0, content);
793
928
  let hasPatched = false;
794
929
  traverse(ast, {
795
- FunctionDeclaration(path8) {
796
- const node = path8.node;
797
- if (_optionalChain([node, 'access', _53 => _53.id, 'optionalAccess', _54 => _54.name]) !== "processTailwindFeatures" || node.body.body.length !== 1) {
930
+ FunctionDeclaration(path9) {
931
+ const node = path9.node;
932
+ if (_optionalChain([node, 'access', _58 => _58.id, 'optionalAccess', _59 => _59.name]) !== "processTailwindFeatures" || node.body.body.length !== 1) {
798
933
  return;
799
934
  }
800
935
  const [returnStatement3] = node.body.body;
@@ -825,10 +960,10 @@ function transformPostcssPlugin(content, { refProperty }) {
825
960
  const valueMember = t2.memberExpression(refIdentifier, t2.identifier("value"));
826
961
  let hasPatched = false;
827
962
  traverse(ast, {
828
- Program(path8) {
829
- const program = path8.node;
963
+ Program(path9) {
964
+ const program = path9.node;
830
965
  const index = program.body.findIndex((statement) => {
831
- return t2.isExpressionStatement(statement) && t2.isAssignmentExpression(statement.expression) && t2.isMemberExpression(statement.expression.left) && t2.isFunctionExpression(statement.expression.right) && _optionalChain([statement, 'access', _55 => _55.expression, 'access', _56 => _56.right, 'access', _57 => _57.id, 'optionalAccess', _58 => _58.name]) === "tailwindcss";
966
+ return t2.isExpressionStatement(statement) && t2.isAssignmentExpression(statement.expression) && t2.isMemberExpression(statement.expression.left) && t2.isFunctionExpression(statement.expression.right) && _optionalChain([statement, 'access', _60 => _60.expression, 'access', _61 => _61.right, 'access', _62 => _62.id, 'optionalAccess', _63 => _63.name]) === "tailwindcss";
832
967
  });
833
968
  if (index === -1) {
834
969
  return;
@@ -864,12 +999,12 @@ function transformPostcssPlugin(content, { refProperty }) {
864
999
  );
865
1000
  }
866
1001
  },
867
- FunctionExpression(path8) {
1002
+ FunctionExpression(path9) {
868
1003
  if (hasPatched) {
869
1004
  return;
870
1005
  }
871
- const fn = path8.node;
872
- if (_optionalChain([fn, 'access', _59 => _59.id, 'optionalAccess', _60 => _60.name]) !== "tailwindcss" || fn.body.body.length !== 1) {
1006
+ const fn = path9.node;
1007
+ if (_optionalChain([fn, 'access', _64 => _64.id, 'optionalAccess', _65 => _65.name]) !== "tailwindcss" || fn.body.body.length !== 1) {
873
1008
  return;
874
1009
  }
875
1010
  const [returnStatement3] = fn.body.body;
@@ -1034,21 +1169,21 @@ function updateLengthUnitsArray(content, options) {
1034
1169
  let arrayRef;
1035
1170
  let changed = false;
1036
1171
  traverse(ast, {
1037
- Identifier(path8) {
1038
- if (path8.node.name === variableName && t3.isVariableDeclarator(path8.parent) && t3.isArrayExpression(path8.parent.init)) {
1039
- arrayRef = path8.parent.init;
1172
+ Identifier(path9) {
1173
+ if (path9.node.name === variableName && t3.isVariableDeclarator(path9.parent) && t3.isArrayExpression(path9.parent.init)) {
1174
+ arrayRef = path9.parent.init;
1040
1175
  const existing = new Set(
1041
- path8.parent.init.elements.map((element) => t3.isStringLiteral(element) ? element.value : void 0).filter(Boolean)
1176
+ path9.parent.init.elements.map((element) => t3.isStringLiteral(element) ? element.value : void 0).filter(Boolean)
1042
1177
  );
1043
1178
  for (const unit of units) {
1044
1179
  if (!existing.has(unit)) {
1045
- path8.parent.init.elements = path8.parent.init.elements.map((element) => {
1180
+ path9.parent.init.elements = path9.parent.init.elements.map((element) => {
1046
1181
  if (t3.isStringLiteral(element)) {
1047
1182
  return t3.stringLiteral(element.value);
1048
1183
  }
1049
1184
  return element;
1050
1185
  });
1051
- path8.parent.init.elements.push(t3.stringLiteral(unit));
1186
+ path9.parent.init.elements.push(t3.stringLiteral(unit));
1052
1187
  changed = true;
1053
1188
  }
1054
1189
  }
@@ -1129,13 +1264,13 @@ function applyExtendLengthUnitsPatchV4(rootDir, options) {
1129
1264
  const { code, file, match } = item;
1130
1265
  const ast = _parser.parse.call(void 0, match[0], { sourceType: "unambiguous" });
1131
1266
  traverse(ast, {
1132
- ArrayExpression(path8) {
1267
+ ArrayExpression(path9) {
1133
1268
  for (const unit of opts.units) {
1134
- if (path8.node.elements.some((element) => t3.isStringLiteral(element) && element.value === unit)) {
1269
+ if (path9.node.elements.some((element) => t3.isStringLiteral(element) && element.value === unit)) {
1135
1270
  item.hasPatched = true;
1136
1271
  return;
1137
1272
  }
1138
- path8.node.elements.push(t3.stringLiteral(unit));
1273
+ path9.node.elements.push(t3.stringLiteral(unit));
1139
1274
  }
1140
1275
  }
1141
1276
  });
@@ -1177,7 +1312,7 @@ function applyTailwindPatches(context) {
1177
1312
  majorVersion
1178
1313
  });
1179
1314
  }
1180
- if (_optionalChain([options, 'access', _61 => _61.features, 'access', _62 => _62.extendLengthUnits, 'optionalAccess', _63 => _63.enabled])) {
1315
+ if (_optionalChain([options, 'access', _66 => _66.features, 'access', _67 => _67.extendLengthUnits, 'optionalAccess', _68 => _68.enabled])) {
1181
1316
  if (majorVersion === 3) {
1182
1317
  results.extendLengthUnits = applyExtendLengthUnitsPatchV3(
1183
1318
  packageInfo.rootPath,
@@ -1343,7 +1478,7 @@ var TailwindcssPatcher = (_class = class {
1343
1478
  return this.mergeWithCacheSync(set);
1344
1479
  }
1345
1480
  async extract(options) {
1346
- const shouldWrite = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _64 => _64.write]), () => ( this.options.output.enabled));
1481
+ const shouldWrite = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _69 => _69.write]), () => ( this.options.output.enabled));
1347
1482
  const classSet = await this.getClassSet();
1348
1483
  const classList = Array.from(classSet);
1349
1484
  const result = {
@@ -1370,6 +1505,22 @@ var TailwindcssPatcher = (_class = class {
1370
1505
  }
1371
1506
  // Backwards compatibility helper used by tests and API consumers.
1372
1507
  __init() {this.extractValidCandidates = exports.extractValidCandidates = extractValidCandidates}
1508
+ async collectContentTokens(options) {
1509
+ return extractProjectCandidatesWithPositions({
1510
+ cwd: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _70 => _70.cwd]), () => ( this.options.projectRoot)),
1511
+ sources: _nullishCoalesce(_nullishCoalesce(_optionalChain([options, 'optionalAccess', _71 => _71.sources]), () => ( _optionalChain([this, 'access', _72 => _72.options, 'access', _73 => _73.tailwind, 'access', _74 => _74.v4, 'optionalAccess', _75 => _75.sources]))), () => ( []))
1512
+ });
1513
+ }
1514
+ async collectContentTokensByFile(options) {
1515
+ const report = await this.collectContentTokens({
1516
+ cwd: _optionalChain([options, 'optionalAccess', _76 => _76.cwd]),
1517
+ sources: _optionalChain([options, 'optionalAccess', _77 => _77.sources])
1518
+ });
1519
+ return groupTokensByFile(report, {
1520
+ key: _optionalChain([options, 'optionalAccess', _78 => _78.key]),
1521
+ stripAbsolutePaths: _optionalChain([options, 'optionalAccess', _79 => _79.stripAbsolutePaths])
1522
+ });
1523
+ }
1373
1524
  }, _class);
1374
1525
 
1375
1526
 
@@ -1386,4 +1537,6 @@ var TailwindcssPatcher = (_class = class {
1386
1537
 
1387
1538
 
1388
1539
 
1389
- exports.logger_default = logger_default; exports.CacheStore = CacheStore; exports.extractRawCandidatesWithPositions = extractRawCandidatesWithPositions; exports.extractRawCandidates = extractRawCandidates; exports.extractValidCandidates = extractValidCandidates; exports.fromLegacyOptions = fromLegacyOptions; exports.fromUnifiedConfig = fromUnifiedConfig; exports.normalizeOptions = normalizeOptions; exports.collectClassesFromContexts = collectClassesFromContexts; exports.collectClassesFromTailwindV4 = collectClassesFromTailwindV4; exports.loadRuntimeContexts = loadRuntimeContexts; exports.runTailwindBuild = runTailwindBuild; exports.TailwindcssPatcher = TailwindcssPatcher;
1540
+
1541
+
1542
+ exports.logger_default = logger_default; exports.CacheStore = CacheStore; exports.extractRawCandidatesWithPositions = extractRawCandidatesWithPositions; exports.extractRawCandidates = extractRawCandidates; exports.extractValidCandidates = extractValidCandidates; exports.extractProjectCandidatesWithPositions = extractProjectCandidatesWithPositions; exports.groupTokensByFile = groupTokensByFile; exports.fromLegacyOptions = fromLegacyOptions; exports.fromUnifiedConfig = fromUnifiedConfig; exports.normalizeOptions = normalizeOptions; exports.collectClassesFromContexts = collectClassesFromContexts; exports.collectClassesFromTailwindV4 = collectClassesFromTailwindV4; exports.loadRuntimeContexts = loadRuntimeContexts; exports.runTailwindBuild = runTailwindBuild; exports.TailwindcssPatcher = TailwindcssPatcher;