diff --git a/crates/lib/page/src/page.rs b/crates/lib/page/src/page.rs index 82aff76..df6c20c 100644 --- a/crates/lib/page/src/page.rs +++ b/crates/lib/page/src/page.rs @@ -15,7 +15,7 @@ pub struct PageMetadata { pub author: Option, pub description: Option, pub image: Option, - pub slug: Option, + pub backlinks: Option, } impl Default for PageMetadata { @@ -25,7 +25,7 @@ impl Default for PageMetadata { author: None, description: None, image: None, - slug: None, + backlinks: None, } } } diff --git a/crates/lib/page/src/requestcontext.rs b/crates/lib/page/src/requestcontext.rs index d1ee3d8..565a848 100644 --- a/crates/lib/page/src/requestcontext.rs +++ b/crates/lib/page/src/requestcontext.rs @@ -3,6 +3,7 @@ use axum::http::HeaderMap; #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct RequestContext { pub client_info: ClientInfo, + pub route: String, } // diff --git a/crates/lib/page/src/server.rs b/crates/lib/page/src/server.rs index 5e73dbb..3a674a7 100644 --- a/crates/lib/page/src/server.rs +++ b/crates/lib/page/src/server.rs @@ -170,7 +170,10 @@ impl PageServer { device_type = ?client_info.device_type ); - let req_ctx = RequestContext { client_info }; + let req_ctx = RequestContext { + client_info, + route: format!("/{route}"), + }; let cache_key = (route.clone(), req_ctx.clone()); let now = Utc::now(); diff --git a/crates/service/service-webpage/src/components/md.rs b/crates/service/service-webpage/src/components/md.rs index f57ef5f..3adb068 100644 --- a/crates/service/service-webpage/src/components/md.rs +++ b/crates/service/service-webpage/src/components/md.rs @@ -5,12 +5,11 @@ use markdown_it::parser::core::Root; use markdown_it::parser::inline::{InlineRule, InlineState}; use markdown_it::{MarkdownIt, Node, NodeValue, Renderer}; use maud::{Markup, PreEscaped, Render, html}; -use page::{Page, PageMetadata}; +use page::{Page, PageMetadata, RequestContext}; use std::str::FromStr; use crate::components::fa::FAIcon; use crate::components::mangle::{MangledBetaEmail, MangledGoogleEmail}; -use crate::components::misc::Backlinks; lazy_static! { static ref MdParser: MarkdownIt = { @@ -115,12 +114,13 @@ pub fn page_from_markdown(md: impl Into, default_image: Option) Page { meta, - generate_html: Box::new(move |page, _| { + generate_html: Box::new(move |page, ctx| { let html = html.clone(); + Box::pin(async move { html! { - @if let Some(slug) = &page.meta.slug { - (Backlinks(&[("/", "home")], slug)) + @if let Some(backlinks) = backlinks(page, ctx) { + (backlinks) } (html) @@ -132,6 +132,36 @@ pub fn page_from_markdown(md: impl Into, default_image: Option) } } +pub fn backlinks(page: &Page, ctx: &RequestContext) -> Option { + let mut last = None; + let mut backlinks = vec![("/", "home")]; + + if page.meta.backlinks.unwrap_or(false) { + let mut segments = ctx.route.split("/").skip(1).collect::>(); + last = segments.pop(); + + let mut end = 0; + for s in segments { + end += s.len(); + backlinks.push((&ctx.route[0..=end], s)); + end += 1; // trailing slash + } + } + + last.map(|last| { + html! { + div { + @for (url, text) in backlinks { + a href=(url) style="padding-left:5pt;padding-right:5pt;" { (text) } + "/" + } + + span style="color:var(--metaColor);padding-left:5pt;padding-right:5pt;" { (last) } + } + } + }) +} + // // MARK: extensions // diff --git a/crates/service/service-webpage/src/components/misc.rs b/crates/service/service-webpage/src/components/misc.rs index f6c0c8d..53b73c0 100644 --- a/crates/service/service-webpage/src/components/misc.rs +++ b/crates/service/service-webpage/src/components/misc.rs @@ -15,20 +15,3 @@ impl Render for FarLink<'_, T> { ) } } - -pub struct Backlinks<'a>(pub &'a [(&'a str, &'a str)], pub &'a str); - -impl Render for Backlinks<'_> { - fn render(&self) -> Markup { - html! { - div { - @for (url, text) in self.0 { - a href=(url) style="padding-left:5pt;padding-right:5pt;" { (text) } - "/" - } - - span style="color:var(--metaColor);padding-left:5pt;padding-right:5pt;" { (self.1) } - } - } - } -} diff --git a/crates/service/service-webpage/src/pages/betalupi.md b/crates/service/service-webpage/src/pages/betalupi.md index c93abaf..88e6ef3 100644 --- a/crates/service/service-webpage/src/pages/betalupi.md +++ b/crates/service/service-webpage/src/pages/betalupi.md @@ -1,7 +1,7 @@ +++ title = "What's a \"betalupi?\"" author = "Mark" -slug = "whats-a-betalupi" +backlinks = true +++ [es]: https://github.com/endless-sky/endless-sky diff --git a/crates/service/service-webpage/src/pages/handouts.md b/crates/service/service-webpage/src/pages/handouts.md index b44b10d..ceda1c3 100644 --- a/crates/service/service-webpage/src/pages/handouts.md +++ b/crates/service/service-webpage/src/pages/handouts.md @@ -1,7 +1,7 @@ +++ title = "Mark's Handouts" author = "Mark" -slug = "handouts" +backlinks = true +++ # Mark's Handouts diff --git a/crates/service/service-webpage/src/pages/handouts.rs b/crates/service/service-webpage/src/pages/handouts.rs index 90e289b..cf27b36 100644 --- a/crates/service/service-webpage/src/pages/handouts.rs +++ b/crates/service/service-webpage/src/pages/handouts.rs @@ -14,8 +14,8 @@ use tracing::{debug, warn}; use crate::{ components::{ - md::{Markdown, meta_from_markdown}, - misc::{Backlinks, FarLink}, + md::{Markdown, backlinks, meta_from_markdown}, + misc::FarLink, }, routes::assets::Image_Icon, }; @@ -202,7 +202,7 @@ pub fn handouts() -> Page { meta, html_ttl: Some(TimeDelta::seconds(300)), - generate_html: Box::new(move |page, req_ctx| { + generate_html: Box::new(move |page, ctx| { let html = html.clone(); // TODO: find a way to not clone here let index = index.clone(); Box::pin(async move { @@ -222,7 +222,7 @@ pub fn handouts() -> Page { }; let warmups = match &*handouts { - Ok(handouts) => build_list_for_group(handouts, "Warm-Ups", req_ctx), + Ok(handouts) => build_list_for_group(handouts, "Warm-Ups", ctx), Err(error) => { warn!("Could not load handout index: {error:?}"); fallback.clone() @@ -230,13 +230,13 @@ pub fn handouts() -> Page { }; let advanced = match &*handouts { - Ok(handouts) => build_list_for_group(handouts, "Advanced", req_ctx), + Ok(handouts) => build_list_for_group(handouts, "Advanced", ctx), Err(_) => fallback, }; html! { - @if let Some(slug) = &page.meta.slug { - (Backlinks(&[("/", "home")], slug)) + @if let Some(backlinks) = backlinks(page, ctx) { + (backlinks) } (html) diff --git a/crates/service/service-webpage/src/pages/htwah-typesetting.md b/crates/service/service-webpage/src/pages/htwah-typesetting.md index 4cd94ee..eb75c5c 100644 --- a/crates/service/service-webpage/src/pages/htwah-typesetting.md +++ b/crates/service/service-webpage/src/pages/htwah-typesetting.md @@ -1,9 +1,7 @@ +++ title = "HtWaH: Typesetting" author = "Mark" - -# TODO: many slugs, htwah/typesetting -slug = "handouts" +backlinks = true +++ ## Table of Contents diff --git a/crates/service/service-webpage/src/pages/index.rs b/crates/service/service-webpage/src/pages/index.rs index 1c60a3e..1ebe8d0 100644 --- a/crates/service/service-webpage/src/pages/index.rs +++ b/crates/service/service-webpage/src/pages/index.rs @@ -19,7 +19,7 @@ pub fn index() -> Page { author: Some("Mark".into()), description: Some("Description".into()), image: Some(Image_Icon::URL.into()), - slug: None, + backlinks: Some(false), }, generate_html: Box::new(move |_page, _| { diff --git a/crates/service/service-webpage/src/pages/links.md b/crates/service/service-webpage/src/pages/links.md index 96d2233..3f62bb3 100644 --- a/crates/service/service-webpage/src/pages/links.md +++ b/crates/service/service-webpage/src/pages/links.md @@ -1,7 +1,7 @@ +++ title = "Links" author = "Mark" -slug = "links" +backlinks = true +++ diff --git a/crates/service/service-webpage/src/routes/mod.rs b/crates/service/service-webpage/src/routes/mod.rs index 12c235c..9eb7e47 100644 --- a/crates/service/service-webpage/src/routes/mod.rs +++ b/crates/service/service-webpage/src/routes/mod.rs @@ -26,7 +26,7 @@ fn build_server() -> Arc { .add_page("/links", pages::links()) .add_page("/whats-a-betalupi", pages::betalupi()) .add_page("/handouts", pages::handouts()) - .add_page("/htwah", pages::htwah_typesetting()); + .add_page("/htwah/typesetting", pages::htwah_typesetting()); server }