tailwindcss 3.0.18 → 3.0.19

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,7 +7,18 @@ 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
+ Nothing yet!
11
+
12
+ ## [3.0.19] - 2022-02-07
13
+
14
+ ### Fixed
15
+
16
+ - Fix preflight border color fallback ([#7288](https://github.com/tailwindlabs/tailwindcss/pull/7288))
17
+ - Correctly parse shadow lengths without a leading zero ([#7289](https://github.com/tailwindlabs/tailwindcss/pull/7289))
18
+ - Don't crash when scanning extremely long class candidates ([#7331](https://github.com/tailwindlabs/tailwindcss/pull/7331))
19
+ - Use less hacky fix for URLs detected as custom properties ([#7275](https://github.com/tailwindlabs/tailwindcss/pull/7275))
20
+ - Correctly generate negative utilities when dash is before the prefix ([#7295](https://github.com/tailwindlabs/tailwindcss/pull/7295))
21
+ - Detect prefixed negative utilities in the safelist ([#7295](https://github.com/tailwindlabs/tailwindcss/pull/7295))
11
22
 
12
23
  ## [3.0.18] - 2022-01-28
13
24
 
@@ -1836,7 +1847,8 @@ No release notes
1836
1847
 
1837
1848
  - Everything!
1838
1849
 
1839
- [unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.18...HEAD
1850
+ [unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.19...HEAD
1851
+ [3.0.19]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.18...v3.0.19
1840
1852
  [3.0.18]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.17...v3.0.18
1841
1853
  [3.0.17]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.16...v3.0.17
1842
1854
  [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,
@@ -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
  }
@@ -265,10 +271,32 @@ function parseRules(rule, cache, options = {}) {
265
271
  }
266
272
  const IS_VALID_PROPERTY_NAME = /^[a-z_-]/;
267
273
  function isValidPropName(name) {
268
- // TODO: properly fix this!
269
- return IS_VALID_PROPERTY_NAME.test(name) && !name.startsWith('http');
274
+ return IS_VALID_PROPERTY_NAME.test(name);
275
+ }
276
+ /**
277
+ * @param {string} declaration
278
+ * @returns {boolean}
279
+ */ function looksLikeUri(declaration) {
280
+ // Quick bailout for obvious non-urls
281
+ // This doesn't support schemes that don't use a leading // but that's unlikely to be a problem
282
+ if (!declaration.includes('://')) {
283
+ return false;
284
+ }
285
+ try {
286
+ const url = new URL(declaration);
287
+ return url.scheme !== '' && url.host !== '';
288
+ } catch (err) {
289
+ // Definitely not a valid url
290
+ return false;
291
+ }
270
292
  }
271
293
  function isParsableCssValue(property, value) {
294
+ // We don't want to to treat [https://example.com] as a custom property
295
+ // Even though, according to the CSS grammar, it's a totally valid CSS declaration
296
+ // So we short-circuit here by checking if the custom property looks like a url
297
+ if (looksLikeUri(`${property}:${value}`)) {
298
+ return false;
299
+ }
272
300
  try {
273
301
  _postcss.default.parse(`a{${property}:${value}}`).toResult();
274
302
  return true;
@@ -348,6 +376,14 @@ function* resolveMatchedPlugins(classCandidate, context) {
348
376
  function splitWithSeparator(input, separator) {
349
377
  return input.split(new RegExp(`\\${separator}(?![^[]*\\])`, 'g'));
350
378
  }
379
+ function* recordCandidates(matches, classCandidate) {
380
+ for (const match of matches){
381
+ match[1].raws.tailwind = {
382
+ classCandidate
383
+ };
384
+ yield match;
385
+ }
386
+ }
351
387
  function* resolveMatches(candidate, context) {
352
388
  let separator = context.tailwindConfig.separator;
353
389
  let [classCandidate, ...variants] = splitWithSeparator(candidate, separator).reverse();
@@ -457,7 +493,9 @@ function* resolveMatches(candidate, context) {
457
493
  ]);
458
494
  continue;
459
495
  }
460
- matches = applyPrefix(matches.flat(), context);
496
+ matches = matches.flat();
497
+ matches = Array.from(recordCandidates(matches, classCandidate));
498
+ matches = applyPrefix(matches, context);
461
499
  if (important) {
462
500
  matches = applyImportant(matches, context);
463
501
  }
@@ -673,18 +673,31 @@ function registerPlugins(plugins, context) {
673
673
  }
674
674
  if (checks.length > 0) {
675
675
  let patternMatchingCount = new Map();
676
+ let prefixLength = context.tailwindConfig.prefix.length;
676
677
  for (let util of classList){
677
678
  let utils = Array.isArray(util) ? (()=>{
678
679
  let [utilName, options] = util;
679
680
  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)
681
+ let values = Object.keys((ref = options === null || options === void 0 ? void 0 : options.values) !== null && ref !== void 0 ? ref : {});
682
+ let classes = values.map((value)=>(0, _nameClass).formatClass(utilName, value)
681
683
  );
682
684
  if (options === null || options === void 0 ? void 0 : options.supportsNegativeValues) {
685
+ // This is the normal negated version
686
+ // e.g. `-inset-1` or `-tw-inset-1`
683
687
  classes = [
684
688
  ...classes,
685
689
  ...classes.map((cls)=>'-' + cls
686
690
  )
687
691
  ];
692
+ // This is the negated version *after* the prefix
693
+ // e.g. `tw--inset-1`
694
+ // The prefix is already attached to util name
695
+ // So we add the negative after the prefix
696
+ classes = [
697
+ ...classes,
698
+ ...classes.map((cls)=>cls.slice(0, prefixLength) + '-' + cls.slice(prefixLength)
699
+ ),
700
+ ];
688
701
  }
689
702
  return classes;
690
703
  })() : [
@@ -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.19",
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,11 +41,11 @@
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",
@@ -83,7 +78,7 @@
83
78
  "postcss-selector-parser": "^6.0.9",
84
79
  "postcss-value-parser": "^4.2.0",
85
80
  "quick-lru": "^5.1.1",
86
- "resolve": "^1.21.0"
81
+ "resolve": "^1.22.0"
87
82
  },
88
83
  "browserslist": [
89
84
  "> 1%",