use crate::form::escape;
use crate::{Emit, class};
use makeover_layout::{Figure, Intent, Tone};
use std::fmt::Write as _;
#[must_use]
pub fn figure_text(figure: &Figure<'_>) -> String {
format!("{}: {}", figure.caption, figure.value)
}
#[must_use]
pub fn figure_html(figure: &Figure<'_>, opts: &Emit) -> String {
let mut html = format!(
"<div class=\"{}\" aria-label=\"{}\"",
class("figure", opts),
escape(&figure_text(figure))
);
if figure.tone != Tone::Neutral {
let _ = write!(html, " data-tone=\"{}\"", figure.tone.token());
}
let _ = write!(
html,
"><span class=\"{}\" aria-hidden=\"true\">{}</span>\
<span class=\"{}\" aria-hidden=\"true\">{}</span></div>",
class("figure-value", opts),
escape(figure.value),
class("figure-caption", opts),
escape(figure.caption),
);
html
}
#[must_use]
pub fn figures_html(figures: &[Figure<'_>], opts: &Emit) -> String {
let mut html = format!("<div class=\"{}\">", class("figures", opts));
for figure in figures {
html.push_str(&figure_html(figure, opts));
}
html.push_str("</div>");
html
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_noun_reaches_a_reader_before_the_number() {
let figure = Figure::new("17", "Current Streak");
assert_eq!(figure_text(&figure), "Current Streak: 17");
let html = figure_html(&figure, &Emit::default());
assert!(html.contains(r#"aria-label="Current Streak: 17""#));
assert_eq!(html.matches(r#"aria-hidden="true""#).count(), 2);
}
#[test]
fn an_untoned_figure_emits_no_tone_attribute() {
let plain = figure_html(&Figure::new("17", "Total"), &Emit::default());
assert!(!plain.contains("data-tone"));
let toned = figure_html(
&Figure::new("0", "Current Streak").tone(Tone::Warning),
&Emit::default(),
);
assert!(toned.contains(r#"data-tone="warning""#));
}
#[test]
fn a_value_and_a_caption_are_escaped_like_every_other_string() {
let html = figure_html(&Figure::new("<b>3</b>", "a & b"), &Emit::default());
assert!(html.contains("a & b"));
assert!(html.contains("<b>"));
assert!(!html.contains("<b>"));
}
#[test]
fn a_strip_is_the_unit_because_a_renderer_cannot_infer_a_set() {
let html = figures_html(
&[
Figure::new("17", "Current Streak"),
Figure::new("84%", "Completion Rate"),
],
&Emit::default(),
);
assert!(html.starts_with(r#"<div class="figures">"#));
assert_eq!(html.matches(r#"class="figure""#).count(), 2);
}
#[test]
fn an_empty_strip_renders_as_an_empty_strip() {
let html = figures_html(&[], &Emit::default());
assert_eq!(html, r#"<div class="figures"></div>"#);
assert!(!html.contains("figure-"));
}
#[test]
fn the_prefix_reaches_every_class() {
let opts = Emit {
class_prefix: "mo-",
..Emit::default()
};
let html = figures_html(&[Figure::new("17", "Total")], &opts);
assert!(html.contains(r#"class="mo-figures""#));
assert!(html.contains(r#"class="mo-figure""#));
assert!(html.contains(r#"class="mo-figure-value""#));
assert!(html.contains(r#"class="mo-figure-caption""#));
}
}