tailwindcss 3.4.5 → 3.4.7
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 +20 -1
- package/lib/corePlugins.js +6 -6
- package/lib/lib/defaultExtractor.js +3 -1
- package/lib/util/applyImportantSelector.js +5 -3
- package/lib/util/dataTypes.js +22 -0
- package/package.json +1 -1
- package/src/corePlugins.js +15 -11
- package/src/lib/defaultExtractor.js +4 -1
- package/src/util/applyImportantSelector.js +5 -6
- package/src/util/dataTypes.js +28 -0
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
9
9
|
|
|
10
10
|
- Nothing yet!
|
|
11
11
|
|
|
12
|
+
## [3.4.7] - 2024-07-25
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- Fix class detection in Slim templates with attached attributes and ID ([#14019](https://github.com/tailwindlabs/tailwindcss/pull/14019))
|
|
17
|
+
- Ensure attribute values in `data-*` and `aria-*` modifiers are always quoted in the generated CSS ([#14037](https://github.com/tailwindlabs/tailwindcss/pull/14037))
|
|
18
|
+
|
|
19
|
+
## [3.4.6] - 2024-07-16
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- Fix detection of some utilities in Slim/Pug templates ([#14006](https://github.com/tailwindlabs/tailwindcss/pull/14006))
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- Loosen `:is()` wrapping rules when using an important selector ([#13900](https://github.com/tailwindlabs/tailwindcss/pull/13900))
|
|
28
|
+
|
|
12
29
|
## [3.4.5] - 2024-07-15
|
|
13
30
|
|
|
14
31
|
### Fixed
|
|
@@ -2395,7 +2412,9 @@ No release notes
|
|
|
2395
2412
|
|
|
2396
2413
|
- Everything!
|
|
2397
2414
|
|
|
2398
|
-
[unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.
|
|
2415
|
+
[unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.7...HEAD
|
|
2416
|
+
[3.4.7]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.6...v3.4.7
|
|
2417
|
+
[3.4.6]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.5...v3.4.6
|
|
2399
2418
|
[3.4.5]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.4...v3.4.5
|
|
2400
2419
|
[3.4.4]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.3...v3.4.4
|
|
2401
2420
|
[3.4.3]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.2...v3.4.3
|
package/lib/corePlugins.js
CHANGED
|
@@ -482,29 +482,29 @@ let variantPlugins = {
|
|
|
482
482
|
},
|
|
483
483
|
ariaVariants: ({ matchVariant , theme })=>{
|
|
484
484
|
var _theme;
|
|
485
|
-
matchVariant("aria", (value)=>`&[aria-${(0, _dataTypes.normalize)(value)}]`, {
|
|
485
|
+
matchVariant("aria", (value)=>`&[aria-${(0, _dataTypes.normalizeAttributeSelectors)((0, _dataTypes.normalize)(value))}]`, {
|
|
486
486
|
values: (_theme = theme("aria")) !== null && _theme !== void 0 ? _theme : {}
|
|
487
487
|
});
|
|
488
488
|
var _theme1;
|
|
489
|
-
matchVariant("group-aria", (value, { modifier })=>modifier ? `:merge(.group\\/${modifier})[aria-${(0, _dataTypes.normalize)(value)}] &` : `:merge(.group)[aria-${(0, _dataTypes.normalize)(value)}] &`, {
|
|
489
|
+
matchVariant("group-aria", (value, { modifier })=>modifier ? `:merge(.group\\/${modifier})[aria-${(0, _dataTypes.normalizeAttributeSelectors)((0, _dataTypes.normalize)(value))}] &` : `:merge(.group)[aria-${(0, _dataTypes.normalizeAttributeSelectors)((0, _dataTypes.normalize)(value))}] &`, {
|
|
490
490
|
values: (_theme1 = theme("aria")) !== null && _theme1 !== void 0 ? _theme1 : {}
|
|
491
491
|
});
|
|
492
492
|
var _theme2;
|
|
493
|
-
matchVariant("peer-aria", (value, { modifier })=>modifier ? `:merge(.peer\\/${modifier})[aria-${(0, _dataTypes.normalize)(value)}] ~ &` : `:merge(.peer)[aria-${(0, _dataTypes.normalize)(value)}] ~ &`, {
|
|
493
|
+
matchVariant("peer-aria", (value, { modifier })=>modifier ? `:merge(.peer\\/${modifier})[aria-${(0, _dataTypes.normalizeAttributeSelectors)((0, _dataTypes.normalize)(value))}] ~ &` : `:merge(.peer)[aria-${(0, _dataTypes.normalizeAttributeSelectors)((0, _dataTypes.normalize)(value))}] ~ &`, {
|
|
494
494
|
values: (_theme2 = theme("aria")) !== null && _theme2 !== void 0 ? _theme2 : {}
|
|
495
495
|
});
|
|
496
496
|
},
|
|
497
497
|
dataVariants: ({ matchVariant , theme })=>{
|
|
498
498
|
var _theme;
|
|
499
|
-
matchVariant("data", (value)=>`&[data-${(0, _dataTypes.normalize)(value)}]`, {
|
|
499
|
+
matchVariant("data", (value)=>`&[data-${(0, _dataTypes.normalizeAttributeSelectors)((0, _dataTypes.normalize)(value))}]`, {
|
|
500
500
|
values: (_theme = theme("data")) !== null && _theme !== void 0 ? _theme : {}
|
|
501
501
|
});
|
|
502
502
|
var _theme1;
|
|
503
|
-
matchVariant("group-data", (value, { modifier })=>modifier ? `:merge(.group\\/${modifier})[data-${(0, _dataTypes.normalize)(value)}] &` : `:merge(.group)[data-${(0, _dataTypes.normalize)(value)}] &`, {
|
|
503
|
+
matchVariant("group-data", (value, { modifier })=>modifier ? `:merge(.group\\/${modifier})[data-${(0, _dataTypes.normalizeAttributeSelectors)((0, _dataTypes.normalize)(value))}] &` : `:merge(.group)[data-${(0, _dataTypes.normalizeAttributeSelectors)((0, _dataTypes.normalize)(value))}] &`, {
|
|
504
504
|
values: (_theme1 = theme("data")) !== null && _theme1 !== void 0 ? _theme1 : {}
|
|
505
505
|
});
|
|
506
506
|
var _theme2;
|
|
507
|
-
matchVariant("peer-data", (value, { modifier })=>modifier ? `:merge(.peer\\/${modifier})[data-${(0, _dataTypes.normalize)(value)}] ~ &` : `:merge(.peer)[data-${(0, _dataTypes.normalize)(value)}] ~ &`, {
|
|
507
|
+
matchVariant("peer-data", (value, { modifier })=>modifier ? `:merge(.peer\\/${modifier})[data-${(0, _dataTypes.normalizeAttributeSelectors)((0, _dataTypes.normalize)(value))}] ~ &` : `:merge(.peer)[data-${(0, _dataTypes.normalizeAttributeSelectors)((0, _dataTypes.normalize)(value))}] ~ &`, {
|
|
508
508
|
values: (_theme2 = theme("data")) !== null && _theme2 !== void 0 ? _theme2 : {}
|
|
509
509
|
});
|
|
510
510
|
},
|
|
@@ -74,7 +74,7 @@ function defaultExtractor(context) {
|
|
|
74
74
|
// If the next segment is a number, discard both, for example seeing
|
|
75
75
|
// `px-1` and `5` means the real candidate was `px-1.5` which is already
|
|
76
76
|
// captured.
|
|
77
|
-
let next =
|
|
77
|
+
let next = Number(segments[idx + 1]);
|
|
78
78
|
if (isNaN(next)) {
|
|
79
79
|
results.push(segment);
|
|
80
80
|
} else {
|
|
@@ -191,6 +191,8 @@ function* buildRegExps(context) {
|
|
|
191
191
|
utility
|
|
192
192
|
]);
|
|
193
193
|
}
|
|
194
|
+
// 5. Inner matches
|
|
195
|
+
yield /[^<>"'`\s.(){}[\]#=%$][^<>"'`\s(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g;
|
|
194
196
|
}
|
|
195
197
|
// We want to capture any "special" characters
|
|
196
198
|
// AND the characters immediately following them (if there is one)
|
|
@@ -18,9 +18,11 @@ function _interop_require_default(obj) {
|
|
|
18
18
|
function applyImportantSelector(selector, important) {
|
|
19
19
|
let sel = (0, _postcssselectorparser.default)().astSync(selector);
|
|
20
20
|
sel.each((sel)=>{
|
|
21
|
-
//
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
// For nesting, we only need to wrap a selector with :is() if it has a top-level combinator,
|
|
22
|
+
// e.g. `.dark .text-white`, to be independent of DOM order. Any other selector, including
|
|
23
|
+
// combinators inside of pseudos like `:where()`, are ok to nest.
|
|
24
|
+
let shouldWrap = sel.nodes.some((node)=>node.type === "combinator");
|
|
25
|
+
if (shouldWrap) {
|
|
24
26
|
sel.nodes = [
|
|
25
27
|
_postcssselectorparser.default.pseudo({
|
|
26
28
|
value: ":is",
|
package/lib/util/dataTypes.js
CHANGED
|
@@ -12,6 +12,9 @@ _export(exports, {
|
|
|
12
12
|
normalize: function() {
|
|
13
13
|
return normalize;
|
|
14
14
|
},
|
|
15
|
+
normalizeAttributeSelectors: function() {
|
|
16
|
+
return normalizeAttributeSelectors;
|
|
17
|
+
},
|
|
15
18
|
url: function() {
|
|
16
19
|
return url;
|
|
17
20
|
},
|
|
@@ -118,6 +121,25 @@ function normalize(value, context = null, isRoot = true) {
|
|
|
118
121
|
value = normalizeMathOperatorSpacing(value);
|
|
119
122
|
return value;
|
|
120
123
|
}
|
|
124
|
+
function normalizeAttributeSelectors(value) {
|
|
125
|
+
// Wrap values in attribute selectors with quotes
|
|
126
|
+
if (value.includes("=")) {
|
|
127
|
+
value = value.replace(/(=.*)/g, (_fullMatch, match)=>{
|
|
128
|
+
if (match[1] === "'" || match[1] === '"') {
|
|
129
|
+
return match;
|
|
130
|
+
}
|
|
131
|
+
// Handle regex flags on unescaped values
|
|
132
|
+
if (match.length > 2) {
|
|
133
|
+
let trailingCharacter = match[match.length - 1];
|
|
134
|
+
if (match[match.length - 2] === " " && (trailingCharacter === "i" || trailingCharacter === "I" || trailingCharacter === "s" || trailingCharacter === "S")) {
|
|
135
|
+
return `="${match.slice(1, -2)}" ${match[match.length - 1]}`;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return `="${match.slice(1)}"`;
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
return value;
|
|
142
|
+
}
|
|
121
143
|
/**
|
|
122
144
|
* Add spaces around operators inside math functions
|
|
123
145
|
* like calc() that do not follow an operator, '(', or `,`.
|
package/package.json
CHANGED
package/src/corePlugins.js
CHANGED
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
import { formatBoxShadowValue, parseBoxShadowValue } from './util/parseBoxShadowValue'
|
|
22
22
|
import { removeAlphaVariables } from './util/removeAlphaVariables'
|
|
23
23
|
import { flagEnabled } from './featureFlags'
|
|
24
|
-
import { normalize } from './util/dataTypes'
|
|
24
|
+
import { normalize, normalizeAttributeSelectors } from './util/dataTypes'
|
|
25
25
|
import { INTERNAL_FEATURES } from './lib/setupContextUtils'
|
|
26
26
|
|
|
27
27
|
export let variantPlugins = {
|
|
@@ -472,41 +472,45 @@ export let variantPlugins = {
|
|
|
472
472
|
},
|
|
473
473
|
|
|
474
474
|
ariaVariants: ({ matchVariant, theme }) => {
|
|
475
|
-
matchVariant('aria', (value) => `&[aria-${normalize(value)}]`, {
|
|
475
|
+
matchVariant('aria', (value) => `&[aria-${normalizeAttributeSelectors(normalize(value))}]`, {
|
|
476
|
+
values: theme('aria') ?? {},
|
|
477
|
+
})
|
|
476
478
|
matchVariant(
|
|
477
479
|
'group-aria',
|
|
478
480
|
(value, { modifier }) =>
|
|
479
481
|
modifier
|
|
480
|
-
? `:merge(.group\\/${modifier})[aria-${normalize(value)}] &`
|
|
481
|
-
: `:merge(.group)[aria-${normalize(value)}] &`,
|
|
482
|
+
? `:merge(.group\\/${modifier})[aria-${normalizeAttributeSelectors(normalize(value))}] &`
|
|
483
|
+
: `:merge(.group)[aria-${normalizeAttributeSelectors(normalize(value))}] &`,
|
|
482
484
|
{ values: theme('aria') ?? {} }
|
|
483
485
|
)
|
|
484
486
|
matchVariant(
|
|
485
487
|
'peer-aria',
|
|
486
488
|
(value, { modifier }) =>
|
|
487
489
|
modifier
|
|
488
|
-
? `:merge(.peer\\/${modifier})[aria-${normalize(value)}] ~ &`
|
|
489
|
-
: `:merge(.peer)[aria-${normalize(value)}] ~ &`,
|
|
490
|
+
? `:merge(.peer\\/${modifier})[aria-${normalizeAttributeSelectors(normalize(value))}] ~ &`
|
|
491
|
+
: `:merge(.peer)[aria-${normalizeAttributeSelectors(normalize(value))}] ~ &`,
|
|
490
492
|
{ values: theme('aria') ?? {} }
|
|
491
493
|
)
|
|
492
494
|
},
|
|
493
495
|
|
|
494
496
|
dataVariants: ({ matchVariant, theme }) => {
|
|
495
|
-
matchVariant('data', (value) => `&[data-${normalize(value)}]`, {
|
|
497
|
+
matchVariant('data', (value) => `&[data-${normalizeAttributeSelectors(normalize(value))}]`, {
|
|
498
|
+
values: theme('data') ?? {},
|
|
499
|
+
})
|
|
496
500
|
matchVariant(
|
|
497
501
|
'group-data',
|
|
498
502
|
(value, { modifier }) =>
|
|
499
503
|
modifier
|
|
500
|
-
? `:merge(.group\\/${modifier})[data-${normalize(value)}] &`
|
|
501
|
-
: `:merge(.group)[data-${normalize(value)}] &`,
|
|
504
|
+
? `:merge(.group\\/${modifier})[data-${normalizeAttributeSelectors(normalize(value))}] &`
|
|
505
|
+
: `:merge(.group)[data-${normalizeAttributeSelectors(normalize(value))}] &`,
|
|
502
506
|
{ values: theme('data') ?? {} }
|
|
503
507
|
)
|
|
504
508
|
matchVariant(
|
|
505
509
|
'peer-data',
|
|
506
510
|
(value, { modifier }) =>
|
|
507
511
|
modifier
|
|
508
|
-
? `:merge(.peer\\/${modifier})[data-${normalize(value)}] ~ &`
|
|
509
|
-
: `:merge(.peer)[data-${normalize(value)}] ~ &`,
|
|
512
|
+
? `:merge(.peer\\/${modifier})[data-${normalizeAttributeSelectors(normalize(value))}] ~ &`
|
|
513
|
+
: `:merge(.peer)[data-${normalizeAttributeSelectors(normalize(value))}] ~ &`,
|
|
510
514
|
{ values: theme('data') ?? {} }
|
|
511
515
|
)
|
|
512
516
|
},
|
|
@@ -32,7 +32,7 @@ export function defaultExtractor(context) {
|
|
|
32
32
|
// If the next segment is a number, discard both, for example seeing
|
|
33
33
|
// `px-1` and `5` means the real candidate was `px-1.5` which is already
|
|
34
34
|
// captured.
|
|
35
|
-
let next =
|
|
35
|
+
let next = Number(segments[idx + 1])
|
|
36
36
|
if (isNaN(next)) {
|
|
37
37
|
results.push(segment)
|
|
38
38
|
} else {
|
|
@@ -152,6 +152,9 @@ function* buildRegExps(context) {
|
|
|
152
152
|
utility,
|
|
153
153
|
])
|
|
154
154
|
}
|
|
155
|
+
|
|
156
|
+
// 5. Inner matches
|
|
157
|
+
yield /[^<>"'`\s.(){}[\]#=%$][^<>"'`\s(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g
|
|
155
158
|
}
|
|
156
159
|
|
|
157
160
|
// We want to capture any "special" characters
|
|
@@ -5,13 +5,12 @@ export function applyImportantSelector(selector, important) {
|
|
|
5
5
|
let sel = parser().astSync(selector)
|
|
6
6
|
|
|
7
7
|
sel.each((sel) => {
|
|
8
|
-
//
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
sel.nodes.every((node) => node.type !== 'combinator')
|
|
8
|
+
// For nesting, we only need to wrap a selector with :is() if it has a top-level combinator,
|
|
9
|
+
// e.g. `.dark .text-white`, to be independent of DOM order. Any other selector, including
|
|
10
|
+
// combinators inside of pseudos like `:where()`, are ok to nest.
|
|
11
|
+
let shouldWrap = sel.nodes.some((node) => node.type === 'combinator')
|
|
13
12
|
|
|
14
|
-
if (
|
|
13
|
+
if (shouldWrap) {
|
|
15
14
|
sel.nodes = [
|
|
16
15
|
parser.pseudo({
|
|
17
16
|
value: ':is',
|
package/src/util/dataTypes.js
CHANGED
|
@@ -81,6 +81,34 @@ export function normalize(value, context = null, isRoot = true) {
|
|
|
81
81
|
return value
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
+
export function normalizeAttributeSelectors(value) {
|
|
85
|
+
// Wrap values in attribute selectors with quotes
|
|
86
|
+
if (value.includes('=')) {
|
|
87
|
+
value = value.replace(/(=.*)/g, (_fullMatch, match) => {
|
|
88
|
+
if (match[1] === "'" || match[1] === '"') {
|
|
89
|
+
return match
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Handle regex flags on unescaped values
|
|
93
|
+
if (match.length > 2) {
|
|
94
|
+
let trailingCharacter = match[match.length - 1]
|
|
95
|
+
if (
|
|
96
|
+
match[match.length - 2] === ' ' &&
|
|
97
|
+
(trailingCharacter === 'i' ||
|
|
98
|
+
trailingCharacter === 'I' ||
|
|
99
|
+
trailingCharacter === 's' ||
|
|
100
|
+
trailingCharacter === 'S')
|
|
101
|
+
) {
|
|
102
|
+
return `="${match.slice(1, -2)}" ${match[match.length - 1]}`
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return `="${match.slice(1)}"`
|
|
107
|
+
})
|
|
108
|
+
}
|
|
109
|
+
return value
|
|
110
|
+
}
|
|
111
|
+
|
|
84
112
|
/**
|
|
85
113
|
* Add spaces around operators inside math functions
|
|
86
114
|
* like calc() that do not follow an operator, '(', or `,`.
|