@@ -44,6 +44,7 @@ interface TailwindV3Internals {
4444}
4545
4646interface TailwindV3IncrementalGenerateCacheEntry {
47+ context : TailwindV3Context
4748 seenCandidates : Set < string >
4849 classSet : Set < string >
4950 css : string
@@ -234,42 +235,6 @@ function createRuntimeReadyCacheKey(source: TailwindV3ResolvedSource, rootPath:
234235 ] . join ( '\0' )
235236}
236237
237- function isTailwindImport ( params : string , layer : string ) {
238- const trimmed = params . trim ( )
239- return new RegExp ( `^(?:url\\()?['"]tailwindcss/${ layer } (?:\\.css)?['"]\\)?(?:\\s|$)` ) . test ( trimmed )
240- }
241-
242- function createUtilitiesOnlyCss ( css : string ) {
243- try {
244- const root = postcss . parse ( css )
245- root . walkAtRules ( ( rule ) => {
246- if ( rule . name === 'tailwind' ) {
247- const layer = rule . params . trim ( )
248- if ( layer === 'base' || layer === 'components' ) {
249- rule . remove ( )
250- }
251- return
252- }
253- if ( rule . name === 'import' && ( isTailwindImport ( rule . params , 'base' ) || isTailwindImport ( rule . params , 'components' ) ) ) {
254- rule . remove ( )
255- return
256- }
257- if ( rule . name === 'layer' ) {
258- const layer = rule . params . trim ( )
259- if ( layer === 'base' || layer === 'components' ) {
260- rule . remove ( )
261- }
262- }
263- } )
264- return root . toString ( )
265- }
266- catch {
267- return css
268- . replace ( / @ t a i l w i n d \s + (?: b a s e | c o m p o n e n t s ) \s * ; / g, '' )
269- . replace ( / @ i m p o r t \s + (?: u r l \( ) ? [ ' " ] t a i l w i n d c s s \/ (?: b a s e | c o m p o n e n t s ) (?: \. c s s ) ? [ ' " ] [ ^ ; ] * ; / g, '' )
270- }
271- }
272-
273238function isDirectUtilitiesOnlyCss ( css : string ) {
274239 return css . replace ( / \s + / g, '' ) === '@tailwindutilities;'
275240}
@@ -304,8 +269,8 @@ function sortCandidates(candidates: Iterable<string>) {
304269 } )
305270}
306271
307- function appendDirectUtilityRules ( root : postcss . Root , context : TailwindV3Context ) {
308- const sortedRules = context . offsets . sort ( [ ... context . ruleCache ] )
272+ function appendUtilityRules ( root : postcss . Root , context : TailwindV3Context , rules : Array < [ unknown , postcss . Node ] > ) {
273+ const sortedRules = context . offsets . sort ( rules )
309274 for ( const [ sort , rule ] of sortedRules ) {
310275 const tailwindRaw = rule . raws . tailwind as { parentLayer ?: string } | undefined
311276 if ( sort . layer === 'utilities' || ( sort . layer === 'variants' && tailwindRaw ?. parentLayer === 'utilities' ) ) {
@@ -314,6 +279,10 @@ function appendDirectUtilityRules(root: postcss.Root, context: TailwindV3Context
314279 }
315280}
316281
282+ function appendDirectUtilityRules ( root : postcss . Root , context : TailwindV3Context ) {
283+ appendUtilityRules ( root , context , [ ...context . ruleCache ] )
284+ }
285+
317286function createRuntimeReadyPromise ( source : TailwindV3ResolvedSource ) {
318287 const patcher = createTailwindcssPatcher ( {
319288 basedir : source . cwd ,
@@ -397,6 +366,7 @@ export function createTailwindV3Engine(source: TailwindV3ResolvedSource): Tailwi
397366 return {
398367 css,
399368 rawCss,
369+ context,
400370 classSet,
401371 rawCandidates : collectCandidates ( options . candidates ) ,
402372 dependencies : [ ...dependencies ] ,
@@ -407,6 +377,35 @@ export function createTailwindV3Engine(source: TailwindV3ResolvedSource): Tailwi
407377 }
408378 }
409379
380+ async function generateIncrementalMissingUtilities (
381+ context : TailwindV3Context ,
382+ candidates : string [ ] ,
383+ target : TailwindV3GenerateTarget ,
384+ styleOptions : Partial < IStyleHandlerOptions > | undefined ,
385+ ) {
386+ tailwindInternals ??= loadTailwindV3Internals ( source )
387+ const internals = tailwindInternals
388+ const root = postcss . root ( )
389+ const result : TailwindV3ProcessResult = {
390+ css : '' ,
391+ messages : [ ] ,
392+ }
393+ const rules = internals . generateRules ( new Set ( sortCandidates ( candidates ) ) , context )
394+ appendUtilityRules ( root , context , rules )
395+ internals . resolveDefaultsAtRules ( context ) ( root , result )
396+ internals . collapseAdjacentRules ( context ) ( root , result )
397+ internals . collapseDuplicateDeclarations ( context ) ( root , result )
398+
399+ const rawCss = root . toString ( )
400+ const css = await transformTailwindV3CssByTarget ( rawCss , target , styleOptions )
401+ return {
402+ css,
403+ rawCss,
404+ classSet : collectClassSet ( context ) ,
405+ dependencies : collectDependencyMessages ( result ) ,
406+ }
407+ }
408+
410409 async function generateWithIncrementalCache ( options : TailwindV3GenerateOptions = { } ) {
411410 if ( ( options . sources ?. length ?? 0 ) > 0 ) {
412411 return generateOnce ( source , options )
@@ -432,14 +431,12 @@ export function createTailwindV3Engine(source: TailwindV3ResolvedSource): Tailwi
432431 }
433432 }
434433
435- const utilitySource = {
436- ...source ,
437- css : createUtilitiesOnlyCss ( source . css ) ,
438- }
439- const generated = await generateOnce ( utilitySource , {
440- ...options ,
441- candidates : missingCandidates ,
442- } )
434+ const generated = await generateIncrementalMissingUtilities (
435+ cached . context ,
436+ missingCandidates ,
437+ target ,
438+ options . styleOptions ,
439+ )
443440 for ( const candidate of missingCandidates ) {
444441 cached . seenCandidates . add ( candidate )
445442 }
@@ -464,6 +461,7 @@ export function createTailwindV3Engine(source: TailwindV3ResolvedSource): Tailwi
464461
465462 const generated = await generateOnce ( source , options )
466463 incrementalGenerateCache . set ( cacheKey , {
464+ context : generated . context ,
467465 seenCandidates : new Set ( requestedCandidates ) ,
468466 classSet : new Set ( generated . classSet ) ,
469467 css : generated . css ,
0 commit comments