use anyhow::Error; use std::collections::HashMap; use warp::hyper::StatusCode; use crate::{image::MyImage, load::load_from_path, misc::Misc, post::Post, resp::Response}; pub struct Blog { //pages: Vec<Page>, posts: Vec<Post>, imgs: Vec<MyImage>, misc: Vec<Misc>, } impl Blog { pub fn new() -> Result<Self, Error> { /*let pages = fs::read_dir("pages")? .map(|path| Page::new(path?)?) .collect();*/ let posts = load_from_path("posts", "posts")?; let imgs = load_from_path("assets/img", "")?; let misc = load_from_path("assets/misc", "misc")?; Ok(Self { posts, imgs, misc }) } fn home(&mut self) -> Result<String, Error> { self.posts.sort(); self.posts.reverse(); let mut content = r#"<div class="centered"><h1>Stephen's Site</h1>Rewritten in Rust!</div><h4>Recent Posts</h4><table>"# .to_string(); for post in &self.posts { content.push_str(&post.link()?); } content.push_str("</table>"); Ok(dress_page("Stephen's Site", &content)) } } pub struct RenderedBlog { pages: HashMap<String, Response>, not_found: Response, } impl RenderedBlog { pub fn get(&self, path: &str) -> (StatusCode, Response) { self.pages .get(path) .map(|x| (StatusCode::OK, x.clone())) .unwrap_or((StatusCode::NOT_FOUND, self.not_found.clone())) } } impl TryFrom<Blog> for RenderedBlog { type Error = Error; fn try_from(mut b: Blog) -> Result<Self, Error> { let mut pages = HashMap::new(); for p in &b.posts { let body = dress_page(&p.title, &p.html()?); pages.insert(p.url.clone(), Response::html(body)); } pages.insert( "/style.css".to_string(), Response::css(include_str!("assets/style.css").to_string()), ); let home = b.home()?; pages.insert("/".to_string(), Response::html(home)); for img in b.imgs { let (original_url, original, thumbnail_url, thumbnail) = img.into_responses()?; pages.insert(thumbnail_url, thumbnail); pages.insert(original_url, original); } for m in b.misc { pages.insert(m.url.clone(), m.response()); } let not_found = Response::html(dress_page( "Page not found", include_str!("assets/404.html"), )); dbg!(pages.keys()); Ok(Self { not_found, pages }) } } fn dress_page(title: &str, content: &str) -> String { format!( r#"<!DOCTYPE html><html><head><link rel="stylesheet" href="/style.css" /><title>{title}</title></head><body><a href="/">Home</a><hr>{content}</body></html>"# ) }