Skip to content

Commit f498e4a

Browse files
authored
Ensure extracting candidates from JS embedded in a PHP string works as expected (#17031)
This PR fixes an issue where candidates are not properly extractor when they end in `\`. This can happen if you embed a programming language like JS inside another language like PHP where you need to escape some strings. Here is an example of Livewire flux: ```blade @php if ($sidebarIsStashable) { $attributes = $attributes->merge([ 'x-init' => '$el.classList.add(\'-translate-x-full\'); $el.classList.add(\'transition-transform\')', // ^ ^ ]); } @endphp <div x-data {{ $attributes->class('border-r w-64 p-4 min-h-dvh max-h-dvh top-0 fixed left-0') }}> {{ $slot }} </div> ``` Where the `\'` is causing some issues. Another solution might be to add a custom pre processor for blade files where we drop the escaped characters, but that felt overkill for now because some escapes are still valid. Fixes: #17023 # Test plan 1. Added a test to cover this case. 2. Existing tests still pass
1 parent 225f323 commit f498e4a

File tree

3 files changed

+46
-0
lines changed

3 files changed

+46
-0
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2525
- Ensure strings in Pug and Slim templates are handled correctly ([#17000](https://github.com/tailwindlabs/tailwindcss/pull/17000))
2626
- Ensure `}` and `{` are valid boundary characters when extracting candidates ([#17001](https://github.com/tailwindlabs/tailwindcss/pull/17001))
2727
- Add `razor`/`cshtml` pre processing ([#17027](https://github.com/tailwindlabs/tailwindcss/pull/17027))
28+
- Ensure extracting candidates from JS embedded in a PHP string works as expected ([#17031](https://github.com/tailwindlabs/tailwindcss/pull/17031))
2829

2930
## [4.0.11] - 2025-03-06
3031

crates/oxide/src/extractor/boundary.rs

+12
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,18 @@ enum Class {
9797
// ^
9898
// ```
9999
#[bytes(b'=')]
100+
// Escaped character when embedding one language in another via strings, e.g.:
101+
//
102+
// ```
103+
// $attributes->merge([
104+
// 'x-init' => '$el.classList.add(\'-translate-x-full\'); $el.classList.add(\'transition-transform\')',
105+
// ^ ^
106+
// ]);
107+
// ```
108+
//
109+
// In this case there is some JavaScript embedded in an string in PHP and some of the quotes
110+
// need to be escaped.
111+
#[bytes(b'\\')]
100112
After,
101113

102114
#[fallback]

crates/oxide/src/extractor/mod.rs

+33
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,39 @@ mod tests {
888888
);
889889
}
890890

891+
#[test]
892+
fn test_js_embedded_in_php_syntax() {
893+
// Escaped single quotes
894+
let input = r#"
895+
@php
896+
if ($sidebarIsStashable) {
897+
$attributes = $attributes->merge([
898+
'x-init' => '$el.classList.add(\'-translate-x-full\'); $el.classList.add(\'transition-transform\')',
899+
]);
900+
}
901+
@endphp
902+
"#;
903+
assert_extract_candidates_contains(
904+
input,
905+
vec!["-translate-x-full", "transition-transform"],
906+
);
907+
908+
// Double quotes
909+
let input = r#"
910+
@php
911+
if ($sidebarIsStashable) {
912+
$attributes = $attributes->merge([
913+
'x-init' => "\$el.classList.add('-translate-x-full'); \$el.classList.add('transition-transform')",
914+
]);
915+
}
916+
@endphp
917+
"#;
918+
assert_extract_candidates_contains(
919+
input,
920+
vec!["-translate-x-full", "transition-transform"],
921+
);
922+
}
923+
891924
// https://github.com/tailwindlabs/tailwindcss/issues/16978
892925
#[test]
893926
fn test_classes_containing_number_followed_by_dash_or_underscore() {

0 commit comments

Comments
 (0)