Reorganize
This commit is contained in:
87
crates/service/service-webpage/src/components/base.rs
Normal file
87
crates/service/service-webpage/src/components/base.rs
Normal file
@@ -0,0 +1,87 @@
|
||||
use macro_sass::sass;
|
||||
use maud::{DOCTYPE, Markup, PreEscaped, Render, html};
|
||||
|
||||
use crate::components::misc::FarLink;
|
||||
|
||||
pub struct PageMetadata {
|
||||
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" {}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const CSS: &str = sass!("css/main.scss");
|
||||
|
||||
pub struct BasePage<T: Render>(pub PageMetadata, pub T);
|
||||
|
||||
impl<T: Render> Render for BasePage<T> {
|
||||
fn render(&self) -> Markup {
|
||||
let meta = &self.0;
|
||||
|
||||
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.clone())) }
|
||||
style { (PreEscaped(CSS)) }
|
||||
}
|
||||
|
||||
body {
|
||||
div class="wrapper" {
|
||||
main { (self.1) }
|
||||
|
||||
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"))
|
||||
"."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
56
crates/service/service-webpage/src/components/fa.rs
Normal file
56
crates/service/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
|
||||
{}
|
||||
)
|
||||
}
|
||||
}
|
||||
39
crates/service/service-webpage/src/components/mangle.rs
Normal file
39
crates/service/service-webpage/src/components/mangle.rs
Normal file
@@ -0,0 +1,39 @@
|
||||
use maud::{Markup, Render, html};
|
||||
|
||||
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"
|
||||
{}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
106
crates/service/service-webpage/src/components/md.rs
Normal file
106
crates/service/service-webpage/src/components/md.rs
Normal file
@@ -0,0 +1,106 @@
|
||||
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 {
|
||||
/*
|
||||
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);
|
||||
}
|
||||
}
|
||||
17
crates/service/service-webpage/src/components/misc.rs
Normal file
17
crates/service/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) }
|
||||
)
|
||||
}
|
||||
}
|
||||
5
crates/service/service-webpage/src/components/mod.rs
Normal file
5
crates/service/service-webpage/src/components/mod.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
pub mod base;
|
||||
pub mod fa;
|
||||
pub mod mangle;
|
||||
pub mod md;
|
||||
pub mod misc;
|
||||
Reference in New Issue
Block a user