use super::types::CssRule;
use std::collections::HashMap;
pub struct CssOutputGenerator;
impl CssOutputGenerator {
pub fn generate_css(rules: &HashMap<String, CssRule>, custom_properties: &HashMap<String, String>) -> String {
let mut css = String::new();
if !custom_properties.is_empty() {
css.push_str(":root {\n");
for (name, value) in custom_properties {
css.push_str(&format!(" --{}: {};\n", name, value));
}
css.push_str("}\n\n");
}
let mut base_rules = Vec::new();
let mut responsive_rules: HashMap<String, Vec<&CssRule>> = HashMap::new();
for rule in rules.values() {
if let Some(ref media_query) = rule.media_query {
responsive_rules.entry(media_query.clone()).or_default().push(rule);
} else {
base_rules.push(rule);
}
}
for rule in base_rules {
css.push_str(&Self::rule_to_css(rule));
}
for (media_query, rules) in responsive_rules {
css.push_str(&format!("@media {} {{\n", media_query));
for rule in rules {
css.push_str(&Self::rule_to_css(rule));
}
css.push_str("}\n\n");
}
css
}
fn rule_to_css(rule: &CssRule) -> String {
let mut css = String::new();
css.push_str(&format!("{} {{\n", rule.selector));
for property in &rule.properties {
let important = if property.important { " !important" } else { "" };
css.push_str(&format!(" {}: {}{};\n", property.name, property.value, important));
}
css.push_str("}\n\n");
css
}
pub fn generate_minified_css(rules: &HashMap<String, CssRule>, custom_properties: &HashMap<String, String>) -> String {
let mut css = String::new();
if !custom_properties.is_empty() {
css.push_str(":root{");
for (name, value) in custom_properties {
css.push_str(&format!("--{}:{};", name, value));
}
css.push('}');
}
let mut base_rules = Vec::new();
let mut responsive_rules: HashMap<String, Vec<&CssRule>> = HashMap::new();
for rule in rules.values() {
if let Some(ref media_query) = rule.media_query {
responsive_rules.entry(media_query.clone()).or_default().push(rule);
} else {
base_rules.push(rule);
}
}
for rule in base_rules {
css.push_str(&Self::rule_to_minified_css(rule));
}
for (media_query, rules) in responsive_rules {
css.push_str(&format!("@media {} {{", media_query));
for rule in rules {
css.push_str(&Self::rule_to_minified_css(rule));
}
css.push('}');
}
css
}
fn rule_to_minified_css(rule: &CssRule) -> String {
let mut css = String::new();
css.push_str(&format!("{} {{", rule.selector));
for property in &rule.properties {
let important = if property.important { "!important" } else { "" };
css.push_str(&format!("{}:{}{};", property.name, property.value, important));
}
css.push('}');
css
}
}