From 6220cb87498ec084948f916f900d079437b1ea25 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Wed, 26 Mar 2025 06:00:10 -0400 Subject: [PATCH 1/2] 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 --- CHANGELOG.md | 4 ++ Cargo.lock | 27 -------- crates/oxide/Cargo.toml | 2 - .../src/extractor/pre_processors/ruby.rs | 62 +++++++++++++++---- 4 files changed, 55 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91803a72f..75049d6de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,10 @@ 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 `@source inline(…)` ([#17147](https://github.com/tailwindlabs/tailwindcss/pull/17147)) +### 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 ### Added diff --git a/Cargo.lock b/Cargo.lock index 31b5529a6..21f0b3a13 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,21 +27,6 @@ dependencies = [ "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]] name = "bitflags" version = "2.6.0" @@ -171,17 +156,6 @@ dependencies = [ "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]] name = "fast-glob" version = "0.4.3" @@ -564,7 +538,6 @@ dependencies = [ "classification-macros", "crossbeam", "dunce", - "fancy-regex", "fast-glob", "globwalk", "ignore", diff --git a/crates/oxide/Cargo.toml b/crates/oxide/Cargo.toml index f3b67d8d7..edcdc64fc 100644 --- a/crates/oxide/Cargo.toml +++ b/crates/oxide/Cargo.toml @@ -19,8 +19,6 @@ bexpand = "1.2.0" fast-glob = "0.4.3" classification-macros = { path = "../classification-macros" } regex = "1.11.1" -fancy-regex = "0.14.0" [dev-dependencies] tempfile = "3.13.0" - diff --git a/crates/oxide/src/extractor/pre_processors/ruby.rs b/crates/oxide/src/extractor/pre_processors/ruby.rs index edc7be49d..3553ad4f6 100644 --- a/crates/oxide/src/extractor/pre_processors/ruby.rs +++ b/crates/oxide/src/extractor/pre_processors/ruby.rs @@ -4,12 +4,22 @@ use crate::cursor; use crate::extractor::bracket_stack; use crate::extractor::pre_processors::pre_processor::PreProcessor; use crate::pre_process_input; -use bstr::ByteSlice; -use fancy_regex::Regex; +use bstr::ByteVec; +use regex::{Regex, RegexBuilder}; use std::sync; -static TEMPLATE_REGEX: sync::LazyLock = sync::LazyLock::new(|| { - Regex::new(r#"\s*(.*?)_template\s*<<[-~]?([A-Z]+?)\n([\s\S]*?)\2"#).unwrap() +static TEMPLATE_START_REGEX: sync::LazyLock = sync::LazyLock::new(|| { + RegexBuilder::new(r#"\s*([a-z0-9_-]+)_template\s*<<[-~]?([A-Z]+)$"#) + .multi_line(true) + .build() + .unwrap() +}); + +static TEMPLATE_END_REGEX: sync::LazyLock = sync::LazyLock::new(|| { + RegexBuilder::new(r#"^\s*([A-Z]+)"#) + .multi_line(true) + .build() + .unwrap() }); #[derive(Debug, Default)] @@ -25,14 +35,44 @@ impl PreProcessor for Ruby { // Extract embedded template languages // https://viewcomponent.org/guide/templates.html#interpolations 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) - .filter_map(Result::ok) - { - let lang = capture.get(1).unwrap().as_str(); - let body = capture.get(3).unwrap().as_str(); - let replaced = pre_process_input(body.as_bytes(), lang); - result = result.replace(body, replaced); + .collect::>(); + let ends = TEMPLATE_END_REGEX + .captures_iter(content_as_str) + .collect::>(); + + 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 From 6b1c6504109010d13727ad29a7f9f73f192355e2 Mon Sep 17 00:00:00 2001 From: Philipp Spiess Date: Wed, 26 Mar 2025 11:03:16 +0100 Subject: [PATCH 2/2] Prepare v4.0.17 release --- CHANGELOG.md | 5 ++++- crates/node/npm/android-arm-eabi/package.json | 2 +- crates/node/npm/android-arm64/package.json | 2 +- crates/node/npm/darwin-arm64/package.json | 2 +- crates/node/npm/darwin-x64/package.json | 2 +- crates/node/npm/freebsd-x64/package.json | 2 +- crates/node/npm/linux-arm-gnueabihf/package.json | 2 +- crates/node/npm/linux-arm64-gnu/package.json | 2 +- crates/node/npm/linux-arm64-musl/package.json | 2 +- crates/node/npm/linux-x64-gnu/package.json | 2 +- crates/node/npm/linux-x64-musl/package.json | 2 +- crates/node/npm/win32-arm64-msvc/package.json | 2 +- crates/node/npm/win32-x64-msvc/package.json | 2 +- crates/node/package.json | 2 +- packages/@tailwindcss-browser/package.json | 2 +- packages/@tailwindcss-cli/package.json | 2 +- packages/@tailwindcss-node/package.json | 2 +- packages/@tailwindcss-postcss/package.json | 2 +- packages/@tailwindcss-standalone/package.json | 2 +- packages/@tailwindcss-upgrade/package.json | 2 +- packages/@tailwindcss-vite/package.json | 2 +- packages/tailwindcss/package.json | 2 +- 22 files changed, 25 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75049d6de..8e1fc1105 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,8 @@ 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 `@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)) @@ -3581,7 +3583,8 @@ No release notes - 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.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 diff --git a/crates/node/npm/android-arm-eabi/package.json b/crates/node/npm/android-arm-eabi/package.json index 5c6804cfb..b28770010 100644 --- a/crates/node/npm/android-arm-eabi/package.json +++ b/crates/node/npm/android-arm-eabi/package.json @@ -1,6 +1,6 @@ { "name": "@tailwindcss/oxide-android-arm-eabi", - "version": "4.0.16", + "version": "4.0.17", "repository": { "type": "git", "url": "git+https://github.com/tailwindlabs/tailwindcss.git", diff --git a/crates/node/npm/android-arm64/package.json b/crates/node/npm/android-arm64/package.json index 472f85b04..45b7166a9 100644 --- a/crates/node/npm/android-arm64/package.json +++ b/crates/node/npm/android-arm64/package.json @@ -1,6 +1,6 @@ { "name": "@tailwindcss/oxide-android-arm64", - "version": "4.0.16", + "version": "4.0.17", "repository": { "type": "git", "url": "git+https://github.com/tailwindlabs/tailwindcss.git", diff --git a/crates/node/npm/darwin-arm64/package.json b/crates/node/npm/darwin-arm64/package.json index 147643206..703908e47 100644 --- a/crates/node/npm/darwin-arm64/package.json +++ b/crates/node/npm/darwin-arm64/package.json @@ -1,6 +1,6 @@ { "name": "@tailwindcss/oxide-darwin-arm64", - "version": "4.0.16", + "version": "4.0.17", "repository": { "type": "git", "url": "git+https://github.com/tailwindlabs/tailwindcss.git", diff --git a/crates/node/npm/darwin-x64/package.json b/crates/node/npm/darwin-x64/package.json index 5e8db6d55..eb6220118 100644 --- a/crates/node/npm/darwin-x64/package.json +++ b/crates/node/npm/darwin-x64/package.json @@ -1,6 +1,6 @@ { "name": "@tailwindcss/oxide-darwin-x64", - "version": "4.0.16", + "version": "4.0.17", "repository": { "type": "git", "url": "git+https://github.com/tailwindlabs/tailwindcss.git", diff --git a/crates/node/npm/freebsd-x64/package.json b/crates/node/npm/freebsd-x64/package.json index 0a72de7c8..0a258b8b3 100644 --- a/crates/node/npm/freebsd-x64/package.json +++ b/crates/node/npm/freebsd-x64/package.json @@ -1,6 +1,6 @@ { "name": "@tailwindcss/oxide-freebsd-x64", - "version": "4.0.16", + "version": "4.0.17", "repository": { "type": "git", "url": "git+https://github.com/tailwindlabs/tailwindcss.git", diff --git a/crates/node/npm/linux-arm-gnueabihf/package.json b/crates/node/npm/linux-arm-gnueabihf/package.json index 7bd1158e3..7fa9a41c6 100644 --- a/crates/node/npm/linux-arm-gnueabihf/package.json +++ b/crates/node/npm/linux-arm-gnueabihf/package.json @@ -1,6 +1,6 @@ { "name": "@tailwindcss/oxide-linux-arm-gnueabihf", - "version": "4.0.16", + "version": "4.0.17", "repository": { "type": "git", "url": "git+https://github.com/tailwindlabs/tailwindcss.git", diff --git a/crates/node/npm/linux-arm64-gnu/package.json b/crates/node/npm/linux-arm64-gnu/package.json index 4c3c990dc..2556cc6a4 100644 --- a/crates/node/npm/linux-arm64-gnu/package.json +++ b/crates/node/npm/linux-arm64-gnu/package.json @@ -1,6 +1,6 @@ { "name": "@tailwindcss/oxide-linux-arm64-gnu", - "version": "4.0.16", + "version": "4.0.17", "repository": { "type": "git", "url": "git+https://github.com/tailwindlabs/tailwindcss.git", diff --git a/crates/node/npm/linux-arm64-musl/package.json b/crates/node/npm/linux-arm64-musl/package.json index a9157f403..c7e681165 100644 --- a/crates/node/npm/linux-arm64-musl/package.json +++ b/crates/node/npm/linux-arm64-musl/package.json @@ -1,6 +1,6 @@ { "name": "@tailwindcss/oxide-linux-arm64-musl", - "version": "4.0.16", + "version": "4.0.17", "repository": { "type": "git", "url": "git+https://github.com/tailwindlabs/tailwindcss.git", diff --git a/crates/node/npm/linux-x64-gnu/package.json b/crates/node/npm/linux-x64-gnu/package.json index 20983e43e..011faa843 100644 --- a/crates/node/npm/linux-x64-gnu/package.json +++ b/crates/node/npm/linux-x64-gnu/package.json @@ -1,6 +1,6 @@ { "name": "@tailwindcss/oxide-linux-x64-gnu", - "version": "4.0.16", + "version": "4.0.17", "repository": { "type": "git", "url": "git+https://github.com/tailwindlabs/tailwindcss.git", diff --git a/crates/node/npm/linux-x64-musl/package.json b/crates/node/npm/linux-x64-musl/package.json index b091157a3..569f7b9cc 100644 --- a/crates/node/npm/linux-x64-musl/package.json +++ b/crates/node/npm/linux-x64-musl/package.json @@ -1,6 +1,6 @@ { "name": "@tailwindcss/oxide-linux-x64-musl", - "version": "4.0.16", + "version": "4.0.17", "repository": { "type": "git", "url": "git+https://github.com/tailwindlabs/tailwindcss.git", diff --git a/crates/node/npm/win32-arm64-msvc/package.json b/crates/node/npm/win32-arm64-msvc/package.json index 8b8cb434c..1c50aa577 100644 --- a/crates/node/npm/win32-arm64-msvc/package.json +++ b/crates/node/npm/win32-arm64-msvc/package.json @@ -1,6 +1,6 @@ { "name": "@tailwindcss/oxide-win32-arm64-msvc", - "version": "4.0.16", + "version": "4.0.17", "repository": { "type": "git", "url": "git+https://github.com/tailwindlabs/tailwindcss.git", diff --git a/crates/node/npm/win32-x64-msvc/package.json b/crates/node/npm/win32-x64-msvc/package.json index 96b95c5eb..0dca1554c 100644 --- a/crates/node/npm/win32-x64-msvc/package.json +++ b/crates/node/npm/win32-x64-msvc/package.json @@ -1,6 +1,6 @@ { "name": "@tailwindcss/oxide-win32-x64-msvc", - "version": "4.0.16", + "version": "4.0.17", "repository": { "type": "git", "url": "git+https://github.com/tailwindlabs/tailwindcss.git", diff --git a/crates/node/package.json b/crates/node/package.json index c19cd4389..9515f247e 100644 --- a/crates/node/package.json +++ b/crates/node/package.json @@ -1,6 +1,6 @@ { "name": "@tailwindcss/oxide", - "version": "4.0.16", + "version": "4.0.17", "repository": { "type": "git", "url": "git+https://github.com/tailwindlabs/tailwindcss.git", diff --git a/packages/@tailwindcss-browser/package.json b/packages/@tailwindcss-browser/package.json index 24b55b21a..ea6b9571a 100644 --- a/packages/@tailwindcss-browser/package.json +++ b/packages/@tailwindcss-browser/package.json @@ -1,6 +1,6 @@ { "name": "@tailwindcss/browser", - "version": "4.0.16", + "version": "4.0.17", "description": "A utility-first CSS framework for rapidly building custom user interfaces.", "license": "MIT", "main": "./dist/index.global.js", diff --git a/packages/@tailwindcss-cli/package.json b/packages/@tailwindcss-cli/package.json index 7c9e21a3d..e0c3de741 100644 --- a/packages/@tailwindcss-cli/package.json +++ b/packages/@tailwindcss-cli/package.json @@ -1,6 +1,6 @@ { "name": "@tailwindcss/cli", - "version": "4.0.16", + "version": "4.0.17", "description": "A utility-first CSS framework for rapidly building custom user interfaces.", "license": "MIT", "repository": { diff --git a/packages/@tailwindcss-node/package.json b/packages/@tailwindcss-node/package.json index a21c9eeed..cece03c34 100644 --- a/packages/@tailwindcss-node/package.json +++ b/packages/@tailwindcss-node/package.json @@ -1,6 +1,6 @@ { "name": "@tailwindcss/node", - "version": "4.0.16", + "version": "4.0.17", "description": "A utility-first CSS framework for rapidly building custom user interfaces.", "license": "MIT", "repository": { diff --git a/packages/@tailwindcss-postcss/package.json b/packages/@tailwindcss-postcss/package.json index 288517419..b7ba3203c 100644 --- a/packages/@tailwindcss-postcss/package.json +++ b/packages/@tailwindcss-postcss/package.json @@ -1,6 +1,6 @@ { "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", "license": "MIT", "repository": { diff --git a/packages/@tailwindcss-standalone/package.json b/packages/@tailwindcss-standalone/package.json index e69254744..1d208043a 100644 --- a/packages/@tailwindcss-standalone/package.json +++ b/packages/@tailwindcss-standalone/package.json @@ -1,6 +1,6 @@ { "name": "@tailwindcss/standalone", - "version": "4.0.16", + "version": "4.0.17", "private": true, "description": "Standalone CLI for Tailwind CSS", "license": "MIT", diff --git a/packages/@tailwindcss-upgrade/package.json b/packages/@tailwindcss-upgrade/package.json index 235db127d..8e06c1824 100644 --- a/packages/@tailwindcss-upgrade/package.json +++ b/packages/@tailwindcss-upgrade/package.json @@ -1,6 +1,6 @@ { "name": "@tailwindcss/upgrade", - "version": "4.0.16", + "version": "4.0.17", "description": "A utility-first CSS framework for rapidly building custom user interfaces.", "license": "MIT", "repository": { diff --git a/packages/@tailwindcss-vite/package.json b/packages/@tailwindcss-vite/package.json index c180da594..7790be271 100644 --- a/packages/@tailwindcss-vite/package.json +++ b/packages/@tailwindcss-vite/package.json @@ -1,6 +1,6 @@ { "name": "@tailwindcss/vite", - "version": "4.0.16", + "version": "4.0.17", "description": "A utility-first CSS framework for rapidly building custom user interfaces.", "license": "MIT", "repository": { diff --git a/packages/tailwindcss/package.json b/packages/tailwindcss/package.json index c65250771..008c50857 100644 --- a/packages/tailwindcss/package.json +++ b/packages/tailwindcss/package.json @@ -1,6 +1,6 @@ { "name": "tailwindcss", - "version": "4.0.16", + "version": "4.0.17", "description": "A utility-first CSS framework for rapidly building custom user interfaces.", "license": "MIT", "repository": {