From f3e78807afd78c2673d86018c2138095b54c6ecb Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Mon, 18 Mar 2024 23:24:22 +0100 Subject: [PATCH] Parse candidates in `.svelte` files with `class:abc="condition"` syntax (#13274) * handle `.svelte` file In svelte there is a convention where you can use `
` which means that we extract `class:px-4` as a utility where `class` is a variant. This is obviously incorrect, to solve this we can ignore the `class:` part before parsing the whole file. This is also what we do in v3. Ideally we have completely separate parsers for various programming languages (based on file type) and fallback to the generic one we have now. Implementing that, is a much bigger scope. * flatten match arms * add test to verify we can parse `class:px-4="condition"` * explicitly ingore everything but the svelte file * merge tests There is some funky stuff happening when running `cargo test` where it sees contents from another test. Maybe a bug in the tmpdir crate. I don't see this problem locally when running `cargo nextest run`, but when using the native `cargo test` command it fails. * update changelog * run prettier * Update oxide/crates/core/src/lib.rs Co-authored-by: Jordan Pittman * fixup syntax errors --------- Co-authored-by: Jordan Pittman --- CHANGELOG.md | 1 + oxide/crates/core/src/lib.rs | 45 ++++++++++++++++--------- oxide/crates/core/tests/auto_content.rs | 7 +++- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 89d86a5f3..a7b672126 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Validate bare values ([#13245](https://github.com/tailwindlabs/tailwindcss/pull/13245)) +- Parse candidates in `.svelte` files with `class:abc="condition"` syntax ([#13274](https://github.com/tailwindlabs/tailwindcss/pull/13274)) ### Changed diff --git a/oxide/crates/core/src/lib.rs b/oxide/crates/core/src/lib.rs index 6f04adae0..ae49d0c91 100644 --- a/oxide/crates/core/src/lib.rs +++ b/oxide/crates/core/src/lib.rs @@ -1,4 +1,5 @@ use crate::parser::Extractor; +use bstr::ByteSlice; use cache::Cache; use fxhash::FxHashSet; use ignore::DirEntry; @@ -399,6 +400,32 @@ pub fn scan_files(input: Vec, options: u8) -> Vec { } } +fn read_changed_content(c: ChangedContent) -> Option> { + if let Some(content) = c.content { + return Some(content.into_bytes()); + } + + let Some(file) = c.file else { + return Default::default(); + }; + + let Ok(content) = std::fs::read(&file).map_err(|e| { + event!(tracing::Level::ERROR, "Failed to read file: {:?}", e); + e + }) else { + return Default::default(); + }; + + let Some(extension) = file.extension().map(|x| x.to_str()) else { + return Some(content); + }; + + match extension { + Some("svelte") => Some(content.replace(" class:", " ")), + _ => Some(content), + } +} + #[tracing::instrument(skip(changed_content))] fn read_all_files(changed_content: Vec) -> Vec> { event!( @@ -409,17 +436,7 @@ fn read_all_files(changed_content: Vec) -> Vec> { changed_content .into_par_iter() - .map(|c| match (c.file, c.content) { - (Some(file), None) => match std::fs::read(file) { - Ok(content) => content, - Err(e) => { - event!(tracing::Level::ERROR, "Failed to read file: {:?}", e); - Default::default() - } - }, - (None, Some(content)) => content.into_bytes(), - _ => Default::default(), - }) + .filter_map(read_changed_content) .collect() } @@ -433,11 +450,7 @@ fn read_all_files_sync(changed_content: Vec) -> Vec> { changed_content .into_iter() - .filter_map(|c| match (c.file, c.content) { - (Some(file), None) => std::fs::read(file).ok(), - (None, Some(content)) => Some(content.into_bytes()), - _ => Default::default(), - }) + .filter_map(read_changed_content) .collect() } diff --git a/oxide/crates/core/tests/auto_content.rs b/oxide/crates/core/tests/auto_content.rs index 6c0217079..030755373 100644 --- a/oxide/crates/core/tests/auto_content.rs +++ b/oxide/crates/core/tests/auto_content.rs @@ -297,9 +297,14 @@ mod auto_content { ("foo.jpg", Some("xl:font-bold")), // A file that is ignored ("foo.html", Some("lg:font-bold")), + // A svelte file with `class:foo="bar"` syntax + ("index.svelte", Some("
")), ]) .1; - assert_eq!(candidates, vec!["font-bold", "md:flex"]); + assert_eq!( + candidates, + vec!["condition", "div", "font-bold", "md:flex", "px-4"] + ); } }