diff --git a/crates/service-webpage/src/components/md.rs b/crates/service-webpage/src/components/md.rs index 777d691..e1ee6f4 100644 --- a/crates/service-webpage/src/components/md.rs +++ b/crates/service-webpage/src/components/md.rs @@ -1,11 +1,108 @@ +use markdown::{CompileOptions, Constructs, LineEnding, Options, ParseOptions}; use maud::{Markup, PreEscaped, Render}; pub struct Markdown<'a>(pub &'a str); +const OPTS: Options = Options { + parse: ParseOptions { + constructs: Constructs { + attention: true, + autolink: false, + block_quote: true, + character_escape: true, + character_reference: true, + code_indented: false, + code_fenced: true, + code_text: true, + definition: true, + frontmatter: false, + gfm_autolink_literal: true, + gfm_footnote_definition: false, + gfm_label_start_footnote: false, + gfm_strikethrough: false, + gfm_table: false, + gfm_task_list_item: false, + hard_break_escape: false, + hard_break_trailing: false, + heading_atx: true, + heading_setext: false, + label_start_image: false, + label_start_link: true, + label_end: true, + list_item: true, + math_flow: false, + math_text: false, + mdx_esm: false, + thematic_break: false, + + // INLINE HTML + html_flow: false, + html_text: false, + + // INLINE {} + mdx_expression_flow: true, + mdx_expression_text: true, + + // INLINE HTML (alternative) + mdx_jsx_flow: false, + mdx_jsx_text: false, + }, + + gfm_strikethrough_single_tilde: false, + math_text_single_dollar: false, + mdx_expression_parse: None, + mdx_esm_parse: None, + }, + + compile: CompileOptions { + allow_any_img_src: false, + allow_dangerous_html: false, + allow_dangerous_protocol: false, + default_line_ending: LineEnding::LineFeed, + gfm_footnote_back_label: None, + gfm_footnote_clobber_prefix: None, + gfm_footnote_label_attributes: None, + gfm_footnote_label_tag_name: None, + gfm_footnote_label: None, + gfm_task_list_item_checkable: false, + gfm_tagfilter: false, + }, +}; + impl Render for Markdown<'_> { fn render(&self) -> Markup { - // TODO: cache, style - let md = markdown::to_html(self.0); + // TODO: cache + + /* + let mut ast = markdown::to_mdast(MD_A, &opts.parse).unwrap(); + let walk = AstWalkMut::new(&mut ast); + + for i in walk { + match i { + AstWalkMutStep::Exit(node) => { + match node { + Node::MdxTextExpression(x) => { + println!("{x:?}"); + } + Node::MdxFlowExpression(x) => { + println!("{x:?}"); + } + _ => continue, + } + + *node = Node::Text(Text { + value: "LOL".to_owned(), + position: node.position().cloned(), + }) + } + _ => {} + } + } + + println!("{ast:?}"); + */ + + let md = markdown::to_html_with_options(self.0, &OPTS).unwrap(); return PreEscaped(md); } } diff --git a/crates/service-webpage/src/routes/betalupi.rs b/crates/service-webpage/src/routes/betalupi.rs new file mode 100644 index 0000000..d583950 --- /dev/null +++ b/crates/service-webpage/src/routes/betalupi.rs @@ -0,0 +1,101 @@ +use assetserver::Asset; +use macro_sass::sass; +use maud::{DOCTYPE, Markup, PreEscaped, html}; + +use crate::{ + components::{md::Markdown, misc::FarLink}, + routes::{ + assets::{Image_Betalupi, Image_Icon}, + index::PageMetadata, + }, +}; + +const CSS: &str = sass!("css/main.scss"); + +pub async fn betalupi() -> Markup { + let meta = PageMetadata { + title: "What's a \"betalupi?\"".into(), + author: Some("Mark".into()), + description: None, + image: Some(Image_Icon::URL.into()), + }; + + 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" {} + + (meta) + title { (PreEscaped(meta.title)) } + style { (PreEscaped(CSS)) } + } + + body { + div class="wrapper" { + main { + + // TODO: no metadata class, generate backlink array + div { + a href="/" style="padding-left:4pt;padding-right:4pt;" {"home"} + "/" + span class="metaData" style="padding-left:4pt;padding-right:4pt;" { "whats-a-betalupi" } + } + + (Markdown(MD_A)) + + br {} + + (Markdown(MD_B)) + + br {} + + img alt="betalupi map" class="image" src=(Image_Betalupi::URL) {} + } + + 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")) + "." + } + } + } + } + } + } + } +} + +const MD_A: &str = r#"[es]: https://github.com/endless-sky/endless-sky +[*Stellaris*]: https://www.paradoxinteractive.com/games/stellaris/about +[Arabic]: https://en.wikipedia.org/wiki/List_of_Arabic_star_names +[wiki-betalupi]: https://en.wikipedia.org/wiki/Beta_Lupi + +# What's a "betalupi?" + +Beta Lupi is a solar system on the [_Endless Sky_][es] galaxy map, +which is the first place I look whenever I need to name a server. + +Stellar names (especially those of [Arabic] origin) make pretty good hostnames: they're meaningless (in English), they sound interesting, and the "hyperlanes" that connect them in titles like [_Endless Sky_][es] and [*Stellaris*] look a lot like a network topology. + +Beta Lupi also happens to be a real star in the southern constellation of Lupus ([wiki][wiki-betalupi]), but that's not particularly important. + +A snippet of the [_Endless Sky_][es] map is below."#; + +const MD_B: &str = r#"**In other words:** Try finding a `.com` domain that... + +- Isn't already taken +- Doesn't sound awful +- Isn't owned by a scalper that's selling it for $300"#; diff --git a/crates/service-webpage/src/routes/index.rs b/crates/service-webpage/src/routes/index.rs index 2e08ef3..da1f753 100644 --- a/crates/service-webpage/src/routes/index.rs +++ b/crates/service-webpage/src/routes/index.rs @@ -14,7 +14,7 @@ use crate::{ const CSS: &str = sass!("css/main.scss"); -struct PageMetadata { +pub struct PageMetadata { /// Text shown in tab pub title: String, pub author: Option, diff --git a/crates/service-webpage/src/routes/mod.rs b/crates/service-webpage/src/routes/mod.rs index b2c8e75..295dee1 100644 --- a/crates/service-webpage/src/routes/mod.rs +++ b/crates/service-webpage/src/routes/mod.rs @@ -4,6 +4,7 @@ use tracing::info; use utoipa::OpenApi; mod assets; +mod betalupi; mod index; #[derive(OpenApi)] @@ -16,5 +17,6 @@ pub(super) fn router() -> Router<()> { Router::new() .route("/", get(index::index)) + .route("/whats-a-betalupi", get(betalupi::betalupi)) .nest(asset_prefix, asset_router) }