tailwindcss 0.0.0-insiders.e2d5f21 → 0.0.0-insiders.e302ef1

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.
Files changed (91) hide show
  1. package/CHANGELOG.md +244 -3
  2. package/LICENSE +1 -2
  3. package/README.md +8 -4
  4. package/colors.js +2 -1
  5. package/defaultConfig.js +2 -1
  6. package/defaultTheme.js +2 -1
  7. package/lib/cli.js +123 -88
  8. package/lib/corePlugins.js +288 -360
  9. package/lib/css/preflight.css +4 -4
  10. package/lib/featureFlags.js +4 -5
  11. package/lib/index.js +12 -3
  12. package/lib/lib/cacheInvalidation.js +69 -0
  13. package/lib/lib/collapseAdjacentRules.js +14 -1
  14. package/lib/lib/collapseDuplicateDeclarations.js +52 -1
  15. package/lib/lib/defaultExtractor.js +44 -0
  16. package/lib/lib/evaluateTailwindFunctions.js +1 -1
  17. package/lib/lib/expandApplyAtRules.js +265 -60
  18. package/lib/lib/expandTailwindAtRules.js +63 -48
  19. package/lib/lib/generateRules.js +136 -34
  20. package/lib/lib/normalizeTailwindDirectives.js +10 -2
  21. package/lib/lib/partitionApplyAtRules.js +53 -0
  22. package/lib/lib/resolveDefaultsAtRules.js +30 -12
  23. package/lib/lib/setupContextUtils.js +137 -81
  24. package/lib/lib/setupTrackingContext.js +8 -7
  25. package/lib/lib/sharedState.js +38 -5
  26. package/{nesting → lib/postcss-plugins/nesting}/README.md +0 -0
  27. package/lib/postcss-plugins/nesting/index.js +17 -0
  28. package/lib/postcss-plugins/nesting/plugin.js +85 -0
  29. package/lib/processTailwindFeatures.js +10 -2
  30. package/lib/util/cloneNodes.js +12 -1
  31. package/lib/util/color.js +23 -8
  32. package/lib/util/createPlugin.js +1 -2
  33. package/lib/util/createUtilityPlugin.js +4 -8
  34. package/lib/util/dataTypes.js +4 -2
  35. package/lib/util/defaults.js +6 -0
  36. package/lib/util/flattenColorPalette.js +1 -3
  37. package/lib/util/log.js +10 -6
  38. package/lib/util/normalizeConfig.js +47 -15
  39. package/lib/util/normalizeScreens.js +6 -5
  40. package/lib/util/parseBoxShadowValue.js +44 -4
  41. package/lib/util/pluginUtils.js +6 -13
  42. package/lib/util/prefixSelector.js +4 -5
  43. package/lib/util/resolveConfig.js +48 -27
  44. package/lib/util/resolveConfigPath.js +1 -2
  45. package/lib/util/toColorValue.js +1 -2
  46. package/lib/util/toPath.js +6 -1
  47. package/lib/util/transformThemeValue.js +4 -8
  48. package/nesting/index.js +2 -12
  49. package/package.json +28 -33
  50. package/peers/index.js +3209 -4239
  51. package/plugin.js +2 -1
  52. package/resolveConfig.js +2 -1
  53. package/src/cli.js +62 -15
  54. package/src/corePlugins.js +212 -217
  55. package/src/css/preflight.css +4 -4
  56. package/src/featureFlags.js +3 -3
  57. package/src/index.js +14 -6
  58. package/src/lib/cacheInvalidation.js +52 -0
  59. package/src/lib/collapseAdjacentRules.js +16 -1
  60. package/src/lib/collapseDuplicateDeclarations.js +66 -1
  61. package/src/lib/defaultExtractor.js +50 -0
  62. package/src/lib/evaluateTailwindFunctions.js +1 -1
  63. package/src/lib/expandApplyAtRules.js +285 -56
  64. package/src/lib/expandTailwindAtRules.js +75 -37
  65. package/src/lib/generateRules.js +121 -27
  66. package/src/lib/normalizeTailwindDirectives.js +7 -1
  67. package/src/lib/partitionApplyAtRules.js +52 -0
  68. package/src/lib/resolveDefaultsAtRules.js +35 -10
  69. package/src/lib/setupContextUtils.js +127 -45
  70. package/src/lib/setupTrackingContext.js +8 -7
  71. package/src/lib/sharedState.js +42 -4
  72. package/src/postcss-plugins/nesting/README.md +42 -0
  73. package/src/postcss-plugins/nesting/index.js +13 -0
  74. package/src/postcss-plugins/nesting/plugin.js +80 -0
  75. package/src/processTailwindFeatures.js +12 -2
  76. package/src/util/cloneNodes.js +14 -1
  77. package/src/util/color.js +20 -7
  78. package/src/util/dataTypes.js +7 -5
  79. package/src/util/defaults.js +6 -0
  80. package/src/util/log.js +10 -6
  81. package/src/util/normalizeConfig.js +24 -3
  82. package/src/util/normalizeScreens.js +6 -3
  83. package/src/util/parseBoxShadowValue.js +51 -3
  84. package/src/util/pluginUtils.js +1 -1
  85. package/src/util/prefixSelector.js +7 -5
  86. package/src/util/resolveConfig.js +41 -1
  87. package/src/util/toPath.js +23 -1
  88. package/stubs/defaultConfig.stub.js +2 -2
  89. package/lib/lib/setupWatchingContext.js +0 -288
  90. package/nesting/plugin.js +0 -41
  91. package/src/lib/setupWatchingContext.js +0 -311
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  });
5
5
  exports.default = expandApplyAtRules;
6
6
  var _postcss = _interopRequireDefault(require("postcss"));
7
+ var _postcssSelectorParser = _interopRequireDefault(require("postcss-selector-parser"));
7
8
  var _generateRules = require("./generateRules");
8
9
  var _bigSign = _interopRequireDefault(require("../util/bigSign"));
9
10
  var _escapeClassName = _interopRequireDefault(require("../util/escapeClassName"));
@@ -12,11 +13,141 @@ function _interopRequireDefault(obj) {
12
13
  default: obj
13
14
  };
14
15
  }
15
- function prefix1(context, selector) {
16
- let prefix = context.tailwindConfig.prefix;
17
- return typeof prefix === 'function' ? prefix(selector) : prefix + selector;
16
+ /** @typedef {Map<string, [any, import('postcss').Rule[]]>} ApplyCache */ function extractClasses(node) {
17
+ let classes = new Set();
18
+ let container = _postcss.default.root({
19
+ nodes: [
20
+ node.clone()
21
+ ]
22
+ });
23
+ container.walkRules((rule)=>{
24
+ (0, _postcssSelectorParser).default((selectors)=>{
25
+ selectors.walkClasses((classSelector)=>{
26
+ classes.add(classSelector.value);
27
+ });
28
+ }).processSync(rule.selector);
29
+ });
30
+ return Array.from(classes);
31
+ }
32
+ function extractBaseCandidates(candidates, separator) {
33
+ let baseClasses = new Set();
34
+ for (let candidate of candidates){
35
+ baseClasses.add(candidate.split(separator).pop());
36
+ }
37
+ return Array.from(baseClasses);
38
+ }
39
+ function prefix(context, selector) {
40
+ let prefix1 = context.tailwindConfig.prefix;
41
+ return typeof prefix1 === 'function' ? prefix1(selector) : prefix1 + selector;
18
42
  }
19
- function buildApplyCache(applyCandidates, context) {
43
+ function* pathToRoot(node) {
44
+ yield node;
45
+ while(node.parent){
46
+ yield node.parent;
47
+ node = node.parent;
48
+ }
49
+ }
50
+ /**
51
+ * Only clone the node itself and not its children
52
+ *
53
+ * @param {*} node
54
+ * @param {*} overrides
55
+ * @returns
56
+ */ function shallowClone(node, overrides = {}) {
57
+ let children = node.nodes;
58
+ node.nodes = [];
59
+ let tmp = node.clone(overrides);
60
+ node.nodes = children;
61
+ return tmp;
62
+ }
63
+ /**
64
+ * Clone just the nodes all the way to the top that are required to represent
65
+ * this singular rule in the tree.
66
+ *
67
+ * For example, if we have CSS like this:
68
+ * ```css
69
+ * @media (min-width: 768px) {
70
+ * @supports (display: grid) {
71
+ * .foo {
72
+ * display: grid;
73
+ * grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
74
+ * }
75
+ * }
76
+ *
77
+ * @supports (backdrop-filter: blur(1px)) {
78
+ * .bar {
79
+ * backdrop-filter: blur(1px);
80
+ * }
81
+ * }
82
+ *
83
+ * .baz {
84
+ * color: orange;
85
+ * }
86
+ * }
87
+ * ```
88
+ *
89
+ * And we're cloning `.bar` it'll return a cloned version of what's required for just that single node:
90
+ *
91
+ * ```css
92
+ * @media (min-width: 768px) {
93
+ * @supports (backdrop-filter: blur(1px)) {
94
+ * .bar {
95
+ * backdrop-filter: blur(1px);
96
+ * }
97
+ * }
98
+ * }
99
+ * ```
100
+ *
101
+ * @param {import('postcss').Node} node
102
+ */ function nestedClone(node) {
103
+ for (let parent of pathToRoot(node)){
104
+ if (node === parent) {
105
+ continue;
106
+ }
107
+ if (parent.type === 'root') {
108
+ break;
109
+ }
110
+ node = shallowClone(parent, {
111
+ nodes: [
112
+ node
113
+ ]
114
+ });
115
+ }
116
+ return node;
117
+ }
118
+ /**
119
+ * @param {import('postcss').Root} root
120
+ */ function buildLocalApplyCache(root, context) {
121
+ /** @type {ApplyCache} */ let cache = new Map();
122
+ let highestOffset = context.layerOrder.user >> 4n;
123
+ root.walkRules((rule, idx)=>{
124
+ // Ignore rules generated by Tailwind
125
+ for (let node of pathToRoot(rule)){
126
+ var ref;
127
+ if (((ref = node.raws.tailwind) === null || ref === void 0 ? void 0 : ref.layer) !== undefined) {
128
+ return;
129
+ }
130
+ }
131
+ // Clone what's required to represent this singular rule in the tree
132
+ let container = nestedClone(rule);
133
+ for (let className of extractClasses(rule)){
134
+ let list = cache.get(className) || [];
135
+ cache.set(className, list);
136
+ list.push([
137
+ {
138
+ layer: 'user',
139
+ sort: BigInt(idx) + highestOffset,
140
+ important: false
141
+ },
142
+ container,
143
+ ]);
144
+ }
145
+ });
146
+ return cache;
147
+ }
148
+ /**
149
+ * @returns {ApplyCache}
150
+ */ function buildApplyCache(applyCandidates, context) {
20
151
  for (let candidate of applyCandidates){
21
152
  if (context.notClassCache.has(candidate) || context.applyClassCache.has(candidate)) {
22
153
  continue;
@@ -38,6 +169,39 @@ function buildApplyCache(applyCandidates, context) {
38
169
  }
39
170
  return context.applyClassCache;
40
171
  }
172
+ /**
173
+ * Build a cache only when it's first used
174
+ *
175
+ * @param {() => ApplyCache} buildCacheFn
176
+ * @returns {ApplyCache}
177
+ */ function lazyCache(buildCacheFn) {
178
+ let cache = null;
179
+ return {
180
+ get: (name)=>{
181
+ cache = cache || buildCacheFn();
182
+ return cache.get(name);
183
+ },
184
+ has: (name)=>{
185
+ cache = cache || buildCacheFn();
186
+ return cache.has(name);
187
+ }
188
+ };
189
+ }
190
+ /**
191
+ * Take a series of multiple caches and merge
192
+ * them so they act like one large cache
193
+ *
194
+ * @param {ApplyCache[]} caches
195
+ * @returns {ApplyCache}
196
+ */ function combineCaches(caches) {
197
+ return {
198
+ get: (name)=>caches.flatMap((cache)=>cache.get(name) || []
199
+ )
200
+ ,
201
+ has: (name)=>caches.some((cache)=>cache.has(name)
202
+ )
203
+ };
204
+ }
41
205
  function extractApplyCandidates(params) {
42
206
  let candidates = params.split(/[\s\t\n]+/g);
43
207
  if (candidates[candidates.length - 1] === '!important') {
@@ -51,46 +215,7 @@ function extractApplyCandidates(params) {
51
215
  false
52
216
  ];
53
217
  }
54
- function partitionApplyParents(root) {
55
- let applyParents = new Set();
56
- root.walkAtRules('apply', (rule)=>{
57
- applyParents.add(rule.parent);
58
- });
59
- for (let rule1 of applyParents){
60
- let nodeGroups = [];
61
- let lastGroup = [];
62
- for (let node of rule1.nodes){
63
- if (node.type === 'atrule' && node.name === 'apply') {
64
- if (lastGroup.length > 0) {
65
- nodeGroups.push(lastGroup);
66
- lastGroup = [];
67
- }
68
- nodeGroups.push([
69
- node
70
- ]);
71
- } else {
72
- lastGroup.push(node);
73
- }
74
- }
75
- if (lastGroup.length > 0) {
76
- nodeGroups.push(lastGroup);
77
- }
78
- if (nodeGroups.length === 1) {
79
- continue;
80
- }
81
- for (let group of [
82
- ...nodeGroups
83
- ].reverse()){
84
- let newParent = rule1.clone({
85
- nodes: []
86
- });
87
- newParent.append(group);
88
- rule1.after(newParent);
89
- }
90
- rule1.remove();
91
- }
92
- }
93
- function processApply(root, context) {
218
+ function processApply(root, context, localCache) {
94
219
  let applyCandidates = new Set();
95
220
  // Collect all @apply rules and candidates
96
221
  let applies = [];
@@ -104,7 +229,10 @@ function processApply(root, context) {
104
229
  // Start the @apply process if we have rules with @apply in them
105
230
  if (applies.length > 0) {
106
231
  // Fill up some caches!
107
- let applyClassCache = buildApplyCache(applyCandidates, context);
232
+ let applyClassCache = combineCaches([
233
+ localCache,
234
+ buildApplyCache(applyCandidates, context)
235
+ ]);
108
236
  /**
109
237
  * When we have an apply like this:
110
238
  *
@@ -127,8 +255,8 @@ function processApply(root, context) {
127
255
  */ // TODO: Should we use postcss-selector-parser for this instead?
128
256
  function replaceSelector(selector, utilitySelectors, candidate) {
129
257
  let needle = `.${(0, _escapeClassName).default(candidate)}`;
130
- let utilitySelectorsList = utilitySelectors.split(/\s*,\s*/g);
131
- return selector.split(/\s*,\s*/g).map((s)=>{
258
+ let utilitySelectorsList = utilitySelectors.split(/\s*\,(?![^(]*\))\s*/g);
259
+ return selector.split(/\s*\,(?![^(]*\))\s*/g).map((s)=>{
132
260
  let replaced = [];
133
261
  for (let utilitySelector of utilitySelectorsList){
134
262
  let replacedSelector = utilitySelector.replace(needle, s);
@@ -144,7 +272,10 @@ function processApply(root, context) {
144
272
  // Collect all apply candidates and their rules
145
273
  for (let apply of applies){
146
274
  let candidates = perParentApplies.get(apply.parent) || [];
147
- perParentApplies.set(apply.parent, candidates);
275
+ perParentApplies.set(apply.parent, [
276
+ candidates,
277
+ apply.source
278
+ ]);
148
279
  let [applyCandidates, important] = extractApplyCandidates(apply.params);
149
280
  if (apply.parent.type === 'atrule') {
150
281
  if (apply.parent.name === 'screen') {
@@ -155,11 +286,14 @@ function processApply(root, context) {
155
286
  throw apply.error(`@apply is not supported within nested at-rules like @${apply.parent.name}. You can fix this by un-nesting @${apply.parent.name}.`);
156
287
  }
157
288
  for (let applyCandidate of applyCandidates){
289
+ if ([
290
+ prefix(context, 'group'),
291
+ prefix(context, 'peer')
292
+ ].includes(applyCandidate)) {
293
+ // TODO: Link to specific documentation page with error code.
294
+ throw apply.error(`@apply should not be used with the '${applyCandidate}' utility`);
295
+ }
158
296
  if (!applyClassCache.has(applyCandidate)) {
159
- if (applyCandidate === prefix1(context, 'group')) {
160
- // TODO: Link to specific documentation page with error code.
161
- throw apply.error(`@apply should not be used with the '${applyCandidate}' utility`);
162
- }
163
297
  throw apply.error(`The \`${applyCandidate}\` class does not exist. If \`${applyCandidate}\` is a custom class, make sure it is defined within a \`@layer\` directive.`);
164
298
  }
165
299
  let rules = applyClassCache.get(applyCandidate);
@@ -170,18 +304,88 @@ function processApply(root, context) {
170
304
  ]);
171
305
  }
172
306
  }
173
- for (const [parent, candidates] of perParentApplies){
307
+ for (const [parent, [candidates, atApplySource]] of perParentApplies){
174
308
  let siblings = [];
175
309
  for (let [applyCandidate, important, rules] of candidates){
176
- for (let [meta, node] of rules){
310
+ for (let [meta, node1] of rules){
311
+ let parentClasses = extractClasses(parent);
312
+ let nodeClasses = extractClasses(node1);
313
+ // Add base utility classes from the @apply node to the list of
314
+ // classes to check whether it intersects and therefore results in a
315
+ // circular dependency or not.
316
+ //
317
+ // E.g.:
318
+ // .foo {
319
+ // @apply hover:a; // This applies "a" but with a modifier
320
+ // }
321
+ //
322
+ // We only have to do that with base classes of the `node`, not of the `parent`
323
+ // E.g.:
324
+ // .hover\:foo {
325
+ // @apply bar;
326
+ // }
327
+ // .bar {
328
+ // @apply foo;
329
+ // }
330
+ //
331
+ // This should not result in a circular dependency because we are
332
+ // just applying `.foo` and the rule above is `.hover\:foo` which is
333
+ // unrelated. However, if we were to apply `hover:foo` then we _did_
334
+ // have to include this one.
335
+ nodeClasses = nodeClasses.concat(extractBaseCandidates(nodeClasses, context.tailwindConfig.separator));
336
+ let intersects = parentClasses.some((selector)=>nodeClasses.includes(selector)
337
+ );
338
+ if (intersects) {
339
+ throw node1.error(`You cannot \`@apply\` the \`${applyCandidate}\` utility here because it creates a circular dependency.`);
340
+ }
177
341
  let root = _postcss.default.root({
178
342
  nodes: [
179
- node.clone()
343
+ node1.clone()
180
344
  ]
181
345
  });
182
- let canRewriteSelector = node.type !== 'atrule' || node.type === 'atrule' && node.name !== 'keyframes';
346
+ // Make sure every node in the entire tree points back at the @apply rule that generated it
347
+ root.walk((node)=>{
348
+ node.source = atApplySource;
349
+ });
350
+ let canRewriteSelector = node1.type !== 'atrule' || node1.type === 'atrule' && node1.name !== 'keyframes';
183
351
  if (canRewriteSelector) {
184
352
  root.walkRules((rule)=>{
353
+ // Let's imagine you have the following structure:
354
+ //
355
+ // .foo {
356
+ // @apply bar;
357
+ // }
358
+ //
359
+ // @supports (a: b) {
360
+ // .bar {
361
+ // color: blue
362
+ // }
363
+ //
364
+ // .something-unrelated {}
365
+ // }
366
+ //
367
+ // In this case we want to apply `.bar` but it happens to be in
368
+ // an atrule node. We clone that node instead of the nested one
369
+ // because we still want that @supports rule to be there once we
370
+ // applied everything.
371
+ //
372
+ // However it happens to be that the `.something-unrelated` is
373
+ // also in that same shared @supports atrule. This is not good,
374
+ // and this should not be there. The good part is that this is
375
+ // a clone already and it can be safely removed. The question is
376
+ // how do we know we can remove it. Basically what we can do is
377
+ // match it against the applyCandidate that you want to apply. If
378
+ // it doesn't match the we can safely delete it.
379
+ //
380
+ // If we didn't do this, then the `replaceSelector` function
381
+ // would have replaced this with something that didn't exist and
382
+ // therefore it removed the selector altogether. In this specific
383
+ // case it would result in `{}` instead of `.something-unrelated {}`
384
+ if (!extractClasses(rule).some((candidate)=>candidate === applyCandidate
385
+ )) {
386
+ rule.remove();
387
+ return;
388
+ }
185
389
  rule.selector = replaceSelector(parent.selector, rule.selector, applyCandidate);
186
390
  rule.walkDecls((d)=>{
187
391
  d.important = meta.important || important;
@@ -203,7 +407,6 @@ function processApply(root, context) {
203
407
  let nodes = siblings.sort(([a], [z])=>(0, _bigSign).default(a.sort - z.sort)
204
408
  ).map((s)=>s[1]
205
409
  );
206
- // console.log(parent)
207
410
  // `parent` refers to the node at `.abc` in: .abc { @apply mt-2 }
208
411
  parent.after(nodes);
209
412
  }
@@ -217,12 +420,14 @@ function processApply(root, context) {
217
420
  }
218
421
  }
219
422
  // Do it again, in case we have other `@apply` rules
220
- processApply(root, context);
423
+ processApply(root, context, localCache);
221
424
  }
222
425
  }
223
426
  function expandApplyAtRules(context) {
224
427
  return (root)=>{
225
- partitionApplyParents(root);
226
- processApply(root, context);
428
+ // Build a cache of the user's CSS so we can use it to resolve classes used by @apply
429
+ let localCache = lazyCache(()=>buildLocalApplyCache(root, context)
430
+ );
431
+ processApply(root, context, localCache);
227
432
  };
228
433
  }
@@ -7,7 +7,9 @@ var _quickLru = _interopRequireDefault(require("quick-lru"));
7
7
  var sharedState = _interopRequireWildcard(require("./sharedState"));
8
8
  var _generateRules = require("./generateRules");
9
9
  var _bigSign = _interopRequireDefault(require("../util/bigSign"));
10
+ var _log = _interopRequireDefault(require("../util/log"));
10
11
  var _cloneNodes = _interopRequireDefault(require("../util/cloneNodes"));
12
+ var _defaultExtractor = require("./defaultExtractor");
11
13
  function _interopRequireDefault(obj) {
12
14
  return obj && obj.__esModule ? obj : {
13
15
  default: obj
@@ -17,13 +19,11 @@ function _interopRequireWildcard(obj) {
17
19
  if (obj && obj.__esModule) {
18
20
  return obj;
19
21
  } else {
20
- var newObj = {
21
- };
22
+ var newObj = {};
22
23
  if (obj != null) {
23
24
  for(var key in obj){
24
25
  if (Object.prototype.hasOwnProperty.call(obj, key)) {
25
- var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {
26
- };
26
+ var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {};
27
27
  if (desc.get || desc.set) {
28
28
  Object.defineProperty(newObj, key, desc);
29
29
  } else {
@@ -37,31 +37,8 @@ function _interopRequireWildcard(obj) {
37
37
  }
38
38
  }
39
39
  let env = sharedState.env;
40
- const PATTERNS = [
41
- /([^<>"'`\s]*\[\w*'[^"`\s]*'?\])/.source,
42
- /([^<>"'`\s]*\[\w*"[^"`\s]*"?\])/.source,
43
- /([^<>"'`\s]*\[\w*\('[^"'`\s]*'\)\])/.source,
44
- /([^<>"'`\s]*\[\w*\("[^"'`\s]*"\)\])/.source,
45
- /([^<>"'`\s]*\[\w*\('[^"`\s]*'\)\])/.source,
46
- /([^<>"'`\s]*\[\w*\("[^'`\s]*"\)\])/.source,
47
- /([^<>"'`\s]*\['[^"'`\s]*'\])/.source,
48
- /([^<>"'`\s]*\["[^"'`\s]*"\])/.source,
49
- /([^<>"'`\s]*\[[^<>"'`\s]*:'[^"'`\s]*'\])/.source,
50
- /([^<>"'`\s]*\[[^<>"'`\s]*:"[^"'`\s]*"\])/.source,
51
- /([^<>"'`\s]*\[[^"'`\s]+\][^<>"'`\s]*)/.source,
52
- /([^<>"'`\s]*[^"'`\s:])/.source
53
- ].join('|');
54
- const BROAD_MATCH_GLOBAL_REGEXP = new RegExp(PATTERNS, 'g');
55
- const INNER_MATCH_GLOBAL_REGEXP = /[^<>"'`\s.(){}[\]#=%]*[^<>"'`\s.(){}[\]#=%:]/g;
56
40
  const builtInExtractors = {
57
- DEFAULT: (content)=>{
58
- let broadMatches = content.match(BROAD_MATCH_GLOBAL_REGEXP) || [];
59
- let innerMatches = content.match(INNER_MATCH_GLOBAL_REGEXP) || [];
60
- return [
61
- ...broadMatches,
62
- ...innerMatches
63
- ];
64
- }
41
+ DEFAULT: _defaultExtractor.defaultExtractor
65
42
  };
66
43
  const builtInTransformers = {
67
44
  DEFAULT: (content)=>content
@@ -112,6 +89,7 @@ function buildStylesheet(rules, context) {
112
89
  );
113
90
  let returnValue = {
114
91
  base: new Set(),
92
+ defaults: new Set(),
115
93
  components: new Set(),
116
94
  utilities: new Set(),
117
95
  variants: new Set(),
@@ -134,6 +112,10 @@ function buildStylesheet(rules, context) {
134
112
  returnValue.base.add(rule);
135
113
  continue;
136
114
  }
115
+ if (sort & context.layerOrder.defaults) {
116
+ returnValue.defaults.add(rule);
117
+ continue;
118
+ }
137
119
  if (sort & context.layerOrder.components) {
138
120
  returnValue.components.add(rule);
139
121
  continue;
@@ -157,13 +139,15 @@ function expandTailwindAtRules(context) {
157
139
  utilities: null,
158
140
  variants: null
159
141
  };
160
- // Make sure this file contains Tailwind directives. If not, we can save
161
- // a lot of work and bail early. Also we don't have to register our touch
162
- // file as a dependency since the output of this CSS does not depend on
163
- // the source of any templates. Think Vue <style> blocks for example.
164
- root.walkAtRules('tailwind', (rule)=>{
165
- if (Object.keys(layerNodes).includes(rule.params)) {
166
- layerNodes[rule.params] = rule;
142
+ root.walkAtRules((rule)=>{
143
+ // Make sure this file contains Tailwind directives. If not, we can save
144
+ // a lot of work and bail early. Also we don't have to register our touch
145
+ // file as a dependency since the output of this CSS does not depend on
146
+ // the source of any templates. Think Vue <style> blocks for example.
147
+ if (rule.name === 'tailwind') {
148
+ if (Object.keys(layerNodes).includes(rule.params)) {
149
+ layerNodes[rule.params] = rule;
150
+ }
167
151
  }
168
152
  });
169
153
  if (Object.values(layerNodes).every((n)=>n === null
@@ -173,7 +157,7 @@ function expandTailwindAtRules(context) {
173
157
  // ---
174
158
  // Find potential rules in changed files
175
159
  let candidates = new Set([
176
- '*'
160
+ sharedState.NOT_ON_DEMAND
177
161
  ]);
178
162
  let seen = new Set();
179
163
  env.DEBUG && console.time('Reading changed files');
@@ -182,6 +166,7 @@ function expandTailwindAtRules(context) {
182
166
  let extractor = getExtractor(context.tailwindConfig, extension);
183
167
  getClassCandidates(transformer(content), extractor, candidates, seen);
184
168
  }
169
+ env.DEBUG && console.timeEnd('Reading changed files');
185
170
  // ---
186
171
  // Generate the actual CSS
187
172
  let classCacheCount = context.classCache.size;
@@ -199,36 +184,66 @@ function expandTailwindAtRules(context) {
199
184
  ], context);
200
185
  }
201
186
  env.DEBUG && console.timeEnd('Build stylesheet');
202
- let { base: baseNodes , components: componentNodes , utilities: utilityNodes , variants: screenNodes , } = context.stylesheetCache;
187
+ let { defaults: defaultNodes , base: baseNodes , components: componentNodes , utilities: utilityNodes , variants: screenNodes , } = context.stylesheetCache;
203
188
  // ---
204
189
  // Replace any Tailwind directives with generated CSS
205
190
  if (layerNodes.base) {
206
191
  layerNodes.base.before((0, _cloneNodes).default([
207
- ...baseNodes
208
- ], layerNodes.base.source));
192
+ ...baseNodes,
193
+ ...defaultNodes
194
+ ], layerNodes.base.source, {
195
+ layer: 'base'
196
+ }));
209
197
  layerNodes.base.remove();
210
198
  }
211
199
  if (layerNodes.components) {
212
200
  layerNodes.components.before((0, _cloneNodes).default([
213
201
  ...componentNodes
214
- ], layerNodes.components.source));
202
+ ], layerNodes.components.source, {
203
+ layer: 'components'
204
+ }));
215
205
  layerNodes.components.remove();
216
206
  }
217
207
  if (layerNodes.utilities) {
218
208
  layerNodes.utilities.before((0, _cloneNodes).default([
219
209
  ...utilityNodes
220
- ], layerNodes.utilities.source));
210
+ ], layerNodes.utilities.source, {
211
+ layer: 'utilities'
212
+ }));
221
213
  layerNodes.utilities.remove();
222
214
  }
215
+ // We do post-filtering to not alter the emitted order of the variants
216
+ const variantNodes = Array.from(screenNodes).filter((node)=>{
217
+ var ref;
218
+ const parentLayer = (ref = node.raws.tailwind) === null || ref === void 0 ? void 0 : ref.parentLayer;
219
+ if (parentLayer === 'components') {
220
+ return layerNodes.components !== null;
221
+ }
222
+ if (parentLayer === 'utilities') {
223
+ return layerNodes.utilities !== null;
224
+ }
225
+ return true;
226
+ });
223
227
  if (layerNodes.variants) {
224
- layerNodes.variants.before((0, _cloneNodes).default([
225
- ...screenNodes
226
- ], layerNodes.variants.source));
228
+ layerNodes.variants.before((0, _cloneNodes).default(variantNodes, layerNodes.variants.source, {
229
+ layer: 'variants'
230
+ }));
227
231
  layerNodes.variants.remove();
228
- } else {
229
- root.append((0, _cloneNodes).default([
230
- ...screenNodes
231
- ], root.source));
232
+ } else if (variantNodes.length > 0) {
233
+ root.append((0, _cloneNodes).default(variantNodes, root.source, {
234
+ layer: 'variants'
235
+ }));
236
+ }
237
+ // If we've got a utility layer and no utilities are generated there's likely something wrong
238
+ const hasUtilityVariants = variantNodes.some((node)=>{
239
+ var ref;
240
+ return ((ref = node.raws.tailwind) === null || ref === void 0 ? void 0 : ref.parentLayer) === 'utilities';
241
+ });
242
+ if (layerNodes.utilities && utilityNodes.size === 0 && !hasUtilityVariants) {
243
+ _log.default.warn('content-problems', [
244
+ 'No utility classes were detected in your source files. If this is unexpected, double-check the `content` option in your Tailwind CSS configuration.',
245
+ 'https://tailwindcss.com/docs/content-configuration',
246
+ ]);
232
247
  }
233
248
  // ---
234
249
  if (env.DEBUG) {