tailwindcss 3.0.21 → 3.0.24
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 +45 -2
- package/lib/cli-peer-dependencies.js +3 -3
- package/lib/cli.js +183 -161
- package/lib/constants.js +8 -8
- package/lib/corePlugins.js +1597 -1518
- package/lib/featureFlags.js +9 -9
- package/lib/index.js +19 -6
- package/lib/lib/cacheInvalidation.js +69 -0
- package/lib/lib/collapseAdjacentRules.js +26 -13
- package/lib/lib/collapseDuplicateDeclarations.js +1 -1
- package/lib/lib/defaultExtractor.js +8 -6
- package/lib/lib/detectNesting.js +9 -9
- package/lib/lib/evaluateTailwindFunctions.js +16 -16
- package/lib/lib/expandApplyAtRules.js +180 -27
- package/lib/lib/expandTailwindAtRules.js +132 -122
- package/lib/lib/generateRules.js +117 -72
- package/lib/lib/getModuleDependencies.js +14 -14
- package/lib/lib/normalizeTailwindDirectives.js +35 -35
- package/lib/lib/partitionApplyAtRules.js +7 -7
- package/lib/lib/resolveDefaultsAtRules.js +81 -77
- package/lib/lib/setupContextUtils.js +83 -98
- package/lib/lib/setupTrackingContext.js +57 -57
- package/lib/lib/sharedState.js +11 -7
- package/lib/lib/substituteScreenAtRules.js +2 -2
- package/lib/postcss-plugins/nesting/README.md +2 -2
- package/lib/postcss-plugins/nesting/index.js +1 -1
- package/lib/postcss-plugins/nesting/plugin.js +41 -9
- package/lib/processTailwindFeatures.js +7 -7
- package/lib/public/colors.js +241 -241
- package/lib/public/resolve-config.js +5 -5
- package/lib/util/buildMediaQuery.js +2 -2
- package/lib/util/cloneDeep.js +1 -1
- package/lib/util/cloneNodes.js +12 -1
- package/lib/util/color.js +21 -20
- package/lib/util/createUtilityPlugin.js +6 -6
- package/lib/util/dataTypes.js +77 -75
- package/lib/util/escapeClassName.js +5 -5
- package/lib/util/escapeCommas.js +1 -1
- package/lib/util/flattenColorPalette.js +2 -2
- package/lib/util/formatVariantSelector.js +19 -19
- package/lib/util/getAllConfigs.js +5 -5
- package/lib/util/hashConfig.js +5 -5
- package/lib/util/isKeyframeRule.js +1 -1
- package/lib/util/isPlainObject.js +1 -1
- package/lib/util/isValidArbitraryValue.js +27 -27
- package/lib/util/log.js +8 -8
- package/lib/util/nameClass.js +7 -7
- package/lib/util/negateValue.js +4 -4
- package/lib/util/normalizeConfig.js +39 -39
- package/lib/util/normalizeScreens.js +4 -4
- package/lib/util/parseAnimationValue.js +56 -56
- package/lib/util/parseBoxShadowValue.js +60 -20
- package/lib/util/parseDependency.js +32 -32
- package/lib/util/parseObjectStyles.js +6 -6
- package/lib/util/pluginUtils.js +9 -9
- package/lib/util/prefixSelector.js +1 -1
- package/lib/util/resolveConfig.js +28 -28
- package/lib/util/resolveConfigPath.js +16 -16
- package/lib/util/responsive.js +6 -6
- package/lib/util/toColorValue.js +1 -1
- package/lib/util/toPath.js +2 -2
- package/lib/util/transformThemeValue.js +27 -27
- package/lib/util/withAlphaVariable.js +19 -19
- package/package.json +26 -25
- package/peers/index.js +4803 -4857
- package/scripts/generate-types.js +52 -0
- package/src/cli.js +41 -11
- package/src/corePlugins.js +104 -9
- package/src/featureFlags.js +2 -2
- package/src/index.js +17 -1
- package/src/lib/cacheInvalidation.js +52 -0
- package/src/lib/collapseAdjacentRules.js +16 -1
- package/src/lib/defaultExtractor.js +6 -4
- package/src/lib/expandApplyAtRules.js +179 -6
- package/src/lib/expandTailwindAtRules.js +26 -6
- package/src/lib/generateRules.js +73 -46
- package/src/lib/resolveDefaultsAtRules.js +6 -2
- package/src/lib/setupContextUtils.js +39 -48
- package/src/lib/setupTrackingContext.js +3 -3
- package/src/lib/sharedState.js +2 -0
- package/src/postcss-plugins/nesting/README.md +2 -2
- package/src/postcss-plugins/nesting/plugin.js +36 -0
- package/src/util/cloneNodes.js +14 -1
- package/src/util/color.js +7 -5
- package/src/util/dataTypes.js +3 -1
- package/src/util/log.js +7 -7
- package/src/util/parseBoxShadowValue.js +50 -2
- package/src/util/resolveConfig.js +32 -0
- package/stubs/defaultConfig.stub.js +5 -0
|
@@ -8,12 +8,20 @@ var _postcssSelectorParser = _interopRequireDefault(require("postcss-selector-pa
|
|
|
8
8
|
var _generateRules = require("./generateRules");
|
|
9
9
|
var _bigSign = _interopRequireDefault(require("../util/bigSign"));
|
|
10
10
|
var _escapeClassName = _interopRequireDefault(require("../util/escapeClassName"));
|
|
11
|
+
function expandApplyAtRules(context) {
|
|
12
|
+
return (root)=>{
|
|
13
|
+
// Build a cache of the user's CSS so we can use it to resolve classes used by @apply
|
|
14
|
+
let localCache = lazyCache(()=>buildLocalApplyCache(root, context)
|
|
15
|
+
);
|
|
16
|
+
processApply(root, context, localCache);
|
|
17
|
+
};
|
|
18
|
+
}
|
|
11
19
|
function _interopRequireDefault(obj) {
|
|
12
20
|
return obj && obj.__esModule ? obj : {
|
|
13
21
|
default: obj
|
|
14
22
|
};
|
|
15
23
|
}
|
|
16
|
-
function extractClasses(node) {
|
|
24
|
+
/** @typedef {Map<string, [any, import('postcss').Rule[]]>} ApplyCache */ function extractClasses(node) {
|
|
17
25
|
let classes = new Set();
|
|
18
26
|
let container = _postcss.default.root({
|
|
19
27
|
nodes: [
|
|
@@ -38,9 +46,116 @@ function extractBaseCandidates(candidates, separator) {
|
|
|
38
46
|
}
|
|
39
47
|
function prefix(context, selector) {
|
|
40
48
|
let prefix1 = context.tailwindConfig.prefix;
|
|
41
|
-
return typeof prefix1 ===
|
|
49
|
+
return typeof prefix1 === "function" ? prefix1(selector) : prefix1 + selector;
|
|
50
|
+
}
|
|
51
|
+
function* pathToRoot(node) {
|
|
52
|
+
yield node;
|
|
53
|
+
while(node.parent){
|
|
54
|
+
yield node.parent;
|
|
55
|
+
node = node.parent;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Only clone the node itself and not its children
|
|
60
|
+
*
|
|
61
|
+
* @param {*} node
|
|
62
|
+
* @param {*} overrides
|
|
63
|
+
* @returns
|
|
64
|
+
*/ function shallowClone(node, overrides = {}) {
|
|
65
|
+
let children = node.nodes;
|
|
66
|
+
node.nodes = [];
|
|
67
|
+
let tmp = node.clone(overrides);
|
|
68
|
+
node.nodes = children;
|
|
69
|
+
return tmp;
|
|
42
70
|
}
|
|
43
|
-
|
|
71
|
+
/**
|
|
72
|
+
* Clone just the nodes all the way to the top that are required to represent
|
|
73
|
+
* this singular rule in the tree.
|
|
74
|
+
*
|
|
75
|
+
* For example, if we have CSS like this:
|
|
76
|
+
* ```css
|
|
77
|
+
* @media (min-width: 768px) {
|
|
78
|
+
* @supports (display: grid) {
|
|
79
|
+
* .foo {
|
|
80
|
+
* display: grid;
|
|
81
|
+
* grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
82
|
+
* }
|
|
83
|
+
* }
|
|
84
|
+
*
|
|
85
|
+
* @supports (backdrop-filter: blur(1px)) {
|
|
86
|
+
* .bar {
|
|
87
|
+
* backdrop-filter: blur(1px);
|
|
88
|
+
* }
|
|
89
|
+
* }
|
|
90
|
+
*
|
|
91
|
+
* .baz {
|
|
92
|
+
* color: orange;
|
|
93
|
+
* }
|
|
94
|
+
* }
|
|
95
|
+
* ```
|
|
96
|
+
*
|
|
97
|
+
* And we're cloning `.bar` it'll return a cloned version of what's required for just that single node:
|
|
98
|
+
*
|
|
99
|
+
* ```css
|
|
100
|
+
* @media (min-width: 768px) {
|
|
101
|
+
* @supports (backdrop-filter: blur(1px)) {
|
|
102
|
+
* .bar {
|
|
103
|
+
* backdrop-filter: blur(1px);
|
|
104
|
+
* }
|
|
105
|
+
* }
|
|
106
|
+
* }
|
|
107
|
+
* ```
|
|
108
|
+
*
|
|
109
|
+
* @param {import('postcss').Node} node
|
|
110
|
+
*/ function nestedClone(node) {
|
|
111
|
+
for (let parent of pathToRoot(node)){
|
|
112
|
+
if (node === parent) {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
if (parent.type === "root") {
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
node = shallowClone(parent, {
|
|
119
|
+
nodes: [
|
|
120
|
+
node
|
|
121
|
+
]
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
return node;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* @param {import('postcss').Root} root
|
|
128
|
+
*/ function buildLocalApplyCache(root, context) {
|
|
129
|
+
/** @type {ApplyCache} */ let cache = new Map();
|
|
130
|
+
let highestOffset = context.layerOrder.user >> 4n;
|
|
131
|
+
root.walkRules((rule, idx)=>{
|
|
132
|
+
// Ignore rules generated by Tailwind
|
|
133
|
+
for (let node of pathToRoot(rule)){
|
|
134
|
+
var ref;
|
|
135
|
+
if (((ref = node.raws.tailwind) === null || ref === void 0 ? void 0 : ref.layer) !== undefined) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// Clone what's required to represent this singular rule in the tree
|
|
140
|
+
let container = nestedClone(rule);
|
|
141
|
+
for (let className of extractClasses(rule)){
|
|
142
|
+
let list = cache.get(className) || [];
|
|
143
|
+
cache.set(className, list);
|
|
144
|
+
list.push([
|
|
145
|
+
{
|
|
146
|
+
layer: "user",
|
|
147
|
+
sort: BigInt(idx) + highestOffset,
|
|
148
|
+
important: false
|
|
149
|
+
},
|
|
150
|
+
container,
|
|
151
|
+
]);
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
return cache;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* @returns {ApplyCache}
|
|
158
|
+
*/ function buildApplyCache(applyCandidates, context) {
|
|
44
159
|
for (let candidate of applyCandidates){
|
|
45
160
|
if (context.notClassCache.has(candidate) || context.applyClassCache.has(candidate)) {
|
|
46
161
|
continue;
|
|
@@ -62,9 +177,42 @@ function buildApplyCache(applyCandidates, context) {
|
|
|
62
177
|
}
|
|
63
178
|
return context.applyClassCache;
|
|
64
179
|
}
|
|
180
|
+
/**
|
|
181
|
+
* Build a cache only when it's first used
|
|
182
|
+
*
|
|
183
|
+
* @param {() => ApplyCache} buildCacheFn
|
|
184
|
+
* @returns {ApplyCache}
|
|
185
|
+
*/ function lazyCache(buildCacheFn) {
|
|
186
|
+
let cache = null;
|
|
187
|
+
return {
|
|
188
|
+
get: (name)=>{
|
|
189
|
+
cache = cache || buildCacheFn();
|
|
190
|
+
return cache.get(name);
|
|
191
|
+
},
|
|
192
|
+
has: (name)=>{
|
|
193
|
+
cache = cache || buildCacheFn();
|
|
194
|
+
return cache.has(name);
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Take a series of multiple caches and merge
|
|
200
|
+
* them so they act like one large cache
|
|
201
|
+
*
|
|
202
|
+
* @param {ApplyCache[]} caches
|
|
203
|
+
* @returns {ApplyCache}
|
|
204
|
+
*/ function combineCaches(caches) {
|
|
205
|
+
return {
|
|
206
|
+
get: (name)=>caches.flatMap((cache)=>cache.get(name) || []
|
|
207
|
+
)
|
|
208
|
+
,
|
|
209
|
+
has: (name)=>caches.some((cache)=>cache.has(name)
|
|
210
|
+
)
|
|
211
|
+
};
|
|
212
|
+
}
|
|
65
213
|
function extractApplyCandidates(params) {
|
|
66
214
|
let candidates = params.split(/[\s\t\n]+/g);
|
|
67
|
-
if (candidates[candidates.length - 1] ===
|
|
215
|
+
if (candidates[candidates.length - 1] === "!important") {
|
|
68
216
|
return [
|
|
69
217
|
candidates.slice(0, -1),
|
|
70
218
|
true
|
|
@@ -75,11 +223,11 @@ function extractApplyCandidates(params) {
|
|
|
75
223
|
false
|
|
76
224
|
];
|
|
77
225
|
}
|
|
78
|
-
function processApply(root, context) {
|
|
226
|
+
function processApply(root, context, localCache) {
|
|
79
227
|
let applyCandidates = new Set();
|
|
80
228
|
// Collect all @apply rules and candidates
|
|
81
229
|
let applies = [];
|
|
82
|
-
root.walkAtRules(
|
|
230
|
+
root.walkAtRules("apply", (rule)=>{
|
|
83
231
|
let [candidates] = extractApplyCandidates(rule.params);
|
|
84
232
|
for (let util of candidates){
|
|
85
233
|
applyCandidates.add(util);
|
|
@@ -89,7 +237,10 @@ function processApply(root, context) {
|
|
|
89
237
|
// Start the @apply process if we have rules with @apply in them
|
|
90
238
|
if (applies.length > 0) {
|
|
91
239
|
// Fill up some caches!
|
|
92
|
-
let applyClassCache =
|
|
240
|
+
let applyClassCache = combineCaches([
|
|
241
|
+
localCache,
|
|
242
|
+
buildApplyCache(applyCandidates, context)
|
|
243
|
+
]);
|
|
93
244
|
/**
|
|
94
245
|
* When we have an apply like this:
|
|
95
246
|
*
|
|
@@ -122,27 +273,30 @@ function processApply(root, context) {
|
|
|
122
273
|
}
|
|
123
274
|
replaced.push(replacedSelector);
|
|
124
275
|
}
|
|
125
|
-
return replaced.join(
|
|
126
|
-
}).join(
|
|
276
|
+
return replaced.join(", ");
|
|
277
|
+
}).join(", ");
|
|
127
278
|
}
|
|
128
279
|
let perParentApplies = new Map();
|
|
129
280
|
// Collect all apply candidates and their rules
|
|
130
281
|
for (let apply of applies){
|
|
131
282
|
let candidates = perParentApplies.get(apply.parent) || [];
|
|
132
|
-
perParentApplies.set(apply.parent,
|
|
283
|
+
perParentApplies.set(apply.parent, [
|
|
284
|
+
candidates,
|
|
285
|
+
apply.source
|
|
286
|
+
]);
|
|
133
287
|
let [applyCandidates, important] = extractApplyCandidates(apply.params);
|
|
134
|
-
if (apply.parent.type ===
|
|
135
|
-
if (apply.parent.name ===
|
|
288
|
+
if (apply.parent.type === "atrule") {
|
|
289
|
+
if (apply.parent.name === "screen") {
|
|
136
290
|
const screenType = apply.parent.params;
|
|
137
291
|
throw apply.error(`@apply is not supported within nested at-rules like @screen. We suggest you write this as @apply ${applyCandidates.map((c)=>`${screenType}:${c}`
|
|
138
|
-
).join(
|
|
292
|
+
).join(" ")} instead.`);
|
|
139
293
|
}
|
|
140
294
|
throw apply.error(`@apply is not supported within nested at-rules like @${apply.parent.name}. You can fix this by un-nesting @${apply.parent.name}.`);
|
|
141
295
|
}
|
|
142
296
|
for (let applyCandidate of applyCandidates){
|
|
143
297
|
if ([
|
|
144
|
-
prefix(context,
|
|
145
|
-
prefix(context,
|
|
298
|
+
prefix(context, "group"),
|
|
299
|
+
prefix(context, "peer")
|
|
146
300
|
].includes(applyCandidate)) {
|
|
147
301
|
// TODO: Link to specific documentation page with error code.
|
|
148
302
|
throw apply.error(`@apply should not be used with the '${applyCandidate}' utility`);
|
|
@@ -158,12 +312,12 @@ function processApply(root, context) {
|
|
|
158
312
|
]);
|
|
159
313
|
}
|
|
160
314
|
}
|
|
161
|
-
for (const [parent, candidates] of perParentApplies){
|
|
315
|
+
for (const [parent, [candidates, atApplySource]] of perParentApplies){
|
|
162
316
|
let siblings = [];
|
|
163
317
|
for (let [applyCandidate, important, rules] of candidates){
|
|
164
|
-
for (let [meta,
|
|
318
|
+
for (let [meta, node1] of rules){
|
|
165
319
|
let parentClasses = extractClasses(parent);
|
|
166
|
-
let nodeClasses = extractClasses(
|
|
320
|
+
let nodeClasses = extractClasses(node1);
|
|
167
321
|
// Add base utility classes from the @apply node to the list of
|
|
168
322
|
// classes to check whether it intersects and therefore results in a
|
|
169
323
|
// circular dependency or not.
|
|
@@ -190,14 +344,18 @@ function processApply(root, context) {
|
|
|
190
344
|
let intersects = parentClasses.some((selector)=>nodeClasses.includes(selector)
|
|
191
345
|
);
|
|
192
346
|
if (intersects) {
|
|
193
|
-
throw
|
|
347
|
+
throw node1.error(`You cannot \`@apply\` the \`${applyCandidate}\` utility here because it creates a circular dependency.`);
|
|
194
348
|
}
|
|
195
349
|
let root = _postcss.default.root({
|
|
196
350
|
nodes: [
|
|
197
|
-
|
|
351
|
+
node1.clone()
|
|
198
352
|
]
|
|
199
353
|
});
|
|
200
|
-
|
|
354
|
+
// Make sure every node in the entire tree points back at the @apply rule that generated it
|
|
355
|
+
root.walk((node)=>{
|
|
356
|
+
node.source = atApplySource;
|
|
357
|
+
});
|
|
358
|
+
let canRewriteSelector = node1.type !== "atrule" || node1.type === "atrule" && node1.name !== "keyframes";
|
|
201
359
|
if (canRewriteSelector) {
|
|
202
360
|
root.walkRules((rule)=>{
|
|
203
361
|
// Let's imagine you have the following structure:
|
|
@@ -270,11 +428,6 @@ function processApply(root, context) {
|
|
|
270
428
|
}
|
|
271
429
|
}
|
|
272
430
|
// Do it again, in case we have other `@apply` rules
|
|
273
|
-
processApply(root, context);
|
|
431
|
+
processApply(root, context, localCache);
|
|
274
432
|
}
|
|
275
433
|
}
|
|
276
|
-
function expandApplyAtRules(context) {
|
|
277
|
-
return (root)=>{
|
|
278
|
-
processApply(root, context);
|
|
279
|
-
};
|
|
280
|
-
}
|
|
@@ -10,6 +10,135 @@ var _bigSign = _interopRequireDefault(require("../util/bigSign"));
|
|
|
10
10
|
var _log = _interopRequireDefault(require("../util/log"));
|
|
11
11
|
var _cloneNodes = _interopRequireDefault(require("../util/cloneNodes"));
|
|
12
12
|
var _defaultExtractor = require("./defaultExtractor");
|
|
13
|
+
function expandTailwindAtRules(context) {
|
|
14
|
+
return (root)=>{
|
|
15
|
+
let layerNodes = {
|
|
16
|
+
base: null,
|
|
17
|
+
components: null,
|
|
18
|
+
utilities: null,
|
|
19
|
+
variants: null
|
|
20
|
+
};
|
|
21
|
+
root.walkAtRules((rule)=>{
|
|
22
|
+
// Make sure this file contains Tailwind directives. If not, we can save
|
|
23
|
+
// a lot of work and bail early. Also we don't have to register our touch
|
|
24
|
+
// file as a dependency since the output of this CSS does not depend on
|
|
25
|
+
// the source of any templates. Think Vue <style> blocks for example.
|
|
26
|
+
if (rule.name === "tailwind") {
|
|
27
|
+
if (Object.keys(layerNodes).includes(rule.params)) {
|
|
28
|
+
layerNodes[rule.params] = rule;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
if (Object.values(layerNodes).every((n)=>n === null
|
|
33
|
+
)) {
|
|
34
|
+
return root;
|
|
35
|
+
}
|
|
36
|
+
// ---
|
|
37
|
+
// Find potential rules in changed files
|
|
38
|
+
let candidates = new Set([
|
|
39
|
+
sharedState.NOT_ON_DEMAND
|
|
40
|
+
]);
|
|
41
|
+
let seen = new Set();
|
|
42
|
+
env.DEBUG && console.time("Reading changed files");
|
|
43
|
+
for (let { content , extension } of context.changedContent){
|
|
44
|
+
let transformer = getTransformer(context.tailwindConfig, extension);
|
|
45
|
+
let extractor = getExtractor(context.tailwindConfig, extension);
|
|
46
|
+
getClassCandidates(transformer(content), extractor, candidates, seen);
|
|
47
|
+
}
|
|
48
|
+
env.DEBUG && console.timeEnd("Reading changed files");
|
|
49
|
+
// ---
|
|
50
|
+
// Generate the actual CSS
|
|
51
|
+
let classCacheCount = context.classCache.size;
|
|
52
|
+
env.DEBUG && console.time("Generate rules");
|
|
53
|
+
let rules = (0, _generateRules).generateRules(candidates, context);
|
|
54
|
+
env.DEBUG && console.timeEnd("Generate rules");
|
|
55
|
+
// We only ever add to the classCache, so if it didn't grow, there is nothing new.
|
|
56
|
+
env.DEBUG && console.time("Build stylesheet");
|
|
57
|
+
if (context.stylesheetCache === null || context.classCache.size !== classCacheCount) {
|
|
58
|
+
for (let rule of rules){
|
|
59
|
+
context.ruleCache.add(rule);
|
|
60
|
+
}
|
|
61
|
+
context.stylesheetCache = buildStylesheet([
|
|
62
|
+
...context.ruleCache
|
|
63
|
+
], context);
|
|
64
|
+
}
|
|
65
|
+
env.DEBUG && console.timeEnd("Build stylesheet");
|
|
66
|
+
let { defaults: defaultNodes , base: baseNodes , components: componentNodes , utilities: utilityNodes , variants: screenNodes , } = context.stylesheetCache;
|
|
67
|
+
// ---
|
|
68
|
+
// Replace any Tailwind directives with generated CSS
|
|
69
|
+
if (layerNodes.base) {
|
|
70
|
+
layerNodes.base.before((0, _cloneNodes).default([
|
|
71
|
+
...baseNodes,
|
|
72
|
+
...defaultNodes
|
|
73
|
+
], layerNodes.base.source, {
|
|
74
|
+
layer: "base"
|
|
75
|
+
}));
|
|
76
|
+
layerNodes.base.remove();
|
|
77
|
+
}
|
|
78
|
+
if (layerNodes.components) {
|
|
79
|
+
layerNodes.components.before((0, _cloneNodes).default([
|
|
80
|
+
...componentNodes
|
|
81
|
+
], layerNodes.components.source, {
|
|
82
|
+
layer: "components"
|
|
83
|
+
}));
|
|
84
|
+
layerNodes.components.remove();
|
|
85
|
+
}
|
|
86
|
+
if (layerNodes.utilities) {
|
|
87
|
+
layerNodes.utilities.before((0, _cloneNodes).default([
|
|
88
|
+
...utilityNodes
|
|
89
|
+
], layerNodes.utilities.source, {
|
|
90
|
+
layer: "utilities"
|
|
91
|
+
}));
|
|
92
|
+
layerNodes.utilities.remove();
|
|
93
|
+
}
|
|
94
|
+
// We do post-filtering to not alter the emitted order of the variants
|
|
95
|
+
const variantNodes = Array.from(screenNodes).filter((node)=>{
|
|
96
|
+
var ref;
|
|
97
|
+
const parentLayer = (ref = node.raws.tailwind) === null || ref === void 0 ? void 0 : ref.parentLayer;
|
|
98
|
+
if (parentLayer === "components") {
|
|
99
|
+
return layerNodes.components !== null;
|
|
100
|
+
}
|
|
101
|
+
if (parentLayer === "utilities") {
|
|
102
|
+
return layerNodes.utilities !== null;
|
|
103
|
+
}
|
|
104
|
+
return true;
|
|
105
|
+
});
|
|
106
|
+
if (layerNodes.variants) {
|
|
107
|
+
layerNodes.variants.before((0, _cloneNodes).default(variantNodes, layerNodes.variants.source, {
|
|
108
|
+
layer: "variants"
|
|
109
|
+
}));
|
|
110
|
+
layerNodes.variants.remove();
|
|
111
|
+
} else if (variantNodes.length > 0) {
|
|
112
|
+
root.append((0, _cloneNodes).default(variantNodes, root.source, {
|
|
113
|
+
layer: "variants"
|
|
114
|
+
}));
|
|
115
|
+
}
|
|
116
|
+
// If we've got a utility layer and no utilities are generated there's likely something wrong
|
|
117
|
+
const hasUtilityVariants = variantNodes.some((node)=>{
|
|
118
|
+
var ref;
|
|
119
|
+
return ((ref = node.raws.tailwind) === null || ref === void 0 ? void 0 : ref.parentLayer) === "utilities";
|
|
120
|
+
});
|
|
121
|
+
if (layerNodes.utilities && utilityNodes.size === 0 && !hasUtilityVariants) {
|
|
122
|
+
_log.default.warn("content-problems", [
|
|
123
|
+
"No utility classes were detected in your source files. If this is unexpected, double-check the `content` option in your Tailwind CSS configuration.",
|
|
124
|
+
"https://tailwindcss.com/docs/content-configuration",
|
|
125
|
+
]);
|
|
126
|
+
}
|
|
127
|
+
// ---
|
|
128
|
+
if (env.DEBUG) {
|
|
129
|
+
console.log("Potential classes: ", candidates.size);
|
|
130
|
+
console.log("Active contexts: ", sharedState.contextSourcesMap.size);
|
|
131
|
+
}
|
|
132
|
+
// Clear the cache for the changed files
|
|
133
|
+
context.changedContent = [];
|
|
134
|
+
// Cleanup any leftover @layer atrules
|
|
135
|
+
root.walkAtRules("layer", (rule)=>{
|
|
136
|
+
if (Object.keys(layerNodes).includes(rule.params)) {
|
|
137
|
+
rule.remove();
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
};
|
|
141
|
+
}
|
|
13
142
|
function _interopRequireDefault(obj) {
|
|
14
143
|
return obj && obj.__esModule ? obj : {
|
|
15
144
|
default: obj
|
|
@@ -43,7 +172,7 @@ const builtInExtractors = {
|
|
|
43
172
|
const builtInTransformers = {
|
|
44
173
|
DEFAULT: (content)=>content
|
|
45
174
|
,
|
|
46
|
-
svelte: (content)=>content.replace(/(?:^|\s)class:/g,
|
|
175
|
+
svelte: (content)=>content.replace(/(?:^|\s)class:/g, " ")
|
|
47
176
|
};
|
|
48
177
|
function getExtractor(tailwindConfig, fileExtension) {
|
|
49
178
|
let extractors = tailwindConfig.content.extract;
|
|
@@ -63,7 +192,7 @@ function getClassCandidates(content, extractor, candidates, seen) {
|
|
|
63
192
|
maxSize: 25000
|
|
64
193
|
}));
|
|
65
194
|
}
|
|
66
|
-
for (let line of content.split(
|
|
195
|
+
for (let line of content.split("\n")){
|
|
67
196
|
line = line.trim();
|
|
68
197
|
if (seen.has(line)) {
|
|
69
198
|
continue;
|
|
@@ -74,7 +203,7 @@ function getClassCandidates(content, extractor, candidates, seen) {
|
|
|
74
203
|
candidates.add(match);
|
|
75
204
|
}
|
|
76
205
|
} else {
|
|
77
|
-
let extractorMatches = extractor(line).filter((s)=>s !==
|
|
206
|
+
let extractorMatches = extractor(line).filter((s)=>s !== "!*"
|
|
78
207
|
);
|
|
79
208
|
let lineMatchesSet = new Set(extractorMatches);
|
|
80
209
|
for (let match of lineMatchesSet){
|
|
@@ -131,122 +260,3 @@ function buildStylesheet(rules, context) {
|
|
|
131
260
|
}
|
|
132
261
|
return returnValue;
|
|
133
262
|
}
|
|
134
|
-
function expandTailwindAtRules(context) {
|
|
135
|
-
return (root)=>{
|
|
136
|
-
let layerNodes = {
|
|
137
|
-
base: null,
|
|
138
|
-
components: null,
|
|
139
|
-
utilities: null,
|
|
140
|
-
variants: null
|
|
141
|
-
};
|
|
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
|
-
}
|
|
151
|
-
}
|
|
152
|
-
});
|
|
153
|
-
if (Object.values(layerNodes).every((n)=>n === null
|
|
154
|
-
)) {
|
|
155
|
-
return root;
|
|
156
|
-
}
|
|
157
|
-
// ---
|
|
158
|
-
// Find potential rules in changed files
|
|
159
|
-
let candidates = new Set([
|
|
160
|
-
'*'
|
|
161
|
-
]);
|
|
162
|
-
let seen = new Set();
|
|
163
|
-
env.DEBUG && console.time('Reading changed files');
|
|
164
|
-
for (let { content , extension } of context.changedContent){
|
|
165
|
-
let transformer = getTransformer(context.tailwindConfig, extension);
|
|
166
|
-
let extractor = getExtractor(context.tailwindConfig, extension);
|
|
167
|
-
getClassCandidates(transformer(content), extractor, candidates, seen);
|
|
168
|
-
}
|
|
169
|
-
env.DEBUG && console.timeEnd('Reading changed files');
|
|
170
|
-
// ---
|
|
171
|
-
// Generate the actual CSS
|
|
172
|
-
let classCacheCount = context.classCache.size;
|
|
173
|
-
env.DEBUG && console.time('Generate rules');
|
|
174
|
-
let rules = (0, _generateRules).generateRules(candidates, context);
|
|
175
|
-
env.DEBUG && console.timeEnd('Generate rules');
|
|
176
|
-
// We only ever add to the classCache, so if it didn't grow, there is nothing new.
|
|
177
|
-
env.DEBUG && console.time('Build stylesheet');
|
|
178
|
-
if (context.stylesheetCache === null || context.classCache.size !== classCacheCount) {
|
|
179
|
-
for (let rule of rules){
|
|
180
|
-
context.ruleCache.add(rule);
|
|
181
|
-
}
|
|
182
|
-
context.stylesheetCache = buildStylesheet([
|
|
183
|
-
...context.ruleCache
|
|
184
|
-
], context);
|
|
185
|
-
}
|
|
186
|
-
env.DEBUG && console.timeEnd('Build stylesheet');
|
|
187
|
-
let { defaults: defaultNodes , base: baseNodes , components: componentNodes , utilities: utilityNodes , variants: screenNodes , } = context.stylesheetCache;
|
|
188
|
-
// ---
|
|
189
|
-
// Replace any Tailwind directives with generated CSS
|
|
190
|
-
if (layerNodes.base) {
|
|
191
|
-
layerNodes.base.before((0, _cloneNodes).default([
|
|
192
|
-
...baseNodes,
|
|
193
|
-
...defaultNodes
|
|
194
|
-
], layerNodes.base.source));
|
|
195
|
-
layerNodes.base.remove();
|
|
196
|
-
}
|
|
197
|
-
if (layerNodes.components) {
|
|
198
|
-
layerNodes.components.before((0, _cloneNodes).default([
|
|
199
|
-
...componentNodes
|
|
200
|
-
], layerNodes.components.source));
|
|
201
|
-
layerNodes.components.remove();
|
|
202
|
-
}
|
|
203
|
-
if (layerNodes.utilities) {
|
|
204
|
-
layerNodes.utilities.before((0, _cloneNodes).default([
|
|
205
|
-
...utilityNodes
|
|
206
|
-
], layerNodes.utilities.source));
|
|
207
|
-
layerNodes.utilities.remove();
|
|
208
|
-
}
|
|
209
|
-
// We do post-filtering to not alter the emitted order of the variants
|
|
210
|
-
const variantNodes = Array.from(screenNodes).filter((node)=>{
|
|
211
|
-
var ref;
|
|
212
|
-
const parentLayer = (ref = node.raws.tailwind) === null || ref === void 0 ? void 0 : ref.parentLayer;
|
|
213
|
-
if (parentLayer === 'components') {
|
|
214
|
-
return layerNodes.components !== null;
|
|
215
|
-
}
|
|
216
|
-
if (parentLayer === 'utilities') {
|
|
217
|
-
return layerNodes.utilities !== null;
|
|
218
|
-
}
|
|
219
|
-
return true;
|
|
220
|
-
});
|
|
221
|
-
if (layerNodes.variants) {
|
|
222
|
-
layerNodes.variants.before((0, _cloneNodes).default(variantNodes, layerNodes.variants.source));
|
|
223
|
-
layerNodes.variants.remove();
|
|
224
|
-
} else if (variantNodes.length > 0) {
|
|
225
|
-
root.append((0, _cloneNodes).default(variantNodes, root.source));
|
|
226
|
-
}
|
|
227
|
-
// If we've got a utility layer and no utilities are generated there's likely something wrong
|
|
228
|
-
const hasUtilityVariants = variantNodes.some((node)=>{
|
|
229
|
-
var ref;
|
|
230
|
-
return ((ref = node.raws.tailwind) === null || ref === void 0 ? void 0 : ref.parentLayer) === 'utilities';
|
|
231
|
-
});
|
|
232
|
-
if (layerNodes.utilities && utilityNodes.size === 0 && !hasUtilityVariants) {
|
|
233
|
-
_log.default.warn('content-problems', [
|
|
234
|
-
'No utility classes were detected in your source files. If this is unexpected, double-check the `content` option in your Tailwind CSS configuration.',
|
|
235
|
-
'https://tailwindcss.com/docs/content-configuration',
|
|
236
|
-
]);
|
|
237
|
-
}
|
|
238
|
-
// ---
|
|
239
|
-
if (env.DEBUG) {
|
|
240
|
-
console.log('Potential classes: ', candidates.size);
|
|
241
|
-
console.log('Active contexts: ', sharedState.contextSourcesMap.size);
|
|
242
|
-
}
|
|
243
|
-
// Clear the cache for the changed files
|
|
244
|
-
context.changedContent = [];
|
|
245
|
-
// Cleanup any leftover @layer atrules
|
|
246
|
-
root.walkAtRules('layer', (rule)=>{
|
|
247
|
-
if (Object.keys(layerNodes).includes(rule.params)) {
|
|
248
|
-
rule.remove();
|
|
249
|
-
}
|
|
250
|
-
});
|
|
251
|
-
};
|
|
252
|
-
}
|