use crate::Zephyr; #[derive(PartialEq, Debug)] pub(crate) struct Class<'a> { pub name: &'a str, pub value: Option<&'a str>, pub modifiers: Vec<&'a str>, pub pseudo: Option<&'a str>, /// the original unparsed value /// needed to generate the css selector pub original: &'a str, } impl<'a> Class<'a> { pub(crate) fn selector(&self, z: &Zephyr) -> String { let Class { modifiers, pseudo, original, .. } = self; let mut rest = modifiers .iter() .map(|m| -> &str { z.modifiers.get(*m).map(AsRef::as_ref).unwrap_or(m) }) .collect::>() .join(":"); if let Some(pseudo) = pseudo { rest.push_str("::"); let pseudo: &str = z.pseudos.get(*pseudo).map(AsRef::as_ref).unwrap_or(pseudo); rest.push_str(pseudo); } if !rest.is_empty() { rest.insert(0, ':') } let mut r = format!("{original}{rest}") .replace('[', "\\[") .replace(']', "\\]") .replace('|', "\\|") .replace('(', "\\(") .replace(')', "\\)") .replace('.', "\\.") .replace('#', "\\#") .replace('$', "\\$") .replace('\'', "\\'") .replace('*', "\\*") .replace('%', "\\%"); r.insert(0, '.'); r } pub(crate) fn generate(&self, z: &Zephyr) -> Result { let name = z .names .get(self.name) .map(AsRef::as_ref) .unwrap_or(self.name); let selector = self.selector(z); if let Some(val) = self.value { let val = z.values.get(val).map(AsRef::as_ref).unwrap_or(val); Ok(format!("{selector} {{ {name}: {val}; }}",)) } else if let Some(v) = z.rules.get(name) { Ok(format!("{selector} {{ {v} }}",)) } else { Err("{name} is not a no-variable rule, and no variables were provided") } } }