mirror of
https://github.com/tailwindlabs/tailwindcss.git
synced 2025-12-08 21:36:08 +00:00
Fix class extraction followed by ( in Pug (#17320)
This PR fixes an issue where a class shorthand in Pug followed by a `(` is not properly extracted. ```html <template lang="pug"> .text-sky-600.bg-neutral-900(title="A tooltip") This div has an HTML attribute. </template> ``` The `text-sky-600` is extracted, but the `bg-neutral-900` is not. Fixes: #17313 # Test plan 1. Added test to cover this case 2. Existing tests pass (after a few small adjustments due to _more_ extracted candidates, but definitely not _less_) 3. Verified against the original issue (top is before, bottom is this PR) <img width="1307" alt="image" src="https://github.com/user-attachments/assets/68a0529f-63ad-477d-a342-e3f91c5a1690" /> We had this exact same bug in Slim (https://github.com/tailwindlabs/tailwindcss/pull/17278). Since Pug, Slim and Haml are the only pre processors we have right now with this dot-separated class notation I also double checked the Haml pre-processor if this is an issue or not (and it's already covered there). <img width="1263" alt="image" src="https://github.com/user-attachments/assets/c658168b-d124-46c9-9ec0-9697151a57bf" />
This commit is contained in:
parent
91c0d56d0f
commit
5426baf358
@ -38,6 +38,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Remove redundant `line-height: initial` from Preflight ([#15212](https://github.com/tailwindlabs/tailwindcss/pull/15212))
|
||||
- Increase Standalone hardware compatibility on macOS x64 builds ([#17267](https://github.com/tailwindlabs/tailwindcss/pull/17267))
|
||||
- Ensure that the CSS file rebuilds if a new CSS variable is used from templates ([#17301](https://github.com/tailwindlabs/tailwindcss/pull/17301))
|
||||
- Fix class extraction followed by `(` in Pug ([#17320](https://github.com/tailwindlabs/tailwindcss/pull/17320))
|
||||
|
||||
### Changed
|
||||
|
||||
|
||||
@ -605,7 +605,7 @@ mod tests {
|
||||
// Quoted attribute
|
||||
(
|
||||
r#"input(type="checkbox" class="px-2.5")"#,
|
||||
vec!["checkbox", "class", "px-2.5"],
|
||||
vec!["input", "type", "checkbox", "class", "px-2.5"],
|
||||
),
|
||||
] {
|
||||
assert_extract_sorted_candidates(&pre_process_input(input, "pug"), expected);
|
||||
|
||||
@ -56,6 +56,23 @@ impl PreProcessor for Pug {
|
||||
}
|
||||
}
|
||||
|
||||
// In Pug the class name shorthand can be followed by a parenthesis. E.g.:
|
||||
//
|
||||
// ```pug
|
||||
// body.border-t-4.p-8(attr=value)
|
||||
// ^ Not part of the p-8 class
|
||||
// ```
|
||||
//
|
||||
// This means that we need to replace all these `(` and `)` with spaces to make
|
||||
// sure that we can extract the `p-8`.
|
||||
//
|
||||
// However, we also need to make sure that we keep the parens that are part of the
|
||||
// utility class. E.g.: `bg-(--my-color)`.
|
||||
b'(' if bracket_stack.is_empty() && !matches!(cursor.prev, b'-' | b'/') => {
|
||||
result[cursor.pos] = b' ';
|
||||
bracket_stack.push(cursor.curr);
|
||||
}
|
||||
|
||||
b'(' | b'[' | b'{' => {
|
||||
bracket_stack.push(cursor.curr);
|
||||
}
|
||||
@ -87,7 +104,7 @@ mod tests {
|
||||
("div.flex.bg-red-500", "div flex bg-red-500"),
|
||||
(".flex.bg-red-500", " flex bg-red-500"),
|
||||
// Keep dots in strings
|
||||
(r#"div(class="px-2.5")"#, r#"div(class="px-2.5")"#),
|
||||
(r#"div(class="px-2.5")"#, r#"div class="px-2.5")"#),
|
||||
// Nested brackets
|
||||
(
|
||||
"bg-[url(https://example.com/?q=[1,2])]",
|
||||
@ -134,4 +151,31 @@ mod tests {
|
||||
"#;
|
||||
Pug::test_extract_contains(input, vec!["flex", "items-center"]);
|
||||
}
|
||||
|
||||
// https://github.com/tailwindlabs/tailwindcss/issues/17313
|
||||
#[test]
|
||||
fn test_class_shorthand_followed_by_parens() {
|
||||
let input = r#"
|
||||
.text-sky-600.bg-neutral-900(title="A tooltip") This div has an HTML attribute.
|
||||
"#;
|
||||
Pug::test_extract_contains(input, vec!["text-sky-600", "bg-neutral-900"]);
|
||||
|
||||
// Additional test with CSS Variable shorthand syntax in the attribute itself because `(`
|
||||
// and `)` are not valid in the class shorthand version.
|
||||
//
|
||||
// Also included an arbitrary value including `(` and `)` to make sure that we don't
|
||||
// accidentally remove those either.
|
||||
let input = r#"
|
||||
.p-8(class="bg-(--my-color) bg-(--my-color)/(--my-opacity) bg-[url(https://example.com)]")
|
||||
"#;
|
||||
Pug::test_extract_contains(
|
||||
input,
|
||||
vec![
|
||||
"p-8",
|
||||
"bg-(--my-color)",
|
||||
"bg-(--my-color)/(--my-opacity)",
|
||||
"bg-[url(https://example.com)]",
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,7 +80,7 @@ impl PreProcessor for Slim {
|
||||
bracket_stack.push(cursor.curr);
|
||||
}
|
||||
|
||||
// In slim the class name shorthand can be followed by a parenthesis. E.g.:
|
||||
// In Slim the class name shorthand can be followed by a parenthesis. E.g.:
|
||||
//
|
||||
// ```slim
|
||||
// body.border-t-4.p-8(attr=value)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user