Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: tailwindlabs/tailwindcss
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v4.0.15
Choose a base ref
...
head repository: tailwindlabs/tailwindcss
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v4.0.16
Choose a head ref
  • 10 commits
  • 42 files changed
  • 5 contributors

Commits on Mar 20, 2025

  1. Revert "Temporarily revert changes to `@utility"

    This reverts commit 1aab04c.
    thecrypticace committed Mar 20, 2025
    Copy the full SHA
    91c0d56 View commit details

Commits on Mar 21, 2025

  1. 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
    (#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"
    />
    RobinMalfait authored Mar 21, 2025
    Copy the full SHA
    5426baf View commit details

Commits on Mar 24, 2025

  1. Update all of nextjs 15.2.1 → 15.2.3 (patch) (#17337)

    depfu[bot] authored Mar 24, 2025
    Copy the full SHA
    1c481b8 View commit details
  2. Fix changelog (#17348)

    This change was added in #17320 which was not released yet, see commit
    order on `main`:
    https://github.com/tailwindlabs/tailwindcss/commits/main/
    philipp-spiess authored Mar 24, 2025
    Copy the full SHA
    42f68bb View commit details
  3. Vite: Emit build dependencies on partial rebuilds (#17347)

    Closes #17339
    
    This PR fixes an issue that caused changes to `@import`-ed CSS files to
    no longer rebuild the stylesheet after a change was made to a template
    file.
    
    The change in the template file causes a fast-path in the Vite plugin
    now after changes in 4.0.8: _partial rebuilds_. For that branch we do
    not need to re-evaluate your input CSS since we know only the candidate
    list changed. However, we still need to emit all build dependencies as
    via `addWatchFile(…)`, otherwise Vite will not correctly register
    updates for these dependencies anymore.
    
    ## Test plan
    
    - Updated the kitchen-sink Vite update tests to ensure that an
    `@import`-ed CSS file can be updated even after a partial rebuild.
    - Ensure this works in our Vite playground
    philipp-spiess authored Mar 24, 2025
    Copy the full SHA
    fac8f7d View commit details
  4. Pre process Slim templates embedded in Ruby files (#17336)

    This PR fixes an issue where embedded Slim templates inside of Ruby
    files are not pre processed because we pre process based on a file
    extension.
    
    This PR also handles embedded SLIM templates using the following syntax:
    
    ```rb
    slim_template <<~SLIM
      .flex
        .flex-1
          h1 Hello World
        .flex-1
          p This is a test
    SLIM
    ```
    
    ~~As far as I can tell, this is only a Slim template thing and not a
    Haml template thing but I could be wrong here. See:
    https://viewcomponent.org/guide/templates.html#interpolations~~
    
    The ViewComponent package handles anything that looks like
    `{lang}_template`, so the lang here will be used as the pre processing
    language for now.
    
    Fixes: #17334
    
    # Test plan
    
    1. Added test for this
    2. Existing tests pass
    3. Made sure that the snippet from the issue works as expected:
    
    Added an example where we have a `slim_template` and a `svelte_template`
    to prove that it embeds based on the language. I also added a
    `html_template` with Svelte syntax to really make sure that that
    _doesn't_ work.
    
    <img width="1816" alt="image"
    src="https://github.com/user-attachments/assets/35564a32-9c46-4b51-bb1f-e02f4ffe8b01"
    />
    RobinMalfait authored Mar 24, 2025
    Copy the full SHA
    711b9cd View commit details
  5. Add Input & Output check to CLI (#17311)

    Throw an error if the input and output file for the CLI are identical.
    
    ---------
    
    Co-authored-by: Philipp Spiess <hello@philippspiess.com>
    Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
    3 people authored Mar 24, 2025
    Copy the full SHA
    baa016a View commit details
  6. Extract keyframe name when followed by comma (#17352)

    Fixes #17332
    
    This PR ensures that keyframes are emitted even when they are referenced
    following a comma, e.g.:
    
    ```css
    @theme {
      --animate-test: 500ms both fade-in, 1000ms linear 500ms spin infinite;
                                     /* ^ */
    
      @Keyframes fade-in {
        from {
          opacity: 0%;
        }
        to {
          opacity: 100%;
        }
      }
    }
    ```
    
    ## Test plan
    
    Added a unit test to capture the issue from #17332
    philipp-spiess authored Mar 24, 2025
    Copy the full SHA
    e8715d0 View commit details

Commits on Mar 25, 2025

  1. Add ::-webkit-details-marker pseudo to marker variant (#17362)

    See #17360
    
    This PR updates the `marker` variant to also target the marker present
    in `<summary>` elements in WebKit browsers. Chromium uses `::marker` and
    is therefore already covered.
    
    ---------
    
    Co-authored-by: Philipp Spiess <hello@philippspiess.com>
    thecrypticace and philipp-spiess authored Mar 25, 2025
    Copy the full SHA
    bd501e8 View commit details
  2. Prepare v4.0.16 release (#17372)

    Prepare the 4.0.16 release.
    
    ~~Also added a commit to mark the `--value('…')` and `--modifier('…')`
    with literals strings as an experimental feature (aka not shipped in
    this PR). But we can revert that commit if we still want to ship it in
    4.0.16 instead of 4.1.~~
    
    ---------
    
    Co-authored-by: Philipp Spiess <hello@philippspiess.com>
    RobinMalfait and philipp-spiess authored Mar 25, 2025
    Copy the full SHA
    1c50b5c View commit details
Showing with 677 additions and 167 deletions.
  1. +18 −1 CHANGELOG.md
  2. +27 −0 Cargo.lock
  3. +1 −1 crates/node/npm/android-arm-eabi/package.json
  4. +1 −1 crates/node/npm/android-arm64/package.json
  5. +1 −1 crates/node/npm/darwin-arm64/package.json
  6. +1 −1 crates/node/npm/darwin-x64/package.json
  7. +1 −1 crates/node/npm/freebsd-x64/package.json
  8. +1 −1 crates/node/npm/linux-arm-gnueabihf/package.json
  9. +1 −1 crates/node/npm/linux-arm64-gnu/package.json
  10. +1 −1 crates/node/npm/linux-arm64-musl/package.json
  11. +1 −1 crates/node/npm/linux-x64-gnu/package.json
  12. +1 −1 crates/node/npm/linux-x64-musl/package.json
  13. +1 −1 crates/node/npm/win32-arm64-msvc/package.json
  14. +1 −1 crates/node/npm/win32-x64-msvc/package.json
  15. +1 −1 crates/node/package.json
  16. +1 −0 crates/oxide/Cargo.toml
  17. +1 −1 crates/oxide/src/extractor/mod.rs
  18. +45 −1 crates/oxide/src/extractor/pre_processors/pug.rs
  19. +69 −0 crates/oxide/src/extractor/pre_processors/ruby.rs
  20. +1 −1 crates/oxide/src/extractor/pre_processors/slim.rs
  21. +70 −0 integrations/cli/index.test.ts
  22. +48 −0 integrations/vite/index.test.ts
  23. +1 −1 packages/@tailwindcss-browser/package.json
  24. +1 −1 packages/@tailwindcss-cli/package.json
  25. +11 −0 packages/@tailwindcss-cli/src/commands/build/index.ts
  26. +1 −1 packages/@tailwindcss-node/package.json
  27. +1 −1 packages/@tailwindcss-postcss/package.json
  28. +1 −1 packages/@tailwindcss-standalone/package.json
  29. +1 −1 packages/@tailwindcss-upgrade/package.json
  30. +1 −1 packages/@tailwindcss-vite/package.json
  31. +4 −0 packages/@tailwindcss-vite/src/index.ts
  32. +1 −1 packages/tailwindcss/package.json
  33. +8 −4 packages/tailwindcss/src/ast.ts
  34. +43 −0 packages/tailwindcss/src/index.test.ts
  35. +38 −3 packages/tailwindcss/src/intellisense.test.ts
  36. +36 −1 packages/tailwindcss/src/utilities.test.ts
  37. +152 −65 packages/tailwindcss/src/utilities.ts
  38. +16 −0 packages/tailwindcss/src/variants.test.ts
  39. +6 −2 packages/tailwindcss/src/variants.ts
  40. +2 −2 playgrounds/nextjs/package.json
  41. +2 −2 playgrounds/v3/package.json
  42. +58 −63 pnpm-lock.yaml
19 changes: 18 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -20,6 +20,22 @@ 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.16] - 2025-03-25

### Added

- Add support for literal values in `--value('…')` and `--modifier('…')` ([#17304](https://github.com/tailwindlabs/tailwindcss/pull/17304))

### Fixed

- Fix class extraction followed by `(` in Pug ([#17320](https://github.com/tailwindlabs/tailwindcss/pull/17320))
- Ensure `@keyframes` for theme animations are emitted if they are referenced following a comma ([#17352](https://github.com/tailwindlabs/tailwindcss/pull/17352))
- Vite: Ensure that updates to an imported CSS file are properly propagated after updating source files ([#17347](https://github.com/tailwindlabs/tailwindcss/pull/17347))
- Pre process `Slim` templates embedded in Ruby files ([#17336](https://github.com/tailwindlabs/tailwindcss/pull/17336))
- Error when input and output files resolve to the same file when using the CLI ([#17311](https://github.com/tailwindlabs/tailwindcss/pull/17311))
- Add missing suggestions when `--spacing(--value(integer, number))` is used ([#17308](https://github.com/tailwindlabs/tailwindcss/pull/17308))
- Add `::-webkit-details-marker` pseudo to `marker` variant ([#17362](https://github.com/tailwindlabs/tailwindcss/pull/17362))

### [4.0.15] - 2025-03-20

### Fixed
@@ -3561,7 +3577,8 @@ No release notes

- Everything!

[unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v4.0.15...HEAD
[unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v4.0.16...HEAD
[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
[4.0.13]: https://github.com/tailwindlabs/tailwindcss/compare/v4.0.12...v4.0.13
27 changes: 27 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion crates/node/npm/android-arm-eabi/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@tailwindcss/oxide-android-arm-eabi",
"version": "4.0.15",
"version": "4.0.16",
"repository": {
"type": "git",
"url": "git+https://github.com/tailwindlabs/tailwindcss.git",
2 changes: 1 addition & 1 deletion crates/node/npm/android-arm64/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@tailwindcss/oxide-android-arm64",
"version": "4.0.15",
"version": "4.0.16",
"repository": {
"type": "git",
"url": "git+https://github.com/tailwindlabs/tailwindcss.git",
2 changes: 1 addition & 1 deletion crates/node/npm/darwin-arm64/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@tailwindcss/oxide-darwin-arm64",
"version": "4.0.15",
"version": "4.0.16",
"repository": {
"type": "git",
"url": "git+https://github.com/tailwindlabs/tailwindcss.git",
2 changes: 1 addition & 1 deletion crates/node/npm/darwin-x64/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@tailwindcss/oxide-darwin-x64",
"version": "4.0.15",
"version": "4.0.16",
"repository": {
"type": "git",
"url": "git+https://github.com/tailwindlabs/tailwindcss.git",
2 changes: 1 addition & 1 deletion crates/node/npm/freebsd-x64/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@tailwindcss/oxide-freebsd-x64",
"version": "4.0.15",
"version": "4.0.16",
"repository": {
"type": "git",
"url": "git+https://github.com/tailwindlabs/tailwindcss.git",
2 changes: 1 addition & 1 deletion crates/node/npm/linux-arm-gnueabihf/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@tailwindcss/oxide-linux-arm-gnueabihf",
"version": "4.0.15",
"version": "4.0.16",
"repository": {
"type": "git",
"url": "git+https://github.com/tailwindlabs/tailwindcss.git",
2 changes: 1 addition & 1 deletion crates/node/npm/linux-arm64-gnu/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@tailwindcss/oxide-linux-arm64-gnu",
"version": "4.0.15",
"version": "4.0.16",
"repository": {
"type": "git",
"url": "git+https://github.com/tailwindlabs/tailwindcss.git",
2 changes: 1 addition & 1 deletion crates/node/npm/linux-arm64-musl/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@tailwindcss/oxide-linux-arm64-musl",
"version": "4.0.15",
"version": "4.0.16",
"repository": {
"type": "git",
"url": "git+https://github.com/tailwindlabs/tailwindcss.git",
2 changes: 1 addition & 1 deletion crates/node/npm/linux-x64-gnu/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@tailwindcss/oxide-linux-x64-gnu",
"version": "4.0.15",
"version": "4.0.16",
"repository": {
"type": "git",
"url": "git+https://github.com/tailwindlabs/tailwindcss.git",
2 changes: 1 addition & 1 deletion crates/node/npm/linux-x64-musl/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@tailwindcss/oxide-linux-x64-musl",
"version": "4.0.15",
"version": "4.0.16",
"repository": {
"type": "git",
"url": "git+https://github.com/tailwindlabs/tailwindcss.git",
2 changes: 1 addition & 1 deletion crates/node/npm/win32-arm64-msvc/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@tailwindcss/oxide-win32-arm64-msvc",
"version": "4.0.15",
"version": "4.0.16",
"repository": {
"type": "git",
"url": "git+https://github.com/tailwindlabs/tailwindcss.git",
2 changes: 1 addition & 1 deletion crates/node/npm/win32-x64-msvc/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@tailwindcss/oxide-win32-x64-msvc",
"version": "4.0.15",
"version": "4.0.16",
"repository": {
"type": "git",
"url": "git+https://github.com/tailwindlabs/tailwindcss.git",
2 changes: 1 addition & 1 deletion crates/node/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@tailwindcss/oxide",
"version": "4.0.15",
"version": "4.0.16",
"repository": {
"type": "git",
"url": "git+https://github.com/tailwindlabs/tailwindcss.git",
1 change: 1 addition & 0 deletions crates/oxide/Cargo.toml
Original file line number Diff line number Diff line change
@@ -19,6 +19,7 @@ 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"
2 changes: 1 addition & 1 deletion crates/oxide/src/extractor/mod.rs
Original file line number Diff line number Diff line change
@@ -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);
46 changes: 45 additions & 1 deletion crates/oxide/src/extractor/pre_processors/pug.rs
Original file line number Diff line number Diff line change
@@ -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)]",
],
);
}
}
69 changes: 69 additions & 0 deletions crates/oxide/src/extractor/pre_processors/ruby.rs
Original file line number Diff line number Diff line change
@@ -3,6 +3,14 @@
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 std::sync;

static TEMPLATE_REGEX: sync::LazyLock<Regex> = sync::LazyLock::new(|| {
Regex::new(r#"\s*(.*?)_template\s*<<[-~]?([A-Z]+?)\n([\s\S]*?)\2"#).unwrap()
});

#[derive(Debug, Default)]
pub struct Ruby;
@@ -14,6 +22,20 @@ impl PreProcessor for Ruby {
let mut cursor = cursor::Cursor::new(content);
let mut bracket_stack = bracket_stack::BracketStack::default();

// 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
.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);
}

// Ruby extraction
while cursor.pos < len {
// Looking for `%w` or `%W`
if cursor.curr != b'%' && !matches!(cursor.next, b'w' | b'W') {
@@ -153,4 +175,51 @@ mod tests {
Ruby::test_extract_contains(input, expected);
}
}

// https://github.com/tailwindlabs/tailwindcss/issues/17334
#[test]
fn test_embedded_slim_extraction() {
let input = r#"
class QweComponent < ApplicationComponent
slim_template <<~SLIM
button.rounded-full.bg-red-500
| Some text
button.rounded-full(
class="flex"
)
| Some text
SLIM
end
"#;

Ruby::test_extract_contains(input, vec!["rounded-full", "bg-red-500", "flex"]);

// Embedded Svelte just to verify that we properly pick up the `{x}_template`
let input = r#"
class QweComponent < ApplicationComponent
svelte_template <<~HTML
<div class:flex="true"></div>
HTML
end
"#;

Ruby::test_extract_contains(input, vec!["flex"]);

// Together in the same file
let input = r#"
class QweComponent < ApplicationComponent
slim_template <<~SLIM
button.z-1.z-2
| Some text
SLIM
end
class QweComponent < ApplicationComponent
svelte_template <<~HTML
<div class:z-3="true"></div>
HTML
end
"#;
Ruby::test_extract_contains(input, vec!["z-1", "z-2", "z-3"]);
}
}
2 changes: 1 addition & 1 deletion crates/oxide/src/extractor/pre_processors/slim.rs
Original file line number Diff line number Diff line change
@@ -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