Compare commits

...
Sign in to create a new pull request.

2 commits

Author SHA1 Message Date
Philipp Spiess
6b1c650410 Prepare v4.0.17 release 2025-03-26 11:03:16 +01:00
Jordan Pittman
6220cb8749 Fix Ruby files causing the CLI to hang (#17383)
Fixes #17379

The preprocessor we added to detect embedded languages uses a back
reference and given a long enough file with certain byte / character
patterns it'll cause what appears to be an indefinite hang (might just
be catastrophically exponential backtracking but not sure)

This replaces the one regex w/ back references with two, anchored,
multi-line regexes

Now we search for all the starting & ending delimiters in the file. We
then loop over all the starting delimiters, find the paired ending one,
and preprocess the content inside

---------

Co-authored-by: Philipp Spiess <hello@philippspiess.com>
2025-03-26 11:02:09 +01:00
25 changed files with 80 additions and 62 deletions

View file

@ -20,6 +20,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- _Experimental_: Add `wrap-anywhere`, `wrap-break-word`, and `wrap-normal` utilities ([#12128](https://github.com/tailwindlabs/tailwindcss/pull/12128)) - _Experimental_: Add `wrap-anywhere`, `wrap-break-word`, and `wrap-normal` utilities ([#12128](https://github.com/tailwindlabs/tailwindcss/pull/12128))
- _Experimental_: Add `@source inline(…)` ([#17147](https://github.com/tailwindlabs/tailwindcss/pull/17147)) - _Experimental_: Add `@source inline(…)` ([#17147](https://github.com/tailwindlabs/tailwindcss/pull/17147))
## [4.0.17] - 2025-03-26
### Fixed
- Fix an issue causing the CLI to hang when processing Ruby files ([#17383](https://github.com/tailwindlabs/tailwindcss/pull/17383))
## [4.0.16] - 2025-03-25 ## [4.0.16] - 2025-03-25
### Added ### Added
@ -3577,7 +3583,8 @@ No release notes
- Everything! - Everything!
[unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v4.0.16...HEAD [unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v4.0.17...HEAD
[4.0.17]: https://github.com/tailwindlabs/tailwindcss/compare/v4.0.16...v4.0.17
[4.0.16]: https://github.com/tailwindlabs/tailwindcss/compare/v4.0.15...v4.0.16 [4.0.16]: https://github.com/tailwindlabs/tailwindcss/compare/v4.0.15...v4.0.16
[4.0.15]: https://github.com/tailwindlabs/tailwindcss/compare/v4.0.14...v4.0.15 [4.0.15]: https://github.com/tailwindlabs/tailwindcss/compare/v4.0.14...v4.0.15
[4.0.14]: https://github.com/tailwindlabs/tailwindcss/compare/v4.0.13...v4.0.14 [4.0.14]: https://github.com/tailwindlabs/tailwindcss/compare/v4.0.13...v4.0.14

27
Cargo.lock generated
View file

@ -27,21 +27,6 @@ dependencies = [
"nom", "nom",
] ]
[[package]]
name = "bit-set"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3"
dependencies = [
"bit-vec",
]
[[package]]
name = "bit-vec"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.6.0" version = "2.6.0"
@ -171,17 +156,6 @@ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "fancy-regex"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e24cb5a94bcae1e5408b0effca5cd7172ea3c5755049c5f3af4cd283a165298"
dependencies = [
"bit-set",
"regex-automata 0.4.8",
"regex-syntax 0.8.5",
]
[[package]] [[package]]
name = "fast-glob" name = "fast-glob"
version = "0.4.3" version = "0.4.3"
@ -564,7 +538,6 @@ dependencies = [
"classification-macros", "classification-macros",
"crossbeam", "crossbeam",
"dunce", "dunce",
"fancy-regex",
"fast-glob", "fast-glob",
"globwalk", "globwalk",
"ignore", "ignore",

View file

@ -1,6 +1,6 @@
{ {
"name": "@tailwindcss/oxide-android-arm-eabi", "name": "@tailwindcss/oxide-android-arm-eabi",
"version": "4.0.16", "version": "4.0.17",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/tailwindlabs/tailwindcss.git", "url": "git+https://github.com/tailwindlabs/tailwindcss.git",

View file

@ -1,6 +1,6 @@
{ {
"name": "@tailwindcss/oxide-android-arm64", "name": "@tailwindcss/oxide-android-arm64",
"version": "4.0.16", "version": "4.0.17",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/tailwindlabs/tailwindcss.git", "url": "git+https://github.com/tailwindlabs/tailwindcss.git",

View file

@ -1,6 +1,6 @@
{ {
"name": "@tailwindcss/oxide-darwin-arm64", "name": "@tailwindcss/oxide-darwin-arm64",
"version": "4.0.16", "version": "4.0.17",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/tailwindlabs/tailwindcss.git", "url": "git+https://github.com/tailwindlabs/tailwindcss.git",

View file

@ -1,6 +1,6 @@
{ {
"name": "@tailwindcss/oxide-darwin-x64", "name": "@tailwindcss/oxide-darwin-x64",
"version": "4.0.16", "version": "4.0.17",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/tailwindlabs/tailwindcss.git", "url": "git+https://github.com/tailwindlabs/tailwindcss.git",

View file

@ -1,6 +1,6 @@
{ {
"name": "@tailwindcss/oxide-freebsd-x64", "name": "@tailwindcss/oxide-freebsd-x64",
"version": "4.0.16", "version": "4.0.17",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/tailwindlabs/tailwindcss.git", "url": "git+https://github.com/tailwindlabs/tailwindcss.git",

View file

@ -1,6 +1,6 @@
{ {
"name": "@tailwindcss/oxide-linux-arm-gnueabihf", "name": "@tailwindcss/oxide-linux-arm-gnueabihf",
"version": "4.0.16", "version": "4.0.17",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/tailwindlabs/tailwindcss.git", "url": "git+https://github.com/tailwindlabs/tailwindcss.git",

View file

@ -1,6 +1,6 @@
{ {
"name": "@tailwindcss/oxide-linux-arm64-gnu", "name": "@tailwindcss/oxide-linux-arm64-gnu",
"version": "4.0.16", "version": "4.0.17",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/tailwindlabs/tailwindcss.git", "url": "git+https://github.com/tailwindlabs/tailwindcss.git",

View file

@ -1,6 +1,6 @@
{ {
"name": "@tailwindcss/oxide-linux-arm64-musl", "name": "@tailwindcss/oxide-linux-arm64-musl",
"version": "4.0.16", "version": "4.0.17",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/tailwindlabs/tailwindcss.git", "url": "git+https://github.com/tailwindlabs/tailwindcss.git",

View file

@ -1,6 +1,6 @@
{ {
"name": "@tailwindcss/oxide-linux-x64-gnu", "name": "@tailwindcss/oxide-linux-x64-gnu",
"version": "4.0.16", "version": "4.0.17",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/tailwindlabs/tailwindcss.git", "url": "git+https://github.com/tailwindlabs/tailwindcss.git",

View file

@ -1,6 +1,6 @@
{ {
"name": "@tailwindcss/oxide-linux-x64-musl", "name": "@tailwindcss/oxide-linux-x64-musl",
"version": "4.0.16", "version": "4.0.17",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/tailwindlabs/tailwindcss.git", "url": "git+https://github.com/tailwindlabs/tailwindcss.git",

View file

@ -1,6 +1,6 @@
{ {
"name": "@tailwindcss/oxide-win32-arm64-msvc", "name": "@tailwindcss/oxide-win32-arm64-msvc",
"version": "4.0.16", "version": "4.0.17",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/tailwindlabs/tailwindcss.git", "url": "git+https://github.com/tailwindlabs/tailwindcss.git",

View file

@ -1,6 +1,6 @@
{ {
"name": "@tailwindcss/oxide-win32-x64-msvc", "name": "@tailwindcss/oxide-win32-x64-msvc",
"version": "4.0.16", "version": "4.0.17",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/tailwindlabs/tailwindcss.git", "url": "git+https://github.com/tailwindlabs/tailwindcss.git",

View file

@ -1,6 +1,6 @@
{ {
"name": "@tailwindcss/oxide", "name": "@tailwindcss/oxide",
"version": "4.0.16", "version": "4.0.17",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/tailwindlabs/tailwindcss.git", "url": "git+https://github.com/tailwindlabs/tailwindcss.git",

View file

@ -19,8 +19,6 @@ bexpand = "1.2.0"
fast-glob = "0.4.3" fast-glob = "0.4.3"
classification-macros = { path = "../classification-macros" } classification-macros = { path = "../classification-macros" }
regex = "1.11.1" regex = "1.11.1"
fancy-regex = "0.14.0"
[dev-dependencies] [dev-dependencies]
tempfile = "3.13.0" tempfile = "3.13.0"

View file

@ -4,12 +4,22 @@ use crate::cursor;
use crate::extractor::bracket_stack; use crate::extractor::bracket_stack;
use crate::extractor::pre_processors::pre_processor::PreProcessor; use crate::extractor::pre_processors::pre_processor::PreProcessor;
use crate::pre_process_input; use crate::pre_process_input;
use bstr::ByteSlice; use bstr::ByteVec;
use fancy_regex::Regex; use regex::{Regex, RegexBuilder};
use std::sync; use std::sync;
static TEMPLATE_REGEX: sync::LazyLock<Regex> = sync::LazyLock::new(|| { static TEMPLATE_START_REGEX: sync::LazyLock<Regex> = sync::LazyLock::new(|| {
Regex::new(r#"\s*(.*?)_template\s*<<[-~]?([A-Z]+?)\n([\s\S]*?)\2"#).unwrap() RegexBuilder::new(r#"\s*([a-z0-9_-]+)_template\s*<<[-~]?([A-Z]+)$"#)
.multi_line(true)
.build()
.unwrap()
});
static TEMPLATE_END_REGEX: sync::LazyLock<Regex> = sync::LazyLock::new(|| {
RegexBuilder::new(r#"^\s*([A-Z]+)"#)
.multi_line(true)
.build()
.unwrap()
}); });
#[derive(Debug, Default)] #[derive(Debug, Default)]
@ -25,14 +35,44 @@ impl PreProcessor for Ruby {
// Extract embedded template languages // Extract embedded template languages
// https://viewcomponent.org/guide/templates.html#interpolations // https://viewcomponent.org/guide/templates.html#interpolations
let content_as_str = std::str::from_utf8(content).unwrap(); let content_as_str = std::str::from_utf8(content).unwrap();
for capture in TEMPLATE_REGEX
let starts = TEMPLATE_START_REGEX
.captures_iter(content_as_str) .captures_iter(content_as_str)
.filter_map(Result::ok) .collect::<Vec<_>>();
{ let ends = TEMPLATE_END_REGEX
let lang = capture.get(1).unwrap().as_str(); .captures_iter(content_as_str)
let body = capture.get(3).unwrap().as_str(); .collect::<Vec<_>>();
let replaced = pre_process_input(body.as_bytes(), lang);
result = result.replace(body, replaced); for start in starts.iter() {
// The language for this block
let lang = start.get(1).unwrap().as_str();
// The HEREDOC delimiter
let delimiter_start = start.get(2).unwrap().as_str();
// Where the "body" starts for the HEREDOC block
let body_start = start.get(0).unwrap().end();
// Look through all of the ends to find a matching language
for end in ends.iter() {
// 1. This must appear after the start
let body_end = end.get(0).unwrap().start();
if body_end < body_start {
continue;
}
// The languages must match otherwise we haven't found the end
let delimiter_end = end.get(1).unwrap().as_str();
if delimiter_end != delimiter_start {
continue;
}
let body = &content_as_str[body_start..body_end];
let replaced = pre_process_input(body.as_bytes(), &lang.to_ascii_lowercase());
result.replace_range(body_start..body_end, replaced);
break;
}
} }
// Ruby extraction // Ruby extraction

View file

@ -1,6 +1,6 @@
{ {
"name": "@tailwindcss/browser", "name": "@tailwindcss/browser",
"version": "4.0.16", "version": "4.0.17",
"description": "A utility-first CSS framework for rapidly building custom user interfaces.", "description": "A utility-first CSS framework for rapidly building custom user interfaces.",
"license": "MIT", "license": "MIT",
"main": "./dist/index.global.js", "main": "./dist/index.global.js",

View file

@ -1,6 +1,6 @@
{ {
"name": "@tailwindcss/cli", "name": "@tailwindcss/cli",
"version": "4.0.16", "version": "4.0.17",
"description": "A utility-first CSS framework for rapidly building custom user interfaces.", "description": "A utility-first CSS framework for rapidly building custom user interfaces.",
"license": "MIT", "license": "MIT",
"repository": { "repository": {

View file

@ -1,6 +1,6 @@
{ {
"name": "@tailwindcss/node", "name": "@tailwindcss/node",
"version": "4.0.16", "version": "4.0.17",
"description": "A utility-first CSS framework for rapidly building custom user interfaces.", "description": "A utility-first CSS framework for rapidly building custom user interfaces.",
"license": "MIT", "license": "MIT",
"repository": { "repository": {

View file

@ -1,6 +1,6 @@
{ {
"name": "@tailwindcss/postcss", "name": "@tailwindcss/postcss",
"version": "4.0.16", "version": "4.0.17",
"description": "PostCSS plugin for Tailwind CSS, a utility-first CSS framework for rapidly building custom user interfaces", "description": "PostCSS plugin for Tailwind CSS, a utility-first CSS framework for rapidly building custom user interfaces",
"license": "MIT", "license": "MIT",
"repository": { "repository": {

View file

@ -1,6 +1,6 @@
{ {
"name": "@tailwindcss/standalone", "name": "@tailwindcss/standalone",
"version": "4.0.16", "version": "4.0.17",
"private": true, "private": true,
"description": "Standalone CLI for Tailwind CSS", "description": "Standalone CLI for Tailwind CSS",
"license": "MIT", "license": "MIT",

View file

@ -1,6 +1,6 @@
{ {
"name": "@tailwindcss/upgrade", "name": "@tailwindcss/upgrade",
"version": "4.0.16", "version": "4.0.17",
"description": "A utility-first CSS framework for rapidly building custom user interfaces.", "description": "A utility-first CSS framework for rapidly building custom user interfaces.",
"license": "MIT", "license": "MIT",
"repository": { "repository": {

View file

@ -1,6 +1,6 @@
{ {
"name": "@tailwindcss/vite", "name": "@tailwindcss/vite",
"version": "4.0.16", "version": "4.0.17",
"description": "A utility-first CSS framework for rapidly building custom user interfaces.", "description": "A utility-first CSS framework for rapidly building custom user interfaces.",
"license": "MIT", "license": "MIT",
"repository": { "repository": {

View file

@ -1,6 +1,6 @@
{ {
"name": "tailwindcss", "name": "tailwindcss",
"version": "4.0.16", "version": "4.0.17",
"description": "A utility-first CSS framework for rapidly building custom user interfaces.", "description": "A utility-first CSS framework for rapidly building custom user interfaces.",
"license": "MIT", "license": "MIT",
"repository": { "repository": {