tailwindcss 3.1.1 → 3.1.4

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,34 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
 
10
10
  - Nothing yet!
11
11
 
12
+ ## [3.1.4] - 2022-06-21
13
+
14
+ ### Fixed
15
+
16
+ - Provide default to `<alpha-value>` when using `theme()` ([#8652](https://github.com/tailwindlabs/tailwindcss/pull/8652))
17
+ - Detect arbitrary variants with quotes ([#8687](https://github.com/tailwindlabs/tailwindcss/pull/8687))
18
+ - Don’t add spaces around raw `/` that are preceded by numbers ([#8688](https://github.com/tailwindlabs/tailwindcss/pull/8688))
19
+
20
+ ## [3.1.3] - 2022-06-14
21
+
22
+ ### Fixed
23
+
24
+ - Fix extraction of multi-word utilities with arbitrary values and quotes ([#8604](https://github.com/tailwindlabs/tailwindcss/pull/8604))
25
+ - Fix casing of import of `corePluginList` type definition ([#8587](https://github.com/tailwindlabs/tailwindcss/pull/8587))
26
+ - Ignore PostCSS nodes returned by `addVariant` ([#8608](https://github.com/tailwindlabs/tailwindcss/pull/8608))
27
+ - Fix missing spaces around arithmetic operators ([#8615](https://github.com/tailwindlabs/tailwindcss/pull/8615))
28
+ - Detect alpha value in CSS `theme()` function when using quotes ([#8625](https://github.com/tailwindlabs/tailwindcss/pull/8625))
29
+ - Fix "Maximum call stack size exceeded" bug ([#8636](https://github.com/tailwindlabs/tailwindcss/pull/8636))
30
+ - Allow functions returning parallel variants to mutate the container ([#8622](https://github.com/tailwindlabs/tailwindcss/pull/8622))
31
+ - Remove text opacity CSS variables from `::marker` ([#8622](https://github.com/tailwindlabs/tailwindcss/pull/8622))
32
+
33
+ ## [3.1.2] - 2022-06-10
34
+
35
+ ### Fixed
36
+
37
+ - Ensure `\` is a valid arbitrary variant token ([#8576](https://github.com/tailwindlabs/tailwindcss/pull/8576))
38
+ - Enable `postcss-import` in the CLI by default in watch mode ([#8574](https://github.com/tailwindlabs/tailwindcss/pull/8574), [#8580](https://github.com/tailwindlabs/tailwindcss/pull/8580))
39
+
12
40
  ## [3.1.1] - 2022-06-09
13
41
 
14
42
  ### Fixed
@@ -1961,7 +1989,10 @@ No release notes
1961
1989
 
1962
1990
  - Everything!
1963
1991
 
1964
- [unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.1.1...HEAD
1992
+ [unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.1.4...HEAD
1993
+ [3.1.4]: https://github.com/tailwindlabs/tailwindcss/compare/v3.1.3...v3.1.4
1994
+ [3.1.3]: https://github.com/tailwindlabs/tailwindcss/compare/v3.1.2...v3.1.3
1995
+ [3.1.2]: https://github.com/tailwindlabs/tailwindcss/compare/v3.1.1...v3.1.2
1965
1996
  [3.1.1]: https://github.com/tailwindlabs/tailwindcss/compare/v3.1.0...v3.1.1
1966
1997
  [3.1.0]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.24...v3.1.0
1967
1998
  [3.0.24]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.23...v3.0.24
package/lib/cli.js CHANGED
@@ -428,6 +428,43 @@ async function build() {
428
428
  config1.options
429
429
  ];
430
430
  }
431
+ function loadBuiltinPostcssPlugins() {
432
+ let postcss = loadPostcss();
433
+ let IMPORT_COMMENT = "__TAILWIND_RESTORE_IMPORT__: ";
434
+ return [
435
+ [
436
+ (root)=>{
437
+ root.walkAtRules("import", (rule)=>{
438
+ if (rule.params.slice(1).startsWith("tailwindcss/")) {
439
+ rule.after(postcss.comment({
440
+ text: IMPORT_COMMENT + rule.params
441
+ }));
442
+ rule.remove();
443
+ }
444
+ });
445
+ },
446
+ (()=>{
447
+ try {
448
+ return require("postcss-import");
449
+ } catch {}
450
+ return (0, _indexJs).lazyPostcssImport();
451
+ })(),
452
+ (root)=>{
453
+ root.walkComments((rule)=>{
454
+ if (rule.text.startsWith(IMPORT_COMMENT)) {
455
+ rule.after(postcss.atRule({
456
+ name: "import",
457
+ params: rule.text.replace(IMPORT_COMMENT, "")
458
+ }));
459
+ rule.remove();
460
+ }
461
+ });
462
+ },
463
+ ],
464
+ [],
465
+ {},
466
+ ];
467
+ }
431
468
  function resolveConfig() {
432
469
  let config = configPath ? require(configPath) : {};
433
470
  if (args["--purge"]) {
@@ -503,40 +540,7 @@ async function build() {
503
540
  };
504
541
  };
505
542
  tailwindPlugin.postcss = true;
506
- let IMPORT_COMMENT = "__TAILWIND_RESTORE_IMPORT__: ";
507
- let [beforePlugins, afterPlugins, postcssOptions] = includePostCss ? await loadPostCssPlugins() : [
508
- [
509
- (root)=>{
510
- root.walkAtRules("import", (rule)=>{
511
- if (rule.params.slice(1).startsWith("tailwindcss/")) {
512
- rule.after(postcss.comment({
513
- text: IMPORT_COMMENT + rule.params
514
- }));
515
- rule.remove();
516
- }
517
- });
518
- },
519
- (()=>{
520
- try {
521
- return require("postcss-import");
522
- } catch {}
523
- return (0, _indexJs).lazyPostcssImport();
524
- })(),
525
- (root)=>{
526
- root.walkComments((rule)=>{
527
- if (rule.text.startsWith(IMPORT_COMMENT)) {
528
- rule.after(postcss.atRule({
529
- name: "import",
530
- params: rule.text.replace(IMPORT_COMMENT, "")
531
- }));
532
- rule.remove();
533
- }
534
- });
535
- },
536
- ],
537
- [],
538
- {},
539
- ];
543
+ let [beforePlugins, afterPlugins, postcssOptions] = includePostCss ? await loadPostCssPlugins() : loadBuiltinPostcssPlugins();
540
544
  let plugins = [
541
545
  ...beforePlugins,
542
546
  tailwindPlugin,
@@ -623,10 +627,7 @@ async function build() {
623
627
  env.DEBUG && console.timeEnd("Module dependencies");
624
628
  return resolveConfig();
625
629
  }
626
- let [beforePlugins, afterPlugins] = includePostCss ? await loadPostCssPlugins() : [
627
- [],
628
- []
629
- ];
630
+ let [beforePlugins, afterPlugins] = includePostCss ? await loadPostCssPlugins() : loadBuiltinPostcssPlugins();
630
631
  let plugins = [
631
632
  ...beforePlugins,
632
633
  "__TAILWIND_PLUGIN_POSITION__",
@@ -19,6 +19,7 @@ var _packageJson = require("../package.json");
19
19
  var _log = _interopRequireDefault(require("./util/log"));
20
20
  var _normalizeScreens = require("./util/normalizeScreens");
21
21
  var _parseBoxShadowValue = require("./util/parseBoxShadowValue");
22
+ var _removeAlphaVariables = require("./util/removeAlphaVariables");
22
23
  var _featureFlags = require("./featureFlags");
23
24
  function _interopRequireDefault(obj) {
24
25
  return obj && obj.__esModule ? obj : {
@@ -69,8 +70,18 @@ let variantPlugins = {
69
70
  addVariant("first-letter", "&::first-letter");
70
71
  addVariant("first-line", "&::first-line");
71
72
  addVariant("marker", [
72
- "& *::marker",
73
- "&::marker"
73
+ ({ container })=>{
74
+ (0, _removeAlphaVariables).removeAlphaVariables(container, [
75
+ "--tw-text-opacity"
76
+ ]);
77
+ return "& *::marker";
78
+ },
79
+ ({ container })=>{
80
+ (0, _removeAlphaVariables).removeAlphaVariables(container, [
81
+ "--tw-text-opacity"
82
+ ]);
83
+ return "&::marker";
84
+ },
74
85
  ]);
75
86
  addVariant("selection", [
76
87
  "& *::selection",
@@ -140,22 +151,11 @@ let variantPlugins = {
140
151
  [
141
152
  "visited",
142
153
  ({ container })=>{
143
- let toRemove = [
154
+ (0, _removeAlphaVariables).removeAlphaVariables(container, [
144
155
  "--tw-text-opacity",
145
156
  "--tw-border-opacity",
146
- "--tw-bg-opacity"
147
- ];
148
- container.walkDecls((decl)=>{
149
- if (toRemove.includes(decl.prop)) {
150
- decl.remove();
151
- return;
152
- }
153
- for (const varName of toRemove){
154
- if (decl.value.includes(`/ var(${varName})`)) {
155
- decl.value = decl.value.replace(`/ var(${varName})`, "");
156
- }
157
- }
158
- });
157
+ "--tw-bg-opacity",
158
+ ]);
159
159
  return "&:visited";
160
160
  },
161
161
  ],
@@ -52,7 +52,10 @@ function defaultExtractor(context) {
52
52
  /** @type {(string|string)[]} */ let results = [];
53
53
  for (let pattern of patterns){
54
54
  var ref;
55
- results.push(...(ref = content.match(pattern)) !== null && ref !== void 0 ? ref : []);
55
+ results = [
56
+ ...results,
57
+ ...(ref = content.match(pattern)) !== null && ref !== void 0 ? ref : []
58
+ ];
56
59
  }
57
60
  return results.filter((v)=>v !== undefined).map(clipAtBalancedParens);
58
61
  };
@@ -71,7 +74,7 @@ function* buildRegExps(context) {
71
74
  regex.optional(regex.any([
72
75
  regex.pattern([
73
76
  // Arbitrary values
74
- /-\[[^\s:]+\]/,
77
+ /-(?:\w+-)*\[[^\s:]+\]/,
75
78
  // Not immediately followed by an `{[(`
76
79
  /(?![{([]])/,
77
80
  // optionally followed by an opacity modifier
@@ -79,7 +82,7 @@ function* buildRegExps(context) {
79
82
  ]),
80
83
  regex.pattern([
81
84
  // Arbitrary values
82
- /-\[[^\s]+\]/,
85
+ /-(?:\w+-)*\[[^\s]+\]/,
83
86
  // Not immediately followed by an `{[(`
84
87
  /(?![{([]])/,
85
88
  // optionally followed by an opacity modifier
@@ -90,37 +93,54 @@ function* buildRegExps(context) {
90
93
  ])),
91
94
  ]),
92
95
  ]);
93
- yield regex.pattern([
94
- // Variants
95
- "((?=((",
96
+ let variantPatterns = [
97
+ // Without quotes
96
98
  regex.any([
97
99
  regex.pattern([
98
- /([^\s"'`\[\\]+-)?\[[^\s"'`\\]+\]/,
100
+ /([^\s"'`\[\\]+-)?\[[^\s"'`]+\]/,
99
101
  separator
100
102
  ]),
101
103
  regex.pattern([
102
104
  /[^\s"'`\[\\]+/,
103
105
  separator
104
106
  ]),
105
- ], true),
106
- ")+))\\2)?",
107
- // Important (optional)
108
- /!?/,
109
- variantGroupingEnabled ? regex.any([
110
- // Or any of those things but grouped separated by commas
107
+ ]),
108
+ // With quotes allowed
109
+ regex.any([
111
110
  regex.pattern([
112
- /\(/,
113
- utility,
114
- regex.zeroOrMore([
115
- /,/,
116
- utility
117
- ]),
118
- /\)/
111
+ /([^\s"'`\[\\]+-)?\[[^\s`]+\]/,
112
+ separator
119
113
  ]),
120
- // Arbitrary properties, constrained utilities, arbitrary values, etc…
121
- utility,
122
- ]) : utility,
123
- ]);
114
+ regex.pattern([
115
+ /[^\s`\[\\]+/,
116
+ separator
117
+ ]),
118
+ ]),
119
+ ];
120
+ for (const variantPattern of variantPatterns){
121
+ yield regex.pattern([
122
+ // Variants
123
+ "((?=((",
124
+ variantPattern,
125
+ ")+))\\2)?",
126
+ // Important (optional)
127
+ /!?/,
128
+ variantGroupingEnabled ? regex.any([
129
+ // Or any of those things but grouped separated by commas
130
+ regex.pattern([
131
+ /\(/,
132
+ utility,
133
+ regex.zeroOrMore([
134
+ /,/,
135
+ utility
136
+ ]),
137
+ /\)/
138
+ ]),
139
+ // Arbitrary properties, constrained utilities, arbitrary values, etc…
140
+ utility,
141
+ ]) : utility,
142
+ ]);
143
+ }
124
144
  // 5. Inner matches
125
145
  yield /[^<>"'`\s.(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g;
126
146
  }
@@ -42,7 +42,7 @@ function listKeys(obj) {
42
42
  return list(Object.keys(obj));
43
43
  }
44
44
  function validatePath(config, path, defaultValue, themeOpts = {}) {
45
- const pathString = Array.isArray(path) ? pathToString(path) : path.replace(/^['"]+/g, "").replace(/['"]+$/g, "");
45
+ const pathString = Array.isArray(path) ? pathToString(path) : path.replace(/^['"]+|['"]+$/g, "");
46
46
  const pathSegments = Array.isArray(path) ? path : (0, _toPath).toPath(pathString);
47
47
  const value = (0, _dlv).default(config.theme, pathSegments, defaultValue);
48
48
  if (value === undefined) {
@@ -140,6 +140,9 @@ let nodeTypePropertyMap = {
140
140
  function _default({ tailwindConfig: config }) {
141
141
  let functions = {
142
142
  theme: (node, path, ...defaultValue)=>{
143
+ // Strip quotes from beginning and end of string
144
+ // This allows the alpha value to be present inside of quotes
145
+ path = path.replace(/^['"]+|['"]+$/g, "");
143
146
  let matches = path.match(/^([^\s]+)(?![^\[]*\])(?:\s*\/\s*([^\/\s]+))$/);
144
147
  let alpha = undefined;
145
148
  if (matches) {
@@ -152,9 +155,13 @@ function _default({ tailwindConfig: config }) {
152
155
  if (!isValid) {
153
156
  throw node.error(error);
154
157
  }
155
- if (alpha !== undefined) {
156
- value = (0, _pluginUtils).parseColorFormat(value);
157
- value = (0, _withAlphaVariable).withAlphaValue(value, alpha, value);
158
+ let maybeColor = (0, _pluginUtils).parseColorFormat(value);
159
+ let isColorFunction = maybeColor !== undefined && typeof maybeColor === "function";
160
+ if (alpha !== undefined || isColorFunction) {
161
+ if (alpha === undefined) {
162
+ alpha = 1.0;
163
+ }
164
+ value = (0, _withAlphaVariable).withAlphaValue(maybeColor, alpha, maybeColor);
158
165
  }
159
166
  return value;
160
167
  },
@@ -205,13 +205,16 @@ function applyVariant(variant, matches, context) {
205
205
  rule1.clone()
206
206
  ]
207
207
  });
208
- for (let [variantSort, variantFunction] of variantFunctionTuples){
209
- let clone = container.clone();
208
+ for (let [variantSort, variantFunction, containerFromArray] of variantFunctionTuples){
209
+ let clone = containerFromArray !== null && containerFromArray !== void 0 ? containerFromArray : container.clone();
210
210
  let collectedFormats = [];
211
- let originals = new Map();
212
211
  function prepareBackup() {
213
- if (originals.size > 0) return; // Already prepared, chicken out
214
- clone.walkRules((rule)=>originals.set(rule, rule.selector));
212
+ // Already prepared, chicken out
213
+ if (clone.raws.neededBackup) {
214
+ return;
215
+ }
216
+ clone.raws.neededBackup = true;
217
+ clone.walkRules((rule)=>rule.raws.originalSelector = rule.selector);
215
218
  }
216
219
  function modifySelectors(modifierFunction) {
217
220
  prepareBackup();
@@ -264,7 +267,10 @@ function applyVariant(variant, matches, context) {
264
267
  // then this might be the place too look at. One potential solution to this problem is
265
268
  // reserving additional X places for these 'unknown' variants in between.
266
269
  variantSort | BigInt(idx << ruleWithVariant.length),
267
- variantFunction,
270
+ variantFunction,
271
+ // If the clone has been modified we have to pass that back
272
+ // though so each rule can use the modified container
273
+ clone.clone(),
268
274
  ]);
269
275
  }
270
276
  continue;
@@ -275,13 +281,15 @@ function applyVariant(variant, matches, context) {
275
281
  if (ruleWithVariant === null) {
276
282
  continue;
277
283
  }
278
- // We filled the `originals`, therefore we assume that somebody touched
284
+ // We had to backup selectors, therefore we assume that somebody touched
279
285
  // `container` or `modifySelectors`. Let's see if they did, so that we
280
286
  // can restore the selectors, and collect the format strings.
281
- if (originals.size > 0) {
287
+ if (clone.raws.neededBackup) {
288
+ delete clone.raws.neededBackup;
282
289
  clone.walkRules((rule)=>{
283
- if (!originals.has(rule)) return;
284
- let before = originals.get(rule);
290
+ let before = rule.raws.originalSelector;
291
+ if (!before) return;
292
+ delete rule.raws.originalSelector;
285
293
  if (before === rule.selector) return; // No mutation happened
286
294
  let modified = rule.selector;
287
295
  // Rebuild the base selector, this is what plugin authors would do
@@ -478,10 +478,11 @@ function buildPluginApi(tailwindConfig, context, { variantList , variantMap , of
478
478
  throw new Error(`Your custom variant \`${variantName}\` has an invalid format string. Make sure it's an at-rule or contains a \`&\` placeholder.`);
479
479
  }
480
480
  if (Array.isArray(result)) {
481
- return result.map((variant)=>parseVariant(variant));
481
+ return result.filter((variant)=>typeof variant === "string").map((variant)=>parseVariant(variant));
482
482
  }
483
483
  // result may be undefined with legacy variants that use APIs like `modifySelectors`
484
- return result && parseVariant(result)(api);
484
+ // result may also be a postcss node if someone was returning the result from `modifySelectors`
485
+ return result && typeof result === "string" && parseVariant(result)(api);
485
486
  };
486
487
  }
487
488
  if (!isValidVariantFormatString(variantFunction)) {
@@ -46,14 +46,12 @@ function normalize(value, isRoot = true) {
46
46
  if (isRoot) {
47
47
  value = value.trim();
48
48
  }
49
- // Add spaces around operators inside calc() that do not follow an operator
49
+ // Add spaces around operators inside math functions like calc() that do not follow an operator
50
50
  // or '('.
51
- value = value.replace(/calc\(.+\)/g, (match)=>{
51
+ value = value.replace(/(calc|min|max|clamp)\(.+\)/g, (match)=>{
52
52
  return match.replace(/(-?\d*\.?\d(?!\b-.+[,)](?![^+\-/*])\D)(?:%|[a-z]+)?|\))([+\-/*])/g, "$1 $2 ");
53
53
  });
54
- // Add spaces around some operators not inside calc() that do not follow an operator
55
- // or '('.
56
- return value.replace(/(-?\d*\.?\d(?!\b-.+[,)](?![^+\-/*])\D)(?:%|[a-z]+)?|\))([\/])/g, "$1 $2 ");
54
+ return value;
57
55
  }
58
56
  function url(value) {
59
57
  return value.startsWith("url(");
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ exports.removeAlphaVariables = removeAlphaVariables;
6
+ function removeAlphaVariables(container, toRemove) {
7
+ container.walkDecls((decl)=>{
8
+ if (toRemove.includes(decl.prop)) {
9
+ decl.remove();
10
+ return;
11
+ }
12
+ for (let varName of toRemove){
13
+ if (decl.value.includes(`/ var(${varName})`)) {
14
+ decl.value = decl.value.replace(`/ var(${varName})`, "");
15
+ }
16
+ }
17
+ });
18
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tailwindcss",
3
- "version": "3.1.1",
3
+ "version": "3.1.4",
4
4
  "description": "A utility-first CSS framework for rapidly building custom user interfaces.",
5
5
  "license": "MIT",
6
6
  "main": "lib/index.js",
@@ -47,14 +47,14 @@
47
47
  "@swc/jest": "^0.2.21",
48
48
  "@swc/register": "^0.1.10",
49
49
  "autoprefixer": "^10.4.7",
50
- "cssnano": "^5.1.9",
51
- "esbuild": "^0.14.39",
50
+ "cssnano": "^5.1.11",
51
+ "esbuild": "^0.14.43",
52
52
  "eslint": "^8.16.0",
53
53
  "eslint-config-prettier": "^8.5.0",
54
54
  "eslint-plugin-prettier": "^4.0.0",
55
- "jest": "^28.1.0",
56
- "jest-diff": "^28.1.0",
57
- "prettier": "^2.6.2",
55
+ "jest": "^28.1.1",
56
+ "jest-diff": "^28.1.1",
57
+ "prettier": "^2.7.1",
58
58
  "prettier-plugin-tailwindcss": "^0.1.11",
59
59
  "rimraf": "^3.0.0",
60
60
  "source-map-js": "^1.0.2"
@@ -63,7 +63,7 @@
63
63
  "postcss": "^8.0.9"
64
64
  },
65
65
  "dependencies": {
66
- "arg": "^5.0.1",
66
+ "arg": "^5.0.2",
67
67
  "chokidar": "^3.5.3",
68
68
  "color-name": "^1.1.4",
69
69
  "detective": "^5.2.1",