tailwindcss 3.0.8 → 3.0.12

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 (37) hide show
  1. package/CHANGELOG.md +53 -1
  2. package/lib/cli.js +49 -12
  3. package/lib/corePlugins.js +114 -142
  4. package/lib/css/preflight.css +1 -1
  5. package/lib/featureFlags.js +1 -3
  6. package/lib/index.js +1 -3
  7. package/lib/lib/collapseDuplicateDeclarations.js +52 -1
  8. package/lib/lib/defaultExtractor.js +2 -0
  9. package/lib/lib/expandApplyAtRules.js +0 -40
  10. package/lib/lib/expandTailwindAtRules.js +12 -25
  11. package/lib/lib/normalizeTailwindDirectives.js +8 -1
  12. package/lib/lib/resolveDefaultsAtRules.js +4 -4
  13. package/lib/lib/setupContextUtils.js +131 -69
  14. package/lib/lib/setupTrackingContext.js +11 -10
  15. package/lib/lib/sharedState.js +33 -4
  16. package/lib/processTailwindFeatures.js +3 -2
  17. package/lib/util/pluginUtils.js +1 -1
  18. package/package.json +7 -8
  19. package/peers/index.js +606 -606
  20. package/src/cli.js +57 -12
  21. package/src/corePlugins.js +121 -155
  22. package/src/css/preflight.css +1 -1
  23. package/src/featureFlags.js +1 -5
  24. package/src/index.js +1 -7
  25. package/src/lib/collapseDuplicateDeclarations.js +66 -1
  26. package/src/lib/defaultExtractor.js +2 -0
  27. package/src/lib/expandApplyAtRules.js +0 -42
  28. package/src/lib/expandTailwindAtRules.js +12 -21
  29. package/src/lib/normalizeTailwindDirectives.js +6 -1
  30. package/src/lib/resolveDefaultsAtRules.js +5 -5
  31. package/src/lib/setupContextUtils.js +108 -19
  32. package/src/lib/setupTrackingContext.js +11 -10
  33. package/src/lib/sharedState.js +40 -4
  34. package/src/processTailwindFeatures.js +4 -2
  35. package/src/util/pluginUtils.js +1 -1
  36. package/lib/lib/setupWatchingContext.js +0 -288
  37. package/src/lib/setupWatchingContext.js +0 -311
@@ -8,6 +8,7 @@ function collapseDuplicateDeclarations() {
8
8
  root.walkRules((node)=>{
9
9
  let seen = new Map();
10
10
  let droppable = new Set([]);
11
+ let byProperty = new Map();
11
12
  node.walkDecls((decl)=>{
12
13
  // This could happen if we have nested selectors. In that case the
13
14
  // parent will loop over all its declarations but also the declarations
@@ -17,13 +18,63 @@ function collapseDuplicateDeclarations() {
17
18
  return;
18
19
  }
19
20
  if (seen.has(decl.prop)) {
20
- droppable.add(seen.get(decl.prop));
21
+ // Exact same value as what we have seen so far
22
+ if (seen.get(decl.prop).value === decl.value) {
23
+ // Keep the last one, drop the one we've seen so far
24
+ droppable.add(seen.get(decl.prop));
25
+ // Override the existing one with the new value. This is necessary
26
+ // so that if we happen to have more than one declaration with the
27
+ // same value, that we keep removing the previous one. Otherwise we
28
+ // will only remove the *first* one.
29
+ seen.set(decl.prop, decl);
30
+ return;
31
+ }
32
+ // Not the same value, so we need to check if we can merge it so
33
+ // let's collect it first.
34
+ if (!byProperty.has(decl.prop)) {
35
+ byProperty.set(decl.prop, new Set());
36
+ }
37
+ byProperty.get(decl.prop).add(seen.get(decl.prop));
38
+ byProperty.get(decl.prop).add(decl);
21
39
  }
22
40
  seen.set(decl.prop, decl);
23
41
  });
42
+ // Drop all the duplicate declarations with the exact same value we've
43
+ // already seen so far.
24
44
  for (let decl1 of droppable){
25
45
  decl1.remove();
26
46
  }
47
+ // Analyze the declarations based on its unit, drop all the declarations
48
+ // with the same unit but the last one in the list.
49
+ for (let declarations of byProperty.values()){
50
+ let byUnit = new Map();
51
+ for (let decl of declarations){
52
+ let unit = resolveUnit(decl.value);
53
+ if (unit === null) {
54
+ continue;
55
+ }
56
+ if (!byUnit.has(unit)) {
57
+ byUnit.set(unit, new Set());
58
+ }
59
+ byUnit.get(unit).add(decl);
60
+ }
61
+ for (let declarations1 of byUnit.values()){
62
+ // Get all but the last one
63
+ let removableDeclarations = Array.from(declarations1).slice(0, -1);
64
+ for (let decl of removableDeclarations){
65
+ decl.remove();
66
+ }
67
+ }
68
+ }
27
69
  });
28
70
  };
29
71
  }
72
+ let UNITLESS_NUMBER = Symbol('unitless-number');
73
+ function resolveUnit(input) {
74
+ let result = /^-?\d*.?\d+([\w%]+)?$/g.exec(input);
75
+ if (result) {
76
+ var ref;
77
+ return (ref = result[1]) !== null && ref !== void 0 ? ref : UNITLESS_NUMBER;
78
+ }
79
+ return null;
80
+ }
@@ -15,9 +15,11 @@ const PATTERNS = [
15
15
  /([^<>"'`\s]*\[\w*\("[^'`\s]*"\)\])/.source,
16
16
  /([^<>"'`\s]*\['[^"'`\s]*'\])/.source,
17
17
  /([^<>"'`\s]*\["[^"'`\s]*"\])/.source,
18
+ /([^<>"'`\s]*\[[^<>"'`\s]*:[^\]\s]*\])/.source,
18
19
  /([^<>"'`\s]*\[[^<>"'`\s]*:'[^"'`\s]*'\])/.source,
19
20
  /([^<>"'`\s]*\[[^<>"'`\s]*:"[^"'`\s]*"\])/.source,
20
21
  /([^<>"'`\s]*\[[^"'`\s]+\][^<>"'`\s]*)/.source,
22
+ /([^"'`\s]*[^<>"'`\s:\\])/.source,
21
23
  /([^<>"'`\s]*[^"'`\s:\\])/.source,
22
24
  ].join('|');
23
25
  const BROAD_MATCH_GLOBAL_REGEXP = new RegExp(PATTERNS, 'g');
@@ -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
  }
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
5
  exports.default = expandTailwindAtRules;
6
- exports.DEFAULTS_LAYER = void 0;
7
6
  var _quickLru = _interopRequireDefault(require("quick-lru"));
8
7
  var sharedState = _interopRequireWildcard(require("./sharedState"));
9
8
  var _generateRules = require("./generateRules");
@@ -133,8 +132,6 @@ function buildStylesheet(rules, context) {
133
132
  }
134
133
  return returnValue;
135
134
  }
136
- const DEFAULTS_LAYER = Symbol('defaults-layer');
137
- exports.DEFAULTS_LAYER = DEFAULTS_LAYER;
138
135
  function expandTailwindAtRules(context) {
139
136
  return (root)=>{
140
137
  let layerNodes = {
@@ -143,13 +140,15 @@ function expandTailwindAtRules(context) {
143
140
  utilities: null,
144
141
  variants: null
145
142
  };
146
- // Make sure this file contains Tailwind directives. If not, we can save
147
- // a lot of work and bail early. Also we don't have to register our touch
148
- // file as a dependency since the output of this CSS does not depend on
149
- // the source of any templates. Think Vue <style> blocks for example.
150
- root.walkAtRules('tailwind', (rule)=>{
151
- if (Object.keys(layerNodes).includes(rule.params)) {
152
- layerNodes[rule.params] = rule;
143
+ root.walkAtRules((rule)=>{
144
+ // Make sure this file contains Tailwind directives. If not, we can save
145
+ // a lot of work and bail early. Also we don't have to register our touch
146
+ // file as a dependency since the output of this CSS does not depend on
147
+ // the source of any templates. Think Vue <style> blocks for example.
148
+ if (rule.name === 'tailwind') {
149
+ if (Object.keys(layerNodes).includes(rule.params)) {
150
+ layerNodes[rule.params] = rule;
151
+ }
153
152
  }
154
153
  });
155
154
  if (Object.values(layerNodes).every((n)=>n === null
@@ -168,6 +167,7 @@ function expandTailwindAtRules(context) {
168
167
  let extractor = getExtractor(context.tailwindConfig, extension);
169
168
  getClassCandidates(transformer(content), extractor, candidates, seen);
170
169
  }
170
+ env.DEBUG && console.timeEnd('Reading changed files');
171
171
  // ---
172
172
  // Generate the actual CSS
173
173
  let classCacheCount = context.classCache.size;
@@ -190,23 +190,10 @@ function expandTailwindAtRules(context) {
190
190
  // Replace any Tailwind directives with generated CSS
191
191
  if (layerNodes.base) {
192
192
  layerNodes.base.before((0, _cloneNodes).default([
193
- ...baseNodes
193
+ ...baseNodes,
194
+ ...defaultNodes
194
195
  ], layerNodes.base.source));
195
196
  }
196
- // @defaults rules are unconditionally added first to ensure that
197
- // using any utility that relies on defaults will work even when
198
- // compiled in an isolated environment like CSS modules
199
- if (context.tailwindConfig[DEFAULTS_LAYER] !== false) {
200
- if (layerNodes.base) {
201
- layerNodes.base.after((0, _cloneNodes).default([
202
- ...defaultNodes
203
- ], root.source));
204
- } else {
205
- root.prepend((0, _cloneNodes).default([
206
- ...defaultNodes
207
- ], root.source));
208
- }
209
- }
210
197
  if (layerNodes.base) {
211
198
  layerNodes.base.remove();
212
199
  }
@@ -12,7 +12,11 @@ function _interopRequireDefault(obj) {
12
12
  function normalizeTailwindDirectives(root) {
13
13
  let tailwindDirectives = new Set();
14
14
  let layerDirectives = new Set();
15
+ let applyDirectives = new Set();
15
16
  root.walkAtRules((atRule)=>{
17
+ if (atRule.name === 'apply') {
18
+ applyDirectives.add(atRule);
19
+ }
16
20
  if (atRule.name === 'import') {
17
21
  if (atRule.params === '"tailwindcss/base"' || atRule.params === "'tailwindcss/base'") {
18
22
  atRule.name = 'tailwind';
@@ -72,5 +76,8 @@ function normalizeTailwindDirectives(root) {
72
76
  }
73
77
  }
74
78
  }
75
- return tailwindDirectives;
79
+ return {
80
+ tailwindDirectives,
81
+ applyDirectives
82
+ };
76
83
  }
@@ -109,11 +109,11 @@ function resolveDefaultsAtRules({ tailwindConfig }) {
109
109
  selectors.add(selector);
110
110
  }
111
111
  }
112
- if (selectorGroups.size === 0) {
113
- universal.remove();
114
- continue;
115
- }
116
112
  if ((0, _featureFlags).flagEnabled(tailwindConfig, 'optimizeUniversalDefaults')) {
113
+ if (selectorGroups.size === 0) {
114
+ universal.remove();
115
+ continue;
116
+ }
117
117
  for (let [, selectors] of selectorGroups){
118
118
  let universalRule = _postcss.default.rule();
119
119
  universalRule.selectors = [
@@ -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) {
@@ -463,11 +519,17 @@ function getFileModifiedMap(context) {
463
519
  function trackModified(files, fileModifiedMap) {
464
520
  let changed = false;
465
521
  for (let file of files){
522
+ var ref;
466
523
  if (!file) continue;
467
524
  let parsed = _url.default.parse(file);
468
525
  let pathname = parsed.hash ? parsed.href.replace(parsed.hash, '') : parsed.href;
469
526
  pathname = parsed.search ? pathname.replace(parsed.search, '') : pathname;
470
- let newModified = _fs.default.statSync(decodeURIComponent(pathname)).mtimeMs;
527
+ let newModified = (ref = _fs.default.statSync(decodeURIComponent(pathname), {
528
+ throwIfNoEntry: false
529
+ })) === null || ref === void 0 ? void 0 : ref.mtimeMs;
530
+ if (!newModified) {
531
+ continue;
532
+ }
471
533
  if (!fileModifiedMap.has(file) || newModified > fileModifiedMap.get(file)) {
472
534
  changed = true;
473
535
  }
@@ -119,16 +119,17 @@ function resolveChangedFiles(candidateFiles, fileModifiedMap) {
119
119
  return changedFiles;
120
120
  }
121
121
  function setupTrackingContext(configOrPath) {
122
- return ({ tailwindDirectives , registerDependency })=>{
122
+ return ({ tailwindDirectives , registerDependency , applyDirectives })=>{
123
123
  return (root, result)=>{
124
124
  let [tailwindConfig, userConfigPath, tailwindConfigHash, configDependencies] = getTailwindConfig(configOrPath);
125
125
  let contextDependencies = new Set(configDependencies);
126
- // If there are no @tailwind rules, we don't consider this CSS file or it's dependencies
127
- // to be dependencies of the context. Can reuse the context even if they change.
128
- // We may want to think about `@layer` being part of this trigger too, but it's tough
129
- // because it's impossible for a layer in one file to end up in the actual @tailwind rule
130
- // in another file since independent sources are effectively isolated.
131
- if (tailwindDirectives.size > 0) {
126
+ // If there are no @tailwind or @apply rules, we don't consider this CSS
127
+ // file or its dependencies to be dependencies of the context. Can reuse
128
+ // the context even if they change. We may want to think about `@layer`
129
+ // being part of this trigger too, but it's tough because it's impossible
130
+ // for a layer in one file to end up in the actual @tailwind rule in
131
+ // another file since independent sources are effectively isolated.
132
+ if (tailwindDirectives.size > 0 || applyDirectives.size > 0) {
132
133
  // Add current css file as a context dependencies.
133
134
  contextDependencies.add(result.opts.from);
134
135
  // Add all css @import dependencies as context dependencies.
@@ -140,12 +141,12 @@ function setupTrackingContext(configOrPath) {
140
141
  }
141
142
  let [context] = (0, _setupContextUtils).getContext(root, result, tailwindConfig, userConfigPath, tailwindConfigHash, contextDependencies);
142
143
  let candidateFiles = getCandidateFiles(context, tailwindConfig);
143
- // If there are no @tailwind rules, we don't consider this CSS file or it's dependencies
144
- // to be dependencies of the context. Can reuse the context even if they change.
144
+ // If there are no @tailwind or @apply rules, we don't consider this CSS file or it's
145
+ // dependencies to be dependencies of the context. Can reuse the context even if they change.
145
146
  // We may want to think about `@layer` being part of this trigger too, but it's tough
146
147
  // because it's impossible for a layer in one file to end up in the actual @tailwind rule
147
148
  // in another file since independent sources are effectively isolated.
148
- if (tailwindDirectives.size > 0) {
149
+ if (tailwindDirectives.size > 0 || applyDirectives.size > 0) {
149
150
  let fileModifiedMap = (0, _setupContextUtils).getFileModifiedMap(context);
150
151
  // Add template paths as postcss dependencies.
151
152
  for (let fileOrGlob of candidateFiles){
@@ -2,13 +2,11 @@
2
2
  Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
+ exports.resolveDebug = resolveDebug;
5
6
  exports.contextSourcesMap = exports.configContextMap = exports.contextMap = exports.env = void 0;
6
7
  const env = {
7
- TAILWIND_MODE: process.env.TAILWIND_MODE,
8
8
  NODE_ENV: process.env.NODE_ENV,
9
- DEBUG: process.env.DEBUG !== undefined && process.env.DEBUG !== '0',
10
- TAILWIND_DISABLE_TOUCH: process.env.TAILWIND_DISABLE_TOUCH !== undefined,
11
- TAILWIND_TOUCH_DIR: process.env.TAILWIND_TOUCH_DIR
9
+ DEBUG: resolveDebug(process.env.DEBUG)
12
10
  };
13
11
  exports.env = env;
14
12
  const contextMap = new Map();
@@ -17,3 +15,34 @@ const configContextMap = new Map();
17
15
  exports.configContextMap = configContextMap;
18
16
  const contextSourcesMap = new Map();
19
17
  exports.contextSourcesMap = contextSourcesMap;
18
+ function resolveDebug(debug) {
19
+ if (debug === undefined) {
20
+ return false;
21
+ }
22
+ // Environment variables are strings, so convert to boolean
23
+ if (debug === 'true' || debug === '1') {
24
+ return true;
25
+ }
26
+ if (debug === 'false' || debug === '0') {
27
+ return false;
28
+ }
29
+ // Keep the debug convention into account:
30
+ // DEBUG=* -> This enables all debug modes
31
+ // DEBUG=projectA,projectB,projectC -> This enables debug for projectA, projectB and projectC
32
+ // DEBUG=projectA:* -> This enables all debug modes for projectA (if you have sub-types)
33
+ // DEBUG=projectA,-projectB -> This enables debug for projectA and explicitly disables it for projectB
34
+ if (debug === '*') {
35
+ return true;
36
+ }
37
+ let debuggers = debug.split(',').map((d)=>d.split(':')[0]
38
+ );
39
+ // Ignoring tailwindcss
40
+ if (debuggers.includes('-tailwindcss')) {
41
+ return false;
42
+ }
43
+ // Including tailwindcss
44
+ if (debuggers.includes('tailwindcss')) {
45
+ return true;
46
+ }
47
+ return false;
48
+ }
@@ -21,9 +21,11 @@ function _interopRequireDefault(obj) {
21
21
  }
22
22
  function processTailwindFeatures(setupContext) {
23
23
  return function(root, result) {
24
- let tailwindDirectives = (0, _normalizeTailwindDirectives).default(root);
24
+ let { tailwindDirectives , applyDirectives } = (0, _normalizeTailwindDirectives).default(root);
25
+ (0, _detectNesting).default()(root, result);
25
26
  let context = setupContext({
26
27
  tailwindDirectives,
28
+ applyDirectives,
27
29
  registerDependency (dependency) {
28
30
  result.messages.push({
29
31
  plugin: 'tailwindcss',
@@ -39,7 +41,6 @@ function processTailwindFeatures(setupContext) {
39
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.");
40
42
  }
41
43
  (0, _featureFlags).issueFlagNotices(context.tailwindConfig);
42
- (0, _detectNesting).default(context)(root, result);
43
44
  (0, _expandTailwindAtRules).default(context)(root, result);
44
45
  (0, _expandApplyAtRules).default(context)(root, result);
45
46
  (0, _evaluateTailwindFunctions).default(context)(root, result);