tailwindcss-patch 9.4.1 → 9.4.2

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.
@@ -5,11 +5,12 @@ import type {
5
5
  TailwindTokenLocation,
6
6
  TailwindTokenReport,
7
7
  } from '../types'
8
+ import type { BareArbitraryValueOptions } from '../v4/bare-arbitrary-values'
8
9
  import { promises as fs } from 'node:fs'
9
10
  import process from 'node:process'
10
11
  import path from 'pathe'
11
12
  import {
12
- type BareArbitraryValueOptions,
13
+ extractBareArbitraryValueSourceCandidatesWithPositions,
13
14
  resolveBareArbitraryValueCandidate,
14
15
  } from '../v4/bare-arbitrary-values'
15
16
  import { extractTailwindV4InlineSourceCandidates, resolveValidTailwindV4Candidates } from '../v4/candidates'
@@ -59,6 +60,10 @@ export interface ExtractValidCandidatesOption {
59
60
  bareArbitraryValues?: boolean | BareArbitraryValueOptions
60
61
  }
61
62
 
63
+ export interface ExtractCandidateOptions {
64
+ bareArbitraryValues?: boolean | BareArbitraryValueOptions
65
+ }
66
+
62
67
  export interface ExtractSourceCandidate {
63
68
  rawCandidate: string
64
69
  start: number
@@ -75,7 +80,7 @@ const HTML_ATTRIBUTE_NAME_CANDIDATE_RE = /^(?:class|className|hover-class|hoverC
75
80
  const CSS_DIRECTIVE_CANDIDATE_RE = /^@(?:apply|tailwind|source|config|plugin|theme|utility|custom-variant|variant)$/
76
81
  const CSS_APPLY_IMPORTANT = '!important'
77
82
  const CSS_APPLY_RE = /@apply\s+([^;{}]+)/g
78
- const JS_LIKE_SOURCE_EXTENSION_RE = /^(?:[cm]?[jt]sx?)$/
83
+ const JS_LIKE_SOURCE_EXTENSION_RE = /^[cm]?[jt]sx?$/
79
84
  const MIXED_TEMPLATE_SOURCE_EXTENSION_RE = /^(?:vue|uvue|nvue|svelte|mpx)$/
80
85
  const CSS_LIKE_SOURCE_EXTENSION_RE = /^(?:css|wxss|acss|jxss|ttss|qss|tyss|scss|sass|less|styl|stylus)$/
81
86
  const SFC_SCRIPT_BLOCK_RE = /<script\b[^>]*>([\s\S]*?)<\/script>/gi
@@ -102,7 +107,7 @@ function isInsideHtmlTagText(content: string, candidate: ExtractSourceCandidate)
102
107
  return false
103
108
  }
104
109
  const nextOpen = content.indexOf('<', candidate.end)
105
- return nextOpen !== -1 && (nextOpen < content.indexOf('>', candidate.end) || content.indexOf('>', candidate.end) === -1)
110
+ return nextOpen !== -1 && (nextOpen < content.indexOf('>', candidate.end) || !content.includes('>', candidate.end))
106
111
  }
107
112
 
108
113
  function isCssDirectiveCandidate(candidate: string) {
@@ -223,7 +228,36 @@ function createLocalCandidate(candidate: ExtractSourceCandidateWithContext): Ext
223
228
  }
224
229
  }
225
230
 
226
- async function extractCssApplyCandidates(content: string, extension: string) {
231
+ function dedupeCandidatesWithPositions(candidates: ExtractSourceCandidate[]) {
232
+ const seen = new Set<string>()
233
+ return candidates.filter((candidate) => {
234
+ const key = `${candidate.start}:${candidate.end}:${candidate.rawCandidate}`
235
+ if (seen.has(key)) {
236
+ return false
237
+ }
238
+ seen.add(key)
239
+ return true
240
+ })
241
+ }
242
+
243
+ function createBareArbitraryValueCandidateContexts(
244
+ content: string,
245
+ extension: string,
246
+ offset: number,
247
+ options?: ExtractCandidateOptions,
248
+ ): ExtractSourceCandidateWithContext[] {
249
+ return extractBareArbitraryValueSourceCandidatesWithPositions(content, options?.bareArbitraryValues)
250
+ .map(candidate => ({
251
+ content,
252
+ extension,
253
+ localStart: candidate.start,
254
+ rawCandidate: candidate.rawCandidate,
255
+ start: candidate.start + offset,
256
+ end: candidate.end + offset,
257
+ }))
258
+ }
259
+
260
+ async function extractCssApplyCandidates(content: string, extension: string, options?: ExtractCandidateOptions) {
227
261
  const candidates: ExtractSourceCandidateWithContext[] = []
228
262
  CSS_APPLY_RE.lastIndex = 0
229
263
  let match = CSS_APPLY_RE.exec(content)
@@ -239,12 +273,13 @@ async function extractCssApplyCandidates(content: string, extension: string) {
239
273
  start: candidate.start + applyParamsStart,
240
274
  end: candidate.end + applyParamsStart,
241
275
  })))
276
+ candidates.push(...createBareArbitraryValueCandidateContexts(applyParams, 'html', applyParamsStart, options))
242
277
  match = CSS_APPLY_RE.exec(content)
243
278
  }
244
279
  return candidates
245
280
  }
246
281
 
247
- async function extractMixedSourceScriptCandidates(content: string) {
282
+ async function extractMixedSourceScriptCandidates(content: string, options?: ExtractCandidateOptions) {
248
283
  const candidates: ExtractSourceCandidateWithContext[] = []
249
284
  SFC_SCRIPT_BLOCK_RE.lastIndex = 0
250
285
  let match = SFC_SCRIPT_BLOCK_RE.exec(content)
@@ -260,6 +295,7 @@ async function extractMixedSourceScriptCandidates(content: string) {
260
295
  start: candidate.start + scriptStart,
261
296
  end: candidate.end + scriptStart,
262
297
  })))
298
+ candidates.push(...createBareArbitraryValueCandidateContexts(scriptContent, 'js', scriptStart, options))
263
299
  match = SFC_SCRIPT_BLOCK_RE.exec(content)
264
300
  }
265
301
  return candidates
@@ -278,26 +314,30 @@ function createCandidateCacheKey(
278
314
  export async function extractRawCandidatesWithPositions(
279
315
  content: string,
280
316
  extension: string = 'html',
317
+ options?: ExtractCandidateOptions,
281
318
  ): Promise<ExtractSourceCandidate[]> {
282
319
  const { Scanner } = await getOxideModule()
283
320
  const scanner = new Scanner({})
284
321
  const result = scanner.getCandidatesWithPositions({ content, extension })
285
322
 
286
- return result.map(({ candidate, position }) => ({
323
+ const candidates = result.map(({ candidate, position }) => ({
287
324
  rawCandidate: candidate,
288
325
  start: position,
289
326
  end: position + candidate.length,
290
327
  }))
328
+ candidates.push(...extractBareArbitraryValueSourceCandidatesWithPositions(content, options?.bareArbitraryValues))
329
+ return dedupeCandidatesWithPositions(candidates)
291
330
  }
292
331
 
293
332
  export async function extractSourceCandidatesWithPositions(
294
333
  content: string,
295
334
  extension: string = 'html',
335
+ options?: ExtractCandidateOptions,
296
336
  ): Promise<ExtractSourceCandidate[]> {
297
337
  const normalizedExtension = extension.replace(/^\./, '')
298
338
  const candidates: ExtractSourceCandidateWithContext[] = CSS_LIKE_SOURCE_EXTENSION_RE.test(normalizedExtension)
299
- ? await extractCssApplyCandidates(content, normalizedExtension)
300
- : (await extractRawCandidatesWithPositions(content, normalizedExtension))
339
+ ? await extractCssApplyCandidates(content, normalizedExtension, options)
340
+ : (await extractRawCandidatesWithPositions(content, normalizedExtension, options))
301
341
  .map(candidate => ({
302
342
  ...candidate,
303
343
  content,
@@ -305,7 +345,7 @@ export async function extractSourceCandidatesWithPositions(
305
345
  localStart: candidate.start,
306
346
  }))
307
347
  if (MIXED_TEMPLATE_SOURCE_EXTENSION_RE.test(normalizedExtension)) {
308
- candidates.push(...await extractMixedSourceScriptCandidates(content))
348
+ candidates.push(...await extractMixedSourceScriptCandidates(content, options))
309
349
  }
310
350
  const seen = new Set<string>()
311
351
  return candidates.filter((candidate) => {
@@ -324,18 +364,37 @@ export async function extractSourceCandidatesWithPositions(
324
364
  export async function extractSourceCandidates(
325
365
  content: string,
326
366
  extension: string = 'html',
367
+ options?: ExtractCandidateOptions,
327
368
  ): Promise<string[]> {
328
- const candidates = await extractSourceCandidatesWithPositions(content, extension)
369
+ const candidates = await extractSourceCandidatesWithPositions(content, extension, options)
329
370
  return [...new Set(candidates.map(candidate => candidate.rawCandidate))]
330
371
  }
331
372
 
332
373
  export async function extractRawCandidates(
333
374
  sources?: SourceEntry[],
375
+ options?: ExtractCandidateOptions,
334
376
  ): Promise<string[]> {
335
377
  const { Scanner } = await getOxideModule()
336
378
  const scanner = new Scanner(sources === undefined ? {} : { sources })
337
379
 
338
- return scanner.scan()
380
+ const candidates = new Set(scanner.scan())
381
+ if (options?.bareArbitraryValues !== undefined && options.bareArbitraryValues !== false) {
382
+ await Promise.all((scanner.files ?? []).map(async (file) => {
383
+ try {
384
+ const content = await fs.readFile(file, 'utf8')
385
+ const extension = toExtension(file)
386
+ for (const candidate of extractBareArbitraryValueSourceCandidatesWithPositions(content, options.bareArbitraryValues)) {
387
+ if (shouldKeepSourceCandidate(content, extension, candidate)) {
388
+ candidates.add(candidate.rawCandidate)
389
+ }
390
+ }
391
+ }
392
+ catch {
393
+ // 文件可能在扫描和读取之间被移除,保持与 Tailwind 原扫描结果一致。
394
+ }
395
+ }))
396
+ }
397
+ return [...candidates]
339
398
  }
340
399
 
341
400
  export async function extractValidCandidates(options?: ExtractValidCandidatesOption) {
@@ -370,7 +429,12 @@ export async function extractValidCandidates(options?: ExtractValidCandidatesOpt
370
429
  const candidateCache = designSystemCandidateCache.get(candidateCacheKey) ?? new Map<string, boolean>()
371
430
  designSystemCandidateCache.set(candidateCacheKey, candidateCache)
372
431
 
373
- const candidates = await extractRawCandidates(sources)
432
+ const candidates = await extractRawCandidates(
433
+ sources,
434
+ providedOptions.bareArbitraryValues === undefined
435
+ ? undefined
436
+ : { bareArbitraryValues: providedOptions.bareArbitraryValues },
437
+ )
374
438
  const inlineSources = extractTailwindV4InlineSourceCandidates(css)
375
439
  for (const candidate of inlineSources.included) {
376
440
  candidates.push(candidate)
package/src/public-api.ts CHANGED
@@ -2,6 +2,17 @@ import type { TailwindcssMangleConfig } from '@tailwindcss-mangle/config'
2
2
 
3
3
  export { TailwindcssPatcher } from './api/tailwindcss-patcher'
4
4
  export { CacheStore } from './cache/store'
5
+ export {
6
+ type ConfigFileMigrationEntry,
7
+ type ConfigFileMigrationReport,
8
+ migrateConfigFiles,
9
+ type MigrateConfigFilesOptions,
10
+ MIGRATION_REPORT_KIND,
11
+ MIGRATION_REPORT_SCHEMA_VERSION,
12
+ restoreConfigFiles,
13
+ type RestoreConfigFilesOptions,
14
+ type RestoreConfigFilesResult,
15
+ } from './commands/migrate-config'
5
16
  export {
6
17
  type TailwindcssPatchCliMountOptions,
7
18
  type TailwindcssPatchCliOptions,
@@ -22,29 +33,18 @@ export {
22
33
  type ValidateJsonFailurePayload,
23
34
  type ValidateJsonSuccessPayload,
24
35
  } from './commands/validate'
25
- export {
26
- type ConfigFileMigrationEntry,
27
- type ConfigFileMigrationReport,
28
- migrateConfigFiles,
29
- type MigrateConfigFilesOptions,
30
- MIGRATION_REPORT_KIND,
31
- MIGRATION_REPORT_SCHEMA_VERSION,
32
- restoreConfigFiles,
33
- type RestoreConfigFilesOptions,
34
- type RestoreConfigFilesResult,
35
- } from './commands/migrate-config'
36
36
  export { normalizeOptions } from './config'
37
37
  export type { TailwindCssPatchOptions } from './config'
38
38
  export {
39
39
  extractProjectCandidatesWithPositions,
40
40
  extractRawCandidates,
41
41
  extractRawCandidatesWithPositions,
42
+ type ExtractSourceCandidate,
42
43
  extractSourceCandidates,
43
44
  extractSourceCandidatesWithPositions,
44
45
  extractValidCandidates,
45
46
  groupTokensByFile,
46
47
  resolveProjectSourceFiles,
47
- type ExtractSourceCandidate,
48
48
  } from './extraction/candidate-extractor'
49
49
  export {
50
50
  isValidCandidateToken,
@@ -61,21 +61,28 @@ export {
61
61
  export { default as logger } from './logger'
62
62
  export * from './types'
63
63
  export {
64
+ canonicalizeBareArbitraryValueCandidates,
64
65
  createTailwindV4CompiledSourceEntries,
65
- createTailwindV4Engine,
66
66
  createTailwindV4DefaultIgnoreSources,
67
+ createTailwindV4Engine,
67
68
  createTailwindV4RootSources,
68
69
  createTailwindV4SourceEntryMatcher,
69
70
  createTailwindV4SourceExclusionMatcher,
71
+ escapeCssClassName,
70
72
  expandTailwindV4SourceEntries,
71
73
  expandTailwindV4SourceEntryBraces,
74
+ extractBareArbitraryValueSourceCandidates,
75
+ extractBareArbitraryValueSourceCandidatesWithPositions,
72
76
  isFileExcludedByTailwindV4SourceEntries,
73
77
  isFileMatchedByTailwindV4SourceEntries,
78
+ isBareArbitraryValuesEnabled,
74
79
  loadTailwindV4DesignSystem,
75
80
  mergeTailwindV4SourceEntries,
76
81
  normalizeTailwindV4ScannerSources,
77
82
  normalizeTailwindV4SourceEntries,
78
83
  resolveSourceScanPath,
84
+ replaceBareArbitraryValueSelectors,
85
+ resolveBareArbitraryValueCandidate,
79
86
  resolveTailwindV4Source,
80
87
  resolveTailwindV4SourceBaseCandidates,
81
88
  resolveTailwindV4SourceEntry,
@@ -10,6 +10,12 @@ export interface BareArbitraryValueResolveResult {
10
10
  canonicalCandidate: string
11
11
  }
12
12
 
13
+ export interface BareArbitraryValueSourceCandidate {
14
+ rawCandidate: string
15
+ start: number
16
+ end: number
17
+ }
18
+
13
19
  const DEFAULT_BARE_ARBITRARY_VALUE_UNITS = [
14
20
  '%',
15
21
  'px',
@@ -41,6 +47,8 @@ const DEFAULT_BARE_ARBITRARY_VALUE_UNITS = [
41
47
  const NUMBER_RE = /^-?(?:\d+|\d*\.\d+)$/
42
48
  const FUNCTION_VALUE_RE = /^[a-z_-][\w-]*\(/i
43
49
  const HEX_ESCAPE_RE = /^[\da-f]$/i
50
+ const ASPECT_RATIO_RE = /^\d+\/\d+$/
51
+ const ESCAPED_WHITESPACE_RE = /\\[nrt]/g
44
52
 
45
53
  function splitVariantPrefix(candidate: string) {
46
54
  let depth = 0
@@ -221,6 +229,10 @@ function normalizeBareArbitraryValueOptions(options: boolean | BareArbitraryValu
221
229
  }
222
230
  }
223
231
 
232
+ export function isBareArbitraryValuesEnabled(options: boolean | BareArbitraryValueOptions | undefined) {
233
+ return normalizeBareArbitraryValueOptions(options) !== undefined
234
+ }
235
+
224
236
  function normalizeEscapedValue(value: string) {
225
237
  let result = ''
226
238
  for (let index = 0; index < value.length; index++) {
@@ -276,13 +288,17 @@ function resolveValueWithUnit(body: string, units: string[]) {
276
288
  }
277
289
  }
278
290
 
279
- function resolveArbitraryValue(body: string, units: string[]) {
291
+ function resolveArbitraryValue(utility: string, body: string, units: string[]) {
280
292
  const value = normalizeEscapedValue(body)
281
293
  const withUnit = resolveValueWithUnit(value, units)
282
294
  if (withUnit) {
283
295
  return withUnit
284
296
  }
285
297
 
298
+ if (utility === 'aspect' && ASPECT_RATIO_RE.test(value)) {
299
+ return value
300
+ }
301
+
286
302
  if (isHexColorValue(value)) {
287
303
  return value
288
304
  }
@@ -292,6 +308,9 @@ function resolveArbitraryValue(body: string, units: string[]) {
292
308
  }
293
309
 
294
310
  if (FUNCTION_VALUE_RE.test(value) && value.endsWith(')') && isBalancedFunctionValue(value)) {
311
+ if (utility === 'text' && /^var\(/i.test(value)) {
312
+ return `color:${value}`
313
+ }
295
314
  return value
296
315
  }
297
316
  }
@@ -339,7 +358,7 @@ function resolveUtilityAndValue(body: string, units: string[]) {
339
358
  continue
340
359
  }
341
360
 
342
- const value = resolveArbitraryValue(rawValue, units)
361
+ const value = resolveArbitraryValue(utility, rawValue, units)
343
362
  if (value) {
344
363
  return {
345
364
  utility,
@@ -380,6 +399,112 @@ export function resolveBareArbitraryValueCandidate(
380
399
  }
381
400
  }
382
401
 
402
+ function isBareArbitrarySourceSplitter(char: string) {
403
+ return /\s/.test(char)
404
+ }
405
+
406
+ function isQuoteBoundary(content: string, start: number, index: number) {
407
+ const tokenPrefix = content.slice(start, index)
408
+ return tokenPrefix.length === 0 || !tokenPrefix.endsWith('-')
409
+ }
410
+
411
+ function trimBareArbitrarySourceToken(token: string, start: number) {
412
+ let nextToken = token
413
+ let nextStart = start
414
+ while (nextToken.length > 0 && /^[<{([]$/.test(nextToken[0]!)) {
415
+ nextToken = nextToken.slice(1)
416
+ nextStart++
417
+ }
418
+ while (nextToken.length > 0 && /^[>\],;]$/.test(nextToken[nextToken.length - 1]!)) {
419
+ nextToken = nextToken.slice(0, -1)
420
+ }
421
+ return {
422
+ token: nextToken,
423
+ start: nextStart,
424
+ }
425
+ }
426
+
427
+ function pushBareArbitrarySourceCandidate(
428
+ result: BareArbitraryValueSourceCandidate[],
429
+ token: string,
430
+ start: number,
431
+ options: boolean | BareArbitraryValueOptions | undefined,
432
+ ) {
433
+ const trimmed = trimBareArbitrarySourceToken(token, start)
434
+ if (!trimmed.token || trimmed.token.includes('=') || trimmed.token.includes('[') || trimmed.token.includes(']')) {
435
+ return
436
+ }
437
+ if (!resolveBareArbitraryValueCandidate(trimmed.token, options)) {
438
+ return
439
+ }
440
+ result.push({
441
+ rawCandidate: trimmed.token,
442
+ start: trimmed.start,
443
+ end: trimmed.start + trimmed.token.length,
444
+ })
445
+ }
446
+
447
+ export function extractBareArbitraryValueSourceCandidatesWithPositions(
448
+ content: string,
449
+ options?: boolean | BareArbitraryValueOptions,
450
+ ): BareArbitraryValueSourceCandidate[] {
451
+ if (!isBareArbitraryValuesEnabled(options)) {
452
+ return []
453
+ }
454
+
455
+ const normalized = content.includes('\\') ? content.replace(ESCAPED_WHITESPACE_RE, ' ') : content
456
+ const result: BareArbitraryValueSourceCandidate[] = []
457
+ let depth = 0
458
+ let quote: string | undefined
459
+ let start = 0
460
+
461
+ for (let index = 0; index < normalized.length; index++) {
462
+ const char = normalized[index]
463
+ if (char === undefined) {
464
+ continue
465
+ }
466
+ if (char === '\\') {
467
+ index++
468
+ continue
469
+ }
470
+
471
+ if (quote) {
472
+ if (char === quote) {
473
+ quote = undefined
474
+ }
475
+ }
476
+ else if ((char === '"' || char === '\'' || char === '`') && !isQuoteBoundary(normalized, start, index)) {
477
+ quote = char
478
+ }
479
+ else if (char === '(' || char === '{' || char === '[') {
480
+ depth++
481
+ }
482
+ else if (char === ')' || char === '}' || char === ']') {
483
+ depth = Math.max(0, depth - 1)
484
+ }
485
+
486
+ if (!isBareArbitrarySourceSplitter(char) && !((char === '"' || char === '\'' || char === '`') && depth === 0 && isQuoteBoundary(normalized, start, index))) {
487
+ continue
488
+ }
489
+
490
+ pushBareArbitrarySourceCandidate(result, normalized.slice(start, index), start, options)
491
+ start = index + 1
492
+ }
493
+
494
+ pushBareArbitrarySourceCandidate(result, normalized.slice(start), start, options)
495
+ return result
496
+ }
497
+
498
+ export function extractBareArbitraryValueSourceCandidates(
499
+ content: string,
500
+ options?: boolean | BareArbitraryValueOptions,
501
+ ) {
502
+ return [...new Set(
503
+ extractBareArbitraryValueSourceCandidatesWithPositions(content, options)
504
+ .map(candidate => candidate.rawCandidate),
505
+ )]
506
+ }
507
+
383
508
  // Based on the CSS.escape algorithm, scoped to class selector escaping.
384
509
  export function escapeCssClassName(value: string) {
385
510
  let result = ''
package/src/v4/engine.ts CHANGED
@@ -37,13 +37,16 @@ async function collectRawCandidates(
37
37
  compiledSources: TailwindV4SourcePattern[] = [],
38
38
  ) {
39
39
  const rawCandidates = new Set<string>()
40
+ const extractOptions = options?.bareArbitraryValues === undefined
41
+ ? undefined
42
+ : { bareArbitraryValues: options.bareArbitraryValues }
40
43
 
41
44
  for (const candidate of options?.candidates ?? []) {
42
45
  rawCandidates.add(candidate)
43
46
  }
44
47
 
45
48
  for (const candidateSource of options?.sources ?? []) {
46
- const candidates = await extractRawCandidatesWithPositions(candidateSource.content, candidateSource.extension)
49
+ const candidates = await extractRawCandidatesWithPositions(candidateSource.content, candidateSource.extension, extractOptions)
47
50
  for (const candidate of candidates) {
48
51
  rawCandidates.add(candidate.rawCandidate)
49
52
  }
@@ -51,7 +54,7 @@ async function collectRawCandidates(
51
54
 
52
55
  const filesystemSources = resolveScanSources(options, source, compiledRoot, compiledSources)
53
56
  if (filesystemSources.length > 0) {
54
- for (const candidate of await extractRawCandidates(filesystemSources)) {
57
+ for (const candidate of await extractRawCandidates(filesystemSources, extractOptions)) {
55
58
  rawCandidates.add(candidate)
56
59
  }
57
60
  }
package/src/v4/index.ts CHANGED
@@ -1,13 +1,27 @@
1
1
  export {
2
+ canonicalizeBareArbitraryValueCandidates,
2
3
  extractTailwindV4InlineSourceCandidates,
4
+ replaceBareArbitraryValueSelectors,
3
5
  resolveValidTailwindV4Candidates,
4
6
  } from './candidates'
7
+ export {
8
+ escapeCssClassName,
9
+ extractBareArbitraryValueSourceCandidates,
10
+ extractBareArbitraryValueSourceCandidatesWithPositions,
11
+ isBareArbitraryValuesEnabled,
12
+ resolveBareArbitraryValueCandidate,
13
+ } from './bare-arbitrary-values'
5
14
  export { createTailwindV4Engine } from './engine'
6
15
  export {
7
16
  compileTailwindV4Source,
8
17
  loadTailwindV4DesignSystem,
9
18
  loadTailwindV4NodeModule,
10
19
  } from './node-adapter'
20
+ export {
21
+ resolveTailwindV4Source,
22
+ resolveTailwindV4SourceFromPatchOptions,
23
+ tailwindV4SourceOptionsFromPatchOptions,
24
+ } from './source'
11
25
  export {
12
26
  createTailwindV4CompiledSourceEntries,
13
27
  createTailwindV4DefaultIgnoreSources,
@@ -29,11 +43,6 @@ export {
29
43
  TAILWIND_V4_IGNORED_EXTENSIONS,
30
44
  TAILWIND_V4_IGNORED_FILES,
31
45
  } from './source-scan'
32
- export {
33
- resolveTailwindV4Source,
34
- resolveTailwindV4SourceFromPatchOptions,
35
- tailwindV4SourceOptionsFromPatchOptions,
36
- } from './source'
37
46
  export type {
38
47
  TailwindV4CandidateSource,
39
48
  TailwindV4CompiledSourceRoot,
@@ -1,7 +1,7 @@
1
1
  import type {
2
+ TailwindV4CompiledSourceRoot,
2
3
  TailwindV4DesignSystem,
3
4
  TailwindV4ResolvedSource,
4
- TailwindV4CompiledSourceRoot,
5
5
  TailwindV4SourcePattern,
6
6
  } from './types'
7
7
  import { createRequire } from 'node:module'
@@ -3,8 +3,8 @@ import type { TailwindV4CompiledSourceRoot, TailwindV4SourcePattern } from './ty
3
3
  import { realpathSync } from 'node:fs'
4
4
  import { stat } from 'node:fs/promises'
5
5
  import process from 'node:process'
6
- import path from 'pathe'
7
6
  import micromatch from 'micromatch'
7
+ import path from 'pathe'
8
8
 
9
9
  export const TAILWIND_V4_IGNORED_CONTENT_DIRS = [
10
10
  '.git',