context aware values
This commit is contained in:
parent
d985d71fa4
commit
871fce954d
17
src/class.rs
17
src/class.rs
|
@ -21,10 +21,16 @@ pub(crate) struct Class<'a> {
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug)]
|
||||||
pub(crate) enum ValueType {
|
pub(crate) enum ValueType {
|
||||||
/// replacements will be performed
|
/// replacements will be performed
|
||||||
|
///
|
||||||
|
/// eg: `m[1rem]`
|
||||||
Normal,
|
Normal,
|
||||||
/// no replacements will be done. value will be output as-is
|
/// no replacements will be done. value will be output as-is
|
||||||
|
///
|
||||||
|
/// eg: `border{1px solid black}`
|
||||||
Literal,
|
Literal,
|
||||||
/// value will be output as `var(--value)`, without any replacements
|
/// value will be output as `var(--value)`, without any replacements
|
||||||
|
///
|
||||||
|
/// eg: `c(main-color)`
|
||||||
Variable,
|
Variable,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +92,14 @@ impl<'a> Class<'a> {
|
||||||
if let Some(val) = self.value {
|
if let Some(val) = self.value {
|
||||||
let val = match self.value_type {
|
let val = match self.value_type {
|
||||||
ValueType::Normal => {
|
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::Literal => val.into(),
|
||||||
ValueType::Variable => format!("var(--{val})").into(),
|
ValueType::Variable => format!("var(--{val})").into(),
|
||||||
|
@ -96,7 +109,7 @@ impl<'a> Class<'a> {
|
||||||
let v = fun(&val);
|
let v = fun(&val);
|
||||||
Ok(format!("{selector}{{{v}}}",))
|
Ok(format!("{selector}{{{v}}}",))
|
||||||
} else {
|
} else {
|
||||||
Ok(format!("{selector}{{{property}:{val};}}"))
|
Ok(format!("{selector}{{{property}:{val}}}"))
|
||||||
}
|
}
|
||||||
} else if let Some(v) = z.declarations.get(property) {
|
} else if let Some(v) = z.declarations.get(property) {
|
||||||
Ok(format!("{selector}{{{v}}}"))
|
Ok(format!("{selector}{{{v}}}"))
|
||||||
|
|
|
@ -2,8 +2,14 @@ use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::SpecialDeclaration;
|
use crate::SpecialDeclaration;
|
||||||
|
|
||||||
|
fn vec_to_hashmap(v: &[(&str, &str)]) -> HashMap<String, String> {
|
||||||
|
v.into_iter()
|
||||||
|
.map(|(a, b)| (a.to_string(), b.to_string()))
|
||||||
|
.collect::<HashMap<_, _>>()
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn default_declarations() -> HashMap<String, String> {
|
pub(crate) fn default_declarations() -> HashMap<String, String> {
|
||||||
vec![
|
vec_to_hashmap(&[
|
||||||
("flex", "display:flex"),
|
("flex", "display:flex"),
|
||||||
("flex-row", "display:flex;flex-direction:row"),
|
("flex-row", "display:flex;flex-direction:row"),
|
||||||
("flex-col", "display:flex;flex-direction:column"),
|
("flex-col", "display:flex;flex-direction:column"),
|
||||||
|
@ -16,14 +22,11 @@ pub(crate) fn default_declarations() -> HashMap<String, String> {
|
||||||
("text-left", "text-align:left"),
|
("text-left", "text-align:left"),
|
||||||
("text-right", "text-align:right"),
|
("text-right", "text-align:right"),
|
||||||
// TODO
|
// TODO
|
||||||
]
|
])
|
||||||
.into_iter()
|
|
||||||
.map(|(a, b)| (a.to_string(), b.to_string()))
|
|
||||||
.collect::<HashMap<_, _>>()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn default_properties() -> HashMap<String, String> {
|
pub(crate) fn default_properties() -> HashMap<String, String> {
|
||||||
vec![
|
vec_to_hashmap(&[
|
||||||
("w", "width"),
|
("w", "width"),
|
||||||
("h", "height"),
|
("h", "height"),
|
||||||
("m", "margin"),
|
("m", "margin"),
|
||||||
|
@ -36,47 +39,89 @@ pub(crate) fn default_properties() -> HashMap<String, String> {
|
||||||
("pb", "padding-bottom"),
|
("pb", "padding-bottom"),
|
||||||
("pl", "padding-left"),
|
("pl", "padding-left"),
|
||||||
("pr", "padding-right"),
|
("pr", "padding-right"),
|
||||||
|
("c", "color"),
|
||||||
("bg", "background"),
|
("bg", "background"),
|
||||||
("bgc", "background-color"),
|
("bgc", "background-color"),
|
||||||
|
("tt", "text-transform"),
|
||||||
|
("td", "text-decoration"),
|
||||||
// TODO
|
// TODO
|
||||||
]
|
])
|
||||||
.into_iter()
|
|
||||||
.map(|(a, b)| (a.to_string(), b.to_string()))
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn default_values() -> HashMap<String, String> {
|
pub(crate) fn default_values() -> HashMap<String, String> {
|
||||||
vec![
|
vec_to_hashmap(&[
|
||||||
("full", "100%"),
|
("full", "100%"),
|
||||||
// TODO
|
// TODO
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn default_context_aware_values() -> HashMap<String, HashMap<String, String>> {
|
||||||
|
[
|
||||||
|
(
|
||||||
|
"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()
|
.into_iter()
|
||||||
.map(|(a, b)| (a.to_string(), b.to_string()))
|
.map(|(n, h)| (n.to_string(), vec_to_hashmap(h)))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn default_modifiers() -> HashMap<String, String> {
|
pub(crate) fn default_modifiers() -> HashMap<String, String> {
|
||||||
vec![
|
vec_to_hashmap(&[
|
||||||
("odd", "nth-child(odd)"),
|
("odd", "nth-child(odd)"),
|
||||||
("even", "nth-child(even)"),
|
("even", "nth-child(even)"),
|
||||||
("first", "first-child"),
|
("first", "first-child"),
|
||||||
("last", "last-child"),
|
("last", "last-child"),
|
||||||
("only", "only-child"),
|
("only", "only-child"),
|
||||||
// TODO
|
// TODO
|
||||||
]
|
])
|
||||||
.into_iter()
|
|
||||||
.map(|(a, b)| (a.to_string(), b.to_string()))
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn default_pseudos() -> HashMap<String, String> {
|
pub(crate) fn default_pseudos() -> HashMap<String, String> {
|
||||||
vec![
|
vec_to_hashmap(&[
|
||||||
("ph", "placeholder"),
|
("ph", "placeholder"),
|
||||||
// TODO
|
// TODO
|
||||||
]
|
])
|
||||||
.into_iter()
|
|
||||||
.map(|(a, b)| (a.to_string(), b.to_string()))
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! special {
|
macro_rules! special {
|
||||||
|
@ -91,11 +136,11 @@ macro_rules! special {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn default_specials() -> HashMap<String, SpecialDeclaration> {
|
pub(crate) fn default_specials() -> HashMap<String, SpecialDeclaration> {
|
||||||
vec![
|
[
|
||||||
special!("mx", val, "margin-left:{val};margin-right:{val};"),
|
special!("mx", val, "margin-left:{val};margin-right:{val}"),
|
||||||
special!("my", val, "margin-top:{val};margin-bottom:{val};"),
|
special!("my", val, "margin-top:{val};margin-bottom:{val}"),
|
||||||
special!("px", val, "padding-left:{val};padding-right:{val};"),
|
special!("px", val, "padding-left:{val};padding-right:{val}"),
|
||||||
special!("py", val, "padding-top:{val};padding-bottom:{val};"),
|
special!("py", val, "padding-top:{val};padding-bottom:{val}"),
|
||||||
special!("wh", val, "width:{val};height:{val};"),
|
special!("wh", val, "width:{val};height:{val};"),
|
||||||
// TODO
|
// TODO
|
||||||
]
|
]
|
||||||
|
|
|
@ -35,6 +35,10 @@ pub struct Zephyr {
|
||||||
pub modifiers: HashMap<String, String>,
|
pub modifiers: HashMap<String, String>,
|
||||||
/// list of pseudo-element short-hands
|
/// list of pseudo-element short-hands
|
||||||
pub pseudos: HashMap<String, String>,
|
pub pseudos: HashMap<String, String>,
|
||||||
|
/// list of value replacements for each property
|
||||||
|
///
|
||||||
|
/// property -> [(short, expanded)]
|
||||||
|
pub context_aware_values: HashMap<String, HashMap<String, String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// value -> declarations
|
/// value -> declarations
|
||||||
|
@ -108,6 +112,7 @@ impl Zephyr {
|
||||||
modifiers: default_modifiers(),
|
modifiers: default_modifiers(),
|
||||||
pseudos: default_pseudos(),
|
pseudos: default_pseudos(),
|
||||||
specials: default_specials(),
|
specials: default_specials(),
|
||||||
|
context_aware_values: default_context_aware_values(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
30
src/tests.rs
30
src/tests.rs
|
@ -14,7 +14,7 @@ fn generate_margin_works() {
|
||||||
value_type: class::ValueType::Normal,
|
value_type: class::ValueType::Normal,
|
||||||
};
|
};
|
||||||
let css = class.generate(&z).unwrap();
|
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 {
|
let class = Class {
|
||||||
property: "m",
|
property: "m",
|
||||||
|
@ -25,7 +25,7 @@ fn generate_margin_works() {
|
||||||
value_type: class::ValueType::Normal,
|
value_type: class::ValueType::Normal,
|
||||||
};
|
};
|
||||||
let css = class.generate(&z).unwrap();
|
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 {
|
let class = Class {
|
||||||
property: "m",
|
property: "m",
|
||||||
|
@ -38,7 +38,7 @@ fn generate_margin_works() {
|
||||||
let css = class.generate(&z).unwrap();
|
let css = class.generate(&z).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
css,
|
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"]);
|
let classes = z.generate_classes(["m[3rem]hover,focus$placeholder"]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
classes,
|
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"]);
|
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]"]);
|
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]
|
#[test]
|
||||||
|
@ -73,7 +73,7 @@ fn generate_multiple_works() {
|
||||||
let classes_separate = z.generate_classes(["flex-row", "mt[1rem]"]);
|
let classes_separate = z.generate_classes(["flex-row", "mt[1rem]"]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
classes_joined,
|
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);
|
assert_eq!(classes_separate, classes_joined);
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ fn generate_specials_works() {
|
||||||
let classes = z.generate_classes(["mx[1rem]"]);
|
let classes = z.generate_classes(["mx[1rem]"]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
classes,
|
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]"]);
|
let classes = z.generate_classes(["border[1px_solid_black]"]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
classes,
|
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}"]);
|
let classes = z.generate_classes(["border{1px_solid_black}", "w{full}"]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
classes,
|
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"]);
|
let classes = z.generate_classes(["m[1rem]sm"]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
classes,
|
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(--...)`
|
// the parens indicate that it should be replaced by `var(--...)`
|
||||||
let classes = z.generate_classes(["m(my-margin)"]);
|
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]
|
#[test]
|
||||||
|
@ -142,3 +142,11 @@ fn generate_css_colors() {
|
||||||
r#".white{color:white}.blanchedalmond{color:blanchedalmond}"#
|
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}"#);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue