Skip to content

Commit

Permalink
Merge pull request #16 from gaucho-labs/fixes
Browse files Browse the repository at this point in the history
Collision Fixes
  • Loading branch information
nicoburniske committed Mar 30, 2024
2 parents 0b0fee9 + c8e8293 commit aeb2773
Show file tree
Hide file tree
Showing 6 changed files with 189 additions and 30 deletions.
29 changes: 11 additions & 18 deletions fuse/src/core/merge/get_collision_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,9 @@ pub fn get_collision_id(classes: &[&str], arbitrary: &str) -> Result<&'static st
["stroke"] if is_valid_length(arbitrary) => Ok("stroke-width"),

// https://tailwindcss.com/docs/stroke
["stroke", ..] => Ok("stroke"),
["stroke", ..]=> {
Ok("stroke")
},

// https://tailwindcss.com/docs/screen-readers
["sr", "only"] | ["not", "sr", "only"] => Ok("screen-readers"),
Expand Down Expand Up @@ -798,7 +800,7 @@ fn valid_top_right_bottom_left(mode: &str) -> bool {
mode == "auto"
|| mode == "full"
|| mode == "px"
|| parse_single_digit_decimal(mode).is_some()
|| validators::parse_single_digit_decimal(mode)
|| parse_fraction(mode).is_some()
}

Expand All @@ -809,30 +811,21 @@ fn valid_break_after(mode: &str) -> bool {
)
}

// Need starts_with for this https://tailwindcss.com/docs/font-size#setting-the-line-height
fn valid_text_size(mode: &str) -> bool {
mode == "base"
|| mode.starts_with("xs")
|| mode.ends_with("xs")
|| mode.starts_with("sm")
|| mode.ends_with("sm")
|| mode.starts_with("md")
|| mode.ends_with("md")
|| mode.starts_with("lg")
|| mode.ends_with("lg")
|| mode.starts_with("xl")
|| mode.ends_with("xl")
}

// parses 1.5 but not 1.55
fn parse_single_digit_decimal(input: &str) -> Option<()> {
if input.len() == 1 {
let _ = input.parse::<usize>().ok()?;
Some(())
} else if input.len() == 3 {
let (l, r) = input.split_once('.')?;
let _ = l.parse::<usize>().ok()?;
let _ = r.parse::<usize>().ok()?;
Some(())
} else {
None
}
}

fn parse_fraction_or_usize(input: &str) -> bool {
parse_fraction(input)
.map(|_| ())
Expand Down Expand Up @@ -909,8 +902,8 @@ mod test {
assert!(is_valid_length("10%"));
assert!(is_valid_length("100rem"));

assert!(!is_valid_length("10"), "needs unit");
assert!(!is_valid_length("hsl(350_80%_0%)"), "no color");
assert!(!is_valid_length("--my-0"), "double negative");
}

#[test]
Expand Down
2 changes: 1 addition & 1 deletion fuse/src/core/merge/get_collisions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub(crate) fn get_collisions(collision_id: &str) -> Option<Vec<&'static str>> {
"margin-x" => Some(vec!["margin-right", "margin-left"]),
"margin-y" => Some(vec!["margin-top", "margin-bottom"]),
"size" => Some(vec!["width", "height"]),
"font-size" => Some(vec!["leading"]),
"font-size" => Some(vec!["line-height"]),
"fvn-normal" => Some(vec![
"fvn-ordinal",
"fvn-slashed-zero",
Expand Down
58 changes: 50 additions & 8 deletions fuse/src/core/merge/merge_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,19 @@ pub fn tw_merge_with_override(
});

match result {
Err(error) => {
#[cfg(debug)]
println!("No Instance found: {style:?} {error:?}");
let _ = error;
valid_styles.push(Ok(style));
}
Err(error) => match Collision::check_arbitrary(style.clone()) {
Some(collision) => {
if collision_styles.contains(&collision) {
continue;
}
collision_styles.insert(collision);
}
None => {
#[cfg(debug)]
println!("No Instance found: {style:?} {error:?}");
let _ = error;
}
},
Ok(collision_id) => {
// hover:md:focus
let all_variants: Vec<&str> = style.variants.clone();
Expand Down Expand Up @@ -75,10 +82,9 @@ pub fn tw_merge_with_override(
collision_styles.insert(collision);
});
}

valid_styles.push(Ok(style));
}
}
valid_styles.push(Ok(style));
}

valid_styles.reverse();
Expand All @@ -99,3 +105,39 @@ struct Collision<'a> {
variants: Vec<&'a str>,
collision_id: &'a str,
}

// For [color:blue] => label = "color"
impl<'a> Collision<'a> {
fn check_arbitrary(style: AstStyle<'a>) -> Option<Self> {
let arbitrary = style.arbitrary?;
if arbitrary.contains(':') {
let mut parts = arbitrary.split(':');
let collision_id = parts.next()?;
Some(Self {
collision_id,
important: style.important,
variants: style.variants,
})
} else {
None
}
}
}

#[test]
fn check_arbitrary() {
let style = crate::ast::parse_tailwind(&["[color:blue]"], Default::default())
.into_iter()
.next()
.unwrap()
.unwrap();

assert_eq!(
Collision::check_arbitrary(style),
Some(Collision {
important: false,
variants: vec![],
collision_id: "color"
})
);
}
73 changes: 70 additions & 3 deletions fuse/src/core/merge/validators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,17 @@ pub mod length {
use super::*;

pub fn parse(input: &str) -> IResult<&str, &str> {
alt((tag("0"), number, unit, functional_notation))(input)
alt((tag("0"), number, functional_notation))(input)
}

// Parser for numeric values
fn number(input: &str) -> IResult<&str, &str> {
recognize(pair(
take_while1(|c: char| c.is_ascii_digit() || c == '.' || c == '-'),
unit,
pair(
opt(char('-')),
take_while1(|c: char| c.is_ascii_digit() || c == '.'),
),
opt(unit),
))(input)
}

Expand Down Expand Up @@ -74,6 +77,14 @@ pub mod length {
let (_, result) = parse(input).unwrap();
assert_eq!(result, "theme(fontSize.4xl)/1.125");
}

#[test]
fn num_len() {
let input = "1";
assert!('1'.is_ascii_digit());
let result = number(input).unwrap();
assert_eq!(result, ("", "1"));
}
}

pub mod arbitrary {
Expand Down Expand Up @@ -173,3 +184,59 @@ pub mod image {
take_while1(|c: char| c != ')')(input)
}
}

pub fn parse_single_digit_decimal(input: &str) -> bool {
if input.is_empty() {
return false;
}

let mut dot_index = None;
for (i, c) in input.char_indices() {
if c == '.' {
if dot_index.is_some() || i == 0 || i == input.len() - 1 || input.len() - i != 2 {
return false;
}
dot_index = Some(i);
} else if !c.is_ascii_digit() {
return false;
}
}

true
}

#[test]
fn test_valid_single_digit_decimal() {
assert!(parse_single_digit_decimal("1.5"));
assert!(parse_single_digit_decimal("11.5"));
assert!(parse_single_digit_decimal("0.0"));
assert!(parse_single_digit_decimal("9.9"));
assert!(parse_single_digit_decimal("123"));
assert!(parse_single_digit_decimal("0"));
assert!(parse_single_digit_decimal("1"));
assert!(parse_single_digit_decimal("12345"));
assert!(parse_single_digit_decimal("9.0"));
assert!(parse_single_digit_decimal("0.9"));
}

#[test]
fn test_invalid_single_digit_decimal() {
assert!(!parse_single_digit_decimal(""));
assert!(!parse_single_digit_decimal("1.55"));
assert!(!parse_single_digit_decimal("11.55"));
assert!(!parse_single_digit_decimal("1."));
assert!(!parse_single_digit_decimal(".5"));
assert!(!parse_single_digit_decimal("1.5.5"));
assert!(!parse_single_digit_decimal("a.5"));
assert!(!parse_single_digit_decimal("1.a"));
assert!(!parse_single_digit_decimal("1 .5"));
assert!(!parse_single_digit_decimal("1. 5"));
assert!(!parse_single_digit_decimal("-1.5"));
assert!(!parse_single_digit_decimal("+1.5"));
assert!(!parse_single_digit_decimal("1.5e3"));
assert!(!parse_single_digit_decimal("1.5E3"));
assert!(!parse_single_digit_decimal("1.5f"));
assert!(!parse_single_digit_decimal("1.5d"));
assert!(!parse_single_digit_decimal("1,5"));
assert!(!parse_single_digit_decimal("1..5"));
}
31 changes: 31 additions & 0 deletions fuse/tests/group-conflicts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,3 +179,34 @@ fn line_clamp_classes_do_create_conflicts_correctly() {
"line-clamp-1 overflow-auto inline"
);
}

#[test]
fn test_line_height_font_size() {
assert_eq!(tw_merge("leading-9 text-lg"), "text-lg");
}

#[test]
fn text_color_font_size() {
assert_eq!(tw_merge("text-red-500 text-lg"), "text-red-500 text-lg");

// https://tailwindcss.com/docs/font-size#setting-the-line-height
assert_eq!(
tw_merge("text-red-500/10 text-lg/9"),
"text-red-500/10 text-lg/9"
);
}

#[test]
fn stroke_width() {
assert_eq!(tw_merge("stroke-2 stroke-[3]"), "stroke-[3]");
}

#[test]
fn handles_negative_value_conflicts_correctly() {
assert_eq!(tw_merge("-top-12 -top-2000"), "-top-2000");
}

#[test]
fn tailwind_3_4() {
assert_eq!(tw_merge("text-red text-lg/8"), "text-red text-lg/8");
}
26 changes: 26 additions & 0 deletions fuse/tests/merge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,3 +436,29 @@ fn columns() {
let result = tw_merge(class);
assert_eq!(result, "columns-[2rem]");
}

#[test]
fn arbitrary_property_conflicts() {
let class = "[&>*]:[color:red] [&>*]:[color:blue]";
let result = tw_merge(class);
assert_eq!(result, "[&>*]:[color:blue]");

let class = "![some:prop] [some:other] [some:one] ![some:another]";
let result = tw_merge(class);
assert_eq!(result, "[some:one] ![some:another]");

let class = "hover:[paint-order:markers] hover:[paint-order:normal]";
let result = tw_merge(class);
assert_eq!(result, "hover:[paint-order:normal]");
}

#[test]
fn test_negative_values() {
let class = "top-12 -top-69";
let result = tw_merge(class);
assert_eq!(result, "-top-69");

let class = "-top-12 -top-2000";
let result = tw_merge(class);
assert_eq!(result, "-top-2000");
}

0 comments on commit aeb2773

Please sign in to comment.