diff --git a/src/class.rs b/src/class.rs index 81c9a6f..080c6c2 100644 --- a/src/class.rs +++ b/src/class.rs @@ -21,10 +21,16 @@ pub(crate) struct Class<'a> { #[derive(PartialEq, Debug)] pub(crate) enum ValueType { /// replacements will be performed + /// + /// eg: `m[1rem]` Normal, /// no replacements will be done. value will be output as-is + /// + /// eg: `border{1px solid black}` Literal, /// value will be output as `var(--value)`, without any replacements + /// + /// eg: `c(main-color)` Variable, } @@ -86,7 +92,14 @@ impl<'a> Class<'a> { if let Some(val) = self.value { let val = match self.value_type { ValueType::Normal => { - replace_underscores(z.values.get(val).map(AsRef::as_ref).unwrap_or(val)) + let v = z + .context_aware_values + .get(property) + .and_then(|h| h.get(val)) + .or_else(|| z.values.get(val)) + .map(AsRef::as_ref) + .unwrap_or(val); + replace_underscores(v) } ValueType::Literal => val.into(), ValueType::Variable => format!("var(--{val})").into(), @@ -96,7 +109,7 @@ impl<'a> Class<'a> { let v = fun(&val); Ok(format!("{selector}{{{v}}}",)) } else { - Ok(format!("{selector}{{{property}:{val};}}")) + Ok(format!("{selector}{{{property}:{val}}}")) } } else if let Some(v) = z.declarations.get(property) { Ok(format!("{selector}{{{v}}}")) diff --git a/src/defaults.rs b/src/defaults.rs index abdb91e..e98cd8d 100644 --- a/src/defaults.rs +++ b/src/defaults.rs @@ -2,8 +2,14 @@ use std::collections::HashMap; use crate::SpecialDeclaration; +fn vec_to_hashmap(v: &[(&str, &str)]) -> HashMap { + v.into_iter() + .map(|(a, b)| (a.to_string(), b.to_string())) + .collect::>() +} + pub(crate) fn default_declarations() -> HashMap { - vec![ + vec_to_hashmap(&[ ("flex", "display:flex"), ("flex-row", "display:flex;flex-direction:row"), ("flex-col", "display:flex;flex-direction:column"), @@ -16,14 +22,11 @@ pub(crate) fn default_declarations() -> HashMap { ("text-left", "text-align:left"), ("text-right", "text-align:right"), // TODO - ] - .into_iter() - .map(|(a, b)| (a.to_string(), b.to_string())) - .collect::>() + ]) } pub(crate) fn default_properties() -> HashMap { - vec![ + vec_to_hashmap(&[ ("w", "width"), ("h", "height"), ("m", "margin"), @@ -36,47 +39,89 @@ pub(crate) fn default_properties() -> HashMap { ("pb", "padding-bottom"), ("pl", "padding-left"), ("pr", "padding-right"), + ("c", "color"), ("bg", "background"), ("bgc", "background-color"), + ("tt", "text-transform"), + ("td", "text-decoration"), // TODO - ] - .into_iter() - .map(|(a, b)| (a.to_string(), b.to_string())) - .collect() + ]) } pub(crate) fn default_values() -> HashMap { - vec![ + vec_to_hashmap(&[ ("full", "100%"), // TODO + ]) +} + +pub(crate) fn default_context_aware_values() -> HashMap> { + [ + ( + "text-decoration", + &[ + ("u", "underline"), + ("ud", "underline dotted"), + ("uw", "underline wavy"), + ("o", "overline"), + ("od", "overline dotted"), + ("ow", "overline wavy"), + ] as &[(&str, &str)], + ), + ( + "text-transform", + &[("c", "capitalize"), ("u", "uppercase"), ("l", "lowercase")], + ), + ( + "overflow", + &[ + ("v", "visible"), + ("h", "hidden"), + ("s", "scroll"), + ("c", "clip"), + ], + ), + ( + "overflow-x", + &[ + ("v", "visible"), + ("h", "hidden"), + ("s", "scroll"), + ("c", "clip"), + ], + ), + ( + "overflow-y", + &[ + ("v", "visible"), + ("h", "hidden"), + ("s", "scroll"), + ("c", "clip"), + ], + ), + // TODO ] .into_iter() - .map(|(a, b)| (a.to_string(), b.to_string())) + .map(|(n, h)| (n.to_string(), vec_to_hashmap(h))) .collect() } pub(crate) fn default_modifiers() -> HashMap { - vec![ + vec_to_hashmap(&[ ("odd", "nth-child(odd)"), ("even", "nth-child(even)"), ("first", "first-child"), ("last", "last-child"), ("only", "only-child"), // TODO - ] - .into_iter() - .map(|(a, b)| (a.to_string(), b.to_string())) - .collect() + ]) } pub(crate) fn default_pseudos() -> HashMap { - vec![ + vec_to_hashmap(&[ ("ph", "placeholder"), // TODO - ] - .into_iter() - .map(|(a, b)| (a.to_string(), b.to_string())) - .collect() + ]) } macro_rules! special { @@ -91,11 +136,11 @@ macro_rules! special { } pub(crate) fn default_specials() -> HashMap { - vec![ - 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};"), + [ + 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}"), special!("wh", val, "width:{val};height:{val};"), // TODO ] diff --git a/src/lib.rs b/src/lib.rs index 8f95dc6..857d9b8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,6 +35,10 @@ pub struct Zephyr { pub modifiers: HashMap, /// list of pseudo-element short-hands pub pseudos: HashMap, + /// list of value replacements for each property + /// + /// property -> [(short, expanded)] + pub context_aware_values: HashMap>, } /// value -> declarations @@ -108,6 +112,7 @@ impl Zephyr { modifiers: default_modifiers(), pseudos: default_pseudos(), specials: default_specials(), + context_aware_values: default_context_aware_values(), } } diff --git a/src/tests.rs b/src/tests.rs index c6a035b..c4448ed 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -14,7 +14,7 @@ fn generate_margin_works() { value_type: class::ValueType::Normal, }; 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 { property: "m", @@ -25,7 +25,7 @@ fn generate_margin_works() { value_type: class::ValueType::Normal, }; 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 { property: "m", @@ -38,7 +38,7 @@ fn generate_margin_works() { 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}"# ); } @@ -52,7 +52,7 @@ fn generate_classes_works() { 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"]); @@ -62,7 +62,7 @@ fn generate_classes_works() { ); 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] @@ -73,7 +73,7 @@ fn generate_multiple_works() { 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); } @@ -85,7 +85,7 @@ fn generate_specials_works() { 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}"# ); } @@ -96,7 +96,7 @@ fn generate_with_spaces_works() { let classes = z.generate_classes(["border[1px_solid_black]"]); assert_eq!( classes, - r#".border\[1px_solid_black\]{border:1px solid black;}"# + r#".border\[1px_solid_black\]{border:1px solid black}"# ); } @@ -108,7 +108,7 @@ fn generate_literals_works() { let classes = z.generate_classes(["border{1px_solid_black}", "w{full}"]); assert_eq!( classes, - r#".border\{1px_solid_black\}{border:1px_solid_black;}.w\{full\}{width:full;}"# + r#".border\{1px_solid_black\}{border:1px_solid_black}.w\{full\}{width:full}"# ); } @@ -119,7 +119,7 @@ fn generate_with_media_query() { let classes = z.generate_classes(["m[1rem]sm"]); assert_eq!( classes, - r#"@media(min-width:640px){.m\[1rem\]sm{margin:1rem;}}"# + r#"@media(min-width:640px){.m\[1rem\]sm{margin:1rem}}"# ); } @@ -129,7 +129,7 @@ fn generate_variable() { // the parens indicate that it should be replaced by `var(--...)` let classes = z.generate_classes(["m(my-margin)"]); - assert_eq!(classes, r#".m\(my-margin\){margin:var(--my-margin);}"#); + assert_eq!(classes, r#".m\(my-margin\){margin:var(--my-margin)}"#); } #[test] @@ -142,3 +142,11 @@ fn generate_css_colors() { r#".white{color:white}.blanchedalmond{color:blanchedalmond}"# ); } + +#[test] +fn generate_context_aware_value() { + let z = Zephyr::new(); + + let classes = z.generate_classes(["tt[u]"]); + assert_eq!(classes, r#".tt\[u\]{text-transform:uppercase}"#); +}