//! Rendering helpers with no knowledge of routes: Markdown, syntax //! highlighting, diffs, the history graph, and human times. Each is pure //! and unit tested. pub mod diff; pub mod graph; pub mod highlight; pub mod markdown; pub mod time; /// HTML-escape text for insertion into element content or attributes. pub fn escape(s: &str) -> String { let mut out = String::with_capacity(s.len()); for c in s.chars() { match c { '&' => out.push_str("&"), '<' => out.push_str("<"), '>' => out.push_str(">"), '"' => out.push_str("""), '\'' => out.push_str("'"), _ => out.push(c), } } out } /// `1.2 KiB`, `3.4 MiB`, `512 B`. pub fn bytes(n: u64) -> String { const UNITS: [&str; 5] = ["B", "KiB", "MiB", "GiB", "TiB"]; let mut v = n as f64; let mut i = 0; while v >= 1024.0 && i < UNITS.len() - 1 { v /= 1024.0; i += 1; } if i == 0 { format!("{n} B") } else { format!("{v:.1} {}", UNITS[i]) } } #[cfg(test)] mod tests { use super::*; #[test] fn escaping_and_sizes() { assert_eq!(escape("&'"), "<a href="x">&'"); assert_eq!(bytes(512), "512 B"); assert_eq!(bytes(1536), "1.5 KiB"); assert_eq!(bytes(5 << 20), "5.0 MiB"); } }