From cedd54fecf99aae81dd6d282d066c493c8036744 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Wed, 12 Mar 2025 22:04:11 +0100 Subject: [PATCH] Fix variants with `.` are extracted correctly (#17153) This PR fixes an issue where if you use a number with a decimal in a variant then it wasn't picked up correctly. E.g.: ```
^^^^^^^^ Picked up ^^^^^^^^^^ Not picket up ``` This PR fixes that behavior by applying the same rules for utilities where a `.` is valid if it is surrounded by numbers. # Test plan 1. Added test to ensure this is picked up 2. Existing tests pass 3. Ran the extractor on a real example with the following results: | Before | After | | --- | --- | | image | image | They are crossed out just because it's not a default value we know in the system, but you can see that the `1.` part is also extracted now. Fixes: #17148 --- CHANGELOG.md | 1 + .../src/extractor/named_variant_machine.rs | 30 +++++++++++-------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 635f62f72..517c7d5da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Do not extract candidates with JS string interpolation `${` ([#17142](https://github.com/tailwindlabs/tailwindcss/pull/17142)) +- Fix extraction of variants containing `.` character ([#17153](https://github.com/tailwindlabs/tailwindcss/pull/17153)) ## [4.0.13] - 2025-03-11 diff --git a/crates/oxide/src/extractor/named_variant_machine.rs b/crates/oxide/src/extractor/named_variant_machine.rs index 649947b73..642c568a3 100644 --- a/crates/oxide/src/extractor/named_variant_machine.rs +++ b/crates/oxide/src/extractor/named_variant_machine.rs @@ -235,6 +235,22 @@ impl Machine for NamedVariantMachine { // ^ Class::Colon => return self.done(self.start_pos, cursor), + // A dot must be surrounded by numbers + // + // E.g.: `2.5xl:flex` + // ^^^ + Class::Dot => { + if !matches!(cursor.prev.into(), Class::Number) { + return self.restart(); + } + + if !matches!(cursor.next.into(), Class::Number) { + return self.restart(); + } + + cursor.advance(); + } + // Everything else is invalid _ => return self.restart(), }; @@ -325,24 +341,15 @@ enum Class { #[bytes(b'.')] Dot, - #[bytes(b'\0')] - End, - #[bytes_range(b'0'..=b'9')] Number, #[bytes(b'[')] OpenBracket, - #[bytes(b']')] - CloseBracket, - #[bytes(b'(')] OpenParen, - #[bytes(b'\'', b'"', b'`')] - Quote, - #[bytes(b'*')] Star, @@ -352,9 +359,6 @@ enum Class { #[bytes(b'_')] Underscore, - #[bytes(b' ', b'\t', b'\n', b'\r', b'\x0C')] - Whitespace, - #[fallback] Other, } @@ -391,6 +395,8 @@ mod tests { vec!["group-[data-state=pending]/name:"], ), ("supports-(--foo)/name:flex", vec!["supports-(--foo)/name:"]), + // Odd media queries + ("1.5xl:flex", vec!["1.5xl:"]), // Container queries ("@md:flex", vec!["@md:"]), ("@max-md:flex", vec!["@max-md:"]),