use std::fmt::Write;
use crate::themes::compiled::CompiledTheme;
pub(crate) const LIGHT_SUFFIX: &str = "l-";
pub(crate) const DARK_SUFFIX: &str = "d-";
pub(crate) fn generate_css(theme: &CompiledTheme, prefix: &str) -> String {
let mut css = String::new();
writeln!(css, "/*").unwrap();
writeln!(css, " * theme \"{}\" generated by giallo", theme.name).unwrap();
writeln!(css, " */").unwrap();
writeln!(css).unwrap();
writeln!(css, ".{prefix}code {{").unwrap();
writeln!(
css,
" {}",
theme.default_style.foreground.as_css_color_property()
)
.unwrap();
writeln!(
css,
" {}",
theme.default_style.background.as_css_bg_color_property()
)
.unwrap();
writeln!(css, "}}").unwrap();
writeln!(css).unwrap();
if let Some(ref highlight_bg) = theme.highlight_background_color {
writeln!(css, ".{prefix}hl {{").unwrap();
writeln!(css, " {}", highlight_bg.as_css_bg_color_property()).unwrap();
writeln!(css, "}}").unwrap();
writeln!(css).unwrap();
}
if let Some(ref line_number_fg) = theme.line_number_foreground {
writeln!(css, ".giallo-ln {{").unwrap();
writeln!(css, " {}", line_number_fg.as_css_color_property()).unwrap();
writeln!(css, "}}").unwrap();
writeln!(css).unwrap();
}
let mut fg_entries: Vec<_> = theme.style_map.fg.iter().collect();
fg_entries.sort_by_key(|(_, id)| *id);
for (color, id) in fg_entries {
writeln!(css, ".{prefix}{id} {{ {} }}", color.as_css_color_property()).unwrap();
}
let mut bg_entries: Vec<_> = theme.style_map.bg.iter().collect();
bg_entries.sort_by_key(|(_, id)| *id);
for (color, id) in bg_entries {
writeln!(
css,
".{prefix}bg{id} {{ {} }}",
color.as_css_bg_color_property()
)
.unwrap();
}
writeln!(css, ".{prefix}b {{ font-weight: bold; }}").unwrap();
writeln!(css, ".{prefix}i {{ font-style: italic; }}").unwrap();
writeln!(css, ".{prefix}u {{ text-decoration: underline; }}").unwrap();
writeln!(css, ".{prefix}s {{ text-decoration: line-through; }}").unwrap();
writeln!(
css,
".{prefix}us {{ text-decoration: underline line-through; }}"
)
.unwrap();
if !theme.default_style.font_style.is_empty() {
writeln!(
css,
".{prefix}fr {{ font-style: normal; font-weight: normal; text-decoration: none; }}"
)
.unwrap();
}
css
}
#[cfg(test)]
mod tests {
use super::*;
use crate::themes::RawTheme;
use insta::assert_snapshot;
#[test]
fn can_generate_css_for_theme() {
let theme = RawTheme::load_from_file(
"grammars-themes/packages/tm-themes/themes/vitesse-black.json",
)
.unwrap()
.compile()
.unwrap();
assert!(theme.style_map.fg.len() < theme.rules.len());
assert_snapshot!(generate_css(&theme, "g-"));
}
}