diff --git a/src/class.rs b/src/class.rs index b5ce108..a02cd8e 100644 --- a/src/class.rs +++ b/src/class.rs @@ -1,9 +1,10 @@ use std::borrow::Cow; use crate::{ + indent, media_queries::{wrap_in_query, ReducedMotion, Responsive}, modifiers::Modifiers, - Zephyr, ZephyrError, + nl, space, Zephyr, ZephyrError, }; #[derive(PartialEq, Debug)] @@ -83,7 +84,7 @@ impl<'a> Class<'a> { /// generates the css rule for this class /// does not generate the corresponding media query - pub(crate) fn generate(&self, z: &Zephyr) -> Result { + pub(crate) fn generate(&self, z: &Zephyr, indent_level: usize) -> Result { let property = z .properties .get(self.property) @@ -91,6 +92,11 @@ impl<'a> Class<'a> { .unwrap_or(self.property); let selector = self.selector(z); + let space = space(z.pretty_print); + let indent2 = indent(z.pretty_print, indent_level + 1); + let indent = indent(z.pretty_print, indent_level); + let nl = nl(z.pretty_print); + if let Some(val) = self.value { let val = match self.value_type { ValueType::Normal => { @@ -109,22 +115,24 @@ impl<'a> Class<'a> { if let Some(fun) = z.specials.get(property) { let v = fun(&val); - Ok(format!("{selector}{{{v}}}",)) + Ok(format!( + "{indent}{selector}{space}{{{nl}{indent2}{v}{nl}{indent}}}{nl}", + )) } else { - Ok(format!("{selector}{{{property}:{val}}}")) + Ok(format!( + "{indent}{selector}{space}{{{nl}{indent2}{property}:{val}{nl}{indent}}}{nl}" + )) } } else if let Some(v) = z.declarations.get(property) { - Ok(format!("{selector}{{{v}}}")) + Ok(format!( + "{indent}{selector}{space}{{{nl}{indent2}{v}{nl}{indent}}}{nl}" + )) } else { Err(ZephyrError::ValueMissing) } } pub fn generate_with_media_query(&self, z: &Zephyr) -> Result { - let css = self.generate(z)?; - - dbg!(&self.modifiers); - let mut queries: Vec = vec![]; if let Some(r) = &self.modifiers.responsive { queries.extend(r.queries()); @@ -133,7 +141,9 @@ impl<'a> Class<'a> { queries.extend(r.queries().iter().map(ToString::to_string)); } - Ok(wrap_in_query(css, &queries)) + let css = self.generate(z, queries.is_empty().then_some(0).unwrap_or(1))?; + + Ok(wrap_in_query(css, &queries, z.pretty_print)) } } diff --git a/src/defaults.rs b/src/defaults.rs index 5d3bd61..cf5e5e9 100644 --- a/src/defaults.rs +++ b/src/defaults.rs @@ -44,6 +44,7 @@ pub(crate) fn default_properties() -> HashMap { ("bgc", "background-color"), ("tt", "text-transform"), ("td", "text-decoration"), + ("fw", "font-weight"), // TODO ]) } diff --git a/src/lib.rs b/src/lib.rs index a5d0091..17f5597 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,6 +42,8 @@ pub struct Zephyr { /// /// property -> [(short, expanded)] pub context_aware_values: HashMap>, + + pub pretty_print: bool, } /// value -> declarations @@ -97,7 +99,7 @@ impl Zephyr { let len = classes.len(); tracing::trace!("finished generating {len} classes"); - classes.join("") + classes.join(nl(self.pretty_print)) } /// this one returns an error if parsing or generating fails @@ -116,15 +118,30 @@ impl Zephyr { pseudos: default_pseudos(), specials: default_specials(), context_aware_values: default_context_aware_values(), + pretty_print: false, } } pub fn with_css_colors(mut self) -> Self { - self.declarations.extend( - crate::consts::CSS_COLORS - .iter() - .map(|c| (c.to_string(), format!("color:{c}"))), - ); + self.declarations + .extend(crate::consts::CSS_COLORS.iter().map(|c| { + ( + c.to_string(), + format!("color:{}{c}", space(self.pretty_print)), + ) + })); self } } + +pub(crate) fn space(b: bool) -> &'static str { + b.then_some(" ").unwrap_or_default() +} + +pub(crate) fn indent(b: bool, level: usize) -> String { + b.then_some(" ".repeat(level)).unwrap_or_default() +} + +pub(crate) fn nl(b: bool) -> &'static str { + b.then_some("\n").unwrap_or_default() +} diff --git a/src/media_queries.rs b/src/media_queries.rs index f956176..22971cc 100644 --- a/src/media_queries.rs +++ b/src/media_queries.rs @@ -1,3 +1,5 @@ +use crate::{nl, space}; + #[derive(PartialEq, Debug)] pub(crate) struct Responsive { breakpoint: Breakpoint, @@ -118,7 +120,7 @@ impl ReducedMotion { } } -pub(crate) fn wrap_in_query(css: String, queries: &[String]) -> String { +pub(crate) fn wrap_in_query(css: String, queries: &[String], pretty_print: bool) -> String { if queries.is_empty() { return css; } @@ -126,8 +128,10 @@ pub(crate) fn wrap_in_query(css: String, queries: &[String]) -> String { .iter() .map(|s| format!("({s})")) .collect::>() - .join("and"); - format!("@media{query}{{{css}}}") + .join(if pretty_print { " and " } else { "and" }); + let space = space(pretty_print); + let nl = nl(pretty_print); + format!("@media{space}{query}{space}{{{nl}{css}}}{nl}") } #[cfg(test)] diff --git a/src/tests.rs b/src/tests.rs index 71373ef..efdda66 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -13,7 +13,7 @@ fn generate_margin_works() { original: "m[1rem]", value_type: class::ValueType::Normal, }; - let css = class.generate(&z).unwrap(); + let css = class.generate(&z, 0).unwrap(); assert_eq!(css, r#".m\[1rem\]{margin:1rem}"#); let class = Class { @@ -24,7 +24,7 @@ fn generate_margin_works() { original: "m[1rem]focus", value_type: class::ValueType::Normal, }; - let css = class.generate(&z).unwrap(); + let css = class.generate(&z, 0).unwrap(); assert_eq!(css, r#".m\[1rem\]focus:focus{margin:1rem}"#); let class = Class { @@ -35,7 +35,7 @@ fn generate_margin_works() { original: "m[1rem]focus,hover,odd", value_type: class::ValueType::Normal, }; - let css = class.generate(&z).unwrap(); + let css = class.generate(&z, 0).unwrap(); assert_eq!( css, r#".m\[1rem\]focus,hover,odd:focus:hover:nth-child\(odd\){margin:1rem}"#