tailwindcss 0.0.0-insiders.8259dfd → 0.0.0-insiders.8293c2d
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 +207 -2
- package/README.md +8 -4
- package/colors.js +2 -1
- package/defaultConfig.js +2 -1
- package/defaultTheme.js +2 -1
- package/lib/cli.js +94 -61
- package/lib/constants.js +1 -1
- package/lib/corePluginList.js +8 -1
- package/lib/corePlugins.js +477 -517
- package/lib/css/preflight.css +18 -5
- package/lib/featureFlags.js +5 -6
- package/lib/index.js +1 -3
- package/lib/lib/collapseDuplicateDeclarations.js +80 -0
- package/lib/lib/defaultExtractor.js +42 -0
- package/lib/lib/detectNesting.js +17 -2
- package/lib/lib/evaluateTailwindFunctions.js +10 -6
- package/lib/lib/expandApplyAtRules.js +94 -45
- package/lib/lib/expandTailwindAtRules.js +32 -33
- package/lib/lib/generateRules.js +167 -21
- package/lib/lib/normalizeTailwindDirectives.js +8 -1
- package/lib/lib/partitionApplyAtRules.js +53 -0
- package/lib/lib/resolveDefaultsAtRules.js +28 -14
- package/lib/lib/setupContextUtils.js +153 -129
- package/lib/lib/setupTrackingContext.js +11 -10
- package/lib/lib/sharedState.js +34 -5
- package/lib/lib/substituteScreenAtRules.js +7 -4
- package/lib/processTailwindFeatures.js +7 -2
- package/lib/util/buildMediaQuery.js +13 -24
- package/lib/util/color.js +23 -8
- package/lib/util/createPlugin.js +1 -2
- package/lib/util/createUtilityPlugin.js +6 -10
- package/lib/util/dataTypes.js +38 -7
- package/lib/util/defaults.js +6 -0
- package/lib/util/flattenColorPalette.js +1 -3
- package/lib/util/formatVariantSelector.js +186 -0
- package/lib/util/isValidArbitraryValue.js +64 -0
- package/lib/util/log.js +4 -0
- package/lib/util/nameClass.js +1 -0
- package/lib/util/normalizeConfig.js +63 -21
- package/lib/util/normalizeScreens.js +59 -0
- package/lib/util/parseBoxShadowValue.js +77 -0
- package/lib/util/pluginUtils.js +27 -158
- package/lib/util/prefixSelector.js +1 -3
- package/lib/util/resolveConfig.js +30 -31
- package/lib/util/resolveConfigPath.js +1 -2
- package/lib/util/toColorValue.js +1 -2
- package/lib/util/toPath.js +6 -1
- package/lib/util/transformThemeValue.js +19 -13
- package/nesting/plugin.js +4 -1
- package/package.json +19 -21
- package/peers/index.js +4621 -5626
- package/plugin.js +2 -1
- package/resolveConfig.js +2 -1
- package/src/cli.js +66 -14
- package/src/corePluginList.js +1 -1
- package/src/corePlugins.js +406 -518
- package/src/css/preflight.css +18 -5
- package/src/featureFlags.js +1 -1
- package/src/index.js +1 -7
- package/src/lib/collapseDuplicateDeclarations.js +93 -0
- package/src/lib/defaultExtractor.js +48 -0
- package/src/lib/detectNesting.js +22 -3
- package/src/lib/evaluateTailwindFunctions.js +6 -3
- package/src/lib/expandApplyAtRules.js +101 -45
- package/src/lib/expandTailwindAtRules.js +33 -27
- package/src/lib/generateRules.js +178 -11
- package/src/lib/normalizeTailwindDirectives.js +6 -1
- package/src/lib/partitionApplyAtRules.js +52 -0
- package/src/lib/resolveDefaultsAtRules.js +31 -10
- package/src/lib/setupContextUtils.js +140 -84
- package/src/lib/setupTrackingContext.js +11 -10
- package/src/lib/sharedState.js +40 -4
- package/src/lib/substituteScreenAtRules.js +6 -3
- package/src/processTailwindFeatures.js +8 -2
- package/src/util/buildMediaQuery.js +14 -18
- package/src/util/color.js +20 -7
- package/src/util/dataTypes.js +43 -11
- package/src/util/defaults.js +6 -0
- package/src/util/formatVariantSelector.js +196 -0
- package/src/util/isValidArbitraryValue.js +61 -0
- package/src/util/log.js +4 -0
- package/src/util/nameClass.js +1 -1
- package/src/util/normalizeConfig.js +37 -2
- package/src/util/normalizeScreens.js +45 -0
- package/src/util/parseBoxShadowValue.js +71 -0
- package/src/util/pluginUtils.js +15 -138
- package/src/util/prefixSelector.js +1 -4
- package/src/util/resolveConfig.js +11 -1
- package/src/util/toPath.js +23 -1
- package/src/util/transformThemeValue.js +22 -7
- package/stubs/defaultConfig.stub.js +42 -16
- package/lib/lib/setupWatchingContext.js +0 -284
- package/src/lib/setupWatchingContext.js +0 -304
package/lib/css/preflight.css
CHANGED
|
@@ -9,7 +9,12 @@
|
|
|
9
9
|
box-sizing: border-box; /* 1 */
|
|
10
10
|
border-width: 0; /* 2 */
|
|
11
11
|
border-style: solid; /* 2 */
|
|
12
|
-
border-color: currentColor; /* 2 */
|
|
12
|
+
border-color: theme('borderColor.DEFAULT', 'currentColor'); /* 2 */
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
::before,
|
|
16
|
+
::after {
|
|
17
|
+
--tw-content: '';
|
|
13
18
|
}
|
|
14
19
|
|
|
15
20
|
/*
|
|
@@ -53,7 +58,7 @@ hr {
|
|
|
53
58
|
Add the correct text decoration in Chrome, Edge, and Safari.
|
|
54
59
|
*/
|
|
55
60
|
|
|
56
|
-
abbr[title] {
|
|
61
|
+
abbr:where([title]) {
|
|
57
62
|
text-decoration: underline dotted;
|
|
58
63
|
}
|
|
59
64
|
|
|
@@ -139,7 +144,7 @@ sup {
|
|
|
139
144
|
table {
|
|
140
145
|
text-indent: 0; /* 1 */
|
|
141
146
|
border-color: inherit; /* 2 */
|
|
142
|
-
border-collapse: collapse;
|
|
147
|
+
border-collapse: collapse; /* 3 */
|
|
143
148
|
}
|
|
144
149
|
|
|
145
150
|
/*
|
|
@@ -283,7 +288,8 @@ legend {
|
|
|
283
288
|
}
|
|
284
289
|
|
|
285
290
|
ol,
|
|
286
|
-
ul
|
|
291
|
+
ul,
|
|
292
|
+
menu {
|
|
287
293
|
list-style: none;
|
|
288
294
|
margin: 0;
|
|
289
295
|
padding: 0;
|
|
@@ -304,7 +310,7 @@ textarea {
|
|
|
304
310
|
|
|
305
311
|
input::placeholder,
|
|
306
312
|
textarea::placeholder {
|
|
307
|
-
opacity: 1;
|
|
313
|
+
opacity: 1; /* 1 */
|
|
308
314
|
color: theme('colors.gray.400', #9ca3af); /* 2 */
|
|
309
315
|
}
|
|
310
316
|
|
|
@@ -317,6 +323,13 @@ button,
|
|
|
317
323
|
cursor: pointer;
|
|
318
324
|
}
|
|
319
325
|
|
|
326
|
+
/*
|
|
327
|
+
Make sure disabled buttons don't get the pointer cursor.
|
|
328
|
+
*/
|
|
329
|
+
:disabled {
|
|
330
|
+
cursor: default;
|
|
331
|
+
}
|
|
332
|
+
|
|
320
333
|
/*
|
|
321
334
|
1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
|
|
322
335
|
2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
|
package/lib/featureFlags.js
CHANGED
|
@@ -13,7 +13,7 @@ function _interopRequireDefault(obj) {
|
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
15
|
let defaults = {
|
|
16
|
-
optimizeUniversalDefaults:
|
|
16
|
+
optimizeUniversalDefaults: false
|
|
17
17
|
};
|
|
18
18
|
let featureFlags = {
|
|
19
19
|
future: [],
|
|
@@ -28,9 +28,9 @@ function flagEnabled(config, flag) {
|
|
|
28
28
|
return config.future === 'all' || ((ref2 = (ref1 = config === null || config === void 0 ? void 0 : (ref = config.future) === null || ref === void 0 ? void 0 : ref[flag]) !== null && ref1 !== void 0 ? ref1 : defaults[flag]) !== null && ref2 !== void 0 ? ref2 : false);
|
|
29
29
|
}
|
|
30
30
|
if (featureFlags.experimental.includes(flag)) {
|
|
31
|
-
var
|
|
32
|
-
var
|
|
33
|
-
return config.experimental === 'all' || ((
|
|
31
|
+
var ref3;
|
|
32
|
+
var ref4, ref5;
|
|
33
|
+
return config.experimental === 'all' || ((ref5 = (ref4 = config === null || config === void 0 ? void 0 : (ref3 = config.experimental) === null || ref3 === void 0 ? void 0 : ref3[flag]) !== null && ref4 !== void 0 ? ref4 : defaults[flag]) !== null && ref5 !== void 0 ? ref5 : false);
|
|
34
34
|
}
|
|
35
35
|
return false;
|
|
36
36
|
}
|
|
@@ -39,8 +39,7 @@ function experimentalFlagsEnabled(config) {
|
|
|
39
39
|
return featureFlags.experimental;
|
|
40
40
|
}
|
|
41
41
|
var ref;
|
|
42
|
-
return Object.keys((ref = config === null || config === void 0 ? void 0 : config.experimental) !== null && ref !== void 0 ? ref : {
|
|
43
|
-
}).filter((flag)=>featureFlags.experimental.includes(flag) && config.experimental[flag]
|
|
42
|
+
return Object.keys((ref = config === null || config === void 0 ? void 0 : config.experimental) !== null && ref !== void 0 ? ref : {}).filter((flag)=>featureFlags.experimental.includes(flag) && config.experimental[flag]
|
|
44
43
|
);
|
|
45
44
|
}
|
|
46
45
|
function issueFlagNotices(config) {
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var _setupTrackingContext = _interopRequireDefault(require("./lib/setupTrackingContext"));
|
|
3
|
-
var _setupWatchingContext = _interopRequireDefault(require("./lib/setupWatchingContext"));
|
|
4
3
|
var _processTailwindFeatures = _interopRequireDefault(require("./processTailwindFeatures"));
|
|
5
4
|
var _sharedState = require("./lib/sharedState");
|
|
6
5
|
function _interopRequireDefault(obj) {
|
|
@@ -18,8 +17,7 @@ module.exports = function tailwindcss(configOrPath) {
|
|
|
18
17
|
return root;
|
|
19
18
|
},
|
|
20
19
|
function(root, result) {
|
|
21
|
-
|
|
22
|
-
(0, _processTailwindFeatures).default(setupContext)(root, result);
|
|
20
|
+
(0, _processTailwindFeatures).default((0, _setupTrackingContext).default(configOrPath))(root, result);
|
|
23
21
|
},
|
|
24
22
|
_sharedState.env.DEBUG && function(root) {
|
|
25
23
|
console.timeEnd('JIT TOTAL');
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
exports.default = collapseDuplicateDeclarations;
|
|
6
|
+
function collapseDuplicateDeclarations() {
|
|
7
|
+
return (root)=>{
|
|
8
|
+
root.walkRules((node)=>{
|
|
9
|
+
let seen = new Map();
|
|
10
|
+
let droppable = new Set([]);
|
|
11
|
+
let byProperty = new Map();
|
|
12
|
+
node.walkDecls((decl)=>{
|
|
13
|
+
// This could happen if we have nested selectors. In that case the
|
|
14
|
+
// parent will loop over all its declarations but also the declarations
|
|
15
|
+
// of nested rules. With this we ensure that we are shallowly checking
|
|
16
|
+
// declarations.
|
|
17
|
+
if (decl.parent !== node) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (seen.has(decl.prop)) {
|
|
21
|
+
// Exact same value as what we have seen so far
|
|
22
|
+
if (seen.get(decl.prop).value === decl.value) {
|
|
23
|
+
// Keep the last one, drop the one we've seen so far
|
|
24
|
+
droppable.add(seen.get(decl.prop));
|
|
25
|
+
// Override the existing one with the new value. This is necessary
|
|
26
|
+
// so that if we happen to have more than one declaration with the
|
|
27
|
+
// same value, that we keep removing the previous one. Otherwise we
|
|
28
|
+
// will only remove the *first* one.
|
|
29
|
+
seen.set(decl.prop, decl);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
// Not the same value, so we need to check if we can merge it so
|
|
33
|
+
// let's collect it first.
|
|
34
|
+
if (!byProperty.has(decl.prop)) {
|
|
35
|
+
byProperty.set(decl.prop, new Set());
|
|
36
|
+
}
|
|
37
|
+
byProperty.get(decl.prop).add(seen.get(decl.prop));
|
|
38
|
+
byProperty.get(decl.prop).add(decl);
|
|
39
|
+
}
|
|
40
|
+
seen.set(decl.prop, decl);
|
|
41
|
+
});
|
|
42
|
+
// Drop all the duplicate declarations with the exact same value we've
|
|
43
|
+
// already seen so far.
|
|
44
|
+
for (let decl1 of droppable){
|
|
45
|
+
decl1.remove();
|
|
46
|
+
}
|
|
47
|
+
// Analyze the declarations based on its unit, drop all the declarations
|
|
48
|
+
// with the same unit but the last one in the list.
|
|
49
|
+
for (let declarations of byProperty.values()){
|
|
50
|
+
let byUnit = new Map();
|
|
51
|
+
for (let decl of declarations){
|
|
52
|
+
let unit = resolveUnit(decl.value);
|
|
53
|
+
if (unit === null) {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (!byUnit.has(unit)) {
|
|
57
|
+
byUnit.set(unit, new Set());
|
|
58
|
+
}
|
|
59
|
+
byUnit.get(unit).add(decl);
|
|
60
|
+
}
|
|
61
|
+
for (let declarations1 of byUnit.values()){
|
|
62
|
+
// Get all but the last one
|
|
63
|
+
let removableDeclarations = Array.from(declarations1).slice(0, -1);
|
|
64
|
+
for (let decl of removableDeclarations){
|
|
65
|
+
decl.remove();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
let UNITLESS_NUMBER = Symbol('unitless-number');
|
|
73
|
+
function resolveUnit(input) {
|
|
74
|
+
let result = /^-?\d*.?\d+([\w%]+)?$/g.exec(input);
|
|
75
|
+
if (result) {
|
|
76
|
+
var ref;
|
|
77
|
+
return (ref = result[1]) !== null && ref !== void 0 ? ref : UNITLESS_NUMBER;
|
|
78
|
+
}
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
exports.defaultExtractor = defaultExtractor;
|
|
6
|
+
const PATTERNS = [
|
|
7
|
+
/(?:\['([^'\s]+[^<>"'`\s:\\])')/.source,
|
|
8
|
+
/(?:\["([^"\s]+[^<>"'`\s:\\])")/.source,
|
|
9
|
+
/(?:\[`([^`\s]+[^<>"'`\s:\\])`)/.source,
|
|
10
|
+
/([^<>"'`\s]*\[\w*'[^"`\s]*'?\])/.source,
|
|
11
|
+
/([^<>"'`\s]*\[\w*"[^'`\s]*"?\])/.source,
|
|
12
|
+
/([^<>"'`\s]*\[\w*\('[^"'`\s]*'\)\])/.source,
|
|
13
|
+
/([^<>"'`\s]*\[\w*\("[^"'`\s]*"\)\])/.source,
|
|
14
|
+
/([^<>"'`\s]*\[\w*\('[^"`\s]*'\)\])/.source,
|
|
15
|
+
/([^<>"'`\s]*\[\w*\("[^'`\s]*"\)\])/.source,
|
|
16
|
+
/([^<>"'`\s]*\['[^"'`\s]*'\])/.source,
|
|
17
|
+
/([^<>"'`\s]*\["[^"'`\s]*"\])/.source,
|
|
18
|
+
/([^<>"'`\s]*\[[^<>"'`\s]*:[^\]\s]*\])/.source,
|
|
19
|
+
/([^<>"'`\s]*\[[^<>"'`\s]*:'[^"'`\s]*'\])/.source,
|
|
20
|
+
/([^<>"'`\s]*\[[^<>"'`\s]*:"[^"'`\s]*"\])/.source,
|
|
21
|
+
/([^<>"'`\s]*\[[^"'`\s]+\][^<>"'`\s]*)/.source,
|
|
22
|
+
/([^"'`\s]*[^<>"'`\s:\\])/.source,
|
|
23
|
+
/([^<>"'`\s]*[^"'`\s:\\])/.source,
|
|
24
|
+
].join('|');
|
|
25
|
+
const BROAD_MATCH_GLOBAL_REGEXP = new RegExp(PATTERNS, 'g');
|
|
26
|
+
const INNER_MATCH_GLOBAL_REGEXP = /[^<>"'`\s.(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g;
|
|
27
|
+
function defaultExtractor(content) {
|
|
28
|
+
let broadMatches = content.matchAll(BROAD_MATCH_GLOBAL_REGEXP);
|
|
29
|
+
let innerMatches = content.match(INNER_MATCH_GLOBAL_REGEXP) || [];
|
|
30
|
+
let results = [
|
|
31
|
+
...broadMatches,
|
|
32
|
+
...innerMatches
|
|
33
|
+
].flat().filter((v)=>v !== undefined
|
|
34
|
+
);
|
|
35
|
+
return results;
|
|
36
|
+
} // Regular utilities
|
|
37
|
+
// {{modifier}:}*{namespace}{-{suffix}}*{/{opacityModifier}}?
|
|
38
|
+
// Arbitrary values
|
|
39
|
+
// {{modifier}:}*{namespace}-[{arbitraryValue}]{/{opacityModifier}}?
|
|
40
|
+
// arbitraryValue: no whitespace, balanced quotes unless within quotes, balanced brackets unless within quotes
|
|
41
|
+
// Arbitrary properties
|
|
42
|
+
// {{modifier}:}*[{validCssPropertyName}:{arbitraryValue}]
|
package/lib/lib/detectNesting.js
CHANGED
|
@@ -6,12 +6,27 @@ exports.default = _default;
|
|
|
6
6
|
function _default(_context) {
|
|
7
7
|
return (root, result)=>{
|
|
8
8
|
let found = false;
|
|
9
|
+
root.walkAtRules('tailwind', (node)=>{
|
|
10
|
+
if (found) return false;
|
|
11
|
+
if (node.parent && node.parent.type !== 'root') {
|
|
12
|
+
found = true;
|
|
13
|
+
node.warn(result, [
|
|
14
|
+
'Nested @tailwind rules were detected, but are not supported.',
|
|
15
|
+
"Consider using a prefix to scope Tailwind's classes: https://tailwindcss.com/docs/configuration#prefix",
|
|
16
|
+
'Alternatively, use the important selector strategy: https://tailwindcss.com/docs/configuration#selector-strategy',
|
|
17
|
+
].join('\n'));
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
});
|
|
9
21
|
root.walkRules((rule)=>{
|
|
10
22
|
if (found) return false;
|
|
11
23
|
rule.walkRules((nestedRule)=>{
|
|
12
24
|
found = true;
|
|
13
|
-
nestedRule.warn(result,
|
|
14
|
-
|
|
25
|
+
nestedRule.warn(result, [
|
|
26
|
+
'Nested CSS was detected, but CSS nesting has not been configured correctly.',
|
|
27
|
+
'Please enable a CSS nesting plugin *before* Tailwind in your configuration.',
|
|
28
|
+
'See how here: https://tailwindcss.com/docs/using-with-preprocessors#nesting',
|
|
29
|
+
].join('\n'));
|
|
15
30
|
return false;
|
|
16
31
|
});
|
|
17
32
|
});
|
|
@@ -7,6 +7,7 @@ var _dlv = _interopRequireDefault(require("dlv"));
|
|
|
7
7
|
var _didyoumean = _interopRequireDefault(require("didyoumean"));
|
|
8
8
|
var _transformThemeValue = _interopRequireDefault(require("../util/transformThemeValue"));
|
|
9
9
|
var _postcssValueParser = _interopRequireDefault(require("postcss-value-parser"));
|
|
10
|
+
var _normalizeScreens = require("../util/normalizeScreens");
|
|
10
11
|
var _buildMediaQuery = _interopRequireDefault(require("../util/buildMediaQuery"));
|
|
11
12
|
var _toPath = require("../util/toPath");
|
|
12
13
|
function _interopRequireDefault(obj) {
|
|
@@ -42,7 +43,7 @@ function listKeys(obj) {
|
|
|
42
43
|
function validatePath(config, path, defaultValue) {
|
|
43
44
|
const pathString = Array.isArray(path) ? pathToString(path) : path.replace(/^['"]+/g, '').replace(/['"]+$/g, '');
|
|
44
45
|
const pathSegments = Array.isArray(path) ? path : (0, _toPath).toPath(pathString);
|
|
45
|
-
const value = (0, _dlv).default(config.theme,
|
|
46
|
+
const value = (0, _dlv).default(config.theme, pathSegments, defaultValue);
|
|
46
47
|
if (value === undefined) {
|
|
47
48
|
let error = `'${pathString}' does not exist in your theme config.`;
|
|
48
49
|
const parentSegments = pathSegments.slice(0, -1);
|
|
@@ -112,11 +113,11 @@ function extractArgs(node, vNodes, functions) {
|
|
|
112
113
|
let args = [
|
|
113
114
|
''
|
|
114
115
|
];
|
|
115
|
-
for (let
|
|
116
|
-
if (
|
|
116
|
+
for (let vNode1 of vNodes){
|
|
117
|
+
if (vNode1.type === 'div' && vNode1.value === ',') {
|
|
117
118
|
args.push('');
|
|
118
119
|
} else {
|
|
119
|
-
args[args.length - 1] += _postcssValueParser.default.stringify(
|
|
120
|
+
args[args.length - 1] += _postcssValueParser.default.stringify(vNode1);
|
|
120
121
|
}
|
|
121
122
|
}
|
|
122
123
|
return args;
|
|
@@ -149,10 +150,13 @@ function _default({ tailwindConfig: config }) {
|
|
|
149
150
|
},
|
|
150
151
|
screen: (node, screen)=>{
|
|
151
152
|
screen = screen.replace(/^['"]+/g, '').replace(/['"]+$/g, '');
|
|
152
|
-
|
|
153
|
+
let screens = (0, _normalizeScreens).normalizeScreens(config.theme.screens);
|
|
154
|
+
let screenDefinition = screens.find(({ name })=>name === screen
|
|
155
|
+
);
|
|
156
|
+
if (!screenDefinition) {
|
|
153
157
|
throw node.error(`The '${screen}' screen does not exist in your theme.`);
|
|
154
158
|
}
|
|
155
|
-
return (0, _buildMediaQuery).default(
|
|
159
|
+
return (0, _buildMediaQuery).default(screenDefinition);
|
|
156
160
|
}
|
|
157
161
|
};
|
|
158
162
|
return (root)=>{
|
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
});
|
|
5
5
|
exports.default = expandApplyAtRules;
|
|
6
6
|
var _postcss = _interopRequireDefault(require("postcss"));
|
|
7
|
+
var _postcssSelectorParser = _interopRequireDefault(require("postcss-selector-parser"));
|
|
7
8
|
var _generateRules = require("./generateRules");
|
|
8
9
|
var _bigSign = _interopRequireDefault(require("../util/bigSign"));
|
|
9
10
|
var _escapeClassName = _interopRequireDefault(require("../util/escapeClassName"));
|
|
@@ -12,9 +13,32 @@ function _interopRequireDefault(obj) {
|
|
|
12
13
|
default: obj
|
|
13
14
|
};
|
|
14
15
|
}
|
|
16
|
+
function extractClasses(node) {
|
|
17
|
+
let classes = new Set();
|
|
18
|
+
let container = _postcss.default.root({
|
|
19
|
+
nodes: [
|
|
20
|
+
node.clone()
|
|
21
|
+
]
|
|
22
|
+
});
|
|
23
|
+
container.walkRules((rule)=>{
|
|
24
|
+
(0, _postcssSelectorParser).default((selectors)=>{
|
|
25
|
+
selectors.walkClasses((classSelector)=>{
|
|
26
|
+
classes.add(classSelector.value);
|
|
27
|
+
});
|
|
28
|
+
}).processSync(rule.selector);
|
|
29
|
+
});
|
|
30
|
+
return Array.from(classes);
|
|
31
|
+
}
|
|
32
|
+
function extractBaseCandidates(candidates, separator) {
|
|
33
|
+
let baseClasses = new Set();
|
|
34
|
+
for (let candidate of candidates){
|
|
35
|
+
baseClasses.add(candidate.split(separator).pop());
|
|
36
|
+
}
|
|
37
|
+
return Array.from(baseClasses);
|
|
38
|
+
}
|
|
15
39
|
function prefix(context, selector) {
|
|
16
|
-
let
|
|
17
|
-
return typeof
|
|
40
|
+
let prefix1 = context.tailwindConfig.prefix;
|
|
41
|
+
return typeof prefix1 === 'function' ? prefix1(selector) : prefix1 + selector;
|
|
18
42
|
}
|
|
19
43
|
function buildApplyCache(applyCandidates, context) {
|
|
20
44
|
for (let candidate of applyCandidates){
|
|
@@ -51,45 +75,6 @@ function extractApplyCandidates(params) {
|
|
|
51
75
|
false
|
|
52
76
|
];
|
|
53
77
|
}
|
|
54
|
-
function partitionApplyParents(root) {
|
|
55
|
-
let applyParents = new Set();
|
|
56
|
-
root.walkAtRules('apply', (rule)=>{
|
|
57
|
-
applyParents.add(rule.parent);
|
|
58
|
-
});
|
|
59
|
-
for (let rule of applyParents){
|
|
60
|
-
let nodeGroups = [];
|
|
61
|
-
let lastGroup = [];
|
|
62
|
-
for (let node of rule.nodes){
|
|
63
|
-
if (node.type === 'atrule' && node.name === 'apply') {
|
|
64
|
-
if (lastGroup.length > 0) {
|
|
65
|
-
nodeGroups.push(lastGroup);
|
|
66
|
-
lastGroup = [];
|
|
67
|
-
}
|
|
68
|
-
nodeGroups.push([
|
|
69
|
-
node
|
|
70
|
-
]);
|
|
71
|
-
} else {
|
|
72
|
-
lastGroup.push(node);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
if (lastGroup.length > 0) {
|
|
76
|
-
nodeGroups.push(lastGroup);
|
|
77
|
-
}
|
|
78
|
-
if (nodeGroups.length === 1) {
|
|
79
|
-
continue;
|
|
80
|
-
}
|
|
81
|
-
for (let group of [
|
|
82
|
-
...nodeGroups
|
|
83
|
-
].reverse()){
|
|
84
|
-
let newParent = rule.clone({
|
|
85
|
-
nodes: []
|
|
86
|
-
});
|
|
87
|
-
newParent.append(group);
|
|
88
|
-
rule.after(newParent);
|
|
89
|
-
}
|
|
90
|
-
rule.remove();
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
78
|
function processApply(root, context) {
|
|
94
79
|
let applyCandidates = new Set();
|
|
95
80
|
// Collect all @apply rules and candidates
|
|
@@ -127,8 +112,8 @@ function processApply(root, context) {
|
|
|
127
112
|
*/ // TODO: Should we use postcss-selector-parser for this instead?
|
|
128
113
|
function replaceSelector(selector, utilitySelectors, candidate) {
|
|
129
114
|
let needle = `.${(0, _escapeClassName).default(candidate)}`;
|
|
130
|
-
let utilitySelectorsList = utilitySelectors.split(/\s
|
|
131
|
-
return selector.split(/\s
|
|
115
|
+
let utilitySelectorsList = utilitySelectors.split(/\s*\,(?![^(]*\))\s*/g);
|
|
116
|
+
return selector.split(/\s*\,(?![^(]*\))\s*/g).map((s)=>{
|
|
132
117
|
let replaced = [];
|
|
133
118
|
for (let utilitySelector of utilitySelectorsList){
|
|
134
119
|
let replacedSelector = utilitySelector.replace(needle, s);
|
|
@@ -174,6 +159,36 @@ function processApply(root, context) {
|
|
|
174
159
|
let siblings = [];
|
|
175
160
|
for (let [applyCandidate, important, rules] of candidates){
|
|
176
161
|
for (let [meta, node] of rules){
|
|
162
|
+
let parentClasses = extractClasses(parent);
|
|
163
|
+
let nodeClasses = extractClasses(node);
|
|
164
|
+
// Add base utility classes from the @apply node to the list of
|
|
165
|
+
// classes to check whether it intersects and therefore results in a
|
|
166
|
+
// circular dependency or not.
|
|
167
|
+
//
|
|
168
|
+
// E.g.:
|
|
169
|
+
// .foo {
|
|
170
|
+
// @apply hover:a; // This applies "a" but with a modifier
|
|
171
|
+
// }
|
|
172
|
+
//
|
|
173
|
+
// We only have to do that with base classes of the `node`, not of the `parent`
|
|
174
|
+
// E.g.:
|
|
175
|
+
// .hover\:foo {
|
|
176
|
+
// @apply bar;
|
|
177
|
+
// }
|
|
178
|
+
// .bar {
|
|
179
|
+
// @apply foo;
|
|
180
|
+
// }
|
|
181
|
+
//
|
|
182
|
+
// This should not result in a circular dependency because we are
|
|
183
|
+
// just applying `.foo` and the rule above is `.hover\:foo` which is
|
|
184
|
+
// unrelated. However, if we were to apply `hover:foo` then we _did_
|
|
185
|
+
// have to include this one.
|
|
186
|
+
nodeClasses = nodeClasses.concat(extractBaseCandidates(nodeClasses, context.tailwindConfig.separator));
|
|
187
|
+
let intersects = parentClasses.some((selector)=>nodeClasses.includes(selector)
|
|
188
|
+
);
|
|
189
|
+
if (intersects) {
|
|
190
|
+
throw node.error(`You cannot \`@apply\` the \`${applyCandidate}\` utility here because it creates a circular dependency.`);
|
|
191
|
+
}
|
|
177
192
|
let root = _postcss.default.root({
|
|
178
193
|
nodes: [
|
|
179
194
|
node.clone()
|
|
@@ -182,6 +197,42 @@ function processApply(root, context) {
|
|
|
182
197
|
let canRewriteSelector = node.type !== 'atrule' || node.type === 'atrule' && node.name !== 'keyframes';
|
|
183
198
|
if (canRewriteSelector) {
|
|
184
199
|
root.walkRules((rule)=>{
|
|
200
|
+
// Let's imagine you have the following structure:
|
|
201
|
+
//
|
|
202
|
+
// .foo {
|
|
203
|
+
// @apply bar;
|
|
204
|
+
// }
|
|
205
|
+
//
|
|
206
|
+
// @supports (a: b) {
|
|
207
|
+
// .bar {
|
|
208
|
+
// color: blue
|
|
209
|
+
// }
|
|
210
|
+
//
|
|
211
|
+
// .something-unrelated {}
|
|
212
|
+
// }
|
|
213
|
+
//
|
|
214
|
+
// In this case we want to apply `.bar` but it happens to be in
|
|
215
|
+
// an atrule node. We clone that node instead of the nested one
|
|
216
|
+
// because we still want that @supports rule to be there once we
|
|
217
|
+
// applied everything.
|
|
218
|
+
//
|
|
219
|
+
// However it happens to be that the `.something-unrelated` is
|
|
220
|
+
// also in that same shared @supports atrule. This is not good,
|
|
221
|
+
// and this should not be there. The good part is that this is
|
|
222
|
+
// a clone already and it can be safely removed. The question is
|
|
223
|
+
// how do we know we can remove it. Basically what we can do is
|
|
224
|
+
// match it against the applyCandidate that you want to apply. If
|
|
225
|
+
// it doesn't match the we can safely delete it.
|
|
226
|
+
//
|
|
227
|
+
// If we didn't do this, then the `replaceSelector` function
|
|
228
|
+
// would have replaced this with something that didn't exist and
|
|
229
|
+
// therefore it removed the selector altogether. In this specific
|
|
230
|
+
// case it would result in `{}` instead of `.something-unrelated {}`
|
|
231
|
+
if (!extractClasses(rule).some((candidate)=>candidate === applyCandidate
|
|
232
|
+
)) {
|
|
233
|
+
rule.remove();
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
185
236
|
rule.selector = replaceSelector(parent.selector, rule.selector, applyCandidate);
|
|
186
237
|
rule.walkDecls((d)=>{
|
|
187
238
|
d.important = meta.important || important;
|
|
@@ -203,7 +254,6 @@ function processApply(root, context) {
|
|
|
203
254
|
let nodes = siblings.sort(([a], [z])=>(0, _bigSign).default(a.sort - z.sort)
|
|
204
255
|
).map((s)=>s[1]
|
|
205
256
|
);
|
|
206
|
-
// console.log(parent)
|
|
207
257
|
// `parent` refers to the node at `.abc` in: .abc { @apply mt-2 }
|
|
208
258
|
parent.after(nodes);
|
|
209
259
|
}
|
|
@@ -222,7 +272,6 @@ function processApply(root, context) {
|
|
|
222
272
|
}
|
|
223
273
|
function expandApplyAtRules(context) {
|
|
224
274
|
return (root)=>{
|
|
225
|
-
partitionApplyParents(root);
|
|
226
275
|
processApply(root, context);
|
|
227
276
|
};
|
|
228
277
|
}
|
|
@@ -7,7 +7,9 @@ var _quickLru = _interopRequireDefault(require("quick-lru"));
|
|
|
7
7
|
var sharedState = _interopRequireWildcard(require("./sharedState"));
|
|
8
8
|
var _generateRules = require("./generateRules");
|
|
9
9
|
var _bigSign = _interopRequireDefault(require("../util/bigSign"));
|
|
10
|
+
var _log = _interopRequireDefault(require("../util/log"));
|
|
10
11
|
var _cloneNodes = _interopRequireDefault(require("../util/cloneNodes"));
|
|
12
|
+
var _defaultExtractor = require("./defaultExtractor");
|
|
11
13
|
function _interopRequireDefault(obj) {
|
|
12
14
|
return obj && obj.__esModule ? obj : {
|
|
13
15
|
default: obj
|
|
@@ -17,13 +19,11 @@ function _interopRequireWildcard(obj) {
|
|
|
17
19
|
if (obj && obj.__esModule) {
|
|
18
20
|
return obj;
|
|
19
21
|
} else {
|
|
20
|
-
var newObj = {
|
|
21
|
-
};
|
|
22
|
+
var newObj = {};
|
|
22
23
|
if (obj != null) {
|
|
23
24
|
for(var key in obj){
|
|
24
25
|
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
25
|
-
var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {
|
|
26
|
-
};
|
|
26
|
+
var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {};
|
|
27
27
|
if (desc.get || desc.set) {
|
|
28
28
|
Object.defineProperty(newObj, key, desc);
|
|
29
29
|
} else {
|
|
@@ -37,27 +37,8 @@ function _interopRequireWildcard(obj) {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
let env = sharedState.env;
|
|
40
|
-
const PATTERNS = [
|
|
41
|
-
/([^<>"'`\s]*\[\w*'[^"`\s]*'?\])/.source,
|
|
42
|
-
/([^<>"'`\s]*\[\w*"[^"`\s]*"?\])/.source,
|
|
43
|
-
/([^<>"'`\s]*\[\w*\('[^"'`\s]*'\)\])/.source,
|
|
44
|
-
/([^<>"'`\s]*\[\w*\("[^"'`\s]*"\)\])/.source,
|
|
45
|
-
/([^<>"'`\s]*\['[^"'`\s]*'\])/.source,
|
|
46
|
-
/([^<>"'`\s]*\["[^"'`\s]*"\])/.source,
|
|
47
|
-
/([^<>"'`\s]*\[[^"'`\s]+\][^<>"'`\s]*)/.source,
|
|
48
|
-
/([^<>"'`\s]*[^"'`\s:])/.source
|
|
49
|
-
].join('|');
|
|
50
|
-
const BROAD_MATCH_GLOBAL_REGEXP = new RegExp(PATTERNS, 'g');
|
|
51
|
-
const INNER_MATCH_GLOBAL_REGEXP = /[^<>"'`\s.(){}[\]#=%]*[^<>"'`\s.(){}[\]#=%:]/g;
|
|
52
40
|
const builtInExtractors = {
|
|
53
|
-
DEFAULT:
|
|
54
|
-
let broadMatches = content.match(BROAD_MATCH_GLOBAL_REGEXP) || [];
|
|
55
|
-
let innerMatches = content.match(INNER_MATCH_GLOBAL_REGEXP) || [];
|
|
56
|
-
return [
|
|
57
|
-
...broadMatches,
|
|
58
|
-
...innerMatches
|
|
59
|
-
];
|
|
60
|
-
}
|
|
41
|
+
DEFAULT: _defaultExtractor.defaultExtractor
|
|
61
42
|
};
|
|
62
43
|
const builtInTransformers = {
|
|
63
44
|
DEFAULT: (content)=>content
|
|
@@ -108,6 +89,7 @@ function buildStylesheet(rules, context) {
|
|
|
108
89
|
);
|
|
109
90
|
let returnValue = {
|
|
110
91
|
base: new Set(),
|
|
92
|
+
defaults: new Set(),
|
|
111
93
|
components: new Set(),
|
|
112
94
|
utilities: new Set(),
|
|
113
95
|
variants: new Set(),
|
|
@@ -130,6 +112,10 @@ function buildStylesheet(rules, context) {
|
|
|
130
112
|
returnValue.base.add(rule);
|
|
131
113
|
continue;
|
|
132
114
|
}
|
|
115
|
+
if (sort & context.layerOrder.defaults) {
|
|
116
|
+
returnValue.defaults.add(rule);
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
133
119
|
if (sort & context.layerOrder.components) {
|
|
134
120
|
returnValue.components.add(rule);
|
|
135
121
|
continue;
|
|
@@ -153,13 +139,15 @@ function expandTailwindAtRules(context) {
|
|
|
153
139
|
utilities: null,
|
|
154
140
|
variants: null
|
|
155
141
|
};
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
if (
|
|
162
|
-
layerNodes
|
|
142
|
+
root.walkAtRules((rule)=>{
|
|
143
|
+
// Make sure this file contains Tailwind directives. If not, we can save
|
|
144
|
+
// a lot of work and bail early. Also we don't have to register our touch
|
|
145
|
+
// file as a dependency since the output of this CSS does not depend on
|
|
146
|
+
// the source of any templates. Think Vue <style> blocks for example.
|
|
147
|
+
if (rule.name === 'tailwind') {
|
|
148
|
+
if (Object.keys(layerNodes).includes(rule.params)) {
|
|
149
|
+
layerNodes[rule.params] = rule;
|
|
150
|
+
}
|
|
163
151
|
}
|
|
164
152
|
});
|
|
165
153
|
if (Object.values(layerNodes).every((n)=>n === null
|
|
@@ -178,6 +166,7 @@ function expandTailwindAtRules(context) {
|
|
|
178
166
|
let extractor = getExtractor(context.tailwindConfig, extension);
|
|
179
167
|
getClassCandidates(transformer(content), extractor, candidates, seen);
|
|
180
168
|
}
|
|
169
|
+
env.DEBUG && console.timeEnd('Reading changed files');
|
|
181
170
|
// ---
|
|
182
171
|
// Generate the actual CSS
|
|
183
172
|
let classCacheCount = context.classCache.size;
|
|
@@ -195,13 +184,16 @@ function expandTailwindAtRules(context) {
|
|
|
195
184
|
], context);
|
|
196
185
|
}
|
|
197
186
|
env.DEBUG && console.timeEnd('Build stylesheet');
|
|
198
|
-
let { base: baseNodes , components: componentNodes , utilities: utilityNodes , variants: screenNodes , } = context.stylesheetCache;
|
|
187
|
+
let { defaults: defaultNodes , base: baseNodes , components: componentNodes , utilities: utilityNodes , variants: screenNodes , } = context.stylesheetCache;
|
|
199
188
|
// ---
|
|
200
189
|
// Replace any Tailwind directives with generated CSS
|
|
201
190
|
if (layerNodes.base) {
|
|
202
191
|
layerNodes.base.before((0, _cloneNodes).default([
|
|
203
|
-
...baseNodes
|
|
192
|
+
...baseNodes,
|
|
193
|
+
...defaultNodes
|
|
204
194
|
], layerNodes.base.source));
|
|
195
|
+
}
|
|
196
|
+
if (layerNodes.base) {
|
|
205
197
|
layerNodes.base.remove();
|
|
206
198
|
}
|
|
207
199
|
if (layerNodes.components) {
|
|
@@ -226,6 +218,13 @@ function expandTailwindAtRules(context) {
|
|
|
226
218
|
...screenNodes
|
|
227
219
|
], root.source));
|
|
228
220
|
}
|
|
221
|
+
// If we've got a utility layer and no utilities are generated there's likely something wrong
|
|
222
|
+
// TODO: Detect utility variants only
|
|
223
|
+
if (layerNodes.utilities && utilityNodes.size === 0 && screenNodes.size === 0) {
|
|
224
|
+
_log.default.warn('content-problems', [
|
|
225
|
+
'No utilities were generated there is likely a problem with the `content` key in the tailwind config. For more information see the documentation: https://tailwindcss.com/docs/content-configuration',
|
|
226
|
+
]);
|
|
227
|
+
}
|
|
229
228
|
// ---
|
|
230
229
|
if (env.DEBUG) {
|
|
231
230
|
console.log('Potential classes: ', candidates.size);
|