tailwindcss 3.3.3 → 3.3.5
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 +31 -2
- package/lib/cli/build/watching.js +1 -1
- package/lib/lib/defaultExtractor.js +16 -22
- package/lib/lib/expandApplyAtRules.js +6 -0
- package/lib/lib/expandTailwindAtRules.js +20 -6
- package/lib/lib/generateRules.js +19 -17
- package/lib/lib/setupContextUtils.js +29 -27
- package/lib/oxide/cli/build/plugin.js +2 -2
- package/lib/util/color.js +1 -1
- package/lib/util/dataTypes.js +110 -10
- package/lib/util/formatVariantSelector.js +8 -1
- package/lib/util/isPlainObject.js +1 -1
- package/nesting/index.d.ts +4 -0
- package/package.json +5 -5
- package/peers/index.js +701 -617
- package/src/cli/build/watching.js +1 -1
- package/src/featureFlags.js +0 -1
- package/src/lib/defaultExtractor.js +12 -13
- package/src/lib/expandApplyAtRules.js +7 -0
- package/src/lib/expandTailwindAtRules.js +20 -8
- package/src/lib/generateRules.js +19 -17
- package/src/lib/setupContextUtils.js +32 -30
- package/src/oxide/cli/build/plugin.ts +2 -2
- package/src/util/color.js +1 -1
- package/src/util/dataTypes.js +115 -13
- package/src/util/formatVariantSelector.js +9 -1
- package/src/util/isPlainObject.js +1 -1
- package/types/config.d.ts +6 -6
- package/types/index.d.ts +7 -3
package/CHANGELOG.md
CHANGED
|
@@ -7,7 +7,34 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
-
-
|
|
10
|
+
## [3.3.5] - 2023-10-25
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Fix incorrect spaces around `-` in `calc()` expression ([#12283](https://github.com/tailwindlabs/tailwindcss/pull/12283))
|
|
15
|
+
|
|
16
|
+
## [3.3.4] - 2023-10-24
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- Improve normalisation of `calc()`-like functions ([#11686](https://github.com/tailwindlabs/tailwindcss/pull/11686))
|
|
21
|
+
- Skip `calc()` normalisation in nested `theme()` calls ([#11705](https://github.com/tailwindlabs/tailwindcss/pull/11705))
|
|
22
|
+
- Fix incorrectly generated CSS when using square brackets inside arbitrary properties ([#11709](https://github.com/tailwindlabs/tailwindcss/pull/11709))
|
|
23
|
+
- Make `content` optional for presets in TypeScript types ([#11730](https://github.com/tailwindlabs/tailwindcss/pull/11730))
|
|
24
|
+
- Handle variable colors that have variable fallback values ([#12049](https://github.com/tailwindlabs/tailwindcss/pull/12049))
|
|
25
|
+
- Batch reading content files to prevent `too many open files` error ([#12079](https://github.com/tailwindlabs/tailwindcss/pull/12079))
|
|
26
|
+
- Skip over classes inside `:not(…)` when nested in an at-rule ([#12105](https://github.com/tailwindlabs/tailwindcss/pull/12105))
|
|
27
|
+
- Update types to work with `Node16` module resolution ([#12097](https://github.com/tailwindlabs/tailwindcss/pull/12097))
|
|
28
|
+
- Don’t crash when important and parent selectors are equal in `@apply` ([#12112](https://github.com/tailwindlabs/tailwindcss/pull/12112))
|
|
29
|
+
- Eliminate irrelevant rules when applying variants ([#12113](https://github.com/tailwindlabs/tailwindcss/pull/12113))
|
|
30
|
+
- Improve RegEx parser, reduce possibilities as the key for arbitrary properties ([#12121](https://github.com/tailwindlabs/tailwindcss/pull/12121))
|
|
31
|
+
- Fix sorting of utilities that share multiple candidates ([#12173](https://github.com/tailwindlabs/tailwindcss/pull/12173))
|
|
32
|
+
- Ensure variants with arbitrary values and a modifier are correctly matched in the RegEx based parser ([#12179](https://github.com/tailwindlabs/tailwindcss/pull/12179))
|
|
33
|
+
- Fix crash when watching renamed files on FreeBSD ([#12193](https://github.com/tailwindlabs/tailwindcss/pull/12193))
|
|
34
|
+
- Allow plugins from a parent document to be used in an iframe ([#12208](https://github.com/tailwindlabs/tailwindcss/pull/12208))
|
|
35
|
+
- Add types for `tailwindcss/nesting` ([#12269](https://github.com/tailwindlabs/tailwindcss/pull/12269))
|
|
36
|
+
- Bump `jiti`, `fast-glob`, and `browserlist` dependencies ([#11550](https://github.com/tailwindlabs/tailwindcss/pull/11550))
|
|
37
|
+
- Improve automatic `var` injection for properties that accept a `<dashed-ident>` ([#12236](https://github.com/tailwindlabs/tailwindcss/pull/12236))
|
|
11
38
|
|
|
12
39
|
## [3.3.3] - 2023-07-13
|
|
13
40
|
|
|
@@ -2260,7 +2287,9 @@ No release notes
|
|
|
2260
2287
|
|
|
2261
2288
|
- Everything!
|
|
2262
2289
|
|
|
2263
|
-
[unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.3.
|
|
2290
|
+
[unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.3.5...HEAD
|
|
2291
|
+
[3.3.5]: https://github.com/tailwindlabs/tailwindcss/compare/v3.3.4...v3.3.5
|
|
2292
|
+
[3.3.4]: https://github.com/tailwindlabs/tailwindcss/compare/v3.3.3...v3.3.4
|
|
2264
2293
|
[3.3.3]: https://github.com/tailwindlabs/tailwindcss/compare/v3.3.2...v3.3.3
|
|
2265
2294
|
[3.3.2]: https://github.com/tailwindlabs/tailwindcss/compare/v3.3.1...v3.3.2
|
|
2266
2295
|
[3.3.1]: https://github.com/tailwindlabs/tailwindcss/compare/v3.3.0...v3.3.1
|
|
@@ -126,7 +126,7 @@ function createWatcher(args, { state , rebuild }) {
|
|
|
126
126
|
// This is very likely a chokidar bug but it's one we need to work around
|
|
127
127
|
// We treat this as a change event and rebuild the CSS
|
|
128
128
|
watcher.on("raw", (evt, filePath, meta)=>{
|
|
129
|
-
if (evt !== "rename") {
|
|
129
|
+
if (evt !== "rename" || filePath === null) {
|
|
130
130
|
return;
|
|
131
131
|
}
|
|
132
132
|
let watchedPath = meta.watchedPath;
|
|
@@ -8,7 +8,6 @@ Object.defineProperty(exports, "defaultExtractor", {
|
|
|
8
8
|
return defaultExtractor;
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
|
-
const _featureFlags = require("../featureFlags");
|
|
12
11
|
const _regex = /*#__PURE__*/ _interop_require_wildcard(require("./regex"));
|
|
13
12
|
function _getRequireWildcardCache(nodeInterop) {
|
|
14
13
|
if (typeof WeakMap !== "function") return null;
|
|
@@ -57,17 +56,15 @@ function defaultExtractor(context) {
|
|
|
57
56
|
/** @type {(string|string)[]} */ let results = [];
|
|
58
57
|
for (let pattern of patterns){
|
|
59
58
|
var _content_match;
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
];
|
|
59
|
+
for (let result of (_content_match = content.match(pattern)) !== null && _content_match !== void 0 ? _content_match : []){
|
|
60
|
+
results.push(clipAtBalancedParens(result));
|
|
61
|
+
}
|
|
64
62
|
}
|
|
65
|
-
return results
|
|
63
|
+
return results;
|
|
66
64
|
};
|
|
67
65
|
}
|
|
68
66
|
function* buildRegExps(context) {
|
|
69
67
|
let separator = context.tailwindConfig.separator;
|
|
70
|
-
let variantGroupingEnabled = (0, _featureFlags.flagEnabled)(context.tailwindConfig, "variantGrouping");
|
|
71
68
|
let prefix = context.tailwindConfig.prefix !== "" ? _regex.optional(_regex.pattern([
|
|
72
69
|
/-?/,
|
|
73
70
|
_regex.escape(context.tailwindConfig.prefix)
|
|
@@ -79,7 +76,7 @@ function* buildRegExps(context) {
|
|
|
79
76
|
// This is a targeted fix to continue to allow theme()
|
|
80
77
|
// with square brackets to work in arbitrary properties
|
|
81
78
|
// while fixing a problem with the regex matching too much
|
|
82
|
-
/\[[^\s:'"
|
|
79
|
+
/\[[^\s:'"`\]]+:[^\s]+?\[[^\s]+\][^\s]+?\]/,
|
|
83
80
|
// Utilities
|
|
84
81
|
_regex.pattern([
|
|
85
82
|
// Utility Name / Group Name
|
|
@@ -115,6 +112,11 @@ function* buildRegExps(context) {
|
|
|
115
112
|
/@\[[^\s"'`]+\](\/[^\s"'`]+)?/,
|
|
116
113
|
separator
|
|
117
114
|
]),
|
|
115
|
+
// With variant modifier (e.g.: group-[..]/modifier)
|
|
116
|
+
_regex.pattern([
|
|
117
|
+
/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]\/\w+/,
|
|
118
|
+
separator
|
|
119
|
+
]),
|
|
118
120
|
_regex.pattern([
|
|
119
121
|
/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]/,
|
|
120
122
|
separator
|
|
@@ -126,6 +128,11 @@ function* buildRegExps(context) {
|
|
|
126
128
|
]),
|
|
127
129
|
// With quotes allowed
|
|
128
130
|
_regex.any([
|
|
131
|
+
// With variant modifier (e.g.: group-[..]/modifier)
|
|
132
|
+
_regex.pattern([
|
|
133
|
+
/([^\s"'`\[\\]+-)?\[[^\s`]+\]\/\w+/,
|
|
134
|
+
separator
|
|
135
|
+
]),
|
|
129
136
|
_regex.pattern([
|
|
130
137
|
/([^\s"'`\[\\]+-)?\[[^\s`]+\]/,
|
|
131
138
|
separator
|
|
@@ -145,20 +152,7 @@ function* buildRegExps(context) {
|
|
|
145
152
|
// Important (optional)
|
|
146
153
|
/!?/,
|
|
147
154
|
prefix,
|
|
148
|
-
|
|
149
|
-
// Or any of those things but grouped separated by commas
|
|
150
|
-
_regex.pattern([
|
|
151
|
-
/\(/,
|
|
152
|
-
utility,
|
|
153
|
-
_regex.zeroOrMore([
|
|
154
|
-
/,/,
|
|
155
|
-
utility
|
|
156
|
-
]),
|
|
157
|
-
/\)/
|
|
158
|
-
]),
|
|
159
|
-
// Arbitrary properties, constrained utilities, arbitrary values, etc…
|
|
160
|
-
utility
|
|
161
|
-
]) : utility
|
|
155
|
+
utility
|
|
162
156
|
]);
|
|
163
157
|
}
|
|
164
158
|
// 5. Inner matches
|
|
@@ -482,6 +482,12 @@ function processApply(root, context, localCache) {
|
|
|
482
482
|
// We do *not* want to do this for user CSS that happens to be structured the same
|
|
483
483
|
let isGenerated = parent.raws.tailwind !== undefined;
|
|
484
484
|
let parentSelector = isGenerated && importantSelector && parent.selector.indexOf(importantSelector) === 0 ? parent.selector.slice(importantSelector.length) : parent.selector;
|
|
485
|
+
// If the selector becomes empty after replacing the important selector
|
|
486
|
+
// This means that it's the same as the parent selector and we don't want to replace it
|
|
487
|
+
// Otherwise we'll crash
|
|
488
|
+
if (parentSelector === "") {
|
|
489
|
+
parentSelector = parent.selector;
|
|
490
|
+
}
|
|
485
491
|
rule.selector = replaceSelector(parentSelector, rule.selector, applyCandidate);
|
|
486
492
|
// And then re-add it if it was removed
|
|
487
493
|
if (importantSelector && parentSelector !== parent.selector) {
|
|
@@ -165,12 +165,26 @@ function expandTailwindAtRules(context) {
|
|
|
165
165
|
// getClassCandidatesOxide(file, transformer(content), extractor, candidates, seen)
|
|
166
166
|
// }
|
|
167
167
|
} else {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
let
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
168
|
+
/** @type {[item: {file?: string, content?: string}, meta: {transformer: any, extractor: any}][]} */ let regexParserContent = [];
|
|
169
|
+
for (let item of context.changedContent){
|
|
170
|
+
let transformer = getTransformer(context.tailwindConfig, item.extension);
|
|
171
|
+
let extractor = getExtractor(context, item.extension);
|
|
172
|
+
regexParserContent.push([
|
|
173
|
+
item,
|
|
174
|
+
{
|
|
175
|
+
transformer,
|
|
176
|
+
extractor
|
|
177
|
+
}
|
|
178
|
+
]);
|
|
179
|
+
}
|
|
180
|
+
const BATCH_SIZE = 500;
|
|
181
|
+
for(let i = 0; i < regexParserContent.length; i += BATCH_SIZE){
|
|
182
|
+
let batch = regexParserContent.slice(i, i + BATCH_SIZE);
|
|
183
|
+
await Promise.all(batch.map(async ([{ file , content }, { transformer , extractor }])=>{
|
|
184
|
+
content = file ? await _fs.default.promises.readFile(file, "utf8") : content;
|
|
185
|
+
getClassCandidates(transformer(content), extractor, candidates, seen);
|
|
186
|
+
}));
|
|
187
|
+
}
|
|
174
188
|
}
|
|
175
189
|
env.DEBUG && console.timeEnd("Reading changed files");
|
|
176
190
|
// ---
|
package/lib/lib/generateRules.js
CHANGED
|
@@ -500,7 +500,9 @@ function extractArbitraryProperty(classCandidate, context) {
|
|
|
500
500
|
if (!(0, _isSyntacticallyValidPropertyValue.default)(value)) {
|
|
501
501
|
return null;
|
|
502
502
|
}
|
|
503
|
-
let normalized = (0, _dataTypes.normalize)(value
|
|
503
|
+
let normalized = (0, _dataTypes.normalize)(value, {
|
|
504
|
+
property
|
|
505
|
+
});
|
|
504
506
|
if (!isParsableCssValue(property, normalized)) {
|
|
505
507
|
return null;
|
|
506
508
|
}
|
|
@@ -578,7 +580,7 @@ function* recordCandidates(matches, classCandidate) {
|
|
|
578
580
|
yield match;
|
|
579
581
|
}
|
|
580
582
|
}
|
|
581
|
-
function* resolveMatches(candidate, context
|
|
583
|
+
function* resolveMatches(candidate, context) {
|
|
582
584
|
let separator = context.tailwindConfig.separator;
|
|
583
585
|
let [classCandidate, ...variants] = splitWithSeparator(candidate, separator).reverse();
|
|
584
586
|
let important = false;
|
|
@@ -586,14 +588,6 @@ function* resolveMatches(candidate, context, original = candidate) {
|
|
|
586
588
|
important = true;
|
|
587
589
|
classCandidate = classCandidate.slice(1);
|
|
588
590
|
}
|
|
589
|
-
if ((0, _featureFlags.flagEnabled)(context.tailwindConfig, "variantGrouping")) {
|
|
590
|
-
if (classCandidate.startsWith("(") && classCandidate.endsWith(")")) {
|
|
591
|
-
let base = variants.slice().reverse().join(separator);
|
|
592
|
-
for (let part of (0, _splitAtTopLevelOnly.splitAtTopLevelOnly)(classCandidate.slice(1, -1), ",")){
|
|
593
|
-
yield* resolveMatches(base + separator + part, context, original);
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
591
|
// TODO: Reintroduce this in ways that doesn't break on false positives
|
|
598
592
|
// function sortAgainst(toSort, against) {
|
|
599
593
|
// return toSort.slice().sort((a, z) => {
|
|
@@ -753,8 +747,7 @@ function* resolveMatches(candidate, context, original = candidate) {
|
|
|
753
747
|
// Apply final format selector
|
|
754
748
|
match = applyFinalFormat(match, {
|
|
755
749
|
context,
|
|
756
|
-
candidate
|
|
757
|
-
original
|
|
750
|
+
candidate
|
|
758
751
|
});
|
|
759
752
|
// Skip rules with invalid selectors
|
|
760
753
|
// This will cause the candidate to be added to the "not class"
|
|
@@ -766,7 +759,7 @@ function* resolveMatches(candidate, context, original = candidate) {
|
|
|
766
759
|
}
|
|
767
760
|
}
|
|
768
761
|
}
|
|
769
|
-
function applyFinalFormat(match, { context , candidate
|
|
762
|
+
function applyFinalFormat(match, { context , candidate }) {
|
|
770
763
|
if (!match[0].collectedFormats) {
|
|
771
764
|
return match;
|
|
772
765
|
}
|
|
@@ -799,10 +792,17 @@ function applyFinalFormat(match, { context , candidate , original }) {
|
|
|
799
792
|
return;
|
|
800
793
|
}
|
|
801
794
|
try {
|
|
802
|
-
|
|
803
|
-
candidate
|
|
795
|
+
let selector = (0, _formatVariantSelector.finalizeSelector)(rule.selector, finalFormat, {
|
|
796
|
+
candidate,
|
|
804
797
|
context
|
|
805
798
|
});
|
|
799
|
+
// Finalize Selector determined that this candidate is irrelevant
|
|
800
|
+
// TODO: This elimination should happen earlier so this never happens
|
|
801
|
+
if (selector === null) {
|
|
802
|
+
rule.remove();
|
|
803
|
+
return;
|
|
804
|
+
}
|
|
805
|
+
rule.selector = selector;
|
|
806
806
|
} catch {
|
|
807
807
|
// If this selector is invalid we also want to skip it
|
|
808
808
|
// But it's likely that being invalid here means there's a bug in a plugin rather than too loosely matching content
|
|
@@ -843,7 +843,7 @@ function getImportantStrategy(important) {
|
|
|
843
843
|
};
|
|
844
844
|
}
|
|
845
845
|
}
|
|
846
|
-
function generateRules(candidates, context) {
|
|
846
|
+
function generateRules(candidates, context, isSorting = false) {
|
|
847
847
|
let allRules = [];
|
|
848
848
|
let strategy = getImportantStrategy(context.tailwindConfig.important);
|
|
849
849
|
for (let candidate of candidates){
|
|
@@ -874,9 +874,11 @@ function generateRules(candidates, context) {
|
|
|
874
874
|
container.walkRules(strategy);
|
|
875
875
|
rule = container.nodes[0];
|
|
876
876
|
}
|
|
877
|
+
// Note: We have to clone rules during sorting
|
|
878
|
+
// so we eliminate some shared mutable state
|
|
877
879
|
let newEntry = [
|
|
878
880
|
sort,
|
|
879
|
-
rule
|
|
881
|
+
isSorting ? rule.clone() : rule
|
|
880
882
|
];
|
|
881
883
|
rules.add(newEntry);
|
|
882
884
|
context.ruleCache.add(newEntry);
|
|
@@ -201,39 +201,41 @@ function getClasses(selector, mutate) {
|
|
|
201
201
|
});
|
|
202
202
|
return parser.transformSync(selector);
|
|
203
203
|
}
|
|
204
|
+
/**
|
|
205
|
+
* Ignore everything inside a :not(...). This allows you to write code like
|
|
206
|
+
* `div:not(.foo)`. If `.foo` is never found in your code, then we used to
|
|
207
|
+
* not generated it. But now we will ignore everything inside a `:not`, so
|
|
208
|
+
* that it still gets generated.
|
|
209
|
+
*
|
|
210
|
+
* @param {selectorParser.Root} selectors
|
|
211
|
+
*/ function ignoreNot(selectors) {
|
|
212
|
+
selectors.walkPseudos((pseudo)=>{
|
|
213
|
+
if (pseudo.value === ":not") {
|
|
214
|
+
pseudo.remove();
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
}
|
|
204
218
|
function extractCandidates(node, state = {
|
|
205
219
|
containsNonOnDemandable: false
|
|
206
220
|
}, depth = 0) {
|
|
207
221
|
let classes = [];
|
|
208
|
-
|
|
222
|
+
let selectors = [];
|
|
209
223
|
if (node.type === "rule") {
|
|
210
|
-
//
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
//
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
224
|
+
// Handle normal rules
|
|
225
|
+
selectors.push(...node.selectors);
|
|
226
|
+
} else if (node.type === "atrule") {
|
|
227
|
+
// Handle at-rules (which contains nested rules)
|
|
228
|
+
node.walkRules((rule)=>selectors.push(...rule.selectors));
|
|
229
|
+
}
|
|
230
|
+
for (let selector of selectors){
|
|
231
|
+
let classCandidates = getClasses(selector, ignoreNot);
|
|
232
|
+
// At least one of the selectors contains non-"on-demandable" candidates.
|
|
233
|
+
if (classCandidates.length === 0) {
|
|
234
|
+
state.containsNonOnDemandable = true;
|
|
220
235
|
}
|
|
221
|
-
for (let
|
|
222
|
-
|
|
223
|
-
// At least one of the selectors contains non-"on-demandable" candidates.
|
|
224
|
-
if (classCandidates.length === 0) {
|
|
225
|
-
state.containsNonOnDemandable = true;
|
|
226
|
-
}
|
|
227
|
-
for (let classCandidate of classCandidates){
|
|
228
|
-
classes.push(classCandidate);
|
|
229
|
-
}
|
|
236
|
+
for (let classCandidate of classCandidates){
|
|
237
|
+
classes.push(classCandidate);
|
|
230
238
|
}
|
|
231
|
-
} else if (node.type === "atrule") {
|
|
232
|
-
node.walkRules((rule)=>{
|
|
233
|
-
for (let classCandidate of rule.selectors.flatMap((selector)=>getClasses(selector))){
|
|
234
|
-
classes.push(classCandidate);
|
|
235
|
-
}
|
|
236
|
-
});
|
|
237
239
|
}
|
|
238
240
|
if (depth === 0) {
|
|
239
241
|
return [
|
|
@@ -927,7 +929,7 @@ function registerPlugins(plugins, context) {
|
|
|
927
929
|
]));
|
|
928
930
|
// Sort all classes in order
|
|
929
931
|
// Non-tailwind classes won't be generated and will be left as `null`
|
|
930
|
-
let rules = (0, _generateRules.generateRules)(new Set(sorted), context);
|
|
932
|
+
let rules = (0, _generateRules.generateRules)(new Set(sorted), context, true);
|
|
931
933
|
rules = context.offsets.sort(rules);
|
|
932
934
|
let idx = BigInt(parasiteUtilities.length);
|
|
933
935
|
for (const [, rule] of rules){
|
|
@@ -244,9 +244,9 @@ async function createProcessor(args, cliConfigPath) {
|
|
|
244
244
|
let tailwindPlugin = ()=>{
|
|
245
245
|
return {
|
|
246
246
|
postcssPlugin: "tailwindcss",
|
|
247
|
-
Once (root, { result }) {
|
|
247
|
+
async Once (root, { result }) {
|
|
248
248
|
_sharedState.env.DEBUG && console.time("Compiling CSS");
|
|
249
|
-
(0, _processTailwindFeatures.default)(({ createContext })=>{
|
|
249
|
+
await (0, _processTailwindFeatures.default)(({ createContext })=>{
|
|
250
250
|
console.error();
|
|
251
251
|
console.error("Rebuilding...");
|
|
252
252
|
return ()=>{
|
package/lib/util/color.js
CHANGED
|
@@ -27,7 +27,7 @@ let SHORT_HEX = /^#([a-f\d])([a-f\d])([a-f\d])([a-f\d])?$/i;
|
|
|
27
27
|
let VALUE = /(?:\d+|\d*\.\d+)%?/;
|
|
28
28
|
let SEP = /(?:\s*,\s*|\s+)/;
|
|
29
29
|
let ALPHA_SEP = /\s*[,/]\s*/;
|
|
30
|
-
let CUSTOM_PROPERTY = /var\(--(?:[^ )]*?)\)/;
|
|
30
|
+
let CUSTOM_PROPERTY = /var\(--(?:[^ )]*?)(?:,(?:[^ )]*?|var\(--[^ )]*?\)))?\)/;
|
|
31
31
|
let RGB = new RegExp(`^(rgba?)\\(\\s*(${VALUE.source}|${CUSTOM_PROPERTY.source})(?:${SEP.source}(${VALUE.source}|${CUSTOM_PROPERTY.source}))?(?:${SEP.source}(${VALUE.source}|${CUSTOM_PROPERTY.source}))?(?:${ALPHA_SEP.source}(${VALUE.source}|${CUSTOM_PROPERTY.source}))?\\s*\\)$`);
|
|
32
32
|
let HSL = new RegExp(`^(hsla?)\\(\\s*((?:${VALUE.source})(?:deg|rad|grad|turn)?|${CUSTOM_PROPERTY.source})(?:${SEP.source}(${VALUE.source}|${CUSTOM_PROPERTY.source}))?(?:${SEP.source}(${VALUE.source}|${CUSTOM_PROPERTY.source}))?(?:${ALPHA_SEP.source}(${VALUE.source}|${CUSTOM_PROPERTY.source}))?\\s*\\)$`);
|
|
33
33
|
function parseColor(value, { loose =false } = {}) {
|
package/lib/util/dataTypes.js
CHANGED
|
@@ -68,10 +68,30 @@ let cssFunctions = [
|
|
|
68
68
|
function isCSSFunction(value) {
|
|
69
69
|
return cssFunctions.some((fn)=>new RegExp(`^${fn}\\(.*\\)`).test(value));
|
|
70
70
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
71
|
+
// These properties accept a `<dashed-ident>` as one of the values. This means that you can use them
|
|
72
|
+
// as: `timeline-scope: --tl;`
|
|
73
|
+
//
|
|
74
|
+
// Without the `var(--tl)`, in these cases we don't want to normalize the value, and you should add
|
|
75
|
+
// the `var()` yourself.
|
|
76
|
+
//
|
|
77
|
+
// More info:
|
|
78
|
+
// - https://drafts.csswg.org/scroll-animations/#propdef-timeline-scope
|
|
79
|
+
// - https://developer.mozilla.org/en-US/docs/Web/CSS/timeline-scope#dashed-ident
|
|
80
|
+
//
|
|
81
|
+
const AUTO_VAR_INJECTION_EXCEPTIONS = new Set([
|
|
82
|
+
// Concrete properties
|
|
83
|
+
"scroll-timeline-name",
|
|
84
|
+
"timeline-scope",
|
|
85
|
+
"view-timeline-name",
|
|
86
|
+
"font-palette",
|
|
87
|
+
// Shorthand properties
|
|
88
|
+
"scroll-timeline",
|
|
89
|
+
"animation-timeline",
|
|
90
|
+
"view-timeline"
|
|
91
|
+
]);
|
|
92
|
+
function normalize(value, context = null, isRoot = true) {
|
|
93
|
+
let isVarException = context && AUTO_VAR_INJECTION_EXCEPTIONS.has(context.property);
|
|
94
|
+
if (value.startsWith("--") && !isVarException) {
|
|
75
95
|
return `var(${value})`;
|
|
76
96
|
}
|
|
77
97
|
// Keep raw strings if it starts with `url(`
|
|
@@ -80,7 +100,7 @@ function normalize(value, isRoot = true) {
|
|
|
80
100
|
if (/^url\(.*?\)$/.test(part)) {
|
|
81
101
|
return part;
|
|
82
102
|
}
|
|
83
|
-
return normalize(part, false);
|
|
103
|
+
return normalize(part, context, false);
|
|
84
104
|
}).join("");
|
|
85
105
|
}
|
|
86
106
|
// Convert `_` to ` `, except for escaped underscores `\_`
|
|
@@ -99,12 +119,92 @@ function normalize(value, isRoot = true) {
|
|
|
99
119
|
* @param {string} value
|
|
100
120
|
* @returns {string}
|
|
101
121
|
*/ function normalizeMathOperatorSpacing(value) {
|
|
122
|
+
let preventFormattingInFunctions = [
|
|
123
|
+
"theme"
|
|
124
|
+
];
|
|
125
|
+
let preventFormattingKeywords = [
|
|
126
|
+
"min-content",
|
|
127
|
+
"max-content",
|
|
128
|
+
"fit-content",
|
|
129
|
+
// Env
|
|
130
|
+
"safe-area-inset-top",
|
|
131
|
+
"safe-area-inset-right",
|
|
132
|
+
"safe-area-inset-bottom",
|
|
133
|
+
"safe-area-inset-left",
|
|
134
|
+
"titlebar-area-x",
|
|
135
|
+
"titlebar-area-y",
|
|
136
|
+
"titlebar-area-width",
|
|
137
|
+
"titlebar-area-height",
|
|
138
|
+
"keyboard-inset-top",
|
|
139
|
+
"keyboard-inset-right",
|
|
140
|
+
"keyboard-inset-bottom",
|
|
141
|
+
"keyboard-inset-left",
|
|
142
|
+
"keyboard-inset-width",
|
|
143
|
+
"keyboard-inset-height"
|
|
144
|
+
];
|
|
102
145
|
return value.replace(/(calc|min|max|clamp)\(.+\)/g, (match)=>{
|
|
103
|
-
let
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
return
|
|
107
|
-
}
|
|
146
|
+
let result = "";
|
|
147
|
+
function lastChar() {
|
|
148
|
+
let char = result.trimEnd();
|
|
149
|
+
return char[char.length - 1];
|
|
150
|
+
}
|
|
151
|
+
for(let i = 0; i < match.length; i++){
|
|
152
|
+
function peek(word) {
|
|
153
|
+
return word.split("").every((char, j)=>match[i + j] === char);
|
|
154
|
+
}
|
|
155
|
+
function consumeUntil(chars) {
|
|
156
|
+
let minIndex = Infinity;
|
|
157
|
+
for (let char of chars){
|
|
158
|
+
let index = match.indexOf(char, i);
|
|
159
|
+
if (index !== -1 && index < minIndex) {
|
|
160
|
+
minIndex = index;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
let result = match.slice(i, minIndex);
|
|
164
|
+
i += result.length - 1;
|
|
165
|
+
return result;
|
|
166
|
+
}
|
|
167
|
+
let char = match[i];
|
|
168
|
+
// Handle `var(--variable)`
|
|
169
|
+
if (peek("var")) {
|
|
170
|
+
// When we consume until `)`, then we are dealing with this scenario:
|
|
171
|
+
// `var(--example)`
|
|
172
|
+
//
|
|
173
|
+
// When we consume until `,`, then we are dealing with this scenario:
|
|
174
|
+
// `var(--example, 1rem)`
|
|
175
|
+
//
|
|
176
|
+
// In this case we do want to "format", the default value as well
|
|
177
|
+
result += consumeUntil([
|
|
178
|
+
")",
|
|
179
|
+
","
|
|
180
|
+
]);
|
|
181
|
+
} else if (preventFormattingKeywords.some((keyword)=>peek(keyword))) {
|
|
182
|
+
let keyword = preventFormattingKeywords.find((keyword)=>peek(keyword));
|
|
183
|
+
result += keyword;
|
|
184
|
+
i += keyword.length - 1;
|
|
185
|
+
} else if (preventFormattingInFunctions.some((fn)=>peek(fn))) {
|
|
186
|
+
result += consumeUntil([
|
|
187
|
+
")"
|
|
188
|
+
]);
|
|
189
|
+
} else if ([
|
|
190
|
+
"+",
|
|
191
|
+
"-",
|
|
192
|
+
"*",
|
|
193
|
+
"/"
|
|
194
|
+
].includes(char) && ![
|
|
195
|
+
"(",
|
|
196
|
+
"+",
|
|
197
|
+
"-",
|
|
198
|
+
"*",
|
|
199
|
+
"/"
|
|
200
|
+
].includes(lastChar())) {
|
|
201
|
+
result += ` ${char} `;
|
|
202
|
+
} else {
|
|
203
|
+
result += char;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
// Simplify multiple spaces
|
|
207
|
+
return result.replace(/\s+/g, " ");
|
|
108
208
|
});
|
|
109
209
|
}
|
|
110
210
|
function url(value) {
|
|
@@ -27,6 +27,7 @@ const _unesc = /*#__PURE__*/ _interop_require_default(require("postcss-selector-
|
|
|
27
27
|
const _escapeClassName = /*#__PURE__*/ _interop_require_default(require("../util/escapeClassName"));
|
|
28
28
|
const _prefixSelector = /*#__PURE__*/ _interop_require_default(require("../util/prefixSelector"));
|
|
29
29
|
const _pseudoElements = require("./pseudoElements");
|
|
30
|
+
const _splitAtTopLevelOnly = require("./splitAtTopLevelOnly");
|
|
30
31
|
function _interop_require_default(obj) {
|
|
31
32
|
return obj && obj.__esModule ? obj : {
|
|
32
33
|
default: obj
|
|
@@ -138,7 +139,7 @@ function finalizeSelector(current, formats, { context , candidate , base }) {
|
|
|
138
139
|
// │ │ │ ╰── We will not split here
|
|
139
140
|
// ╰──┴─────┴─────────────── We will split here
|
|
140
141
|
//
|
|
141
|
-
base = base !== null && base !== void 0 ? base :
|
|
142
|
+
base = base !== null && base !== void 0 ? base : (0, _splitAtTopLevelOnly.splitAtTopLevelOnly)(candidate, separator).pop();
|
|
142
143
|
// Parse the selector into an AST
|
|
143
144
|
let selector = (0, _postcssselectorparser.default)().astSync(current);
|
|
144
145
|
// Normalize escaped classes, e.g.:
|
|
@@ -159,6 +160,12 @@ function finalizeSelector(current, formats, { context , candidate , base }) {
|
|
|
159
160
|
});
|
|
160
161
|
// Remove extraneous selectors that do not include the base candidate
|
|
161
162
|
selector.each((sel)=>eliminateIrrelevantSelectors(sel, base));
|
|
163
|
+
// If ffter eliminating irrelevant selectors, we end up with nothing
|
|
164
|
+
// Then the whole "rule" this is associated with does not need to exist
|
|
165
|
+
// We use `null` as a marker value for that case
|
|
166
|
+
if (selector.length === 0) {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
162
169
|
// If there are no formats that means there were no variants added to the candidate
|
|
163
170
|
// so we can just return the selector as-is
|
|
164
171
|
let formatAst = Array.isArray(formats) ? formatVariantSelector(formats, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tailwindcss",
|
|
3
|
-
"version": "3.3.
|
|
3
|
+
"version": "3.3.5",
|
|
4
4
|
"description": "A utility-first CSS framework for rapidly building custom user interfaces.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -58,8 +58,8 @@
|
|
|
58
58
|
"eslint": "^8.39.0",
|
|
59
59
|
"eslint-config-prettier": "^8.8.0",
|
|
60
60
|
"eslint-plugin-prettier": "^4.2.1",
|
|
61
|
-
"jest": "^29.
|
|
62
|
-
"jest-diff": "^29.
|
|
61
|
+
"jest": "^29.6.0",
|
|
62
|
+
"jest-diff": "^29.6.0",
|
|
63
63
|
"lightningcss": "1.18.0",
|
|
64
64
|
"prettier": "^2.8.8",
|
|
65
65
|
"rimraf": "^5.0.0",
|
|
@@ -72,10 +72,10 @@
|
|
|
72
72
|
"chokidar": "^3.5.3",
|
|
73
73
|
"didyoumean": "^1.2.2",
|
|
74
74
|
"dlv": "^1.1.3",
|
|
75
|
-
"fast-glob": "^3.
|
|
75
|
+
"fast-glob": "^3.3.0",
|
|
76
76
|
"glob-parent": "^6.0.2",
|
|
77
77
|
"is-glob": "^4.0.3",
|
|
78
|
-
"jiti": "^1.
|
|
78
|
+
"jiti": "^1.19.1",
|
|
79
79
|
"lilconfig": "^2.1.0",
|
|
80
80
|
"micromatch": "^4.0.5",
|
|
81
81
|
"normalize-path": "^3.0.0",
|