tailwindcss 3.4.0 → 3.4.2
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 +40 -1
- package/README.md +2 -3
- package/lib/cli/build/plugin.js +4 -11
- package/lib/cli.js +1 -5
- package/lib/corePluginList.js +1 -0
- package/lib/corePlugins.js +92 -25
- package/lib/css/preflight.css +4 -3
- package/lib/featureFlags.js +2 -6
- package/lib/lib/content.js +36 -3
- package/lib/lib/defaultExtractor.js +2 -2
- package/lib/lib/expandApplyAtRules.js +13 -0
- package/lib/lib/expandTailwindAtRules.js +20 -32
- package/lib/lib/generateRules.js +13 -2
- package/lib/lib/load-config.js +4 -0
- package/lib/lib/offsets.js +51 -2
- package/lib/lib/resolveDefaultsAtRules.js +3 -1
- package/lib/lib/setupContextUtils.js +23 -3
- package/lib/lib/sharedState.js +2 -10
- package/lib/plugin.js +0 -50
- package/lib/processTailwindFeatures.js +0 -2
- package/lib/util/dataTypes.js +12 -2
- package/lib/util/pseudoElements.js +3 -0
- package/package.json +5 -8
- package/peers/index.js +61 -61
- package/src/cli/build/plugin.js +4 -11
- package/src/cli.js +1 -5
- package/src/corePluginList.js +1 -1
- package/src/corePlugins.js +88 -27
- package/src/css/preflight.css +4 -3
- package/src/featureFlags.js +2 -6
- package/src/lib/content.js +42 -1
- package/src/lib/defaultExtractor.js +2 -2
- package/src/lib/expandApplyAtRules.js +17 -0
- package/src/lib/expandTailwindAtRules.js +23 -41
- package/src/lib/generateRules.js +12 -2
- package/src/lib/load-config.ts +5 -0
- package/src/lib/offsets.js +61 -2
- package/src/lib/resolveDefaultsAtRules.js +5 -1
- package/src/lib/setupContextUtils.js +28 -2
- package/src/lib/sharedState.js +0 -4
- package/src/plugin.js +0 -60
- package/src/processTailwindFeatures.js +0 -3
- package/src/util/dataTypes.js +13 -1
- package/src/util/pseudoElements.js +4 -0
- package/types/config.d.ts +7 -0
- package/types/generated/corePluginList.d.ts +1 -1
- package/lib/lib/detectNesting.js +0 -45
- package/lib/oxide/cli/build/deps.js +0 -89
- package/lib/oxide/cli/build/index.js +0 -53
- package/lib/oxide/cli/build/plugin.js +0 -375
- package/lib/oxide/cli/build/utils.js +0 -87
- package/lib/oxide/cli/build/watching.js +0 -179
- package/lib/oxide/cli/help/index.js +0 -72
- package/lib/oxide/cli/index.js +0 -214
- package/lib/oxide/cli/init/index.js +0 -52
- package/lib/oxide/cli.js +0 -5
- package/lib/oxide/postcss-plugin.js +0 -2
- package/scripts/swap-engines.js +0 -40
- package/src/lib/detectNesting.js +0 -47
- package/src/oxide/cli/build/deps.ts +0 -91
- package/src/oxide/cli/build/index.ts +0 -47
- package/src/oxide/cli/build/plugin.ts +0 -442
- package/src/oxide/cli/build/utils.ts +0 -74
- package/src/oxide/cli/build/watching.ts +0 -225
- package/src/oxide/cli/help/index.ts +0 -69
- package/src/oxide/cli/index.ts +0 -204
- package/src/oxide/cli/init/index.ts +0 -59
- package/src/oxide/cli.ts +0 -1
- package/src/oxide/postcss-plugin.ts +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,43 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
- Nothing yet!
|
|
11
|
+
|
|
12
|
+
## [3.4.2] - 2024-03-27
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- Ensure max specificity of `0,0,1` for button and input Preflight rules ([#12735](https://github.com/tailwindlabs/tailwindcss/pull/12735))
|
|
17
|
+
- Improve glob handling for folders with `(`, `)`, `[` or `]` in the file path ([#12715](https://github.com/tailwindlabs/tailwindcss/pull/12715))
|
|
18
|
+
- Split `:has` rules when using `experimental.optimizeUniversalDefaults` ([#12736](https://github.com/tailwindlabs/tailwindcss/pull/12736))
|
|
19
|
+
- Sort arbitrary properties alphabetically across multiple class lists ([#12911](https://github.com/tailwindlabs/tailwindcss/pull/12911))
|
|
20
|
+
- Add `mix-blend-plus-darker` utility ([#12923](https://github.com/tailwindlabs/tailwindcss/pull/12923))
|
|
21
|
+
- Ensure dashes are allowed in variant modifiers ([#13303](https://github.com/tailwindlabs/tailwindcss/pull/13303))
|
|
22
|
+
- Fix crash showing completions in Intellisense when using a custom separator ([#13306](https://github.com/tailwindlabs/tailwindcss/pull/13306))
|
|
23
|
+
- Transpile `import.meta.url` in config files ([#13322](https://github.com/tailwindlabs/tailwindcss/pull/13322))
|
|
24
|
+
- Reset letter spacing for form elements ([#13150](https://github.com/tailwindlabs/tailwindcss/pull/13150))
|
|
25
|
+
- Fix missing `xx-large` and remove double `x-large` absolute size ([#13324](https://github.com/tailwindlabs/tailwindcss/pull/13324))
|
|
26
|
+
- Don't error when encountering nested CSS unless trying to `@apply` a class that uses nesting ([#13325](https://github.com/tailwindlabs/tailwindcss/pull/13325))
|
|
27
|
+
- Ensure that arbitrary properties respect `important` configuration ([#13353](https://github.com/tailwindlabs/tailwindcss/pull/13353))
|
|
28
|
+
- Change dark mode selector so `@apply` works correctly with pseudo elements ([#13379](https://github.com/tailwindlabs/tailwindcss/pull/13379))
|
|
29
|
+
|
|
30
|
+
## [3.4.1] - 2024-01-05
|
|
31
|
+
|
|
32
|
+
### Fixed
|
|
33
|
+
|
|
34
|
+
- Don't remove keyframe stops when using important utilities ([#12639](https://github.com/tailwindlabs/tailwindcss/pull/12639))
|
|
35
|
+
- Don't add spaces to gradients and grid track names when followed by `calc()` ([#12704](https://github.com/tailwindlabs/tailwindcss/pull/12704))
|
|
36
|
+
- Restore old behavior for `class` dark mode strategy ([#12717](https://github.com/tailwindlabs/tailwindcss/pull/12717))
|
|
37
|
+
- Improve glob handling for folders with `(`, `)`, `[` or `]` in the file path ([#12715](https://github.com/tailwindlabs/tailwindcss/pull/12715))
|
|
38
|
+
|
|
39
|
+
### Added
|
|
40
|
+
|
|
41
|
+
- Add new `selector` and `variant` strategies for dark mode ([#12717](https://github.com/tailwindlabs/tailwindcss/pull/12717))
|
|
42
|
+
|
|
43
|
+
### Changed
|
|
44
|
+
|
|
45
|
+
- Support `rtl` and `ltr` variants on same element as `dir` attribute ([#12717](https://github.com/tailwindlabs/tailwindcss/pull/12717))
|
|
46
|
+
|
|
10
47
|
## [3.4.0] - 2023-12-19
|
|
11
48
|
|
|
12
49
|
### Added
|
|
@@ -2333,7 +2370,9 @@ No release notes
|
|
|
2333
2370
|
|
|
2334
2371
|
- Everything!
|
|
2335
2372
|
|
|
2336
|
-
[unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.
|
|
2373
|
+
[unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.2...HEAD
|
|
2374
|
+
[3.4.2]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.1...v3.4.2
|
|
2375
|
+
[3.4.1]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.0...v3.4.1
|
|
2337
2376
|
[3.4.0]: https://github.com/tailwindlabs/tailwindcss/compare/v3.3.7...v3.4.0
|
|
2338
2377
|
[3.3.7]: https://github.com/tailwindlabs/tailwindcss/compare/v3.3.6...v3.3.7
|
|
2339
2378
|
[3.3.6]: https://github.com/tailwindlabs/tailwindcss/compare/v3.3.5...v3.3.6
|
package/README.md
CHANGED
|
@@ -12,15 +12,14 @@
|
|
|
12
12
|
A utility-first CSS framework for rapidly building custom user interfaces.
|
|
13
13
|
</p>
|
|
14
14
|
|
|
15
|
-
|
|
16
15
|
<p align="center">
|
|
17
|
-
<a href="https://github.com/tailwindlabs/tailwindcss/actions"><img src="https://img.shields.io/github/actions/workflow/status/tailwindlabs/tailwindcss/ci
|
|
16
|
+
<a href="https://github.com/tailwindlabs/tailwindcss/actions"><img src="https://img.shields.io/github/actions/workflow/status/tailwindlabs/tailwindcss/ci.yml?branch=master" alt="Build Status"></a>
|
|
18
17
|
<a href="https://www.npmjs.com/package/tailwindcss"><img src="https://img.shields.io/npm/dt/tailwindcss.svg" alt="Total Downloads"></a>
|
|
19
18
|
<a href="https://github.com/tailwindcss/tailwindcss/releases"><img src="https://img.shields.io/npm/v/tailwindcss.svg" alt="Latest Release"></a>
|
|
20
19
|
<a href="https://github.com/tailwindcss/tailwindcss/blob/master/LICENSE"><img src="https://img.shields.io/npm/l/tailwindcss.svg" alt="License"></a>
|
|
21
20
|
</p>
|
|
22
21
|
|
|
23
|
-
|
|
22
|
+
---
|
|
24
23
|
|
|
25
24
|
## Documentation
|
|
26
25
|
|
package/lib/cli/build/plugin.js
CHANGED
|
@@ -167,17 +167,10 @@ let state = {
|
|
|
167
167
|
// TODO: When we make the postcss plugin async-capable this can become async
|
|
168
168
|
let files = _fastglob.default.sync(this.contentPatterns.all);
|
|
169
169
|
for (let file of files){
|
|
170
|
-
|
|
171
|
-
content.
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
});
|
|
175
|
-
} else {
|
|
176
|
-
content.push({
|
|
177
|
-
content: _fs.default.readFileSync(_path.default.resolve(file), "utf8"),
|
|
178
|
-
extension: _path.default.extname(file).slice(1)
|
|
179
|
-
});
|
|
180
|
-
}
|
|
170
|
+
content.push({
|
|
171
|
+
content: _fs.default.readFileSync(_path.default.resolve(file), "utf8"),
|
|
172
|
+
extension: _path.default.extname(file).slice(1)
|
|
173
|
+
});
|
|
181
174
|
}
|
|
182
175
|
// Resolve raw content in the tailwind config
|
|
183
176
|
let rawContent = this.config.content.files.filter((file)=>{
|
package/lib/cli.js
CHANGED
package/lib/corePluginList.js
CHANGED
package/lib/corePlugins.js
CHANGED
|
@@ -267,15 +267,15 @@ let variantPlugins = {
|
|
|
267
267
|
}
|
|
268
268
|
},
|
|
269
269
|
directionVariants: ({ addVariant })=>{
|
|
270
|
-
addVariant("ltr", '
|
|
271
|
-
addVariant("rtl", '
|
|
270
|
+
addVariant("ltr", '&:where([dir="ltr"], [dir="ltr"] *)');
|
|
271
|
+
addVariant("rtl", '&:where([dir="rtl"], [dir="rtl"] *)');
|
|
272
272
|
},
|
|
273
273
|
reducedMotionVariants: ({ addVariant })=>{
|
|
274
274
|
addVariant("motion-safe", "@media (prefers-reduced-motion: no-preference)");
|
|
275
275
|
addVariant("motion-reduce", "@media (prefers-reduced-motion: reduce)");
|
|
276
276
|
},
|
|
277
277
|
darkVariants: ({ config , addVariant })=>{
|
|
278
|
-
let [mode,
|
|
278
|
+
let [mode, selector = ".dark"] = [].concat(config("darkMode", "media"));
|
|
279
279
|
if (mode === false) {
|
|
280
280
|
mode = "media";
|
|
281
281
|
_log.default.warn("darkmode-false", [
|
|
@@ -284,10 +284,48 @@ let variantPlugins = {
|
|
|
284
284
|
"https://tailwindcss.com/docs/upgrade-guide#remove-dark-mode-configuration"
|
|
285
285
|
]);
|
|
286
286
|
}
|
|
287
|
-
if (mode === "
|
|
288
|
-
|
|
287
|
+
if (mode === "variant") {
|
|
288
|
+
let formats;
|
|
289
|
+
if (Array.isArray(selector)) {
|
|
290
|
+
formats = selector;
|
|
291
|
+
} else if (typeof selector === "function") {
|
|
292
|
+
formats = selector;
|
|
293
|
+
} else if (typeof selector === "string") {
|
|
294
|
+
formats = [
|
|
295
|
+
selector
|
|
296
|
+
];
|
|
297
|
+
}
|
|
298
|
+
// TODO: We could also add these warnings if the user passes a function that returns string | string[]
|
|
299
|
+
// But this is an advanced enough use case that it's probably not necessary
|
|
300
|
+
if (Array.isArray(formats)) {
|
|
301
|
+
for (let format of formats){
|
|
302
|
+
if (format === ".dark") {
|
|
303
|
+
mode = false;
|
|
304
|
+
_log.default.warn("darkmode-variant-without-selector", [
|
|
305
|
+
"When using `variant` for `darkMode`, you must provide a selector.",
|
|
306
|
+
'Example: `darkMode: ["variant", ".your-selector &"]`'
|
|
307
|
+
]);
|
|
308
|
+
} else if (!format.includes("&")) {
|
|
309
|
+
mode = false;
|
|
310
|
+
_log.default.warn("darkmode-variant-without-ampersand", [
|
|
311
|
+
"When using `variant` for `darkMode`, your selector must contain `&`.",
|
|
312
|
+
'Example `darkMode: ["variant", ".your-selector &"]`'
|
|
313
|
+
]);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
selector = formats;
|
|
318
|
+
}
|
|
319
|
+
if (mode === "selector") {
|
|
320
|
+
// New preferred behavior
|
|
321
|
+
addVariant("dark", `&:where(${selector}, ${selector} *)`);
|
|
289
322
|
} else if (mode === "media") {
|
|
290
323
|
addVariant("dark", "@media (prefers-color-scheme: dark)");
|
|
324
|
+
} else if (mode === "variant") {
|
|
325
|
+
addVariant("dark", selector);
|
|
326
|
+
} else if (mode === "class") {
|
|
327
|
+
// Old behavior
|
|
328
|
+
addVariant("dark", `&:is(${selector} *)`);
|
|
291
329
|
}
|
|
292
330
|
},
|
|
293
331
|
printVariant: ({ addVariant })=>{
|
|
@@ -1984,15 +2022,6 @@ let corePlugins = {
|
|
|
1984
2022
|
matchUtilities({
|
|
1985
2023
|
"space-x": (value)=>{
|
|
1986
2024
|
value = value === "0" ? "0px" : value;
|
|
1987
|
-
if (false) {
|
|
1988
|
-
return {
|
|
1989
|
-
"& > :not([hidden]) ~ :not([hidden])": {
|
|
1990
|
-
"--tw-space-x-reverse": "0",
|
|
1991
|
-
"margin-inline-end": `calc(${value} * var(--tw-space-x-reverse))`,
|
|
1992
|
-
"margin-inline-start": `calc(${value} * calc(1 - var(--tw-space-x-reverse)))`
|
|
1993
|
-
}
|
|
1994
|
-
};
|
|
1995
|
-
}
|
|
1996
2025
|
return {
|
|
1997
2026
|
"& > :not([hidden]) ~ :not([hidden])": {
|
|
1998
2027
|
"--tw-space-x-reverse": "0",
|
|
@@ -2028,16 +2057,6 @@ let corePlugins = {
|
|
|
2028
2057
|
matchUtilities({
|
|
2029
2058
|
"divide-x": (value)=>{
|
|
2030
2059
|
value = value === "0" ? "0px" : value;
|
|
2031
|
-
if (false) {
|
|
2032
|
-
return {
|
|
2033
|
-
"& > :not([hidden]) ~ :not([hidden])": {
|
|
2034
|
-
"@defaults border-width": {},
|
|
2035
|
-
"--tw-divide-x-reverse": "0",
|
|
2036
|
-
"border-inline-end-width": `calc(${value} * var(--tw-divide-x-reverse))`,
|
|
2037
|
-
"border-inline-start-width": `calc(${value} * calc(1 - var(--tw-divide-x-reverse)))`
|
|
2038
|
-
}
|
|
2039
|
-
};
|
|
2040
|
-
}
|
|
2041
2060
|
return {
|
|
2042
2061
|
"& > :not([hidden]) ~ :not([hidden])": {
|
|
2043
2062
|
"@defaults border-width": {},
|
|
@@ -3654,6 +3673,9 @@ let corePlugins = {
|
|
|
3654
3673
|
".mix-blend-luminosity": {
|
|
3655
3674
|
"mix-blend-mode": "luminosity"
|
|
3656
3675
|
},
|
|
3676
|
+
".mix-blend-plus-darker": {
|
|
3677
|
+
"mix-blend-mode": "plus-darker"
|
|
3678
|
+
},
|
|
3657
3679
|
".mix-blend-plus-lighter": {
|
|
3658
3680
|
"mix-blend-mode": "plus-lighter"
|
|
3659
3681
|
}
|
|
@@ -3667,7 +3689,7 @@ let corePlugins = {
|
|
|
3667
3689
|
`var(--tw-shadow)`
|
|
3668
3690
|
].join(", ");
|
|
3669
3691
|
return function({ matchUtilities , addDefaults , theme }) {
|
|
3670
|
-
addDefaults("
|
|
3692
|
+
addDefaults("box-shadow", {
|
|
3671
3693
|
"--tw-ring-offset-shadow": "0 0 #0000",
|
|
3672
3694
|
"--tw-ring-shadow": "0 0 #0000",
|
|
3673
3695
|
"--tw-shadow": "0 0 #0000",
|
|
@@ -4219,6 +4241,51 @@ let corePlugins = {
|
|
|
4219
4241
|
]
|
|
4220
4242
|
]
|
|
4221
4243
|
]),
|
|
4244
|
+
contain: ({ addDefaults , addUtilities })=>{
|
|
4245
|
+
let cssContainValue = "var(--tw-contain-size) var(--tw-contain-layout) var(--tw-contain-paint) var(--tw-contain-style)";
|
|
4246
|
+
addDefaults("contain", {
|
|
4247
|
+
"--tw-contain-size": " ",
|
|
4248
|
+
"--tw-contain-layout": " ",
|
|
4249
|
+
"--tw-contain-paint": " ",
|
|
4250
|
+
"--tw-contain-style": " "
|
|
4251
|
+
});
|
|
4252
|
+
addUtilities({
|
|
4253
|
+
".contain-none": {
|
|
4254
|
+
contain: "none"
|
|
4255
|
+
},
|
|
4256
|
+
".contain-content": {
|
|
4257
|
+
contain: "content"
|
|
4258
|
+
},
|
|
4259
|
+
".contain-strict": {
|
|
4260
|
+
contain: "strict"
|
|
4261
|
+
},
|
|
4262
|
+
".contain-size": {
|
|
4263
|
+
"@defaults contain": {},
|
|
4264
|
+
"--tw-contain-size": "size",
|
|
4265
|
+
contain: cssContainValue
|
|
4266
|
+
},
|
|
4267
|
+
".contain-inline-size": {
|
|
4268
|
+
"@defaults contain": {},
|
|
4269
|
+
"--tw-contain-size": "inline-size",
|
|
4270
|
+
contain: cssContainValue
|
|
4271
|
+
},
|
|
4272
|
+
".contain-layout": {
|
|
4273
|
+
"@defaults contain": {},
|
|
4274
|
+
"--tw-contain-layout": "layout",
|
|
4275
|
+
contain: cssContainValue
|
|
4276
|
+
},
|
|
4277
|
+
".contain-paint": {
|
|
4278
|
+
"@defaults contain": {},
|
|
4279
|
+
"--tw-contain-paint": "paint",
|
|
4280
|
+
contain: cssContainValue
|
|
4281
|
+
},
|
|
4282
|
+
".contain-style": {
|
|
4283
|
+
"@defaults contain": {},
|
|
4284
|
+
"--tw-contain-style": "style",
|
|
4285
|
+
contain: cssContainValue
|
|
4286
|
+
}
|
|
4287
|
+
});
|
|
4288
|
+
},
|
|
4222
4289
|
content: (0, _createUtilityPlugin.default)("content", [
|
|
4223
4290
|
[
|
|
4224
4291
|
"content",
|
package/lib/css/preflight.css
CHANGED
|
@@ -175,6 +175,7 @@ textarea {
|
|
|
175
175
|
font-size: 100%; /* 1 */
|
|
176
176
|
font-weight: inherit; /* 1 */
|
|
177
177
|
line-height: inherit; /* 1 */
|
|
178
|
+
letter-spacing: inherit; /* 1 */
|
|
178
179
|
color: inherit; /* 1 */
|
|
179
180
|
margin: 0; /* 2 */
|
|
180
181
|
padding: 0; /* 3 */
|
|
@@ -195,9 +196,9 @@ select {
|
|
|
195
196
|
*/
|
|
196
197
|
|
|
197
198
|
button,
|
|
198
|
-
[type='button'],
|
|
199
|
-
[type='reset'],
|
|
200
|
-
[type='submit'] {
|
|
199
|
+
input:where([type='button']),
|
|
200
|
+
input:where([type='reset']),
|
|
201
|
+
input:where([type='submit']) {
|
|
201
202
|
-webkit-appearance: button; /* 1 */
|
|
202
203
|
background-color: transparent; /* 2 */
|
|
203
204
|
background-image: none; /* 2 */
|
package/lib/featureFlags.js
CHANGED
|
@@ -29,12 +29,8 @@ function _interop_require_default(obj) {
|
|
|
29
29
|
let defaults = {
|
|
30
30
|
optimizeUniversalDefaults: false,
|
|
31
31
|
generalizedModifiers: true,
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
},
|
|
35
|
-
get relativeContentPathsByDefault () {
|
|
36
|
-
return false;
|
|
37
|
-
}
|
|
32
|
+
disableColorOpacityUtilitiesByDefault: false,
|
|
33
|
+
relativeContentPathsByDefault: false
|
|
38
34
|
};
|
|
39
35
|
let featureFlags = {
|
|
40
36
|
future: [
|
package/lib/lib/content.js
CHANGED
|
@@ -21,7 +21,6 @@ const _fs = /*#__PURE__*/ _interop_require_default(require("fs"));
|
|
|
21
21
|
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
|
|
22
22
|
const _isglob = /*#__PURE__*/ _interop_require_default(require("is-glob"));
|
|
23
23
|
const _fastglob = /*#__PURE__*/ _interop_require_default(require("fast-glob"));
|
|
24
|
-
const _normalizepath = /*#__PURE__*/ _interop_require_default(require("normalize-path"));
|
|
25
24
|
const _parseGlob = require("../util/parseGlob");
|
|
26
25
|
const _sharedState = require("./sharedState");
|
|
27
26
|
function _interop_require_default(obj) {
|
|
@@ -29,11 +28,42 @@ function _interop_require_default(obj) {
|
|
|
29
28
|
default: obj
|
|
30
29
|
};
|
|
31
30
|
}
|
|
31
|
+
/*!
|
|
32
|
+
* Modified version of normalize-path, original license below
|
|
33
|
+
*
|
|
34
|
+
* normalize-path <https://github.com/jonschlinkert/normalize-path>
|
|
35
|
+
*
|
|
36
|
+
* Copyright (c) 2014-2018, Jon Schlinkert.
|
|
37
|
+
* Released under the MIT License.
|
|
38
|
+
*/ function normalizePath(path) {
|
|
39
|
+
if (typeof path !== "string") {
|
|
40
|
+
throw new TypeError("expected path to be a string");
|
|
41
|
+
}
|
|
42
|
+
if (path === "\\" || path === "/") return "/";
|
|
43
|
+
var len = path.length;
|
|
44
|
+
if (len <= 1) return path;
|
|
45
|
+
// ensure that win32 namespaces has two leading slashes, so that the path is
|
|
46
|
+
// handled properly by the win32 version of path.parse() after being normalized
|
|
47
|
+
// https://msdn.microsoft.com/library/windows/desktop/aa365247(v=vs.85).aspx#namespaces
|
|
48
|
+
var prefix = "";
|
|
49
|
+
if (len > 4 && path[3] === "\\") {
|
|
50
|
+
var ch = path[2];
|
|
51
|
+
if ((ch === "?" || ch === ".") && path.slice(0, 2) === "\\\\") {
|
|
52
|
+
path = path.slice(2);
|
|
53
|
+
prefix = "//";
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// Modified part: instead of purely splitting on `\\` and `/`, we split on
|
|
57
|
+
// `/` and `\\` that is _not_ followed by any of the following characters: ()[]
|
|
58
|
+
// This is to ensure that we keep the escaping of brackets and parentheses
|
|
59
|
+
let segs = path.split(/[/\\]+(?![\(\)\[\]])/);
|
|
60
|
+
return prefix + segs.join("/");
|
|
61
|
+
}
|
|
32
62
|
function parseCandidateFiles(context, tailwindConfig) {
|
|
33
63
|
let files = tailwindConfig.content.files;
|
|
34
64
|
// Normalize the file globs
|
|
35
65
|
files = files.filter((filePath)=>typeof filePath === "string");
|
|
36
|
-
files = files.map(
|
|
66
|
+
files = files.map(normalizePath);
|
|
37
67
|
// Split into included and excluded globs
|
|
38
68
|
let tasks = _fastglob.default.generateTasks(files);
|
|
39
69
|
/** @type {ContentPath[]} */ let included = [];
|
|
@@ -60,6 +90,9 @@ function parseCandidateFiles(context, tailwindConfig) {
|
|
|
60
90
|
* @param {boolean} ignore
|
|
61
91
|
* @returns {ContentPath}
|
|
62
92
|
*/ function parseFilePath(filePath, ignore) {
|
|
93
|
+
// Escape special characters in the file path such as: ()[]
|
|
94
|
+
// But only if the special character isn't already escaped
|
|
95
|
+
filePath = filePath.replace(/(?<!\\)([\[\]\(\)])/g, "\\$1");
|
|
63
96
|
let contentPath = {
|
|
64
97
|
original: filePath,
|
|
65
98
|
base: filePath,
|
|
@@ -81,7 +114,7 @@ function parseCandidateFiles(context, tailwindConfig) {
|
|
|
81
114
|
// Afaik, this technically shouldn't be needed but there's probably
|
|
82
115
|
// some internal, direct path matching with a normalized path in
|
|
83
116
|
// a package which can't handle mixed directory separators
|
|
84
|
-
let base = (
|
|
117
|
+
let base = normalizePath(contentPath.base);
|
|
85
118
|
// If the user's file path contains any special characters (like parens) for instance fast-glob
|
|
86
119
|
// is like "OOOH SHINY" and treats them as such. So we have to escape the base path to fix this
|
|
87
120
|
base = _fastglob.default.escapePath(base);
|
|
@@ -128,7 +128,7 @@ function* buildRegExps(context) {
|
|
|
128
128
|
]),
|
|
129
129
|
// With variant modifier (e.g.: group-[..]/modifier)
|
|
130
130
|
_regex.pattern([
|
|
131
|
-
/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]
|
|
131
|
+
/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]\/[\w_-]+/,
|
|
132
132
|
separator
|
|
133
133
|
]),
|
|
134
134
|
_regex.pattern([
|
|
@@ -144,7 +144,7 @@ function* buildRegExps(context) {
|
|
|
144
144
|
_regex.any([
|
|
145
145
|
// With variant modifier (e.g.: group-[..]/modifier)
|
|
146
146
|
_regex.pattern([
|
|
147
|
-
/([^\s"'`\[\\]+-)?\[[^\s`]+\]
|
|
147
|
+
/([^\s"'`\[\\]+-)?\[[^\s`]+\]\/[\w_-]+/,
|
|
148
148
|
separator
|
|
149
149
|
]),
|
|
150
150
|
_regex.pattern([
|
|
@@ -380,6 +380,19 @@ function processApply(root, context, localCache) {
|
|
|
380
380
|
throw apply.error(`The \`${applyCandidate}\` class does not exist. If \`${applyCandidate}\` is a custom class, make sure it is defined within a \`@layer\` directive.`);
|
|
381
381
|
}
|
|
382
382
|
let rules = applyClassCache.get(applyCandidate);
|
|
383
|
+
// Verify that we can apply the class
|
|
384
|
+
for (let [, rule] of rules){
|
|
385
|
+
if (rule.type === "atrule") {
|
|
386
|
+
continue;
|
|
387
|
+
}
|
|
388
|
+
rule.walkRules(()=>{
|
|
389
|
+
throw apply.error([
|
|
390
|
+
`The \`${applyCandidate}\` class cannot be used with \`@apply\` because \`@apply\` does not currently support nested CSS.`,
|
|
391
|
+
"Rewrite the selector without nesting or configure the `tailwindcss/nesting` plugin:",
|
|
392
|
+
"https://tailwindcss.com/docs/using-with-preprocessors#nesting"
|
|
393
|
+
].join("\n"));
|
|
394
|
+
});
|
|
395
|
+
}
|
|
383
396
|
candidates.push([
|
|
384
397
|
applyCandidate,
|
|
385
398
|
important,
|
|
@@ -154,37 +154,25 @@ function expandTailwindAtRules(context) {
|
|
|
154
154
|
]);
|
|
155
155
|
let seen = new Set();
|
|
156
156
|
env.DEBUG && console.time("Reading changed files");
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
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
|
-
}
|
|
157
|
+
/** @type {[item: {file?: string, content?: string}, meta: {transformer: any, extractor: any}][]} */ let regexParserContent = [];
|
|
158
|
+
for (let item of context.changedContent){
|
|
159
|
+
let transformer = getTransformer(context.tailwindConfig, item.extension);
|
|
160
|
+
let extractor = getExtractor(context, item.extension);
|
|
161
|
+
regexParserContent.push([
|
|
162
|
+
item,
|
|
163
|
+
{
|
|
164
|
+
transformer,
|
|
165
|
+
extractor
|
|
166
|
+
}
|
|
167
|
+
]);
|
|
168
|
+
}
|
|
169
|
+
const BATCH_SIZE = 500;
|
|
170
|
+
for(let i = 0; i < regexParserContent.length; i += BATCH_SIZE){
|
|
171
|
+
let batch = regexParserContent.slice(i, i + BATCH_SIZE);
|
|
172
|
+
await Promise.all(batch.map(async ([{ file , content }, { transformer , extractor }])=>{
|
|
173
|
+
content = file ? await _fs.default.promises.readFile(file, "utf8") : content;
|
|
174
|
+
getClassCandidates(transformer(content), extractor, candidates, seen);
|
|
175
|
+
}));
|
|
188
176
|
}
|
|
189
177
|
env.DEBUG && console.timeEnd("Reading changed files");
|
|
190
178
|
// ---
|
|
@@ -192,7 +180,7 @@ function expandTailwindAtRules(context) {
|
|
|
192
180
|
let classCacheCount = context.classCache.size;
|
|
193
181
|
env.DEBUG && console.time("Generate rules");
|
|
194
182
|
env.DEBUG && console.time("Sorting candidates");
|
|
195
|
-
let sortedCandidates =
|
|
183
|
+
let sortedCandidates = new Set([
|
|
196
184
|
...candidates
|
|
197
185
|
].sort((a, z)=>{
|
|
198
186
|
if (a === z) return 0;
|
package/lib/lib/generateRules.js
CHANGED
|
@@ -162,6 +162,9 @@ function applyImportant(matches, classCandidate) {
|
|
|
162
162
|
return matches;
|
|
163
163
|
}
|
|
164
164
|
let result = [];
|
|
165
|
+
function isInKeyframes(rule) {
|
|
166
|
+
return rule.parent && rule.parent.type === "atrule" && rule.parent.name === "keyframes";
|
|
167
|
+
}
|
|
165
168
|
for (let [meta, rule] of matches){
|
|
166
169
|
let container = _postcss.default.root({
|
|
167
170
|
nodes: [
|
|
@@ -169,6 +172,11 @@ function applyImportant(matches, classCandidate) {
|
|
|
169
172
|
]
|
|
170
173
|
});
|
|
171
174
|
container.walkRules((r)=>{
|
|
175
|
+
// Declarations inside keyframes cannot be marked as important
|
|
176
|
+
// They will be ignored by the browser
|
|
177
|
+
if (isInKeyframes(r)) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
172
180
|
let ast = (0, _postcssselectorparser.default)().astSync(r.selector);
|
|
173
181
|
// Remove extraneous selectors that do not include the base candidate
|
|
174
182
|
ast.each((sel)=>(0, _formatVariantSelector.eliminateIrrelevantSelectors)(sel, classCandidate));
|
|
@@ -506,12 +514,15 @@ function extractArbitraryProperty(classCandidate, context) {
|
|
|
506
514
|
if (!isParsableCssValue(property, normalized)) {
|
|
507
515
|
return null;
|
|
508
516
|
}
|
|
509
|
-
let sort = context.offsets.arbitraryProperty();
|
|
517
|
+
let sort = context.offsets.arbitraryProperty(classCandidate);
|
|
510
518
|
return [
|
|
511
519
|
[
|
|
512
520
|
{
|
|
513
521
|
sort,
|
|
514
|
-
layer: "utilities"
|
|
522
|
+
layer: "utilities",
|
|
523
|
+
options: {
|
|
524
|
+
respectImportant: true
|
|
525
|
+
}
|
|
515
526
|
},
|
|
516
527
|
()=>({
|
|
517
528
|
[(0, _nameClass.asClass)(classCandidate)]: {
|
package/lib/lib/load-config.js
CHANGED
|
@@ -31,6 +31,10 @@ function lazyJiti() {
|
|
|
31
31
|
return jiti !== null && jiti !== void 0 ? jiti : jiti = (0, _jiti.default)(__filename, {
|
|
32
32
|
interopDefault: true,
|
|
33
33
|
transform: (opts)=>{
|
|
34
|
+
// Sucrase can't transform import.meta so we have to use Babel
|
|
35
|
+
if (opts.source.includes("import.meta")) {
|
|
36
|
+
return require("jiti/dist/babel.js")(opts);
|
|
37
|
+
}
|
|
34
38
|
return (0, _sucrase.transform)(opts.source, {
|
|
35
39
|
transforms: [
|
|
36
40
|
"typescript",
|
package/lib/lib/offsets.js
CHANGED
|
@@ -66,15 +66,19 @@ class Offsets {
|
|
|
66
66
|
variants: 0n,
|
|
67
67
|
parallelIndex: 0n,
|
|
68
68
|
index: this.offsets[layer]++,
|
|
69
|
+
propertyOffset: 0n,
|
|
70
|
+
property: "",
|
|
69
71
|
options: []
|
|
70
72
|
};
|
|
71
73
|
}
|
|
72
74
|
/**
|
|
75
|
+
* @param {string} name
|
|
73
76
|
* @returns {RuleOffset}
|
|
74
|
-
*/ arbitraryProperty() {
|
|
77
|
+
*/ arbitraryProperty(name) {
|
|
75
78
|
return {
|
|
76
79
|
...this.create("utilities"),
|
|
77
|
-
arbitrary: 1n
|
|
80
|
+
arbitrary: 1n,
|
|
81
|
+
property: name
|
|
78
82
|
};
|
|
79
83
|
}
|
|
80
84
|
/**
|
|
@@ -214,6 +218,10 @@ class Offsets {
|
|
|
214
218
|
if (a.arbitrary !== b.arbitrary) {
|
|
215
219
|
return a.arbitrary - b.arbitrary;
|
|
216
220
|
}
|
|
221
|
+
// Always sort arbitrary properties alphabetically
|
|
222
|
+
if (a.propertyOffset !== b.propertyOffset) {
|
|
223
|
+
return a.propertyOffset - b.propertyOffset;
|
|
224
|
+
}
|
|
217
225
|
// Sort utilities, components, etc… in the order they were registered
|
|
218
226
|
return a.index - b.index;
|
|
219
227
|
}
|
|
@@ -267,8 +275,49 @@ class Offsets {
|
|
|
267
275
|
* @template T
|
|
268
276
|
* @param {[RuleOffset, T][]} list
|
|
269
277
|
* @returns {[RuleOffset, T][]}
|
|
278
|
+
*/ sortArbitraryProperties(list) {
|
|
279
|
+
// Collect all known arbitrary properties
|
|
280
|
+
let known = new Set();
|
|
281
|
+
for (let [offset] of list){
|
|
282
|
+
if (offset.arbitrary === 1n) {
|
|
283
|
+
known.add(offset.property);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
// No arbitrary properties? Nothing to do.
|
|
287
|
+
if (known.size === 0) {
|
|
288
|
+
return list;
|
|
289
|
+
}
|
|
290
|
+
// Sort the properties alphabetically
|
|
291
|
+
let properties = Array.from(known).sort();
|
|
292
|
+
// Create a map from the property name to its offset
|
|
293
|
+
let offsets = new Map();
|
|
294
|
+
let offset = 1n;
|
|
295
|
+
for (let property of properties){
|
|
296
|
+
offsets.set(property, offset++);
|
|
297
|
+
}
|
|
298
|
+
// Apply the sorted offsets to the list
|
|
299
|
+
return list.map((item)=>{
|
|
300
|
+
let [offset, rule] = item;
|
|
301
|
+
var _offsets_get;
|
|
302
|
+
offset = {
|
|
303
|
+
...offset,
|
|
304
|
+
propertyOffset: (_offsets_get = offsets.get(offset.property)) !== null && _offsets_get !== void 0 ? _offsets_get : 0n
|
|
305
|
+
};
|
|
306
|
+
return [
|
|
307
|
+
offset,
|
|
308
|
+
rule
|
|
309
|
+
];
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* @template T
|
|
314
|
+
* @param {[RuleOffset, T][]} list
|
|
315
|
+
* @returns {[RuleOffset, T][]}
|
|
270
316
|
*/ sort(list) {
|
|
317
|
+
// Sort arbitrary variants so they're in alphabetical order
|
|
271
318
|
list = this.remapArbitraryVariantOffsets(list);
|
|
319
|
+
// Sort arbitrary properties so they're in alphabetical order
|
|
320
|
+
list = this.sortArbitraryProperties(list);
|
|
272
321
|
return list.sort(([a], [b])=>(0, _bigSign.default)(this.compare(a, b)));
|
|
273
322
|
}
|
|
274
323
|
}
|
|
@@ -111,7 +111,9 @@ function resolveDefaultsAtRules({ tailwindConfig }) {
|
|
|
111
111
|
// we consider them separately because merging the declarations into
|
|
112
112
|
// a single rule will cause browsers that do not understand the
|
|
113
113
|
// vendor prefix to throw out the whole rule
|
|
114
|
-
|
|
114
|
+
// Additionally if a selector contains `:has` we also consider
|
|
115
|
+
// it separately because FF only recently gained support for it
|
|
116
|
+
let selectorGroupName = selector.includes(":-") || selector.includes("::-") || selector.includes(":has") ? selector : "__DEFAULT__";
|
|
115
117
|
var _selectorGroups_get;
|
|
116
118
|
let selectors = (_selectorGroups_get = selectorGroups.get(selectorGroupName)) !== null && _selectorGroups_get !== void 0 ? _selectorGroups_get : new Set();
|
|
117
119
|
selectorGroups.set(selectorGroupName, selectors);
|