tailwindcss 0.0.0-insiders.fc6c27d → 0.0.0-insiders.fe08e91

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/CHANGELOG.md CHANGED
@@ -7,7 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
- - Nothing yet!
10
+ ### Fixed
11
+
12
+ - Allow use of falsy values in theme config ([#6917](https://github.com/tailwindlabs/tailwindcss/pull/6917))
13
+ - Ensure we can apply classes that are grouped with non-class selectors ([#6922](https://github.com/tailwindlabs/tailwindcss/pull/6922))
14
+ - Improve standalone CLI compatibility on Linux by switching to the `linuxstatic` build target ([#6914](https://github.com/tailwindlabs/tailwindcss/pull/6914))
15
+ - Ensure `@apply` works consistently with or without `@layer` ([#6938](https://github.com/tailwindlabs/tailwindcss/pull/6938))
11
16
 
12
17
  ## [3.0.11] - 2022-01-05
13
18
 
@@ -75,45 +75,6 @@ function extractApplyCandidates(params) {
75
75
  false
76
76
  ];
77
77
  }
78
- function partitionApplyParents(root) {
79
- let applyParents = new Set();
80
- root.walkAtRules('apply', (rule)=>{
81
- applyParents.add(rule.parent);
82
- });
83
- for (let rule1 of applyParents){
84
- let nodeGroups = [];
85
- let lastGroup = [];
86
- for (let node of rule1.nodes){
87
- if (node.type === 'atrule' && node.name === 'apply') {
88
- if (lastGroup.length > 0) {
89
- nodeGroups.push(lastGroup);
90
- lastGroup = [];
91
- }
92
- nodeGroups.push([
93
- node
94
- ]);
95
- } else {
96
- lastGroup.push(node);
97
- }
98
- }
99
- if (lastGroup.length > 0) {
100
- nodeGroups.push(lastGroup);
101
- }
102
- if (nodeGroups.length === 1) {
103
- continue;
104
- }
105
- for (let group of [
106
- ...nodeGroups
107
- ].reverse()){
108
- let newParent = rule1.clone({
109
- nodes: []
110
- });
111
- newParent.append(group);
112
- rule1.after(newParent);
113
- }
114
- rule1.remove();
115
- }
116
- }
117
78
  function processApply(root, context) {
118
79
  let applyCandidates = new Set();
119
80
  // Collect all @apply rules and candidates
@@ -311,7 +272,6 @@ function processApply(root, context) {
311
272
  }
312
273
  function expandApplyAtRules(context) {
313
274
  return (root)=>{
314
- partitionApplyParents(root);
315
275
  processApply(root, context);
316
276
  };
317
277
  }
@@ -52,6 +52,55 @@ function _interopRequireWildcard(obj) {
52
52
  return newObj;
53
53
  }
54
54
  }
55
+ function partitionRules(root) {
56
+ if (!root.walkAtRules) return [
57
+ root
58
+ ];
59
+ let applyParents = new Set();
60
+ let rules = [];
61
+ root.walkAtRules('apply', (rule)=>{
62
+ applyParents.add(rule.parent);
63
+ });
64
+ if (applyParents.size === 0) {
65
+ rules.push(root);
66
+ }
67
+ for (let rule1 of applyParents){
68
+ let nodeGroups = [];
69
+ let lastGroup = [];
70
+ for (let node of rule1.nodes){
71
+ if (node.type === 'atrule' && node.name === 'apply') {
72
+ if (lastGroup.length > 0) {
73
+ nodeGroups.push(lastGroup);
74
+ lastGroup = [];
75
+ }
76
+ nodeGroups.push([
77
+ node
78
+ ]);
79
+ } else {
80
+ lastGroup.push(node);
81
+ }
82
+ }
83
+ if (lastGroup.length > 0) {
84
+ nodeGroups.push(lastGroup);
85
+ }
86
+ if (nodeGroups.length === 1) {
87
+ rules.push(rule1);
88
+ continue;
89
+ }
90
+ for (let group of [
91
+ ...nodeGroups
92
+ ].reverse()){
93
+ let clone = rule1.clone({
94
+ nodes: []
95
+ });
96
+ clone.append(group);
97
+ rules.unshift(clone);
98
+ rule1.after(clone);
99
+ }
100
+ rule1.remove();
101
+ }
102
+ return rules;
103
+ }
55
104
  function parseVariantFormatString(input) {
56
105
  if (input.includes('{')) {
57
106
  if (!isBalanced(input)) throw new Error(`Your { and } are unbalanced.`);
@@ -112,44 +161,49 @@ function getClasses(selector) {
112
161
  });
113
162
  return parser.transformSync(selector);
114
163
  }
115
- function extractCandidates(node) {
164
+ function extractCandidates(node, state = {
165
+ containsNonOnDemandable: false
166
+ }, depth = 0) {
116
167
  let classes = [];
168
+ // Handle normal rules
117
169
  if (node.type === 'rule') {
118
170
  for (let selector of node.selectors){
119
171
  let classCandidates = getClasses(selector);
120
172
  // At least one of the selectors contains non-"on-demandable" candidates.
121
- if (classCandidates.length === 0) return [];
122
- classes = [
123
- ...classes,
124
- ...classCandidates
125
- ];
173
+ if (classCandidates.length === 0) {
174
+ state.containsNonOnDemandable = true;
175
+ }
176
+ for (let classCandidate of classCandidates){
177
+ classes.push(classCandidate);
178
+ }
126
179
  }
127
- return classes;
128
- }
129
- if (node.type === 'atrule') {
180
+ } else if (node.type === 'atrule') {
130
181
  node.walkRules((rule)=>{
131
- classes = [
132
- ...classes,
133
- ...rule.selectors.flatMap((selector)=>getClasses(selector)
134
- )
135
- ];
182
+ for (let classCandidate of rule.selectors.flatMap((selector)=>getClasses(selector, state, depth + 1)
183
+ )){
184
+ classes.push(classCandidate);
185
+ }
136
186
  });
137
187
  }
188
+ if (depth === 0) {
189
+ return [
190
+ state.containsNonOnDemandable || classes.length === 0,
191
+ classes
192
+ ];
193
+ }
138
194
  return classes;
139
195
  }
140
196
  function withIdentifiers(styles) {
141
197
  return parseStyles(styles).flatMap((node)=>{
142
198
  let nodeMap = new Map();
143
- let candidates = extractCandidates(node);
144
- // If this isn't "on-demandable", assign it a universal candidate.
145
- if (candidates.length === 0) {
146
- return [
147
- [
148
- '*',
149
- node
150
- ]
151
- ];
199
+ let [containsNonOnDemandableSelectors, candidates] = extractCandidates(node);
200
+ // If this isn't "on-demandable", assign it a universal candidate to always include it.
201
+ if (containsNonOnDemandableSelectors) {
202
+ candidates.unshift('*');
152
203
  }
204
+ // However, it could be that it also contains "on-demandable" candidates.
205
+ // E.g.: `span, .foo {}`, in that case it should still be possible to use
206
+ // `@apply foo` for example.
153
207
  return candidates.map((c)=>{
154
208
  if (!nodeMap.has(node)) {
155
209
  nodeMap.set(node, node);
@@ -240,35 +294,37 @@ function buildPluginApi(tailwindConfig, context, { variantList , variantMap , of
240
294
  return [];
241
295
  },
242
296
  addUserCss (userCss) {
243
- for (let [identifier, rule] of withIdentifiers(userCss)){
297
+ for (let [identifier, rule2] of withIdentifiers(userCss)){
244
298
  let offset = offsets.user++;
245
299
  if (!context.candidateRuleMap.has(identifier)) {
246
300
  context.candidateRuleMap.set(identifier, []);
247
301
  }
248
- context.candidateRuleMap.get(identifier).push([
249
- {
250
- sort: offset,
251
- layer: 'user'
252
- },
253
- rule
254
- ]);
302
+ context.candidateRuleMap.get(identifier).push(...partitionRules(rule2).map((rule)=>[
303
+ {
304
+ sort: offset,
305
+ layer: 'user'
306
+ },
307
+ rule
308
+ ]
309
+ ));
255
310
  }
256
311
  },
257
312
  addBase (base) {
258
- for (let [identifier, rule] of withIdentifiers(base)){
313
+ for (let [identifier, rule3] of withIdentifiers(base)){
259
314
  let prefixedIdentifier = prefixIdentifier(identifier, {
260
315
  });
261
316
  let offset = offsets.base++;
262
317
  if (!context.candidateRuleMap.has(prefixedIdentifier)) {
263
318
  context.candidateRuleMap.set(prefixedIdentifier, []);
264
319
  }
265
- context.candidateRuleMap.get(prefixedIdentifier).push([
266
- {
267
- sort: offset,
268
- layer: 'base'
269
- },
270
- rule
271
- ]);
320
+ context.candidateRuleMap.get(prefixedIdentifier).push(...partitionRules(rule3).map((rule)=>[
321
+ {
322
+ sort: offset,
323
+ layer: 'base'
324
+ },
325
+ rule
326
+ ]
327
+ ));
272
328
  }
273
329
  },
274
330
  /**
@@ -278,20 +334,20 @@ function buildPluginApi(tailwindConfig, context, { variantList , variantMap , of
278
334
  const groups = {
279
335
  [`@defaults ${group}`]: declarations
280
336
  };
281
- for (let [identifier, rule] of withIdentifiers(groups)){
337
+ for (let [identifier, rule4] of withIdentifiers(groups)){
282
338
  let prefixedIdentifier = prefixIdentifier(identifier, {
283
339
  });
284
- let offset = offsets.base++;
285
340
  if (!context.candidateRuleMap.has(prefixedIdentifier)) {
286
341
  context.candidateRuleMap.set(prefixedIdentifier, []);
287
342
  }
288
- context.candidateRuleMap.get(prefixedIdentifier).push([
289
- {
290
- sort: offset,
291
- layer: 'defaults'
292
- },
293
- rule
294
- ]);
343
+ context.candidateRuleMap.get(prefixedIdentifier).push(...partitionRules(rule4).map((rule)=>[
344
+ {
345
+ sort: offsets.base++,
346
+ layer: 'defaults'
347
+ },
348
+ rule,
349
+ ]
350
+ ));
295
351
  }
296
352
  },
297
353
  addComponents (components, options) {
@@ -302,21 +358,21 @@ function buildPluginApi(tailwindConfig, context, { variantList , variantMap , of
302
358
  options = Object.assign({
303
359
  }, defaultOptions, Array.isArray(options) ? {
304
360
  } : options);
305
- for (let [identifier, rule] of withIdentifiers(components)){
361
+ for (let [identifier, rule5] of withIdentifiers(components)){
306
362
  let prefixedIdentifier = prefixIdentifier(identifier, options);
307
- let offset = offsets.components++;
308
363
  classList.add(prefixedIdentifier);
309
364
  if (!context.candidateRuleMap.has(prefixedIdentifier)) {
310
365
  context.candidateRuleMap.set(prefixedIdentifier, []);
311
366
  }
312
- context.candidateRuleMap.get(prefixedIdentifier).push([
313
- {
314
- sort: offset,
315
- layer: 'components',
316
- options
317
- },
318
- rule
319
- ]);
367
+ context.candidateRuleMap.get(prefixedIdentifier).push(...partitionRules(rule5).map((rule)=>[
368
+ {
369
+ sort: offsets.components++,
370
+ layer: 'components',
371
+ options
372
+ },
373
+ rule,
374
+ ]
375
+ ));
320
376
  }
321
377
  },
322
378
  addUtilities (utilities, options) {
@@ -327,21 +383,21 @@ function buildPluginApi(tailwindConfig, context, { variantList , variantMap , of
327
383
  options = Object.assign({
328
384
  }, defaultOptions, Array.isArray(options) ? {
329
385
  } : options);
330
- for (let [identifier, rule] of withIdentifiers(utilities)){
386
+ for (let [identifier, rule6] of withIdentifiers(utilities)){
331
387
  let prefixedIdentifier = prefixIdentifier(identifier, options);
332
- let offset = offsets.utilities++;
333
388
  classList.add(prefixedIdentifier);
334
389
  if (!context.candidateRuleMap.has(prefixedIdentifier)) {
335
390
  context.candidateRuleMap.set(prefixedIdentifier, []);
336
391
  }
337
- context.candidateRuleMap.get(prefixedIdentifier).push([
338
- {
339
- sort: offset,
340
- layer: 'utilities',
341
- options
342
- },
343
- rule
344
- ]);
392
+ context.candidateRuleMap.get(prefixedIdentifier).push(...partitionRules(rule6).map((rule)=>[
393
+ {
394
+ sort: offsets.utilities++,
395
+ layer: 'utilities',
396
+ options
397
+ },
398
+ rule,
399
+ ]
400
+ ));
345
401
  }
346
402
  },
347
403
  matchUtilities: function(utilities, options) {
@@ -22,6 +22,7 @@ function _interopRequireDefault(obj) {
22
22
  function processTailwindFeatures(setupContext) {
23
23
  return function(root, result) {
24
24
  let { tailwindDirectives , applyDirectives } = (0, _normalizeTailwindDirectives).default(root);
25
+ (0, _detectNesting).default()(root, result);
25
26
  let context = setupContext({
26
27
  tailwindDirectives,
27
28
  applyDirectives,
@@ -40,7 +41,6 @@ function processTailwindFeatures(setupContext) {
40
41
  throw new Error("The '-' character cannot be used as a custom separator in JIT mode due to parsing ambiguity. Please use another character like '_' instead.");
41
42
  }
42
43
  (0, _featureFlags).issueFlagNotices(context.tailwindConfig);
43
- (0, _detectNesting).default(context)(root, result);
44
44
  (0, _expandTailwindAtRules).default(context)(root, result);
45
45
  (0, _expandApplyAtRules).default(context)(root, result);
46
46
  (0, _evaluateTailwindFunctions).default(context)(root, result);
@@ -177,7 +177,7 @@ function coerceValue(types, modifier, options, tailwindConfig) {
177
177
  let result = typeMap[type](modifier, options, {
178
178
  tailwindConfig
179
179
  });
180
- if (result) return [
180
+ if (result !== undefined) return [
181
181
  result,
182
182
  type
183
183
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tailwindcss",
3
- "version": "0.0.0-insiders.fc6c27d",
3
+ "version": "0.0.0-insiders.fe08e91",
4
4
  "description": "A utility-first CSS framework for rapidly building custom user interfaces.",
5
5
  "license": "MIT",
6
6
  "main": "lib/index.js",
@@ -82,7 +82,7 @@
82
82
  "postcss-js": "^4.0.0",
83
83
  "postcss-load-config": "^3.1.0",
84
84
  "postcss-nested": "5.0.6",
85
- "postcss-selector-parser": "^6.0.7",
85
+ "postcss-selector-parser": "^6.0.8",
86
86
  "postcss-value-parser": "^4.2.0",
87
87
  "quick-lru": "^5.1.1",
88
88
  "resolve": "^1.20.0"
@@ -72,47 +72,6 @@ function extractApplyCandidates(params) {
72
72
  return [candidates, false]
73
73
  }
74
74
 
75
- function partitionApplyParents(root) {
76
- let applyParents = new Set()
77
-
78
- root.walkAtRules('apply', (rule) => {
79
- applyParents.add(rule.parent)
80
- })
81
-
82
- for (let rule of applyParents) {
83
- let nodeGroups = []
84
- let lastGroup = []
85
-
86
- for (let node of rule.nodes) {
87
- if (node.type === 'atrule' && node.name === 'apply') {
88
- if (lastGroup.length > 0) {
89
- nodeGroups.push(lastGroup)
90
- lastGroup = []
91
- }
92
- nodeGroups.push([node])
93
- } else {
94
- lastGroup.push(node)
95
- }
96
- }
97
-
98
- if (lastGroup.length > 0) {
99
- nodeGroups.push(lastGroup)
100
- }
101
-
102
- if (nodeGroups.length === 1) {
103
- continue
104
- }
105
-
106
- for (let group of [...nodeGroups].reverse()) {
107
- let newParent = rule.clone({ nodes: [] })
108
- newParent.append(group)
109
- rule.after(newParent)
110
- }
111
-
112
- rule.remove()
113
- }
114
- }
115
-
116
75
  function processApply(root, context) {
117
76
  let applyCandidates = new Set()
118
77
 
@@ -343,7 +302,6 @@ function processApply(root, context) {
343
302
 
344
303
  export default function expandApplyAtRules(context) {
345
304
  return (root) => {
346
- partitionApplyParents(root)
347
305
  processApply(root, context)
348
306
  }
349
307
  }
@@ -20,6 +20,58 @@ import log from '../util/log'
20
20
  import negateValue from '../util/negateValue'
21
21
  import isValidArbitraryValue from '../util/isValidArbitraryValue'
22
22
 
23
+ function partitionRules(root) {
24
+ if (!root.walkAtRules) return [root]
25
+
26
+ let applyParents = new Set()
27
+ let rules = []
28
+
29
+ root.walkAtRules('apply', (rule) => {
30
+ applyParents.add(rule.parent)
31
+ })
32
+
33
+ if (applyParents.size === 0) {
34
+ rules.push(root)
35
+ }
36
+
37
+ for (let rule of applyParents) {
38
+ let nodeGroups = []
39
+ let lastGroup = []
40
+
41
+ for (let node of rule.nodes) {
42
+ if (node.type === 'atrule' && node.name === 'apply') {
43
+ if (lastGroup.length > 0) {
44
+ nodeGroups.push(lastGroup)
45
+ lastGroup = []
46
+ }
47
+ nodeGroups.push([node])
48
+ } else {
49
+ lastGroup.push(node)
50
+ }
51
+ }
52
+
53
+ if (lastGroup.length > 0) {
54
+ nodeGroups.push(lastGroup)
55
+ }
56
+
57
+ if (nodeGroups.length === 1) {
58
+ rules.push(rule)
59
+ continue
60
+ }
61
+
62
+ for (let group of [...nodeGroups].reverse()) {
63
+ let clone = rule.clone({ nodes: [] })
64
+ clone.append(group)
65
+ rules.unshift(clone)
66
+ rule.after(clone)
67
+ }
68
+
69
+ rule.remove()
70
+ }
71
+
72
+ return rules
73
+ }
74
+
23
75
  function parseVariantFormatString(input) {
24
76
  if (input.includes('{')) {
25
77
  if (!isBalanced(input)) throw new Error(`Your { and } are unbalanced.`)
@@ -89,39 +141,55 @@ function getClasses(selector) {
89
141
  return parser.transformSync(selector)
90
142
  }
91
143
 
92
- function extractCandidates(node) {
144
+ function extractCandidates(node, state = { containsNonOnDemandable: false }, depth = 0) {
93
145
  let classes = []
94
146
 
147
+ // Handle normal rules
95
148
  if (node.type === 'rule') {
96
149
  for (let selector of node.selectors) {
97
150
  let classCandidates = getClasses(selector)
98
151
  // At least one of the selectors contains non-"on-demandable" candidates.
99
- if (classCandidates.length === 0) return []
152
+ if (classCandidates.length === 0) {
153
+ state.containsNonOnDemandable = true
154
+ }
100
155
 
101
- classes = [...classes, ...classCandidates]
156
+ for (let classCandidate of classCandidates) {
157
+ classes.push(classCandidate)
158
+ }
102
159
  }
103
- return classes
104
160
  }
105
161
 
106
- if (node.type === 'atrule') {
162
+ // Handle at-rules (which contains nested rules)
163
+ else if (node.type === 'atrule') {
107
164
  node.walkRules((rule) => {
108
- classes = [...classes, ...rule.selectors.flatMap((selector) => getClasses(selector))]
165
+ for (let classCandidate of rule.selectors.flatMap((selector) =>
166
+ getClasses(selector, state, depth + 1)
167
+ )) {
168
+ classes.push(classCandidate)
169
+ }
109
170
  })
110
171
  }
111
172
 
173
+ if (depth === 0) {
174
+ return [state.containsNonOnDemandable || classes.length === 0, classes]
175
+ }
176
+
112
177
  return classes
113
178
  }
114
179
 
115
180
  function withIdentifiers(styles) {
116
181
  return parseStyles(styles).flatMap((node) => {
117
182
  let nodeMap = new Map()
118
- let candidates = extractCandidates(node)
183
+ let [containsNonOnDemandableSelectors, candidates] = extractCandidates(node)
119
184
 
120
- // If this isn't "on-demandable", assign it a universal candidate.
121
- if (candidates.length === 0) {
122
- return [['*', node]]
185
+ // If this isn't "on-demandable", assign it a universal candidate to always include it.
186
+ if (containsNonOnDemandableSelectors) {
187
+ candidates.unshift('*')
123
188
  }
124
189
 
190
+ // However, it could be that it also contains "on-demandable" candidates.
191
+ // E.g.: `span, .foo {}`, in that case it should still be possible to use
192
+ // `@apply foo` for example.
125
193
  return candidates.map((c) => {
126
194
  if (!nodeMap.has(node)) {
127
195
  nodeMap.set(node, node)
@@ -216,7 +284,9 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
216
284
  context.candidateRuleMap.set(identifier, [])
217
285
  }
218
286
 
219
- context.candidateRuleMap.get(identifier).push([{ sort: offset, layer: 'user' }, rule])
287
+ context.candidateRuleMap
288
+ .get(identifier)
289
+ .push(...partitionRules(rule).map((rule) => [{ sort: offset, layer: 'user' }, rule]))
220
290
  }
221
291
  },
222
292
  addBase(base) {
@@ -230,7 +300,7 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
230
300
 
231
301
  context.candidateRuleMap
232
302
  .get(prefixedIdentifier)
233
- .push([{ sort: offset, layer: 'base' }, rule])
303
+ .push(...partitionRules(rule).map((rule) => [{ sort: offset, layer: 'base' }, rule]))
234
304
  }
235
305
  },
236
306
  /**
@@ -244,7 +314,6 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
244
314
 
245
315
  for (let [identifier, rule] of withIdentifiers(groups)) {
246
316
  let prefixedIdentifier = prefixIdentifier(identifier, {})
247
- let offset = offsets.base++
248
317
 
249
318
  if (!context.candidateRuleMap.has(prefixedIdentifier)) {
250
319
  context.candidateRuleMap.set(prefixedIdentifier, [])
@@ -252,7 +321,12 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
252
321
 
253
322
  context.candidateRuleMap
254
323
  .get(prefixedIdentifier)
255
- .push([{ sort: offset, layer: 'defaults' }, rule])
324
+ .push(
325
+ ...partitionRules(rule).map((rule) => [
326
+ { sort: offsets.base++, layer: 'defaults' },
327
+ rule,
328
+ ])
329
+ )
256
330
  }
257
331
  },
258
332
  addComponents(components, options) {
@@ -265,7 +339,6 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
265
339
 
266
340
  for (let [identifier, rule] of withIdentifiers(components)) {
267
341
  let prefixedIdentifier = prefixIdentifier(identifier, options)
268
- let offset = offsets.components++
269
342
 
270
343
  classList.add(prefixedIdentifier)
271
344
 
@@ -275,7 +348,12 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
275
348
 
276
349
  context.candidateRuleMap
277
350
  .get(prefixedIdentifier)
278
- .push([{ sort: offset, layer: 'components', options }, rule])
351
+ .push(
352
+ ...partitionRules(rule).map((rule) => [
353
+ { sort: offsets.components++, layer: 'components', options },
354
+ rule,
355
+ ])
356
+ )
279
357
  }
280
358
  },
281
359
  addUtilities(utilities, options) {
@@ -288,7 +366,6 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
288
366
 
289
367
  for (let [identifier, rule] of withIdentifiers(utilities)) {
290
368
  let prefixedIdentifier = prefixIdentifier(identifier, options)
291
- let offset = offsets.utilities++
292
369
 
293
370
  classList.add(prefixedIdentifier)
294
371
 
@@ -298,7 +375,12 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
298
375
 
299
376
  context.candidateRuleMap
300
377
  .get(prefixedIdentifier)
301
- .push([{ sort: offset, layer: 'utilities', options }, rule])
378
+ .push(
379
+ ...partitionRules(rule).map((rule) => [
380
+ { sort: offsets.utilities++, layer: 'utilities', options },
381
+ rule,
382
+ ])
383
+ )
302
384
  }
303
385
  },
304
386
  matchUtilities: function (utilities, options) {
@@ -14,6 +14,8 @@ export default function processTailwindFeatures(setupContext) {
14
14
  return function (root, result) {
15
15
  let { tailwindDirectives, applyDirectives } = normalizeTailwindDirectives(root)
16
16
 
17
+ detectNesting()(root, result)
18
+
17
19
  let context = setupContext({
18
20
  tailwindDirectives,
19
21
  applyDirectives,
@@ -37,7 +39,6 @@ export default function processTailwindFeatures(setupContext) {
37
39
 
38
40
  issueFlagNotices(context.tailwindConfig)
39
41
 
40
- detectNesting(context)(root, result)
41
42
  expandTailwindAtRules(context)(root, result)
42
43
  expandApplyAtRules(context)(root, result)
43
44
  evaluateTailwindFunctions(context)(root, result)
@@ -185,7 +185,7 @@ export function coerceValue(types, modifier, options, tailwindConfig) {
185
185
  // Find first matching type
186
186
  for (let type of [].concat(types)) {
187
187
  let result = typeMap[type](modifier, options, { tailwindConfig })
188
- if (result) return [result, type]
188
+ if (result !== undefined) return [result, type]
189
189
  }
190
190
 
191
191
  return []