tailwindcss 3.0.4 → 3.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,13 +7,41 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
- - Nothing yet!
10
+ ### Fixed
11
+
12
+ - Reduce specificity of `abbr` rule in preflight ([#6671](https://github.com/tailwindlabs/tailwindcss/pull/6671))
13
+ - Support HSL with hue units in arbitrary values ([#6726](https://github.com/tailwindlabs/tailwindcss/pull/6726))
14
+ - Add `node16-linux-arm64` target for standalone CLI ([#6693](https://github.com/tailwindlabs/tailwindcss/pull/6693))
15
+
16
+ ## [3.0.7] - 2021-12-17
17
+
18
+ ### Fixed
19
+
20
+ - Don't mutate custom color palette when overriding per-plugin colors ([#6546](https://github.com/tailwindlabs/tailwindcss/pull/6546))
21
+ - Improve circular dependency detection when using `@apply` ([#6588](https://github.com/tailwindlabs/tailwindcss/pull/6588))
22
+ - Only generate variants for non-`user` layers ([#6589](https://github.com/tailwindlabs/tailwindcss/pull/6589))
23
+ - Properly extract classes with arbitrary values in arrays and classes followed by escaped quotes ([#6590](https://github.com/tailwindlabs/tailwindcss/pull/6590))
24
+ - Improve jsx interpolation candidate matching ([#6593](https://github.com/tailwindlabs/tailwindcss/pull/6593))
25
+ - Ensure `@apply` of a rule inside an AtRule works ([#6594](https://github.com/tailwindlabs/tailwindcss/pull/6594))
26
+
27
+ ## [3.0.6] - 2021-12-16
28
+
29
+ ### Fixed
30
+
31
+ - Support square bracket notation in paths ([#6519](https://github.com/tailwindlabs/tailwindcss/pull/6519))
32
+ - Ensure all plugins are executed for a given candidate ([#6540](https://github.com/tailwindlabs/tailwindcss/pull/6540))
33
+
34
+ ## [3.0.5] - 2021-12-15
35
+
36
+ ### Fixed
37
+
38
+ - Revert: add `li` to list-style reset ([9777562d](https://github.com/tailwindlabs/tailwindcss/commit/9777562da37ee631bbf77374c0d14825f09ef9af))
11
39
 
12
40
  ## [3.0.4] - 2021-12-15
13
41
 
14
42
  ### Fixed
15
43
 
16
- - Insert always on defaults layer in correct spot ([#6526](https://github.com/tailwindlabs/tailwindcss/pull/6526))
44
+ - Insert always-on defaults layer in correct spot ([#6526](https://github.com/tailwindlabs/tailwindcss/pull/6526))
17
45
 
18
46
  ## [3.0.3] - 2021-12-15
19
47
 
@@ -21,13 +49,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
21
49
 
22
50
  - Warn about invalid globs in `content` ([#6449](https://github.com/tailwindlabs/tailwindcss/pull/6449))
23
51
  - Add standalone tailwindcss CLI ([#6506](https://github.com/tailwindlabs/tailwindcss/pull/6506))
52
+ - Add `li` to list-style reset ([00f60e6](https://github.com/tailwindlabs/tailwindcss/commit/00f60e61013c6e4e3419e4b699371a13eb30b75d))
24
53
 
25
54
  ### Fixed
26
55
 
27
56
  - Don't output unparsable values ([#6469](https://github.com/tailwindlabs/tailwindcss/pull/6469))
28
57
  - Fix text decoration utilities from overriding the new text decoration color/style/thickness utilities when used with a modifier ([#6378](https://github.com/tailwindlabs/tailwindcss/pull/6378))
29
58
  - Move defaults to their own always-on layer ([#6500](https://github.com/tailwindlabs/tailwindcss/pull/6500))
30
- - Support negative values in safelist patterns ([6480](https://github.com/tailwindlabs/tailwindcss/pull/6480))
59
+ - Support negative values in safelist patterns ([#6480](https://github.com/tailwindlabs/tailwindcss/pull/6480))
31
60
 
32
61
  ## [3.0.2] - 2021-12-13
33
62
 
@@ -1716,7 +1745,10 @@ No release notes
1716
1745
 
1717
1746
  - Everything!
1718
1747
 
1719
- [unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.4...HEAD
1748
+ [unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.7...HEAD
1749
+ [3.0.7]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.6...v3.0.7
1750
+ [3.0.6]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.5...v3.0.6
1751
+ [3.0.5]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.4...v3.0.5
1720
1752
  [3.0.4]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.3...v3.0.4
1721
1753
  [3.0.3]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.2...v3.0.3
1722
1754
  [3.0.2]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.1...v3.0.2
package/README.md CHANGED
@@ -1,10 +1,14 @@
1
1
  <p>
2
- <a href="https://tailwindcss.com/" target="_blank">
3
- <img alt="Tailwind CSS" width="350" src="https://refactoringui.nyc3.cdn.digitaloceanspaces.com/tailwind-logo-sticker.svg">
4
- </a><br>
5
- A utility-first CSS framework for rapidly building custom user interfaces.
2
+ <a href="https://tailwindcss.com/#gh-light-mode-only" target="_blank">
3
+ <img src="./.github/logo-light.svg" alt="Tailwind CSS" width="350" height="70">
4
+ </a>
5
+ <a href="https://tailwindcss.com/#gh-dark-mode-only" target="_blank">
6
+ <img src="./.github/logo-dark.svg" alt="Tailwind CSS" width="350" height="70">
7
+ </a>
6
8
  </p>
7
9
 
10
+ A utility-first CSS framework for rapidly building custom user interfaces.
11
+
8
12
  <p>
9
13
  <a href="https://github.com/tailwindlabs/tailwindcss/actions"><img src="https://img.shields.io/github/workflow/status/tailwindlabs/tailwindcss/Node.js%20CI" alt="Build Status"></a>
10
14
  <a href="https://www.npmjs.com/package/tailwindcss"><img src="https://img.shields.io/npm/dt/tailwindcss.svg" alt="Total Downloads"></a>
@@ -58,7 +58,7 @@ hr {
58
58
  Add the correct text decoration in Chrome, Edge, and Safari.
59
59
  */
60
60
 
61
- abbr[title] {
61
+ abbr:where([title]) {
62
62
  text-decoration: underline dotted;
63
63
  }
64
64
 
@@ -289,7 +289,6 @@ legend {
289
289
 
290
290
  ol,
291
291
  ul,
292
- li,
293
292
  menu {
294
293
  list-style: none;
295
294
  margin: 0;
@@ -0,0 +1,40 @@
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:\\])/.source,
22
+ ].join('|');
23
+ const BROAD_MATCH_GLOBAL_REGEXP = new RegExp(PATTERNS, 'g');
24
+ const INNER_MATCH_GLOBAL_REGEXP = /[^<>"'`\s.(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g;
25
+ function defaultExtractor(content) {
26
+ let broadMatches = content.matchAll(BROAD_MATCH_GLOBAL_REGEXP);
27
+ let innerMatches = content.match(INNER_MATCH_GLOBAL_REGEXP) || [];
28
+ let results = [
29
+ ...broadMatches,
30
+ ...innerMatches
31
+ ].flat().filter((v)=>v !== undefined
32
+ );
33
+ return results;
34
+ } // Regular utilities
35
+ // {{modifier}:}*{namespace}{-{suffix}}*{/{opacityModifier}}?
36
+ // Arbitrary values
37
+ // {{modifier}:}*{namespace}-[{arbitraryValue}]{/{opacityModifier}}?
38
+ // arbitraryValue: no whitespace, balanced quotes unless within quotes, balanced brackets unless within quotes
39
+ // Arbitrary properties
40
+ // {{modifier}:}*[{validCssPropertyName}:{arbitraryValue}]
@@ -43,7 +43,7 @@ function listKeys(obj) {
43
43
  function validatePath(config, path, defaultValue) {
44
44
  const pathString = Array.isArray(path) ? pathToString(path) : path.replace(/^['"]+/g, '').replace(/['"]+$/g, '');
45
45
  const pathSegments = Array.isArray(path) ? path : (0, _toPath).toPath(pathString);
46
- const value = (0, _dlv).default(config.theme, pathString, defaultValue);
46
+ const value = (0, _dlv).default(config.theme, pathSegments, defaultValue);
47
47
  if (value === undefined) {
48
48
  let error = `'${pathString}' does not exist in your theme config.`;
49
49
  const parentSegments = pathSegments.slice(0, -1);
@@ -13,17 +13,28 @@ function _interopRequireDefault(obj) {
13
13
  default: obj
14
14
  };
15
15
  }
16
- function containsBase(selector, classCandidateBase, separator) {
17
- return (0, _postcssSelectorParser).default((selectors)=>{
18
- let contains = false;
19
- selectors.walkClasses((classSelector)=>{
20
- if (classSelector.value.split(separator).pop() === classCandidateBase) {
21
- contains = true;
22
- return false;
23
- }
24
- });
25
- return contains;
26
- }).transformSync(selector);
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);
27
38
  }
28
39
  function prefix(context, selector) {
29
40
  let prefix1 = context.tailwindConfig.prefix;
@@ -186,10 +197,36 @@ function processApply(root, context) {
186
197
  for (const [parent, candidates] of perParentApplies){
187
198
  let siblings = [];
188
199
  for (let [applyCandidate, important, rules] of candidates){
189
- let base = applyCandidate.split(context.tailwindConfig.separator).pop();
190
200
  for (let [meta, node] of rules){
191
- if (containsBase(parent.selector, base, context.tailwindConfig.separator) && containsBase(node.selector, base, context.tailwindConfig.separator)) {
192
- throw node.error(`Circular dependency detected when using: \`@apply ${applyCandidate}\``);
201
+ let parentClasses = extractClasses(parent);
202
+ let nodeClasses = extractClasses(node);
203
+ // Add base utility classes from the @apply node to the list of
204
+ // classes to check whether it intersects and therefore results in a
205
+ // circular dependency or not.
206
+ //
207
+ // E.g.:
208
+ // .foo {
209
+ // @apply hover:a; // This applies "a" but with a modifier
210
+ // }
211
+ //
212
+ // We only have to do that with base classes of the `node`, not of the `parent`
213
+ // E.g.:
214
+ // .hover\:foo {
215
+ // @apply bar;
216
+ // }
217
+ // .bar {
218
+ // @apply foo;
219
+ // }
220
+ //
221
+ // This should not result in a circular dependency because we are
222
+ // just applying `.foo` and the rule above is `.hover\:foo` which is
223
+ // unrelated. However, if we were to apply `hover:foo` then we _did_
224
+ // have to include this one.
225
+ nodeClasses = nodeClasses.concat(extractBaseCandidates(nodeClasses, context.tailwindConfig.separator));
226
+ let intersects = parentClasses.some((selector)=>nodeClasses.includes(selector)
227
+ );
228
+ if (intersects) {
229
+ throw node.error(`You cannot \`@apply\` the \`${applyCandidate}\` utility here because it creates a circular dependency.`);
193
230
  }
194
231
  let root = _postcss.default.root({
195
232
  nodes: [
@@ -199,6 +236,42 @@ function processApply(root, context) {
199
236
  let canRewriteSelector = node.type !== 'atrule' || node.type === 'atrule' && node.name !== 'keyframes';
200
237
  if (canRewriteSelector) {
201
238
  root.walkRules((rule)=>{
239
+ // Let's imagine you have the following structure:
240
+ //
241
+ // .foo {
242
+ // @apply bar;
243
+ // }
244
+ //
245
+ // @supports (a: b) {
246
+ // .bar {
247
+ // color: blue
248
+ // }
249
+ //
250
+ // .something-unrelated {}
251
+ // }
252
+ //
253
+ // In this case we want to apply `.bar` but it happens to be in
254
+ // an atrule node. We clone that node instead of the nested one
255
+ // because we still want that @supports rule to be there once we
256
+ // applied everything.
257
+ //
258
+ // However it happens to be that the `.something-unrelated` is
259
+ // also in that same shared @supports atrule. This is not good,
260
+ // and this should not be there. The good part is that this is
261
+ // a clone already and it can be safely removed. The question is
262
+ // how do we know we can remove it. Basically what we can do is
263
+ // match it against the applyCandidate that you want to apply. If
264
+ // it doesn't match the we can safely delete it.
265
+ //
266
+ // If we didn't do this, then the `replaceSelector` function
267
+ // would have replaced this with something that didn't exist and
268
+ // therefore it removed the selector altogether. In this specific
269
+ // case it would result in `{}` instead of `.something-unrelated {}`
270
+ if (!extractClasses(rule).some((candidate)=>candidate === applyCandidate
271
+ )) {
272
+ rule.remove();
273
+ return;
274
+ }
202
275
  rule.selector = replaceSelector(parent.selector, rule.selector, applyCandidate);
203
276
  rule.walkDecls((d)=>{
204
277
  d.important = meta.important || important;
@@ -220,7 +293,6 @@ function processApply(root, context) {
220
293
  let nodes = siblings.sort(([a], [z])=>(0, _bigSign).default(a.sort - z.sort)
221
294
  ).map((s)=>s[1]
222
295
  );
223
- // console.log(parent)
224
296
  // `parent` refers to the node at `.abc` in: .abc { @apply mt-2 }
225
297
  parent.after(nodes);
226
298
  }
@@ -9,6 +9,7 @@ var sharedState = _interopRequireWildcard(require("./sharedState"));
9
9
  var _generateRules = require("./generateRules");
10
10
  var _bigSign = _interopRequireDefault(require("../util/bigSign"));
11
11
  var _cloneNodes = _interopRequireDefault(require("../util/cloneNodes"));
12
+ var _defaultExtractor = require("./defaultExtractor");
12
13
  function _interopRequireDefault(obj) {
13
14
  return obj && obj.__esModule ? obj : {
14
15
  default: obj
@@ -38,31 +39,8 @@ function _interopRequireWildcard(obj) {
38
39
  }
39
40
  }
40
41
  let env = sharedState.env;
41
- const PATTERNS = [
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]*\[\w*\("[^'`\s]*"\)\])/.source,
48
- /([^<>"'`\s]*\['[^"'`\s]*'\])/.source,
49
- /([^<>"'`\s]*\["[^"'`\s]*"\])/.source,
50
- /([^<>"'`\s]*\[[^<>"'`\s]*:'[^"'`\s]*'\])/.source,
51
- /([^<>"'`\s]*\[[^<>"'`\s]*:"[^"'`\s]*"\])/.source,
52
- /([^<>"'`\s]*\[[^"'`\s]+\][^<>"'`\s]*)/.source,
53
- /([^<>"'`\s]*[^"'`\s:])/.source
54
- ].join('|');
55
- const BROAD_MATCH_GLOBAL_REGEXP = new RegExp(PATTERNS, 'g');
56
- const INNER_MATCH_GLOBAL_REGEXP = /[^<>"'`\s.(){}[\]#=%]*[^<>"'`\s.(){}[\]#=%:]/g;
57
42
  const builtInExtractors = {
58
- DEFAULT: (content)=>{
59
- let broadMatches = content.match(BROAD_MATCH_GLOBAL_REGEXP) || [];
60
- let innerMatches = content.match(INNER_MATCH_GLOBAL_REGEXP) || [];
61
- return [
62
- ...broadMatches,
63
- ...innerMatches
64
- ];
65
- }
43
+ DEFAULT: _defaultExtractor.defaultExtractor
66
44
  };
67
45
  const builtInTransformers = {
68
46
  DEFAULT: (content)=>content
@@ -124,6 +124,10 @@ function applyVariant(variant, matches, context) {
124
124
  let variantFunctionTuples = context.variantMap.get(variant);
125
125
  let result = [];
126
126
  for (let [meta, rule1] of matches){
127
+ // Don't generate variants for user css
128
+ if (meta.layer === 'user') {
129
+ continue;
130
+ }
127
131
  let container = _postcss.default.root({
128
132
  nodes: [
129
133
  rule1.clone()
@@ -331,7 +335,6 @@ function* resolveMatchedPlugins(classCandidate, context) {
331
335
  context.candidateRuleMap.get(prefix),
332
336
  negative ? `-${modifier}` : modifier
333
337
  ];
334
- return;
335
338
  }
336
339
  }
337
340
  }
package/lib/util/color.js CHANGED
@@ -15,7 +15,8 @@ let SHORT_HEX = /^#([a-f\d])([a-f\d])([a-f\d])([a-f\d])?$/i;
15
15
  let VALUE = `(?:\\d+|\\d*\\.\\d+)%?`;
16
16
  let SEP = `(?:\\s*,\\s*|\\s+)`;
17
17
  let ALPHA_SEP = `\\s*[,/]\\s*`;
18
- let RGB_HSL = new RegExp(`^(rgb|hsl)a?\\(\\s*(${VALUE})${SEP}(${VALUE})${SEP}(${VALUE})(?:${ALPHA_SEP}(${VALUE}))?\\s*\\)$`);
18
+ let RGB = new RegExp(`^rgba?\\(\\s*(${VALUE})${SEP}(${VALUE})${SEP}(${VALUE})(?:${ALPHA_SEP}(${VALUE}))?\\s*\\)$`);
19
+ let HSL = new RegExp(`^hsla?\\(\\s*((?:${VALUE})(?:deg|rad|grad|turn)?)${SEP}(${VALUE})${SEP}(${VALUE})(?:${ALPHA_SEP}(${VALUE}))?\\s*\\)$`);
19
20
  function parseColor(value) {
20
21
  if (typeof value !== 'string') {
21
22
  return null;
@@ -62,18 +63,32 @@ function parseColor(value) {
62
63
  alpha: hex[4] ? (parseInt(hex[4], 16) / 255).toString() : undefined
63
64
  };
64
65
  }
65
- let match = value.match(RGB_HSL);
66
- if (match !== null) {
66
+ let rgbMatch = value.match(RGB);
67
+ if (rgbMatch !== null) {
67
68
  var ref, ref1;
68
69
  return {
69
- mode: match[1],
70
+ mode: 'rgb',
71
+ color: [
72
+ rgbMatch[1],
73
+ rgbMatch[2],
74
+ rgbMatch[3]
75
+ ].map((v)=>v.toString()
76
+ ),
77
+ alpha: (ref = rgbMatch[4]) === null || ref === void 0 ? void 0 : (ref1 = ref.toString) === null || ref1 === void 0 ? void 0 : ref1.call(ref)
78
+ };
79
+ }
80
+ let hslMatch = value.match(HSL);
81
+ if (hslMatch !== null) {
82
+ var ref2, ref3;
83
+ return {
84
+ mode: 'hsl',
70
85
  color: [
71
- match[2],
72
- match[3],
73
- match[4]
86
+ hslMatch[1],
87
+ hslMatch[2],
88
+ hslMatch[3]
74
89
  ].map((v)=>v.toString()
75
90
  ),
76
- alpha: (ref = match[5]) === null || ref === void 0 ? void 0 : (ref1 = ref.toString) === null || ref1 === void 0 ? void 0 : ref1.call(ref)
91
+ alpha: (ref2 = hslMatch[4]) === null || ref2 === void 0 ? void 0 : (ref3 = ref2.toString) === null || ref3 === void 0 ? void 0 : ref3.call(ref2)
77
92
  };
78
93
  }
79
94
  return null;
@@ -11,6 +11,8 @@ var _colors = _interopRequireDefault(require("../public/colors"));
11
11
  var _defaults = require("./defaults");
12
12
  var _toPath = require("./toPath");
13
13
  var _normalizeConfig = require("./normalizeConfig");
14
+ var _isPlainObject = _interopRequireDefault(require("./isPlainObject"));
15
+ var _cloneDeep = require("./cloneDeep");
14
16
  function _interopRequireDefault(obj) {
15
17
  return obj && obj.__esModule ? obj : {
16
18
  default: obj
@@ -143,7 +145,13 @@ function resolveFunctionKeys(object) {
143
145
  val = val[path[index++]];
144
146
  val = isFunction(val) ? val(resolvePath, configUtils) : val;
145
147
  }
146
- return val === undefined ? defaultValue : val;
148
+ if (val === undefined) {
149
+ return defaultValue;
150
+ }
151
+ if ((0, _isPlainObject).default(val)) {
152
+ return (0, _cloneDeep).cloneDeep(val);
153
+ }
154
+ return val;
147
155
  };
148
156
  resolvePath.theme = resolvePath;
149
157
  for(let key1 in configUtils){
@@ -5,5 +5,10 @@ Object.defineProperty(exports, "__esModule", {
5
5
  exports.toPath = toPath;
6
6
  function toPath(path) {
7
7
  if (Array.isArray(path)) return path;
8
- return path.split(/[\.\]\[]+/g);
8
+ let openBrackets = path.split('[').length - 1;
9
+ let closedBrackets = path.split(']').length - 1;
10
+ if (openBrackets !== closedBrackets) {
11
+ throw new Error(`Path is invalid. Has unbalanced brackets: ${path}`);
12
+ }
13
+ return path.split(/\.(?![^\[]*\])|[\[\]]/g).filter(Boolean);
9
14
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tailwindcss",
3
- "version": "3.0.4",
3
+ "version": "3.0.8",
4
4
  "description": "A utility-first CSS framework for rapidly building custom user interfaces.",
5
5
  "license": "MIT",
6
6
  "main": "lib/index.js",
@@ -43,22 +43,22 @@
43
43
  "*.js"
44
44
  ],
45
45
  "devDependencies": {
46
- "@swc/cli": "^0.1.52",
46
+ "@swc/cli": "^0.1.55",
47
47
  "@swc/core": "^1.2.118",
48
- "@swc/jest": "^0.2.11",
48
+ "@swc/jest": "^0.2.15",
49
49
  "@swc/register": "^0.1.7",
50
50
  "autoprefixer": "^10.4.0",
51
51
  "cross-env": "^7.0.3",
52
- "cssnano": "^5.0.12",
52
+ "cssnano": "^5.0.14",
53
53
  "esbuild": "^0.14.2",
54
54
  "eslint": "^8.4.1",
55
55
  "eslint-config-prettier": "^8.3.0",
56
56
  "eslint-plugin-prettier": "^4.0.0",
57
57
  "jest": "^27.4.3",
58
58
  "jest-diff": "^27.4.2",
59
- "postcss": "^8.4.4",
59
+ "postcss": "^8.4.5",
60
60
  "postcss-cli": "^8.3.1",
61
- "prettier": "^2.5.0",
61
+ "prettier": "^2.5.1",
62
62
  "rimraf": "^3.0.0"
63
63
  },
64
64
  "peerDependencies": {
@@ -82,7 +82,7 @@
82
82
  "postcss-js": "^3.0.3",
83
83
  "postcss-load-config": "^3.1.0",
84
84
  "postcss-nested": "5.0.6",
85
- "postcss-selector-parser": "^6.0.6",
85
+ "postcss-selector-parser": "^6.0.7",
86
86
  "postcss-value-parser": "^4.2.0",
87
87
  "quick-lru": "^5.1.1",
88
88
  "resolve": "^1.20.0",
package/peers/index.js CHANGED
@@ -5406,7 +5406,7 @@ var require_processor = __commonJS({
5406
5406
  var Root = require_root();
5407
5407
  var Processor = class {
5408
5408
  constructor(plugins = []) {
5409
- this.version = "8.4.4";
5409
+ this.version = "8.4.5";
5410
5410
  this.plugins = this.normalize(plugins);
5411
5411
  }
5412
5412
  use(plugin) {
@@ -23880,25 +23880,6 @@ var require_dist2 = __commonJS({
23880
23880
  }
23881
23881
  });
23882
23882
 
23883
- // node_modules/is-resolvable/index.js
23884
- var require_is_resolvable = __commonJS({
23885
- "node_modules/is-resolvable/index.js"(exports2, module2) {
23886
- "use strict";
23887
- var inspect = require("util").inspect;
23888
- module2.exports = function isResolvable(moduleId, options) {
23889
- if (typeof moduleId !== "string") {
23890
- throw new TypeError(inspect(moduleId) + " is not a string. Expected a valid Node.js module identifier (<string>), for example 'eslint', './index.js', './lib'.");
23891
- }
23892
- try {
23893
- require.resolve(moduleId, options);
23894
- return true;
23895
- } catch (err) {
23896
- return false;
23897
- }
23898
- };
23899
- }
23900
- });
23901
-
23902
23883
  // node_modules/timsort/build/timsort.js
23903
23884
  var require_timsort = __commonJS({
23904
23885
  "node_modules/timsort/build/timsort.js"(exports2) {
@@ -29271,7 +29252,7 @@ var require_attributes = __commonJS({
29271
29252
  if (/\s/.test(value)) {
29272
29253
  return boolbase_1.falseFunc;
29273
29254
  }
29274
- var regex = new RegExp("(?:^|\\s)" + escapeRegex(value) + "(?:$|\\s)", ignoreCase ? "i" : "");
29255
+ var regex = new RegExp("(?:^|\\s)".concat(escapeRegex(value), "(?:$|\\s)"), ignoreCase ? "i" : "");
29275
29256
  return function element(elem) {
29276
29257
  var attr = adapter.getAttributeValue(elem, name);
29277
29258
  return attr != null && attr.length >= value.length && regex.test(attr) && next(elem);
@@ -29520,7 +29501,7 @@ var require_filters = __commonJS({
29520
29501
  },
29521
29502
  "nth-child": function(next, rule, _a) {
29522
29503
  var adapter = _a.adapter, equals = _a.equals;
29523
- var func = nth_check_1.default(rule);
29504
+ var func = (0, nth_check_1.default)(rule);
29524
29505
  if (func === boolbase_1.falseFunc)
29525
29506
  return boolbase_1.falseFunc;
29526
29507
  if (func === boolbase_1.trueFunc)
@@ -29540,7 +29521,7 @@ var require_filters = __commonJS({
29540
29521
  },
29541
29522
  "nth-last-child": function(next, rule, _a) {
29542
29523
  var adapter = _a.adapter, equals = _a.equals;
29543
- var func = nth_check_1.default(rule);
29524
+ var func = (0, nth_check_1.default)(rule);
29544
29525
  if (func === boolbase_1.falseFunc)
29545
29526
  return boolbase_1.falseFunc;
29546
29527
  if (func === boolbase_1.trueFunc)
@@ -29560,7 +29541,7 @@ var require_filters = __commonJS({
29560
29541
  },
29561
29542
  "nth-of-type": function(next, rule, _a) {
29562
29543
  var adapter = _a.adapter, equals = _a.equals;
29563
- var func = nth_check_1.default(rule);
29544
+ var func = (0, nth_check_1.default)(rule);
29564
29545
  if (func === boolbase_1.falseFunc)
29565
29546
  return boolbase_1.falseFunc;
29566
29547
  if (func === boolbase_1.trueFunc)
@@ -29581,7 +29562,7 @@ var require_filters = __commonJS({
29581
29562
  },
29582
29563
  "nth-last-of-type": function(next, rule, _a) {
29583
29564
  var adapter = _a.adapter, equals = _a.equals;
29584
- var func = nth_check_1.default(rule);
29565
+ var func = (0, nth_check_1.default)(rule);
29585
29566
  if (func === boolbase_1.falseFunc)
29586
29567
  return boolbase_1.falseFunc;
29587
29568
  if (func === boolbase_1.trueFunc)
@@ -29716,10 +29697,10 @@ var require_pseudos = __commonJS({
29716
29697
  function verifyPseudoArgs(func, name, subselect) {
29717
29698
  if (subselect === null) {
29718
29699
  if (func.length > 2) {
29719
- throw new Error("pseudo-selector :" + name + " requires an argument");
29700
+ throw new Error("pseudo-selector :".concat(name, " requires an argument"));
29720
29701
  }
29721
29702
  } else if (func.length === 2) {
29722
- throw new Error("pseudo-selector :" + name + " doesn't have any arguments");
29703
+ throw new Error("pseudo-selector :".concat(name, " doesn't have any arguments"));
29723
29704
  }
29724
29705
  }
29725
29706
  exports2.verifyPseudoArgs = verifyPseudoArgs;
@@ -29761,10 +29742,16 @@ var require_aliases = __commonJS({
29761
29742
  var require_subselects = __commonJS({
29762
29743
  "node_modules/css-select/lib/pseudo-selectors/subselects.js"(exports2) {
29763
29744
  "use strict";
29764
- var __spreadArray = exports2 && exports2.__spreadArray || function(to, from) {
29765
- for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
29766
- to[j] = from[i];
29767
- return to;
29745
+ var __spreadArray = exports2 && exports2.__spreadArray || function(to, from, pack) {
29746
+ if (pack || arguments.length === 2)
29747
+ for (var i = 0, l = from.length, ar; i < l; i++) {
29748
+ if (ar || !(i in from)) {
29749
+ if (!ar)
29750
+ ar = Array.prototype.slice.call(from, 0, i);
29751
+ ar[i] = from[i];
29752
+ }
29753
+ }
29754
+ return to.concat(ar || Array.prototype.slice.call(from));
29768
29755
  };
29769
29756
  Object.defineProperty(exports2, "__esModule", { value: true });
29770
29757
  exports2.subselects = exports2.getNextSiblings = exports2.ensureIsTag = exports2.PLACEHOLDER_ELEMENT = void 0;
@@ -29803,6 +29790,7 @@ var require_subselects = __commonJS({
29803
29790
  exports2.subselects = {
29804
29791
  is,
29805
29792
  matches: is,
29793
+ where: is,
29806
29794
  not: function(next, token, options, context, compileToken) {
29807
29795
  var opts = {
29808
29796
  xmlMode: !!options.xmlMode,
@@ -29842,7 +29830,7 @@ var require_subselects = __commonJS({
29842
29830
  return function(elem) {
29843
29831
  context[0] = elem;
29844
29832
  var childs = adapter.getChildren(elem);
29845
- var nextElements = shouldTestNextSiblings ? __spreadArray(__spreadArray([], childs), getNextSiblings(elem, adapter)) : childs;
29833
+ var nextElements = shouldTestNextSiblings ? __spreadArray(__spreadArray([], childs, true), getNextSiblings(elem, adapter), true) : childs;
29846
29834
  return next(elem) && adapter.existsOne(hasElement, nextElements);
29847
29835
  };
29848
29836
  }
@@ -29882,9 +29870,9 @@ var require_pseudo_selectors = __commonJS({
29882
29870
  }
29883
29871
  if (name in aliases_1.aliases) {
29884
29872
  if (data != null) {
29885
- throw new Error("Pseudo " + name + " doesn't have any arguments");
29873
+ throw new Error("Pseudo ".concat(name, " doesn't have any arguments"));
29886
29874
  }
29887
- var alias = css_what_1.parse(aliases_1.aliases[name], options);
29875
+ var alias = (0, css_what_1.parse)(aliases_1.aliases[name], options);
29888
29876
  return subselects_1.subselects.is(next, alias, options, context, compileToken);
29889
29877
  }
29890
29878
  if (name in filters_1.filters) {
@@ -29892,14 +29880,14 @@ var require_pseudo_selectors = __commonJS({
29892
29880
  }
29893
29881
  if (name in pseudos_1.pseudos) {
29894
29882
  var pseudo_1 = pseudos_1.pseudos[name];
29895
- pseudos_1.verifyPseudoArgs(pseudo_1, name, data);
29883
+ (0, pseudos_1.verifyPseudoArgs)(pseudo_1, name, data);
29896
29884
  return pseudo_1 === boolbase_1.falseFunc ? boolbase_1.falseFunc : next === boolbase_1.trueFunc ? function(elem) {
29897
29885
  return pseudo_1(elem, options, data);
29898
29886
  } : function(elem) {
29899
29887
  return pseudo_1(elem, options, data) && next(elem);
29900
29888
  };
29901
29889
  }
29902
- throw new Error("unmatched pseudo-class :" + name);
29890
+ throw new Error("unmatched pseudo-class :".concat(name));
29903
29891
  }
29904
29892
  exports2.compilePseudoSelector = compilePseudoSelector;
29905
29893
  }
@@ -29921,7 +29909,7 @@ var require_general = __commonJS({
29921
29909
  case "attribute":
29922
29910
  return attributes_1.attributeRules[selector.action](next, selector, options);
29923
29911
  case "pseudo":
29924
- return pseudo_selectors_1.compilePseudoSelector(next, selector, options, context, compileToken);
29912
+ return (0, pseudo_selectors_1.compilePseudoSelector)(next, selector, options, context, compileToken);
29925
29913
  case "tag":
29926
29914
  return function tag(elem) {
29927
29915
  return adapter.getName(elem) === selector.name && next(elem);
@@ -30023,11 +30011,11 @@ var require_compile2 = __commonJS({
30023
30011
  var subselects_1 = require_subselects();
30024
30012
  function compile(selector, options, context) {
30025
30013
  var next = compileUnsafe(selector, options, context);
30026
- return subselects_1.ensureIsTag(next, options.adapter);
30014
+ return (0, subselects_1.ensureIsTag)(next, options.adapter);
30027
30015
  }
30028
30016
  exports2.compile = compile;
30029
30017
  function compileUnsafe(selector, options, context) {
30030
- var token = typeof selector === "string" ? css_what_1.parse(selector, options) : selector;
30018
+ var token = typeof selector === "string" ? (0, css_what_1.parse)(selector, options) : selector;
30031
30019
  return compileToken(token, options, context);
30032
30020
  }
30033
30021
  exports2.compileUnsafe = compileUnsafe;
@@ -30049,7 +30037,7 @@ var require_compile2 = __commonJS({
30049
30037
  }));
30050
30038
  for (var _i = 0, token_1 = token; _i < token_1.length; _i++) {
30051
30039
  var t = token_1[_i];
30052
- if (t.length > 0 && procedure_1.isTraversal(t[0]) && t[0].type !== "descendant") {
30040
+ if (t.length > 0 && (0, procedure_1.isTraversal)(t[0]) && t[0].type !== "descendant") {
30053
30041
  } else if (hasContext && !t.some(includesScopePseudo)) {
30054
30042
  t.unshift(DESCENDANT_TOKEN);
30055
30043
  } else {
@@ -30088,7 +30076,7 @@ var require_compile2 = __commonJS({
30088
30076
  function compileRules(rules, options, context) {
30089
30077
  var _a;
30090
30078
  return rules.reduce(function(previous, rule) {
30091
- return previous === boolbase_1.falseFunc ? boolbase_1.falseFunc : general_1.compileGeneralSelector(previous, rule, options, context, compileToken);
30079
+ return previous === boolbase_1.falseFunc ? boolbase_1.falseFunc : (0, general_1.compileGeneralSelector)(previous, rule, options, context, compileToken);
30092
30080
  }, (_a = options.rootFunc) !== null && _a !== void 0 ? _a : boolbase_1.trueFunc);
30093
30081
  }
30094
30082
  function reduceRules(a, b) {
@@ -30170,7 +30158,7 @@ var require_lib9 = __commonJS({
30170
30158
  return function select(query, elements, options) {
30171
30159
  var opts = convertOptionFormats(options);
30172
30160
  if (typeof query !== "function") {
30173
- query = compile_1.compileUnsafe(query, opts, elements);
30161
+ query = (0, compile_1.compileUnsafe)(query, opts, elements);
30174
30162
  }
30175
30163
  var filteredElements = prepareContext(elements, opts.adapter, query.shouldTestNextSiblings);
30176
30164
  return searchFunc(query, filteredElements, opts);
@@ -30188,8 +30176,9 @@ var require_lib9 = __commonJS({
30188
30176
  exports2.prepareContext = prepareContext;
30189
30177
  function appendNextSiblings(elem, adapter) {
30190
30178
  var elems = Array.isArray(elem) ? elem.slice(0) : [elem];
30191
- for (var i = 0; i < elems.length; i++) {
30192
- var nextSiblings = subselects_1.getNextSiblings(elems[i], adapter);
30179
+ var elemsLength = elems.length;
30180
+ for (var i = 0; i < elemsLength; i++) {
30181
+ var nextSiblings = (0, subselects_1.getNextSiblings)(elems[i], adapter);
30193
30182
  elems.push.apply(elems, nextSiblings);
30194
30183
  }
30195
30184
  return elems;
@@ -30202,7 +30191,7 @@ var require_lib9 = __commonJS({
30202
30191
  });
30203
30192
  function is(elem, query, options) {
30204
30193
  var opts = convertOptionFormats(options);
30205
- return (typeof query === "function" ? query : compile_1.compile(query, opts))(elem);
30194
+ return (typeof query === "function" ? query : (0, compile_1.compile)(query, opts))(elem);
30206
30195
  }
30207
30196
  exports2.is = is;
30208
30197
  exports2.default = exports2.selectAll;
@@ -67097,7 +67086,9 @@ var require_parser4 = __commonJS({
67097
67086
  nextToken = this.nextToken;
67098
67087
  }
67099
67088
  var hasClass = indexesOf(word, ".").filter(function(i) {
67100
- return word[i - 1] !== "\\";
67089
+ var escapedDot = word[i - 1] === "\\";
67090
+ var isKeyframesPercent = /^\d+\.\d+%$/.test(word);
67091
+ return !escapedDot && !isKeyframesPercent;
67101
67092
  });
67102
67093
  var hasId = indexesOf(word, "#").filter(function(i) {
67103
67094
  return word[i - 1] !== "\\";
@@ -70086,18 +70077,9 @@ var require_minifyColor = __commonJS({
70086
70077
  }
70087
70078
  (0, _colord.extend)([_names.default, _minify.default]);
70088
70079
  function minifyColor(input, options = {}) {
70089
- const settings = {
70090
- supportsAlphaHex: false,
70091
- supportsTransparent: true,
70092
- ...options
70093
- };
70094
70080
  const instance = (0, _colord.colord)(input);
70095
70081
  if (instance.isValid()) {
70096
- const minified = instance.minify({
70097
- alphaHex: settings.supportsAlphaHex,
70098
- transparent: settings.supportsTransparent,
70099
- name: true
70100
- });
70082
+ const minified = instance.minify(options);
70101
70083
  return minified.length < input.length ? minified : input.toLowerCase();
70102
70084
  } else {
70103
70085
  return input;
@@ -70203,21 +70185,29 @@ var require_dist13 = __commonJS({
70203
70185
  });
70204
70186
  return parsed.toString();
70205
70187
  }
70206
- function pluginCreator() {
70188
+ function addPluginDefaults(options, browsers) {
70189
+ const defaults = {
70190
+ transparent: browsers.some(hasTransparentBug) === false,
70191
+ alphaHex: (0, _caniuseApi.isSupported)("css-rrggbbaa", browsers),
70192
+ name: true
70193
+ };
70194
+ return {
70195
+ ...defaults,
70196
+ ...options
70197
+ };
70198
+ }
70199
+ function pluginCreator(config = {}) {
70207
70200
  return {
70208
70201
  postcssPlugin: "postcss-colormin",
70209
70202
  prepare(result) {
70210
- const resultOpts = result.opts || {};
70203
+ const resultOptions = result.opts || {};
70211
70204
  const browsers = (0, _browserslist.default)(null, {
70212
- stats: resultOpts.stats,
70205
+ stats: resultOptions.stats,
70213
70206
  path: __dirname,
70214
- env: resultOpts.env
70207
+ env: resultOptions.env
70215
70208
  });
70216
- const options = {
70217
- supportsTransparent: browsers.some(hasTransparentBug) === false,
70218
- supportsAlphaHex: (0, _caniuseApi.isSupported)("css-rrggbbaa", browsers)
70219
- };
70220
70209
  const cache = {};
70210
+ const options = addPluginDefaults(config, browsers);
70221
70211
  return {
70222
70212
  OnceExit(css) {
70223
70213
  css.walkDecls((decl) => {
@@ -72140,22 +72130,6 @@ var require_normalize_url = __commonJS({
72140
72130
  }
72141
72131
  });
72142
72132
 
72143
- // node_modules/is-absolute-url/index.js
72144
- var require_is_absolute_url = __commonJS({
72145
- "node_modules/is-absolute-url/index.js"(exports2, module2) {
72146
- "use strict";
72147
- module2.exports = (url) => {
72148
- if (typeof url !== "string") {
72149
- throw new TypeError(`Expected a \`string\`, got \`${typeof url}\``);
72150
- }
72151
- if (/^[a-zA-Z]:\\/.test(url)) {
72152
- return false;
72153
- }
72154
- return /^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(url);
72155
- };
72156
- }
72157
- });
72158
-
72159
72133
  // node_modules/postcss-normalize-url/dist/index.js
72160
72134
  var require_dist19 = __commonJS({
72161
72135
  "node_modules/postcss-normalize-url/dist/index.js"(exports2, module2) {
@@ -72167,14 +72141,21 @@ var require_dist19 = __commonJS({
72167
72141
  var _path = _interopRequireDefault(require("path"));
72168
72142
  var _postcssValueParser = _interopRequireDefault(require_lib());
72169
72143
  var _normalizeUrl = _interopRequireDefault(require_normalize_url());
72170
- var _isAbsoluteUrl = _interopRequireDefault(require_is_absolute_url());
72171
72144
  function _interopRequireDefault(obj) {
72172
72145
  return obj && obj.__esModule ? obj : { default: obj };
72173
72146
  }
72174
72147
  var multiline = /\\[\r\n]/;
72175
72148
  var escapeChars = /([\s\(\)"'])/g;
72149
+ var ABSOLUTE_URL_REGEX = /^[a-zA-Z][a-zA-Z\d+\-.]*?:/;
72150
+ var WINDOWS_PATH_REGEX = /^[a-zA-Z]:\\/;
72151
+ function isAbsolute(url) {
72152
+ if (WINDOWS_PATH_REGEX.test(url)) {
72153
+ return false;
72154
+ }
72155
+ return ABSOLUTE_URL_REGEX.test(url);
72156
+ }
72176
72157
  function convert(url, options) {
72177
- if ((0, _isAbsoluteUrl.default)(url) || url.startsWith("//")) {
72158
+ if (isAbsolute(url) || url.startsWith("//")) {
72178
72159
  let normalizedURL = null;
72179
72160
  try {
72180
72161
  normalizedURL = (0, _normalizeUrl.default)(url, options);
@@ -75968,11 +75949,18 @@ var require_dist35 = __commonJS({
75968
75949
  var _postcss = _interopRequireDefault(require_postcss());
75969
75950
  var _yaml = _interopRequireDefault(require_yaml());
75970
75951
  var _lilconfig = require_dist2();
75971
- var _isResolvable = _interopRequireDefault(require_is_resolvable());
75972
75952
  function _interopRequireDefault(obj) {
75973
75953
  return obj && obj.__esModule ? obj : { default: obj };
75974
75954
  }
75975
75955
  var cssnano = "cssnano";
75956
+ function isResolvable(moduleId) {
75957
+ try {
75958
+ require.resolve(moduleId);
75959
+ return true;
75960
+ } catch (e) {
75961
+ return false;
75962
+ }
75963
+ }
75976
75964
  function resolvePreset(preset) {
75977
75965
  let fn, options;
75978
75966
  if (Array.isArray(preset)) {
@@ -75991,11 +75979,11 @@ var require_dist35 = __commonJS({
75991
75979
  if (typeof fn === "function") {
75992
75980
  return fn(options).plugins;
75993
75981
  }
75994
- if ((0, _isResolvable.default)(fn)) {
75982
+ if (isResolvable(fn)) {
75995
75983
  return require(fn)(options).plugins;
75996
75984
  }
75997
75985
  const sugar = `cssnano-preset-${fn}`;
75998
- if ((0, _isResolvable.default)(sugar)) {
75986
+ if (isResolvable(sugar)) {
75999
75987
  return require(sugar)(options).plugins;
76000
75988
  }
76001
75989
  throw new Error(`Cannot load preset "${fn}". Please check your configuration for errors and try again.`);
@@ -76033,12 +76021,12 @@ var require_dist35 = __commonJS({
76033
76021
  options.plugins.forEach((plugin) => {
76034
76022
  if (Array.isArray(plugin)) {
76035
76023
  const [pluginDef, opts = {}] = plugin;
76036
- if (typeof pluginDef === "string" && (0, _isResolvable.default)(pluginDef)) {
76024
+ if (typeof pluginDef === "string" && isResolvable(pluginDef)) {
76037
76025
  options.preset.plugins.push([require(pluginDef), opts]);
76038
76026
  } else {
76039
76027
  options.preset.plugins.push([pluginDef, opts]);
76040
76028
  }
76041
- } else if (typeof plugin === "string" && (0, _isResolvable.default)(plugin)) {
76029
+ } else if (typeof plugin === "string" && isResolvable(plugin)) {
76042
76030
  options.preset.plugins.push([require(plugin), {}]);
76043
76031
  } else {
76044
76032
  options.preset.plugins.push([plugin, {}]);
@@ -58,7 +58,7 @@ hr {
58
58
  Add the correct text decoration in Chrome, Edge, and Safari.
59
59
  */
60
60
 
61
- abbr[title] {
61
+ abbr:where([title]) {
62
62
  text-decoration: underline dotted;
63
63
  }
64
64
 
@@ -289,7 +289,6 @@ legend {
289
289
 
290
290
  ol,
291
291
  ul,
292
- li,
293
292
  menu {
294
293
  list-style: none;
295
294
  margin: 0;
@@ -0,0 +1,46 @@
1
+ const PATTERNS = [
2
+ /(?:\['([^'\s]+[^<>"'`\s:\\])')/.source, // ['text-lg' -> text-lg
3
+ /(?:\["([^"\s]+[^<>"'`\s:\\])")/.source, // ["text-lg" -> text-lg
4
+ /(?:\[`([^`\s]+[^<>"'`\s:\\])`)/.source, // [`text-lg` -> text-lg
5
+ /([^<>"'`\s]*\[\w*'[^"`\s]*'?\])/.source, // font-['some_font',sans-serif]
6
+ /([^<>"'`\s]*\[\w*"[^'`\s]*"?\])/.source, // font-["some_font",sans-serif]
7
+ /([^<>"'`\s]*\[\w*\('[^"'`\s]*'\)\])/.source, // bg-[url('...')]
8
+ /([^<>"'`\s]*\[\w*\("[^"'`\s]*"\)\])/.source, // bg-[url("...")]
9
+ /([^<>"'`\s]*\[\w*\('[^"`\s]*'\)\])/.source, // bg-[url('...'),url('...')]
10
+ /([^<>"'`\s]*\[\w*\("[^'`\s]*"\)\])/.source, // bg-[url("..."),url("...")]
11
+ /([^<>"'`\s]*\['[^"'`\s]*'\])/.source, // `content-['hello']` but not `content-['hello']']`
12
+ /([^<>"'`\s]*\["[^"'`\s]*"\])/.source, // `content-["hello"]` but not `content-["hello"]"]`
13
+ /([^<>"'`\s]*\[[^<>"'`\s]*:'[^"'`\s]*'\])/.source, // `[content:'hello']` but not `[content:"hello"]`
14
+ /([^<>"'`\s]*\[[^<>"'`\s]*:"[^"'`\s]*"\])/.source, // `[content:"hello"]` but not `[content:'hello']`
15
+ /([^<>"'`\s]*\[[^"'`\s]+\][^<>"'`\s]*)/.source, // `fill-[#bada55]`, `fill-[#bada55]/50`
16
+ /([^<>"'`\s]*[^"'`\s:\\])/.source, // `px-1.5`, `uppercase` but not `uppercase:`
17
+
18
+ // Arbitrary properties
19
+ // /([^"\s]*\[[^\s]+?\][^"\s]*)/.source,
20
+ // /([^'\s]*\[[^\s]+?\][^'\s]*)/.source,
21
+ // /([^`\s]*\[[^\s]+?\][^`\s]*)/.source,
22
+ ].join('|')
23
+
24
+ const BROAD_MATCH_GLOBAL_REGEXP = new RegExp(PATTERNS, 'g')
25
+ const INNER_MATCH_GLOBAL_REGEXP = /[^<>"'`\s.(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g
26
+
27
+ /**
28
+ * @param {string} content
29
+ */
30
+ export function defaultExtractor(content) {
31
+ let broadMatches = content.matchAll(BROAD_MATCH_GLOBAL_REGEXP)
32
+ let innerMatches = content.match(INNER_MATCH_GLOBAL_REGEXP) || []
33
+ let results = [...broadMatches, ...innerMatches].flat().filter((v) => v !== undefined)
34
+
35
+ return results
36
+ }
37
+
38
+ // Regular utilities
39
+ // {{modifier}:}*{namespace}{-{suffix}}*{/{opacityModifier}}?
40
+
41
+ // Arbitrary values
42
+ // {{modifier}:}*{namespace}-[{arbitraryValue}]{/{opacityModifier}}?
43
+ // arbitraryValue: no whitespace, balanced quotes unless within quotes, balanced brackets unless within quotes
44
+
45
+ // Arbitrary properties
46
+ // {{modifier}:}*[{validCssPropertyName}:{arbitraryValue}]
@@ -42,7 +42,7 @@ function validatePath(config, path, defaultValue) {
42
42
  ? pathToString(path)
43
43
  : path.replace(/^['"]+/g, '').replace(/['"]+$/g, '')
44
44
  const pathSegments = Array.isArray(path) ? path : toPath(pathString)
45
- const value = dlv(config.theme, pathString, defaultValue)
45
+ const value = dlv(config.theme, pathSegments, defaultValue)
46
46
 
47
47
  if (value === undefined) {
48
48
  let error = `'${pathString}' does not exist in your theme config.`
@@ -1,22 +1,33 @@
1
1
  import postcss from 'postcss'
2
2
  import parser from 'postcss-selector-parser'
3
+
3
4
  import { resolveMatches } from './generateRules'
4
5
  import bigSign from '../util/bigSign'
5
6
  import escapeClassName from '../util/escapeClassName'
6
7
 
7
- function containsBase(selector, classCandidateBase, separator) {
8
- return parser((selectors) => {
9
- let contains = false
8
+ function extractClasses(node) {
9
+ let classes = new Set()
10
+ let container = postcss.root({ nodes: [node.clone()] })
10
11
 
11
- selectors.walkClasses((classSelector) => {
12
- if (classSelector.value.split(separator).pop() === classCandidateBase) {
13
- contains = true
14
- return false
15
- }
16
- })
12
+ container.walkRules((rule) => {
13
+ parser((selectors) => {
14
+ selectors.walkClasses((classSelector) => {
15
+ classes.add(classSelector.value)
16
+ })
17
+ }).processSync(rule.selector)
18
+ })
19
+
20
+ return Array.from(classes)
21
+ }
22
+
23
+ function extractBaseCandidates(candidates, separator) {
24
+ let baseClasses = new Set()
17
25
 
18
- return contains
19
- }).transformSync(selector)
26
+ for (let candidate of candidates) {
27
+ baseClasses.add(candidate.split(separator).pop())
28
+ }
29
+
30
+ return Array.from(baseClasses)
20
31
  }
21
32
 
22
33
  function prefix(context, selector) {
@@ -212,15 +223,40 @@ function processApply(root, context) {
212
223
  let siblings = []
213
224
 
214
225
  for (let [applyCandidate, important, rules] of candidates) {
215
- let base = applyCandidate.split(context.tailwindConfig.separator).pop()
216
-
217
226
  for (let [meta, node] of rules) {
218
- if (
219
- containsBase(parent.selector, base, context.tailwindConfig.separator) &&
220
- containsBase(node.selector, base, context.tailwindConfig.separator)
221
- ) {
227
+ let parentClasses = extractClasses(parent)
228
+ let nodeClasses = extractClasses(node)
229
+
230
+ // Add base utility classes from the @apply node to the list of
231
+ // classes to check whether it intersects and therefore results in a
232
+ // circular dependency or not.
233
+ //
234
+ // E.g.:
235
+ // .foo {
236
+ // @apply hover:a; // This applies "a" but with a modifier
237
+ // }
238
+ //
239
+ // We only have to do that with base classes of the `node`, not of the `parent`
240
+ // E.g.:
241
+ // .hover\:foo {
242
+ // @apply bar;
243
+ // }
244
+ // .bar {
245
+ // @apply foo;
246
+ // }
247
+ //
248
+ // This should not result in a circular dependency because we are
249
+ // just applying `.foo` and the rule above is `.hover\:foo` which is
250
+ // unrelated. However, if we were to apply `hover:foo` then we _did_
251
+ // have to include this one.
252
+ nodeClasses = nodeClasses.concat(
253
+ extractBaseCandidates(nodeClasses, context.tailwindConfig.separator)
254
+ )
255
+
256
+ let intersects = parentClasses.some((selector) => nodeClasses.includes(selector))
257
+ if (intersects) {
222
258
  throw node.error(
223
- `Circular dependency detected when using: \`@apply ${applyCandidate}\``
259
+ `You cannot \`@apply\` the \`${applyCandidate}\` utility here because it creates a circular dependency.`
224
260
  )
225
261
  }
226
262
 
@@ -230,6 +266,42 @@ function processApply(root, context) {
230
266
 
231
267
  if (canRewriteSelector) {
232
268
  root.walkRules((rule) => {
269
+ // Let's imagine you have the following structure:
270
+ //
271
+ // .foo {
272
+ // @apply bar;
273
+ // }
274
+ //
275
+ // @supports (a: b) {
276
+ // .bar {
277
+ // color: blue
278
+ // }
279
+ //
280
+ // .something-unrelated {}
281
+ // }
282
+ //
283
+ // In this case we want to apply `.bar` but it happens to be in
284
+ // an atrule node. We clone that node instead of the nested one
285
+ // because we still want that @supports rule to be there once we
286
+ // applied everything.
287
+ //
288
+ // However it happens to be that the `.something-unrelated` is
289
+ // also in that same shared @supports atrule. This is not good,
290
+ // and this should not be there. The good part is that this is
291
+ // a clone already and it can be safely removed. The question is
292
+ // how do we know we can remove it. Basically what we can do is
293
+ // match it against the applyCandidate that you want to apply. If
294
+ // it doesn't match the we can safely delete it.
295
+ //
296
+ // If we didn't do this, then the `replaceSelector` function
297
+ // would have replaced this with something that didn't exist and
298
+ // therefore it removed the selector altogether. In this specific
299
+ // case it would result in `{}` instead of `.something-unrelated {}`
300
+ if (!extractClasses(rule).some((candidate) => candidate === applyCandidate)) {
301
+ rule.remove()
302
+ return
303
+ }
304
+
233
305
  rule.selector = replaceSelector(parent.selector, rule.selector, applyCandidate)
234
306
 
235
307
  rule.walkDecls((d) => {
@@ -250,7 +322,6 @@ function processApply(root, context) {
250
322
  // Inject the rules, sorted, correctly
251
323
  let nodes = siblings.sort(([a], [z]) => bigSign(a.sort - z.sort)).map((s) => s[1])
252
324
 
253
- // console.log(parent)
254
325
  // `parent` refers to the node at `.abc` in: .abc { @apply mt-2 }
255
326
  parent.after(nodes)
256
327
  }
@@ -3,33 +3,12 @@ import * as sharedState from './sharedState'
3
3
  import { generateRules } from './generateRules'
4
4
  import bigSign from '../util/bigSign'
5
5
  import cloneNodes from '../util/cloneNodes'
6
+ import { defaultExtractor } from './defaultExtractor'
6
7
 
7
8
  let env = sharedState.env
8
9
 
9
- const PATTERNS = [
10
- /([^<>"'`\s]*\[\w*'[^"`\s]*'?\])/.source, // font-['some_font',sans-serif]
11
- /([^<>"'`\s]*\[\w*"[^"`\s]*"?\])/.source, // font-["some_font",sans-serif]
12
- /([^<>"'`\s]*\[\w*\('[^"'`\s]*'\)\])/.source, // bg-[url('...')]
13
- /([^<>"'`\s]*\[\w*\("[^"'`\s]*"\)\])/.source, // bg-[url("...")]
14
- /([^<>"'`\s]*\[\w*\('[^"`\s]*'\)\])/.source, // bg-[url('...'),url('...')]
15
- /([^<>"'`\s]*\[\w*\("[^'`\s]*"\)\])/.source, // bg-[url("..."),url("...")]
16
- /([^<>"'`\s]*\['[^"'`\s]*'\])/.source, // `content-['hello']` but not `content-['hello']']`
17
- /([^<>"'`\s]*\["[^"'`\s]*"\])/.source, // `content-["hello"]` but not `content-["hello"]"]`
18
- /([^<>"'`\s]*\[[^<>"'`\s]*:'[^"'`\s]*'\])/.source, // `[content:'hello']` but not `[content:"hello"]`
19
- /([^<>"'`\s]*\[[^<>"'`\s]*:"[^"'`\s]*"\])/.source, // `[content:"hello"]` but not `[content:'hello']`
20
- /([^<>"'`\s]*\[[^"'`\s]+\][^<>"'`\s]*)/.source, // `fill-[#bada55]`, `fill-[#bada55]/50`
21
- /([^<>"'`\s]*[^"'`\s:])/.source, // `px-1.5`, `uppercase` but not `uppercase:`
22
- ].join('|')
23
- const BROAD_MATCH_GLOBAL_REGEXP = new RegExp(PATTERNS, 'g')
24
- const INNER_MATCH_GLOBAL_REGEXP = /[^<>"'`\s.(){}[\]#=%]*[^<>"'`\s.(){}[\]#=%:]/g
25
-
26
10
  const builtInExtractors = {
27
- DEFAULT: (content) => {
28
- let broadMatches = content.match(BROAD_MATCH_GLOBAL_REGEXP) || []
29
- let innerMatches = content.match(INNER_MATCH_GLOBAL_REGEXP) || []
30
-
31
- return [...broadMatches, ...innerMatches]
32
- },
11
+ DEFAULT: defaultExtractor,
33
12
  }
34
13
 
35
14
  const builtInTransformers = {
@@ -112,6 +112,11 @@ function applyVariant(variant, matches, context) {
112
112
  let result = []
113
113
 
114
114
  for (let [meta, rule] of matches) {
115
+ // Don't generate variants for user css
116
+ if (meta.layer === 'user') {
117
+ continue
118
+ }
119
+
115
120
  let container = postcss.root({ nodes: [rule.clone()] })
116
121
 
117
122
  for (let [variantSort, variantFunction] of variantFunctionTuples) {
@@ -325,7 +330,6 @@ function* resolveMatchedPlugins(classCandidate, context) {
325
330
  for (let [prefix, modifier] of candidatePermutations(candidatePrefix)) {
326
331
  if (context.candidateRuleMap.has(prefix)) {
327
332
  yield [context.candidateRuleMap.get(prefix), negative ? `-${modifier}` : modifier]
328
- return
329
333
  }
330
334
  }
331
335
  }
package/src/util/color.js CHANGED
@@ -5,8 +5,11 @@ let SHORT_HEX = /^#([a-f\d])([a-f\d])([a-f\d])([a-f\d])?$/i
5
5
  let VALUE = `(?:\\d+|\\d*\\.\\d+)%?`
6
6
  let SEP = `(?:\\s*,\\s*|\\s+)`
7
7
  let ALPHA_SEP = `\\s*[,/]\\s*`
8
- let RGB_HSL = new RegExp(
9
- `^(rgb|hsl)a?\\(\\s*(${VALUE})${SEP}(${VALUE})${SEP}(${VALUE})(?:${ALPHA_SEP}(${VALUE}))?\\s*\\)$`
8
+ let RGB = new RegExp(
9
+ `^rgba?\\(\\s*(${VALUE})${SEP}(${VALUE})${SEP}(${VALUE})(?:${ALPHA_SEP}(${VALUE}))?\\s*\\)$`
10
+ )
11
+ let HSL = new RegExp(
12
+ `^hsla?\\(\\s*((?:${VALUE})(?:deg|rad|grad|turn)?)${SEP}(${VALUE})${SEP}(${VALUE})(?:${ALPHA_SEP}(${VALUE}))?\\s*\\)$`
10
13
  )
11
14
 
12
15
  export function parseColor(value) {
@@ -37,13 +40,23 @@ export function parseColor(value) {
37
40
  }
38
41
  }
39
42
 
40
- let match = value.match(RGB_HSL)
43
+ let rgbMatch = value.match(RGB)
44
+
45
+ if (rgbMatch !== null) {
46
+ return {
47
+ mode: 'rgb',
48
+ color: [rgbMatch[1], rgbMatch[2], rgbMatch[3]].map((v) => v.toString()),
49
+ alpha: rgbMatch[4]?.toString?.(),
50
+ }
51
+ }
52
+
53
+ let hslMatch = value.match(HSL)
41
54
 
42
- if (match !== null) {
55
+ if (hslMatch !== null) {
43
56
  return {
44
- mode: match[1],
45
- color: [match[2], match[3], match[4]].map((v) => v.toString()),
46
- alpha: match[5]?.toString?.(),
57
+ mode: 'hsl',
58
+ color: [hslMatch[1], hslMatch[2], hslMatch[3]].map((v) => v.toString()),
59
+ alpha: hslMatch[4]?.toString?.(),
47
60
  }
48
61
  }
49
62
 
@@ -6,6 +6,8 @@ import colors from '../public/colors'
6
6
  import { defaults } from './defaults'
7
7
  import { toPath } from './toPath'
8
8
  import { normalizeConfig } from './normalizeConfig'
9
+ import isPlainObject from './isPlainObject'
10
+ import { cloneDeep } from './cloneDeep'
9
11
 
10
12
  function isFunction(input) {
11
13
  return typeof input === 'function'
@@ -144,7 +146,15 @@ function resolveFunctionKeys(object) {
144
146
  val = isFunction(val) ? val(resolvePath, configUtils) : val
145
147
  }
146
148
 
147
- return val === undefined ? defaultValue : val
149
+ if (val === undefined) {
150
+ return defaultValue
151
+ }
152
+
153
+ if (isPlainObject(val)) {
154
+ return cloneDeep(val)
155
+ }
156
+
157
+ return val
148
158
  }
149
159
 
150
160
  resolvePath.theme = resolvePath
@@ -1,4 +1,26 @@
1
+ /**
2
+ * Parse a path string into an array of path segments.
3
+ *
4
+ * Square bracket notation `a[b]` may be used to "escape" dots that would otherwise be interpreted as path separators.
5
+ *
6
+ * Example:
7
+ * a -> ['a]
8
+ * a.b.c -> ['a', 'b', 'c']
9
+ * a[b].c -> ['a', 'b', 'c']
10
+ * a[b.c].e.f -> ['a', 'b.c', 'e', 'f']
11
+ * a[b][c][d] -> ['a', 'b', 'c', 'd']
12
+ *
13
+ * @param {string|string[]} path
14
+ **/
1
15
  export function toPath(path) {
2
16
  if (Array.isArray(path)) return path
3
- return path.split(/[\.\]\[]+/g)
17
+
18
+ let openBrackets = path.split('[').length - 1
19
+ let closedBrackets = path.split(']').length - 1
20
+
21
+ if (openBrackets !== closedBrackets) {
22
+ throw new Error(`Path is invalid. Has unbalanced brackets: ${path}`)
23
+ }
24
+
25
+ return path.split(/\.(?![^\[]*\])|[\[\]]/g).filter(Boolean)
4
26
  }
@@ -854,8 +854,8 @@ module.exports = {
854
854
  none: 'none',
855
855
  all: 'all',
856
856
  DEFAULT:
857
- 'background-color, border-color, color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter',
858
- colors: 'background-color, border-color, color, fill, stroke',
857
+ 'color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter',
858
+ colors: 'color, background-color, border-color, text-decoration-color, fill, stroke',
859
859
  opacity: 'opacity',
860
860
  shadow: 'box-shadow',
861
861
  transform: 'transform',