Newer
Older
use fnv::FnvHashMap;
config::Logo, favicon::Favicon, image::MyImage, load::load_from_path, misc::Misc,
path::UrlPath, post::Post, resp::Response, style::Style,
pub fn new(
name: String,
description: String,
base_path: &Path,
logo: Option<Logo>,
) -> Result<Self, Error> {
let pages = load_from_path(base_path, &base_path.join("pages"), "pages")?;
let posts = load_from_path(base_path, &base_path.join("posts"), "posts")?;
let imgs = load_from_path(base_path, &base_path.join("assets/img"), "")?;
let misc = load_from_path(base_path, &base_path.join("assets/misc"), "")?;
let custom_style = Style::load_if_exists(base_path.join("assets/style.css"))?;
let favicon = Favicon::load_if_exists(base_path.join("assets/favicon.png"))?;
let name = &self.name;
let description = &self.description;
let mut content = format!(
r#"<div class="centered"><h1>{name}</h1>{description}</div><h2>Recent Posts</h2><table>"#
);
Ok(self.dress_page(None, &content))
}
fn dress_page(&self, title: Option<&str>, content: &str) -> String {
let title = match title {
Some(title) => format!("{} | {}", title.trim(), self.name.trim()),
None => self.name.trim().to_string(),
};
let favicons = match &self.favicon {
Some(f) => f.html(),
None => "",
};
let logo = match &self.logo {
Some(logo) => format!(
r#"<img src="{}" width="{}" height="{}" alt="{}" class="align-right" />"#,
logo.path, logo.width, logo.height, logo.alt
),
None => "".to_string(),
};
let mut page_links = String::new();
for p in &self.pages {
page_links.push_str(&p.link_short());
}
format!(
r#"<!DOCTYPE html><html lang="en"><head><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/style.css" />{favicons}<title>{title}</title></head><body><div><a href="/">Home</a>{page_links}{logo}</div><hr>{content}</body></html>"#
)
pages: FnvHashMap<UrlPath, Response>,
.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 = FnvHashMap::default();
let mut style = include_str!("assets/style.css").to_string();
if let Some(s) = &b.custom_style {
style.push_str(&s.content);
}
for img in &b.imgs {
let (original_url, original, thumbnail_url, thumbnail) =
img.clone().into_responses()?;
insert_path(&mut pages, &thumbnail_url, thumbnail)?;
insert_path(&mut pages, &original_url, original)?;
for m in &b.misc {
insert_path(&mut pages, &m.url.clone(), m.clone().response())?;
let not_found =
Response::html(b.dress_page(Some("Page not found"), include_str!("assets/404.html")));
if let Some(fav) = b.favicon {
for (p, r) in fav.responses {
insert_path(&mut pages, p, r)?;
}
}
pages: &mut FnvHashMap<UrlPath, Response>,
path: &str,
value: Response,
) -> anyhow::Result<()> {
let path = UrlPath::new(path);
if pages.contains_key(&path) {
bail!(
"Cannot serve {} - already serving an asset with the same path",
path
);
}
pages.insert(path, value);
Ok(())
}