tailwindcss 3.1.0 → 3.1.3
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 +33 -1
- package/lib/cli.js +39 -38
- package/lib/corePlugins.js +16 -16
- package/lib/lib/defaultExtractor.js +14 -11
- package/lib/lib/evaluateTailwindFunctions.js +5 -2
- package/lib/lib/generateRules.js +18 -10
- package/lib/lib/resolveDefaultsAtRules.js +54 -40
- package/lib/lib/setupContextUtils.js +3 -2
- package/lib/util/dataTypes.js +2 -2
- package/lib/util/removeAlphaVariables.js +18 -0
- package/package.json +4 -4
- package/src/cli.js +43 -37
- package/src/corePlugins.js +19 -16
- package/src/lib/defaultExtractor.js +10 -10
- package/src/lib/evaluateTailwindFunctions.js +6 -4
- package/src/lib/generateRules.js +18 -10
- package/src/lib/resolveDefaultsAtRules.js +53 -36
- package/src/lib/setupContextUtils.js +5 -2
- package/src/util/dataTypes.js +2 -2
- package/src/util/removeAlphaVariables.js +24 -0
- package/types/config.d.ts +1 -1
- package/types/index.d.ts +7 -1
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.1.3] - 2022-06-14
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- Fix extraction of multi-word utilities with arbitrary values and quotes ([#8604](https://github.com/tailwindlabs/tailwindcss/pull/8604))
|
|
17
|
+
- Fix casing of import of `corePluginList` type definition ([#8587](https://github.com/tailwindlabs/tailwindcss/pull/8587))
|
|
18
|
+
- Ignore PostCSS nodes returned by `addVariant` ([#8608](https://github.com/tailwindlabs/tailwindcss/pull/8608))
|
|
19
|
+
- Fix missing spaces around arithmetic operators ([#8615](https://github.com/tailwindlabs/tailwindcss/pull/8615))
|
|
20
|
+
- Detect alpha value in CSS `theme()` function when using quotes ([#8625](https://github.com/tailwindlabs/tailwindcss/pull/8625))
|
|
21
|
+
- Fix "Maximum call stack size exceeded" bug ([#8636](https://github.com/tailwindlabs/tailwindcss/pull/8636))
|
|
22
|
+
- Allow functions returning parallel variants to mutate the container ([#8622](https://github.com/tailwindlabs/tailwindcss/pull/8622))
|
|
23
|
+
- Remove text opacity CSS variables from `::marker` ([#8622](https://github.com/tailwindlabs/tailwindcss/pull/8622))
|
|
24
|
+
|
|
25
|
+
## [3.1.2] - 2022-06-10
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
|
|
29
|
+
- Ensure `\` is a valid arbitrary variant token ([#8576](https://github.com/tailwindlabs/tailwindcss/pull/8576))
|
|
30
|
+
- 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))
|
|
31
|
+
|
|
32
|
+
## [3.1.1] - 2022-06-09
|
|
33
|
+
|
|
34
|
+
### Fixed
|
|
35
|
+
|
|
36
|
+
- Fix candidate extractor regression ([#8558](https://github.com/tailwindlabs/tailwindcss/pull/8558))
|
|
37
|
+
- Split `::backdrop` into separate defaults group ([#8567](https://github.com/tailwindlabs/tailwindcss/pull/8567))
|
|
38
|
+
- Fix postcss plugin type ([#8564](https://github.com/tailwindlabs/tailwindcss/pull/8564))
|
|
39
|
+
- Fix class detection in markdown code fences and slim templates ([#8569](https://github.com/tailwindlabs/tailwindcss/pull/8569))
|
|
40
|
+
|
|
12
41
|
## [3.1.0] - 2022-06-08
|
|
13
42
|
|
|
14
43
|
### Fixed
|
|
@@ -1952,7 +1981,10 @@ No release notes
|
|
|
1952
1981
|
|
|
1953
1982
|
- Everything!
|
|
1954
1983
|
|
|
1955
|
-
[unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.1.
|
|
1984
|
+
[unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.1.3...HEAD
|
|
1985
|
+
[3.1.3]: https://github.com/tailwindlabs/tailwindcss/compare/v3.1.2...v3.1.3
|
|
1986
|
+
[3.1.2]: https://github.com/tailwindlabs/tailwindcss/compare/v3.1.1...v3.1.2
|
|
1987
|
+
[3.1.1]: https://github.com/tailwindlabs/tailwindcss/compare/v3.1.0...v3.1.1
|
|
1956
1988
|
[3.1.0]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.24...v3.1.0
|
|
1957
1989
|
[3.0.24]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.23...v3.0.24
|
|
1958
1990
|
[3.0.23]: https://github.com/tailwindlabs/tailwindcss/compare/v3.0.22...v3.0.23
|
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
|
|
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__",
|
package/lib/corePlugins.js
CHANGED
|
@@ -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
|
-
|
|
73
|
-
|
|
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
|
-
|
|
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
|
|
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
|
};
|
|
@@ -62,7 +65,7 @@ function* buildRegExps(context) {
|
|
|
62
65
|
let variantGroupingEnabled = (0, _featureFlagsJs).flagEnabled(context.tailwindConfig, "variantGrouping");
|
|
63
66
|
let utility = regex.any([
|
|
64
67
|
// Arbitrary properties
|
|
65
|
-
/\[[^\s:'"]+:[^\s\]]+\]/,
|
|
68
|
+
/\[[^\s:'"`]+:[^\s\]]+\]/,
|
|
66
69
|
// Utilities
|
|
67
70
|
regex.pattern([
|
|
68
71
|
// Utility Name / Group Name
|
|
@@ -71,22 +74,22 @@ function* buildRegExps(context) {
|
|
|
71
74
|
regex.optional(regex.any([
|
|
72
75
|
regex.pattern([
|
|
73
76
|
// Arbitrary values
|
|
74
|
-
|
|
77
|
+
/-(?:\w+-)*\[[^\s:]+\]/,
|
|
75
78
|
// Not immediately followed by an `{[(`
|
|
76
79
|
/(?![{([]])/,
|
|
77
80
|
// optionally followed by an opacity modifier
|
|
78
|
-
/(?:\/[^\s'"
|
|
81
|
+
/(?:\/[^\s'"`\\><$]*)?/,
|
|
79
82
|
]),
|
|
80
83
|
regex.pattern([
|
|
81
84
|
// Arbitrary values
|
|
82
|
-
|
|
85
|
+
/-(?:\w+-)*\[[^\s]+\]/,
|
|
83
86
|
// Not immediately followed by an `{[(`
|
|
84
87
|
/(?![{([]])/,
|
|
85
88
|
// optionally followed by an opacity modifier
|
|
86
|
-
/(?:\/[^\s'"
|
|
89
|
+
/(?:\/[^\s'"`\\$]*)?/,
|
|
87
90
|
]),
|
|
88
91
|
// Normal values w/o quotes — may include an opacity modifier
|
|
89
|
-
/[-\/][^\s'"
|
|
92
|
+
/[-\/][^\s'"`\\$={><]*/,
|
|
90
93
|
])),
|
|
91
94
|
]),
|
|
92
95
|
]);
|
|
@@ -95,11 +98,11 @@ function* buildRegExps(context) {
|
|
|
95
98
|
"((?=((",
|
|
96
99
|
regex.any([
|
|
97
100
|
regex.pattern([
|
|
98
|
-
/([^\s"'
|
|
101
|
+
/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]/,
|
|
99
102
|
separator
|
|
100
103
|
]),
|
|
101
104
|
regex.pattern([
|
|
102
|
-
/[^\s"'
|
|
105
|
+
/[^\s"'`\[\\]+/,
|
|
103
106
|
separator
|
|
104
107
|
]),
|
|
105
108
|
], true),
|
|
@@ -121,8 +124,8 @@ function* buildRegExps(context) {
|
|
|
121
124
|
utility,
|
|
122
125
|
]) : utility,
|
|
123
126
|
]);
|
|
124
|
-
// 5. Inner matches
|
|
125
|
-
|
|
127
|
+
// 5. Inner matches
|
|
128
|
+
yield /[^<>"'`\s.(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g;
|
|
126
129
|
}
|
|
127
130
|
// We want to capture any "special" characters
|
|
128
131
|
// AND the characters immediately following them (if there is one)
|
|
@@ -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(/^['"]
|
|
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,7 +140,10 @@ let nodeTypePropertyMap = {
|
|
|
140
140
|
function _default({ tailwindConfig: config }) {
|
|
141
141
|
let functions = {
|
|
142
142
|
theme: (node, path, ...defaultValue)=>{
|
|
143
|
-
|
|
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, "");
|
|
146
|
+
let matches = path.match(/^([^\s]+)(?![^\[]*\])(?:\s*\/\s*([^\/\s]+))$/);
|
|
144
147
|
let alpha = undefined;
|
|
145
148
|
if (matches) {
|
|
146
149
|
path = matches[1];
|
package/lib/lib/generateRules.js
CHANGED
|
@@ -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
|
-
|
|
214
|
-
clone.
|
|
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
|
|
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 (
|
|
287
|
+
if (clone.raws.neededBackup) {
|
|
288
|
+
delete clone.raws.neededBackup;
|
|
282
289
|
clone.walkRules((rule)=>{
|
|
283
|
-
|
|
284
|
-
|
|
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
|
|
@@ -23,52 +23,66 @@ function resolveDefaultsAtRules({ tailwindConfig }) {
|
|
|
23
23
|
variableNodeMap.get(variable).add(rule.parent);
|
|
24
24
|
rule.remove();
|
|
25
25
|
});
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
for (let
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
26
|
+
if ((0, _featureFlags).flagEnabled(tailwindConfig, "optimizeUniversalDefaults")) {
|
|
27
|
+
for (let universal of universals){
|
|
28
|
+
/** @type {Map<string, Set<string>>} */ let selectorGroups = new Map();
|
|
29
|
+
var ref;
|
|
30
|
+
let rules = (ref = variableNodeMap.get(universal.params)) !== null && ref !== void 0 ? ref : [];
|
|
31
|
+
for (let rule of rules){
|
|
32
|
+
for (let selector of extractElementSelector(rule.selector)){
|
|
33
|
+
// If selector contains a vendor prefix after a pseudo element or class,
|
|
34
|
+
// we consider them separately because merging the declarations into
|
|
35
|
+
// a single rule will cause browsers that do not understand the
|
|
36
|
+
// vendor prefix to throw out the whole rule
|
|
37
|
+
let selectorGroupName = selector.includes(":-") || selector.includes("::-") ? selector : "__DEFAULT__";
|
|
38
|
+
var ref1;
|
|
39
|
+
let selectors = (ref1 = selectorGroups.get(selectorGroupName)) !== null && ref1 !== void 0 ? ref1 : new Set();
|
|
40
|
+
selectorGroups.set(selectorGroupName, selectors);
|
|
41
|
+
selectors.add(selector);
|
|
42
|
+
}
|
|
41
43
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
44
|
+
if ((0, _featureFlags).flagEnabled(tailwindConfig, "optimizeUniversalDefaults")) {
|
|
45
|
+
if (selectorGroups.size === 0) {
|
|
46
|
+
universal.remove();
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
for (let [, selectors] of selectorGroups){
|
|
50
|
+
let universalRule = _postcss.default.rule({
|
|
51
|
+
source: universal.source
|
|
52
|
+
});
|
|
53
|
+
universalRule.selectors = [
|
|
54
|
+
...selectors
|
|
55
|
+
];
|
|
56
|
+
universalRule.append(universal.nodes.map((node)=>node.clone()));
|
|
57
|
+
universal.before(universalRule);
|
|
58
|
+
}
|
|
57
59
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
universal.remove();
|
|
61
|
+
}
|
|
62
|
+
} else if (universals.size) {
|
|
63
|
+
let universalRule = _postcss.default.rule({
|
|
64
|
+
selectors: [
|
|
63
65
|
"*",
|
|
64
66
|
"::before",
|
|
65
|
-
"::after"
|
|
66
|
-
|
|
67
|
-
|
|
67
|
+
"::after"
|
|
68
|
+
]
|
|
69
|
+
});
|
|
70
|
+
for (let universal of universals){
|
|
68
71
|
universalRule.append(universal.nodes);
|
|
69
|
-
|
|
72
|
+
if (!universalRule.parent) {
|
|
73
|
+
universal.before(universalRule);
|
|
74
|
+
}
|
|
75
|
+
if (!universalRule.source) {
|
|
76
|
+
universalRule.source = universal.source;
|
|
77
|
+
}
|
|
78
|
+
universal.remove();
|
|
70
79
|
}
|
|
71
|
-
|
|
80
|
+
let backdropRule = universalRule.clone({
|
|
81
|
+
selectors: [
|
|
82
|
+
"::backdrop"
|
|
83
|
+
]
|
|
84
|
+
});
|
|
85
|
+
universalRule.after(backdropRule);
|
|
72
86
|
}
|
|
73
87
|
};
|
|
74
88
|
}
|
|
@@ -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
|
-
|
|
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)) {
|
package/lib/util/dataTypes.js
CHANGED
|
@@ -46,9 +46,9 @@ 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
54
|
// Add spaces around some operators not inside calc() that do not follow an operator
|
|
@@ -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.
|
|
3
|
+
"version": "3.1.3",
|
|
4
4
|
"description": "A utility-first CSS framework for rapidly building custom user interfaces.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -52,8 +52,8 @@
|
|
|
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.
|
|
56
|
-
"jest-diff": "^28.1.
|
|
55
|
+
"jest": "^28.1.1",
|
|
56
|
+
"jest-diff": "^28.1.1",
|
|
57
57
|
"prettier": "^2.6.2",
|
|
58
58
|
"prettier-plugin-tailwindcss": "^0.1.11",
|
|
59
59
|
"rimraf": "^3.0.0",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"postcss": "^8.0.9"
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
|
-
"arg": "^5.0.
|
|
66
|
+
"arg": "^5.0.2",
|
|
67
67
|
"chokidar": "^3.5.3",
|
|
68
68
|
"color-name": "^1.1.4",
|
|
69
69
|
"detective": "^5.2.1",
|
package/src/cli.js
CHANGED
|
@@ -484,6 +484,45 @@ async function build() {
|
|
|
484
484
|
return [beforePlugins, afterPlugins, config.options]
|
|
485
485
|
}
|
|
486
486
|
|
|
487
|
+
function loadBuiltinPostcssPlugins() {
|
|
488
|
+
let postcss = loadPostcss()
|
|
489
|
+
let IMPORT_COMMENT = '__TAILWIND_RESTORE_IMPORT__: '
|
|
490
|
+
return [
|
|
491
|
+
[
|
|
492
|
+
(root) => {
|
|
493
|
+
root.walkAtRules('import', (rule) => {
|
|
494
|
+
if (rule.params.slice(1).startsWith('tailwindcss/')) {
|
|
495
|
+
rule.after(postcss.comment({ text: IMPORT_COMMENT + rule.params }))
|
|
496
|
+
rule.remove()
|
|
497
|
+
}
|
|
498
|
+
})
|
|
499
|
+
},
|
|
500
|
+
(() => {
|
|
501
|
+
try {
|
|
502
|
+
return require('postcss-import')
|
|
503
|
+
} catch {}
|
|
504
|
+
|
|
505
|
+
return lazyPostcssImport()
|
|
506
|
+
})(),
|
|
507
|
+
(root) => {
|
|
508
|
+
root.walkComments((rule) => {
|
|
509
|
+
if (rule.text.startsWith(IMPORT_COMMENT)) {
|
|
510
|
+
rule.after(
|
|
511
|
+
postcss.atRule({
|
|
512
|
+
name: 'import',
|
|
513
|
+
params: rule.text.replace(IMPORT_COMMENT, ''),
|
|
514
|
+
})
|
|
515
|
+
)
|
|
516
|
+
rule.remove()
|
|
517
|
+
}
|
|
518
|
+
})
|
|
519
|
+
},
|
|
520
|
+
],
|
|
521
|
+
[],
|
|
522
|
+
{},
|
|
523
|
+
]
|
|
524
|
+
}
|
|
525
|
+
|
|
487
526
|
function resolveConfig() {
|
|
488
527
|
let config = configPath ? require(configPath) : {}
|
|
489
528
|
|
|
@@ -568,44 +607,9 @@ async function build() {
|
|
|
568
607
|
|
|
569
608
|
tailwindPlugin.postcss = true
|
|
570
609
|
|
|
571
|
-
let IMPORT_COMMENT = '__TAILWIND_RESTORE_IMPORT__: '
|
|
572
|
-
|
|
573
610
|
let [beforePlugins, afterPlugins, postcssOptions] = includePostCss
|
|
574
611
|
? await loadPostCssPlugins()
|
|
575
|
-
:
|
|
576
|
-
[
|
|
577
|
-
(root) => {
|
|
578
|
-
root.walkAtRules('import', (rule) => {
|
|
579
|
-
if (rule.params.slice(1).startsWith('tailwindcss/')) {
|
|
580
|
-
rule.after(postcss.comment({ text: IMPORT_COMMENT + rule.params }))
|
|
581
|
-
rule.remove()
|
|
582
|
-
}
|
|
583
|
-
})
|
|
584
|
-
},
|
|
585
|
-
(() => {
|
|
586
|
-
try {
|
|
587
|
-
return require('postcss-import')
|
|
588
|
-
} catch {}
|
|
589
|
-
|
|
590
|
-
return lazyPostcssImport()
|
|
591
|
-
})(),
|
|
592
|
-
(root) => {
|
|
593
|
-
root.walkComments((rule) => {
|
|
594
|
-
if (rule.text.startsWith(IMPORT_COMMENT)) {
|
|
595
|
-
rule.after(
|
|
596
|
-
postcss.atRule({
|
|
597
|
-
name: 'import',
|
|
598
|
-
params: rule.text.replace(IMPORT_COMMENT, ''),
|
|
599
|
-
})
|
|
600
|
-
)
|
|
601
|
-
rule.remove()
|
|
602
|
-
}
|
|
603
|
-
})
|
|
604
|
-
},
|
|
605
|
-
],
|
|
606
|
-
[],
|
|
607
|
-
{},
|
|
608
|
-
]
|
|
612
|
+
: loadBuiltinPostcssPlugins()
|
|
609
613
|
|
|
610
614
|
let plugins = [
|
|
611
615
|
...beforePlugins,
|
|
@@ -705,7 +709,9 @@ async function build() {
|
|
|
705
709
|
return resolveConfig()
|
|
706
710
|
}
|
|
707
711
|
|
|
708
|
-
let [beforePlugins, afterPlugins] = includePostCss
|
|
712
|
+
let [beforePlugins, afterPlugins] = includePostCss
|
|
713
|
+
? await loadPostCssPlugins()
|
|
714
|
+
: loadBuiltinPostcssPlugins()
|
|
709
715
|
|
|
710
716
|
let plugins = [
|
|
711
717
|
...beforePlugins,
|
package/src/corePlugins.js
CHANGED
|
@@ -14,6 +14,7 @@ import { version as tailwindVersion } from '../package.json'
|
|
|
14
14
|
import log from './util/log'
|
|
15
15
|
import { normalizeScreens } from './util/normalizeScreens'
|
|
16
16
|
import { formatBoxShadowValue, parseBoxShadowValue } from './util/parseBoxShadowValue'
|
|
17
|
+
import { removeAlphaVariables } from './util/removeAlphaVariables'
|
|
17
18
|
import { flagEnabled } from './featureFlags'
|
|
18
19
|
|
|
19
20
|
export let variantPlugins = {
|
|
@@ -21,7 +22,19 @@ export let variantPlugins = {
|
|
|
21
22
|
addVariant('first-letter', '&::first-letter')
|
|
22
23
|
addVariant('first-line', '&::first-line')
|
|
23
24
|
|
|
24
|
-
addVariant('marker', [
|
|
25
|
+
addVariant('marker', [
|
|
26
|
+
({ container }) => {
|
|
27
|
+
removeAlphaVariables(container, ['--tw-text-opacity'])
|
|
28
|
+
|
|
29
|
+
return '& *::marker'
|
|
30
|
+
},
|
|
31
|
+
({ container }) => {
|
|
32
|
+
removeAlphaVariables(container, ['--tw-text-opacity'])
|
|
33
|
+
|
|
34
|
+
return '&::marker'
|
|
35
|
+
},
|
|
36
|
+
])
|
|
37
|
+
|
|
25
38
|
addVariant('selection', ['& *::selection', '&::selection'])
|
|
26
39
|
|
|
27
40
|
addVariant('file', '&::file-selector-button')
|
|
@@ -77,21 +90,11 @@ export let variantPlugins = {
|
|
|
77
90
|
[
|
|
78
91
|
'visited',
|
|
79
92
|
({ container }) => {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
return
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
for (const varName of toRemove) {
|
|
90
|
-
if (decl.value.includes(`/ var(${varName})`)) {
|
|
91
|
-
decl.value = decl.value.replace(`/ var(${varName})`, '')
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
})
|
|
93
|
+
removeAlphaVariables(container, [
|
|
94
|
+
'--tw-text-opacity',
|
|
95
|
+
'--tw-border-opacity',
|
|
96
|
+
'--tw-bg-opacity',
|
|
97
|
+
])
|
|
95
98
|
|
|
96
99
|
return '&:visited'
|
|
97
100
|
},
|
|
@@ -12,7 +12,7 @@ export function defaultExtractor(context) {
|
|
|
12
12
|
let results = []
|
|
13
13
|
|
|
14
14
|
for (let pattern of patterns) {
|
|
15
|
-
results
|
|
15
|
+
results = [...results, ...(content.match(pattern) ?? [])]
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
return results.filter((v) => v !== undefined).map(clipAtBalancedParens)
|
|
@@ -25,7 +25,7 @@ function* buildRegExps(context) {
|
|
|
25
25
|
|
|
26
26
|
let utility = regex.any([
|
|
27
27
|
// Arbitrary properties
|
|
28
|
-
/\[[^\s:'"]+:[^\s\]]+\]/,
|
|
28
|
+
/\[[^\s:'"`]+:[^\s\]]+\]/,
|
|
29
29
|
|
|
30
30
|
// Utilities
|
|
31
31
|
regex.pattern([
|
|
@@ -37,28 +37,28 @@ function* buildRegExps(context) {
|
|
|
37
37
|
regex.any([
|
|
38
38
|
regex.pattern([
|
|
39
39
|
// Arbitrary values
|
|
40
|
-
|
|
40
|
+
/-(?:\w+-)*\[[^\s:]+\]/,
|
|
41
41
|
|
|
42
42
|
// Not immediately followed by an `{[(`
|
|
43
43
|
/(?![{([]])/,
|
|
44
44
|
|
|
45
45
|
// optionally followed by an opacity modifier
|
|
46
|
-
/(?:\/[^\s'"
|
|
46
|
+
/(?:\/[^\s'"`\\><$]*)?/,
|
|
47
47
|
]),
|
|
48
48
|
|
|
49
49
|
regex.pattern([
|
|
50
50
|
// Arbitrary values
|
|
51
|
-
|
|
51
|
+
/-(?:\w+-)*\[[^\s]+\]/,
|
|
52
52
|
|
|
53
53
|
// Not immediately followed by an `{[(`
|
|
54
54
|
/(?![{([]])/,
|
|
55
55
|
|
|
56
56
|
// optionally followed by an opacity modifier
|
|
57
|
-
/(?:\/[^\s'"
|
|
57
|
+
/(?:\/[^\s'"`\\$]*)?/,
|
|
58
58
|
]),
|
|
59
59
|
|
|
60
60
|
// Normal values w/o quotes — may include an opacity modifier
|
|
61
|
-
/[-\/][^\s'"
|
|
61
|
+
/[-\/][^\s'"`\\$={><]*/,
|
|
62
62
|
])
|
|
63
63
|
),
|
|
64
64
|
]),
|
|
@@ -69,8 +69,8 @@ function* buildRegExps(context) {
|
|
|
69
69
|
'((?=((',
|
|
70
70
|
regex.any(
|
|
71
71
|
[
|
|
72
|
-
regex.pattern([/([^\s"'
|
|
73
|
-
regex.pattern([/[^\s"'
|
|
72
|
+
regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]/, separator]),
|
|
73
|
+
regex.pattern([/[^\s"'`\[\\]+/, separator]),
|
|
74
74
|
],
|
|
75
75
|
true
|
|
76
76
|
),
|
|
@@ -91,7 +91,7 @@ function* buildRegExps(context) {
|
|
|
91
91
|
])
|
|
92
92
|
|
|
93
93
|
// 5. Inner matches
|
|
94
|
-
|
|
94
|
+
yield /[^<>"'`\s.(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
// We want to capture any "special" characters
|
|
@@ -40,9 +40,7 @@ function listKeys(obj) {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
function validatePath(config, path, defaultValue, themeOpts = {}) {
|
|
43
|
-
const pathString = Array.isArray(path)
|
|
44
|
-
? pathToString(path)
|
|
45
|
-
: path.replace(/^['"]+/g, '').replace(/['"]+$/g, '')
|
|
43
|
+
const pathString = Array.isArray(path) ? pathToString(path) : path.replace(/^['"]+|['"]+$/g, '')
|
|
46
44
|
const pathSegments = Array.isArray(path) ? path : toPath(pathString)
|
|
47
45
|
const value = dlv(config.theme, pathSegments, defaultValue)
|
|
48
46
|
|
|
@@ -162,7 +160,11 @@ let nodeTypePropertyMap = {
|
|
|
162
160
|
export default function ({ tailwindConfig: config }) {
|
|
163
161
|
let functions = {
|
|
164
162
|
theme: (node, path, ...defaultValue) => {
|
|
165
|
-
|
|
163
|
+
// Strip quotes from beginning and end of string
|
|
164
|
+
// This allows the alpha value to be present inside of quotes
|
|
165
|
+
path = path.replace(/^['"]+|['"]+$/g, '')
|
|
166
|
+
|
|
167
|
+
let matches = path.match(/^([^\s]+)(?![^\[]*\])(?:\s*\/\s*([^\/\s]+))$/)
|
|
166
168
|
let alpha = undefined
|
|
167
169
|
|
|
168
170
|
if (matches) {
|
package/src/lib/generateRules.js
CHANGED
|
@@ -163,15 +163,17 @@ function applyVariant(variant, matches, context) {
|
|
|
163
163
|
|
|
164
164
|
let container = postcss.root({ nodes: [rule.clone()] })
|
|
165
165
|
|
|
166
|
-
for (let [variantSort, variantFunction] of variantFunctionTuples) {
|
|
167
|
-
let clone = container.clone()
|
|
166
|
+
for (let [variantSort, variantFunction, containerFromArray] of variantFunctionTuples) {
|
|
167
|
+
let clone = containerFromArray ?? container.clone()
|
|
168
168
|
let collectedFormats = []
|
|
169
169
|
|
|
170
|
-
let originals = new Map()
|
|
171
|
-
|
|
172
170
|
function prepareBackup() {
|
|
173
|
-
|
|
174
|
-
clone.
|
|
171
|
+
// Already prepared, chicken out
|
|
172
|
+
if (clone.raws.neededBackup) {
|
|
173
|
+
return
|
|
174
|
+
}
|
|
175
|
+
clone.raws.neededBackup = true
|
|
176
|
+
clone.walkRules((rule) => (rule.raws.originalSelector = rule.selector))
|
|
175
177
|
}
|
|
176
178
|
|
|
177
179
|
function modifySelectors(modifierFunction) {
|
|
@@ -231,6 +233,10 @@ function applyVariant(variant, matches, context) {
|
|
|
231
233
|
// reserving additional X places for these 'unknown' variants in between.
|
|
232
234
|
variantSort | BigInt(idx << ruleWithVariant.length),
|
|
233
235
|
variantFunction,
|
|
236
|
+
|
|
237
|
+
// If the clone has been modified we have to pass that back
|
|
238
|
+
// though so each rule can use the modified container
|
|
239
|
+
clone.clone(),
|
|
234
240
|
])
|
|
235
241
|
}
|
|
236
242
|
continue
|
|
@@ -244,13 +250,15 @@ function applyVariant(variant, matches, context) {
|
|
|
244
250
|
continue
|
|
245
251
|
}
|
|
246
252
|
|
|
247
|
-
// We
|
|
253
|
+
// We had to backup selectors, therefore we assume that somebody touched
|
|
248
254
|
// `container` or `modifySelectors`. Let's see if they did, so that we
|
|
249
255
|
// can restore the selectors, and collect the format strings.
|
|
250
|
-
if (
|
|
256
|
+
if (clone.raws.neededBackup) {
|
|
257
|
+
delete clone.raws.neededBackup
|
|
251
258
|
clone.walkRules((rule) => {
|
|
252
|
-
|
|
253
|
-
|
|
259
|
+
let before = rule.raws.originalSelector
|
|
260
|
+
if (!before) return
|
|
261
|
+
delete rule.raws.originalSelector
|
|
254
262
|
if (before === rule.selector) return // No mutation happened
|
|
255
263
|
|
|
256
264
|
let modified = rule.selector
|
|
@@ -91,56 +91,73 @@ export default function resolveDefaultsAtRules({ tailwindConfig }) {
|
|
|
91
91
|
rule.remove()
|
|
92
92
|
})
|
|
93
93
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
if (flagEnabled(tailwindConfig, 'optimizeUniversalDefaults')) {
|
|
95
|
+
for (let universal of universals) {
|
|
96
|
+
/** @type {Map<string, Set<string>>} */
|
|
97
|
+
let selectorGroups = new Map()
|
|
98
|
+
|
|
99
|
+
let rules = variableNodeMap.get(universal.params) ?? []
|
|
100
|
+
|
|
101
|
+
for (let rule of rules) {
|
|
102
|
+
for (let selector of extractElementSelector(rule.selector)) {
|
|
103
|
+
// If selector contains a vendor prefix after a pseudo element or class,
|
|
104
|
+
// we consider them separately because merging the declarations into
|
|
105
|
+
// a single rule will cause browsers that do not understand the
|
|
106
|
+
// vendor prefix to throw out the whole rule
|
|
107
|
+
let selectorGroupName =
|
|
108
|
+
selector.includes(':-') || selector.includes('::-') ? selector : '__DEFAULT__'
|
|
109
|
+
|
|
110
|
+
let selectors = selectorGroups.get(selectorGroupName) ?? new Set()
|
|
111
|
+
selectorGroups.set(selectorGroupName, selectors)
|
|
112
|
+
|
|
113
|
+
selectors.add(selector)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
97
116
|
|
|
98
|
-
|
|
117
|
+
if (flagEnabled(tailwindConfig, 'optimizeUniversalDefaults')) {
|
|
118
|
+
if (selectorGroups.size === 0) {
|
|
119
|
+
universal.remove()
|
|
120
|
+
continue
|
|
121
|
+
}
|
|
99
122
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
// a single rule will cause browsers that do not understand the
|
|
105
|
-
// vendor prefix to throw out the whole rule
|
|
106
|
-
let selectorGroupName =
|
|
107
|
-
selector.includes(':-') || selector.includes('::-') ? selector : '__DEFAULT__'
|
|
123
|
+
for (let [, selectors] of selectorGroups) {
|
|
124
|
+
let universalRule = postcss.rule({
|
|
125
|
+
source: universal.source,
|
|
126
|
+
})
|
|
108
127
|
|
|
109
|
-
|
|
110
|
-
selectorGroups.set(selectorGroupName, selectors)
|
|
128
|
+
universalRule.selectors = [...selectors]
|
|
111
129
|
|
|
112
|
-
|
|
130
|
+
universalRule.append(universal.nodes.map((node) => node.clone()))
|
|
131
|
+
universal.before(universalRule)
|
|
132
|
+
}
|
|
113
133
|
}
|
|
114
|
-
}
|
|
115
134
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
for (let [, selectors] of selectorGroups) {
|
|
123
|
-
let universalRule = postcss.rule({
|
|
124
|
-
source: universal.source,
|
|
125
|
-
})
|
|
135
|
+
universal.remove()
|
|
136
|
+
}
|
|
137
|
+
} else if (universals.size) {
|
|
138
|
+
let universalRule = postcss.rule({
|
|
139
|
+
selectors: ['*', '::before', '::after'],
|
|
140
|
+
})
|
|
126
141
|
|
|
127
|
-
|
|
142
|
+
for (let universal of universals) {
|
|
143
|
+
universalRule.append(universal.nodes)
|
|
128
144
|
|
|
129
|
-
|
|
145
|
+
if (!universalRule.parent) {
|
|
130
146
|
universal.before(universalRule)
|
|
131
147
|
}
|
|
132
|
-
} else {
|
|
133
|
-
let universalRule = postcss.rule({
|
|
134
|
-
source: universal.source,
|
|
135
|
-
})
|
|
136
148
|
|
|
137
|
-
universalRule.
|
|
149
|
+
if (!universalRule.source) {
|
|
150
|
+
universalRule.source = universal.source
|
|
151
|
+
}
|
|
138
152
|
|
|
139
|
-
|
|
140
|
-
universal.before(universalRule)
|
|
153
|
+
universal.remove()
|
|
141
154
|
}
|
|
142
155
|
|
|
143
|
-
|
|
156
|
+
let backdropRule = universalRule.clone({
|
|
157
|
+
selectors: ['::backdrop'],
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
universalRule.after(backdropRule)
|
|
144
161
|
}
|
|
145
162
|
}
|
|
146
163
|
}
|
|
@@ -465,11 +465,14 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
465
465
|
}
|
|
466
466
|
|
|
467
467
|
if (Array.isArray(result)) {
|
|
468
|
-
return result
|
|
468
|
+
return result
|
|
469
|
+
.filter((variant) => typeof variant === 'string')
|
|
470
|
+
.map((variant) => parseVariant(variant))
|
|
469
471
|
}
|
|
470
472
|
|
|
471
473
|
// result may be undefined with legacy variants that use APIs like `modifySelectors`
|
|
472
|
-
|
|
474
|
+
// result may also be a postcss node if someone was returning the result from `modifySelectors`
|
|
475
|
+
return result && typeof result === 'string' && parseVariant(result)(api)
|
|
473
476
|
}
|
|
474
477
|
}
|
|
475
478
|
|
package/src/util/dataTypes.js
CHANGED
|
@@ -40,9 +40,9 @@ export function normalize(value, isRoot = true) {
|
|
|
40
40
|
value = value.trim()
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
// Add spaces around operators inside calc() that do not follow an operator
|
|
43
|
+
// Add spaces around operators inside math functions like calc() that do not follow an operator
|
|
44
44
|
// or '('.
|
|
45
|
-
value = value.replace(/calc\(.+\)/g, (match) => {
|
|
45
|
+
value = value.replace(/(calc|min|max|clamp)\(.+\)/g, (match) => {
|
|
46
46
|
return match.replace(
|
|
47
47
|
/(-?\d*\.?\d(?!\b-.+[,)](?![^+\-/*])\D)(?:%|[a-z]+)?|\))([+\-/*])/g,
|
|
48
48
|
'$1 $2 '
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This function removes any uses of CSS variables used as an alpha channel
|
|
3
|
+
*
|
|
4
|
+
* This is required for selectors like `:visited` which do not allow
|
|
5
|
+
* changes in opacity or external control using CSS variables.
|
|
6
|
+
*
|
|
7
|
+
* @param {import('postcss').Container} container
|
|
8
|
+
* @param {string[]} toRemove
|
|
9
|
+
*/
|
|
10
|
+
export function removeAlphaVariables(container, toRemove) {
|
|
11
|
+
container.walkDecls((decl) => {
|
|
12
|
+
if (toRemove.includes(decl.prop)) {
|
|
13
|
+
decl.remove()
|
|
14
|
+
|
|
15
|
+
return
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
for (let varName of toRemove) {
|
|
19
|
+
if (decl.value.includes(`/ var(${varName})`)) {
|
|
20
|
+
decl.value = decl.value.replace(`/ var(${varName})`, '')
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
})
|
|
24
|
+
}
|
package/types/config.d.ts
CHANGED
package/types/index.d.ts
CHANGED