No description
Previously all `@source` directives were compiled into a single file walker: directives became layered gitignore rules, `expand_restricted_patterns` injected `*` / `/*` / `!/dir/` counter-rules to restrict concrete patterns, and a global `filter_entry` re-checked files against every source. Because all rules were global to the one walker, sources contaminated each other: pattern-driven re-includes leaked into auto source results, and auto source bases legitimized files that only a pattern's walk root reached. This caused a family of bugs: - #18870: globs through directories that are ignored from within (Laravel's `storage/` layout) found nothing - a concrete file `@source` pointing behind `node_modules` or a git ignored directory scanned all of its siblings - `@source "./foo/*.html"` on an ignored folder also scanned other extensions in `foo` - external sources (explicitly listed ignored directories) scanned nested `node_modules` Sources are now split over multiple walkers: - One gitignore-aware walker for all auto/external roots. Default rules and `@source not` rules are registered as explicit in-memory gitignores in directive order (later directives win); external roots get a `!/**/*` whitelist plus a re-statement of the default rules so that e.g. nested `node_modules` stay ignored. - One walker per pattern base. The static prefix of a glob is the explicit part: it is used as the walk root and `.gitignore` files above it never apply, even when the base is hidden inside an ignored directory. The wildcard part is not explicit: `.gitignore` files inside the subtree and the default-ignored directories still prune (`@source "./**/*.html"` does not descend into `node_modules` or a git ignored `dist/"; `@source "./dist/**/*.html"` does). Matching files always win over file-level ignores, and globs that don't pin an extension re-apply the default extension rules. A filter closure makes the exact per-file decision, honoring the relative order of `@source not` directives, and `dir_could_contain_matches` keeps the walk pruned to directories that can actually contribute files. The `@source` semantics are now documented as a spec at the top of `scanner/mod.rs` and pinned by eleven new tests (six of which failed on the old implementation). Four unit tests asserting the internals of the removed `expand_restricted_patterns` mechanism were deleted; the user-visible behavior they guarded is covered by the scanner-level tests. |
||
|---|---|---|
| .github | ||
| crates | ||
| integrations | ||
| packages | ||
| patches | ||
| playgrounds | ||
| scripts | ||
| .gitignore | ||
| .prettierignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CHANGELOG.md | ||
| LICENSE | ||
| package.json | ||
| pnpm-lock.yaml | ||
| pnpm-workspace.yaml | ||
| README.md | ||
| rust-toolchain.toml | ||
| turbo.json | ||
| vitest.config.mts | ||
A utility-first CSS framework for rapidly building custom user interfaces.
Documentation
For full documentation, visit tailwindcss.com.
Community
For help, discussion about best practices, or feature ideas:
Discuss Tailwind CSS on GitHub
Contributing
If you're interested in contributing to Tailwind CSS, please read our contributing docs before submitting a pull request.