Generic servable
Some checks failed
CI / Check typos (push) Successful in 8s
CI / Check links (push) Failing after 11s
CI / Clippy (push) Successful in 53s
CI / Build and test (push) Successful in 1m10s
CI / Build container (push) Successful in 54s
CI / Deploy on waypoint (push) Successful in 43s
Some checks failed
CI / Check typos (push) Successful in 8s
CI / Check links (push) Failing after 11s
CI / Clippy (push) Successful in 53s
CI / Build and test (push) Successful in 1m10s
CI / Build container (push) Successful in 54s
CI / Deploy on waypoint (push) Successful in 43s
This commit is contained in:
@@ -2,7 +2,8 @@ use lazy_static::lazy_static;
|
||||
use markdown_it::generics::inline::full_link;
|
||||
use markdown_it::{MarkdownIt, Node};
|
||||
use maud::{Markup, PreEscaped, Render, html};
|
||||
use page::{Page, PageMetadata, RequestContext};
|
||||
use page::RequestContext;
|
||||
use page::page::{Page, PageMetadata};
|
||||
|
||||
use crate::components::md::emote::InlineEmote;
|
||||
use crate::components::md::frontmatter::{TomlFrontMatter, YamlFrontMatter};
|
||||
@@ -101,43 +102,6 @@ pub fn meta_from_markdown(root_node: &Node) -> Result<Option<PageMetadata>, toml
|
||||
.map_or(Ok(None), |v| v.map(Some))
|
||||
}
|
||||
|
||||
pub fn page_from_markdown(md: impl Into<String>, default_image: Option<String>) -> Page {
|
||||
let md: String = md.into();
|
||||
let md = Markdown::parse(&md);
|
||||
|
||||
let mut meta = meta_from_markdown(&md)
|
||||
.unwrap_or(Some(PageMetadata {
|
||||
title: "Invalid frontmatter!".into(),
|
||||
..Default::default()
|
||||
}))
|
||||
.unwrap_or_default();
|
||||
|
||||
if meta.image.is_none() {
|
||||
meta.image = default_image
|
||||
}
|
||||
|
||||
let html = PreEscaped(md.render());
|
||||
|
||||
Page {
|
||||
meta,
|
||||
generate_html: Box::new(move |page, ctx| {
|
||||
let html = html.clone();
|
||||
|
||||
Box::pin(async move {
|
||||
html! {
|
||||
@if let Some(backlinks) = backlinks(page, ctx) {
|
||||
(backlinks)
|
||||
}
|
||||
|
||||
(html)
|
||||
}
|
||||
})
|
||||
}),
|
||||
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn backlinks(page: &Page, ctx: &RequestContext) -> Option<Markup> {
|
||||
let mut last = None;
|
||||
let mut backlinks = vec![("/", "home")];
|
||||
|
||||
@@ -7,7 +7,7 @@ use std::{
|
||||
use assetserver::Asset;
|
||||
use chrono::{DateTime, TimeDelta, Utc};
|
||||
use maud::{Markup, PreEscaped, html};
|
||||
use page::{DeviceType, Page, RequestContext};
|
||||
use page::{DeviceType, RequestContext, page::Page};
|
||||
use parking_lot::Mutex;
|
||||
use serde::Deserialize;
|
||||
use tracing::{debug, warn};
|
||||
@@ -17,6 +17,7 @@ use crate::{
|
||||
md::{Markdown, backlinks, meta_from_markdown},
|
||||
misc::FarLink,
|
||||
},
|
||||
pages::page_wrapper,
|
||||
routes::assets::Image_Icon,
|
||||
};
|
||||
|
||||
@@ -234,7 +235,7 @@ pub fn handouts() -> Page {
|
||||
Err(_) => fallback,
|
||||
};
|
||||
|
||||
html! {
|
||||
let inner = html! {
|
||||
@if let Some(backlinks) = backlinks(page, ctx) {
|
||||
(backlinks)
|
||||
}
|
||||
@@ -260,7 +261,9 @@ pub fn handouts() -> Page {
|
||||
)))
|
||||
(advanced)
|
||||
br {}
|
||||
}
|
||||
};
|
||||
|
||||
page_wrapper(&page.meta, inner).await
|
||||
})
|
||||
}),
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use assetserver::Asset;
|
||||
use maud::html;
|
||||
use page::{Page, PageMetadata};
|
||||
use page::page::{Page, PageMetadata};
|
||||
|
||||
use crate::{
|
||||
components::{
|
||||
@@ -9,6 +9,7 @@ use crate::{
|
||||
md::Markdown,
|
||||
misc::FarLink,
|
||||
},
|
||||
pages::page_wrapper,
|
||||
routes::assets::{Image_Cover, Image_Icon},
|
||||
};
|
||||
|
||||
@@ -22,9 +23,9 @@ pub fn index() -> Page {
|
||||
backlinks: Some(false),
|
||||
},
|
||||
|
||||
generate_html: Box::new(move |_page, _| {
|
||||
generate_html: Box::new(move |page, _ctx| {
|
||||
Box::pin(async {
|
||||
html! {
|
||||
let inner = html! {
|
||||
h2 id="about" { "About" }
|
||||
|
||||
div {
|
||||
@@ -70,9 +71,12 @@ pub fn index() -> Page {
|
||||
}
|
||||
|
||||
(Markdown(include_str!("index.md")))
|
||||
}
|
||||
};
|
||||
|
||||
page_wrapper(&page.meta, inner).await
|
||||
})
|
||||
}),
|
||||
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
use assetserver::Asset;
|
||||
use page::Page;
|
||||
use chrono::TimeDelta;
|
||||
use maud::{DOCTYPE, Markup, PreEscaped, html};
|
||||
use page::page::{Page, PageMetadata};
|
||||
use std::pin::Pin;
|
||||
|
||||
use crate::{components::md::page_from_markdown, routes::assets::Image_Icon};
|
||||
use crate::{
|
||||
components::{
|
||||
md::{Markdown, backlinks, meta_from_markdown},
|
||||
misc::FarLink,
|
||||
},
|
||||
routes::assets::{Image_Icon, Styles_Main},
|
||||
};
|
||||
|
||||
mod handouts;
|
||||
mod index;
|
||||
@@ -33,3 +42,97 @@ pub fn htwah_typesetting() -> Page {
|
||||
Some(Image_Icon::URL.to_owned()),
|
||||
)
|
||||
}
|
||||
|
||||
//
|
||||
// MARK: md
|
||||
//
|
||||
|
||||
fn page_from_markdown(md: impl Into<String>, default_image: Option<String>) -> Page {
|
||||
let md: String = md.into();
|
||||
let md = Markdown::parse(&md);
|
||||
|
||||
let mut meta = meta_from_markdown(&md)
|
||||
.unwrap_or(Some(PageMetadata {
|
||||
title: "Invalid frontmatter!".into(),
|
||||
..Default::default()
|
||||
}))
|
||||
.unwrap_or_default();
|
||||
|
||||
if meta.image.is_none() {
|
||||
meta.image = default_image
|
||||
}
|
||||
|
||||
let html = PreEscaped(md.render());
|
||||
|
||||
Page {
|
||||
meta,
|
||||
|
||||
html_ttl: Some(TimeDelta::seconds(60 * 24 * 30)),
|
||||
generate_html: Box::new(move |page, ctx| {
|
||||
let html = html.clone();
|
||||
|
||||
Box::pin(async move {
|
||||
let inner = html! {
|
||||
@if let Some(backlinks) = backlinks(page, ctx) {
|
||||
(backlinks)
|
||||
}
|
||||
|
||||
(html)
|
||||
};
|
||||
|
||||
page_wrapper(&page.meta, inner).await
|
||||
})
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// MARK: wrapper
|
||||
//
|
||||
|
||||
pub fn page_wrapper<'a>(
|
||||
meta: &'a PageMetadata,
|
||||
inner: Markup,
|
||||
) -> Pin<Box<dyn Future<Output = Markup> + 'a + Send + Sync>> {
|
||||
Box::pin(async move {
|
||||
html! {
|
||||
(DOCTYPE)
|
||||
html {
|
||||
head {
|
||||
meta charset="UTF" {}
|
||||
meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" {}
|
||||
meta content="text/html; charset=UTF-8" http-equiv="content-type" {}
|
||||
meta property="og:type" content="website" {}
|
||||
|
||||
link rel="stylesheet" href=(Styles_Main::URL) {}
|
||||
|
||||
(&meta)
|
||||
title { (PreEscaped(meta.title.clone())) }
|
||||
}
|
||||
|
||||
body {
|
||||
div class="wrapper" {
|
||||
main { (inner) }
|
||||
|
||||
footer {
|
||||
hr class = "footline" {}
|
||||
div class = "footContainer" {
|
||||
p {
|
||||
"This site was built by hand using "
|
||||
(FarLink("https://rust-lang.org", "Rust"))
|
||||
", "
|
||||
(FarLink("https://maud.lambda.xyz", "Maud"))
|
||||
", "
|
||||
(FarLink("https://github.com/connorskees/grass", "Grass"))
|
||||
", and "
|
||||
(FarLink("https://docs.rs/axum/latest/axum", "Axum"))
|
||||
"."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
use std::{pin::Pin, sync::Arc};
|
||||
|
||||
use assetserver::Asset;
|
||||
use axum::Router;
|
||||
use maud::{DOCTYPE, Markup, PreEscaped, html};
|
||||
use page::{Page, PageServer, RequestContext};
|
||||
use page::{PageServer, redirect::Redirect};
|
||||
use std::sync::Arc;
|
||||
use tracing::info;
|
||||
|
||||
use crate::{components::misc::FarLink, pages, routes::assets::Styles_Main};
|
||||
use crate::pages;
|
||||
|
||||
pub mod assets;
|
||||
|
||||
@@ -20,63 +17,20 @@ pub(super) fn router() -> Router<()> {
|
||||
}
|
||||
|
||||
fn build_server() -> Arc<PageServer> {
|
||||
let server = PageServer::new(Box::new(page_wrapper));
|
||||
let server = PageServer::new();
|
||||
|
||||
#[expect(clippy::unwrap_used)]
|
||||
server
|
||||
.add_page("/", pages::index())
|
||||
.add_page("/links", pages::links())
|
||||
.add_page("/whats-a-betalupi", pages::betalupi())
|
||||
.add_page("/handouts", pages::handouts())
|
||||
.add_page("/htwah", Redirect::new("/handouts").unwrap())
|
||||
.add_page("/htwah/typesetting", pages::htwah_typesetting());
|
||||
|
||||
server
|
||||
}
|
||||
|
||||
fn page_wrapper<'a>(
|
||||
page: &'a Page,
|
||||
req_ctx: &'a RequestContext,
|
||||
) -> Pin<Box<dyn Future<Output = Markup> + 'a + Send + Sync>> {
|
||||
Box::pin(async move {
|
||||
html! {
|
||||
(DOCTYPE)
|
||||
html {
|
||||
head {
|
||||
meta charset="UTF" {}
|
||||
meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" {}
|
||||
meta content="text/html; charset=UTF-8" http-equiv="content-type" {}
|
||||
meta property="og:type" content="website" {}
|
||||
|
||||
link rel="stylesheet" href=(Styles_Main::URL) {}
|
||||
|
||||
(&page.meta)
|
||||
title { (PreEscaped(page.meta.title.clone())) }
|
||||
}
|
||||
|
||||
body {
|
||||
div class="wrapper" {
|
||||
main { ( page.generate_html(req_ctx).await ) }
|
||||
|
||||
footer {
|
||||
hr class = "footline" {}
|
||||
div class = "footContainer" {
|
||||
p {
|
||||
"This site was built by hand using "
|
||||
(FarLink("https://rust-lang.org", "Rust"))
|
||||
", "
|
||||
(FarLink("https://maud.lambda.xyz", "Maud"))
|
||||
", "
|
||||
(FarLink("https://github.com/connorskees/grass", "Grass"))
|
||||
", and "
|
||||
(FarLink("https://docs.rs/axum/latest/axum", "Axum"))
|
||||
"."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn server_builds_without_panic() {
|
||||
tokio::runtime::Builder::new_current_thread()
|
||||
|
||||
Reference in New Issue
Block a user