merge globs and detectSources

Now that we can promote `@source "../path/to/folder"` to enable auto
source detection, it means that we can just merge the globs together and
add the base folder as if it was `@source "../path/to/folder"`
This commit is contained in:
Robin Malfait 2024-10-25 16:19:39 +02:00 • committed by Jordan Pittman
parent 4a8718c025
commit 0f73bb7d2e
4 changed files with 41 additions and 72 deletions

View file

@ -18,13 +18,6 @@ pub struct ChangedContent {
pub extension: String,
}
#[derive(Debug, Clone)]
#[napi(object)]
pub struct DetectSources {
/// Base path to start scanning from
pub base: String,
}
#[derive(Debug, Clone)]
#[napi(object)]
pub struct GlobEntry {
@ -62,20 +55,11 @@ impl From<tailwindcss_oxide::GlobEntry> for GlobEntry {
}
}
impl From<DetectSources> for tailwindcss_oxide::scanner::detect_sources::DetectSources {
fn from(detect_sources: DetectSources) -> Self {
Self::new(detect_sources.base.into())
}
}
// ---
#[derive(Debug, Clone)]
#[napi(object)]
pub struct ScannerOptions {
/// Automatically detect sources in the base path
pub detect_sources: Option<DetectSources>,
/// Glob sources
pub sources: Option<Vec<GlobEntry>>,
}
@ -102,7 +86,6 @@ impl Scanner {
pub fn new(opts: ScannerOptions) -> Self {
Self {
scanner: tailwindcss_oxide::Scanner::new(
opts.detect_sources.map(Into::into),
opts
.sources
.map(|x| x.into_iter().map(Into::into).collect()),

View file

@ -62,9 +62,6 @@ pub struct GlobEntry {
#[derive(Debug, Clone, Default)]
pub struct Scanner {
/// Auto content configuration
detect_sources: Option<DetectSources>,
/// Glob sources
sources: Option<Vec<GlobEntry>>,
@ -86,9 +83,8 @@ pub struct Scanner {
}
impl Scanner {
pub fn new(detect_sources: Option<DetectSources>, sources: Option<Vec<GlobEntry>>) -> Self {
pub fn new(sources: Option<Vec<GlobEntry>>) -> Self {
Self {
detect_sources,
sources,
..Default::default()
}
@ -206,51 +202,11 @@ impl Scanner {
return;
}
self.detect_sources();
self.scan_sources();
self.ready = true;
}
#[tracing::instrument(skip_all)]
fn detect_sources(&mut self) {
if let Some(detect_sources) = &self.detect_sources {
let (files, globs) = detect_sources.detect();
self.files.extend(files);
self.globs.extend(globs);
}
// Find all `@source` globs that point to a directory. If so, promote the source to auto
// source detection instead.
if let Some(sources) = &mut self.sources {
for source in sources {
// If a glob ends with `**/*`, then we just want to register the base path as a new
// base.
if source.pattern.ends_with("**/*") {
source.pattern = source.pattern.trim_end_matches("**/*").to_owned();
}
let path = PathBuf::from(&source.base).join(&source.pattern);
let Some(folder_name) = path.file_name() else {
continue;
};
// Contains a file extension, e.g.: `foo.html`, therefore we don't want to
// detect sources here.
if folder_name.to_str().unwrap().contains(".") {
continue;
}
// Promote to auto source detection
let detect_sources = DetectSources::new(path.clone());
let (files, globs) = detect_sources.detect();
self.files.extend(files);
self.globs.extend(globs);
}
}
}
#[tracing::instrument(skip_all)]
fn scan_sources(&mut self) {
let Some(sources) = &self.sources else {
@ -261,7 +217,38 @@ impl Scanner {
return;
}
let resolved_files: Vec<_> = match fast_glob(sources) {
// Partition sources into sources that should be promoted to auto source detection and
// sources that should be resolved as globs.
let (auto_sources, glob_sources): (Vec<_>, Vec<_>) = sources.iter().partition(|source| {
// If a glob ends with `/**/*`, then we just want to register the base path as a new
// base. Essentially converting it to use auto source detection.
if source.pattern.ends_with("**/*") {
return true;
}
// Directories should be promoted to auto source detection
if PathBuf::from(&source.base).join(&source.pattern).is_dir() {
return true;
}
false
});
// Turn `Vec<&GlobEntry>` in `Vec<GlobEntry>`
let glob_sources: Vec<_> = glob_sources.into_iter().cloned().collect();
for path in auto_sources
.iter()
.map(|source| PathBuf::from(&source.base).join(source.pattern.trim_end_matches("**/*")))
{
let detect_sources = DetectSources::new(path);
let (files, globs) = detect_sources.detect();
self.files.extend(files);
self.globs.extend(globs);
}
let resolved_files: Vec<_> = match fast_glob(&glob_sources) {
Ok(matches) => matches
.filter_map(|x| dunce::canonicalize(&x).ok())
.collect(),
@ -272,7 +259,7 @@ impl Scanner {
};
self.files.extend(resolved_files);
self.globs.extend(sources.clone());
self.globs.extend(glob_sources);
// Re-optimize the globs to reduce the number of patterns we have to scan.
self.globs = get_fast_patterns(&self.globs)

View file

@ -138,22 +138,22 @@ export async function handle(args: Result<ReturnType<typeof options>>) {
},
})
let detectSources = (() => {
let sources = (() => {
// Disable auto source detection
if (compiler.root === 'none') {
return undefined
return []
}
// No root specified, use the base directory
if (compiler.root === null) {
return { base }
return [{ base, pattern: '**/*' }]
}
// Use the specified root
return { base: path.resolve(compiler.root.base, compiler.root.pattern) }
})()
return [{ base: path.resolve(compiler.root.base, compiler.root.pattern), pattern: '**/*' }]
})().concat(compiler.globs)
let scanner = new Scanner({ detectSources, sources: compiler.globs })
let scanner = new Scanner({ sources })
env.DEBUG && console.timeEnd('[@tailwindcss/cli] Setup compiler')
return [compiler, scanner] as const

View file

@ -136,8 +136,7 @@ function tailwindcss(opts: PluginOptions = {}): AcceptedPlugin {
if (context.scanner === null || rebuildStrategy === 'full') {
// Look for candidates used to generate the CSS
context.scanner = new Scanner({
detectSources: { base },
sources: context.compiler.globs,
sources: [{ base, pattern: '**/*' }].concat(context.compiler.globs),
})
}