Ensure @source globs ending in **/* preserve dynamic path segments to avoid scanning too many files (#20217)
This PR fixes an issue where we were over-scanning because we lost pattern information when a `@source` ended in `**/*` and contained other dynamic parts in the glob pattern. Noticed this while debugging and working on #20214. Let's say you have the following: ```css @source './blog/*/foo/bar/baz/**/*'; ``` We make sure that folders or patterns ending in `**/*` are converted to "auto sources", meaning that auto content detection should be used in these folders. However, when doing so, we would only take the `base` path of the glob. And since we have "dynamic" parts (the `*`) in the pattern, that should not be the case. So the `@source` from above, would be turned into: ```rs SourceEntry::Auto { base = "/Users/projects/project/blog" } ``` Notice that we lose all the information related to `/*/foo/bar/baz/`. While this would technically still work, it also means that we are scanning **too many files and folders** because we're only interested in folders in the `blog` folder that also contain `foo/bar/baz`. If the `*` wasn't there, then this would be correct, because then we would've moved the `/blog/foo/bar/baz` part to the `base` ahead of time, and the pattern would just be `/**/*`. That would result in: ```rs SourceEntry::Auto { base = "/Users/projects/project/blog/foo/bar/baz" } ``` This PR fixes that, by _not_ converting it to an auto-source, and instead convert it to a pattern: ```rs SourceEntry::Pattern { base: "/Users/projects/project/blog", pattern: "/*/foo/bar/baz/**/*" } ``` Notice that the static part `blog` is still moved to the base path. But the rest stays in the `pattern` part as expected. ## Test plan 1. Added a failing test to make sure this doesn't happen anymore 2. Existing tests pass 3. Tested this on the tailwindcss.com codebase using `@source "../blog/tailwindcss*/**/*";` ```diff diff --git a/./tailwindcss-55526.log b/./tailwindcss-55527.log index ce79c5da..03e97598 100644 --- a/./tailwindcss-55526.log +++ b/./tailwindcss-55527.log @@ -2,50 +2,9 @@ INFO tailwindcss_oxide::scanner: Provided sources: INFO tailwindcss_oxide::scanner: Source: PublicSourceEntry { base: "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/app", pattern: "../blog/tailwindcss*/**/*", negated: false } INFO tailwindcss_oxide::scanner: Source: PublicSourceEntry { base: "/Users/robin/.bun/bin", pattern: "bun", negated: true } INFO tailwindcss_oxide::scanner: Optimized sources: -INFO tailwindcss_oxide::scanner: Source: Auto { base: "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog" } +INFO tailwindcss_oxide::scanner: Source: Pattern { base: "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog", pattern: "/tailwindcss*/**/*" } INFO tailwindcss_oxide::scanner: Source: Ignored { base: "/Users/robin/.bun/bin", pattern: "/bun" } INFO discover_sources: tailwindcss_oxide::scanner: enter -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/2022-05-23-headless-ui-v1-6-tailwind-ui-team-management/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/2022-06-23-tailwind-templates-and-all-access/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/2022-08-17-tailwind-framer-motion-template-and-tailwind-jobs/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/2022-09-09-new-personal-website-heroicons-2-headless-ui-v17/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/2022-12-15-protocol-api-documentation-template/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/2023-04-24-new-changelog-template-and-the-biggest-tailwind-ui-update-ever/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/2023-07-18-tailwind-connect-2023-recap/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/2023-08-07-meet-studio-our-new-agency-template/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/2024-05-24-catalyst-application-layouts/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/2024-05-30-prettier-plugin-collapse-whitespace/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/2024-06-21-headless-ui-v2-1/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/2024-09-12-radiant-a-beautiful-new-marketing-site-template/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/2025-05-14-compass-course-starter-kit/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/automatic-class-sorting-with-prettier/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/building-react-and-vue-support-for-tailwind-ui/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/building-the-tailwind-blog/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/designing-tailwind-ui-ecommerce/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/from-900-to-1-how-we-hired-robin-malfait/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/headless-ui-unstyled-accessible-ui-components/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/headless-ui-v1-4/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/headless-ui-v1-5/demo.tsx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/headless-ui-v1-5/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/headless-ui-v1/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/headless-ui-v2/examples/HeadlessUIV2Examples.tsx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/headless-ui-v2/examples/StateAttributesExample.tsx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/headless-ui-v2/examples/anchor-positioning.tsx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/headless-ui-v2/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/heroicons-micro/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/heroicons-v1/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/hiring-a-design-engineer-and-staff-engineer/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/introducing-catalyst/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/introducing-heroicons/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/introducing-linting-for-tailwindcss-intellisense/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/introducing-tailwind-play/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/just-in-time-the-next-generation-of-tailwind-css/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/multi-line-truncation-with-tailwindcss-line-clamp/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/simon-vrachliotis-joins-tailwind-labs/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/standalone-cli/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/tailwind-plus/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/tailwind-ui-ecommerce/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/tailwind-ui-now-with-react-and-vue-support/index.mdx" INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/tailwindcss-1-5/index.mdx" INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/tailwindcss-1-6/index.mdx" INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/tailwindcss-1-7/index.mdx" @@ -68,10 +27,4 @@ INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/t INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/tailwindcss-v4-beta/index.mdx" INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/tailwindcss-v4/color-palette.tsx" INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/tailwindcss-v4/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/utility-friendly-transitions-with-tailwindui-react/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/vanilla-js-support-for-tailwind-plus/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/welcoming-brad-cornes-to-the-tailwind-team/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/welcoming-david-luhr-to-tailwind-labs/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/welcoming-james-mcdonald-to-tailwind-labs/index.mdx" -INFO tailwindcss_oxide::scanner: Reading "/Users/robin/github.com/tailwindlabs/tailwindcss.com/src/blog/whats-new-in-tailwindcss-on-youtube/index.mdx" INFO discover_sources: tailwindcss_oxide::scanner: exit ``` Notice now that a lot of files are skipped as expected since we-re not accidentally over-scanning now. [ci-all]
This commit is contained in:
parent
1bf4291e85
commit
6b0eb5193e
3 changed files with 34 additions and 3 deletions
|
|
@ -32,6 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Upgrade: don't migrate empty class rules to invalid `@utility` rules ([#20205](https://github.com/tailwindlabs/tailwindcss/pull/20205))
|
||||
- Ensure transitions between `inset-shadow-none` and other inset shadows work correctly ([#20208](https://github.com/tailwindlabs/tailwindcss/pull/20208))
|
||||
- Ensure explicitly referenced `@source` directories are scanned even when ignored by git ([#20214](https://github.com/tailwindlabs/tailwindcss/pull/20214))
|
||||
- Ensure `@source` globs ending in `**/*` preserve dynamic path segments to avoid scanning too many files ([#20217](https://github.com/tailwindlabs/tailwindcss/pull/20217))
|
||||
|
||||
### Changed
|
||||
|
||||
|
|
|
|||
|
|
@ -512,8 +512,8 @@ impl From<PublicSourceEntry> for SourceEntry {
|
|||
};
|
||||
}
|
||||
|
||||
let auto = value.pattern.ends_with("**/*")
|
||||
|| PathBuf::from(&value.base).join(&value.pattern).is_dir();
|
||||
let auto =
|
||||
value.pattern == "/**/*" || PathBuf::from(&value.base).join(&value.pattern).is_dir();
|
||||
|
||||
if !auto {
|
||||
return SourceEntry::Pattern {
|
||||
|
|
@ -530,7 +530,7 @@ impl From<PublicSourceEntry> for SourceEntry {
|
|||
std::path::MAIN_SEPARATOR
|
||||
)) || value
|
||||
.base
|
||||
.ends_with(&format!("{}{}", std::path::MAIN_SEPARATOR, dir,))
|
||||
.ends_with(&format!("{}{}", std::path::MAIN_SEPARATOR, dir))
|
||||
});
|
||||
|
||||
match inside_ignored_content_dir {
|
||||
|
|
|
|||
|
|
@ -659,6 +659,36 @@ mod scanner {
|
|||
assert_eq!(normalized_sources, vec!["**/*", "*.styl"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_should_preserve_paths_for_sources_ending_in_a_deep_glob() {
|
||||
let ScanResult {
|
||||
candidates,
|
||||
files,
|
||||
globs,
|
||||
normalized_sources,
|
||||
} = scan_with_globs(
|
||||
&[
|
||||
(
|
||||
"blog/2024/foo/bar/baz/index.html",
|
||||
"content-['blog/2024/foo/bar/baz/index.html']",
|
||||
),
|
||||
(
|
||||
"blog/2024/foo/bar/qux/index.html",
|
||||
"content-['blog/2024/foo/bar/qux/index.html']",
|
||||
),
|
||||
],
|
||||
vec!["@source './blog/*/foo/bar/baz/**/*'"],
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
candidates,
|
||||
vec!["content-['blog/2024/foo/bar/baz/index.html']"]
|
||||
);
|
||||
assert_eq!(files, vec!["blog/2024/foo/bar/baz/index.html"]);
|
||||
assert_eq!(globs, vec!["blog/*/foo/bar/baz/**/*"]);
|
||||
assert_eq!(normalized_sources, vec!["blog/*/foo/bar/baz/**/*"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_should_scan_next_dynamic_folders() {
|
||||
let ScanResult {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue