diff --git a/src/class.rs b/src/class.rs index b10ac05..f492932 100644 --- a/src/class.rs +++ b/src/class.rs @@ -4,6 +4,8 @@ use crate::Zephyr; pub(crate) struct Class<'a> { pub name: &'a str, pub value: Option<&'a str>, + /// if true, no replacements will be done on `value` + pub value_literal: bool, pub modifiers: Vec<&'a str>, pub pseudo: Option<&'a str>, /// the original unparsed value @@ -61,16 +63,24 @@ impl<'a> Class<'a> { let selector = self.selector(z); if let Some(val) = self.value { - let val = z.values.get(val).map(AsRef::as_ref).unwrap_or(val); + let val = if self.value_literal { + val.to_string() + } else { + z.values + .get(val) + .map(AsRef::as_ref) + .unwrap_or(val) + .replace('_', " ") + }; if let Some(fun) = z.specials.get(name) { - let v = fun(val); - Ok(format!("{selector} {{ {v} }}",)) + let v = fun(&val); + Ok(format!("{selector}{{{v}}}",)) } else { - Ok(format!("{selector} {{ {name}: {val}; }}",)) + Ok(format!("{selector}{{{name}:{val};}}")) } } else if let Some(v) = z.rules.get(name) { - Ok(format!("{selector} {{ {v} }}",)) + Ok(format!("{selector}{{{v}}}")) } else { Err("{name} is not a no-variable rule, and no variables were provided") } diff --git a/src/defaults.rs b/src/defaults.rs index a657808..9890de7 100644 --- a/src/defaults.rs +++ b/src/defaults.rs @@ -4,11 +4,11 @@ use crate::SpecialRule; pub(crate) fn default_rules() -> HashMap { vec![ - ("flex", "display: flex;"), - ("flex-row", "display: flex; flex-direction: row;"), - ("flex-col", "display: flex; flex-direction: column;"), - ("items-center", "align-items: center"), - ("justify-center", "justify-content: center"), + ("flex", "display:flex;"), + ("flex-row", "display:flex;flex-direction:row;"), + ("flex-col", "display:flex;flex-direction:column;"), + ("items-center", "align-items:center"), + ("justify-center", "justify-content:center"), // TODO ] .into_iter() @@ -73,32 +73,23 @@ pub(crate) fn default_pseudos() -> HashMap { .collect() } +macro_rules! special { + ($name:literal, $val:ident, $string:literal) => { + ($name, { + fn fun<'a>($val: &'a str) -> String { + format!($string) + } + Box::new(fun) as SpecialRule + }) + }; +} + pub(crate) fn default_specials() -> HashMap { vec![ - ("mx", { - fn fun<'a>(val: &'a str) -> String { - format!("margin-left: {val}; margin-right: {val};") - } - Box::new(fun) as SpecialRule - }), - ("my", { - fn fun<'a>(val: &'a str) -> String { - format!("margin-top: {val}; margin-bottom: {val};") - } - Box::new(fun) as SpecialRule - }), - ("px", { - fn fun<'a>(val: &'a str) -> String { - format!("padding-left: {val}; padding-right: {val};") - } - Box::new(fun) as SpecialRule - }), - ("py", { - fn fun<'a>(val: &'a str) -> String { - format!("padding-top: {val}; padding-bottom: {val};") - } - Box::new(fun) as SpecialRule - }), + special!("mx", val, "margin-left:{val};margin-right:{val};"), + special!("my", val, "margin-top:{val};margin-bottom:{val};"), + special!("px", val, "padding-left:{val};padding-right:{val};"), + special!("py", val, "padding-top:{val};padding-bottom:{val};"), // TODO ] .into_iter() diff --git a/src/lib.rs b/src/lib.rs index 8f9fe2c..fa835c4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -107,9 +107,10 @@ mod tests { modifiers: vec![].into(), pseudo: None, original: "m[1rem]", + value_literal: false, }; let css = class.generate(&z).unwrap(); - assert_eq!(css, r#".m\[1rem\] { margin: 1rem; }"#); + assert_eq!(css, r#".m\[1rem\]{margin:1rem;}"#); let class = Class { name: "m", @@ -117,9 +118,10 @@ mod tests { modifiers: vec!["focus"].into(), pseudo: None, original: "m[1rem]focus", + value_literal: false, }; let css = class.generate(&z).unwrap(); - assert_eq!(css, r#".m\[1rem\]focus:focus { margin: 1rem; }"#); + assert_eq!(css, r#".m\[1rem\]focus:focus{margin:1rem;}"#); let class = Class { name: "m", @@ -127,11 +129,12 @@ mod tests { modifiers: vec!["focus", "hover", "odd"].into(), pseudo: None, original: "m[1rem]focus,hover,odd", + value_literal: false, }; let css = class.generate(&z).unwrap(); assert_eq!( css, - r#".m\[1rem\]focus,hover,odd:focus:hover:nth-child\(odd\) { margin: 1rem; }"# + r#".m\[1rem\]focus,hover,odd:focus:hover:nth-child\(odd\){margin:1rem;}"# ); } @@ -140,25 +143,22 @@ mod tests { let z = Zephyr::new(); let classes = z.generate_classes(["flex-row"]); - assert_eq!( - classes, - r#".flex-row { display: flex; flex-direction: row; }"# - ); + assert_eq!(classes, r#".flex-row{display:flex;flex-direction:row;}"#); let classes = z.generate_classes(["m[3rem]hover,focus$placeholder"]); assert_eq!( classes, - r#".m\[3rem\]hover,focus\$placeholder:hover:focus::placeholder { margin: 3rem; }"# + r#".m\[3rem\]hover,focus\$placeholder:hover:focus::placeholder{margin:3rem;}"# ); let classes = z.generate_classes(["flex|hover,focus$placeholder"]); assert_eq!( classes, - r#".flex\|hover,focus\$placeholder:hover:focus::placeholder { display: flex; }"# + r#".flex\|hover,focus\$placeholder:hover:focus::placeholder{display:flex;}"# ); let classes = z.generate_classes(["mr[0.5rem]"]); - assert_eq!(classes, r#".mr\[0\.5rem\] { margin-right: 0.5rem; }"#); + assert_eq!(classes, r#".mr\[0\.5rem\]{margin-right:0.5rem;}"#); } #[test] @@ -169,7 +169,7 @@ mod tests { let classes_separate = z.generate_classes(["flex-row", "mt[1rem]"]); assert_eq!( classes_joined, - r#".flex-row { display: flex; flex-direction: row; }.mt\[1rem\] { margin-top: 1rem; }"# + r#".flex-row{display:flex;flex-direction:row;}.mt\[1rem\]{margin-top:1rem;}"# ); assert_eq!(classes_separate, classes_joined); } @@ -181,7 +181,18 @@ mod tests { let classes = z.generate_classes(["mx[1rem]"]); assert_eq!( classes, - r#".mx\[1rem\] { margin-left: 1rem; margin-right: 1rem; }"# + r#".mx\[1rem\]{margin-left:1rem;margin-right:1rem;}"# + ); + } + + #[test] + fn generate_with_spaces_works() { + let z = Zephyr::new(); + + let classes = z.generate_classes(["border[1px_solid_black]"]); + assert_eq!( + classes, + r#".border\[1px_solid_black\]{border:1px solid black;}"# ); } } diff --git a/src/parse.rs b/src/parse.rs index 6a76093..9282aba 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -20,6 +20,7 @@ pub(crate) fn parse_class<'a>(original: &'a str) -> Option> { modifiers: mods.into(), pseudo, original, + value_literal: false, }); } @@ -37,6 +38,7 @@ pub(crate) fn parse_class<'a>(original: &'a str) -> Option> { modifiers: mods.into(), pseudo, original, + value_literal: false, }); } _ => { @@ -46,6 +48,7 @@ pub(crate) fn parse_class<'a>(original: &'a str) -> Option> { modifiers: vec![].into(), pseudo, original, + value_literal: false, }); } } @@ -70,7 +73,8 @@ mod tests { value, modifiers: modifiers.into(), pseudo, - original: class + original: class, + value_literal: false, }) ); }