diff --git a/CHANGELOG.md b/CHANGELOG.md index 23469db88876..a4a9559af9e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Treat starting single quote as verbatim text in Slim ([#17085](https://github.com/tailwindlabs/tailwindcss/pull/17085)) - Ensure `.node` and `.wasm` files are not scanned for utilities ([#17123](https://github.com/tailwindlabs/tailwindcss/pull/17123)) - Improve performance when scanning `JSON` files ([#17125](https://github.com/tailwindlabs/tailwindcss/pull/17125)) +- Don't create invalid CSS when encountering a link wrapped in square brackets ([#17129](https://github.com/tailwindlabs/tailwindcss/pull/17129)) ## [4.0.12] - 2025-03-07 diff --git a/crates/oxide/src/extractor/arbitrary_property_machine.rs b/crates/oxide/src/extractor/arbitrary_property_machine.rs index c1460092fca2..947073c2fb99 100644 --- a/crates/oxide/src/extractor/arbitrary_property_machine.rs +++ b/crates/oxide/src/extractor/arbitrary_property_machine.rs @@ -163,6 +163,7 @@ impl Machine for ArbitraryPropertyMachine { #[inline] fn next(&mut self, cursor: &mut cursor::Cursor<'_>) -> MachineState { let len = cursor.input.len(); + let start_of_value_pos = cursor.pos; while cursor.pos < len { match cursor.curr.into() { Class::Escape => match cursor.next.into() { @@ -222,6 +223,9 @@ impl Machine for ArbitraryPropertyMachine { // Any kind of whitespace is not allowed Class::Whitespace => return self.restart(), + // URLs are not allowed + Class::Slash if start_of_value_pos == cursor.pos => return self.restart(), + // Everything else is valid _ => cursor.advance(), }; @@ -278,6 +282,9 @@ enum Class { #[bytes(b':')] Colon, + #[bytes(b'/')] + Slash, + #[bytes(b' ', b'\t', b'\n', b'\r', b'\x0C')] Whitespace, @@ -341,6 +348,9 @@ mod tests { ("[:red]", vec![]), // Empty brackets are not allowed ("[]", vec![]), + // URLs + ("[http://example.com]", vec![]), + ("[https://example.com]", vec![]), // Missing colon in more complex example (r#"[CssClass("gap-y-4")]"#, vec![]), // Brackets must be balanced