From 761af37ba738fb385f8f40269cd65c1aa4022a89 Mon Sep 17 00:00:00 2001 From: annieversary Date: Sat, 2 Jul 2022 14:30:40 +0100 Subject: [PATCH] finish rework --- src/class.rs | 34 ++++++++++++++++--------- src/defaults.rs | 35 ++++++++++++++++++++++++++ src/lib.rs | 23 +++++++++++------ src/modifiers.rs | 65 ------------------------------------------------ src/name.rs | 49 ------------------------------------ src/parse.rs | 10 ++++---- 6 files changed, 77 insertions(+), 139 deletions(-) delete mode 100644 src/modifiers.rs delete mode 100644 src/name.rs diff --git a/src/class.rs b/src/class.rs index e2d27ff..5a0e875 100644 --- a/src/class.rs +++ b/src/class.rs @@ -1,10 +1,10 @@ -use crate::{modifiers::Modifiers, name::Name, Zephyr}; +use crate::Zephyr; #[derive(PartialEq, Debug)] pub(crate) struct Class<'a> { - pub name: Name<'a>, + pub name: &'a str, pub value: Option<&'a str>, - pub modifiers: Modifiers<'a>, + pub modifiers: Vec<&'a str>, pub pseudo: Option<&'a str>, /// the original unparsed value /// needed to generate the css selector @@ -12,7 +12,7 @@ pub(crate) struct Class<'a> { } impl<'a> Class<'a> { - pub(crate) fn selector(&self) -> String { + pub(crate) fn selector(&self, z: &Zephyr) -> String { let Class { modifiers, pseudo, @@ -20,16 +20,22 @@ impl<'a> Class<'a> { .. } = self; - let mut rest = if let Some(mods) = modifiers.get() { - format!(":{mods}") - } else { - "".to_string() - }; + 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("::"); rest.push_str(pseudo); } + // TODO we can probably skip the format here, we just need to push the char at the start + if !rest.is_empty() { + rest = format!(":{rest}"); + } + format!(".{original}{rest}") .replace('[', "\\[") .replace(']', "\\]") @@ -45,12 +51,16 @@ impl<'a> Class<'a> { /// TODO return result pub(crate) fn generate(&self, z: &Zephyr) -> String { - let name = self.name.as_str(); + 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 selector = self.selector(); format!("{selector} {{ {name}: {val}; }}",) } else if let Some(v) = z.rules.get(name) { - let selector = self.selector(); format!("{selector} {{ {v} }}",) } else { panic!("{name} is not a no-variable rule, and no variables were provided"); diff --git a/src/defaults.rs b/src/defaults.rs index e3ae070..111e66a 100644 --- a/src/defaults.rs +++ b/src/defaults.rs @@ -13,3 +13,38 @@ pub(crate) fn default_rules() -> HashMap { .map(|(a, b)| (a.to_string(), b.to_string())) .collect() } + +pub(crate) fn default_names() -> HashMap { + vec![ + ("m", "margin"), + ("mt", "margin-top"), + ("mb", "margin-bottom"), + ("ml", "margin-left"), + ("mr", "margin-right"), + ("p", "padding"), + ("pt", "padding-top"), + ("pb", "padding-bottom"), + ("pl", "padding-left"), + ("pr", "padding-right"), + ("bg", "background"), + ("bgc", "background-color"), + // TODO + ] + .into_iter() + .map(|(a, b)| (a.to_string(), b.to_string())) + .collect() +} + +pub(crate) fn default_modifiers() -> HashMap { + vec![ + ("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() +} diff --git a/src/lib.rs b/src/lib.rs index d0f29c4..dc44fa7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,13 +1,14 @@ use std::collections::HashMap; -use defaults::default_rules; +use defaults::default_modifiers; -use crate::parse::*; +use crate::{ + defaults::{default_names, default_rules}, + parse::*, +}; mod class; mod defaults; -mod modifiers; -mod name; mod parse; // pub fn generate_and_write(classes: &[&str], path: impl AsRef) -> Result<(), std::io::Error> { @@ -19,6 +20,8 @@ mod parse; pub struct Zephyr { pub rules: HashMap, + pub names: HashMap, + pub modifiers: HashMap, } impl Zephyr { @@ -26,13 +29,17 @@ impl Zephyr { pub fn new() -> Self { Self { rules: default_rules(), + names: default_names(), + modifiers: default_modifiers(), } } /// builds a `Zephyr` without the default ruleset - pub fn new_without_rules() -> Self { + pub fn new_without_defaults() -> Self { Self { rules: HashMap::new(), + names: HashMap::new(), + modifiers: HashMap::new(), } } @@ -59,7 +66,7 @@ mod tests { let z = Zephyr::new(); let class = Class { - name: "m".into(), + name: "m", value: Some("1rem"), modifiers: vec![].into(), pseudo: None, @@ -69,7 +76,7 @@ mod tests { assert_eq!(css, r#".m\[1rem\] { margin: 1rem; }"#); let class = Class { - name: "m".into(), + name: "m", value: Some("1rem"), modifiers: vec!["focus"].into(), pseudo: None, @@ -79,7 +86,7 @@ mod tests { assert_eq!(css, r#".m\[1rem\]focus:focus { margin: 1rem; }"#); let class = Class { - name: "m".into(), + name: "m", value: Some("1rem"), modifiers: vec!["focus", "hover", "odd"].into(), pseudo: None, diff --git a/src/modifiers.rs b/src/modifiers.rs deleted file mode 100644 index 3701ee6..0000000 --- a/src/modifiers.rs +++ /dev/null @@ -1,65 +0,0 @@ -use once_cell::sync::Lazy; -use std::collections::HashMap; - -static REPLACEMENTS: Lazy> = Lazy::new(|| { - [ - ("odd", "nth-child(odd)"), - ("even", "nth-child(even)"), - ("first", "first-child"), - ("last", "last-child"), - ("only", "only-child"), - ] - .into() -}); - -#[derive(Default, PartialEq, Debug)] -pub(crate) struct Modifiers<'a>(Vec>); - -impl<'a> Modifiers<'a> { - pub(crate) fn get(&self) -> Option { - if self.is_empty() { - None - } else { - Some( - self.0 - .iter() - .map(Modifier::as_str) - .collect::>() - .join(":"), - ) - } - } - - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } -} - -impl<'a> From> for Modifiers<'a> { - fn from(v: Vec<&'a str>) -> Self { - Modifiers(v.into_iter().map(Modifier::new).collect()) - } -} - -#[derive(Debug, PartialEq)] -enum Modifier<'a> { - Converted { from: &'a str, to: &'static str }, - Unknown(&'a str), -} - -impl<'a> Modifier<'a> { - fn new(s: &'a str) -> Self { - if let Some(to) = REPLACEMENTS.get(s) { - Self::Converted { from: s, to } - } else { - Self::Unknown(s) - } - } - - fn as_str(&self) -> &str { - match self { - Self::Converted { to, .. } => to, - Self::Unknown(v) => v, - } - } -} diff --git a/src/name.rs b/src/name.rs deleted file mode 100644 index 8dfa82c..0000000 --- a/src/name.rs +++ /dev/null @@ -1,49 +0,0 @@ -use once_cell::sync::Lazy; -use std::collections::HashMap; - -static REPLACEMENTS: Lazy> = Lazy::new(|| { - [ - ("m", "margin"), - ("mt", "margin-top"), - ("mb", "margin-bottom"), - ("ml", "margin-left"), - ("mr", "margin-right"), - ("p", "padding"), - ("pt", "padding-top"), - ("pb", "padding-bottom"), - ("pl", "padding-left"), - ("pr", "padding-right"), - ("bg", "background"), - ("bgc", "background-color"), - ] - .into() -}); - -#[derive(Debug, PartialEq)] -pub(crate) enum Name<'a> { - Converted { from: &'a str, to: &'static str }, - Unknown(&'a str), -} - -impl<'a> Name<'a> { - pub(crate) fn new(s: &'a str) -> Self { - if let Some(to) = REPLACEMENTS.get(s) { - Self::Converted { from: s, to } - } else { - Self::Unknown(s) - } - } - - pub(crate) fn as_str(&self) -> &str { - match self { - Self::Converted { to, .. } => to, - Self::Unknown(v) => v, - } - } -} - -impl<'a> From<&'a str> for Name<'a> { - fn from(s: &'a str) -> Self { - Name::new(s) - } -} diff --git a/src/parse.rs b/src/parse.rs index 19f9ee8..6a76093 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -1,4 +1,4 @@ -use crate::{class::Class, name::Name}; +use crate::class::Class; pub(crate) fn parse_class<'a>(original: &'a str) -> Option> { let (class, pseudo) = if let Some((class, pseudo)) = original.split_once('$') { @@ -15,7 +15,7 @@ pub(crate) fn parse_class<'a>(original: &'a str) -> Option> { }; return Some(Class { - name: Name::new(&class[0..p]), + name: &class[0..p], value: None, modifiers: mods.into(), pseudo, @@ -32,7 +32,7 @@ pub(crate) fn parse_class<'a>(original: &'a str) -> Option> { }; return Some(Class { - name: Name::new(&class[0..start]), + name: &class[0..start], value: Some(&class[start + 1..end]), modifiers: mods.into(), pseudo, @@ -41,7 +41,7 @@ pub(crate) fn parse_class<'a>(original: &'a str) -> Option> { } _ => { return Some(Class { - name: Name::new(&class[0..]), + name: &class[0..], value: None, modifiers: vec![].into(), pseudo, @@ -66,7 +66,7 @@ mod tests { assert_eq!( parse_class(class), Some(Class { - name: Name::new(name), + name, value, modifiers: modifiers.into(), pseudo,