tailwindcss 0.0.0-insiders.e63c111 → 0.0.0-insiders.e66110e
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 +42 -1
- package/lib/cli/build/plugin.js +14 -3
- package/lib/cli/build/watching.js +77 -12
- package/lib/css/preflight.css +2 -0
- package/lib/lib/content.js +8 -1
- package/lib/lib/defaultExtractor.js +1 -1
- package/lib/lib/expandApplyAtRules.js +34 -15
- package/lib/lib/expandTailwindAtRules.js +1 -1
- package/lib/lib/generateRules.js +2 -2
- package/lib/lib/setupContextUtils.js +21 -8
- package/lib/util/formatVariantSelector.js +3 -3
- package/lib/util/normalizeConfig.js +14 -0
- package/lib/util/pluginUtils.js +38 -27
- package/lib/util/resolveConfig.js +4 -9
- package/package.json +7 -7
- package/peers/index.js +634 -579
- package/src/cli/build/plugin.js +19 -2
- package/src/cli/build/watching.js +105 -12
- package/src/css/preflight.css +2 -0
- package/src/lib/content.js +8 -1
- package/src/lib/defaultExtractor.js +1 -1
- package/src/lib/expandApplyAtRules.js +35 -15
- package/src/lib/generateRules.js +10 -7
- package/src/lib/setupContextUtils.js +21 -9
- package/src/util/formatVariantSelector.js +2 -2
- package/src/util/normalizeConfig.js +18 -0
- package/src/util/pluginUtils.js +39 -19
- package/src/util/resolveConfig.js +3 -9
- package/stubs/defaultConfig.stub.js +0 -18
package/CHANGELOG.md
CHANGED
|
@@ -9,7 +9,45 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
9
9
|
|
|
10
10
|
### Fixed
|
|
11
11
|
|
|
12
|
+
- Cleanup unused `variantOrder` ([#9829](https://github.com/tailwindlabs/tailwindcss/pull/9829))
|
|
13
|
+
- Fix `foo-[abc]/[def]` not being handled correctly ([#9866](https://github.com/tailwindlabs/tailwindcss/pull/9866))
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- Add container queries plugin to standalone CLI ([#9865](https://github.com/tailwindlabs/tailwindcss/pull/9865))
|
|
18
|
+
|
|
19
|
+
## [3.2.4] - 2022-11-11
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
- Add `blocklist` option to prevent generating unwanted CSS ([#9812](https://github.com/tailwindlabs/tailwindcss/pull/9812))
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- Fix watching of files on Linux when renames are involved ([#9796](https://github.com/tailwindlabs/tailwindcss/pull/9796))
|
|
28
|
+
- Make sure errors are always displayed when watching for changes ([#9810](https://github.com/tailwindlabs/tailwindcss/pull/9810))
|
|
29
|
+
|
|
30
|
+
## [3.2.3] - 2022-11-09
|
|
31
|
+
|
|
32
|
+
### Fixed
|
|
33
|
+
|
|
34
|
+
- Fixed use of `raw` content in the CLI ([#9773](https://github.com/tailwindlabs/tailwindcss/pull/9773))
|
|
35
|
+
- Pick up changes from files that are both context and content deps ([#9787](https://github.com/tailwindlabs/tailwindcss/pull/9787))
|
|
36
|
+
- Sort pseudo-elements ONLY after classes when using variants and `@apply` ([#9765](https://github.com/tailwindlabs/tailwindcss/pull/9765))
|
|
37
|
+
- Support important utilities in the safelist (pattern must include a `!`) ([#9791](https://github.com/tailwindlabs/tailwindcss/pull/9791))
|
|
38
|
+
|
|
39
|
+
## [3.2.2] - 2022-11-04
|
|
40
|
+
|
|
41
|
+
### Fixed
|
|
42
|
+
|
|
12
43
|
- Escape special characters in resolved content base paths ([#9650](https://github.com/tailwindlabs/tailwindcss/pull/9650))
|
|
44
|
+
- Don't reuse container for array returning variant functions ([#9644](https://github.com/tailwindlabs/tailwindcss/pull/9644))
|
|
45
|
+
- Exclude non-relevant selectors when generating rules with the important modifier ([#9677](https://github.com/tailwindlabs/tailwindcss/issues/9677))
|
|
46
|
+
- Fix merging of arrays during config resolution ([#9706](https://github.com/tailwindlabs/tailwindcss/issues/9706))
|
|
47
|
+
- Ensure configured `font-feature-settings` are included in Preflight ([#9707](https://github.com/tailwindlabs/tailwindcss/pull/9707))
|
|
48
|
+
- Fix fractional values not being parsed properly inside arbitrary properties ([#9705](https://github.com/tailwindlabs/tailwindcss/pull/9705))
|
|
49
|
+
- Fix incorrect selectors when using `@apply` in selectors with combinators and pseudos ([#9722](https://github.com/tailwindlabs/tailwindcss/pull/9722))
|
|
50
|
+
- Fix cannot read properties of undefined (reading 'modifier') ([#9656](https://github.com/tailwindlabs/tailwindcss/pull/9656), [aa979d6](https://github.com/tailwindlabs/tailwindcss/commit/aa979d645f8bf4108c5fc938d7c0ba085b654c31))
|
|
13
51
|
|
|
14
52
|
## [3.2.1] - 2022-10-21
|
|
15
53
|
|
|
@@ -2090,7 +2128,10 @@ No release notes
|
|
|
2090
2128
|
|
|
2091
2129
|
- Everything!
|
|
2092
2130
|
|
|
2093
|
-
[unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.2.
|
|
2131
|
+
[unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.2.4...HEAD
|
|
2132
|
+
[3.2.4]: https://github.com/tailwindlabs/tailwindcss/compare/v3.2.3...v3.2.4
|
|
2133
|
+
[3.2.3]: https://github.com/tailwindlabs/tailwindcss/compare/v3.2.2...v3.2.3
|
|
2134
|
+
[3.2.2]: https://github.com/tailwindlabs/tailwindcss/compare/v3.2.1...v3.2.2
|
|
2094
2135
|
[3.2.1]: https://github.com/tailwindlabs/tailwindcss/compare/v3.2.0...v3.2.1
|
|
2095
2136
|
[3.2.0]: https://github.com/tailwindlabs/tailwindcss/compare/v3.1.8...v3.2.0
|
|
2096
2137
|
[3.1.8]: https://github.com/tailwindlabs/tailwindcss/compare/v3.1.7...v3.1.8
|
package/lib/cli/build/plugin.js
CHANGED
|
@@ -170,9 +170,9 @@ let state = {
|
|
|
170
170
|
let rawContent = this.config.content.files.filter((file)=>{
|
|
171
171
|
return file !== null && typeof file === "object";
|
|
172
172
|
});
|
|
173
|
-
for (let { raw:
|
|
174
|
-
|
|
175
|
-
content:
|
|
173
|
+
for (let { raw: htmlContent , extension ="html" } of rawContent){
|
|
174
|
+
content.push({
|
|
175
|
+
content: htmlContent,
|
|
176
176
|
extension
|
|
177
177
|
});
|
|
178
178
|
}
|
|
@@ -311,6 +311,17 @@ async function createProcessor(args, cliConfigPath) {
|
|
|
311
311
|
let end = process.hrtime.bigint();
|
|
312
312
|
console.error();
|
|
313
313
|
console.error("Done in", (end - start) / BigInt(1e6) + "ms.");
|
|
314
|
+
}).then(()=>{}, (err)=>{
|
|
315
|
+
// TODO: If an initial build fails we can't easily pick up any PostCSS dependencies
|
|
316
|
+
// that were collected before the error occurred
|
|
317
|
+
// The result is not stored on the error so we have to store it externally
|
|
318
|
+
// and pull the messages off of it here somehow
|
|
319
|
+
// This results in a less than ideal DX because the watcher will not pick up
|
|
320
|
+
// changes to imported CSS if one of them caused an error during the initial build
|
|
321
|
+
// If you fix it and then save the main CSS file so there's no error
|
|
322
|
+
// The watcher will start watching the imported CSS files and will be
|
|
323
|
+
// resilient to future errors.
|
|
324
|
+
console.error(err);
|
|
314
325
|
});
|
|
315
326
|
}
|
|
316
327
|
/**
|
|
@@ -37,22 +37,70 @@ function createWatcher(args, { state , rebuild }) {
|
|
|
37
37
|
pollInterval: pollInterval
|
|
38
38
|
} : false
|
|
39
39
|
});
|
|
40
|
+
// A queue of rebuilds, file reads, etc… to run
|
|
40
41
|
let chain = Promise.resolve();
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
/**
|
|
43
|
+
* A list of files that have been changed since the last rebuild
|
|
44
|
+
*
|
|
45
|
+
* @type {{file: string, content: () => Promise<string>, extension: string}[]}
|
|
46
|
+
*/ let changedContent = [];
|
|
47
|
+
/**
|
|
48
|
+
* A list of files for which a rebuild has already been queued.
|
|
49
|
+
* This is used to prevent duplicate rebuilds when multiple events are fired for the same file.
|
|
50
|
+
* The rebuilt file is cleared from this list when it's associated rebuild has _started_
|
|
51
|
+
* This is because if the file is changed during a rebuild it won't trigger a new rebuild which it should
|
|
52
|
+
**/ let pendingRebuilds = new Set();
|
|
53
|
+
let _timer;
|
|
54
|
+
let _reject;
|
|
55
|
+
/**
|
|
56
|
+
* Rebuilds the changed files and resolves when the rebuild is
|
|
57
|
+
* complete regardless of whether it was successful or not
|
|
58
|
+
*/ async function rebuildAndContinue() {
|
|
59
|
+
let changes = changedContent.splice(0);
|
|
60
|
+
// There are no changes to rebuild so we can just do nothing
|
|
61
|
+
if (changes.length === 0) {
|
|
62
|
+
return Promise.resolve();
|
|
63
|
+
}
|
|
64
|
+
// Clear all pending rebuilds for the about-to-be-built files
|
|
65
|
+
changes.forEach((change)=>pendingRebuilds.delete(change.file));
|
|
66
|
+
// Resolve the promise even when the rebuild fails
|
|
67
|
+
return rebuild(changes).then(()=>{}, ()=>{});
|
|
68
|
+
}
|
|
43
69
|
/**
|
|
44
70
|
*
|
|
45
71
|
* @param {*} file
|
|
46
72
|
* @param {(() => Promise<string>) | null} content
|
|
47
|
-
|
|
73
|
+
* @param {boolean} skipPendingCheck
|
|
74
|
+
* @returns {Promise<void>}
|
|
75
|
+
*/ function recordChangedFile(file, content = null, skipPendingCheck = false) {
|
|
48
76
|
file = _path.default.resolve(file);
|
|
49
|
-
|
|
77
|
+
// Applications like Vim/Neovim fire both rename and change events in succession for atomic writes
|
|
78
|
+
// In that case rebuild has already been queued by rename, so can be skipped in change
|
|
79
|
+
if (pendingRebuilds.has(file) && !skipPendingCheck) {
|
|
80
|
+
return Promise.resolve();
|
|
81
|
+
}
|
|
82
|
+
// Mark that a rebuild of this file is going to happen
|
|
83
|
+
// It MUST happen synchronously before the rebuild is queued for this to be effective
|
|
84
|
+
pendingRebuilds.add(file);
|
|
50
85
|
changedContent.push({
|
|
51
86
|
file,
|
|
52
|
-
content,
|
|
87
|
+
content: content !== null && content !== void 0 ? content : ()=>_fs.default.promises.readFile(file, "utf8"),
|
|
53
88
|
extension: _path.default.extname(file).slice(1)
|
|
54
89
|
});
|
|
55
|
-
|
|
90
|
+
if (_timer) {
|
|
91
|
+
clearTimeout(_timer);
|
|
92
|
+
_reject();
|
|
93
|
+
}
|
|
94
|
+
// If a rebuild is already in progress we don't want to start another one until the 10ms timer has expired
|
|
95
|
+
chain = chain.then(()=>new Promise((resolve, reject)=>{
|
|
96
|
+
_timer = setTimeout(resolve, 10);
|
|
97
|
+
_reject = reject;
|
|
98
|
+
}));
|
|
99
|
+
// Resolves once this file has been rebuilt (or the rebuild for this file has failed)
|
|
100
|
+
// This queues as many rebuilds as there are changed files
|
|
101
|
+
// But those rebuilds happen after some delay
|
|
102
|
+
// And will immediately resolve if there are no changes
|
|
103
|
+
chain = chain.then(rebuildAndContinue, rebuildAndContinue);
|
|
56
104
|
return chain;
|
|
57
105
|
}
|
|
58
106
|
watcher.on("change", (file)=>recordChangedFile(file));
|
|
@@ -91,15 +139,32 @@ function createWatcher(args, { state , rebuild }) {
|
|
|
91
139
|
if (pendingRebuilds.has(filePath)) {
|
|
92
140
|
return;
|
|
93
141
|
}
|
|
142
|
+
// We'll go ahead and add the file to the pending rebuilds list here
|
|
143
|
+
// It'll be removed when the rebuild starts unless the read fails
|
|
144
|
+
// which will be taken care of as well
|
|
94
145
|
pendingRebuilds.add(filePath);
|
|
95
|
-
|
|
96
|
-
let content;
|
|
146
|
+
async function enqueue() {
|
|
97
147
|
try {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
148
|
+
// We need to read the file as early as possible outside of the chain
|
|
149
|
+
// because it may be gone by the time we get to it. doing the read
|
|
150
|
+
// immediately increases the chance that the file is still there
|
|
151
|
+
let content = await (0, _utilsJs.readFileWithRetries)(_path.default.resolve(filePath));
|
|
152
|
+
if (content === undefined) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
// This will push the rebuild onto the chain
|
|
156
|
+
// We MUST skip the rebuild check here otherwise the rebuild will never happen on Linux
|
|
157
|
+
// This is because the order of events and timing is different on Linux
|
|
158
|
+
// @ts-ignore: TypeScript isn't picking up that content is a string here
|
|
159
|
+
await recordChangedFile(filePath, ()=>content, true);
|
|
160
|
+
} catch {
|
|
161
|
+
// If reading the file fails, it's was probably a deleted temporary file
|
|
162
|
+
// So we can ignore it and no rebuild is needed
|
|
101
163
|
}
|
|
102
|
-
|
|
164
|
+
}
|
|
165
|
+
enqueue().then(()=>{
|
|
166
|
+
// If the file read fails we still need to make sure the file isn't stuck in the pending rebuilds list
|
|
167
|
+
pendingRebuilds.delete(filePath);
|
|
103
168
|
});
|
|
104
169
|
});
|
|
105
170
|
return {
|
package/lib/css/preflight.css
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
2. Prevent adjustments of font size after orientation changes in iOS.
|
|
23
23
|
3. Use a more readable tab size.
|
|
24
24
|
4. Use the user's configured `sans` font-family by default.
|
|
25
|
+
5. Use the user's configured `sans` font-feature-settings by default.
|
|
25
26
|
*/
|
|
26
27
|
|
|
27
28
|
html {
|
|
@@ -30,6 +31,7 @@ html {
|
|
|
30
31
|
-moz-tab-size: 4; /* 3 */
|
|
31
32
|
tab-size: 4; /* 3 */
|
|
32
33
|
font-family: theme('fontFamily.sans', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"); /* 4 */
|
|
34
|
+
font-feature-settings: theme('fontFamily.sans[1].fontFeatureSettings', normal); /* 5 */
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
/*
|
package/lib/lib/content.js
CHANGED
|
@@ -160,7 +160,14 @@ function resolvedChangedContent(context, candidateFiles, fileModifiedMap) {
|
|
|
160
160
|
for (let file of files){
|
|
161
161
|
let prevModified = fileModifiedMap.has(file) ? fileModifiedMap.get(file) : -Infinity;
|
|
162
162
|
let modified = _fs.default.statSync(file).mtimeMs;
|
|
163
|
-
|
|
163
|
+
// This check is intentionally >= because we track the last modified time of context dependencies
|
|
164
|
+
// earier in the process and we want to make sure we don't miss any changes that happen
|
|
165
|
+
// when a context dependency is also a content dependency
|
|
166
|
+
// Ideally, we'd do all this tracking at one time but that is a larger refactor
|
|
167
|
+
// than we want to commit to right now, so this is a decent compromise.
|
|
168
|
+
// This should be sufficient because file modification times will be off by at least
|
|
169
|
+
// 1ms (the precision of fstat in Node) in most cases if they exist and were changed.
|
|
170
|
+
if (modified >= prevModified) {
|
|
164
171
|
changedFiles.add(file);
|
|
165
172
|
fileModifiedMap.set(file, modified);
|
|
166
173
|
}
|
|
@@ -306,21 +306,40 @@ function processApply(root, context, localCache) {
|
|
|
306
306
|
hasReplaced = true;
|
|
307
307
|
});
|
|
308
308
|
});
|
|
309
|
-
// Sort tag names before class names
|
|
309
|
+
// Sort tag names before class names (but only sort each group (separated by a combinator)
|
|
310
|
+
// separately and not in total)
|
|
310
311
|
// This happens when replacing `.bar` in `.foo.bar` with a tag like `section`
|
|
311
|
-
for (
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
} else
|
|
320
|
-
|
|
312
|
+
for (let sel1 of replaced){
|
|
313
|
+
let groups = [
|
|
314
|
+
[]
|
|
315
|
+
];
|
|
316
|
+
for (let node of sel1.nodes){
|
|
317
|
+
if (node.type === "combinator") {
|
|
318
|
+
groups.push(node);
|
|
319
|
+
groups.push([]);
|
|
320
|
+
} else {
|
|
321
|
+
let last = groups[groups.length - 1];
|
|
322
|
+
last.push(node);
|
|
321
323
|
}
|
|
322
|
-
|
|
323
|
-
|
|
324
|
+
}
|
|
325
|
+
sel1.nodes = [];
|
|
326
|
+
for (let group of groups){
|
|
327
|
+
if (Array.isArray(group)) {
|
|
328
|
+
group.sort((a, b)=>{
|
|
329
|
+
if (a.type === "tag" && b.type === "class") {
|
|
330
|
+
return -1;
|
|
331
|
+
} else if (a.type === "class" && b.type === "tag") {
|
|
332
|
+
return 1;
|
|
333
|
+
} else if (a.type === "class" && b.type === "pseudo" && b.value.startsWith("::")) {
|
|
334
|
+
return -1;
|
|
335
|
+
} else if (a.type === "pseudo" && a.value.startsWith("::") && b.type === "class") {
|
|
336
|
+
return 1;
|
|
337
|
+
}
|
|
338
|
+
return 0;
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
sel1.nodes = sel1.nodes.concat(group);
|
|
342
|
+
}
|
|
324
343
|
}
|
|
325
344
|
sel.replaceWith(...replaced);
|
|
326
345
|
});
|
|
@@ -340,7 +359,7 @@ function processApply(root, context, localCache) {
|
|
|
340
359
|
let [applyCandidates1, important] = extractApplyCandidates(apply.params);
|
|
341
360
|
if (apply.parent.type === "atrule") {
|
|
342
361
|
if (apply.parent.name === "screen") {
|
|
343
|
-
|
|
362
|
+
let screenType = apply.parent.params;
|
|
344
363
|
throw apply.error(`@apply is not supported within nested at-rules like @screen. We suggest you write this as @apply ${applyCandidates1.map((c)=>`${screenType}:${c}`).join(" ")} instead.`);
|
|
345
364
|
}
|
|
346
365
|
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}.`);
|
|
@@ -364,7 +383,7 @@ function processApply(root, context, localCache) {
|
|
|
364
383
|
]);
|
|
365
384
|
}
|
|
366
385
|
}
|
|
367
|
-
for (
|
|
386
|
+
for (let [parent, [candidates1, atApplySource]] of perParentApplies){
|
|
368
387
|
let siblings = [];
|
|
369
388
|
for (let [applyCandidate1, important1, rules1] of candidates1){
|
|
370
389
|
let potentialApplyCandidates = [
|
|
@@ -169,7 +169,7 @@ function expandTailwindAtRules(context) {
|
|
|
169
169
|
], context);
|
|
170
170
|
}
|
|
171
171
|
env.DEBUG && console.timeEnd("Build stylesheet");
|
|
172
|
-
let { defaults: defaultNodes , base: baseNodes , components: componentNodes , utilities: utilityNodes , variants: screenNodes
|
|
172
|
+
let { defaults: defaultNodes , base: baseNodes , components: componentNodes , utilities: utilityNodes , variants: screenNodes } = context.stylesheetCache;
|
|
173
173
|
// ---
|
|
174
174
|
// Replace any Tailwind directives with generated CSS
|
|
175
175
|
if (layerNodes.base) {
|
package/lib/lib/generateRules.js
CHANGED
|
@@ -162,7 +162,7 @@ function applyImportant(matches, classCandidate) {
|
|
|
162
162
|
]
|
|
163
163
|
});
|
|
164
164
|
container.walkRules((r)=>{
|
|
165
|
-
r.selector = (0, _pluginUtils.updateAllClasses)(r.selector, (className)=>{
|
|
165
|
+
r.selector = (0, _pluginUtils.updateAllClasses)((0, _pluginUtils.filterSelectorsForClass)(r.selector, classCandidate), (className)=>{
|
|
166
166
|
if (className === classCandidate) {
|
|
167
167
|
return `!${className}`;
|
|
168
168
|
}
|
|
@@ -256,7 +256,7 @@ function applyVariant(variant, matches, context) {
|
|
|
256
256
|
]
|
|
257
257
|
});
|
|
258
258
|
for (let [variantSort, variantFunction, containerFromArray] of variantFunctionTuples){
|
|
259
|
-
let clone = containerFromArray !== null && containerFromArray !== void 0 ? containerFromArray : container.clone();
|
|
259
|
+
let clone = (containerFromArray !== null && containerFromArray !== void 0 ? containerFromArray : container).clone();
|
|
260
260
|
let collectedFormats = [];
|
|
261
261
|
function prepareBackup() {
|
|
262
262
|
// Already prepared, chicken out
|
|
@@ -533,7 +533,7 @@ function parseVariant(variant) {
|
|
|
533
533
|
variantFunctions = [].concat(variantFunctions).map((variantFunction)=>{
|
|
534
534
|
if (typeof variantFunction !== "string") {
|
|
535
535
|
// Safelist public API functions
|
|
536
|
-
return (api)=>{
|
|
536
|
+
return (api = {})=>{
|
|
537
537
|
let { args , modifySelectors , container , separator , wrap , format } = api;
|
|
538
538
|
let result = variantFunction(Object.assign({
|
|
539
539
|
modifySelectors,
|
|
@@ -574,12 +574,14 @@ function parseVariant(variant) {
|
|
|
574
574
|
var ref1;
|
|
575
575
|
for (let [key, value] of Object.entries((ref1 = options === null || options === void 0 ? void 0 : options.values) !== null && ref1 !== void 0 ? ref1 : {})){
|
|
576
576
|
if (key === "DEFAULT") continue;
|
|
577
|
-
api.addVariant(isSpecial ? `${variant}${key}` : `${variant}-${key}`, ({ args , container })=>
|
|
578
|
-
|
|
577
|
+
api.addVariant(isSpecial ? `${variant}${key}` : `${variant}-${key}`, ({ args , container })=>{
|
|
578
|
+
return variantFn(value, modifiersEnabled ? {
|
|
579
|
+
modifier: args === null || args === void 0 ? void 0 : args.modifier,
|
|
579
580
|
container
|
|
580
581
|
} : {
|
|
581
582
|
container
|
|
582
|
-
})
|
|
583
|
+
});
|
|
584
|
+
}, {
|
|
583
585
|
...options,
|
|
584
586
|
value,
|
|
585
587
|
id,
|
|
@@ -590,11 +592,13 @@ function parseVariant(variant) {
|
|
|
590
592
|
var ref2;
|
|
591
593
|
let hasDefault = "DEFAULT" in ((ref2 = options === null || options === void 0 ? void 0 : options.values) !== null && ref2 !== void 0 ? ref2 : {});
|
|
592
594
|
api.addVariant(variant, ({ args , container })=>{
|
|
593
|
-
if (args.value === _sharedState.NONE && !hasDefault) {
|
|
595
|
+
if ((args === null || args === void 0 ? void 0 : args.value) === _sharedState.NONE && !hasDefault) {
|
|
594
596
|
return null;
|
|
595
597
|
}
|
|
596
|
-
|
|
597
|
-
|
|
598
|
+
var // (JetBrains) plugins.
|
|
599
|
+
ref;
|
|
600
|
+
return variantFn((args === null || args === void 0 ? void 0 : args.value) === _sharedState.NONE ? options.values.DEFAULT : (ref = args === null || args === void 0 ? void 0 : args.value) !== null && ref !== void 0 ? ref : typeof args === "string" ? args : "", modifiersEnabled ? {
|
|
601
|
+
modifier: args === null || args === void 0 ? void 0 : args.modifier,
|
|
598
602
|
container
|
|
599
603
|
} : {
|
|
600
604
|
container
|
|
@@ -795,6 +799,7 @@ function registerPlugins(plugins, context) {
|
|
|
795
799
|
if (checks.length > 0) {
|
|
796
800
|
let patternMatchingCount = new Map();
|
|
797
801
|
let prefixLength = context.tailwindConfig.prefix.length;
|
|
802
|
+
let checkImportantUtils = checks.some((check)=>check.pattern.source.includes("!"));
|
|
798
803
|
for (let util of classList){
|
|
799
804
|
let utils = Array.isArray(util) ? (()=>{
|
|
800
805
|
let [utilName, options] = util;
|
|
@@ -823,6 +828,12 @@ function registerPlugins(plugins, context) {
|
|
|
823
828
|
...classes.flatMap((cls)=>Object.keys(context.tailwindConfig.theme.opacity).map((opacity)=>`${cls}/${opacity}`))
|
|
824
829
|
];
|
|
825
830
|
}
|
|
831
|
+
if (checkImportantUtils && (options === null || options === void 0 ? void 0 : options.respectImportant)) {
|
|
832
|
+
classes = [
|
|
833
|
+
...classes,
|
|
834
|
+
...classes.map((cls)=>"!" + cls)
|
|
835
|
+
];
|
|
836
|
+
}
|
|
826
837
|
return classes;
|
|
827
838
|
})() : [
|
|
828
839
|
util
|
|
@@ -1087,13 +1098,15 @@ function registerPlugins(plugins, context) {
|
|
|
1087
1098
|
markInvalidUtilityCandidate(context, candidate);
|
|
1088
1099
|
}
|
|
1089
1100
|
function createContext(tailwindConfig, changedContent = [], root = _postcss.default.root()) {
|
|
1101
|
+
var _blocklist;
|
|
1090
1102
|
let context = {
|
|
1091
1103
|
disposables: [],
|
|
1092
1104
|
ruleCache: new Set(),
|
|
1093
1105
|
candidateRuleCache: new Map(),
|
|
1094
1106
|
classCache: new Map(),
|
|
1095
1107
|
applyClassCache: new Map(),
|
|
1096
|
-
|
|
1108
|
+
// Seed the not class cache with the blocklist (which is only strings)
|
|
1109
|
+
notClassCache: new Set((_blocklist = tailwindConfig.blocklist) !== null && _blocklist !== void 0 ? _blocklist : []),
|
|
1097
1110
|
postCssNodeCache: new Map(),
|
|
1098
1111
|
candidateRuleMap: new Map(),
|
|
1099
1112
|
tailwindConfig,
|
|
@@ -78,9 +78,9 @@ function formatVariantSelector(current, ...others) {
|
|
|
78
78
|
return -1;
|
|
79
79
|
} else if (a.type === "class" && b.type === "tag") {
|
|
80
80
|
return 1;
|
|
81
|
-
} else if (a.type === "class" && b.type === "pseudo" && b.value
|
|
81
|
+
} else if (a.type === "class" && b.type === "pseudo" && b.value.startsWith("::")) {
|
|
82
82
|
return -1;
|
|
83
|
-
} else if (a.type === "pseudo" && a.value
|
|
83
|
+
} else if (a.type === "pseudo" && a.value.startsWith("::") && b.type === "class") {
|
|
84
84
|
return 1;
|
|
85
85
|
}
|
|
86
86
|
return sel.index(a) - sel.index(b);
|
|
@@ -114,7 +114,7 @@ function finalizeSelector(format, { selector , candidate , context , isArbitrary
|
|
|
114
114
|
// │ │ │ ╰── We will not split here
|
|
115
115
|
// ╰──┴─────┴─────────────── We will split here
|
|
116
116
|
//
|
|
117
|
-
base =candidate.split(new RegExp(`\\${(ref1 = context === null || context === void 0 ? void 0 : (ref = context.tailwindConfig) === null || ref === void 0 ? void 0 : ref.separator) !== null && ref1 !== void 0 ? ref1 : ":"}(?![^[]*\\])`)).pop()
|
|
117
|
+
base =candidate.split(new RegExp(`\\${(ref1 = context === null || context === void 0 ? void 0 : (ref = context.tailwindConfig) === null || ref === void 0 ? void 0 : ref.separator) !== null && ref1 !== void 0 ? ref1 : ":"}(?![^[]*\\])`)).pop() }) {
|
|
118
118
|
var ref2;
|
|
119
119
|
let ast = (0, _postcssSelectorParser.default)().astSync(selector);
|
|
120
120
|
// We explicitly DO NOT prefix classes in arbitrary variants
|
|
@@ -162,6 +162,20 @@ function normalizeConfig(config) {
|
|
|
162
162
|
if (Array.isArray(purge === null || purge === void 0 ? void 0 : (ref = purge.options) === null || ref === void 0 ? void 0 : ref.safelist)) return purge.options.safelist;
|
|
163
163
|
return [];
|
|
164
164
|
})();
|
|
165
|
+
// Normalize the `blocklist`
|
|
166
|
+
config.blocklist = (()=>{
|
|
167
|
+
let { blocklist } = config;
|
|
168
|
+
if (Array.isArray(blocklist)) {
|
|
169
|
+
if (blocklist.every((item)=>typeof item === "string")) {
|
|
170
|
+
return blocklist;
|
|
171
|
+
}
|
|
172
|
+
_log.default.warn("blocklist-invalid", [
|
|
173
|
+
"The `blocklist` option must be an array of strings.",
|
|
174
|
+
"https://tailwindcss.com/docs/content-configuration#discarding-classes"
|
|
175
|
+
]);
|
|
176
|
+
}
|
|
177
|
+
return [];
|
|
178
|
+
})();
|
|
165
179
|
// Normalize prefix option
|
|
166
180
|
if (typeof config.prefix === "function") {
|
|
167
181
|
_log.default.warn("prefix-function", [
|
package/lib/util/pluginUtils.js
CHANGED
|
@@ -10,6 +10,7 @@ function _export(target, all) {
|
|
|
10
10
|
}
|
|
11
11
|
_export(exports, {
|
|
12
12
|
updateAllClasses: ()=>updateAllClasses,
|
|
13
|
+
filterSelectorsForClass: ()=>filterSelectorsForClass,
|
|
13
14
|
asValue: ()=>asValue,
|
|
14
15
|
parseColorFormat: ()=>parseColorFormat,
|
|
15
16
|
asColor: ()=>asColor,
|
|
@@ -43,6 +44,18 @@ function updateAllClasses(selectors, updateClass) {
|
|
|
43
44
|
let result = parser.processSync(selectors);
|
|
44
45
|
return result;
|
|
45
46
|
}
|
|
47
|
+
function filterSelectorsForClass(selectors, classCandidate) {
|
|
48
|
+
let parser = (0, _postcssSelectorParser.default)((selectors)=>{
|
|
49
|
+
selectors.each((sel)=>{
|
|
50
|
+
const containsClass = sel.nodes.some((node)=>node.type === "class" && node.value === classCandidate);
|
|
51
|
+
if (!containsClass) {
|
|
52
|
+
sel.remove();
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
let result = parser.processSync(selectors);
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
46
59
|
function resolveArbitraryValue(modifier, validate) {
|
|
47
60
|
if (!isArbitraryValue(modifier)) {
|
|
48
61
|
return undefined;
|
|
@@ -110,15 +123,15 @@ function parseColorFormat(value) {
|
|
|
110
123
|
}
|
|
111
124
|
return value;
|
|
112
125
|
}
|
|
113
|
-
function asColor(
|
|
126
|
+
function asColor(modifier, options = {}, { tailwindConfig ={} } = {}) {
|
|
114
127
|
var ref;
|
|
115
|
-
if (((ref = options.values) === null || ref === void 0 ? void 0 : ref[
|
|
128
|
+
if (((ref = options.values) === null || ref === void 0 ? void 0 : ref[modifier]) !== undefined) {
|
|
116
129
|
var ref1;
|
|
117
|
-
return parseColorFormat((ref1 = options.values) === null || ref1 === void 0 ? void 0 : ref1[
|
|
130
|
+
return parseColorFormat((ref1 = options.values) === null || ref1 === void 0 ? void 0 : ref1[modifier]);
|
|
118
131
|
}
|
|
119
132
|
// TODO: Hoist this up to getMatchingTypes or something
|
|
120
133
|
// We do this here because we need the alpha value (if any)
|
|
121
|
-
let [color, alpha] = splitUtilityModifier(
|
|
134
|
+
let [color, alpha] = splitUtilityModifier(modifier);
|
|
122
135
|
if (alpha !== undefined) {
|
|
123
136
|
var ref2, ref3, ref4;
|
|
124
137
|
var ref5;
|
|
@@ -135,9 +148,7 @@ function asColor(_, options = {}, { tailwindConfig ={} , utilityModifier , rawMo
|
|
|
135
148
|
}
|
|
136
149
|
return (0, _withAlphaVariable.withAlphaValue)(normalizedColor, tailwindConfig.theme.opacity[alpha]);
|
|
137
150
|
}
|
|
138
|
-
return asValue(
|
|
139
|
-
rawModifier,
|
|
140
|
-
utilityModifier,
|
|
151
|
+
return asValue(modifier, options, {
|
|
141
152
|
validate: _dataTypes.color
|
|
142
153
|
});
|
|
143
154
|
}
|
|
@@ -146,9 +157,8 @@ function asLookupValue(modifier, options = {}) {
|
|
|
146
157
|
return (ref = options.values) === null || ref === void 0 ? void 0 : ref[modifier];
|
|
147
158
|
}
|
|
148
159
|
function guess(validate) {
|
|
149
|
-
return (modifier, options
|
|
160
|
+
return (modifier, options)=>{
|
|
150
161
|
return asValue(modifier, options, {
|
|
151
|
-
...extras,
|
|
152
162
|
validate
|
|
153
163
|
});
|
|
154
164
|
};
|
|
@@ -184,6 +194,21 @@ function splitAtFirst(input, delim) {
|
|
|
184
194
|
];
|
|
185
195
|
}
|
|
186
196
|
function coerceValue(types, modifier, options, tailwindConfig) {
|
|
197
|
+
if (options.values && modifier in options.values) {
|
|
198
|
+
for (let { type } of types !== null && types !== void 0 ? types : []){
|
|
199
|
+
let result = typeMap[type](modifier, options, {
|
|
200
|
+
tailwindConfig
|
|
201
|
+
});
|
|
202
|
+
if (result === undefined) {
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
return [
|
|
206
|
+
result,
|
|
207
|
+
type,
|
|
208
|
+
null
|
|
209
|
+
];
|
|
210
|
+
}
|
|
211
|
+
}
|
|
187
212
|
if (isArbitraryValue(modifier)) {
|
|
188
213
|
let arbitraryValue = modifier.slice(1, -1);
|
|
189
214
|
let [explicitType, value] = splitAtFirst(arbitraryValue, ":");
|
|
@@ -234,30 +259,16 @@ function* getMatchingTypes(types, rawModifier, options, tailwindConfig) {
|
|
|
234
259
|
utilityModifier = utilityModifier.slice(1, -1);
|
|
235
260
|
}
|
|
236
261
|
}
|
|
237
|
-
let result = asValue(rawModifier, options, {
|
|
238
|
-
rawModifier,
|
|
239
|
-
utilityModifier,
|
|
240
|
-
tailwindConfig
|
|
241
|
-
});
|
|
242
|
-
if (result !== undefined) {
|
|
243
|
-
yield [
|
|
244
|
-
result,
|
|
245
|
-
"any",
|
|
246
|
-
null
|
|
247
|
-
];
|
|
248
|
-
}
|
|
249
262
|
}
|
|
250
|
-
for (
|
|
251
|
-
let
|
|
252
|
-
rawModifier,
|
|
253
|
-
utilityModifier,
|
|
263
|
+
for (let { type } of types !== null && types !== void 0 ? types : []){
|
|
264
|
+
let result = typeMap[type](modifier, options, {
|
|
254
265
|
tailwindConfig
|
|
255
266
|
});
|
|
256
|
-
if (
|
|
267
|
+
if (result === undefined) {
|
|
257
268
|
continue;
|
|
258
269
|
}
|
|
259
270
|
yield [
|
|
260
|
-
|
|
271
|
+
result,
|
|
261
272
|
type,
|
|
262
273
|
utilityModifier !== null && utilityModifier !== void 0 ? utilityModifier : null
|
|
263
274
|
];
|
|
@@ -9,7 +9,6 @@ Object.defineProperty(exports, "default", {
|
|
|
9
9
|
const _negateValue = /*#__PURE__*/ _interopRequireDefault(require("./negateValue"));
|
|
10
10
|
const _corePluginList = /*#__PURE__*/ _interopRequireDefault(require("../corePluginList"));
|
|
11
11
|
const _configurePlugins = /*#__PURE__*/ _interopRequireDefault(require("./configurePlugins"));
|
|
12
|
-
const _defaultConfigStub = /*#__PURE__*/ _interopRequireDefault(require("../../stubs/defaultConfig.stub"));
|
|
13
12
|
const _colors = /*#__PURE__*/ _interopRequireDefault(require("../public/colors"));
|
|
14
13
|
const _defaults = require("./defaults");
|
|
15
14
|
const _toPath = require("./toPath");
|
|
@@ -27,16 +26,13 @@ function _interopRequireDefault(obj) {
|
|
|
27
26
|
function isFunction(input) {
|
|
28
27
|
return typeof input === "function";
|
|
29
28
|
}
|
|
30
|
-
function isObject(input) {
|
|
31
|
-
return typeof input === "object" && input !== null;
|
|
32
|
-
}
|
|
33
29
|
function mergeWith(target, ...sources) {
|
|
34
30
|
let customizer = sources.pop();
|
|
35
31
|
for (let source of sources){
|
|
36
32
|
for(let k in source){
|
|
37
33
|
let merged = customizer(target[k], source[k]);
|
|
38
34
|
if (merged === undefined) {
|
|
39
|
-
if (
|
|
35
|
+
if ((0, _isPlainObject.default)(target[k]) && (0, _isPlainObject.default)(source[k])) {
|
|
40
36
|
target[k] = mergeWith({}, target[k], source[k], customizer);
|
|
41
37
|
} else {
|
|
42
38
|
target[k] = source[k];
|
|
@@ -101,11 +97,11 @@ function mergeThemes(themes) {
|
|
|
101
97
|
}
|
|
102
98
|
function mergeExtensionCustomizer(merged, value) {
|
|
103
99
|
// When we have an array of objects, we do want to merge it
|
|
104
|
-
if (Array.isArray(merged) &&
|
|
100
|
+
if (Array.isArray(merged) && (0, _isPlainObject.default)(merged[0])) {
|
|
105
101
|
return merged.concat(value);
|
|
106
102
|
}
|
|
107
103
|
// When the incoming value is an array, and the existing config is an object, prepend the existing object
|
|
108
|
-
if (Array.isArray(value) &&
|
|
104
|
+
if (Array.isArray(value) && (0, _isPlainObject.default)(value[0]) && (0, _isPlainObject.default)(merged)) {
|
|
109
105
|
return [
|
|
110
106
|
merged,
|
|
111
107
|
...value
|
|
@@ -242,8 +238,7 @@ function resolveConfig(configs) {
|
|
|
242
238
|
{
|
|
243
239
|
prefix: "",
|
|
244
240
|
important: false,
|
|
245
|
-
separator: ":"
|
|
246
|
-
variantOrder: _defaultConfigStub.default.variantOrder
|
|
241
|
+
separator: ":"
|
|
247
242
|
}
|
|
248
243
|
];
|
|
249
244
|
var ref, ref1;
|