repos

blog.bythewood.me-rust

mirror archived upstream

Single-binary self-hosted Markdown blog on Rust axum: no database, live search, Typst PDF export, and strong SEO.

axumblogdockermarkdownminijinjarustself-hostedtypstvite

1.6 KB · 65 lines · Rust Raw History
 1use axum::http::{header, HeaderMap, Uri};
 2use axum::response::Html;
 3use chrono::{Datelike, Local};
 4use minijinja::context;
 5use serde::Serialize;
 6
 7use crate::app::AppState;
 8use crate::error::AppError;
 9use crate::posts::{self, collect_tags};
10use crate::templates::RequestCtx;
11
12#[derive(Debug, Clone, Serialize)]
13pub struct Crumb {
14    pub title: String,
15    pub url: String,
16}
17
18#[derive(Debug, Serialize)]
19struct NowCtx {
20    year: i32,
21}
22
23pub fn build_request(uri: &Uri, headers: &HeaderMap) -> RequestCtx {
24    let host = headers
25        .get(header::HOST)
26        .and_then(|v| v.to_str().ok())
27        .unwrap_or("localhost");
28    let scheme = headers
29        .get("x-forwarded-proto")
30        .and_then(|v| v.to_str().ok())
31        .unwrap_or("http");
32    let url_root = format!("{scheme}://{host}/");
33    let path_and_query = uri.path_and_query().map(|p| p.as_str()).unwrap_or("/");
34    let url = format!("{scheme}://{host}{path_and_query}");
35    let base_url = format!("{scheme}://{host}{}", uri.path());
36    RequestCtx {
37        url,
38        url_root,
39        base_url,
40    }
41}
42
43pub fn render_html(
44    state: &AppState,
45    template: &str,
46    extra: minijinja::Value,
47    request: &RequestCtx,
48) -> Result<Html<String>, AppError> {
49    let published = posts::published(&state.posts);
50    let nav_items = collect_tags(&published);
51    let now = NowCtx {
52        year: Local::now().year(),
53    };
54    let tmpl = state.env.get_template(template)?;
55    let ctx = context! {
56        nav_items => nav_items,
57        now => now,
58        debug => cfg!(debug_assertions),
59        request => request,
60        ..extra
61    };
62    let body = tmpl.render(ctx)?;
63    Ok(Html(body))
64}