tailwindcss 0.0.0-insiders.d2b53cd → 0.0.0-insiders.d2fdf9e

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 (143) hide show
  1. package/CHANGELOG.md +364 -2
  2. package/LICENSE +1 -2
  3. package/README.md +8 -4
  4. package/colors.d.ts +3 -0
  5. package/colors.js +2 -1
  6. package/defaultConfig.d.ts +3 -0
  7. package/defaultConfig.js +2 -1
  8. package/defaultTheme.d.ts +3 -0
  9. package/defaultTheme.js +2 -1
  10. package/lib/cli-peer-dependencies.js +10 -5
  11. package/lib/cli.js +306 -203
  12. package/lib/constants.js +9 -9
  13. package/lib/corePluginList.js +10 -1
  14. package/lib/corePlugins.js +1835 -1760
  15. package/lib/css/preflight.css +19 -13
  16. package/lib/featureFlags.js +18 -15
  17. package/lib/index.js +17 -8
  18. package/lib/lib/cacheInvalidation.js +69 -0
  19. package/lib/lib/collapseAdjacentRules.js +30 -14
  20. package/lib/lib/collapseDuplicateDeclarations.js +80 -0
  21. package/lib/lib/defaultExtractor.js +187 -0
  22. package/lib/lib/detectNesting.js +17 -2
  23. package/lib/lib/evaluateTailwindFunctions.js +40 -24
  24. package/lib/lib/expandApplyAtRules.js +414 -157
  25. package/lib/lib/expandTailwindAtRules.js +145 -126
  26. package/lib/lib/generateRules.js +403 -103
  27. package/lib/lib/getModuleDependencies.js +14 -14
  28. package/lib/lib/normalizeTailwindDirectives.js +43 -35
  29. package/lib/lib/partitionApplyAtRules.js +53 -0
  30. package/lib/lib/regex.js +53 -0
  31. package/lib/lib/resolveDefaultsAtRules.js +83 -65
  32. package/lib/lib/setupContextUtils.js +315 -204
  33. package/lib/lib/setupTrackingContext.js +60 -56
  34. package/lib/lib/sharedState.js +38 -5
  35. package/lib/lib/substituteScreenAtRules.js +9 -6
  36. package/{nesting → lib/postcss-plugins/nesting}/README.md +2 -2
  37. package/lib/postcss-plugins/nesting/index.js +17 -0
  38. package/lib/postcss-plugins/nesting/plugin.js +85 -0
  39. package/lib/processTailwindFeatures.js +19 -9
  40. package/lib/public/colors.js +241 -241
  41. package/lib/public/resolve-config.js +5 -5
  42. package/lib/util/buildMediaQuery.js +13 -24
  43. package/lib/util/cloneDeep.js +1 -1
  44. package/lib/util/cloneNodes.js +12 -1
  45. package/lib/util/color.js +43 -32
  46. package/lib/util/createPlugin.js +1 -2
  47. package/lib/util/createUtilityPlugin.js +11 -15
  48. package/lib/util/dataTypes.js +114 -74
  49. package/lib/util/defaults.js +6 -0
  50. package/lib/util/escapeClassName.js +5 -5
  51. package/lib/util/escapeCommas.js +1 -1
  52. package/lib/util/flattenColorPalette.js +2 -4
  53. package/lib/util/formatVariantSelector.js +194 -0
  54. package/lib/util/getAllConfigs.js +13 -5
  55. package/lib/util/hashConfig.js +5 -5
  56. package/lib/util/isKeyframeRule.js +1 -1
  57. package/lib/util/isPlainObject.js +1 -1
  58. package/lib/util/isValidArbitraryValue.js +64 -0
  59. package/lib/util/log.js +11 -7
  60. package/lib/util/nameClass.js +7 -6
  61. package/lib/util/negateValue.js +4 -4
  62. package/lib/util/normalizeConfig.js +84 -45
  63. package/lib/util/normalizeScreens.js +59 -0
  64. package/lib/util/parseAnimationValue.js +56 -56
  65. package/lib/util/parseBoxShadowValue.js +76 -0
  66. package/lib/util/parseDependency.js +32 -32
  67. package/lib/util/parseObjectStyles.js +6 -6
  68. package/lib/util/pluginUtils.js +34 -165
  69. package/lib/util/prefixSelector.js +4 -7
  70. package/lib/util/resolveConfig.js +115 -66
  71. package/lib/util/resolveConfigPath.js +17 -18
  72. package/lib/util/responsive.js +6 -6
  73. package/lib/util/splitAtTopLevelOnly.js +72 -0
  74. package/lib/util/toColorValue.js +1 -2
  75. package/lib/util/toPath.js +6 -1
  76. package/lib/util/transformThemeValue.js +42 -34
  77. package/lib/util/validateConfig.js +21 -0
  78. package/lib/util/withAlphaVariable.js +19 -19
  79. package/nesting/index.js +2 -12
  80. package/package.json +39 -40
  81. package/peers/index.js +11511 -10819
  82. package/plugin.d.ts +11 -0
  83. package/plugin.js +2 -1
  84. package/resolveConfig.js +2 -1
  85. package/scripts/generate-types.js +52 -0
  86. package/src/cli-peer-dependencies.js +7 -1
  87. package/src/cli.js +164 -30
  88. package/src/corePluginList.js +1 -1
  89. package/src/corePlugins.js +540 -535
  90. package/src/css/preflight.css +19 -13
  91. package/src/featureFlags.js +5 -5
  92. package/src/index.js +14 -6
  93. package/src/lib/cacheInvalidation.js +52 -0
  94. package/src/lib/collapseAdjacentRules.js +21 -2
  95. package/src/lib/collapseDuplicateDeclarations.js +93 -0
  96. package/src/lib/defaultExtractor.js +192 -0
  97. package/src/lib/detectNesting.js +22 -3
  98. package/src/lib/evaluateTailwindFunctions.js +24 -7
  99. package/src/lib/expandApplyAtRules.js +442 -154
  100. package/src/lib/expandTailwindAtRules.js +79 -37
  101. package/src/lib/generateRules.js +400 -83
  102. package/src/lib/normalizeTailwindDirectives.js +7 -1
  103. package/src/lib/partitionApplyAtRules.js +52 -0
  104. package/src/lib/regex.js +74 -0
  105. package/src/lib/resolveDefaultsAtRules.js +35 -10
  106. package/src/lib/setupContextUtils.js +273 -112
  107. package/src/lib/setupTrackingContext.js +12 -7
  108. package/src/lib/sharedState.js +42 -4
  109. package/src/lib/substituteScreenAtRules.js +6 -3
  110. package/src/postcss-plugins/nesting/README.md +42 -0
  111. package/src/postcss-plugins/nesting/index.js +13 -0
  112. package/src/postcss-plugins/nesting/plugin.js +80 -0
  113. package/src/processTailwindFeatures.js +14 -2
  114. package/src/util/buildMediaQuery.js +14 -18
  115. package/src/util/cloneNodes.js +14 -1
  116. package/src/util/color.js +31 -14
  117. package/src/util/dataTypes.js +56 -16
  118. package/src/util/defaults.js +6 -0
  119. package/src/util/formatVariantSelector.js +213 -0
  120. package/src/util/getAllConfigs.js +7 -0
  121. package/src/util/isValidArbitraryValue.js +61 -0
  122. package/src/util/log.js +10 -6
  123. package/src/util/nameClass.js +1 -1
  124. package/src/util/normalizeConfig.js +32 -3
  125. package/src/util/normalizeScreens.js +45 -0
  126. package/src/util/parseBoxShadowValue.js +72 -0
  127. package/src/util/pluginUtils.js +15 -138
  128. package/src/util/prefixSelector.js +7 -8
  129. package/src/util/resolveConfig.js +97 -15
  130. package/src/util/splitAtTopLevelOnly.js +71 -0
  131. package/src/util/toPath.js +23 -1
  132. package/src/util/transformThemeValue.js +24 -7
  133. package/src/util/validateConfig.js +13 -0
  134. package/stubs/defaultConfig.stub.js +47 -17
  135. package/types/config.d.ts +325 -0
  136. package/types/generated/.gitkeep +0 -0
  137. package/types/generated/colors.d.ts +276 -0
  138. package/types/generated/corePluginList.d.ts +1 -0
  139. package/types/index.d.ts +1 -0
  140. package/types.d.ts +1 -0
  141. package/lib/lib/setupWatchingContext.js +0 -284
  142. package/nesting/plugin.js +0 -41
  143. 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
  /*
@@ -155,6 +160,7 @@ select,
155
160
  textarea {
156
161
  font-family: inherit; /* 1 */
157
162
  font-size: 100%; /* 1 */
163
+ font-weight: inherit; /* 1 */
158
164
  line-height: inherit; /* 1 */
159
165
  color: inherit; /* 1 */
160
166
  margin: 0; /* 2 */
@@ -283,7 +289,8 @@ legend {
283
289
  }
284
290
 
285
291
  ol,
286
- ul {
292
+ ul,
293
+ menu {
287
294
  list-style: none;
288
295
  margin: 0;
289
296
  padding: 0;
@@ -304,7 +311,7 @@ textarea {
304
311
 
305
312
  input::placeholder,
306
313
  textarea::placeholder {
307
- opacity: 1; /* 1 */
314
+ opacity: 1; /* 1 */
308
315
  color: theme('colors.gray.400', #9ca3af); /* 2 */
309
316
  }
310
317
 
@@ -317,6 +324,13 @@ button,
317
324
  cursor: pointer;
318
325
  }
319
326
 
327
+ /*
328
+ Make sure disabled buttons don't get the pointer cursor.
329
+ */
330
+ :disabled {
331
+ cursor: default;
332
+ }
333
+
320
334
  /*
321
335
  1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
322
336
  2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
@@ -344,11 +358,3 @@ video {
344
358
  max-width: 100%;
345
359
  height: auto;
346
360
  }
347
-
348
- /*
349
- Ensure the default browser behavior of the `hidden` attribute.
350
- */
351
-
352
- [hidden] {
353
- display: none;
354
- }
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  exports.flagEnabled = flagEnabled;
6
6
  exports.issueFlagNotices = issueFlagNotices;
7
7
  exports.default = void 0;
8
- var _chalk = _interopRequireDefault(require("chalk"));
8
+ var _picocolors = _interopRequireDefault(require("picocolors"));
9
9
  var _log = _interopRequireDefault(require("./util/log"));
10
10
  function _interopRequireDefault(obj) {
11
11
  return obj && obj.__esModule ? obj : {
@@ -13,34 +13,37 @@ function _interopRequireDefault(obj) {
13
13
  };
14
14
  }
15
15
  let defaults = {
16
- optimizeUniversalDefaults: true
16
+ optimizeUniversalDefaults: false
17
17
  };
18
18
  let featureFlags = {
19
- future: [],
19
+ future: [
20
+ "hoverOnlyWhenSupported",
21
+ "respectDefaultRingColorOpacity"
22
+ ],
20
23
  experimental: [
21
- 'optimizeUniversalDefaults'
24
+ "optimizeUniversalDefaults",
25
+ "variantGrouping"
22
26
  ]
23
27
  };
24
28
  function flagEnabled(config, flag) {
25
29
  if (featureFlags.future.includes(flag)) {
26
30
  var ref;
27
31
  var ref1, ref2;
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);
32
+ 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
33
  }
30
34
  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);
35
+ var ref3;
36
+ var ref4, ref5;
37
+ 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
38
  }
35
39
  return false;
36
40
  }
37
41
  function experimentalFlagsEnabled(config) {
38
- if (config.experimental === 'all') {
42
+ if (config.experimental === "all") {
39
43
  return featureFlags.experimental;
40
44
  }
41
45
  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]
46
+ 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
47
  );
45
48
  }
46
49
  function issueFlagNotices(config) {
@@ -48,11 +51,11 @@ function issueFlagNotices(config) {
48
51
  return;
49
52
  }
50
53
  if (experimentalFlagsEnabled(config).length > 0) {
51
- let changes = experimentalFlagsEnabled(config).map((s)=>_chalk.default.yellow(s)
52
- ).join(', ');
53
- _log.default.warn('experimental-flags-enabled', [
54
+ let changes = experimentalFlagsEnabled(config).map((s)=>_picocolors.default.yellow(s)
55
+ ).join(", ");
56
+ _log.default.warn("experimental-flags-enabled", [
54
57
  `You have enabled experimental features: ${changes}`,
55
- 'Experimental features in Tailwind CSS are not covered by semver, may introduce breaking changes, and can change at any time.',
58
+ "Experimental features in Tailwind CSS are not covered by semver, may introduce breaking changes, and can change at any time.",
56
59
  ]);
57
60
  }
58
61
  }
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) {
@@ -10,20 +9,30 @@ function _interopRequireDefault(obj) {
10
9
  }
11
10
  module.exports = function tailwindcss(configOrPath) {
12
11
  return {
13
- postcssPlugin: 'tailwindcss',
12
+ postcssPlugin: "tailwindcss",
14
13
  plugins: [
15
14
  _sharedState.env.DEBUG && function(root) {
16
- console.log('\n');
17
- console.time('JIT TOTAL');
15
+ console.log("\n");
16
+ console.time("JIT TOTAL");
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
+ let context = (0, _setupTrackingContext).default(configOrPath);
21
+ if (root.type === "document") {
22
+ let roots = root.nodes.filter((node)=>node.type === "root"
23
+ );
24
+ for (const root1 of roots){
25
+ if (root1.type === "root") {
26
+ (0, _processTailwindFeatures).default(context)(root1, result);
27
+ }
28
+ }
29
+ return;
30
+ }
31
+ (0, _processTailwindFeatures).default(context)(root, result);
23
32
  },
24
33
  _sharedState.env.DEBUG && function(root) {
25
- console.timeEnd('JIT TOTAL');
26
- console.log('\n');
34
+ console.timeEnd("JIT TOTAL");
35
+ console.log("\n");
27
36
  return root;
28
37
  },
29
38
  ].filter(Boolean)
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ exports.hasContentChanged = hasContentChanged;
6
+ var _crypto = _interopRequireDefault(require("crypto"));
7
+ var sharedState = _interopRequireWildcard(require("./sharedState"));
8
+ function _interopRequireDefault(obj) {
9
+ return obj && obj.__esModule ? obj : {
10
+ default: obj
11
+ };
12
+ }
13
+ function _interopRequireWildcard(obj) {
14
+ if (obj && obj.__esModule) {
15
+ return obj;
16
+ } else {
17
+ var newObj = {};
18
+ if (obj != null) {
19
+ for(var key in obj){
20
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
21
+ var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {};
22
+ if (desc.get || desc.set) {
23
+ Object.defineProperty(newObj, key, desc);
24
+ } else {
25
+ newObj[key] = obj[key];
26
+ }
27
+ }
28
+ }
29
+ }
30
+ newObj.default = obj;
31
+ return newObj;
32
+ }
33
+ }
34
+ /**
35
+ * Calculate the hash of a string.
36
+ *
37
+ * This doesn't need to be cryptographically secure or
38
+ * anything like that since it's used only to detect
39
+ * when the CSS changes to invalidate the context.
40
+ *
41
+ * This is wrapped in a try/catch because it's really dependent
42
+ * on how Node itself is build and the environment and OpenSSL
43
+ * version / build that is installed on the user's machine.
44
+ *
45
+ * Based on the environment this can just outright fail.
46
+ *
47
+ * See https://github.com/nodejs/node/issues/40455
48
+ *
49
+ * @param {string} str
50
+ */ function getHash(str) {
51
+ try {
52
+ return _crypto.default.createHash("md5").update(str, "utf-8").digest("binary");
53
+ } catch (err) {
54
+ return "";
55
+ }
56
+ }
57
+ function hasContentChanged(sourcePath, root) {
58
+ let css = root.toString();
59
+ // We only care about files with @tailwind directives
60
+ // Other files use an existing context
61
+ if (!css.includes("@tailwind")) {
62
+ return false;
63
+ }
64
+ let existingHash = sharedState.sourceHashMap.get(sourcePath);
65
+ let rootHash = getHash(css);
66
+ let didChange = existingHash !== rootHash;
67
+ sharedState.sourceHashMap.set(sourcePath, rootHash);
68
+ return didChange;
69
+ }
@@ -3,18 +3,8 @@ Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
5
  exports.default = collapseAdjacentRules;
6
- let comparisonMap = {
7
- atrule: [
8
- 'name',
9
- 'params'
10
- ],
11
- rule: [
12
- 'selector'
13
- ]
14
- };
15
- let types = new Set(Object.keys(comparisonMap));
16
6
  function collapseAdjacentRules() {
17
- return (root)=>{
7
+ function collapseRulesIn(root) {
18
8
  let currentRule = null;
19
9
  root.each((node)=>{
20
10
  if (!types.has(node.type)) {
@@ -27,15 +17,41 @@ function collapseAdjacentRules() {
27
17
  }
28
18
  let properties = comparisonMap[node.type];
29
19
  var _property, _property1;
30
- if (node.type === 'atrule' && node.name === 'font-face') {
20
+ if (node.type === "atrule" && node.name === "font-face") {
31
21
  currentRule = node;
32
- } else if (properties.every((property)=>((_property = node[property]) !== null && _property !== void 0 ? _property : '').replace(/\s+/g, ' ') === ((_property1 = currentRule[property]) !== null && _property1 !== void 0 ? _property1 : '').replace(/\s+/g, ' ')
22
+ } else if (properties.every((property)=>((_property = node[property]) !== null && _property !== void 0 ? _property : "").replace(/\s+/g, " ") === ((_property1 = currentRule[property]) !== null && _property1 !== void 0 ? _property1 : "").replace(/\s+/g, " ")
33
23
  )) {
34
- currentRule.append(node.nodes);
24
+ // An AtRule may not have children (for example if we encounter duplicate @import url(…) rules)
25
+ if (node.nodes) {
26
+ currentRule.append(node.nodes);
27
+ }
35
28
  node.remove();
36
29
  } else {
37
30
  currentRule = node;
38
31
  }
39
32
  });
33
+ // After we've collapsed adjacent rules & at-rules, we need to collapse
34
+ // adjacent rules & at-rules that are children of at-rules.
35
+ // We do not care about nesting rules because Tailwind CSS
36
+ // explicitly does not handle rule nesting on its own as
37
+ // the user is expected to use a nesting plugin
38
+ root.each((node)=>{
39
+ if (node.type === "atrule") {
40
+ collapseRulesIn(node);
41
+ }
42
+ });
43
+ }
44
+ return (root)=>{
45
+ collapseRulesIn(root);
40
46
  };
41
47
  }
48
+ let comparisonMap = {
49
+ atrule: [
50
+ "name",
51
+ "params"
52
+ ],
53
+ rule: [
54
+ "selector"
55
+ ]
56
+ };
57
+ let types = new Set(Object.keys(comparisonMap));
@@ -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,187 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ exports.defaultExtractor = defaultExtractor;
6
+ var _featureFlagsJs = require("../featureFlags.js");
7
+ var regex = _interopRequireWildcard(require("./regex"));
8
+ function _interopRequireWildcard(obj) {
9
+ if (obj && obj.__esModule) {
10
+ return obj;
11
+ } else {
12
+ var newObj = {};
13
+ if (obj != null) {
14
+ for(var key in obj){
15
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
16
+ var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {};
17
+ if (desc.get || desc.set) {
18
+ Object.defineProperty(newObj, key, desc);
19
+ } else {
20
+ newObj[key] = obj[key];
21
+ }
22
+ }
23
+ }
24
+ }
25
+ newObj.default = obj;
26
+ return newObj;
27
+ }
28
+ }
29
+ function defaultExtractor(context) {
30
+ let patterns = Array.from(buildRegExps(context));
31
+ /**
32
+ * @param {string} content
33
+ */ return (content)=>{
34
+ /** @type {(string|string)[]} */ let results = [];
35
+ for (let pattern of patterns){
36
+ var ref;
37
+ results.push(...(ref = content.match(pattern)) !== null && ref !== void 0 ? ref : []);
38
+ }
39
+ return results.filter((v)=>v !== undefined
40
+ ).map(clipAtBalancedParens);
41
+ };
42
+ }
43
+ function* buildRegExps(context) {
44
+ let separator = context.tailwindConfig.separator;
45
+ let variantGroupingEnabled = (0, _featureFlagsJs).flagEnabled(context.tailwindConfig, "variantGrouping");
46
+ let utility = regex.any([
47
+ // Arbitrary properties
48
+ /\[[^\s:'"]+:[^\s\]]+\]/,
49
+ // Utilities
50
+ regex.pattern([
51
+ // Utility Name / Group Name
52
+ /-?(?:\w+)/,
53
+ // Normal/Arbitrary values
54
+ regex.optional(regex.any([
55
+ regex.pattern([
56
+ // Arbitrary values
57
+ /-\[[^\s:]+\]/,
58
+ // Not immediately followed by an `{[(`
59
+ /(?![{([]])/,
60
+ // optionally followed by an opacity modifier
61
+ /(?:\/[^\s'"\\$]*)?/,
62
+ ]),
63
+ regex.pattern([
64
+ // Arbitrary values
65
+ /-\[[^\s]+\]/,
66
+ // Not immediately followed by an `{[(`
67
+ /(?![{([]])/,
68
+ // optionally followed by an opacity modifier
69
+ /(?:\/[^\s'"\\$]*)?/,
70
+ ]),
71
+ // Normal values w/o quotes — may include an opacity modifier
72
+ /[-\/][^\s'"\\$={]*/,
73
+ ])),
74
+ ]),
75
+ ]);
76
+ yield regex.pattern([
77
+ // Variants
78
+ "((?=((",
79
+ regex.any([
80
+ regex.pattern([
81
+ /([^\s"'\[\\]+-)?\[[^\s"'\\]+\]/,
82
+ separator
83
+ ]),
84
+ regex.pattern([
85
+ /[^\s"'\[\\]+/,
86
+ separator
87
+ ]),
88
+ ], true),
89
+ ")+))\\2)?",
90
+ // Important (optional)
91
+ /!?/,
92
+ variantGroupingEnabled ? regex.any([
93
+ // Or any of those things but grouped separated by commas
94
+ regex.pattern([
95
+ /\(/,
96
+ utility,
97
+ regex.zeroOrMore([
98
+ /,/,
99
+ utility
100
+ ]),
101
+ /\)/
102
+ ]),
103
+ // Arbitrary properties, constrained utilities, arbitrary values, etc…
104
+ utility,
105
+ ]) : utility,
106
+ ]);
107
+ // 5. Inner matches
108
+ // yield /[^<>"'`\s.(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g
109
+ }
110
+ // We want to capture any "special" characters
111
+ // AND the characters immediately following them (if there is one)
112
+ let SPECIALS = /([\[\]'"`])([^\[\]'"`])?/g;
113
+ let ALLOWED_CLASS_CHARACTERS = /[^"'`\s<>\]]+/;
114
+ /**
115
+ * Clips a string ensuring that parentheses, quotes, etc… are balanced
116
+ * Used for arbitrary values only
117
+ *
118
+ * We will go past the end of the balanced parens until we find a non-class character
119
+ *
120
+ * Depth matching behavior:
121
+ * w-[calc(100%-theme('spacing[some_key][1.5]'))]']
122
+ * ┬ ┬ ┬┬ ┬ ┬┬ ┬┬┬┬┬┬┬
123
+ * 1 2 3 4 34 3 210 END
124
+ * ╰────┴──────────┴────────┴────────┴┴───┴─┴┴┴
125
+ *
126
+ * @param {string} input
127
+ */ function clipAtBalancedParens(input) {
128
+ // We are care about this for arbitrary values
129
+ if (!input.includes("-[")) {
130
+ return input;
131
+ }
132
+ let depth = 0;
133
+ let openStringTypes = [];
134
+ // Find all parens, brackets, quotes, etc
135
+ // Stop when we end at a balanced pair
136
+ // This is naive and will treat mismatched parens as balanced
137
+ // This shouldn't be a problem in practice though
138
+ let matches = input.matchAll(SPECIALS);
139
+ // We can't use lookbehind assertions because we have to support Safari
140
+ // So, instead, we've emulated it using capture groups and we'll re-work the matches to accommodate
141
+ matches = Array.from(matches).flatMap((match)=>{
142
+ const [, ...groups] = match;
143
+ return groups.map((group, idx)=>Object.assign([], match, {
144
+ index: match.index + idx,
145
+ 0: group
146
+ })
147
+ );
148
+ });
149
+ for (let match1 of matches){
150
+ let char = match1[0];
151
+ let inStringType = openStringTypes[openStringTypes.length - 1];
152
+ if (char === inStringType) {
153
+ openStringTypes.pop();
154
+ } else if (char === "'" || char === '"' || char === "`") {
155
+ openStringTypes.push(char);
156
+ }
157
+ if (inStringType) {
158
+ continue;
159
+ } else if (char === "[") {
160
+ depth++;
161
+ continue;
162
+ } else if (char === "]") {
163
+ depth--;
164
+ continue;
165
+ }
166
+ // We've gone one character past the point where we should stop
167
+ // This means that there was an extra closing `]`
168
+ // We'll clip to just before it
169
+ if (depth < 0) {
170
+ return input.substring(0, match1.index);
171
+ }
172
+ // We've finished balancing the brackets but there still may be characters that can be included
173
+ // For example in the class `text-[#336699]/[.35]`
174
+ // The depth goes to `0` at the closing `]` but goes up again at the `[`
175
+ // If we're at zero and encounter a non-class character then we clip the class there
176
+ if (depth === 0 && !ALLOWED_CLASS_CHARACTERS.test(char)) {
177
+ return input.substring(0, match1.index);
178
+ }
179
+ }
180
+ return input;
181
+ } // Regular utilities
182
+ // {{modifier}:}*{namespace}{-{suffix}}*{/{opacityModifier}}?
183
+ // Arbitrary values
184
+ // {{modifier}:}*{namespace}-[{arbitraryValue}]{/{opacityModifier}}?
185
+ // arbitraryValue: no whitespace, balanced quotes unless within quotes, balanced brackets unless within quotes
186
+ // Arbitrary properties
187
+ // {{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
  });