Ensure arbitrary variables with data types are extracted correctly (#16986)

Closes #16983

This PR fixes an issue where the arbitrary variable machine did not
extract data type correctly.

## Test plan

- Added regression test
This commit is contained in:
Philipp Spiess 2025-03-06 12:05:33 +01:00 • committed by GitHub
parent af132fbedb
commit bff387bf6b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 62 additions and 1 deletions

View file

@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Ensure classes containing numbers followed by dash or underscore are extracted correctly ([#16980](https://github.com/tailwindlabs/tailwindcss/pull/16980))
- Ensure arbitrary container queries are extracted correctly ([#16984](https://github.com/tailwindlabs/tailwindcss/pull/16984))
- Ensure classes ending in `[` are extracted in Slim templating language ([#16985](https://github.com/tailwindlabs/tailwindcss/pull/16985))
- Ensure arbitrary variables with data types are extracted correctly ([#16986](https://github.com/tailwindlabs/tailwindcss/pull/16986))
## [4.0.10] - 2025-03-05

View file

@ -176,6 +176,8 @@ mod tests {
"[&>[data-slot=icon]:last-child]",
vec!["[&>[data-slot=icon]:last-child]"],
),
// With data types
("[length:32rem]", vec!["[length:32rem]"]),
// Spaces are not allowed
("[ #0088cc ]", vec![]),
// Unbalanced brackets are not allowed

View file

@ -36,6 +36,14 @@ enum State {
#[default]
Idle,
/// Currently parsing the data type of the arbitrary variable
///
/// ```text
/// (length:--my-opacity)
/// ^^^^^^^
/// ```
ParsingDataType,
/// Currently parsing the inside of the arbitrary variable
///
/// ```text
@ -81,6 +89,13 @@ impl Machine for ArbitraryVariableMachine {
self.next(cursor)
}
Class::AlphaLower => {
self.start_pos = cursor.pos;
self.state = State::ParsingDataType;
cursor.advance();
self.next(cursor)
}
_ => MachineState::Idle,
},
@ -89,6 +104,38 @@ impl Machine for ArbitraryVariableMachine {
_ => MachineState::Idle,
},
State::ParsingDataType => {
while cursor.pos < len {
match cursor.curr.into() {
// Valid data type characters
//
// E.g.: `(length:--my-length)`
// ^
Class::AlphaLower | Class::Dash => {
cursor.advance();
}
// End of the data type
//
// E.g.: `(length:--my-length)`
// ^
Class::Colon => match cursor.next.into() {
Class::Dash => {
self.state = State::Parsing;
cursor.advance();
return self.next(cursor);
}
_ => return self.restart(),
},
// Anything else is not a valid character
_ => return self.restart(),
};
}
self.restart()
}
State::Parsing => match self.css_variable_machine.next(cursor) {
MachineState::Idle => self.restart(),
MachineState::Done(_) => match cursor.next.into() {
@ -286,6 +333,8 @@ mod tests {
"(--my-img,url('https://example.com?q=(][)'))",
vec!["(--my-img,url('https://example.com?q=(][)'))"],
),
// With a type hint
("(length:--my-length)", vec!["(length:--my-length)"]),
// --------------------------------------------------------
// Exceptions:

View file

@ -846,7 +846,7 @@ mod tests {
],
);
}
// https://github.com/tailwindlabs/tailwindcss/issues/16978
#[test]
fn test_classes_containing_number_followed_by_dash_or_underscore() {
@ -856,6 +856,15 @@ mod tests {
);
}
// https://github.com/tailwindlabs/tailwindcss/issues/16983
#[test]
fn test_arbitrary_variable_with_data_type() {
assert_extract_sorted_candidates(
r#"<div class="bg-(length:--my-length) bg-[color:var(--my-color)]"></div>"#,
vec!["bg-(length:--my-length)", "bg-[color:var(--my-color)]"],
);
}
#[test]
fn test_extract_css_variables() {
for (input, expected) in [