finish rework
This commit is contained in:
parent
8613e712e7
commit
761af37ba7
34
src/class.rs
34
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::<Vec<_>>()
|
||||
.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");
|
||||
|
|
|
@ -13,3 +13,38 @@ pub(crate) fn default_rules() -> HashMap<String, String> {
|
|||
.map(|(a, b)| (a.to_string(), b.to_string()))
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub(crate) fn default_names() -> HashMap<String, String> {
|
||||
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<String, String> {
|
||||
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()
|
||||
}
|
||||
|
|
23
src/lib.rs
23
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<Path>) -> Result<(), std::io::Error> {
|
||||
|
@ -19,6 +20,8 @@ mod parse;
|
|||
|
||||
pub struct Zephyr {
|
||||
pub rules: HashMap<String, String>,
|
||||
pub names: HashMap<String, String>,
|
||||
pub modifiers: HashMap<String, String>,
|
||||
}
|
||||
|
||||
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,
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
use once_cell::sync::Lazy;
|
||||
use std::collections::HashMap;
|
||||
|
||||
static REPLACEMENTS: Lazy<HashMap<&'static str, &'static str>> = 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<Modifier<'a>>);
|
||||
|
||||
impl<'a> Modifiers<'a> {
|
||||
pub(crate) fn get(&self) -> Option<String> {
|
||||
if self.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(
|
||||
self.0
|
||||
.iter()
|
||||
.map(Modifier::as_str)
|
||||
.collect::<Vec<_>>()
|
||||
.join(":"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.0.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<Vec<&'a str>> 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,
|
||||
}
|
||||
}
|
||||
}
|
49
src/name.rs
49
src/name.rs
|
@ -1,49 +0,0 @@
|
|||
use once_cell::sync::Lazy;
|
||||
use std::collections::HashMap;
|
||||
|
||||
static REPLACEMENTS: Lazy<HashMap<&'static str, &'static str>> = 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)
|
||||
}
|
||||
}
|
10
src/parse.rs
10
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<Class<'a>> {
|
||||
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<Class<'a>> {
|
|||
};
|
||||
|
||||
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<Class<'a>> {
|
|||
};
|
||||
|
||||
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<Class<'a>> {
|
|||
}
|
||||
_ => {
|
||||
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,
|
||||
|
|
Loading…
Reference in New Issue