Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add @source support #14078

Merged
merged 12 commits into from
Aug 7, 2024
Merged

Add @source support #14078

merged 12 commits into from
Aug 7, 2024

Conversation

RobinMalfait
Copy link
Member

@RobinMalfait RobinMalfait commented Jul 29, 2024

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.
  5. Right now we don't support negative globs (starting with a !) yet, that will be available in the near future.

Usage example:

/* ./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 @imports 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:

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.

philipp-spiess added a commit that referenced this pull request Jul 30, 2024
This changes the V4 CI to run on any pull request change (so an opened,
reopened, and updated PR), regardless if the PR is directed into the
`next` branch or not.

This is helpful for testing stacked PRs like:
#14078
@andrefelipeschulle
Copy link

andrefelipeschulle commented Aug 1, 2024

@RobinMalfait Any plans to make it available for testing? Thank you for your incredible work...

@RobinMalfait
Copy link
Member Author

Hey @andrefelipeschulle, this is currently still in development. But I think we should be able to get a next release out by the end of the week 👍

@andrefelipeschulle
Copy link

@RobinMalfait thanks for answering 👍🏻

@philipp-spiess philipp-spiess force-pushed the feat/add-content-support branch 2 times, most recently from 9579da7 to 0f2425d Compare August 5, 2024 11:23
@RobinMalfait RobinMalfait changed the title Add @content support Add @source support Aug 6, 2024
philipp-spiess added a commit that referenced this pull request Aug 7, 2024
This PR just adds two minor errors to guard against invalid `@plugin`
usage similarly to what we do with `@source` in
#14078.
RobinMalfait and others added 9 commits August 7, 2024 16:13
…`@import`ed files (#14063)

We noticed an issue that happened when handling relative file imports in
the `@plugin` and the upcoming `@content` APIs. The problem arises from
relative files that are inside `@import`ed stylesheets. Take, for
example, the following folder structure:

```css
/* src/index.css */
@import "./dir/index.css";
```
```css
/* src/dir/index.css */
@plugin "../../plugin.ts";
```

It's expected that the path is relative to the CSS file that defined it.
However, right now, we use
[`postcss-import`](https://github.com/postcss/postcss-import) to flatten
the CSS file before running the tailwind build step. This causes these
custom-properties to be inlined in a flat file which removes the
information of which file is being referred:

```css
/* src/flat.css */
@plugin "../../plugin.ts"; /* <- This is now pointing to the wrong file */
```

There are generally two approaches that we can do to solve this:

1. **Handle `@import` flattening inside tailwindcss:** While generally
this would give us more freedom and less dependencies, this would
require some work to get all edge cases right. We need to support
layers/conditional imports and also handle all relative urls for
properties like `background-image`.
2. **Rewrite relative paths as a separate postcss visitor:** The
approach this PR takes is instead to implement a custom postcss plugin
that uses the AST to rewrite relative references inside `@plugin` and
`@content`. This has the benefit of requiring little changes to our
existing APIs. The rule is only enabled for relative references inside
`@plugin` and `@content`, so the surface of this rule is very small.

We can use this plugin inside all three current clients:

- `@tailwindcss/postcss` obviously already uses postcss
- `@tailwindcss/cli` also uses postcss to handle `@import` flattening
- `@tailwindcss/vite` allows us to add custom postcss rules via the CSS
pipeline. There are a few cases that we handle with care (e.g. in vite
you can pass a string to the postcss config which is supposed to load
the config from a file).

To validate the changes, we have added both a list of unit test cases to
the plugin itself as well as verified that all three clients are working
as expected:

- `@tailwindcss/postcss` now has an explicit test for this behavior
- `@tailwindcss/cli` and `@tailwindcss/vite` were manually tested by
updating the vite playground. The CLI was run with `--cwd
playgrounds/vite/ -i ./src/app.css -o foo.css`:
<img width="531" alt="Screenshot 2024-07-29 at 11 35 59"
src="https://github.com/user-attachments/assets/78f0acdc-a46c-4c6c-917a-2916417b1001">
This PR fixes the new `postcss-fix-relative-paths` plugin for Windows
paths. The issue was that we mixed Windows-style path separators from
the absolute file paths with the Posix-style separators from globs. This
caused the `dirname` functions to resolve to the wrong files.

To solve this, we now make the difference very clear by calling the
content a `glob`. For globs, we always expect Posix-style path
separators and for the case of making a glob absolute (by prefixing the
directory), we now convert them into Posix-style explicitly.

This PR also fixes an issue where negative rules (e.g. `!./**/*.ts`)
were not properly rewritten.

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
This PR adds `@content` support to `tailwindcss`'s core package. We will
handle the `@content` and call the `onContentPath` function when it's
encountered.

The `@tailwindcss/cli`, `@tailwindcss/vite` and `@tailwindcss/postcss`
packages have to implement the `onContentPath` such that the necessary
globs are scanned and watchers should be setup with this information.

Example usage:

```css
@content "../../packages/my-sibling-package/src/components/*.tsx";
```

If you are in a monorepo setup, then you could point to other packages
if you want. Another common use case is for Laravel projects if you want
to point to Laravel blade files since they won't be covered by Vite's
module graph:

```css
/* ./resources/css/app.css */
@content "../views/*.blade.php"
```

Note: all globs are relative to the current file you are in.
This is a continuation of #14048 where we specifically focus on the
`@tailwindcss/cli`.

This PR optimizes the globs such that we always have a clean `base` and
the `glob` (which is the first dynamic part).

This PR also refactors the CLI such that we can watch files defined by
the `@content` at-rules in the CSS. The `@parcel/watcher` watches from a
base path (not a glob), which means that we have to create a watcher for
each glob's base.

This PR also adds a `scanFiles` to the `scanDir` result, so that we can
verify that a scanned file matches the globs we already know from
`scanDir`.

Co-authored-by: Philipp Spiess <hello@philippspiess.com>
This PR makes sure that when you use `@content`, that these files are
also being watched if you are using Vite.

In Vite we rely on the module graph instead, but sometimes it can be
useful to watch files outside of the module graph. E.g.: A Laravel
project, where you are watching `*.blade.php` files.

---------

Co-authored-by: Philipp Spiess <hello@philippspiess.com>
This PR adds support for `@content` and makes sure that globs are
registered within PostCSS.

From a configuration perspective nothing changes for the end user. It
does however make sure that `@content` can be used and changes in those
globs will be picked up.
This PR renames the `@content` directive to `@source`.
Part of #14078

This PR applies general feedback to the `@sources` umbrella PR.

This PR includes the following changes:
- Used real classes instead of class-like objects.
- Only handle PostCSS imports when `@import` is used.
- Improve some comments
- Improve naming of `GlobEntry` (`glob.glob` -> `glob.pattern`)
- Use `scanFiles` on the `scanDirResult` as-if it's an incremental scan
(under
  the hood we still do a full scan right now).
- Renamed `content_paths` to `sources`

This is a separate PR just so that we can merge the umbrella PR
un-squashed for each sub-PR. This way all the commits here won't show up
in the `next` branch as-is.
CHANGELOG.md Outdated
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Add support for `inline` option when defining `@theme` values ([#14095](https://github.com/tailwindlabs/tailwindcss/pull/14095))
- Add `inert` variant ([#14129](https://github.com/tailwindlabs/tailwindcss/pull/14129))
- Add `@source` support ([#14078](https://github.com/tailwindlabs/tailwindcss/pull/14078), [14063](https://github.com/tailwindlabs/tailwindcss/pull/14063), [14085](https://github.com/tailwindlabs/tailwindcss/pull/14085), [14079](https://github.com/tailwindlabs/tailwindcss/pull/14079), [14067](https://github.com/tailwindlabs/tailwindcss/pull/14067), [14076](https://github.com/tailwindlabs/tailwindcss/pull/14076), [14080](https://github.com/tailwindlabs/tailwindcss/pull/14080), [14127](https://github.com/tailwindlabs/tailwindcss/pull/14127), [14135](https://github.com/tailwindlabs/tailwindcss/pull/14135))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's just reference the umbrella PR here, this looks ridiculous 😄

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haha, just did it because the idea was to merge this umbrella one with a merge commit instead of squashed (so that you see each PR as a separate commit).

But we can squash as well. At the end of the day it's 1 feature (and thousand small sub-features to make things work correctly)

CHANGELOG.md Outdated Show resolved Hide resolved
CHANGELOG.md Outdated Show resolved Hide resolved
@RobinMalfait RobinMalfait merged commit 541d84a into next Aug 7, 2024
2 checks passed
@RobinMalfait RobinMalfait deleted the feat/add-content-support branch August 7, 2024 14:38
philipp-spiess added a commit that referenced this pull request Aug 8, 2024
While working on #14078, there were a couple of debugging techniques
that we were using quite frequently:

- Being able to `cd` into the test setup
- Seeing the stdio and stdout data in real-time (this currently requires
us to mark a test as failing)
- Checking the exact commands that are being run

Since we naturally worked around this quite often, I decided to make
this a first-level API with the introduction of a new `test.debug` flag.
When set, it will:

- Create the test setup in the project dir within a new `.debug` folder
and won't delete it after the run. Having it in an explicit folder
allows us to easily delete it manually when we need to.
- Logs all run commands to the console (`>` for a sync call, `>&` for a
spawned process)
- Logs stdio and stderr to the console in real time.
- Run the test as `.only`

<img width="2267" alt="Screenshot 2024-08-06 at 13 19 49"
src="https://github.com/user-attachments/assets/1b204ac2-feee-489e-9cd8-edf73c0f2abd">

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
philipp-spiess added a commit that referenced this pull request Sep 4, 2024
…uilds (#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](#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](#14078) and [JS
config files](#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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants