tailwindcss 0.0.0-insiders.8259dfd → 0.0.0-insiders.8293c2d

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 (93) hide show
  1. package/CHANGELOG.md +207 -2
  2. package/README.md +8 -4
  3. package/colors.js +2 -1
  4. package/defaultConfig.js +2 -1
  5. package/defaultTheme.js +2 -1
  6. package/lib/cli.js +94 -61
  7. package/lib/constants.js +1 -1
  8. package/lib/corePluginList.js +8 -1
  9. package/lib/corePlugins.js +477 -517
  10. package/lib/css/preflight.css +18 -5
  11. package/lib/featureFlags.js +5 -6
  12. package/lib/index.js +1 -3
  13. package/lib/lib/collapseDuplicateDeclarations.js +80 -0
  14. package/lib/lib/defaultExtractor.js +42 -0
  15. package/lib/lib/detectNesting.js +17 -2
  16. package/lib/lib/evaluateTailwindFunctions.js +10 -6
  17. package/lib/lib/expandApplyAtRules.js +94 -45
  18. package/lib/lib/expandTailwindAtRules.js +32 -33
  19. package/lib/lib/generateRules.js +167 -21
  20. package/lib/lib/normalizeTailwindDirectives.js +8 -1
  21. package/lib/lib/partitionApplyAtRules.js +53 -0
  22. package/lib/lib/resolveDefaultsAtRules.js +28 -14
  23. package/lib/lib/setupContextUtils.js +153 -129
  24. package/lib/lib/setupTrackingContext.js +11 -10
  25. package/lib/lib/sharedState.js +34 -5
  26. package/lib/lib/substituteScreenAtRules.js +7 -4
  27. package/lib/processTailwindFeatures.js +7 -2
  28. package/lib/util/buildMediaQuery.js +13 -24
  29. package/lib/util/color.js +23 -8
  30. package/lib/util/createPlugin.js +1 -2
  31. package/lib/util/createUtilityPlugin.js +6 -10
  32. package/lib/util/dataTypes.js +38 -7
  33. package/lib/util/defaults.js +6 -0
  34. package/lib/util/flattenColorPalette.js +1 -3
  35. package/lib/util/formatVariantSelector.js +186 -0
  36. package/lib/util/isValidArbitraryValue.js +64 -0
  37. package/lib/util/log.js +4 -0
  38. package/lib/util/nameClass.js +1 -0
  39. package/lib/util/normalizeConfig.js +63 -21
  40. package/lib/util/normalizeScreens.js +59 -0
  41. package/lib/util/parseBoxShadowValue.js +77 -0
  42. package/lib/util/pluginUtils.js +27 -158
  43. package/lib/util/prefixSelector.js +1 -3
  44. package/lib/util/resolveConfig.js +30 -31
  45. package/lib/util/resolveConfigPath.js +1 -2
  46. package/lib/util/toColorValue.js +1 -2
  47. package/lib/util/toPath.js +6 -1
  48. package/lib/util/transformThemeValue.js +19 -13
  49. package/nesting/plugin.js +4 -1
  50. package/package.json +19 -21
  51. package/peers/index.js +4621 -5626
  52. package/plugin.js +2 -1
  53. package/resolveConfig.js +2 -1
  54. package/src/cli.js +66 -14
  55. package/src/corePluginList.js +1 -1
  56. package/src/corePlugins.js +406 -518
  57. package/src/css/preflight.css +18 -5
  58. package/src/featureFlags.js +1 -1
  59. package/src/index.js +1 -7
  60. package/src/lib/collapseDuplicateDeclarations.js +93 -0
  61. package/src/lib/defaultExtractor.js +48 -0
  62. package/src/lib/detectNesting.js +22 -3
  63. package/src/lib/evaluateTailwindFunctions.js +6 -3
  64. package/src/lib/expandApplyAtRules.js +101 -45
  65. package/src/lib/expandTailwindAtRules.js +33 -27
  66. package/src/lib/generateRules.js +178 -11
  67. package/src/lib/normalizeTailwindDirectives.js +6 -1
  68. package/src/lib/partitionApplyAtRules.js +52 -0
  69. package/src/lib/resolveDefaultsAtRules.js +31 -10
  70. package/src/lib/setupContextUtils.js +140 -84
  71. package/src/lib/setupTrackingContext.js +11 -10
  72. package/src/lib/sharedState.js +40 -4
  73. package/src/lib/substituteScreenAtRules.js +6 -3
  74. package/src/processTailwindFeatures.js +8 -2
  75. package/src/util/buildMediaQuery.js +14 -18
  76. package/src/util/color.js +20 -7
  77. package/src/util/dataTypes.js +43 -11
  78. package/src/util/defaults.js +6 -0
  79. package/src/util/formatVariantSelector.js +196 -0
  80. package/src/util/isValidArbitraryValue.js +61 -0
  81. package/src/util/log.js +4 -0
  82. package/src/util/nameClass.js +1 -1
  83. package/src/util/normalizeConfig.js +37 -2
  84. package/src/util/normalizeScreens.js +45 -0
  85. package/src/util/parseBoxShadowValue.js +71 -0
  86. package/src/util/pluginUtils.js +15 -138
  87. package/src/util/prefixSelector.js +1 -4
  88. package/src/util/resolveConfig.js +11 -1
  89. package/src/util/toPath.js +23 -1
  90. package/src/util/transformThemeValue.js +22 -7
  91. package/stubs/defaultConfig.stub.js +42 -16
  92. package/lib/lib/setupWatchingContext.js +0 -284
  93. package/src/lib/setupWatchingContext.js +0 -304
@@ -9,7 +9,12 @@
9
9
  box-sizing: border-box; /* 1 */
10
10
  border-width: 0; /* 2 */
11
11
  border-style: solid; /* 2 */
12
- border-color: currentColor; /* 2 */
12
+ border-color: theme('borderColor.DEFAULT', 'currentColor'); /* 2 */
13
+ }
14
+
15
+ ::before,
16
+ ::after {
17
+ --tw-content: '';
13
18
  }
14
19
 
15
20
  /*
@@ -53,7 +58,7 @@ hr {
53
58
  Add the correct text decoration in Chrome, Edge, and Safari.
54
59
  */
55
60
 
56
- abbr[title] {
61
+ abbr:where([title]) {
57
62
  text-decoration: underline dotted;
58
63
  }
59
64
 
@@ -139,7 +144,7 @@ sup {
139
144
  table {
140
145
  text-indent: 0; /* 1 */
141
146
  border-color: inherit; /* 2 */
142
- border-collapse: collapse; /* 3 */
147
+ border-collapse: collapse; /* 3 */
143
148
  }
144
149
 
145
150
  /*
@@ -283,7 +288,8 @@ legend {
283
288
  }
284
289
 
285
290
  ol,
286
- ul {
291
+ ul,
292
+ menu {
287
293
  list-style: none;
288
294
  margin: 0;
289
295
  padding: 0;
@@ -304,7 +310,7 @@ textarea {
304
310
 
305
311
  input::placeholder,
306
312
  textarea::placeholder {
307
- opacity: 1; /* 1 */
313
+ opacity: 1; /* 1 */
308
314
  color: theme('colors.gray.400', #9ca3af); /* 2 */
309
315
  }
310
316
 
@@ -317,6 +323,13 @@ button,
317
323
  cursor: pointer;
318
324
  }
319
325
 
326
+ /*
327
+ Make sure disabled buttons don't get the pointer cursor.
328
+ */
329
+ :disabled {
330
+ cursor: default;
331
+ }
332
+
320
333
  /*
321
334
  1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
322
335
  2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
@@ -13,7 +13,7 @@ function _interopRequireDefault(obj) {
13
13
  };
14
14
  }
15
15
  let defaults = {
16
- optimizeUniversalDefaults: true
16
+ optimizeUniversalDefaults: false
17
17
  };
18
18
  let featureFlags = {
19
19
  future: [],
@@ -28,9 +28,9 @@ function flagEnabled(config, flag) {
28
28
  return config.future === 'all' || ((ref2 = (ref1 = config === null || config === void 0 ? void 0 : (ref = config.future) === null || ref === void 0 ? void 0 : ref[flag]) !== null && ref1 !== void 0 ? ref1 : defaults[flag]) !== null && ref2 !== void 0 ? ref2 : false);
29
29
  }
30
30
  if (featureFlags.experimental.includes(flag)) {
31
- var ref;
32
- var ref11, ref12;
33
- return config.experimental === 'all' || ((ref12 = (ref11 = config === null || config === void 0 ? void 0 : (ref = config.experimental) === null || ref === void 0 ? void 0 : ref[flag]) !== null && ref11 !== void 0 ? ref11 : defaults[flag]) !== null && ref12 !== void 0 ? ref12 : false);
31
+ var ref3;
32
+ var ref4, ref5;
33
+ return config.experimental === 'all' || ((ref5 = (ref4 = config === null || config === void 0 ? void 0 : (ref3 = config.experimental) === null || ref3 === void 0 ? void 0 : ref3[flag]) !== null && ref4 !== void 0 ? ref4 : defaults[flag]) !== null && ref5 !== void 0 ? ref5 : false);
34
34
  }
35
35
  return false;
36
36
  }
@@ -39,8 +39,7 @@ function experimentalFlagsEnabled(config) {
39
39
  return featureFlags.experimental;
40
40
  }
41
41
  var ref;
42
- return Object.keys((ref = config === null || config === void 0 ? void 0 : config.experimental) !== null && ref !== void 0 ? ref : {
43
- }).filter((flag)=>featureFlags.experimental.includes(flag) && config.experimental[flag]
42
+ return Object.keys((ref = config === null || config === void 0 ? void 0 : config.experimental) !== null && ref !== void 0 ? ref : {}).filter((flag)=>featureFlags.experimental.includes(flag) && config.experimental[flag]
44
43
  );
45
44
  }
46
45
  function issueFlagNotices(config) {
package/lib/index.js CHANGED
@@ -1,6 +1,5 @@
1
1
  "use strict";
2
2
  var _setupTrackingContext = _interopRequireDefault(require("./lib/setupTrackingContext"));
3
- var _setupWatchingContext = _interopRequireDefault(require("./lib/setupWatchingContext"));
4
3
  var _processTailwindFeatures = _interopRequireDefault(require("./processTailwindFeatures"));
5
4
  var _sharedState = require("./lib/sharedState");
6
5
  function _interopRequireDefault(obj) {
@@ -18,8 +17,7 @@ module.exports = function tailwindcss(configOrPath) {
18
17
  return root;
19
18
  },
20
19
  function(root, result) {
21
- let setupContext = _sharedState.env.TAILWIND_MODE === 'watch' ? (0, _setupWatchingContext).default(configOrPath) : (0, _setupTrackingContext).default(configOrPath);
22
- (0, _processTailwindFeatures).default(setupContext)(root, result);
20
+ (0, _processTailwindFeatures).default((0, _setupTrackingContext).default(configOrPath))(root, result);
23
21
  },
24
22
  _sharedState.env.DEBUG && function(root) {
25
23
  console.timeEnd('JIT TOTAL');
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ exports.default = collapseDuplicateDeclarations;
6
+ function collapseDuplicateDeclarations() {
7
+ return (root)=>{
8
+ root.walkRules((node)=>{
9
+ let seen = new Map();
10
+ let droppable = new Set([]);
11
+ let byProperty = new Map();
12
+ node.walkDecls((decl)=>{
13
+ // This could happen if we have nested selectors. In that case the
14
+ // parent will loop over all its declarations but also the declarations
15
+ // of nested rules. With this we ensure that we are shallowly checking
16
+ // declarations.
17
+ if (decl.parent !== node) {
18
+ return;
19
+ }
20
+ if (seen.has(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);
39
+ }
40
+ seen.set(decl.prop, decl);
41
+ });
42
+ // Drop all the duplicate declarations with the exact same value we've
43
+ // already seen so far.
44
+ for (let decl1 of droppable){
45
+ decl1.remove();
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
+ }
69
+ });
70
+ };
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
+ }
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ exports.defaultExtractor = defaultExtractor;
6
+ const PATTERNS = [
7
+ /(?:\['([^'\s]+[^<>"'`\s:\\])')/.source,
8
+ /(?:\["([^"\s]+[^<>"'`\s:\\])")/.source,
9
+ /(?:\[`([^`\s]+[^<>"'`\s:\\])`)/.source,
10
+ /([^<>"'`\s]*\[\w*'[^"`\s]*'?\])/.source,
11
+ /([^<>"'`\s]*\[\w*"[^'`\s]*"?\])/.source,
12
+ /([^<>"'`\s]*\[\w*\('[^"'`\s]*'\)\])/.source,
13
+ /([^<>"'`\s]*\[\w*\("[^"'`\s]*"\)\])/.source,
14
+ /([^<>"'`\s]*\[\w*\('[^"`\s]*'\)\])/.source,
15
+ /([^<>"'`\s]*\[\w*\("[^'`\s]*"\)\])/.source,
16
+ /([^<>"'`\s]*\['[^"'`\s]*'\])/.source,
17
+ /([^<>"'`\s]*\["[^"'`\s]*"\])/.source,
18
+ /([^<>"'`\s]*\[[^<>"'`\s]*:[^\]\s]*\])/.source,
19
+ /([^<>"'`\s]*\[[^<>"'`\s]*:'[^"'`\s]*'\])/.source,
20
+ /([^<>"'`\s]*\[[^<>"'`\s]*:"[^"'`\s]*"\])/.source,
21
+ /([^<>"'`\s]*\[[^"'`\s]+\][^<>"'`\s]*)/.source,
22
+ /([^"'`\s]*[^<>"'`\s:\\])/.source,
23
+ /([^<>"'`\s]*[^"'`\s:\\])/.source,
24
+ ].join('|');
25
+ const BROAD_MATCH_GLOBAL_REGEXP = new RegExp(PATTERNS, 'g');
26
+ const INNER_MATCH_GLOBAL_REGEXP = /[^<>"'`\s.(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g;
27
+ function defaultExtractor(content) {
28
+ let broadMatches = content.matchAll(BROAD_MATCH_GLOBAL_REGEXP);
29
+ let innerMatches = content.match(INNER_MATCH_GLOBAL_REGEXP) || [];
30
+ let results = [
31
+ ...broadMatches,
32
+ ...innerMatches
33
+ ].flat().filter((v)=>v !== undefined
34
+ );
35
+ return results;
36
+ } // Regular utilities
37
+ // {{modifier}:}*{namespace}{-{suffix}}*{/{opacityModifier}}?
38
+ // Arbitrary values
39
+ // {{modifier}:}*{namespace}-[{arbitraryValue}]{/{opacityModifier}}?
40
+ // arbitraryValue: no whitespace, balanced quotes unless within quotes, balanced brackets unless within quotes
41
+ // Arbitrary properties
42
+ // {{modifier}:}*[{validCssPropertyName}:{arbitraryValue}]
@@ -6,12 +6,27 @@ exports.default = _default;
6
6
  function _default(_context) {
7
7
  return (root, result)=>{
8
8
  let found = false;
9
+ root.walkAtRules('tailwind', (node)=>{
10
+ if (found) return false;
11
+ if (node.parent && node.parent.type !== 'root') {
12
+ found = true;
13
+ node.warn(result, [
14
+ 'Nested @tailwind rules were detected, but are not supported.',
15
+ "Consider using a prefix to scope Tailwind's classes: https://tailwindcss.com/docs/configuration#prefix",
16
+ 'Alternatively, use the important selector strategy: https://tailwindcss.com/docs/configuration#selector-strategy',
17
+ ].join('\n'));
18
+ return false;
19
+ }
20
+ });
9
21
  root.walkRules((rule)=>{
10
22
  if (found) return false;
11
23
  rule.walkRules((nestedRule)=>{
12
24
  found = true;
13
- nestedRule.warn(result, // TODO: Improve this warning message
14
- 'Nested CSS detected, checkout the docs on how to support nesting: https://tailwindcss.com/docs/using-with-preprocessors#nesting');
25
+ nestedRule.warn(result, [
26
+ 'Nested CSS was detected, but CSS nesting has not been configured correctly.',
27
+ 'Please enable a CSS nesting plugin *before* Tailwind in your configuration.',
28
+ 'See how here: https://tailwindcss.com/docs/using-with-preprocessors#nesting',
29
+ ].join('\n'));
15
30
  return false;
16
31
  });
17
32
  });
@@ -7,6 +7,7 @@ var _dlv = _interopRequireDefault(require("dlv"));
7
7
  var _didyoumean = _interopRequireDefault(require("didyoumean"));
8
8
  var _transformThemeValue = _interopRequireDefault(require("../util/transformThemeValue"));
9
9
  var _postcssValueParser = _interopRequireDefault(require("postcss-value-parser"));
10
+ var _normalizeScreens = require("../util/normalizeScreens");
10
11
  var _buildMediaQuery = _interopRequireDefault(require("../util/buildMediaQuery"));
11
12
  var _toPath = require("../util/toPath");
12
13
  function _interopRequireDefault(obj) {
@@ -42,7 +43,7 @@ function listKeys(obj) {
42
43
  function validatePath(config, path, defaultValue) {
43
44
  const pathString = Array.isArray(path) ? pathToString(path) : path.replace(/^['"]+/g, '').replace(/['"]+$/g, '');
44
45
  const pathSegments = Array.isArray(path) ? path : (0, _toPath).toPath(pathString);
45
- const value = (0, _dlv).default(config.theme, pathString, defaultValue);
46
+ const value = (0, _dlv).default(config.theme, pathSegments, defaultValue);
46
47
  if (value === undefined) {
47
48
  let error = `'${pathString}' does not exist in your theme config.`;
48
49
  const parentSegments = pathSegments.slice(0, -1);
@@ -112,11 +113,11 @@ function extractArgs(node, vNodes, functions) {
112
113
  let args = [
113
114
  ''
114
115
  ];
115
- for (let vNode of vNodes){
116
- if (vNode.type === 'div' && vNode.value === ',') {
116
+ for (let vNode1 of vNodes){
117
+ if (vNode1.type === 'div' && vNode1.value === ',') {
117
118
  args.push('');
118
119
  } else {
119
- args[args.length - 1] += _postcssValueParser.default.stringify(vNode);
120
+ args[args.length - 1] += _postcssValueParser.default.stringify(vNode1);
120
121
  }
121
122
  }
122
123
  return args;
@@ -149,10 +150,13 @@ function _default({ tailwindConfig: config }) {
149
150
  },
150
151
  screen: (node, screen)=>{
151
152
  screen = screen.replace(/^['"]+/g, '').replace(/['"]+$/g, '');
152
- if (config.theme.screens[screen] === undefined) {
153
+ let screens = (0, _normalizeScreens).normalizeScreens(config.theme.screens);
154
+ let screenDefinition = screens.find(({ name })=>name === screen
155
+ );
156
+ if (!screenDefinition) {
153
157
  throw node.error(`The '${screen}' screen does not exist in your theme.`);
154
158
  }
155
- return (0, _buildMediaQuery).default(config.theme.screens[screen]);
159
+ return (0, _buildMediaQuery).default(screenDefinition);
156
160
  }
157
161
  };
158
162
  return (root)=>{
@@ -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,9 +13,32 @@ function _interopRequireDefault(obj) {
12
13
  default: obj
13
14
  };
14
15
  }
16
+ 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
+ }
15
39
  function prefix(context, selector) {
16
- let prefix = context.tailwindConfig.prefix;
17
- return typeof prefix === 'function' ? prefix(selector) : prefix + selector;
40
+ let prefix1 = context.tailwindConfig.prefix;
41
+ return typeof prefix1 === 'function' ? prefix1(selector) : prefix1 + selector;
18
42
  }
19
43
  function buildApplyCache(applyCandidates, context) {
20
44
  for (let candidate of applyCandidates){
@@ -51,45 +75,6 @@ function extractApplyCandidates(params) {
51
75
  false
52
76
  ];
53
77
  }
54
- function partitionApplyParents(root) {
55
- let applyParents = new Set();
56
- root.walkAtRules('apply', (rule)=>{
57
- applyParents.add(rule.parent);
58
- });
59
- for (let rule of applyParents){
60
- let nodeGroups = [];
61
- let lastGroup = [];
62
- for (let node of rule.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 = rule.clone({
85
- nodes: []
86
- });
87
- newParent.append(group);
88
- rule.after(newParent);
89
- }
90
- rule.remove();
91
- }
92
- }
93
78
  function processApply(root, context) {
94
79
  let applyCandidates = new Set();
95
80
  // Collect all @apply rules and candidates
@@ -127,8 +112,8 @@ function processApply(root, context) {
127
112
  */ // TODO: Should we use postcss-selector-parser for this instead?
128
113
  function replaceSelector(selector, utilitySelectors, candidate) {
129
114
  let needle = `.${(0, _escapeClassName).default(candidate)}`;
130
- let utilitySelectorsList = utilitySelectors.split(/\s*,\s*/g);
131
- return selector.split(/\s*,\s*/g).map((s)=>{
115
+ let utilitySelectorsList = utilitySelectors.split(/\s*\,(?![^(]*\))\s*/g);
116
+ return selector.split(/\s*\,(?![^(]*\))\s*/g).map((s)=>{
132
117
  let replaced = [];
133
118
  for (let utilitySelector of utilitySelectorsList){
134
119
  let replacedSelector = utilitySelector.replace(needle, s);
@@ -174,6 +159,36 @@ function processApply(root, context) {
174
159
  let siblings = [];
175
160
  for (let [applyCandidate, important, rules] of candidates){
176
161
  for (let [meta, node] of rules){
162
+ let parentClasses = extractClasses(parent);
163
+ let nodeClasses = extractClasses(node);
164
+ // Add base utility classes from the @apply node to the list of
165
+ // classes to check whether it intersects and therefore results in a
166
+ // circular dependency or not.
167
+ //
168
+ // E.g.:
169
+ // .foo {
170
+ // @apply hover:a; // This applies "a" but with a modifier
171
+ // }
172
+ //
173
+ // We only have to do that with base classes of the `node`, not of the `parent`
174
+ // E.g.:
175
+ // .hover\:foo {
176
+ // @apply bar;
177
+ // }
178
+ // .bar {
179
+ // @apply foo;
180
+ // }
181
+ //
182
+ // This should not result in a circular dependency because we are
183
+ // just applying `.foo` and the rule above is `.hover\:foo` which is
184
+ // unrelated. However, if we were to apply `hover:foo` then we _did_
185
+ // have to include this one.
186
+ nodeClasses = nodeClasses.concat(extractBaseCandidates(nodeClasses, context.tailwindConfig.separator));
187
+ let intersects = parentClasses.some((selector)=>nodeClasses.includes(selector)
188
+ );
189
+ if (intersects) {
190
+ throw node.error(`You cannot \`@apply\` the \`${applyCandidate}\` utility here because it creates a circular dependency.`);
191
+ }
177
192
  let root = _postcss.default.root({
178
193
  nodes: [
179
194
  node.clone()
@@ -182,6 +197,42 @@ function processApply(root, context) {
182
197
  let canRewriteSelector = node.type !== 'atrule' || node.type === 'atrule' && node.name !== 'keyframes';
183
198
  if (canRewriteSelector) {
184
199
  root.walkRules((rule)=>{
200
+ // Let's imagine you have the following structure:
201
+ //
202
+ // .foo {
203
+ // @apply bar;
204
+ // }
205
+ //
206
+ // @supports (a: b) {
207
+ // .bar {
208
+ // color: blue
209
+ // }
210
+ //
211
+ // .something-unrelated {}
212
+ // }
213
+ //
214
+ // In this case we want to apply `.bar` but it happens to be in
215
+ // an atrule node. We clone that node instead of the nested one
216
+ // because we still want that @supports rule to be there once we
217
+ // applied everything.
218
+ //
219
+ // However it happens to be that the `.something-unrelated` is
220
+ // also in that same shared @supports atrule. This is not good,
221
+ // and this should not be there. The good part is that this is
222
+ // a clone already and it can be safely removed. The question is
223
+ // how do we know we can remove it. Basically what we can do is
224
+ // match it against the applyCandidate that you want to apply. If
225
+ // it doesn't match the we can safely delete it.
226
+ //
227
+ // If we didn't do this, then the `replaceSelector` function
228
+ // would have replaced this with something that didn't exist and
229
+ // therefore it removed the selector altogether. In this specific
230
+ // case it would result in `{}` instead of `.something-unrelated {}`
231
+ if (!extractClasses(rule).some((candidate)=>candidate === applyCandidate
232
+ )) {
233
+ rule.remove();
234
+ return;
235
+ }
185
236
  rule.selector = replaceSelector(parent.selector, rule.selector, applyCandidate);
186
237
  rule.walkDecls((d)=>{
187
238
  d.important = meta.important || important;
@@ -203,7 +254,6 @@ function processApply(root, context) {
203
254
  let nodes = siblings.sort(([a], [z])=>(0, _bigSign).default(a.sort - z.sort)
204
255
  ).map((s)=>s[1]
205
256
  );
206
- // console.log(parent)
207
257
  // `parent` refers to the node at `.abc` in: .abc { @apply mt-2 }
208
258
  parent.after(nodes);
209
259
  }
@@ -222,7 +272,6 @@ function processApply(root, context) {
222
272
  }
223
273
  function expandApplyAtRules(context) {
224
274
  return (root)=>{
225
- partitionApplyParents(root);
226
275
  processApply(root, context);
227
276
  };
228
277
  }
@@ -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,27 +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]*\['[^"'`\s]*'\])/.source,
46
- /([^<>"'`\s]*\["[^"'`\s]*"\])/.source,
47
- /([^<>"'`\s]*\[[^"'`\s]+\][^<>"'`\s]*)/.source,
48
- /([^<>"'`\s]*[^"'`\s:])/.source
49
- ].join('|');
50
- const BROAD_MATCH_GLOBAL_REGEXP = new RegExp(PATTERNS, 'g');
51
- const INNER_MATCH_GLOBAL_REGEXP = /[^<>"'`\s.(){}[\]#=%]*[^<>"'`\s.(){}[\]#=%:]/g;
52
40
  const builtInExtractors = {
53
- DEFAULT: (content)=>{
54
- let broadMatches = content.match(BROAD_MATCH_GLOBAL_REGEXP) || [];
55
- let innerMatches = content.match(INNER_MATCH_GLOBAL_REGEXP) || [];
56
- return [
57
- ...broadMatches,
58
- ...innerMatches
59
- ];
60
- }
41
+ DEFAULT: _defaultExtractor.defaultExtractor
61
42
  };
62
43
  const builtInTransformers = {
63
44
  DEFAULT: (content)=>content
@@ -108,6 +89,7 @@ function buildStylesheet(rules, context) {
108
89
  );
109
90
  let returnValue = {
110
91
  base: new Set(),
92
+ defaults: new Set(),
111
93
  components: new Set(),
112
94
  utilities: new Set(),
113
95
  variants: new Set(),
@@ -130,6 +112,10 @@ function buildStylesheet(rules, context) {
130
112
  returnValue.base.add(rule);
131
113
  continue;
132
114
  }
115
+ if (sort & context.layerOrder.defaults) {
116
+ returnValue.defaults.add(rule);
117
+ continue;
118
+ }
133
119
  if (sort & context.layerOrder.components) {
134
120
  returnValue.components.add(rule);
135
121
  continue;
@@ -153,13 +139,15 @@ function expandTailwindAtRules(context) {
153
139
  utilities: null,
154
140
  variants: null
155
141
  };
156
- // Make sure this file contains Tailwind directives. If not, we can save
157
- // a lot of work and bail early. Also we don't have to register our touch
158
- // file as a dependency since the output of this CSS does not depend on
159
- // the source of any templates. Think Vue <style> blocks for example.
160
- root.walkAtRules('tailwind', (rule)=>{
161
- if (Object.keys(layerNodes).includes(rule.params)) {
162
- 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
+ }
163
151
  }
164
152
  });
165
153
  if (Object.values(layerNodes).every((n)=>n === null
@@ -178,6 +166,7 @@ function expandTailwindAtRules(context) {
178
166
  let extractor = getExtractor(context.tailwindConfig, extension);
179
167
  getClassCandidates(transformer(content), extractor, candidates, seen);
180
168
  }
169
+ env.DEBUG && console.timeEnd('Reading changed files');
181
170
  // ---
182
171
  // Generate the actual CSS
183
172
  let classCacheCount = context.classCache.size;
@@ -195,13 +184,16 @@ function expandTailwindAtRules(context) {
195
184
  ], context);
196
185
  }
197
186
  env.DEBUG && console.timeEnd('Build stylesheet');
198
- 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;
199
188
  // ---
200
189
  // Replace any Tailwind directives with generated CSS
201
190
  if (layerNodes.base) {
202
191
  layerNodes.base.before((0, _cloneNodes).default([
203
- ...baseNodes
192
+ ...baseNodes,
193
+ ...defaultNodes
204
194
  ], layerNodes.base.source));
195
+ }
196
+ if (layerNodes.base) {
205
197
  layerNodes.base.remove();
206
198
  }
207
199
  if (layerNodes.components) {
@@ -226,6 +218,13 @@ function expandTailwindAtRules(context) {
226
218
  ...screenNodes
227
219
  ], root.source));
228
220
  }
221
+ // If we've got a utility layer and no utilities are generated there's likely something wrong
222
+ // TODO: Detect utility variants only
223
+ if (layerNodes.utilities && utilityNodes.size === 0 && screenNodes.size === 0) {
224
+ _log.default.warn('content-problems', [
225
+ 'No utilities were generated there is likely a problem with the `content` key in the tailwind config. For more information see the documentation: https://tailwindcss.com/docs/content-configuration',
226
+ ]);
227
+ }
229
228
  // ---
230
229
  if (env.DEBUG) {
231
230
  console.log('Potential classes: ', candidates.size);