tailwindcss 3.0.18 → 3.0.22

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
@@ -9,6 +9,35 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
 
10
10
  - Nothing yet!
11
11
 
12
+ ## [3.0.22] - 2022-02-11
13
+
14
+ ### Fixed
15
+
16
+ - Temporarily move postcss to dependencies ([#7424](https://github.com/tailwindlabs/tailwindcss/pull/7424))
17
+
18
+ ## [3.0.21] - 2022-02-10
19
+
20
+ ### Fixed
21
+
22
+ - Move prettier plugin to dev dependencies ([#7418](https://github.com/tailwindlabs/tailwindcss/pull/7418))
23
+
24
+ ## [3.0.20] - 2022-02-10
25
+
26
+ ### Added
27
+
28
+ - Expose `context.sortClassList(classes)` ([#7412](https://github.com/tailwindlabs/tailwindcss/pull/7412))
29
+
30
+ ## [3.0.19] - 2022-02-07
31
+
32
+ ### Fixed
33
+
34
+ - Fix preflight border color fallback ([#7288](https://github.com/tailwindlabs/tailwindcss/pull/7288))
35
+ - Correctly parse shadow lengths without a leading zero ([#7289](https://github.com/tailwindlabs/tailwindcss/pull/7289))
36
+ - Don't crash when scanning extremely long class candidates ([#7331](https://github.com/tailwindlabs/tailwindcss/pull/7331))
37
+ - Use less hacky fix for URLs detected as custom properties ([#7275](https://github.com/tailwindlabs/tailwindcss/pull/7275))
38
+ - Correctly generate negative utilities when dash is before the prefix ([#7295](https://github.com/tailwindlabs/tailwindcss/pull/7295))
39
+ - Detect prefixed negative utilities in the safelist ([#7295](https://github.com/tailwindlabs/tailwindcss/pull/7295))
40
+
12
41
  ## [3.0.18] - 2022-01-28
13
42
 
14
43
  ### Fixed
@@ -1836,7 +1865,11 @@ No release notes
1836
1865
 
1837
1866
  - Everything!
1838
1867
 
1839
- [unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.18...HEAD
1868
+ [unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.22...HEAD
1869
+ [3.0.22]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.21...v3.0.22
1870
+ [3.0.21]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.20...v3.0.21
1871
+ [3.0.20]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.19...v3.0.20
1872
+ [3.0.19]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.18...v3.0.19
1840
1873
  [3.0.18]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.17...v3.0.18
1841
1874
  [3.0.17]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.16...v3.0.17
1842
1875
  [3.0.16]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.15...v3.0.16
package/LICENSE CHANGED
@@ -1,7 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) Adam Wathan <adam.wathan@gmail.com>
4
- Copyright (c) Jonathan Reinink <jonathan@reinink.ca>
3
+ Copyright (c) Tailwind Labs, Inc.
5
4
 
6
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
7
6
  of this software and associated documentation files (the "Software"), to deal
@@ -9,7 +9,7 @@
9
9
  box-sizing: border-box; /* 1 */
10
10
  border-width: 0; /* 2 */
11
11
  border-style: solid; /* 2 */
12
- border-color: theme('borderColor.DEFAULT', 'currentColor'); /* 2 */
12
+ border-color: theme('borderColor.DEFAULT', currentColor); /* 2 */
13
13
  }
14
14
 
15
15
  ::before,
@@ -140,11 +140,14 @@ function processApply(root, context) {
140
140
  throw apply.error(`@apply is not supported within nested at-rules like @${apply.parent.name}. You can fix this by un-nesting @${apply.parent.name}.`);
141
141
  }
142
142
  for (let applyCandidate of applyCandidates){
143
+ if ([
144
+ prefix(context, 'group'),
145
+ prefix(context, 'peer')
146
+ ].includes(applyCandidate)) {
147
+ // TODO: Link to specific documentation page with error code.
148
+ throw apply.error(`@apply should not be used with the '${applyCandidate}' utility`);
149
+ }
143
150
  if (!applyClassCache.has(applyCandidate)) {
144
- if (applyCandidate === prefix(context, 'group')) {
145
- // TODO: Link to specific documentation page with error code.
146
- throw apply.error(`@apply should not be used with the '${applyCandidate}' utility`);
147
- }
148
151
  throw apply.error(`The \`${applyCandidate}\` class does not exist. If \`${applyCandidate}\` is a custom class, make sure it is defined within a \`@layer\` directive.`);
149
152
  }
150
153
  let rules = applyClassCache.get(applyCandidate);
@@ -33,32 +33,32 @@ function getClassNameFromSelector(selector) {
33
33
  // Example with dynamic classes:
34
34
  // ['grid-cols', '[[linename],1fr,auto]']
35
35
  // ['grid', 'cols-[[linename],1fr,auto]']
36
- function* candidatePermutations(candidate, lastIndex = Infinity) {
37
- if (lastIndex < 0) {
38
- return;
39
- }
40
- let dashIdx;
41
- if (lastIndex === Infinity && candidate.endsWith(']')) {
42
- let bracketIdx = candidate.indexOf('[');
43
- // If character before `[` isn't a dash or a slash, this isn't a dynamic class
44
- // eg. string[]
45
- dashIdx = [
46
- '-',
47
- '/'
48
- ].includes(candidate[bracketIdx - 1]) ? bracketIdx - 1 : -1;
49
- } else {
50
- dashIdx = candidate.lastIndexOf('-', lastIndex);
51
- }
52
- if (dashIdx < 0) {
53
- return;
36
+ function* candidatePermutations(candidate) {
37
+ let lastIndex = Infinity;
38
+ while(lastIndex >= 0){
39
+ let dashIdx;
40
+ if (lastIndex === Infinity && candidate.endsWith(']')) {
41
+ let bracketIdx = candidate.indexOf('[');
42
+ // If character before `[` isn't a dash or a slash, this isn't a dynamic class
43
+ // eg. string[]
44
+ dashIdx = [
45
+ '-',
46
+ '/'
47
+ ].includes(candidate[bracketIdx - 1]) ? bracketIdx - 1 : -1;
48
+ } else {
49
+ dashIdx = candidate.lastIndexOf('-', lastIndex);
50
+ }
51
+ if (dashIdx < 0) {
52
+ break;
53
+ }
54
+ let prefix = candidate.slice(0, dashIdx);
55
+ let modifier = candidate.slice(dashIdx + 1);
56
+ yield [
57
+ prefix,
58
+ modifier
59
+ ];
60
+ lastIndex = dashIdx - 1;
54
61
  }
55
- let prefix = candidate.slice(0, dashIdx);
56
- let modifier = candidate.slice(dashIdx + 1);
57
- yield [
58
- prefix,
59
- modifier
60
- ];
61
- yield* candidatePermutations(candidate, dashIdx - 1);
62
62
  }
63
63
  function applyPrefix(matches, context) {
64
64
  if (matches.length === 0 || context.tailwindConfig.prefix === '') {
@@ -72,8 +72,14 @@ function applyPrefix(matches, context) {
72
72
  match[1].clone()
73
73
  ]
74
74
  });
75
+ let classCandidate = match[1].raws.tailwind.classCandidate;
75
76
  container.walkRules((r)=>{
76
- r.selector = (0, _prefixSelector).default(context.tailwindConfig.prefix, r.selector);
77
+ // If this is a negative utility with a dash *before* the prefix we
78
+ // have to ensure that the generated selector matches the candidate
79
+ // Not doing this will cause `-tw-top-1` to generate the class `.tw--top-1`
80
+ // The disconnect between candidate <-> class can cause @apply to hard crash.
81
+ let shouldPrependNegative = classCandidate.startsWith('-');
82
+ r.selector = (0, _prefixSelector).default(context.tailwindConfig.prefix, r.selector, shouldPrependNegative);
77
83
  });
78
84
  match[1] = container.nodes[0];
79
85
  }
@@ -222,6 +228,7 @@ function applyVariant(variant, matches, context) {
222
228
  // .sm:underline {} is a variant of something in the utilities layer
223
229
  // .sm:container {} is a variant of the container component
224
230
  clone.nodes[0].raws.tailwind = {
231
+ ...clone.nodes[0].raws.tailwind,
225
232
  parentLayer: meta.layer
226
233
  };
227
234
  var _collectedFormats;
@@ -265,10 +272,32 @@ function parseRules(rule, cache, options = {}) {
265
272
  }
266
273
  const IS_VALID_PROPERTY_NAME = /^[a-z_-]/;
267
274
  function isValidPropName(name) {
268
- // TODO: properly fix this!
269
- return IS_VALID_PROPERTY_NAME.test(name) && !name.startsWith('http');
275
+ return IS_VALID_PROPERTY_NAME.test(name);
276
+ }
277
+ /**
278
+ * @param {string} declaration
279
+ * @returns {boolean}
280
+ */ function looksLikeUri(declaration) {
281
+ // Quick bailout for obvious non-urls
282
+ // This doesn't support schemes that don't use a leading // but that's unlikely to be a problem
283
+ if (!declaration.includes('://')) {
284
+ return false;
285
+ }
286
+ try {
287
+ const url = new URL(declaration);
288
+ return url.scheme !== '' && url.host !== '';
289
+ } catch (err) {
290
+ // Definitely not a valid url
291
+ return false;
292
+ }
270
293
  }
271
294
  function isParsableCssValue(property, value) {
295
+ // We don't want to to treat [https://example.com] as a custom property
296
+ // Even though, according to the CSS grammar, it's a totally valid CSS declaration
297
+ // So we short-circuit here by checking if the custom property looks like a url
298
+ if (looksLikeUri(`${property}:${value}`)) {
299
+ return false;
300
+ }
272
301
  try {
273
302
  _postcss.default.parse(`a{${property}:${value}}`).toResult();
274
303
  return true;
@@ -348,6 +377,15 @@ function* resolveMatchedPlugins(classCandidate, context) {
348
377
  function splitWithSeparator(input, separator) {
349
378
  return input.split(new RegExp(`\\${separator}(?![^[]*\\])`, 'g'));
350
379
  }
380
+ function* recordCandidates(matches, classCandidate) {
381
+ for (const match of matches){
382
+ match[1].raws.tailwind = {
383
+ ...match[1].raws.tailwind,
384
+ classCandidate
385
+ };
386
+ yield match;
387
+ }
388
+ }
351
389
  function* resolveMatches(candidate, context) {
352
390
  let separator = context.tailwindConfig.separator;
353
391
  let [classCandidate, ...variants] = splitWithSeparator(candidate, separator).reverse();
@@ -457,7 +495,9 @@ function* resolveMatches(candidate, context) {
457
495
  ]);
458
496
  continue;
459
497
  }
460
- matches = applyPrefix(matches.flat(), context);
498
+ matches = matches.flat();
499
+ matches = Array.from(recordCandidates(matches, classCandidate));
500
+ matches = applyPrefix(matches, context);
461
501
  if (important) {
462
502
  matches = applyImportant(matches, context);
463
503
  }
@@ -465,6 +505,10 @@ function* resolveMatches(candidate, context) {
465
505
  matches = applyVariant(variant, matches, context);
466
506
  }
467
507
  for (let match1 of matches){
508
+ match1[1].raws.tailwind = {
509
+ ...match1[1].raws.tailwind,
510
+ candidate
511
+ };
468
512
  // Apply final format selector
469
513
  if (match1[0].collectedFormats) {
470
514
  let finalFormat = (0, _formatVariantSelector).formatVariantSelector('&', ...match1[0].collectedFormats);
@@ -24,6 +24,7 @@ var _toPath = require("../util/toPath");
24
24
  var _log = _interopRequireDefault(require("../util/log"));
25
25
  var _negateValue = _interopRequireDefault(require("../util/negateValue"));
26
26
  var _isValidArbitraryValue = _interopRequireDefault(require("../util/isValidArbitraryValue"));
27
+ var _generateRules = require("./generateRules");
27
28
  function _interopRequireDefault(obj) {
28
29
  return obj && obj.__esModule ? obj : {
29
30
  default: obj
@@ -50,6 +51,10 @@ function _interopRequireWildcard(obj) {
50
51
  return newObj;
51
52
  }
52
53
  }
54
+ function prefix(context, selector) {
55
+ let prefix1 = context.tailwindConfig.prefix;
56
+ return typeof prefix1 === 'function' ? prefix1(selector) : prefix1 + selector;
57
+ }
53
58
  function parseVariantFormatString(input) {
54
59
  if (input.includes('{')) {
55
60
  if (!isBalanced(input)) throw new Error(`Your { and } are unbalanced.`);
@@ -673,18 +678,31 @@ function registerPlugins(plugins, context) {
673
678
  }
674
679
  if (checks.length > 0) {
675
680
  let patternMatchingCount = new Map();
681
+ let prefixLength = context.tailwindConfig.prefix.length;
676
682
  for (let util of classList){
677
683
  let utils = Array.isArray(util) ? (()=>{
678
684
  let [utilName, options] = util;
679
685
  var ref;
680
- let classes = Object.keys((ref = options === null || options === void 0 ? void 0 : options.values) !== null && ref !== void 0 ? ref : {}).map((value)=>(0, _nameClass).formatClass(utilName, value)
686
+ let values = Object.keys((ref = options === null || options === void 0 ? void 0 : options.values) !== null && ref !== void 0 ? ref : {});
687
+ let classes = values.map((value)=>(0, _nameClass).formatClass(utilName, value)
681
688
  );
682
689
  if (options === null || options === void 0 ? void 0 : options.supportsNegativeValues) {
690
+ // This is the normal negated version
691
+ // e.g. `-inset-1` or `-tw-inset-1`
683
692
  classes = [
684
693
  ...classes,
685
694
  ...classes.map((cls)=>'-' + cls
686
695
  )
687
696
  ];
697
+ // This is the negated version *after* the prefix
698
+ // e.g. `tw--inset-1`
699
+ // The prefix is already attached to util name
700
+ // So we add the negative after the prefix
701
+ classes = [
702
+ ...classes,
703
+ ...classes.map((cls)=>cls.slice(0, prefixLength) + '-' + cls.slice(prefixLength)
704
+ ),
705
+ ];
688
706
  }
689
707
  return classes;
690
708
  })() : [
@@ -723,9 +741,44 @@ function registerPlugins(plugins, context) {
723
741
  }
724
742
  }
725
743
  }
744
+ // A list of utilities that are used by certain Tailwind CSS utilities but
745
+ // that don't exist on their own. This will result in them "not existing" and
746
+ // sorting could be weird since you still require them in order to make the
747
+ // host utitlies work properly. (Thanks Biology)
748
+ let parasiteUtilities = new Set([
749
+ prefix(context, 'group'),
750
+ prefix(context, 'peer')
751
+ ]);
752
+ context.sortClassList = function sortClassList(classes) {
753
+ let sortedClassNames = new Map();
754
+ for (let [sort, rule] of (0, _generateRules).generateRules(new Set(classes), context)){
755
+ if (sortedClassNames.has(rule.raws.tailwind.candidate)) continue;
756
+ sortedClassNames.set(rule.raws.tailwind.candidate, sort);
757
+ }
758
+ return classes.map((className)=>{
759
+ var ref;
760
+ let order = (ref = sortedClassNames.get(className)) !== null && ref !== void 0 ? ref : null;
761
+ if (order === null && parasiteUtilities.has(className)) {
762
+ // This will make sure that it is at the very beginning of the
763
+ // `components` layer which technically means 'before any
764
+ // components'.
765
+ order = context.layerOrder.components;
766
+ }
767
+ return [
768
+ className,
769
+ order
770
+ ];
771
+ }).sort(([, a], [, z])=>{
772
+ if (a === z) return 0;
773
+ if (a === null) return -1;
774
+ if (z === null) return 1;
775
+ return (0, _bigSign).default(a - z);
776
+ }).map(([className])=>className
777
+ );
778
+ };
726
779
  // Generate a list of strings for autocompletion purposes, e.g.
727
780
  // ['uppercase', 'lowercase', ...]
728
- context.getClassList = function() {
781
+ context.getClassList = function getClassList() {
729
782
  let output = [];
730
783
  for (let util of classList){
731
784
  if (Array.isArray(util)) {
@@ -15,7 +15,7 @@ let COMMA = /\,(?![^(]*\))/g // Comma separator that is not located between brac
15
15
  ;
16
16
  let SPACE = /\ +(?![^(]*\))/g // Similar to the one above, but with spaces instead.
17
17
  ;
18
- let LENGTH = /^-?(\d+)(.*?)$/g;
18
+ let LENGTH = /^-?(\d+|\.\d+)(.*?)$/g;
19
19
  function parseBoxShadowValue(input) {
20
20
  let shadows = input.split(COMMA);
21
21
  return shadows.map((shadow)=>{
@@ -4,18 +4,17 @@ Object.defineProperty(exports, "__esModule", {
4
4
  });
5
5
  exports.default = _default;
6
6
  var _postcssSelectorParser = _interopRequireDefault(require("postcss-selector-parser"));
7
- var _tap = require("./tap");
8
7
  function _interopRequireDefault(obj) {
9
8
  return obj && obj.__esModule ? obj : {
10
9
  default: obj
11
10
  };
12
11
  }
13
- function _default(prefix, selector) {
12
+ function _default(prefix, selector, prependNegative = false) {
14
13
  return (0, _postcssSelectorParser).default((selectors)=>{
15
14
  selectors.walkClasses((classSelector)=>{
16
- (0, _tap).tap(classSelector.value, (baseClass)=>{
17
- classSelector.value = `${prefix}${baseClass}`;
18
- });
15
+ let baseClass = classSelector.value;
16
+ let shouldPlaceNegativeBeforePrefix = prependNegative && baseClass.startsWith('-');
17
+ classSelector.value = shouldPlaceNegativeBeforePrefix ? `-${prefix}${baseClass.slice(1)}` : `${prefix}${baseClass}`;
19
18
  });
20
19
  }).processSync(selector);
21
20
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tailwindcss",
3
- "version": "3.0.18",
3
+ "version": "3.0.22",
4
4
  "description": "A utility-first CSS framework for rapidly building custom user interfaces.",
5
5
  "license": "MIT",
6
6
  "main": "lib/index.js",
@@ -12,11 +12,6 @@
12
12
  "tailwind": "lib/cli.js",
13
13
  "tailwindcss": "lib/cli.js"
14
14
  },
15
- "contributors": [
16
- "Adam Wathan <adam.wathan@gmail.com>",
17
- "Jonathan Reinink <jonathan@reinink.ca>",
18
- "David Hemphill <davidlee.hemphill@gmail.com>"
19
- ],
20
15
  "scripts": {
21
16
  "preswcify": "npm run generate:plugin-list && rimraf lib",
22
17
  "swcify": "swc src --out-dir lib --copy-files",
@@ -46,17 +41,17 @@
46
41
  "@swc/cli": "^0.1.55",
47
42
  "@swc/core": "^1.2.127",
48
43
  "@swc/jest": "^0.2.17",
49
- "@swc/register": "^0.1.7",
44
+ "@swc/register": "^0.1.10",
50
45
  "autoprefixer": "^10.4.2",
51
- "cssnano": "^5.0.15",
46
+ "cssnano": "^5.0.16",
52
47
  "esbuild": "^0.14.10",
53
- "eslint": "^8.6.0",
48
+ "eslint": "^8.8.0",
54
49
  "eslint-config-prettier": "^8.3.0",
55
50
  "eslint-plugin-prettier": "^4.0.0",
56
51
  "jest": "^27.4.7",
57
52
  "jest-diff": "^27.4.6",
58
- "postcss": "^8.4.5",
59
53
  "prettier": "^2.5.1",
54
+ "prettier-plugin-tailwindcss": "^0.1.7",
60
55
  "rimraf": "^3.0.0"
61
56
  },
62
57
  "peerDependencies": {
@@ -77,13 +72,14 @@
77
72
  "is-glob": "^4.0.3",
78
73
  "normalize-path": "^3.0.0",
79
74
  "object-hash": "^2.2.0",
75
+ "postcss": "^8.4.6",
80
76
  "postcss-js": "^4.0.0",
81
77
  "postcss-load-config": "^3.1.0",
82
78
  "postcss-nested": "5.0.6",
83
79
  "postcss-selector-parser": "^6.0.9",
84
80
  "postcss-value-parser": "^4.2.0",
85
81
  "quick-lru": "^5.1.1",
86
- "resolve": "^1.21.0"
82
+ "resolve": "^1.22.0"
87
83
  },
88
84
  "browserslist": [
89
85
  "> 1%",