Added index
This commit is contained in:
56
crates/service-webpage/src/components/fa.rs
Normal file
56
crates/service-webpage/src/components/fa.rs
Normal file
@@ -0,0 +1,56 @@
|
||||
use maud::{Markup, Render, html};
|
||||
|
||||
#[expect(clippy::allow_attributes)]
|
||||
#[allow(dead_code)]
|
||||
pub enum FAIcon {
|
||||
Github,
|
||||
Git,
|
||||
Python,
|
||||
Rust,
|
||||
Discord,
|
||||
Instagram,
|
||||
|
||||
Link,
|
||||
Envelope,
|
||||
At,
|
||||
Key,
|
||||
SStar,
|
||||
RStar,
|
||||
Leaf,
|
||||
|
||||
Lock,
|
||||
Fire,
|
||||
Pen,
|
||||
Pencil,
|
||||
}
|
||||
|
||||
impl Render for FAIcon {
|
||||
fn render(&self) -> Markup {
|
||||
let classes = match self {
|
||||
Self::Github => "fa-brands fa-github",
|
||||
Self::Git => "fa-brands fa-git-alt",
|
||||
Self::Python => "fa-brands fa-python",
|
||||
Self::Rust => "fa-brands fa-rust",
|
||||
Self::Discord => "fa-brands fa-discord",
|
||||
Self::Instagram => "fa-brands fa-instagram",
|
||||
Self::Link => "fa-solid fa-link",
|
||||
Self::Envelope => "fa-solid fa-envelope",
|
||||
Self::At => "fa-solid fa-at",
|
||||
Self::Key => "fa-solid fa-key",
|
||||
Self::SStar => "fa-solid fa-star",
|
||||
Self::RStar => "fa-regular fa-star",
|
||||
Self::Leaf => "fa-regular fa-leaf",
|
||||
Self::Lock => "fa-solid fa-lock",
|
||||
Self::Fire => "fa-solid fa-fire",
|
||||
Self::Pen => "fa-solid fa-pen-nib",
|
||||
Self::Pencil => "fa-solid fa-pencil",
|
||||
};
|
||||
|
||||
html!(
|
||||
i
|
||||
class=(classes)
|
||||
style="margin-right:5pt" // TODO: configure, color
|
||||
{}
|
||||
)
|
||||
}
|
||||
}
|
||||
40
crates/service-webpage/src/components/mangle.rs
Normal file
40
crates/service-webpage/src/components/mangle.rs
Normal file
@@ -0,0 +1,40 @@
|
||||
use maud::{Markup, Render, html};
|
||||
|
||||
// TODO: turn these into one self-contained struct
|
||||
pub struct MangledBetaEmail {}
|
||||
|
||||
impl Render for MangledBetaEmail {
|
||||
fn render(&self) -> Markup {
|
||||
html!(
|
||||
span class="eobf eobf-beta" {
|
||||
i id="eobf-en" class="fas fa-envelope" style="margin-right: 5pt" {}
|
||||
i id="eobf-kb" class="fas fa-keyboard" style="margin-right: 5pt" {}
|
||||
span
|
||||
data-b="kra"
|
||||
data-a="c.ipula"
|
||||
data-h="Type this manually"
|
||||
style="unicode-bidi: bidi-override; direction: rtl;"
|
||||
{}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MangledGoogleEmail {}
|
||||
|
||||
impl Render for MangledGoogleEmail {
|
||||
fn render(&self) -> Markup {
|
||||
html!(
|
||||
span class="eobf eobf-goog" {
|
||||
i id="eobf-en" class="fas fa-envelope" style="margin-right: 5pt" {}
|
||||
i id="eobf-kb" class="fas fa-keyboard" style="margin-right: 5pt" {}
|
||||
span
|
||||
data-c="kra"
|
||||
data-b="rmn"
|
||||
data-a="c.lia"
|
||||
data-h="Type this manually"
|
||||
{}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
11
crates/service-webpage/src/components/md.rs
Normal file
11
crates/service-webpage/src/components/md.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
use maud::{Markup, PreEscaped, Render};
|
||||
|
||||
pub struct Markdown<'a>(pub &'a str);
|
||||
|
||||
impl Render for Markdown<'_> {
|
||||
fn render(&self) -> Markup {
|
||||
// TODO: cache, style
|
||||
let md = markdown::to_html(self.0);
|
||||
return PreEscaped(md);
|
||||
}
|
||||
}
|
||||
17
crates/service-webpage/src/components/misc.rs
Normal file
17
crates/service-webpage/src/components/misc.rs
Normal file
@@ -0,0 +1,17 @@
|
||||
use maud::{Markup, Render, html};
|
||||
|
||||
/// Shorthand for an `<a>` link that opens a new tab
|
||||
/// Values are (url, text)
|
||||
pub struct FarLink<'a, T: Render>(pub &'a str, pub T);
|
||||
|
||||
impl<T: Render> Render for FarLink<'_, T> {
|
||||
fn render(&self) -> Markup {
|
||||
html!(
|
||||
a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href=(self.0)
|
||||
{ (self.1) }
|
||||
)
|
||||
}
|
||||
}
|
||||
4
crates/service-webpage/src/components/mod.rs
Normal file
4
crates/service-webpage/src/components/mod.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
pub mod fa;
|
||||
pub mod mangle;
|
||||
pub mod md;
|
||||
pub mod misc;
|
||||
@@ -2,6 +2,7 @@ use axum::Router;
|
||||
use libservice::ToService;
|
||||
use utoipa::OpenApi;
|
||||
|
||||
mod components;
|
||||
mod routes;
|
||||
|
||||
pub struct WebpageService {}
|
||||
|
||||
315
crates/service-webpage/src/routes/index.rs
Normal file
315
crates/service-webpage/src/routes/index.rs
Normal file
@@ -0,0 +1,315 @@
|
||||
use assetserver::Asset;
|
||||
use macro_sass::sass;
|
||||
use maud::{DOCTYPE, Markup, PreEscaped, Render, html};
|
||||
|
||||
use crate::{
|
||||
components::{
|
||||
fa::FAIcon,
|
||||
mangle::{MangledBetaEmail, MangledGoogleEmail},
|
||||
md::Markdown,
|
||||
misc::FarLink,
|
||||
},
|
||||
routes::assets::{Image_Cover, Image_Icon},
|
||||
};
|
||||
|
||||
const CSS: &str = sass!("css/main.scss");
|
||||
|
||||
struct PageMetadata {
|
||||
/// Text shown in tab
|
||||
pub title: String,
|
||||
pub author: Option<String>,
|
||||
pub description: Option<String>,
|
||||
pub image: Option<String>,
|
||||
}
|
||||
|
||||
impl Render for PageMetadata {
|
||||
fn render(&self) -> Markup {
|
||||
let empty = String::new();
|
||||
let title = &self.title;
|
||||
let author = &self.author.as_ref().unwrap_or(&empty);
|
||||
let description = &self.description.as_ref().unwrap_or(&empty);
|
||||
let image = &self.image.as_ref().unwrap_or(&empty);
|
||||
|
||||
html!(
|
||||
meta property="og:site_name" content=(title) {}
|
||||
meta name="title" content=(title) {}
|
||||
meta property="og:title" content=(title) {}
|
||||
meta property="twitter:title" content=(title) {}
|
||||
|
||||
meta name="author" content=(author) {}
|
||||
|
||||
meta name="description" content=(description) {}
|
||||
meta property="og:description" content=(description) {}
|
||||
meta property="twitter:description" content=(description) {}
|
||||
|
||||
|
||||
meta content=(image) property="og:image" {}
|
||||
link rel="shortcut icon" href=(image) type="image/x-icon" {}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn index() -> Markup {
|
||||
let meta = PageMetadata {
|
||||
title: "Betalupi: About".into(),
|
||||
author: Some("Mark".into()),
|
||||
description: Some("Description".into()),
|
||||
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 {
|
||||
h2 id="about" { "About" }
|
||||
|
||||
div {
|
||||
img
|
||||
src=(Image_Cover::URL)
|
||||
style="float:left;margin:10px 10px 10px 10px;display:block;width:25%;"
|
||||
{}
|
||||
|
||||
div style="margin:2ex 1ex 2ex 1ex;display:inline-block;overflow:hidden;width:60%;" {
|
||||
"Welcome, you've reached Mark's main page. Here you'll find"
|
||||
" links to various projects I've worked on."
|
||||
|
||||
ul {
|
||||
li { (MangledBetaEmail {}) }
|
||||
li { (MangledGoogleEmail {}) }
|
||||
|
||||
li {
|
||||
(
|
||||
FarLink(
|
||||
"https://github.com/rm-dr",
|
||||
html!(
|
||||
(FAIcon::Github)
|
||||
"rm-dr"
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
li {
|
||||
(
|
||||
FarLink(
|
||||
"https://git.betalupi.com",
|
||||
html!(
|
||||
(FAIcon::Git)
|
||||
"git.betalupi.com"
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
br style="clear:both;" {}
|
||||
}
|
||||
|
||||
"Also see "
|
||||
a href="/whats-a-betalupi" { "what's a \"betalupi?\"" }
|
||||
|
||||
|
||||
(Markdown(concat!(
|
||||
"## Pages\n",
|
||||
" - [Handouts](/handouts): Math circle lessons I've written\n",
|
||||
" - [Links](/links): Interesting parts of the internet"
|
||||
)))
|
||||
|
||||
hr style="margin-top: 6rem; margin-bottom: 6rem" {}
|
||||
|
||||
h2 { "Projects" }
|
||||
ul {
|
||||
li {
|
||||
p {
|
||||
b { "RedoxOS" }
|
||||
", a general-purpose, microkernel-based operating system written in Rust. "
|
||||
|
||||
em { span style="color: var(--grey);" {"[enthusiast]"} }
|
||||
}
|
||||
|
||||
ul {
|
||||
li {
|
||||
span style="color: var(--grey);" {"Status: "}
|
||||
span style="color: var(--yellow);" {"Passive"}
|
||||
}
|
||||
|
||||
|
||||
li {
|
||||
span style="color: var(--grey);" {"Website: "}
|
||||
(
|
||||
FarLink(
|
||||
"https://www.redox-os.org",
|
||||
html!(
|
||||
(FAIcon::Link)
|
||||
"redox-os.org"
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
li {
|
||||
p {
|
||||
b { "Tectonic" }
|
||||
", the LaTeX engine that is pleasant to use. Experimental, but fully functional. "
|
||||
|
||||
em { span style="color: var(--grey);" {"[co-maintainer]"} }
|
||||
}
|
||||
|
||||
ul {
|
||||
li {
|
||||
span style="color: var(--grey);" {"Status: "}
|
||||
span style="color: var(--yellow);" {"Passive. "}
|
||||
(FarLink("https://github.com/typst/typst", "Typst"))
|
||||
" is better."
|
||||
}
|
||||
|
||||
|
||||
li {
|
||||
span style="color: var(--grey);" {"Main Repo: "}
|
||||
(
|
||||
FarLink(
|
||||
"https://github.com/tectonic-typesetting/tectonic",
|
||||
html!( (FAIcon::Github) "Tectonic" )
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
li {
|
||||
span style="color: var(--grey);" {"Bundle Tools: "}
|
||||
(
|
||||
FarLink(
|
||||
"https://github.com/tectonic-typesetting/tectonic-texlive-bundles",
|
||||
html!( (FAIcon::Github) "tectonic-texlive-bundles" )
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
li {
|
||||
p {
|
||||
b { "Daisy" }
|
||||
", a pretty TUI scientific calculator. "
|
||||
|
||||
em { span style="color: var(--grey);" {"[author]"} }
|
||||
}
|
||||
|
||||
ul {
|
||||
li {
|
||||
span style="color: var(--grey);" {"Status: "}
|
||||
span style="color: var(--orange);" {"Done. "}
|
||||
"Used this to learn Rust. "
|
||||
(FarLink("https://numbat.dev", "Numbat"))
|
||||
" is better."
|
||||
}
|
||||
|
||||
li {
|
||||
span style="color: var(--grey);" {"Repository: "}
|
||||
(
|
||||
FarLink(
|
||||
"https://github.com/rm-dr/daisy",
|
||||
html!( (FAIcon::Github) "rm-dr/daisy" )
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
li {
|
||||
span style="color: var(--grey);" {"Website: "}
|
||||
(
|
||||
FarLink(
|
||||
"https://daisy.betalupi.com",
|
||||
html!(
|
||||
(FAIcon::Link)
|
||||
"daisy.betalupi.com"
|
||||
)
|
||||
)
|
||||
)
|
||||
" (WASM demo)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
li {
|
||||
p {
|
||||
b { "Lamb" }
|
||||
", a lambda calculus engine. "
|
||||
|
||||
em { span style="color: var(--grey);" {"[author]"} }
|
||||
}
|
||||
|
||||
ul {
|
||||
li {
|
||||
span style="color: var(--grey);" {"Status: "}
|
||||
span style="color: var(--orange);" {"Done. "}
|
||||
"Fun little project."
|
||||
}
|
||||
|
||||
li {
|
||||
span style="color: var(--grey);" {"Repository: "}
|
||||
(
|
||||
FarLink(
|
||||
"https://github.com/rm-dr/lamb",
|
||||
html!( (FAIcon::Github) "rm-dr/lamb" )
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
li {
|
||||
span style="color: var(--grey);" {"PyPi: "}
|
||||
(
|
||||
FarLink(
|
||||
"https://pypi.org/project/lamb-engine",
|
||||
html!(
|
||||
(FAIcon::Python)
|
||||
"lamb-engine"
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
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,8 +1,10 @@
|
||||
use axum::Router;
|
||||
use axum::routing::get;
|
||||
use tracing::info;
|
||||
use utoipa::OpenApi;
|
||||
|
||||
mod assets;
|
||||
mod index;
|
||||
|
||||
#[derive(OpenApi)]
|
||||
#[openapi(tags(), paths(), components(schemas()))]
|
||||
@@ -12,5 +14,7 @@ pub(super) fn router() -> Router<()> {
|
||||
let (asset_prefix, asset_router) = assets::asset_router();
|
||||
info!("Serving assets at {asset_prefix}");
|
||||
|
||||
Router::new().nest(asset_prefix, asset_router)
|
||||
Router::new()
|
||||
.route("/", get(index::index))
|
||||
.nest(asset_prefix, asset_router)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user