tailwindcss 3.0.17 → 3.0.21

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,36 @@ 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.21] - 2022-02-10
13
+
14
+ ### Fixed
15
+
16
+ - Move prettier plugin to dev dependencies ([#7418](https://github.com/tailwindlabs/tailwindcss/pull/7418))
17
+
18
+ ## [3.0.20] - 2022-02-10
19
+
20
+ ### Added
21
+
22
+ - Expose `context.sortClassList(classes)` ([#7412](https://github.com/tailwindlabs/tailwindcss/pull/7412))
23
+
24
+ ## [3.0.19] - 2022-02-07
25
+
26
+ ### Fixed
27
+
28
+ - Fix preflight border color fallback ([#7288](https://github.com/tailwindlabs/tailwindcss/pull/7288))
29
+ - Correctly parse shadow lengths without a leading zero ([#7289](https://github.com/tailwindlabs/tailwindcss/pull/7289))
30
+ - Don't crash when scanning extremely long class candidates ([#7331](https://github.com/tailwindlabs/tailwindcss/pull/7331))
31
+ - Use less hacky fix for URLs detected as custom properties ([#7275](https://github.com/tailwindlabs/tailwindcss/pull/7275))
32
+ - Correctly generate negative utilities when dash is before the prefix ([#7295](https://github.com/tailwindlabs/tailwindcss/pull/7295))
33
+ - Detect prefixed negative utilities in the safelist ([#7295](https://github.com/tailwindlabs/tailwindcss/pull/7295))
34
+
35
+ ## [3.0.18] - 2022-01-28
36
+
37
+ ### Fixed
38
+
39
+ - Fix `@apply` order regression (in `addComponents`, `addUtilities`, ...) ([#7232](https://github.com/tailwindlabs/tailwindcss/pull/7232))
40
+ - Quick fix for incorrect arbitrary properties when using URLs ([#7252](https://github.com/tailwindlabs/tailwindcss/pull/7252))
41
+
12
42
  ## [3.0.17] - 2022-01-26
13
43
 
14
44
  ### Fixed
@@ -1829,7 +1859,11 @@ No release notes
1829
1859
 
1830
1860
  - Everything!
1831
1861
 
1832
- [unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.17...HEAD
1862
+ [unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.21...HEAD
1863
+ [3.0.21]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.20...v3.0.21
1864
+ [3.0.20]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.19...v3.0.20
1865
+ [3.0.19]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.18...v3.0.19
1866
+ [3.0.18]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.17...v3.0.18
1833
1867
  [3.0.17]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.16...v3.0.17
1834
1868
  [3.0.16]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.15...v3.0.16
1835
1869
  [3.0.15]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.14...v3.0.15
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;
@@ -267,7 +274,30 @@ const IS_VALID_PROPERTY_NAME = /^[a-z_-]/;
267
274
  function isValidPropName(name) {
268
275
  return IS_VALID_PROPERTY_NAME.test(name);
269
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
+ }
293
+ }
270
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
+ }
271
301
  try {
272
302
  _postcss.default.parse(`a{${property}:${value}}`).toResult();
273
303
  return true;
@@ -347,6 +377,15 @@ function* resolveMatchedPlugins(classCandidate, context) {
347
377
  function splitWithSeparator(input, separator) {
348
378
  return input.split(new RegExp(`\\${separator}(?![^[]*\\])`, 'g'));
349
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
+ }
350
389
  function* resolveMatches(candidate, context) {
351
390
  let separator = context.tailwindConfig.separator;
352
391
  let [classCandidate, ...variants] = splitWithSeparator(candidate, separator).reverse();
@@ -456,7 +495,9 @@ function* resolveMatches(candidate, context) {
456
495
  ]);
457
496
  continue;
458
497
  }
459
- matches = applyPrefix(matches.flat(), context);
498
+ matches = matches.flat();
499
+ matches = Array.from(recordCandidates(matches, classCandidate));
500
+ matches = applyPrefix(matches, context);
460
501
  if (important) {
461
502
  matches = applyImportant(matches, context);
462
503
  }
@@ -464,6 +505,10 @@ function* resolveMatches(candidate, context) {
464
505
  matches = applyVariant(variant, matches, context);
465
506
  }
466
507
  for (let match1 of matches){
508
+ match1[1].raws.tailwind = {
509
+ ...match1[1].raws.tailwind,
510
+ candidate
511
+ };
467
512
  // Apply final format selector
468
513
  if (match1[0].collectedFormats) {
469
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)) {
@@ -24,6 +24,8 @@ function processTailwindFeatures(setupContext) {
24
24
  return function(root, result) {
25
25
  let { tailwindDirectives , applyDirectives } = (0, _normalizeTailwindDirectives).default(root);
26
26
  (0, _detectNesting).default()(root, result);
27
+ // Partition apply rules that are found in the css
28
+ // itself.
27
29
  (0, _partitionApplyAtRules).default()(root, result);
28
30
  let context = setupContext({
29
31
  tailwindDirectives,
@@ -44,6 +46,9 @@ function processTailwindFeatures(setupContext) {
44
46
  }
45
47
  (0, _featureFlags).issueFlagNotices(context.tailwindConfig);
46
48
  (0, _expandTailwindAtRules).default(context)(root, result);
49
+ // Partition apply rules that are generated by
50
+ // addComponents, addUtilities and so on.
51
+ (0, _partitionApplyAtRules).default()(root, result);
47
52
  (0, _expandApplyAtRules).default(context)(root, result);
48
53
  (0, _evaluateTailwindFunctions).default(context)(root, result);
49
54
  (0, _substituteScreenAtRules).default(context)(root, result);
@@ -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.17",
3
+ "version": "3.0.21",
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,18 @@
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",
53
+ "postcss": "^8.4.6",
59
54
  "prettier": "^2.5.1",
55
+ "prettier-plugin-tailwindcss": "^0.1.7",
60
56
  "rimraf": "^3.0.0"
61
57
  },
62
58
  "peerDependencies": {
@@ -80,10 +76,10 @@
80
76
  "postcss-js": "^4.0.0",
81
77
  "postcss-load-config": "^3.1.0",
82
78
  "postcss-nested": "5.0.6",
83
- "postcss-selector-parser": "^6.0.8",
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%",