75 Commits

Author SHA1 Message Date
Adam Wathan
437579d3f0
Prepare v4.0.0-alpha.33 release (#14967)
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-11-11 20:28:41 -05:00
Adam Wathan
7da9272d0f
Prepare v4.0.0-alpha.32 (#14954)
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-11-11 11:05:22 -05:00
Philipp Spiess
c72c83fee3
Vite: Support Tailwind in Svelte <style> blocks (#14151)
Closes #13305

This PR adds registers a Svelte preprocessor, used by the Svelte Vite
plugin, to run Tailwind CSS for styles inside the `<style>` block, this
enables users to use Tailwind CSS features like `@apply` from inside
Svelte components:


```svelte
<script>
  let name = 'world'
</script>
<h1 class="foo underline">Hello {name}!</h1>
<style global>
  @import 'tailwindcss/utilities';
  @import 'tailwindcss/theme' theme(reference);
  @import './components.css';
</style>
```

## Test Plan

I've added integration tests to validate this works as expected.
Furthermore I've used the
[tailwindcss-playgrounds](https://github.com/philipp-spiess/tailwind-playgrounds)
SvelteKit project to ensure this works in an end-to-end setup:

<img width="2250" alt="Screenshot 2024-11-08 at 14 45 31"
src="https://github.com/user-attachments/assets/64e9e0f3-53fb-4039-b0a7-3ce945a29179">
2024-11-08 20:01:16 +01:00
Philipp Spiess
15fc7f4558
Apply non-Tailwind CSS transforms in Vite plugin (#14871)
Fixes: #14839
Fixes: #14796

This PR fixes an issue in the Vite extension where we previously only
ran a small list of allow-listed plugins for the second stage transform
in the build step. This caused some CSS features to unexpectedly not
work in production builds (one such example is Vue's `:deep(...)`
selector).

To fix this, I changed the allow listed plugins that we do want to run
to a block list to filter out some plugins we know we don't want to run
(e.g. the Tailwind Vite plugin for example or some built-in Vite plugins
that are not necessary).


## Test plan

This PR adds a new integration test suite to test interop with a custom
Vite transformer that looks like this:

```js
{
  name: 'recolor',
  transform(code, id) {
    if (id.includes('.css')) {
      return code.replace(/red/g, 'blue')
    }
  },
}
```

I also validated that this does indeed fix the Vue `:deep(...)` selector
related issue that we were seeing by copying the repro of #14839 into
our playground:

![Screenshot 2024-11-05 at
13.35.26.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/0Y77ilPI2WoJfMLFiAEw/4e46ab61-4acf-461a-9e40-f7c9ec3c69b2.png)

You can see in the screenshot above that the `:deep()` selector
overwrites the scoped styles as expected in both the dev mode and the
prod build (screenshotted).

Furthermore I reproduced the issue reported in
https://github.com/tailwindlabs/tailwindcss/issues/14796 and was able to
confirm that in a production build, the styling works as expected:

<img width="517" alt="Screenshot 2024-11-06 at 14 26 50"
src="https://github.com/user-attachments/assets/ade6fe38-be0d-4bd0-9a9a-67b6fec05ae0">

Lastly, I created a repository out of the biggest known-to-me Vite
projects: [Astro, Nuxt, Remix, SolidStart, and
SvelteKit](https://github.com/philipp-spiess/tailwind-playgrounds) and
verified that both dev and prod builds show no issue and the candidate
list is properly appended in each case.

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2024-11-07 16:26:18 +01:00
Jordan Pittman
e82b316c61
Rewrite urls in CSS files when using Vite (#14877)
Fixes #14784

This is an alternative to #14850 in which we actually perform url
rewriting / rebasing ourselves. We ported a large portion of the
URL-rewriting code from Vite (with attribution) to use here with some
minor modifications. We've added test cases for the url rewriting so
verifying individual cases is easy. We also wrote integration tests for
Vite that use PostCSS and Lightning CSS that verify that files are found
and inlined or relocated/renamed as necessary.

We also did some manual testing in the Playground to verify that this
works as expected across several CSS files and directories which you can
see a screenshot from here:

<img width="1344" alt="Screenshot 2024-11-05 at 10 25 16"
src="https://github.com/user-attachments/assets/ff0b3ac8-cdc9-4e26-af79-36396a5b77b9">

---------

Co-authored-by: Philipp Spiess <hello@philippspiess.com>
2024-11-07 09:51:58 -05:00
Robin Malfait
c5b6df2a27
Optimize generated CSS output (#14873)
This PR improves the generated CSS by running it through Lightning CSS
twice.Right now Lightning CSS merges adjacent at-rules and at the end
flattens the nesting. This means that after the nesting is flattened,
the at-rules that are adjacent and could be merged together will not be
merged.

This PR improves our output by running Lightning CSS twice on the
generated CSS which will make sure to merge adjacent at-rules after the
nesting is flattened.

Note: in the diff output you'll notice that some properties are
duplicated. These need some fixes in Lightning CSS itself but they don't
break anything for us right now.

Related PR in Lightning CSS for the double `-webkit-backdrop-filter` can
be found here: https://github.com/parcel-bundler/lightningcss/pull/850

---------

Co-authored-by: Philipp Spiess <hello@philippspiess.com>
2024-11-06 11:39:09 +00:00
Robin Malfait
894bf9f5ef
Support migrating projects with multiple config files (#14863)
When migrating a project from Tailwind CSS v3 to Tailwind CSS v4, then
we started the migration process in the following order:

1. Migrate the JS/TS config file
2. Migrate the source files (found via the `content` option)
3. Migrate the CSS files

However, if you have a setup where you have multiple CSS root files
(e.g.: `frontend` and `admin` are separated), then that typically means
that you have an `@config` directive in your CSS files. These point to
the Tailwind CSS config file.

This PR changes the migration order to do the following:

1. Build a tree of all the CSS files
2. For each `@config` directive, migrate the JS/TS config file
3. For each JS/TS config file, migrate the source files

If a CSS file does not contain any `@config` directives, then we start
by filling in the `@config` directive with the default Tailwind CSS
config file (if found, or the one passed in). If no default config file
or passed in config file can be found, then we will error out (just like
we do now)

---------

Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2024-11-04 16:52:11 +00:00
Robin Malfait
94ea5e225b
Prepare v4.0.0-alpha.31 release (#14823)
Prepare v4.0.0-alpha.31 release
2024-10-30 07:53:51 -04:00
Robin Malfait
f3786253f2
Fix integration tests on Windows (#14824)
This PR fixes Windows related path issues after merging #14820

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2024-10-30 11:26:29 +00:00
Robin Malfait
d68a780f98
Auto source detection improvements (#14820)
This PR introduces a new `source(…)` argument and improves on the
existing `@source`. The goal of this PR is to make the automatic source
detection configurable, let's dig in.

By default, we will perform automatic source detection starting at the
current working directory. Auto source detection will find plain text
files (no binaries, images, ...) and will ignore git-ignored files.

If you want to start from a different directory, you can use the new
`source(…)` next to the `@import "tailwindcss/utilities"
layer(utilities) source(…)`.

E.g.:

```css
/* ./src/styles/index.css */
@import 'tailwindcss/utilities' layer(utilities) source('../../');
```

Most people won't split their source files, and will just use the simple
`@import "tailwindcss";`, because of this reason, you can use
`source(…)` on the import as well:

E.g.:

```css
/* ./src/styles/index.css */
@import 'tailwindcss' source('../../');
```

Sometimes, you want to rely on auto source detection, but also want to
look in another directory for source files. In this case, yuo can use
the `@source` directive:

```css
/* ./src/index.css */
@import 'tailwindcss';

/* Look for `blade.php` files in `../resources/views` */
@source '../resources/views/**/*.blade.php';
```

However, you don't need to specify the extension, instead you can just
point the directory and all the same automatic source detection rules
will apply.

```css
/* ./src/index.css */
@import 'tailwindcss';

@source '../resources/views';
```

If, for whatever reason, you want to disable the default source
detection feature entirely, and only want to rely on very specific glob
patterns you define, then you can disable it via `source(none)`.

```css
/* Completely disable the default auto source detection */
@import 'tailwindcss' source(none);

/* Only look at .blade.php files, nothing else  */
@source "../resources/views/**/*.blade.php";
```

Note: even with `source(none)`, if your `@source` points to a directory,
then auto source detection will still be performed in that directory. If
you don't want that, then you can simply add explicit files in the globs
as seen in the previous example.

```css
/* Completely disable the default auto source detection */
@import 'tailwindcss' source(none);

/* Run auto source detection in `../resources/views` */
@source "../resources/views";
```

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-10-29 20:33:34 +00:00
Jordan Pittman
10a8f1a725
Prepare v4.0.0-alpha.30 release (#14789) 2024-10-24 16:22:08 -04:00
Philipp Spiess
2327e68bc7
Prepare v4.0.0-alpha.29 release (#14761) 2024-10-23 15:30:26 +02:00
philipp-spiess
d59f1b3e5d Vite: Fix issues when loading files via static asset queries (#14716)
Fixes: #14558

This PR fixes an issue where our Vite plugin would crash when trying to load stylesheets via certain static asset query parameters:

```ts
import raw from './style.css?raw'
import url from './style.css?url'
```

The proper behavior for our extension is to _not touch these file at all_. The `?raw` identifier should never transform anything and the `?url` one will emit a module which points to the asset URL. However, if that URL is loaded as a stylesheet, another transform hook is called and the file is properly transformed. I verified this in the Vite setup and have added an integration test ensuring these two features work as expected.

I've also greatly reduced the complexity of the Vite playground to make it easier to set up examples like this in the future.
2024-10-22 16:03:07 +00:00
Adam Wathan
b701ed6916
Prepare v4.0.0-alpha.28 release (#14709)
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-10-17 17:03:28 -04:00
Philipp Spiess
a75152d162
Release v4.0.0-alpha.27 (#14671) 2024-10-15 10:28:34 +00:00
Robin Malfait
39e108d5f5
release v4.0.0-alpha.26 2024-10-03 16:39:59 +02:00
Robin Malfait
35b84cc313
Improve @tailwindcss/postcss performance for initial builds (#14565)
This PR improves the performance of the `@tailwindcss/postcss` plugin.
Before this change we created 2 compiler instances instead of a single
one. On a project where a `tailwindcss.config.ts` file is used, this
means that the timings look like this:

```
[@tailwindcss/postcss] Setup compiler: 137.525ms
⋮
[@tailwindcss/postcss] Setup compiler: 43.95ms
```

This means that with this small change, we can easily shave of ~50ms for
initial PostCSS builds.

---------

Co-authored-by: Philipp Spiess <hello@philippspiess.com>
Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2024-10-03 16:21:54 +02:00
Robin Malfait
ab82efab7d
Expose timing information in debug mode (#14553)
This PR exposes when using the the `DEBUG` environment variable. This
follows the `DEBUG` conventions where:

- `DEBUG=1`
- `DEBUG=true`
- `DEBUG=*`
- `DEBUG=tailwindcss`

Will enable the debug information, but when using:

- `DEBUG=0`
- `DEBUG=false`
- `DEBUG=-tailwindcss`

It will not.

This currently only exposes some timings related to:

1. Scanning for candidates
2. Building the CSS
3. Optimizing the CSS

We can implement a more advanced version of this where we also expose
more fine grained information such as the files we scanned, the amount
of candidates we found and so on. But I believe that this will be enough
to start triaging performance related issues.
2024-09-30 14:39:21 +00:00
Robin Malfait
c094fadbbc
Release v4.0.0-alpha.25 (#14507) 2024-09-24 17:03:00 +00:00
Philipp Spiess
79794744a9
Resolve @import in core (#14446)
This PR brings `@import` resolution into Tailwind CSS core. This means
that our clients (PostCSS, Vite, and CLI) no longer need to depend on
`postcss` and `postcss-import` to resolve `@import`. Furthermore this
simplifies the handling of relative paths for `@source`, `@plugin`, or
`@config` in transitive CSS files (where the relative root should always
be relative to the CSS file that contains the directive). This PR also
fixes a plugin resolution bug where non-relative imports (e.g. directly
importing node modules like `@plugin '@tailwindcss/typography';`) would
not work in CSS files that are based in a different npm package.

### Resolving `@import`

The core of the `@import` resolution is inside
`packages/tailwindcss/src/at-import.ts`. There, to keep things
performant, we do a two-step process to resolve imports. Imagine the
following input CSS file:

```css
@import "tailwindcss/theme.css";
@import "tailwindcss/utilities.css";
```

Since our AST walks are synchronous, we will do a first traversal where
we start a loading request for each `@import` directive. Once all loads
are started, we will await the promise and do a second walk where we
actually replace the AST nodes with their resolved stylesheets. All of
this is recursive, so that `@import`-ed files can again `@import` other
files.

The core `@import` resolver also includes extensive test cases for
[various combinations of media query and supports conditionals as well
als layered
imports](https://developer.mozilla.org/en-US/docs/Web/CSS/@import).

When the same file is imported multiple times, the AST nodes are
duplicated but duplicate I/O is avoided on a per-file basis, so this
will only load one file, but include the `@theme` rules twice:

```css
@import "tailwindcss/theme.css";
@import "tailwindcss/theme.css";
```

### Adding a new `context` node to the AST

One limitation we had when working with the `postcss-import` plugin was
the need to do an additional traversal to rewrite relative `@source`,
`@plugin`, and `@config` directives. This was needed because we want
these paths to be relative to the CSS file that defines the directive
but when flattening a CSS file, this information is no longer part of
the stringifed CSS representation. We worked around this by rewriting
the content of these directives to be relative to the input CSS file,
which resulted in added complexity and caused a lot of issues with
Windows paths in the beginning.

Now that we are doing the `@import` resolution in core, we can use a
different data structure to persist this information. This PR adds a new
`context` node so that we can store arbitrary context like this inside
the Ast directly. This allows us to share information with the sub tree
_while doing the Ast walk_.

Here's an example of how the new `context` node can be used to share
information with subtrees:

```ts
const ast = [
  rule('.foo', [decl('color', 'red')]),
  context({ value: 'a' }, [
    rule('.bar', [
      decl('color', 'blue'),
      context({ value: 'b' }, [
        rule('.baz', [decl('color', 'green')]),
      ]),
    ]),
  ]),
]

walk(ast, (node, { context }) => {
  if (node.kind !== 'declaration') return
  switch (node.value) {
    case 'red':   assert(context.value === undefined)
    case 'blue':  assert(context.value === 'a')
    case 'green': assert(context.value === 'b')
  }
})
```

In core, we use this new Ast node specifically to persist the `base`
path of the current CSS file. We put the input CSS file `base` at the
root of the Ast and then overwrite the `base` on every `@import`
substitution.

### Removing the dependency on `postcss-import`

Now that we support `@import` resolution in core, our clients no longer
need a dependency on `postcss-import`. Furthermore, most dependencies
also don't need to know about `postcss` at all anymore (except the
PostCSS client, of course!).

This also means that our workaround for rewriting `@source`, the
`postcss-fix-relative-paths` plugin, can now go away as a shared
dependency between all of our clients. Note that we still have it for
the PostCSS plugin only, where it's possible that users already have
`postcss-import` running _before_ the `@tailwindcss/postcss` plugin.

Here's an example of the changes to the dependencies for our Vite client
 :

<img width="854" alt="Screenshot 2024-09-19 at 16 59 45"
src="https://github.com/user-attachments/assets/ae1f9d5f-d93a-4de9-9244-61af3aff1237">

### Performance

Since our Vite and CLI clients now no longer need to use `postcss` at
all, we have also measured a significant improvement to the initial
build times. For a small test setup that contains only a hand full of
files (nothing super-complex), we measured an improvement in the
**3.5x** range:

<img width="1334" alt="Screenshot 2024-09-19 at 14 52 49"
src="https://github.com/user-attachments/assets/06071fb0-7f2a-4de6-8ec8-f202d2cc78e5">

The code for this is in the commit history if you want to reproduce the
results. The test was based on the Vite client.

### Caveats

One thing to note is that we previously relied on finding specific
symbols in the input CSS to _bail out of Tailwind processing
completely_. E.g. if a file does not contain a `@tailwind` or `@apply`
directive, it can never be a Tailwind file.

Since we no longer have a string representation of the flattened CSS
file, we can no longer do this check. However, the current
implementation was already inconsistent with differences on the allowed
symbol list between our clients. Ideally, Tailwind CSS should figure out
wether a CSS file is a Tailwind CSS file. This, however, is left as an
improvement for a future API since it goes hand-in-hand with our planned
API changes for the core `tailwindcss` package.

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2024-09-23 17:05:55 +02:00
Philipp Spiess
2ef87ab7fb
Release v4.0.0-alpha.24 (#14395) 2024-09-12 16:10:56 +02:00
Jordan Pittman
15d1714c33 v4.0.0-alpha.23 2024-09-05 10:43:07 -04:00
Adam Wathan
d9558bbc4c v4.0.0-alpha.22 2024-09-04 15:50:57 -04:00
Philipp Spiess
2dd52f5a0f
Vite: Add support for <style> tags in Astro files (#14340)
This works similar to the Vue setup. The styles that Astro will receive
might still contain Tailwind CSS APIs but since it's not picky, we can
pass that through to the regular Vite `transform` handlers for now.

This, however, will have issues like
https://github.com/tailwindlabs/tailwindcss/issues/14205. We have to fix
this together with Vue and other similar extensions later. For now, it
will break when syntax is used that lightningcss rewrites (like `@apply
text-3xl/tight;`)

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2024-09-04 19:14:05 +02:00
Philipp Spiess
719a5351c1
Fix Nuxt integration (#14319)
We noticed that Nuxt projects were not working with the tailwindcss
project. The issue was traced down to the fact that Nuxt starts multiple
Vite dev servers and calling the experimental `waitForRequestsIdle()` on
one of the test servers would never resolve.

This was fixed upstream and is part of the latest Vite/Nuxt release:
https://github.com/vitejs/vite/issues/17980.

We still need to handle the fact that Vite can spawn multiple dev
servers. This is necessary because when we invalidate all roots, we need
to find that module inside all of the spawned servers. If we only look
at the _last server_ (what we have done before), we would not find the
module and thus could not invalidate it.
2024-09-04 10:53:15 -04:00
Philipp Spiess
e7ca667f76 Remove leftover TODO in Vite plugin 2024-09-04 11:43:41 +02:00
Philipp Spiess
835922812b
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269)
Fixes #14205
Fixes #14106

This PR reworks the Vite extension in order to supprt `lightningcss` as
the pre-processor, enable faster rebuilds, and adds support for `vite
build --watch` mode. To make this change possible, we've done two major
changes to the extension that have caused the other changes.

## 1. Tailwind CSS is a preprocessor

We now run all of our modifications in `enforce: 'pre'`. This means that
Tailwind CSS now gets the untransformed CSS files rather than the one
already going through postcss or lightningcss. We do this because
Tailwind CSS _is_ a preprocessor at the same level as those tools and we
do sometimes use the language in ways that [creates problems when it's
the input for other
bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269).

The correct solution here is to make Tailwind not depend on any other
transformations. The main reason we were not using the `enforce: 'pre'`
phase in Vite before was becuase we relied on the `@import` flattening
of postcss so we now have to do this manually. `@import` flattening is
now a concern that every Tailwind V4 client has to deal with so this
might actually be something we want to inline into tailwindcss in the
future.

## 2. A Vite config can have multiple Tailwind roots 

This is something that we have not made very explicit in the previous
iteration of the Vite plugin but we have to support multiple Tailwind
roots in a single Vite workspace. A Tailwind root is a CSS file that is
used to configure Tailwind. Technically, any CSS file can be the input
for `tailwindcss` but you have to add certain rules (e.g. `@import
"tailwindcss";`) to make the compiler do something.

A workspace can have multiple of these rules (e.g. by having different
Tailwind configures for different sub-pages). With the addition of
[support for `@source`
rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS
config files](https://github.com/tailwindlabs/tailwindcss/pull/14239),
Tailwind roots become more complex and can have a custom list of
_dependencies_ (that is other JavaScript modules the compiler includes
as part of these new rules). In order to _only rebuild the roots we need
to_, we have to make this separation very clear.

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
Philipp Spiess
a1d56d8e24
Ensure content globs defined in @config files are relative to that file (#14314)
When you configure custom content globs inside an `@config` file, we
want to tread these globs as being relative to that config file and not
the CSS file that requires the content file. A config can be used by
multiple CSS configs.

---------

Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2024-09-03 16:54:08 +02:00
Adam Wathan
dcfaaac8f6
Prepare v4.0.0-alpha.21 (#14313)
<!--

👋 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 an issue to first
discuss any significant new features. This includes things like adding
new utilities, creating new at-rules, or adding new component examples
to the documentation.


https://github.com/tailwindcss/tailwindcss/blob/master/.github/CONTRIBUTING.md

-->

Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-02 15:43:28 -04:00
Jordan Pittman
52012d90d7
Support loading config files via @config (#14239)
In Tailwind v4 the CSS file is the main entry point to your project and
is generally configured via `@theme`. However, given that all v3
projects were configured via a `tailwind.config.js` file we definitely
need to support those. This PR adds support for loading existing
Tailwind config files by adding an `@config` directive to the CSS —
similar to how v3 supported multiple config files except that this is
now _required_ to use a config file.

You can load a config file like so:

```
@import "tailwindcss";
@config "./path/to/tailwind.config.js";
```

A few notes:
- Both CommonJS and ESM config files are supported (loaded directly via
`import()` in Node)
- This is not yet supported in Intellisense or Prettier — should
hopefully land next week
- TypeScript is **not yet** supported in the config file — this will be
handled in a future PR.

---------

Co-authored-by: Philipp Spiess <hello@philippspiess.com>
Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2024-09-02 18:03:16 +02:00
Philipp Spiess
d5f563b746
Prepare v4.0.0-alpha.20 (#14244)
Prepare next `4.0.0-alpha.20` release
2024-08-23 15:51:53 +02:00
Philipp Spiess
84ebe19da2
Vite: Retain candidates between input CSS updates (#14228)
This PR fixes an issue introduced with the changed candidate cache
behavior in #14187.

Prior to #14187, candidates were cached globally within an instance of
Oxide. This meant that once a candidate was discovered, it would not
reset until you either manually cleared the cache or restarted the Oxide
process. With the changes in #14187 however, the cache was scoped to the
instance of the `Scanner` class with the intention of making the caching
behavior more easy to understand and to avoid a global cache.

This, however, had an unforeseen side-effect in our Vite extension.
Vite, in dev mode, discovers files _lazily_. So when a developer goes to
`/index.html` the first time, we will scan the `/index.html` file for
Tailwind candidates and then build a CSS file with those candidate. When
they go to `/about.html` later, we will _append_ the candidates from the
new file and so forth.

The problem now arises when the dev server detects changes to the input
CSS file. This requires us to do a re-scan of that CSS file which, after
#14187, caused the candidate cache to be gone. This is usually fine
since we would just scan files again for the changed candidate list but
in the Vite case we would only get the input CSS file change _but no
subsequent change events for all other files, including those currently
rendered in the browser_). This caused updates to the CSS file to remove
all candidates from the CSS file again.

Ideally, we can separate between two concepts: The candidate cache and
the CSS input file scan. An instance of the `Scanner` could re-parse the
input CSS file without having to throw away previous candidates. This,
however, would have another issue with the current Vite extension where
we do not properly retain instances of the `Scanner` class anyways. To
properly improve the cache behavior, we will have to fix the Vite
`Scanner` retaining behavior first. Unfortunately this means that for
the short term, we have to add some manual bookkeeping to the Vite
client and retain the candidate cache between builds ourselves.

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2024-08-21 12:54:42 +02:00
Robin Malfait
a902128640
Improve Oxide scanner API (#14187)
This PR updates the API for interacting with the Oxide API. Until now,
we used the name `scanDir(…)` which is fine, but we do way more work
right now.

We now have features such as:

1. Auto source detection (can be turned off, e.g.: `@tailwindcss/vite`
doesn't need it)
2. Scan based on `@source`s found in CSS files
3. Do "incremental" rebuilds (which means that the `scanDir(…)` result
was stateful).

To solve these issues, this PR introduces a new `Scanner` class where
you can pass in the `detectSources` and `sources` options. E.g.:

```ts
let scanner = new Scanner({
  // Optional, omitting `detectSources` field disables automatic source detection
  detectSources: { base: __dirname }, 

  // List of glob entries to scan. These come from `@source` directives in CSS.
  sources: [
    { base: __dirname, pattern: "src/**/*.css" },
    // …
  ],
});
```

The scanner object has the following API:

```ts
export interface ChangedContent {
  /** File path to the changed file */
  file?: string
  /** Contents of the changed file */
  content?: string
  /** File extension */
  extension: string
}
export interface DetectSources {
  /** Base path to start scanning from */
  base: string
}
export interface GlobEntry {
  /** Base path of the glob */
  base: string
  /** Glob pattern */
  pattern: string
}
export interface ScannerOptions {
  /** Automatically detect sources in the base path */
  detectSources?: DetectSources
  /** Glob sources */
  sources?: Array<GlobEntry>
}
export declare class Scanner {
  constructor(opts: ScannerOptions)
  scan(): Array<string>
  scanFiles(input: Array<ChangedContent>): Array<string>
  get files(): Array<string>
  get globs(): Array<GlobEntry>
}
```

The `scanFiles(…)` method is used for incremental rebuilds. It takes the
`ChangedContent` array for all the new/changes files. It returns whether
we scanned any new candidates or not.

Note that the `scanner` object is stateful, this means that we don't
have to track candidates in a `Set` anymore. We can just call
`getCandidates()` when we need it.

This PR also removed some unused code that we had in the `scanDir(…)`
function to allow for sequential or parallel `IO`, and sequential or
parallel `Parsing`. We only used the same `IO` and `Parsing` strategies
for all files, so I just got rid of it.

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2024-08-16 15:05:42 +02:00
Robin Malfait
f5f91ce9de
Prepare v4.0.0-alpha.19 (#14162)
Prepare next `4.0.0-alpha.19` release
2024-08-09 17:58:30 +02:00
Robin Malfait
d223112162
Bump dependencies (#14160)
This PR bumps dependencies

We also make some dependencies `catalog:` dependencies, which allows us
to keep
the version in sync. E.g.: `lightningcss` and `@types/node`.

Bumped `turbo` to the latest version + enabled the new UI

Fixed a bug in the tests now that `lightningcss` outputs the correct
value.
2024-08-09 16:12:24 +02:00
Philipp Spiess
b01ff53f2a
Vite: Support Tailwind in Vue <style> blocks (#14158)
This PR adds support to transforming `<style>` blocks emitted by Vue
components with tailwindcss when the `@tailwindcss/vite` is used.

Example:

```vue
<style>
  @import 'tailwindcss/utilities';
  @import 'tailwindcss/theme' theme(reference);
  .foo {
    @apply text-red-500;
  }
</style>
<template>
 <div class="underline foo">Hello Vue!</div>
</template>
```

Additionally, this PR also adds an integration test.

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2024-08-09 12:41:58 +02:00
Philipp Spiess
921b4b673b
Use import to load plugins (#14132)
Alternative to #14110

This PR changes the way how we load plugins to be compatible with ES6
async `import`s. This allows us to load plugins even inside the browser
but it comes at a downside: We now have to change the `compile` API to
return a `Promise`...

So most of this PR is rewriting all of the call sites of `compile` to
expect a promise instead of the object.

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2024-08-08 11:49:06 -04:00
Robin Malfait
541d84a3bb
Add @source support (#14078)
This PR is an umbrella PR where we will add support for the new
`@source` directive. This will allow you to add explicit content glob
patterns if you want to look for Tailwind classes in other files that
are not automatically detected yet.

Right now this is an addition to the existing auto content detection
that is automatically enabled in the `@tailwindcss/postcss` and
`@tailwindcss/cli` packages. The `@tailwindcss/vite` package doesn't use
the auto content detection, but uses the module graph instead.

From an API perspective there is not a lot going on. There are only a
few things that you have to know when using the `@source` directive, and
you probably already know the rules:

1. You can use multiple `@source` directives if you want.
2. The `@source` accepts a glob pattern so that you can match multiple
files at once
3. The pattern is relative to the current file you are in
4. The pattern includes all files it is matching, even git ignored files
1. The motivation for this is so that you can explicitly point to a
`node_modules` folder if you want to look at `node_modules` for whatever
reason.
6. Right now we don't support negative globs (starting with a `!`) yet,
that will be available in the near future.

Usage example:

```css
/* ./src/input.css */
@import "tailwindcss";
@source "../laravel/resources/views/**/*.blade.php";
@source "../../packages/monorepo-package/**/*.js";
```

It looks like the PR introduced a lot of changes, but this is a side
effect of all the other plumbing work we had to do to make this work.
For example:

1. We added dedicated integration tests that run on Linux and Windows in
CI (just to make sure that all the `path` logic is correct)
2. We Have to make sure that the glob patterns are always correct even
if you are using `@import` in your CSS and use `@source` in an imported
file. This is because we receive the flattened CSS contents where all
`@import`s are inlined.
3. We have to make sure that we also listen for changes in the files
that match any of these patterns and trigger a rebuild.

PRs:

- [x] https://github.com/tailwindlabs/tailwindcss/pull/14063
- [x] https://github.com/tailwindlabs/tailwindcss/pull/14085
- [x] https://github.com/tailwindlabs/tailwindcss/pull/14079
- [x] https://github.com/tailwindlabs/tailwindcss/pull/14067
- [x] https://github.com/tailwindlabs/tailwindcss/pull/14076
- [x] https://github.com/tailwindlabs/tailwindcss/pull/14080
- [x] https://github.com/tailwindlabs/tailwindcss/pull/14127
- [x] https://github.com/tailwindlabs/tailwindcss/pull/14135

Once all the PRs are merged, then this umbrella PR can be merged. 

> [!IMPORTANT]  
> Make sure to merge this without rebasing such that each individual PR
ends up on the main branch.

---------

Co-authored-by: Philipp Spiess <hello@philippspiess.com>
Co-authored-by: Jordan Pittman <jordan@cryptica.me>
Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2024-08-07 16:38:44 +02:00
Philipp Spiess
266727138c
Upgrade vitest and remove bench script from CI (#14101)
This PR updates vitest to v2. The changes are mostly around using fork
instead of threads for how tests are run which should fix one of the
issues we've found.

Ever since adding the unit tests on Windows, we started seeing
occacional flags of vitest crashing with the following error:

```
 ELIFECYCLE  Command failed with exit code 3221225477.
Error: Process completed with exit code 1.
```

When reading the [v2
changelog](https://github.com/vitest-dev/vitest/releases/tag/v2.0.0) we
saw many bug fixes related to segfaulting so we believe this was the
issue.

When upgrading `vitest` alone, we got a bunch of dependency mismatches
though (specifically, vite was installed two times with different peer
dependencies for `@types/node` which causes our vite plugin's `Plugin`
type to be different from the one in the vite playground. Yikes. These
were eventually fixed by having pnpm create a new lockfile for us. So,
unfortunatly this PR also bumps a bunch of patch versions for some
transitive dependencies. Tests seem fine, though 🤞

This PR also removes the `bench` script from CI. It doesn't give us
value in its current state (since it's not reporting when performance
regresses) but added a few seconds of unnecessary overhead to each test
run.
2024-08-02 10:33:14 +02:00
Adam Wathan
50a6a37dc9
Prepare for v4.0.0-alpha.18 release (#14057)
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-07-25 10:19:13 -04:00
Adam Wathan
54474086c8
Add support for basic addVariant plugins with new @plugin directive (#13982)
* Add basic `addVariant` plugin support

* Return early

* Load plugins right away instead later

* Use correct type for variant name

* Preliminary support for addVariant plugins in PostCSS plugin

* Add test for compounding plugin variants

* Add basic `loadPlugin` support to Vite plugin

* Add basic `loadPlugin` support to CLI

* add `io.ts` for integrations

* use shared `loadPlugin` from `tailwindcss/io`

* add `tailwindcss-test-utils` to `@tailwindcss/cli` and `@tailwindcss/vite`

* only add `tailwindcss-test-utils` to `tailwindcss` as a dev dependency

Because `src/io.ts` is requiring the plugin.

* move `tailwindcss-test-utils` to `@tailwindcss/postcss `

This is the spot where we actually need it.

* use newer pnpm version

* Duplicate loadPlugin implementation instead of exporting io file

* Remove another io reference

* update changelog

---------

Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2024-07-11 09:47:26 -04:00
Robin Malfait
06e96e0767
Prep next release: 4.0.0-alpha.17 (#13951)
* bump to version `4.0.0-alpha.17`

* update changelog
2024-07-04 19:08:10 +02:00
Robin Malfait
c711903af5
Prepare next alpha release: 4.0.0-alpha.16 (#13810)
* bump version to 4.0.0-alpha.16

* update changelog
2024-06-07 18:38:44 +02:00
Robin Malfait
2fedbe0194
Bump dependencies (#13741)
* bump dependencies

* update tests to reflect Lightning CSS change
2024-05-25 14:43:59 +02:00
Robin Malfait
0e92310caf
Bump dependencies (#13738)
* run `pnpm update --recursive`

* update tests to reflect lightningcss bump

It looks like it's mainly (re-)ordering properties. Not 100% sure why
though.
2024-05-24 15:07:44 +02:00
Robin Malfait
5e737d8587
4.0.0-alpha.15 (#13658) 2024-05-08 19:26:59 +02:00
Robin Malfait
ce0a7347da
4.0.0-alpha.14 (#13487) 2024-04-09 20:55:54 +02:00
Robin Malfait
4a25bc1fd5
Ensure deterministic SSR builds in @tailwindcss/vite (#13457)
* ensure we wait in the `build` step as well

It looks like when running `astro build` we only run this `build` step
and not the `dev` step where we already use the `waitForRequestsIdle`
code.

Adding this to the `build` part as well does generate the correct
result.

* update changelog

* fix typo

* add comment

* Don’t run transforms more than necessary

* Don’t remove modules from the graph during SSR

* Update changelog

* Add `preview` script

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2024-04-08 18:10:08 -04:00
Adam Wathan
2719903e56 Update versions for alpha.13 2024-04-04 18:03:36 -04:00
Robin Malfait
34fea0e3d3
4.0.0-alpha.12 (#13448) 2024-04-04 17:43:02 +02:00