mirror of
https://github.com/tailwindlabs/tailwindcss.git
synced 2025-12-08 21:36:08 +00:00
6275 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
9cb38993d2
|
Upgrade deprecated order-none to order-0 (#18126)
This PR adds an initial version for deprecated utilities. Right now it's hardcoded to just the `order-none` utility. This means that `order-0` and `order-[0]` will not be migrated to `order-none` anymore. We did that automatically because we prefer named utilities over bare values and arbitrary values. With this PR, `order-none` is ignored. Similarly, `order-none` will be migrated to `order-0` instead (defined in a separate migration for deprecated values). Made it a new migration instead of using the legacy migration because there all utilities still exist, but are defined differently (e.g.: `shadow`, `shadow-sm`, `shadow-xs`). This PR is also an initial version, it doesn't add any form of `deprecated` flag or feature on a per-utility implementation basis. This therefor has the side effect that if you have a custom `order-none` defined, that it will also be ignored during migrations. ## Test plan 1. Added tests to ensure the `order-0` is not migrated to `order-none` 2. Added tests to ensure `order-none` is migrated to `order-0` (if it's safe to do so, the signature is still computed to ensure the output is the same). 3. Ran this on the Tailwind Plus codebase and ensured that `order-0` is not migrated to `order-none` and that `order-none` is migrated to `order-0`. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> |
||
|
|
ed3cecd39d
|
Support Leptos class: attributes (#18093)
<!-- 👋 Hey, thanks for your interest in contributing to Tailwind! **Please ask first before starting work on any significant new features.** It's never a fun experience to have your pull request declined after investing a lot of time and effort into a new feature. To avoid this from happening, we request that contributors create a discussion to first discuss any significant new features. For more info, check out the contributing guide: https://github.com/tailwindcss/tailwindcss/blob/main/.github/CONTRIBUTING.md --> Fixes #18092 ## Summary Using the Svelte preprocessor for Rust files we can support Leptos `class:` attributes syntax. ## Test plan ``` pnpm t ``` --------- Co-authored-by: Robin Malfait <malfait.robin@gmail.com> |
||
|
|
24ed64ebb3
|
Update @types/react 19.1.2 → 19.1.4 (patch) (#18085)
Here is everything you need to know about this update. Please take a good look at what changed and the test results before merging this pull request. ### What changed? #### ✳️ @types/react (19.1.2 → 19.1.4) · [Repo](https://github.com/DefinitelyTyped/DefinitelyTyped) Sorry, we couldn't find anything useful about this release. ---  [Depfu](https://depfu.com) will automatically keep this PR conflict-free, as long as you don't add any commits to this branch yourself. You can also trigger a rebase manually by commenting with `@depfu rebase`. <details><summary>All Depfu comment commands</summary> <blockquote><dl> <dt>@depfu rebase</dt><dd>Rebases against your default branch and redoes this update</dd> <dt>@depfu recreate</dt><dd>Recreates this PR, overwriting any edits that you've made to it</dd> <dt>@depfu merge</dt><dd>Merges this PR once your tests are passing and conflicts are resolved</dd> <dt>@depfu cancel merge</dt><dd>Cancels automatic merging of this PR</dd> <dt>@depfu close</dt><dd>Closes this PR and deletes the branch</dd> <dt>@depfu reopen</dt><dd>Restores the branch and reopens this PR (if it's closed)</dd> <dt>@depfu pause</dt><dd>Ignores all future updates for this dependency and closes this PR</dd> <dt>@depfu pause [minor|major]</dt><dd>Ignores all future minor/major updates for this dependency and closes this PR</dd> <dt>@depfu resume</dt><dd>Future versions of this dependency will create PRs again (leaves this PR as is)</dd> </dl></blockquote> </details> Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com> |
||
|
|
7013ca37ed
|
Update semver 7.7.1 → 7.7.2 (patch) (#18084)
Here is everything you need to know about this update. Please take a good look at what changed and the test results before merging this pull request. ### What changed? #### ✳️ semver (7.7.1 → 7.7.2) · [Repo](https://github.com/npm/node-semver) · [Changelog](https://github.com/npm/node-semver/blob/main/CHANGELOG.md) <details> <summary>Release Notes</summary> <h4><a href="https://github.com/npm/node-semver/releases/tag/v7.7.2">7.7.2</a></h4> <blockquote><h2 dir="auto"> <a href="https://bounce.depfu.com/github.com/npm/node-semver/compare/v7.7.1...v7.7.2">7.7.2</a> (2025-05-12)</h2> <h3 dir="auto">Bug Fixes</h3> <ul dir="auto"> <li> <a href=" |
||
|
|
9df5ba78bf
|
Fix PostCSS crash when using toJSON() (#18083)
When I added source maps to PostCSS I mistakenly assumed that `.source`
on a node could be `undefined`. The comment above the property in
PostCSS says that `source` can be `undefined` but this is a commentary
on the value upon **access** not its expected value on **write**:
```ts
declare abstract class Node_ {
/**
* …
*
* The nodes that are created manually using the public APIs
* provided by PostCSS will have `source` undefined and
* will be absent in the source map.
*
* …
*/
source?: Node.Source
}
```
Rather, what these types mean is that *if the property exists* it must
be defined. But otherwise the property can be missing if a node has no
source location metadata. This generally wasn't a problem with the
string-returning APIs but the `toJSON()` API in PostCSS expects that
`source` is defined if present. This caused a crash because our license
comment doesn't have a source location.
I've addressed this by deleting the `source` property from the node if
source location data is not available.
Fixes #18082
ref https://github.com/parcel-bundler/parcel/issues/10161
|
||
|
|
a42251cc29
|
Improve performance of upgrade tool (#18068)
This PR improves the performance of the upgrade tool due to a regression introduced by https://github.com/tailwindlabs/tailwindcss/pull/18057 Essentially, we had to make sure that we are not in `<style>…</style>` tags because we don't want to migrate declarations in there such as `flex-shrink: 0;` The issue with this approach is that we checked _before_ the candidate if a `<style` cold be found and if we found an `</style>` tag after the candidate. We would basically do this check for every candidate that matches. Running this on our Tailwind UI codebase, this resulted in a bit of a slowdown: ```diff - Before: ~13s + After: ~5m 39s ``` ... quite the difference. This is because we have a snapshot file that contains ~650k lines of code. Looking for `<style>` and `</style>` tags in a file that large is expensive, especially if we do it a lot. I ran some numbers and that file contains ~1.8 million candidates. Anyway, this PR fixes that by doing a few things: 1. We will compute the `<style>` and `</style>` tag positions only once per file and cache it. This allows us to re-use this work for every candidate that needs it. 2. We track the positions, which means that we can simply check if a candidate's location is within any of 2 start and end tags. If so, we skip it. Running the numbers now gets us to: ```diff - Before: ~5m 39s + After: ~9s ``` Much better! --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> |
||
|
|
71fb9cdf59
|
Improve @tailwindcss/upgrade and pnpm workspaces support (#18065)
This PR fixes an issue where an error such as: <img width="1702" alt="image" src="https://github.com/user-attachments/assets/4e6f75c7-3182-4497-939e-96cff08c55ae" /> Will be thrown during the upgrade process. This can happen when you are using `pnpm` and your CSS file includes a `@import "tailwindcss";`. In this scenario, `tailwindcss` will be loaded from a shared `.pnpm` folder outside of the current working directory. In this case, we are also not interested in migrating _that_ file, but we also don't want the upgrade process to just crash. I didn't see an option to ignore errors like this, so wrapped it in a try/catch instead. It also fixes another issue where if you are using a pnpm workspace and run the upgrade tool from the root, then it throws you an error that you cannot add dependencies to the workspace root unless `-w` or `--workspace-root` flags are passed. For this, we disable the check entirely using the `--ignore-workspace-root-check` flag. If we always used the `--workspace-root` flag, then the dependencies would always be added to the root, regardless of where you are running the script from which is not what we want. ## Test plan Before: <img width="1816" alt="image" src="https://github.com/user-attachments/assets/78246876-3eb6-4539-a557-d3d366f1b3a3" /> After: <img width="1816" alt="image" src="https://github.com/user-attachments/assets/a65e4421-d7c5-4d83-b35d-934708543e25" /> Before: <img width="1816" alt="image" src="https://github.com/user-attachments/assets/53772661-2c4a-4212-84d9-a556a0ad320f" /> After: <img width="1816" alt="image" src="https://github.com/user-attachments/assets/5bfaf20e-34b8-44fd-9b59-e72d36738879" /> |
||
|
|
c7d368b3c4
|
Do not migrate declarations in <style> blocks (#18057)
This PR improves the upgrade tool by making sure that we don't migrate
CSS declarations in `<style>…</style>` blocks.
We do this by making sure that:
1. We detect a declaration, the current heuristic is that the candidate
is:
- Preceded by whitespace
- Followed by a colon and whitespace
```html
<style>
.foo {
flex-shrink: 0;
^ ^^
}
</style>
```
2. We are in a `<style>…</style>` block
```html
<style>
^^^^^^
.foo {
flex-shrink: 0;
}
</style>
^^^^^^^^
```
The reason we have these 2 checks is because just relying on the first
heuristic alone, also means that we will not be migrating keys in JS
objects, because they typically follow the same structure:
```js
let classes = {
flex: 0,
^ ^^
}
```
Another important thing to note is that we can't just ignore anything in
between `<style>…</style>` blocks, because you could still be using
`@apply` that we _do_ want to migrate.
Last but not least, the first heuristics is not perfect either. If you
are writing minified CSS then this will likely fail if there is no
whitespace around the candidate.
But my current assumption is that nobody should be writing minified CSS,
and minified CSS will very likely be generated and gitignored. In either
situation, replacements in minified CSS will not be any worse than it is
today.
I'm open to suggestions for better heuristics.
## Test plan
1. Added an integration test that verifies that we do migrate `@apply`
and don't migrate the `flex-shrink: 0;` declaration.
Fixes: #17975
|
||
|
|
d69604e202
|
Update all of nextjs 15.3.1 → 15.3.2 (patch) (#18046) | ||
|
|
74e084ad27
|
Prepare v4.1.7 release (#18040)
Co-authored-by: Adam Wathan <adam.wathan@gmail.com>v4.1.7 |
||
|
|
bf591febf3
|
Fix missing extracted classes containing . in Clojure (#18038)
This PR fixes an issue in the Clojure pre-processor where candidates including `.` characters were not extracted correctly. The solution here is to only replace the `.` with a ` ` when the `.` is not surrounded by numbers. This means that: ``` :.foo.bar ``` Becomes ``` : foo bar ``` But ``` :.gap-1.5.flex ``` Becomes ``` : gap-1.5 flex ``` This way the `gap-1.5` is correctly extracted. ## Test plan 1. Added a test for this case 2. Tested this in the extractor tool as well. Notice how the `gap-1.5` is correctly extracted here. <img width="1247" alt="image" src="https://github.com/user-attachments/assets/f5dd2600-5c5e-4ad8-88af-4e5be44340f5" /> Fixes: 17760 |
||
|
|
1ada8e0f22
|
Make candidate template migrations faster (#18025)
This PR makes the migrations for templates much faster. To make this
work, I also had to move things around a bit (so you might want to check
this PR commit by commit). I also solved an issue by restructuring the
code.
### Performance
For starters, we barely applied any caching when migrating candidates
from α to β. The problem with this is that in big projects the same
candidates will appear _everywhere_, so caching is going to be useful
here.
One of the reasons why we didn't do any caching is that some migrations
were checking if a migration is actually safe to do. To do this, we were
checking the `location` (the location of the candidate in the template).
Since this location is unique for each template, caching was not
possible.
So the first order of business was to hoist the `isSafeMigration` check
up as the very first thing we do in the migration.
If we do this first, then the only remaining code relies on the
`DesignSystem`, `UserConfig` and `rawCandidate`.
In a project, the `DesignSystem` and `UserConfig` will be the same
during the migration, only the `rawCandidate` will be different which
means that we can move all this logic in a good old `DefaultMap` and
cache the heck out of it.
Running the numbers on our Tailwind Plus repo, this results in:
```
Total seen candidates: 2 211 844
Total migrated candidates: 7 775
Cache hits: 1 575 700
```
That's a lot of work we _don't_ have to do. Looking at the timings, the
template migration step goes from ~45s to ~10s because of this.
Another big benefit of this is that this makes migrations _actually_
safe. Before we were checking if a migration was safe to do in specific
migrations. But other migrations were still printing the candidate which
could still result in an unsafe migration.
For example when migrating the `blur` and the `shadow` classes, the
`isSafeMigration` was used. But if the input was `!flex` then the safety
check wasn't even checked in this specific migration.
### Safe migrations
Also made some changes to the `isSafeMigration` logic itself. We used to
start by checking the location, but thinking about the problem again,
the actual big problem we were running into is classes that are short
like `blur`, and `shadow` because they could be used in other contexts
than a Tailwind CSS class.
Inverting this logic means that more specific Tailwind CSS classes will
very likely _not_ cause any issues at all.
For example:
- If you have variants: `hover:focus:flex`
- If you have arbitrary properties: `[color:red]`
- If you have arbitrary values: `bg-[red]`
- If you have a modifier: `bg-red-500/50`
- If you have a `-` in the name: `bg-red-500`
Even better if we can't parse a candidate at all, we can skip the
migrations all together.
This brings us to the issue in #17974, one of the issues was already
solved by just hoisting the `isSafeMigration`. But to make the issue was
completely solved I also made sure that in Vue attributes like
`:active="…"` are also considered unsafe (note: `:class` is allowed).
Last but not least, in case of the `!duration` that got replaced with
`duration!` was solved by verifying that the candidate actually produces
valid CSS. We can compute the signature for this class.
The reason this wasn't thrown away earlier is because we can correctly
parse `duration` but `duration` on its own doesn't exist,
`duration-<number>` does exist as a functional utility which is why it
parsed in the first place.
Fixes: #17974
## Test plan
1. Ran the tool on our Tailwind UI Templates repo to compare the new
output with the "old" behavior and there were no differences in output.
2. Ran the tool on our Tailwind Plus repo, and the template migration
step went from ~45s to ~10s.
3. Added additional tests to verify the issues in #17974 are fixed.
[ci-all] let's run this on all CI platforms...
|
||
|
|
6fb98d2f40
|
Upgrade lightningcss to 1.30.1 (#18037)
|
||
|
|
f3157cd9a6
|
Ignore custom variants with :merge(…) selectors (#18020)
Closes #15617 ## Summary This PR ignores `addVariant(…)` legacy JS plugin calls for variants that are using the [`:merge(…)` selector](https://v3.tailwindcss.com/docs/plugins#parent-and-sibling-states) for parent and sibling states. We can ignore these now because in v4, `group-*` and `peer-*` variants _compound automatically_ and you don't have to define them anymore. ## Test plan Added a unit test to ensure that the `optional` variant example from the v3 docs work as expected. |
||
|
|
e57a2f5a3a
|
Change casing of utilities with named values to kebab-case to match u… (#18017)
Fixes #16156 ## Summary This PR adds a new 3 -> 4 template migration that changes the casing of in both utility values and modifier values from camelCase to kebab-case to match the updated CSS variable names. ## Test plan - Added integration test, see the diff in the PR. |
||
|
|
4db711d1e4
|
Fix -rotate-* with arbitary values (#18014)
Fixes #18013 ## Test plan See updated unit tests |
||
|
|
498f9ff003
|
Migrate bare values to named values (#18000)
This PR improves the upgrade tool by also migrating bare values to named values defined in the `@theme`. Recently we shipped some updates dat allowed us to migrate arbitrary values (with square brackets), but we didn't migrate bare values yet. That means that in this example: ```html <div class="aspect-[16/9]"></div> <div class="aspect-16/9"></div> ``` We migrated this to: ```html <div class="aspect-video"></div> <div class="aspect-16/9"></div> ``` With this change, we will also try and migrate the bare value to a named value. So this example: ```html <div class="aspect-[16/9]"></div> <div class="aspect-16/9"></div> ``` Now becomes: ```html <div class="aspect-video"></div> <div class="aspect-video"></div> ``` ## Test plan 1. Added unit tests for the new functionality. 2. Ran this on a local project Before: <img width="432" alt="image" src="https://github.com/user-attachments/assets/ce1adfbd-7be1-4062-bea5-66368f748e44" /> After: <img width="382" alt="image" src="https://github.com/user-attachments/assets/a385c94c-4e4c-4e1c-ac73-680c56ac4081" /> |
||
|
|
ef2e6c71fe
|
Upgrade: Migrate outline class (#17996)
This PR adds a migration from `outline` to `outline-solid` for the v3 -> v4 upgrade tool. ## Test plan - Added integration test |
||
|
|
4fba87bc90
|
Upgrade lightningcss to 1.30.0 (#17979)
|
||
|
|
ba944ca3b1
|
Upgrade bun to 1.2.13 (#17981)
|
||
|
|
5688f0a7ae
|
Add ignore pattern for node_modules in globby search in upgrade cli (#17969)
When passing `gitignore: true` to globby it will start a search for all .gitignore files, this initial search includes node_modules making it hang forever for large monorepos with many files inside node_modules |
||
|
|
19e2b29c68
|
Update @types/react-dom 19.1.2 → 19.1.3 (patch) (#17976) | ||
|
|
0d975f5f06
|
Update dedent 1.5.3 → 1.6.0 (minor) (#17965)
Here is everything you need to know about this upgrade. Please take a good look at what changed and the test results before merging this pull request. ### What changed? #### ✳️ dedent (1.5.3 → 1.6.0) · [Repo](https://github.com/dmnd/dedent) · [Changelog](https://github.com/dmnd/dedent/blob/main/CHANGELOG.md) <details> <summary>Release Notes</summary> <h4><a href="https://github.com/dmnd/dedent/releases/tag/v1.6.0">1.6.0</a></h4> <blockquote><h2 dir="auto">What's Changed</h2> <ul dir="auto"> <li>feat: add <code class="notranslate">trimWhitespace</code> option by <a href="https://bounce.depfu.com/github.com/43081j">@43081j</a> in <a href="https://bounce.depfu.com/github.com/dmnd/dedent/pull/97">#97</a> </li> </ul> <h2 dir="auto">New Contributors</h2> <ul dir="auto"> <li> <a href="https://bounce.depfu.com/github.com/43081j">@43081j</a> made their first contribution in <a href="https://bounce.depfu.com/github.com/dmnd/dedent/pull/97">#97</a> </li> </ul> <p dir="auto"><strong>Full Changelog</strong>: <a href="https://bounce.depfu.com/github.com/dmnd/dedent/compare/v1.5.3...v1.6.0"><tt>v1.5.3...v1.6.0</tt></a></p></blockquote> <p><em>Does any of this look wrong? <a href="https://depfu.com/packages/npm/dedent/feedback">Please let us know.</a></em></p> </details> <details> <summary>Commits</summary> <p><a href=" |
||
|
|
f0986ce127
|
Prevent duplicate suggestions when using @theme and @utility together (#17675)
Fixes https://github.com/tailwindlabs/tailwindcss-intellisense/issues/1313 Right now given this CSS: ```css @theme reference { --text-header: 1.5rem; } @utility text-header { text-transform: uppercase; } ``` You'll see two entries for `text-header` in IntelliSense completions but we only want you to see one. This PR solves this by merging their modifier lists and de-duping by class name. |
||
|
|
3386049b7b
|
Fix upgrade error when using @import … source(…) (#17963)
This PR fixes an issue when running the upgrade tool and if any of the
CSS files has an import that looks like this:
```css
@import "tailwindcss" source("…");
```
This was trying to resolve `tailwindcss" source("…` instead of
`tailwindcss`.
This PR fixes that.
## Test plan
1. Ran it locally on a project
Before:
<img width="1158" alt="image"
src="https://github.com/user-attachments/assets/09bf5d69-797c-4330-ade1-edc213f7ce5c"
/>
After:
<img width="1029" alt="image"
src="https://github.com/user-attachments/assets/d1c9e194-30e2-4564-83c5-d9a259a67e90"
/>
|
||
|
|
737994b7aa
|
Allow _ before numbers during candidate extraction (#17961)
This PR fixes a bug where a class like `header_1` wasn't properly extracted because we didn't allow an `_` before a number. This PR fixes that by allowing an `_` before a number. Fixes: #17960 ## Test plan 1. Added a test to verify this works 2. Existing tests work Used the visualizer tool for this to verify that the `header_1` class is being extracted: <img width="1816" alt="image" src="https://github.com/user-attachments/assets/fdc21602-0e2b-4e4e-92a1-19c4f4f5393f" /> |
||
|
|
2d139984da
|
Prepare v4.1.6 release (#17951)
Co-authored-by: Adam Wathan <adam.wathan@gmail.com>v4.1.6 |
||
|
|
47bb007eae
|
Download platform specific package if optionalDependencies are skipped (#17929)
Closes #15806 This PR adds a new `postinstall` script to `@tailwindcss/oxide` that will attempt to download the platform-specific optional dependency to avoid issues when the package manager does not do that automatically (see #15806). The implementation for this is fairly simple: The npm package is downloaded from the official npm servers and extracted into the `node_modules` directory of the `@tailwidncss/oxide` installation. ## Test plan Since we still lack a solid repro of #15806, the way I tested this change was to manually remove all automatically-installed optional dependencies and then running the postinstall script manually. The script then downloads the right version package which makes the import to `@tailwidncss/oxide` work. An appropriate integration test was added too. I furthermore also validated that: - This works across CI platforms [ci-all] - The postinstall script bails out when running `pnpm install` in the dev setup. This is necessary since doing the initial install won't have any binary dependencies yet so it would download invalid versions from npm (as the version numbers locally refer to the last released version). We can safely bail out here though since this was never an issue with local development. - The postinstall script does not do anything when the `@tailwindcss/oxide` library is added _unless_ the issue is detected. [ci-all] --------- Co-authored-by: Robin Malfait <malfait.robin@gmail.com> |
||
|
|
2f6679abfe
|
Print sources when DEBUG=* is set (#17952)
This PR improves the debug logging by also adding the provided `@source`
to the log file. It will also print the optimized sources (the ones we
expand and mark as `Auto` or `Pattern`).
In the logs, this will look like this:
```
2025-05-09T11:03:32.906478Z INFO tailwindcss_oxide::scanner: Provided sources:
2025-05-09T11:03:32.906544Z INFO tailwindcss_oxide::scanner: Source: PublicSourceEntry { base: "/Users/robin/github.com/RobinMalfait/spreadsheet", pattern: "**/*", negated: false }
2025-05-09T11:03:32.906589Z INFO tailwindcss_oxide::scanner: Optimized sources:
2025-05-09T11:03:32.906595Z INFO tailwindcss_oxide::scanner: Source: Auto { base: "/Users/robin/github.com/RobinMalfait/spreadsheet" }
```
Or if you have more sources:
```
2025-05-09T11:06:54.767546Z INFO tailwindcss_oxide::scanner: Provided sources:
2025-05-09T11:06:54.767660Z INFO tailwindcss_oxide::scanner: Source: PublicSourceEntry { base: "/Users/robin/github.com/RobinMalfait/spreadsheet", pattern: "**/*", negated: false }
2025-05-09T11:06:54.767987Z INFO tailwindcss_oxide::scanner: Source: PublicSourceEntry { base: "/Users/robin/github.com/RobinMalfait/spreadsheet/app", pattern: "./routes/*.{jsx,tsx}", negated: false }
2025-05-09T11:06:54.767992Z INFO tailwindcss_oxide::scanner: Source: PublicSourceEntry { base: "/Users/robin/github.com/RobinMalfait/spreadsheet/app", pattern: "./utils/*.ts", negated: false }
2025-05-09T11:06:54.768450Z INFO tailwindcss_oxide::scanner: Optimized sources:
2025-05-09T11:06:54.768455Z INFO tailwindcss_oxide::scanner: Source: Auto { base: "/Users/robin/github.com/RobinMalfait/spreadsheet" }
2025-05-09T11:06:54.768459Z INFO tailwindcss_oxide::scanner: Source: Pattern { base: "/Users/robin/github.com/RobinMalfait/spreadsheet/app/routes", pattern: "*.jsx" }
2025-05-09T11:06:54.768462Z INFO tailwindcss_oxide::scanner: Source: Pattern { base: "/Users/robin/github.com/RobinMalfait/spreadsheet/app/routes", pattern: "*.tsx" }
2025-05-09T11:06:54.768466Z INFO tailwindcss_oxide::scanner: Source: Pattern { base: "/Users/robin/github.com/RobinMalfait/spreadsheet/app/utils", pattern: "*.ts" }
```
|
||
|
|
ae57d26852
|
Update contribution docs (#17911)
This PR updates the contribution docs to make it easier for anyone contributing to Tailwind CSS. |
||
|
|
ff9f183368
|
Fix source map paths in CI (#17938) | ||
|
|
56b22bb1d3
|
Add support for source maps (#17775)
Closes #13694 Closes #13591 # Source Maps Support for Tailwind CSS This PR adds support for source maps to Tailwind CSS v4 allowing us to track where styles come from whether that be user CSS, imported stylesheets, or generated utilities. This will improve debuggability in browser dev tools and gives us a good foundation for producing better error messages. I'll go over the details on how end users can enable source maps, any limitations in our implementation, changes to the internal `compile(…)` API, and some details and reasoning around the implementation we chose. ## Usage ### CLI Source maps can be enabled in the CLI by using the command line argument `--map` which will generate an inline source map comment at the bottom of your CSS. A separate file may be generated by passing a file name to `--map`: ```bash # Generates an inline source map npx tailwindcss -i input.css -o output.css --map # Generates a separate source map file npx tailwindcss -i input.css -o output.css --map output.css.map ``` ### PostCSS Source maps are supported when using Tailwind as a PostCSS plugin *in development mode only*. They may or may not be enabled by default depending on your build tool. If they are not you may be able to configure them within your PostCSS config: ```jsonc // package.json { // … "postcss": { "map": { "inline": true }, "plugins": { "@tailwindcss/postcss": {}, }, } } ``` ### Vite Source maps are supported when using the Tailwind CSS Vite plugin in *development mode only* by enabling the `css.devSourcemap` setting: ```js import tailwindcss from "@tailwindcss/vite"; import { defineConfig } from "vite"; export default defineConfig({ plugins: [tailwindcss()], css: { devSourcemap: true, }, }) ``` Now when a CSS file is requested by the browser it'll have an inline source map comment that the browser can use. ## Limitations - Production build source maps are currently disabled due to a bug in Lightning CSS. See https://github.com/parcel-bundler/lightningcss/pull/971 for more details. - In Vite, minified CSS build source maps are not supported at all. See https://github.com/vitejs/vite/issues/2830 for more details. - In PostCSS, minified CSS source maps are not supported. This is due to the complexity required around re-associating every AST node with a location in the generated, optimized CSS. This complexity would also have a non-trivial performance impact. ## Testing Here's how to test the source map functionality in different environments: ### Testing the CLI 1. Setup typical project that the CLI can use and with sources to scan. ```css @import "tailwindcss"; @utilty my-custom-utility { color: red; } /* to test `@apply` */ .card { @apply bg-white text-center shadow-md; } ``` 2. Build with source maps: ```bash bun /path/to/tailwindcss/packages/@tailwindcss-cli/src/index.ts --input input.css -o output.css --map ``` 3. Open Chrome DevTools, inspect an element with utility classes, and you should see rules pointing to `input.css` or `node_modules/tailwindcss/index.css` ### Testing with Vite Testing in Vite will require building and installing necessary files under `dist/*.tgz`. 1. Create a Vite project and enable source maps in `vite.config.js`: ```js import tailwindcss from "@tailwindcss/vite"; import { defineConfig } from "vite"; export default defineConfig({ plugins: [tailwindcss()], css: { // This line is required for them to work devSourcemap: true, }, }) ``` 2. Add a component that uses Tailwind classes and custom CSS: ```jsx // ./src/app.jsx export default function App() { return ( <div className="bg-blue-500 my-custom-class"> Hello World </div> ) } ``` ```css /* ./src/styles.css */ @import "tailwindcss"; @utilty my-custom-utility { color: red; } /* to test `@apply` */ .card { @apply bg-white text-center shadow-md; } ``` 3. Run `npm run dev`, open DevTools, and inspect elements to verify source mapping works for both utility classes and custom CSS. ### Testing with PostCSS CLI 1. Create a test file and update your PostCSS config: ```css /* input.css */ @import "tailwindcss"; @layer components { .card { @apply p-6 rounded-lg shadow-lg; } } ``` ```jsonc // package.json { // … "postcss": { "map": { "inline": true }, "plugins": { "/path/to/tailwindcss/packages/packages/@tailwindcss-postcss/src/index.ts": {} } } } ``` 2. Run PostCSS through Bun: ```bash bunx --bun postcss ./src/index.css -o out.css ``` 3. Inspect the output CSS - it should include an inline source map comment at the bottom. ### Testing with PostCSS + Next.js Testing in Next.js will require building and installing necessary files under `dist/*.tgz`. However, I've not been able to get CSS source maps to work in Next.js without this hack: ```js const nextConfig: NextConfig = { // next.js overwrites config.devtool so we prevent it from doing so // please don't actually do this… webpack: (config) => Object.defineProperty(config, "devtool", { get: () => "inline-source-map", set: () => {}, }), }; ``` This is definitely not supported and also doesn't work with turbopack. This can be used to test them temporarily but I suspect that they just don't work there. ### Manual source map analysis You can analyze source maps using Evan Wallace's [Source Map Visualization](https://evanw.github.io/source-map-visualization/) tool which will help to verify the accuracy and quality of source maps. This is what I used extensively while developing this implementation. It'll help verify that custom, user CSS maps back to itself in the input, that generated utilities all map back to `@tailwind utilities;`, that source locations from imported files are also handled correctly, etc… It also highlights the ranges of stuff so it's easy to see if there are off-by-one errors. It's easiest to use inline source maps with this tool because you can take the CSS file and drop it on the page and it'll analyze it while showing the file content. If you're using Vite you'll want to access the CSS file with `?direct` at the end so you don't get a JS module back. ## Implementation The source map implementation follows the ECMA-426 specification and includes several key components to aid in that goal: ### Source Location Tracking Each emittable AST node in the compilation pipeline tracks two types of source locations: - `src`: Original source location - [source file, start offset, end offset] - `dst`: Generated source location - [output file, start offset, end offset] This dual tracking allows us to maintain mappings between the original source and generated output for things like user CSS, generated utilities, uses of `@apply`, and tracking theme variables. It is important to note that source locations for nodes _never overlap_ within a file which helps simplify source map generation. As such each type of node tracks a specific piece of itself rather than its entire "block": | Node | What a `SourceLocation` represents | | ----------- | ---------------------------------------------------------------- | | Style Rule | The selector | | At Rule | Rule name and params, includes the `@` | | Declaration | Property name and value, excludes the semicolon | | Comment | The entire comment, includes the start `/*` and end `*/` markers | ### Windows line endings when parsing CSS Because our AST tracks nodes through offsets we must ensure that any mutations to the file do *not* change the lenth of the string. We were previously replacing `\r\n` with `\n` (see [filter code points](https://drafts.csswg.org/css-syntax/#css-filter-code-points) from the spec) — which changes the length of the string and all offsets may end up incorrect. The CSS parser was updated to handle the CRLF token directly by skipping over the `\r` and letting remaining code handle `\n` as it did previously. Some additional tweaks were required when "peeking" the input but those changes were fairly small. ### Tracking of imports Source maps need paths to the actual imported stylesheets but the resolve step for stylesheets happens inside the call to `loadStylesheet` which make the file path unavailable to us. Because of this the `loadStylesheet` API was augmented such that it has to return a `path` property that we can then use to identify imported sources. I've also made the same change to the `loadModule` API for consistency but nothing currently uses this property. The `path` property likely makes `base` redundant but elminating that (if we even want to) is a future task. ### Optimizing the AST Our optimization pass may intoduce some nodes, for example, fallbacks we create for `@property`. These nodes are linked back to `@tailwind utilities` as ultimately that is what is responsible for creating them. ### Line Offset Tables A key component to our source map generation is the line offset table, which was inspired by some ESBuild internals. It stores a sorted list of offsets for the start of each line allowing us to translate offsets to line/column `Position`s in `O(log N)` time and from `Position`s to offsets in `O(1)` time. Creation of the table takes `O(N)` time. This means that we can store code point offsets for source locations and not have to worry about computing or tracking line/column numbers during parsing and serialization. Only when a source map is generated do these offsets need to be computed. This ensures the performance penalty when not using source maps is minimal. ### Source Map Generation The source map returned by `buildSourceMap()` is designed to follow the [ECMA-426 spec](https://tc39.es/ecma426). Because that spec is not completely finalized we consider the result of `buildSourceMap()` to be internal API that may change as the spec chamges. The produces source map is a "decoded" map such that all sources and mappings are in an object graph. A library like `source-map-js` must be used to convert this to an encoded source map of the right version where mappings are encoded with base 64 VLQs. Any specific integration (Vite, PostCSS, etc…) can then use `toSourceMap()` from `@tailwindcss/node` to convert from the internal source map to an spec-compliant encoded source map that can be understood by other tools. ### Handling minification in Lightning Since we use Lightning CSS for optimization, and it takes in an input map, we generate an encoded source map that we then pass to lightning. The output source map *from lighting itself* is then passed back in during the second optimization pass. The final map is then passed from lightning to the CLI (but not Vite or PostCSS — see the limitations section for details). In some cases we have to "fix up" the output CSS. When this happens we use `magic-string` to do the replacement in a way that is trackable and `@amppproject/remapping` to map that change back onto the original source map. Once the need for these fix ups disappear these dependencies can go away. Notes: - The accuracy of source maps run though lightning is reduced as it only tracks on a per-rule level. This is sufficient enough for browser dev tools so should be fine. - Source maps during optimization do not function properly at this time because of a bug in Lightning CSS regarding license comments. Once this bug is fixed they will start working as expected. ### How source locations flow through the system 1. During initial CSS parsing, source locations are preserved. 2. During parsing these source locations are also mapped to the destinations which supports an optimization for when no utilities are generated. 3. Throughout the compilation process, transformations maintain source location data 4. Generated utilities are explicitly pointed to `@tailwind utilities` unless generated by `@apply`. 5. When optimization is enabled, source maps are remapped through lightningcss 6. Final source maps are written in the requested format (inline or separate file) |
||
|
|
62706dccb0
|
Trigger updates to the internal upgrades repo (#17928)
This PR updates will now trigger the new internal `upgrades` repo instead of the Tailwind Play repo directly. We will be updating more internal repos when a new version is published. We will also use that new repo to update our other repos for other published packages in the future. |
||
|
|
17ca56d386
|
Fix bug with nested @apply rules in utility classes (#17924) (#17925)
Fixes #17924 When an `@apply` pointed to utility that nested usages of `@apply`, these nested usages were not properly carried through the dependency chain. This was because we were only tracking dependencies on the immediate parent rather than all parents. To fix this, this PR: - Modifies the dependency resolution to track dependencies through the entire parent path - Uses a `walk(…)` for the node replacement logic so that all nested `@apply` usages are also resolved (as these are now tracked in the dependency list anyways ## Test Plan - Added a regression test for #17924 to the unit tests and ensure existing tests don't break |
||
|
|
179e5ddd7c
|
Add more folders to the list of ignored content dirs (#17892)
Closes #15452 This PR adds more directories to the list of ignored content dirs. These are now handled the same as `node_modules`: - Contents of this directory are ignored by default to avoid scanning dependency trees - Explicit `@import`s inside these folders are now treated as _external_, bypassing any `.gitignore` files. The new extensions are: - Version control systems: `.hg`, `.svn` - Bundler caches: `.venv`, `venv`, `.yarn` - Framework caches: `.next`, `.turbo`, `.parcel-cache`, `__pycache__`, `.svelte-kit` ## Test plan Verified with the repro of #15452 by renaming the ignored directory to `.venv` and installing a local tarball: <img width="1283" alt="Screenshot 2025-05-06 at 13 14 55" src="https://github.com/user-attachments/assets/3265acbb-e121-47b3-ac6c-e174770f8234" /> |
||
|
|
d8c4df8001
|
Write to log file when using DEBUG=* (#17906)
This PR improves the debugability of the scanner when using `DEBUG=*` by
writing to a `tailwindcss-{pid}.log` file in the current working
directory.
It will include all the tracing information from the scanner. This PR
also introduces `Discovering {path}` and `Reading {path}` logs.
- `Discovering {path}` — this is logged when we are traversing the file
system looking for files. We use the `ignore` crate, and log this
information in the `filter_entry` callback. If a file was already
ignored by `.gitignore` files, this won't show up, but it also means
that we will not read it.
- `Reading {path}` — this is when we are actually reading the file so we
can start extracting potential Tailwind CSS classes.
These will give you some insights in what paths are being scanned, and
if we get stuck, where we get stuck.
Also, we are appending to the file. In the log below, you can already
see that a `tailwindcss-<number>.log` file exists already even though it
didn't exist before running the command. This should make it easier to
debug if we get stuck on a specific file/folder because the file will be
populated with information.
There are a few reasons for appending to a file:
1. There is a lot of output, so spamming the stdout/stderr is not ideal
2. If you run the same command again, after changing your `@source`
directives, you could diff the outputs. (although, the timestamps will
be different)
3. When using `DEBUG=*`, a lot of other tools also output debug
information, so writing to a file should make this better.
<details>
<summary>Example log</summary>
```log
2025-05-06T23:13:45.912292Z INFO scan_sources: tailwindcss_oxide::scanner: enter
2025-05-06T23:13:45.912697Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/out.css"
2025-05-06T23:13:45.912716Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/tailwindcss-61347.log"
2025-05-06T23:13:45.912748Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app"
2025-05-06T23:13:45.912786Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/test"
2025-05-06T23:13:45.912814Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/test/utils.ts"
2025-05-06T23:13:45.912851Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/utils"
2025-05-06T23:13:45.912873Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/utils/flatten.ts"
2025-05-06T23:13:45.912884Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/utils/matrix.ts"
2025-05-06T23:13:45.912893Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/utils/default-map.ts"
2025-05-06T23:13:45.912904Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/tailwind.css"
2025-05-06T23:13:45.912914Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/root.tsx"
2025-05-06T23:13:45.912936Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain"
2025-05-06T23:13:45.912962Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/expression.ts"
2025-05-06T23:13:45.912972Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/walk-ast.ts"
2025-05-06T23:13:45.912995Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/signature"
2025-05-06T23:13:45.913019Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/signature/parser.test.ts"
2025-05-06T23:13:45.913029Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/signature/validate.test.ts"
2025-05-06T23:13:45.913039Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/signature/tokenizer.ts"
2025-05-06T23:13:45.913048Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/signature/validate.ts"
2025-05-06T23:13:45.913058Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/signature/parser.ts"
2025-05-06T23:13:45.913067Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/signature/tokenizer.test.ts"
2025-05-06T23:13:45.913077Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/ast.ts"
2025-05-06T23:13:45.913086Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/version-control.ts"
2025-05-06T23:13:45.913095Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/tokenizer.ts"
2025-05-06T23:13:45.913105Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/type-checker.test.ts"
2025-05-06T23:13:45.913121Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/evaluation-result.ts"
2025-05-06T23:13:45.913505Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/tmp.test.ts"
2025-05-06T23:13:45.913514Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/version-control.test.ts"
2025-05-06T23:13:45.913523Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/tokenizer.test.ts"
2025-05-06T23:13:45.913531Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/evaluation.ts"
2025-05-06T23:13:45.913554Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions"
2025-05-06T23:13:45.913583Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/sequence.test.ts"
2025-05-06T23:13:45.913592Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/date.ts"
2025-05-06T23:13:45.913601Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/lookup.test.ts"
2025-05-06T23:13:45.913613Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/statistics.ts"
2025-05-06T23:13:45.913622Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/intrinsics.test.ts"
2025-05-06T23:13:45.913631Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/math.ts"
2025-05-06T23:13:45.913640Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/engineering.ts"
2025-05-06T23:13:45.913648Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/types.test.ts"
2025-05-06T23:13:45.913656Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/text.ts"
2025-05-06T23:13:45.913665Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/text.test.ts"
2025-05-06T23:13:45.913673Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/intrinsics.ts"
2025-05-06T23:13:45.913681Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/logic.ts"
2025-05-06T23:13:45.913689Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/date.test.ts"
2025-05-06T23:13:45.913697Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/types.ts"
2025-05-06T23:13:45.913705Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/logic.test.ts"
2025-05-06T23:13:45.913713Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/lookup.ts"
2025-05-06T23:13:45.913720Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/sequence.ts"
2025-05-06T23:13:45.913728Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/engineering.test.ts"
2025-05-06T23:13:45.913741Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/index.ts"
2025-05-06T23:13:45.913749Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/math.test.ts"
2025-05-06T23:13:45.913757Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/statistics.test.ts"
2025-05-06T23:13:45.913783Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/__snapshots__"
2025-05-06T23:13:45.913817Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/spreadsheet.test.ts"
2025-05-06T23:13:45.913826Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/type-checker.ts"
2025-05-06T23:13:45.913833Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/function-utils.ts"
2025-05-06T23:13:45.913841Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/spreadsheet.ts"
2025-05-06T23:13:45.913849Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/expression.test.ts"
2025-05-06T23:13:45.913857Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/evaluation.test.ts"
2025-05-06T23:13:45.913879Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/routes"
2025-05-06T23:13:45.913896Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/app/routes/_index.tsx"
2025-05-06T23:13:45.914172Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/README.md"
2025-05-06T23:13:45.914197Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/public"
2025-05-06T23:13:45.914228Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/public/fonts"
2025-05-06T23:13:45.914268Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/package.json"
2025-05-06T23:13:45.914289Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/scripts"
2025-05-06T23:13:45.914310Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/scripts/generate-documentation.ts"
2025-05-06T23:13:45.914332Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/.github"
2025-05-06T23:13:45.914383Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/.github/workflows"
2025-05-06T23:13:45.914410Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/.github/workflows/ci.yml"
2025-05-06T23:13:45.914420Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/tsconfig.json"
2025-05-06T23:13:45.914455Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/vite.config.ts"
2025-05-06T23:13:45.914486Z INFO scan_sources: tailwindcss_oxide::scanner: Discovering "/Users/robin/github.com/RobinMalfait/spreadsheet/biome.json"
2025-05-06T23:13:45.914512Z INFO scan_sources: tailwindcss_oxide::scanner: exit
2025-05-06T23:13:45.914515Z INFO extract_candidates: tailwindcss_oxide::scanner: enter
2025-05-06T23:13:45.914518Z INFO extract_candidates:read_all_files: tailwindcss_oxide::scanner: enter
2025-05-06T23:13:45.914524Z INFO extract_candidates:read_all_files: tailwindcss_oxide::scanner: Reading 58 file(s)
2025-05-06T23:13:45.914808Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/tailwindcss-61347.log"
2025-05-06T23:13:45.914990Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/routes/_index.tsx"
2025-05-06T23:13:45.915138Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/.github/workflows/ci.yml"
2025-05-06T23:13:45.915140Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/statistics.test.ts"
2025-05-06T23:13:45.915145Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/signature/tokenizer.ts"
2025-05-06T23:13:45.915163Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/tsconfig.json"
2025-05-06T23:13:45.915153Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/engineering.ts"
2025-05-06T23:13:45.915226Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/utils/matrix.ts"
2025-05-06T23:13:45.915229Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/walk-ast.ts"
2025-05-06T23:13:45.915372Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/test/utils.ts"
2025-05-06T23:13:45.915578Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/ast.ts"
2025-05-06T23:13:45.915599Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/signature/validate.ts"
2025-05-06T23:13:45.915637Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/version-control.ts"
2025-05-06T23:13:45.915647Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/signature/parser.ts"
2025-05-06T23:13:45.915657Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/vite.config.ts"
2025-05-06T23:13:45.915680Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/types.test.ts"
2025-05-06T23:13:45.915681Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/utils/flatten.ts"
2025-05-06T23:13:45.915701Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/signature/parser.test.ts"
2025-05-06T23:13:45.915706Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/README.md"
2025-05-06T23:13:45.915691Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/utils/default-map.ts"
2025-05-06T23:13:45.915701Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/spreadsheet.test.ts"
2025-05-06T23:13:45.915730Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/package.json"
2025-05-06T23:13:45.915753Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/tokenizer.ts"
2025-05-06T23:13:45.915731Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/biome.json"
2025-05-06T23:13:45.915787Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/signature/validate.test.ts"
2025-05-06T23:13:45.915822Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/signature/tokenizer.test.ts"
2025-05-06T23:13:45.915826Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/text.ts"
2025-05-06T23:13:45.915885Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/root.tsx"
2025-05-06T23:13:45.915885Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/types.ts"
2025-05-06T23:13:45.915886Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/type-checker.ts"
2025-05-06T23:13:45.915990Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/type-checker.test.ts"
2025-05-06T23:13:45.915995Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/text.test.ts"
2025-05-06T23:13:45.915998Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/logic.ts"
2025-05-06T23:13:45.916000Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/intrinsics.ts"
2025-05-06T23:13:45.916024Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/sequence.ts"
2025-05-06T23:13:45.916056Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/function-utils.ts"
2025-05-06T23:13:45.916058Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/scripts/generate-documentation.ts"
2025-05-06T23:13:45.916070Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/expression.ts"
2025-05-06T23:13:45.916075Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/logic.test.ts"
2025-05-06T23:13:45.916063Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/date.test.ts"
2025-05-06T23:13:45.916119Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/evaluation-result.ts"
2025-05-06T23:13:45.916120Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/index.ts"
2025-05-06T23:13:45.916148Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/expression.test.ts"
2025-05-06T23:13:45.916152Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/engineering.test.ts"
2025-05-06T23:13:45.916193Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/lookup.ts"
2025-05-06T23:13:45.916219Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/tmp.test.ts"
2025-05-06T23:13:45.916228Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/tokenizer.test.ts"
2025-05-06T23:13:45.916245Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/evaluation.test.ts"
2025-05-06T23:13:45.916256Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/spreadsheet.ts"
2025-05-06T23:13:45.916253Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/lookup.test.ts"
2025-05-06T23:13:45.916267Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/sequence.test.ts"
2025-05-06T23:13:45.916287Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/math.test.ts"
2025-05-06T23:13:45.916286Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/version-control.test.ts"
2025-05-06T23:13:45.916317Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/intrinsics.test.ts"
2025-05-06T23:13:45.916323Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/evaluation.ts"
2025-05-06T23:13:45.916354Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/statistics.ts"
2025-05-06T23:13:45.916562Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/date.ts"
2025-05-06T23:13:45.916609Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/domain/functions/math.ts"
2025-05-06T23:13:45.916676Z INFO extract_candidates:read_all_files: tailwindcss_oxide::scanner: exit
2025-05-06T23:13:45.916682Z INFO extract_candidates:parse_all_blobs: tailwindcss_oxide::scanner: enter
2025-05-06T23:13:45.916688Z INFO extract_candidates:parse_all_blobs:extract: tailwindcss_oxide::scanner: enter
2025-05-06T23:13:45.918271Z INFO extract_candidates:parse_all_blobs:extract: tailwindcss_oxide::scanner: exit
2025-05-06T23:13:45.918282Z INFO extract_candidates:parse_all_blobs: tailwindcss_oxide::scanner: exit
2025-05-06T23:13:45.918286Z INFO extract_candidates:read_all_files: tailwindcss_oxide::scanner: enter
2025-05-06T23:13:45.918288Z INFO extract_candidates:read_all_files: tailwindcss_oxide::scanner: Reading 2 file(s)
2025-05-06T23:13:45.918315Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/app/tailwind.css"
2025-05-06T23:13:45.918504Z INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/RobinMalfait/spreadsheet/out.css"
2025-05-06T23:13:45.918512Z INFO extract_candidates:read_all_files: tailwindcss_oxide::scanner: exit
2025-05-06T23:13:45.918519Z INFO extract_candidates:extract_css_variables: tailwindcss_oxide::scanner: enter
2025-05-06T23:13:45.918522Z INFO extract_candidates:extract_css_variables:extract: tailwindcss_oxide::scanner: enter
2025-05-06T23:13:45.918635Z INFO extract_candidates:extract_css_variables:extract: tailwindcss_oxide::scanner: exit
2025-05-06T23:13:45.918640Z INFO extract_candidates:extract_css_variables: tailwindcss_oxide::scanner: exit
2025-05-06T23:13:45.919059Z INFO extract_candidates: tailwindcss_oxide::scanner: exit
```
</details>
We also output where we are writing the file to. This looks like this
when using the CLI:
<img width="1462" alt="image"
src="https://github.com/user-attachments/assets/79c2cc95-adea-4bbd-a4f1-101de45726f5"
/>
Last but not least, this also ignores `.log` files by default
## Test plan
Ran the CLI (but you can use any tool real, since this is implemented in
Oxide) with the `DEBUG=*` flag.
The file generated, looks like the example I shared above.
|
||
|
|
449dfcf00d
|
Make upgrades faster (#17898)
This PR fixes an issue where the upgrade tests were taking too long. This PR fixes that. Essentially when updating dependencies we did this: ```sh npm install tailwindcss@latest npm install @tailwindcss/postcss@latest npm install prettier-plugin-tailwindcss@latest ``` But this is not ideal, because we are calling out to `npm` and run each dependency in isolation. With this PR, we essentially do it all in one go: ```sh npm install tailwindcss@latest @tailwindcss/postcss@latest prettier-plugin-tailwindcss@latest ``` ## Test plan Testing this locally, the results look like this: | Before | After | |--------|-------| | <img width="590" alt="image" src="https://github.com/user-attachments/assets/c899d432-78c3-4945-af73-3ef4fffa08da" /> | <img width="656" alt="image" src="https://github.com/user-attachments/assets/a448d711-dd74-44cf-9790-c8a14fc6964f" /> | In CI: | Before (with a failure) | After | | --- | --- | | <img width="224" alt="image" src="https://github.com/user-attachments/assets/f58a6bf6-fdbe-4474-aa1f-444ab51a53c9" /> | <img width="224" alt="image" src="https://github.com/user-attachments/assets/54606df5-4f69-444b-8d4c-5ce27c5d6b41" /> | [ci-all] |
||
|
|
4f8539c063
|
Fix bug replacing modifier variable shorthand syntax underscores (#17889)
Resolves #17888 **Reproduction URL:** https://play.tailwindcss.com/YvIekuzVRd Changes: * Don't use `decodeArbitraryValue` when parsing variable shorthand syntax in modifiers * replace `decodeArbitraryValue(modifier.slice(1, -1))` with `modifier.slice(1, -1)` * added test case, passing ✅ --------- Co-authored-by: Robin Malfait <malfait.robin@gmail.com> |
||
|
|
ed45952d15
|
Update turbo 2.5.0 → 2.5.2 (patch) (#17887) | ||
|
|
5c5ae04db6
|
Fix Windows CI build (#17878)
This PR fixes a Windows CI issue due to the recently merged #17846 There might be better ways to solve this, but essentially we want to make sure we are always dealing with `\n` and not `\r\n`. This PR fixes that by replacing all `\r\n` with `\n` in the tests. |
||
|
|
6a1df6acf6
|
Ignore @tailwind utilities inside @reference (#17836)
You can use `@reference "tailwindcss"` or `@reference
"../path/to/your/css/file.css"` to reference your theme for use in
`@apply`, `theme(…)`, etc…
Unfortunatley, because the imported file still contains `@tailwind
utilities` it would trigger a re-scan of the filesystem — even though
the use of `@reference` ensures that no CSS can actually be output by
the import itself.
This PR does two things:
- Adds some explicit feature detection tests for what features we pick
up in a stylesheet based on the CSS written and how things are imported
- Explicitly ignores `@tailwind utilities` inside of `@reference` so it
isn't a trigger for file scanning
Because of how Vite itself handles dependencies editing files on disk
will still trigger a rebuild of any file using `@reference`. This is
because Vite rebuilds files when _any_ of its transitive dependencies
change.
For example, given this Vue file:
```vue
<style>
@reference "./styles.css";
</style>
<template> <!-- ... --> </template>
```
And this stylesheet:
```css
@import "tailwindcss";
```
The dependency chain looks like this: `file.vue -> styles.css -> {all
the sources in your project}`
Vite sees that a file (e.g. `index.html`) has changed, thus `styles.css`
needs change, which means `file.vue` needs to be compiled again as well.
Now in reality we depend on the _on disk_ version of styles.css not the
compiled version but Vite itself doesn't know that (or have a way to
indicate this afaik).
Coming up with a solution to that problem will have to be a separate PR
— but there is a workaround:
### 1. Inline the imports from `@import "tailwindcss";`
Replace this in your main stylesheet:
```css
@import "tailwindcss";
```
with this (this is basically what `node_modules/tailwindcss/index.css`
is):
```css
@layer theme, base, components, utilities;
@import 'tailwindcss/theme' layer(theme);
@import 'tailwindcss/preflight' layer(base);
@import 'tailwindcss/utilities' layer(utilities);
/* the rest of your styles imports, styles, etc… */
```
### 2. Split your stylesheet into "main" and "theme" parts
Your "theme" is comprised of the `@import 'tailwindcss/theme'
layer(theme);` import, any custom `@theme` blocks, any `@config`
directives, and any `@plugin` directives. Move all of these into their
own file.
For example, replace this with two files:
```css
@layer theme, base, components, utilities;
@import 'tailwindcss/theme' layer(theme);
@import 'tailwindcss/preflight' layer(base);
@import 'tailwindcss/utilities' layer(utilities);
@theme {
--color-primary: #c0ffee;
}
@plugin "./my-plugin.js";
/* the rest of your styles imports, styles, etc… */
```
with a theme file:
```css
@import 'tailwindcss/theme' layer(theme);
/* all your `@theme` stuff goes in this file */
@theme {
--color-primary: #c0ffee;
}
/* additionally any @config or @plugin does too */
@plugin "./my-plugin.js";
```
and your main CSS file:
```css
@layer theme, base, components, utilities;
@import './my-theme.css'; /* I replaced this import */
@import 'tailwindcss/preflight' layer(base);
@import 'tailwindcss/utilities' layer(utilities);
/* the rest of your styles imports, styles, etc… */
```
### 3. Import only your "theme" file in your Vue components / CSS
modules / etc…
```vue
<style>
@reference "./my-theme.css";
</style>
<template> <!-- ... --> </template>
```
Fixes #17693
|
||
|
|
d38554d110
|
Fix HAML extraction with embedded Ruby (#17846)
This PR fixes and improves the HAML extractor by ensuring that whenever we detect lines or blocks of Ruby code (`-`, `=` and `~`) characters at the beginning of the line, we treat them as Ruby code. Fixes: #17813 ## Test Plan 1. Existing tests pass 2. Changed 1 existing test which embedded Ruby syntax 3. Added a dedicated test to ensure the HAML file in the linked issue is parsed correctly Running this in the internal extractor tool you can see that the `w-[12px]`, `w-[16px]`, `h-[12px]`, and `h-[16px]` are properly extracted. Note: the `mr-12px` is also extracted, but not highlighted because this is not a valid Tailwind CSS class. <img width="1816" alt="image" src="https://github.com/user-attachments/assets/fc5929ca-bc71-47d2-b21b-7abeec86f54d" /> |
||
|
|
473f0241bf
|
Update h3 1.15.1 → 1.15.3 (patch) (#17873) | ||
|
|
e00d0926eb
|
Update @vitejs/plugin-react 4.3.4 → 4.4.1 (minor) (#17862) | ||
|
|
dd5ec49606
|
Update eslint 9.24.0 → 9.25.1 (minor) (#17850)
Here is everything you need to know about this update. Please take a good look at what changed and the test results before merging this pull request. ### What changed? #### ✳️ eslint (9.24.0 → 9.25.1) · [Repo](https://github.com/eslint/eslint) · [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md) <details> <summary>Release Notes</summary> <h4><a href="https://github.com/eslint/eslint/releases/tag/v9.25.1">9.25.1</a></h4> <blockquote><h2 dir="auto">Bug Fixes</h2> <ul dir="auto"> <li> <a href=" |
||
|
|
c095071f22
|
Skip .css files when migrating templates (#17854)
This PR fixes an issue where the upgrade tool also migrates `.css` files as-if they are content files. This is not the intended behavior. ## Test plan Ran this on my personal website. Before: <img width="1316" alt="image" src="https://github.com/user-attachments/assets/2b7337c6-7b88-4811-911f-139ab2e31b3b" /> After: <img width="1046" alt="image" src="https://github.com/user-attachments/assets/55f09355-37cb-419b-9924-973cf2681c1d" /> |
||
|
|
4e4275638f
|
Design system driven upgrade migrations (#17831)
This PR introduces a vastly improved upgrade migrations system, to migrate your codebase and modernize your utilities to make use of the latest variants and utilities. It all started when I saw this PR the other day: https://github.com/tailwindlabs/tailwindcss/pull/17790 I was about to comment "Don't forget to add a migration". But I've been thinking about a system where we can automate this process away. This PR introduces this system. This PR introduces upgrade migrations based on the internal Design System, and it mainly updates arbitrary variants, arbitrary properties and arbitrary values. ## The problem Whenever we ship new utilities, or you make changes to your CSS file by introducing new `@theme` values, or adding new `@utility` rules. It could be that the rest of your codebase isn't aware of that, but you could be using these values. For example, it could be that you have a lot of arbitrary properties in your codebase, they look something like this: ```html <div class="[color-scheme:dark] [text-wrap:balance]"></div> ``` Whenever we introduce new features in Tailwind CSS, you probably don't keep an eye on the release notes and update all of these arbitrary properties to the newly introduced utilities. But with this PR, we can run the upgrade tool: ```console npx -y @tailwindcss/upgrade@latest ``` ...and it will upgrade your project to use the new utilities: ```html <div class="scheme-dark text-balance"></div> ``` It also works for arbitrary values, for example imagine you have classes like this: ```html <!-- Arbitrary property --> <div class="[max-height:1lh]"></div> <!-- Arbitrary value --> <div class="max-h-[1lh]"></div> ``` Running the upgrade tool again: ```console npx -y @tailwindcss/upgrade@latest ``` ... gives you the following output: ```html <!-- Arbitrary property --> <div class="max-h-lh"></div> <!-- Arbitrary value --> <div class="max-h-lh"></div> ``` This is because of the original PR I mentioned, which introduced the `max-h-lh` utilities. A nice benefit is that this output only has 1 unique class instead of 2, which also potentially reduces the size of your CSS file. It could also be that you are using arbitrary values where you (or a team member) didn't even know an alternative solution existed. E.g.: ```html <div class="w-[48rem]"></div> ``` After running the upgrade tool you will get this: ```html <div class="w-3xl"></div> ``` We can go further though. Since the release of Tailwind CSS v4, we introduced the concept of "bare values". Essentially allowing you to type a number on utilities where it makes sense, and we produce a value based on that number. So an input like this: ```html <div class="border-[123px]"></div> ``` Will be optimized to just: ```html <div class="border-123"></div> ``` This can be very useful for complex utilities, for example, how many times have you written something like this: ```html <div class="grid-cols-[repeat(16,minmax(0,1fr))]"></div> ``` Because up until Tailwind CSS v4, we only generated 12 columns by default. But since v4, we can generate any number of columns automatically. Running the migration tool will give you this: ```html <div class="grid-cols-16"></div> ``` ### User CSS But, what if I told you that we can keep going... In [Catalyst](https://tailwindcss.com/plus/ui-kit) we often use classes that look like this for accessibility reasons: ```html <div class="text-[CanvasText] bg-[Highlight]"></div> ``` What if you want to move the `CanvasText` and `Highlight` colors to your CSS: ```css @import "tailwincdss"; @theme { --color-canvas: CanvasText; --color-highlight: Highlight; } ``` If you now run the upgrade tool again, this will be the result: ```html <div class="text-canvas bg-highlight"></div> ``` We never shipped a `text-canvas` or `bg-highlight` utility, but the upgrade tool uses your own CSS configuration to migrate your codebase. This will keep your codebase clean, consistent and modern and you are in control. Let's look at one more example, what if you have this in a lot of places: ```html <div class="[scrollbar-gutter:stable]"></div> ``` And you don't want to wait for the Tailwind CSS team to ship a `scrollbar-stable` (or similar) feature. You can add your own utility: ```css @import "tailwincdss"; @utility scrollbar-stable { scrollbar-gutter: stable; } ``` ```html <div class="scrollbar-stable"></div> ``` ## The solution — how it works There are 2 big things happening here: 1. Instead of us (the Tailwind CSS team) hardcoding certain migrations, we will make use of the internal `DesignSystem` which is the source of truth for all this information. This is also what Tailwind CSS itself uses to generate the CSS file. The internal `DesignSystem` is essentially a list of all: 1. The internal utilities 2. The internal variants 3. The default theme we ship 4. The user CSS 1. With custom `@theme` values 2. With custom `@custom-variant` implementations 3. With custom `@utility` implementations 2. The upgrade tool now has a concept of `signatures` The signatures part is the most interesting one, and it allows us to be 100% sure that we can migrate your codebase without breaking anything. A signature is some unique identifier that represents a utility. But 2 utilities that do the exact same thing will have the same signature. To make this work, we have to make sure that we normalize values. One such value is the selector. I think a little visualization will help here: | UTILITY | GENERATED SIGNATURE | | ---------------- | ----------------------- | | `[display:flex]` | `.x { display: flex; }` | | `flex` | `.x { display: flex; }` | They have the exact same signature and therefore the upgrade tool can safely migrate them to the same utility. For this we will prefer the following order: 1. Static utilities — essentially no brackets. E.g.: `flex`, `grid-cols-2` 2. Arbitrary values — e.g.: `max-h-[1lh]`, `border-[2px]` 3. Arbitrary properties — e.g.: `[color-scheme:dark]`, `[display:flex]` We also have to canonicalize utilities to there minimal form. Essentially making sure we increase the chance of finding a match. ``` [display:_flex_] → [display:flex] → flex [display:_flex] → [display:flex] → flex [display:flex_] → [display:flex] → flex [display:flex] → [display:flex] → flex ``` If we don't do this, then the signatures will be slightly different, due to the whitespace: | UTILITY | GENERATED SIGNATURE | | ------------------ | ------------------------- | | `[display:_flex_]` | `.x { display: flex ; }` | | `[display:_flex]` | `.x { display: flex; }` | | `[display:flex_]` | `.x { display: flex ; }` | | `[display:flex]` | `.x { display: flex; }` | ### Other small improvements A few other improvements are for optimizing existing utilities: 1. Remove unnecessary data types. E.g.: - `bg-[color:red]` -> `bg-[red]` - `shadow-[shadow:inset_0_1px_--theme(--color-white/15%)]` -> `shadow-[inset_0_1px_--theme(--color-white/15%)]` This also makes use of these signatures and if dropping the data type results in the same signature then we can safely drop it. Additionally, if a more specific utility exists, we will prefer that one. This reduced ambiguity and the need for data types. - `bg-[position:123px]` → `bg-position-[123px]` - `bg-[123px]` → `bg-position-[123px]` - `bg-[size:123px]` → `bg-size-[123px]` 2. Optimizing modifiers. E.g.: - `bg-red-500/[25%]` → `bg-red-500/25` - `bg-red-500/[100%]` → `bg-red-500` - `bg-red-500/100` → `bg-red-500` 3. Hoist `not` in arbitrary variants - `[@media_not_(prefers-color-scheme:dark)]:flex` → `not-[@media_(prefers-color-scheme:dark)]:flex` → `not-dark:flex` (in case you are using the default `dark` mode implementation 4. Optimize raw values that could be converted to bare values. This uses the `--spacing` variable to ensure it is safe. - `w-[64rem]` → `w-256` --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Philipp Spiess <hello@philippspiess.com> |
||
|
|
45cd32eed7
|
Prepare v4.1.5 release (#17830)
Co-authored-by: Adam Wathan <adam.wathan@gmail.com>v4.1.5 |
||
|
|
a636933cd4
|
Add discrete properties to the default list of transition properties (#17812)
This PR changes the `transition` utility to include five new properties: - `display` - `visibility` - `content-visibility` - `overlay` - `pointer-eventes` On its own, this change does nothing since these properties will apply their change _immediately_. However, in combination with `transition-discrete` this will ensure that you can now transition these types without requiering `transition-all` or arbitrary transition properties. ## Test plan - Ensured this works in the Vite playground with native `<dialog>` components https://github.com/user-attachments/assets/89bf4a75-b681-4574-8bb4-845fffdec43b Notice how: - the backdrop stays open until the transition is over (that's because of `overlay` in the property list) - the dialog is displayed until the transition is over --------- Co-authored-by: Adam Wathan <adam.wathan@gmail.com> |
||
|
|
ab4eb18bab
|
Update @types/react-dom 19.1.1 → 19.1.2 (patch) (#17829) |