use std::sync::Arc; use serde_derive::Serialize; use tracing::log::*; use axum::{response::{Html, IntoResponse, Response}, extract::Path, Extension}; use pulldown_cmark::{Options, Parser, html}; use crate::State; pub enum Error { NotFound, } pub type Result>> = std::result::Result; #[derive(Serialize)] struct PageContext { content: String } pub async fn index(Extension(state): Extension>) -> Result { let ctx = tera::Context::new(); let res = state.tera.render("index.html", &ctx).map_err(|e| { error!("Failed rendering index: {}", e); Error::NotFound})?; Ok(Html(res.into())) } pub async fn post_view(Path(name): Path, Extension(state): Extension>) -> Result { info!("Requested post: {}", name); let state = state.clone(); let post = state.posts.iter().find(|p| p.name == name).ok_or(Error::NotFound)?; let options = Options::all(); let parser = Parser::new_ext(&post.content, options); let mut out = String::new(); html::push_html(&mut out, parser); let ctx = tera::Context::from_serialize(PageContext { content: out }).map_err(|_| Error::NotFound)?; let res = state.tera.render("post.html", &ctx).map_err(|e| { error!("Failed rendering post: {}", e); Error::NotFound})?; Ok(Html(res.into())) } pub async fn post_index(Extension(state): Extension>) -> Result { let mut ctx = tera::Context::new(); ctx.insert("posts", &state.posts); let res = state.tera.render("postsindex.html", &ctx).map_err(|e| { error!("Failed rendering posts index: {}", e); Error::NotFound})?; Ok(Html(res.into())) } impl IntoResponse for Error { fn into_response(self) -> Response { let result: Vec = "not found".into(); let body = axum::body::boxed(axum::body::Full::from(result)); match self { Error::NotFound => { Response::builder() .status(404) .body(body) .unwrap() }, } } }