Ensure earlier `@source` is not accidentally ignored by later `@source` by RobinMalfait · Pull Request #20335 · tailwindlabs/tailwindcss · GitHub
Skip to content

Ensure earlier @source is not accidentally ignored by later @source - #20335

Merged
RobinMalfait merged 3 commits into
mainfrom
fix/issue-20333
Jul 15, 2026
Merged

RobinMalfait merged 3 commits into
mainfrom
fix/issue-20333

Conversation

@RobinMalfait

@RobinMalfait RobinMalfait commented Jul 15, 2026 •

Copy link
Copy Markdown
Contributor

This PR fixes an issue where an @source pointing to a file in a nested folder was not scanned when a later @source pointed to a file in a parent folder.

E.g.:

@source "./nested/index.html";
@source "./index.html";

When using @source pointing to a specific file, then we want to make sure that we ignore other files since they are not listed explicitly. To ensure that these patterns don't read other files, we inject a * ignore pattern before it. You can think of the above being expanded to:

Ignored { base: "/project/src/nested", pattern: "*" }
Pattern { base: "/project/src/nested", pattern: "/index.html" }
Ignored { base: "/project/src", pattern: "*" }
Pattern { base: "/project/src", pattern: "/index.html" }

The problem with this is that the Ignored { base: "/project/src", pattern: "*" } pattern results in ignoring the nested folder as well. This means that we never even walk into the nested folder, so the earlier @source "./nested/index.html" never matches anything.

We could switch the order in user land, but that's going to be hard to maintain (and order matters for undoing/redoing earlier rules, so we can't re-order internally either). Instead, we can scope the ignore pattern to the current path only, and not deeply nested. In other words, the pattern should become:

- *
+ /*

It's a very subtle difference, but the pattern from above will now become:

  Ignored { base: "/project/src/nested", pattern: "*" }
  Pattern { base: "/project/src/nested", pattern: "/index.html" }
- Ignored { base: "/project/src", pattern: "*" }
+ Ignored { base: "/project/src", pattern: "/*" }
  Pattern { base: "/project/src", pattern: "/index.html" }

We already do this when an unrestricted root (e.g. @source "./nested") lives inside the base of a restricted pattern. This works because every source base is also its own walk root, and a /* pattern only matches direct children so it can't ignore anything when walking from the nested root itself.

This PR extends that same check to restricted pattern bases: if another @source pattern has its base nested inside the current base, we emit /* instead of *.

Note that we only relax the pattern to /* when such a nested root actually exists. Sibling folders that no @source points into (e.g. an ignore-me folder next to nested) are still direct children, so they still match /* and are never walked.

Fixes: #20333

Test plan

  1. Added a regression test with the reproduction setup
  2. Added a similar test with another sibling folder that should still be ignored
  3. Tested it against the actual reproduction:

Before:
image

After:
image

Notice that the text-green-500 now appears as expected.

When using `@source` pointing to a specific file, then we want to make
sure that we ignore _other_ files since they are not listed explicitly.

E.g.:
```css
@source "./nested/index.html";
@source "./index.html";
```

To ensure that these patterns don't read other files, we inject a `*`
ignore pattern before it. You can think of this being expanded to:
```rs
Ignored { base: "/project/src/nested", pattern: "*" }
Pattern { base: "/project/src/nested", pattern: "/index.html" }
Ignored { base: "/project/src", pattern: "*" }
Pattern { base: "/project/src", pattern: "/index.html" }
```

The problem with this is that the `Ignored { base: "/project/src", pattern: "*" }` pattern
results in ignoring the `nested` folder as well.

We could switch the order in user land, but that's going to be hard to
maintain. Instead we should scope the ignore pattern to the _current_
path only, and not deeply nested. In other words, the pattern should
become:

```diff
- *
+ /*
```
@RobinMalfait
RobinMalfait requested a review from a team as a code owner July 15, 2026 11:23
@coderabbitai

coderabbitai Bot commented Jul 15, 2026 •

Copy link
Copy Markdown
Contributor

@greptile-apps

greptile-apps Bot commented Jul 15, 2026 •

Copy link
Copy Markdown
Contributor

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.

Root-level concrete @source hides nested concrete sources with source(none) in v4.3.2

1 participant