use std::collections::HashMap;
use std::fmt::Write;
use crate::markdown;
use super::CodeBlock;
static DEFAULT_BG_COLOR: &str = "#e1eaff";
static DEFAULT_BORDER_COLOR: &str = "#82a7fc";
pub(crate) struct CalloutBlock<'a> {
bg_color: &'a str,
border_color: &'a str,
content: &'a str,
}
impl<'a> CalloutBlock<'a> {
pub fn new(options: HashMap<String, &'a str>, block: &'a str) -> Self {
let (bg_color, border_color) = Self::parse_colors(&options);
CalloutBlock {
bg_color,
border_color,
content: block,
}
}
fn parse_colors(options: &HashMap<String, &'a str>) -> (&'a str, &'a str) {
let (bg_color, border_color) = (
options.get("bg_color").cloned(),
options.get("border_color").cloned(),
);
let (theme_bg_color, theme_border_color) =
match options.get("theme").map(|theme| theme.to_lowercase()) {
Some(theme) => {
match theme.as_ref() {
"grey" | "gray" => ("#dee0e399", "#dee0e3"),
"red" => ("#fde2e2", "#f98e8b"),
"orange" => ("#feead2", "#ffba6b"),
"yellow" => ("#ffffcc", "#fff67a"),
"green" => ("#d9f5d6", "#8ee085"),
"purple" => ("#eceafe", "#ad82f7"),
_ => (DEFAULT_BG_COLOR, DEFAULT_BORDER_COLOR),
}
}
None => (DEFAULT_BG_COLOR, DEFAULT_BORDER_COLOR),
};
(
bg_color.unwrap_or(theme_bg_color),
border_color.unwrap_or(theme_border_color),
)
}
}
impl<'a> CodeBlock for CalloutBlock<'a> {
fn render(&self) -> anyhow::Result<String> {
let mut html = String::new();
let style = format!(
"background-color: {}; border-color: {}",
self.bg_color, self.border_color,
);
writeln!(&mut html, r#"<div class="callout" style="{}">"#, style)?;
let block_html = markdown::render_html(self.content);
writeln!(&mut html, r#" <div>{}</div>"#, block_html)?;
writeln!(&mut html, r#"</div>"#)?;
Ok(html)
}
}
#[cfg(test)]
mod tests {
use crate::code_blocks::Fenced;
use super::CalloutBlock;
#[test]
fn test_parse_colors() {
let fenced = Fenced::parse("callout, theme: red").unwrap();
let callout = CalloutBlock::new(fenced.options, "dummy");
assert_eq!(callout.bg_color, "#fde2e2");
assert_eq!(callout.border_color, "#f98e8b");
let fenced = Fenced::parse("callout, theme: red, bg_color: #123456").unwrap();
let callout = CalloutBlock::new(fenced.options, "dummy");
assert_eq!(callout.bg_color, "#123456");
assert_eq!(callout.border_color, "#f98e8b");
}
}