2022-09-05 00:02:58 +02:00
|
|
|
use std::sync::Arc;
|
|
|
|
|
2022-09-05 00:05:24 +02:00
|
|
|
use axum::{extract::Path, response::Html, Extension};
|
2023-03-22 22:39:18 +01:00
|
|
|
use cached::proc_macro::cached;
|
2022-09-05 00:05:24 +02:00
|
|
|
use pulldown_cmark::{html, Options, Parser};
|
2022-09-05 00:02:58 +02:00
|
|
|
use tracing::log::*;
|
|
|
|
|
2022-09-05 00:05:24 +02:00
|
|
|
use super::{Error, Result};
|
2023-03-22 23:55:30 +01:00
|
|
|
use crate::{handlers::PageContext, State};
|
2022-09-05 00:02:58 +02:00
|
|
|
|
2023-03-22 22:39:18 +01:00
|
|
|
pub async fn view(Path(path): Path<String>, Extension(state): Extension<Arc<State>>) -> Result {
|
|
|
|
let post = path.trim_end_matches('/');
|
|
|
|
info!("Requested post: {}", post);
|
|
|
|
let res = render_post(&state, post).await.ok_or(Error::NotFound)?;
|
|
|
|
Ok(Html(res.into()))
|
|
|
|
}
|
2022-09-05 00:02:58 +02:00
|
|
|
|
2023-03-22 22:39:18 +01:00
|
|
|
#[cached(time = 60, key = "String", convert = r"{ path.to_owned() }")]
|
|
|
|
async fn render_post(state: &State, path: &str) -> Option<String> {
|
2023-03-22 23:52:57 +01:00
|
|
|
info!("Rendering post...");
|
2023-03-22 22:39:18 +01:00
|
|
|
let post = state.posts.iter().find(|p| p.slug == path)?;
|
2022-09-05 00:02:58 +02:00
|
|
|
|
|
|
|
let options = Options::all();
|
|
|
|
let parser = Parser::new_ext(&post.content, options);
|
|
|
|
|
|
|
|
let mut out = String::new();
|
|
|
|
html::push_html(&mut out, parser);
|
|
|
|
|
2023-03-22 22:39:18 +01:00
|
|
|
let ctx = tera::Context::from_serialize(PageContext { content: out }).ok()?;
|
2022-09-05 00:02:58 +02:00
|
|
|
|
2023-03-22 22:39:18 +01:00
|
|
|
let res = match state.tera.render("post.html", &ctx) {
|
|
|
|
Ok(res) => res,
|
|
|
|
Err(e) => {
|
|
|
|
error!("Failed rendering post: {}", e);
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
Some(res)
|
2022-09-05 00:02:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn 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| {
|
2023-03-22 22:39:18 +01:00
|
|
|
error!("Failed rendering posts index: {:?}", e);
|
2022-09-05 00:02:58 +02:00
|
|
|
Error::NotFound
|
|
|
|
})?;
|
|
|
|
Ok(Html(res.into()))
|
|
|
|
}
|