use crate::entries::Entry; pub fn render_page(site_title: &str, site_url: &str, entries: &[Entry], form_html: &str) -> String { let nav_url = site_url.trim_end_matches('/'); let mut html = format!( r#" {site_title}

guestbook

If you visited my site, please sign my guestbook!

{form_html} "# ); for entry in entries { html.push_str(&render_entry(entry)); } html.push_str("\n\n"); html } fn render_entry(entry: &Entry) -> String { let mut header = format!("
\n

{} - {}", entry.meta.date, entry.meta.name); if !entry.meta.website.is_empty() { header.push_str(&format!( " ({})", entry.meta.website, entry.meta.website )); } header.push_str("

\n"); format!("{header} {}\n
\n", entry.body) } pub const FORM_HTML: &str = r#"
"#; pub const STYLE_CSS: &str = "body { max-width: 70ch; line-height: 1.5; margin: 0 auto; padding: 1rem; } "; #[cfg(test)] mod tests { use super::*; use crate::entries::{Entry, EntryMeta, Status}; fn make_entry(name: &str, date: &str, body: &str) -> Entry { Entry { id: "test".into(), meta: EntryMeta { name: name.into(), date: date.into(), website: String::new(), status: Status::Approved, }, body: body.into(), } } #[test] fn test_render_page_contains_nav() { let html = render_page("ily.rs", "https://ily.rs", &[], FORM_HTML); assert!(html.contains(r#"ily.rs"#)); assert!(html.contains(r#"links"#)); } #[test] fn test_render_page_contains_form() { let html = render_page("ily.rs", "https://ily.rs", &[], FORM_HTML); assert!(html.contains(r#"action="/submit""#)); assert!(html.contains(r#"style="display:none""#)); // honeypot } #[test] fn test_render_entry_no_website() { let entry = make_entry("alice", "2026-04-09", "Hello!"); let html = render_page("ily.rs", "https://ily.rs", &[entry], FORM_HTML); assert!(html.contains("alice")); assert!(html.contains("Hello!")); assert!(!html.contains(""#)); } #[test] fn test_render_preserves_html_in_body() { let entry = make_entry("carol", "2026-04-09", "Bold "); let html = render_page("ily.rs", "https://ily.rs", &[entry], FORM_HTML); assert!(html.contains("Bold")); assert!(html.contains("")); } }