70 lines
2 KiB
Rust
70 lines
2 KiB
Rust
|
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<T = Html<Vec<u8>>> = std::result::Result<T, Error>;
|
||
|
|
||
|
#[derive(Serialize)]
|
||
|
struct PageContext {
|
||
|
content: String
|
||
|
}
|
||
|
|
||
|
pub async fn index(Extension(state): Extension<Arc<State>>) -> 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<String>, Extension(state): Extension<Arc<State>>) -> 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<Arc<State>>) -> 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<u8> = "not found".into();
|
||
|
let body = axum::body::boxed(axum::body::Full::from(result));
|
||
|
match self {
|
||
|
Error::NotFound => {
|
||
|
Response::builder()
|
||
|
.status(404)
|
||
|
.body(body)
|
||
|
.unwrap()
|
||
|
},
|
||
|
}
|
||
|
}
|
||
|
}
|