diff options
| author | Xe Iaso <me@christine.website> | 2022-11-25 19:01:10 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-11-25 19:01:10 -0500 |
| commit | cc933b31fd23bb06e95bf41f848a1c99353d44ae (patch) | |
| tree | af8288dbd4db2ad886d6b326bffb1c9d5b568de3 /src/handlers | |
| parent | 551e0384c923ff3ee98cfddf7e3eb42c6dbb2941 (diff) | |
| download | xesite-cc933b31fd23bb06e95bf41f848a1c99353d44ae.tar.xz xesite-cc933b31fd23bb06e95bf41f848a1c99353d44ae.zip | |
Start version 3 (#573)
* Start version 3
* Change version to 3.0.0 in Cargo.toml
* Add metadata for series
* Change types for signal boosts
* Add start of LaTeX resume generation at Nix time
* Add start of proper author tagging for posts in JSONFeed and ldjson
* Convert templates to use Maud
* Add start of dynamic resume generation from dhall
* Make patrons page embed thumbnails
TODO:
* [ ] Remove the rest of the old templates
* [ ] Bring in Xeact for the share on mastodon button
* [ ] Site update post
Signed-off-by: Xe <me@christine.website>
* fix nix builds
Signed-off-by: Xe Iaso <me@christine.website>
* fix dhall build
Signed-off-by: Xe Iaso <me@christine.website>
* fix non-flakes build
Signed-off-by: Xe Iaso <me@christine.website>
* make new mastodon share button
Signed-off-by: Xe Iaso <me@christine.website>
* remove the rest of the ructe templates that I can remove
Signed-off-by: Xe Iaso <me@christine.website>
* refactor blogposts to its own file
Signed-off-by: Xe Iaso <me@christine.website>
* move resume to be generated by nix
Signed-off-by: Xe Iaso <me@christine.website>
* write article
Signed-off-by: Xe Iaso <me@christine.website>
* blog/site-update-v3: hero image
Signed-off-by: Xe Iaso <me@christine.website>
* add site update series tag to site updates
Signed-off-by: Xe Iaso <me@christine.website>
Signed-off-by: Xe <me@christine.website>
Signed-off-by: Xe Iaso <me@christine.website>
Diffstat (limited to 'src/handlers')
| -rw-r--r-- | src/handlers/blog.rs | 66 | ||||
| -rw-r--r-- | src/handlers/gallery.rs | 28 | ||||
| -rw-r--r-- | src/handlers/mod.rs | 77 | ||||
| -rw-r--r-- | src/handlers/talks.rs | 28 |
4 files changed, 89 insertions, 110 deletions
diff --git a/src/handlers/blog.rs b/src/handlers/blog.rs index 012a7ad..feeab44 100644 --- a/src/handlers/blog.rs +++ b/src/handlers/blog.rs @@ -1,14 +1,15 @@ use super::Result; -use crate::{app::State, post::Post, templates}; +use crate::{app::State, post::Post, tmpl}; use axum::{ extract::{Extension, Path}, - response::Html, + http::StatusCode, }; use http::HeaderMap; use lazy_static::lazy_static; +use maud::Markup; use prometheus::{opts, register_int_counter_vec, IntCounterVec}; use std::sync::Arc; -use tracing::{error, instrument}; +use tracing::instrument; lazy_static! { static ref HIT_COUNTER: IntCounterVec = register_int_counter_vec!( @@ -19,40 +20,27 @@ lazy_static! { } #[instrument(skip(state))] -pub async fn index(Extension(state): Extension<Arc<State>>) -> Result { +pub async fn index(Extension(state): Extension<Arc<State>>) -> Result<Markup> { let state = state.clone(); - let mut result: Vec<u8> = vec![]; - templates::blogindex_html(&mut result, state.blog.clone())?; - Ok(Html(result)) + let result = tmpl::post_index(&state.blog, "Blogposts", true); + Ok(result) } #[instrument(skip(state))] -pub async fn series(Extension(state): Extension<Arc<State>>) -> Result { +pub async fn series(Extension(state): Extension<Arc<State>>) -> Result<Markup> { let state = state.clone(); - let mut series: Vec<String> = vec![]; - let mut result: Vec<u8> = vec![]; - for post in &state.blog { - if post.front_matter.series.is_some() { - series.push(post.front_matter.series.as_ref().unwrap().clone()); - } - } - - series.sort(); - series.dedup(); - - templates::series_html(&mut result, series)?; - Ok(Html(result)) + Ok(tmpl::blog_series(&state.cfg.clone().series_descriptions)) } #[instrument(skip(state))] pub async fn series_view( Path(series): Path<String>, Extension(state): Extension<Arc<State>>, -) -> Result { +) -> (StatusCode, Markup) { let state = state.clone(); + let cfg = state.cfg.clone(); let mut posts: Vec<Post> = vec![]; - let mut result: Vec<u8> = vec![]; for post in &state.blog { if post.front_matter.series.is_none() { @@ -64,13 +52,25 @@ pub async fn series_view( posts.push(post.clone()); } + posts.reverse(); + + let desc = cfg.series_desc_map.get(&series); + if posts.len() == 0 { - error!("series not found"); - return Err(super::Error::SeriesNotFound(series)); + ( + StatusCode::NOT_FOUND, + tmpl::error(format!("series not found: {series}")), + ) + } else { + if let Some(desc) = desc { + (StatusCode::OK, tmpl::series_view(&series, desc, &posts)) + } else { + ( + StatusCode::INTERNAL_SERVER_ERROR, + tmpl::error(format!("series metadata in dhall not found: {series}")), + ) + } } - - templates::series_posts_html(&mut result, series, &posts).unwrap(); - Ok(Html(result)) } #[instrument(skip(state, headers))] @@ -78,7 +78,7 @@ pub async fn post_view( Path(name): Path<String>, Extension(state): Extension<Arc<State>>, headers: HeaderMap, -) -> Result { +) -> Result<(StatusCode, Markup)> { let mut want: Option<Post> = None; let want_link = format!("blog/{}", name); @@ -96,15 +96,13 @@ pub async fn post_view( }; match want { - None => Err(super::Error::PostNotFound(name)), + None => Ok((StatusCode::NOT_FOUND, tmpl::not_found(want_link))), Some(post) => { HIT_COUNTER .with_label_values(&[name.clone().as_str()]) .inc(); - let body = templates::Html(post.body_html.clone()); - let mut result: Vec<u8> = vec![]; - templates::blogpost_html(&mut result, post, body, referer)?; - Ok(Html(result)) + let body = maud::PreEscaped(&post.body_html); + Ok((StatusCode::OK, tmpl::blog::blog(&post, body, referer))) } } } diff --git a/src/handlers/gallery.rs b/src/handlers/gallery.rs index ae6c411..25c8dfa 100644 --- a/src/handlers/gallery.rs +++ b/src/handlers/gallery.rs @@ -1,10 +1,8 @@ -use super::{Error::*, Result}; -use crate::{app::State, post::Post, templates}; -use axum::{ - extract::{Extension, Path}, - response::Html, -}; +use crate::{app::State, post::Post, tmpl}; +use axum::extract::{Extension, Path}; +use http::StatusCode; use lazy_static::lazy_static; +use maud::Markup; use prometheus::{opts, register_int_counter_vec, IntCounterVec}; use std::sync::Arc; use tracing::instrument; @@ -18,36 +16,32 @@ lazy_static! { } #[instrument(skip(state))] -pub async fn index(Extension(state): Extension<Arc<State>>) -> Result { +pub async fn index(Extension(state): Extension<Arc<State>>) -> Markup { let state = state.clone(); - let mut result: Vec<u8> = vec![]; - templates::galleryindex_html(&mut result, state.gallery.clone())?; - Ok(Html(result)) + tmpl::gallery_index(&state.gallery) } #[instrument(skip(state))] pub async fn post_view( Path(name): Path<String>, Extension(state): Extension<Arc<State>>, -) -> Result { +) -> (StatusCode, Markup) { let mut want: Option<Post> = None; + let link = format!("gallery/{}", name); for post in &state.gallery { - if post.link == format!("gallery/{}", name) { + if post.link == link { want = Some(post.clone()); } } match want { - None => Err(PostNotFound(name)), + None => (StatusCode::NOT_FOUND, tmpl::not_found(link)), Some(post) => { HIT_COUNTER .with_label_values(&[name.clone().as_str()]) .inc(); - let body = templates::Html(post.body_html.clone()); - let mut result: Vec<u8> = vec![]; - templates::gallerypost_html(&mut result, post, body)?; - Ok(Html(result)) + (StatusCode::OK, tmpl::blog::gallery(&post)) } } } diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs index 37fcac1..a20d654 100644 --- a/src/handlers/mod.rs +++ b/src/handlers/mod.rs @@ -1,4 +1,4 @@ -use crate::{app::State, templates}; +use crate::{app::State, tmpl}; use axum::{ body, extract::Extension, @@ -7,6 +7,7 @@ use axum::{ }; use chrono::{Datelike, Timelike, Utc, Weekday}; use lazy_static::lazy_static; +use maud::Markup; use prometheus::{opts, register_int_counter_vec, IntCounterVec}; use std::sync::Arc; use tracing::instrument; @@ -67,82 +68,74 @@ lazy_static! { }; } -#[instrument] -pub async fn index() -> Result { +#[instrument(skip(state))] +pub async fn index(Extension(state): Extension<Arc<State>>) -> Result<Markup> { HIT_COUNTER.with_label_values(&["index"]).inc(); - let mut result: Vec<u8> = vec![]; - templates::index_html(&mut result)?; - Ok(Html(result)) + let state = state.clone(); + let cfg = state.cfg.clone(); + + Ok(tmpl::index(&cfg.default_author, &cfg.notable_projects)) } -#[instrument] -pub async fn contact() -> Result { +#[instrument(skip(state))] +pub async fn contact(Extension(state): Extension<Arc<State>>) -> Markup { HIT_COUNTER.with_label_values(&["contact"]).inc(); - let mut result: Vec<u8> = vec![]; - templates::contact_html(&mut result)?; - Ok(Html(result)) + let state = state.clone(); + let cfg = state.cfg.clone(); + + crate::tmpl::contact(&cfg.contact_links) } #[instrument] -pub async fn feeds() -> Result { +pub async fn feeds() -> Markup { HIT_COUNTER.with_label_values(&["feeds"]).inc(); - let mut result: Vec<u8> = vec![]; - templates::feeds_html(&mut result)?; - Ok(Html(result)) + crate::tmpl::feeds() } #[axum_macros::debug_handler] #[instrument(skip(state))] -pub async fn salary_transparency(Extension(state): Extension<Arc<State>>) -> Result { +pub async fn salary_transparency(Extension(state): Extension<Arc<State>>) -> Result<Markup> { HIT_COUNTER .with_label_values(&["salary_transparency"]) .inc(); let state = state.clone(); - let mut result: Vec<u8> = vec![]; - templates::salary_transparency(&mut result, state.cfg.clone())?; - Ok(Html(result)) + let cfg = state.cfg.clone(); + + Ok(tmpl::salary_transparency(&cfg.job_history)) } #[axum_macros::debug_handler] -#[instrument(skip(state))] -pub async fn resume(Extension(state): Extension<Arc<State>>) -> Result { +pub async fn resume() -> Markup { HIT_COUNTER.with_label_values(&["resume"]).inc(); - let state = state.clone(); - let mut result: Vec<u8> = vec![]; - templates::resume_html(&mut result, templates::Html(state.resume.clone()))?; - Ok(Html(result)) + + tmpl::resume() } #[instrument(skip(state))] -pub async fn patrons(Extension(state): Extension<Arc<State>>) -> Result { +pub async fn patrons(Extension(state): Extension<Arc<State>>) -> (StatusCode, Markup) { HIT_COUNTER.with_label_values(&["patrons"]).inc(); let state = state.clone(); - let mut result: Vec<u8> = vec![]; match &state.patrons { - None => Err(Error::NoPatrons), - Some(patrons) => { - templates::patrons_html(&mut result, patrons.clone())?; - Ok(Html(result)) - } + None => ( + StatusCode::INTERNAL_SERVER_ERROR, + tmpl::error("Patreon API config is broken, no patrons in ram"), + ), + Some(patrons) => (StatusCode::IM_A_TEAPOT, tmpl::patrons(&patrons)), } } #[axum_macros::debug_handler] #[instrument(skip(state))] -pub async fn signalboost(Extension(state): Extension<Arc<State>>) -> Result { +pub async fn signalboost(Extension(state): Extension<Arc<State>>) -> Markup { HIT_COUNTER.with_label_values(&["signalboost"]).inc(); let state = state.clone(); - let mut result: Vec<u8> = vec![]; - templates::signalboost_html(&mut result, state.signalboost.clone())?; - Ok(Html(result)) + tmpl::signalboost(&state.signalboost) } #[instrument] -pub async fn not_found() -> Result { +pub async fn not_found(uri: axum::http::Uri) -> (StatusCode, Markup) { HIT_COUNTER.with_label_values(&["not_found"]).inc(); - let mut result: Vec<u8> = vec![]; - templates::notfound_html(&mut result, "some path".into())?; - Ok(Html(result)) + (StatusCode::NOT_FOUND, tmpl::not_found(uri.path())) } #[derive(Debug, thiserror::Error)] @@ -170,8 +163,8 @@ pub type Result<T = Html<Vec<u8>>> = std::result::Result<T, Error>; impl IntoResponse for Error { fn into_response(self) -> Response { - let mut result: Vec<u8> = vec![]; - templates::error_html(&mut result, format!("{}", self)).unwrap(); + let result = tmpl::error(format!("{}", self)); + let result = result.0; let body = body::boxed(body::Full::from(result)); diff --git a/src/handlers/talks.rs b/src/handlers/talks.rs index 59d8676..262e481 100644 --- a/src/handlers/talks.rs +++ b/src/handlers/talks.rs @@ -1,11 +1,9 @@ -use super::{Error::*, Result}; -use crate::{app::State, post::Post, templates}; -use axum::{ - extract::{Extension, Path}, - response::Html, -}; -use http::header::HeaderMap; +use super::Result; +use crate::{app::State, post::Post, tmpl}; +use axum::extract::{Extension, Path}; +use http::{header::HeaderMap, StatusCode}; use lazy_static::lazy_static; +use maud::Markup; use prometheus::{opts, register_int_counter_vec, IntCounterVec}; use std::sync::Arc; use tracing::instrument; @@ -19,11 +17,9 @@ lazy_static! { } #[instrument(skip(state))] -pub async fn index(Extension(state): Extension<Arc<State>>) -> Result { +pub async fn index(Extension(state): Extension<Arc<State>>) -> Result<Markup> { let state = state.clone(); - let mut result: Vec<u8> = vec![]; - templates::talkindex_html(&mut result, state.talks.clone())?; - Ok(Html(result)) + Ok(tmpl::post_index(&state.talks, "Talks", false)) } #[instrument(skip(state, headers))] @@ -31,7 +27,7 @@ pub async fn post_view( Path(name): Path<String>, Extension(state): Extension<Arc<State>>, headers: HeaderMap, -) -> Result { +) -> Result<(StatusCode, Markup)> { let mut want: Option<Post> = None; let want_link = format!("talks/{}", name); @@ -49,15 +45,13 @@ pub async fn post_view( }; match want { - None => Err(PostNotFound(name).into()), + None => Ok((StatusCode::NOT_FOUND, tmpl::not_found(want_link))), Some(post) => { HIT_COUNTER .with_label_values(&[name.clone().as_str()]) .inc(); - let body = templates::Html(post.body_html.clone()); - let mut result: Vec<u8> = vec![]; - templates::talkpost_html(&mut result, post, body, referer)?; - Ok(Html(result)) + let body = maud::PreEscaped(&post.body_html); + Ok((StatusCode::OK, tmpl::blog::talk(&post, body, referer))) } } } |
