Markdown upgrades

This commit is contained in:
2025-11-03 23:06:30 -08:00
parent c4f6b8d919
commit 265e30f438
9 changed files with 184 additions and 214 deletions

22
Cargo.lock generated
View File

@@ -1924,6 +1924,7 @@ dependencies = [
"macro-sass", "macro-sass",
"markdown-it", "markdown-it",
"maud", "maud",
"strum",
"tracing", "tracing",
"utoipa", "utoipa",
] ]
@@ -2034,6 +2035,27 @@ version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "strum"
version = "0.27.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf"
dependencies = [
"strum_macros",
]
[[package]]
name = "strum_macros"
version = "0.27.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn 2.0.108",
]
[[package]] [[package]]
name = "subtle" name = "subtle"
version = "2.6.1" version = "2.6.1"

View File

@@ -19,3 +19,4 @@ utoipa = { workspace = true }
maud = { workspace = true } maud = { workspace = true }
markdown-it = { workspace = true } markdown-it = { workspace = true }
emojis = { workspace = true } emojis = { workspace = true }
strum = { workspace = true }

View File

@@ -13,9 +13,9 @@ li p {
} }
/* Bonus space after last li */ /* Bonus space after last li */
li:last-child { //li:last-child {
margin-bottom: 3rem; // margin-bottom: 3rem;
} //}
ul li::marker { ul li::marker {
content: "> "; content: "> ";

View File

@@ -1,7 +1,10 @@
use maud::{Markup, Render, html}; use maud::{Markup, Render, html};
use strum::{Display, EnumString};
#[derive(Debug, Clone, Copy, EnumString, Display)]
#[expect(clippy::allow_attributes)] #[expect(clippy::allow_attributes)]
#[allow(dead_code)] #[allow(dead_code)]
#[strum(serialize_all = "snake_case")]
pub enum FAIcon { pub enum FAIcon {
Github, Github,
Git, Git,

View File

@@ -1,7 +1,10 @@
use emojis::Emoji;
use markdown_it::parser::inline::{InlineRule, InlineState}; use markdown_it::parser::inline::{InlineRule, InlineState};
use markdown_it::{Node, NodeValue, Renderer}; use markdown_it::{Node, NodeValue, Renderer};
use maud::{Markup, PreEscaped, Render}; use maud::{Markup, PreEscaped, Render};
use std::str::FromStr;
use crate::components::fa::FAIcon;
use crate::components::mangle::{MangledBetaEmail, MangledGoogleEmail};
pub struct Markdown<'a>(pub &'a str); pub struct Markdown<'a>(pub &'a str);
@@ -26,11 +29,11 @@ impl Render for Markdown<'_> {
// //
#[derive(Debug)] #[derive(Debug)]
pub struct InlineEmote(&'static Emoji); pub struct InlineEmote(String);
impl NodeValue for InlineEmote { impl NodeValue for InlineEmote {
fn render(&self, _node: &Node, fmt: &mut dyn Renderer) { fn render(&self, _node: &Node, fmt: &mut dyn Renderer) {
fmt.text(self.0.as_str()); fmt.text_raw(self.0.as_str());
} }
} }
@@ -45,9 +48,21 @@ impl InlineRule for InlineEmote {
} }
let end_idx = input[1..].find(':')? + 1; let end_idx = input[1..].find(':')? + 1;
let emote = emojis::get_by_shortcode(&input[1..end_idx])?; let code = &input[1..end_idx];
Some((Node::new(InlineEmote(emote)), end_idx + 1)) let mut emote = None;
if emote.is_none()
&& let Some(code) = code.strip_prefix("fa-")
{
emote = FAIcon::from_str(code).ok().map(|x| x.render().0)
}
if emote.is_none() {
emote = emojis::get_by_shortcode(code).map(|x| x.to_string());
}
Some((Node::new(InlineEmote(emote?)), end_idx + 1))
} }
} }
@@ -60,6 +75,10 @@ impl NodeValue for InlineMdx {
return; return;
} }
if mdx_include(&self.0, node, fmt) {
return;
}
fmt.open("code", &[]); fmt.open("code", &[]);
fmt.text(&self.0); fmt.text(&self.0);
fmt.close("code"); fmt.close("code");
@@ -101,8 +120,9 @@ impl InlineRule for InlineMdx {
} }
fn mdx_style(mdx: &str, _node: &Node, fmt: &mut dyn Renderer) -> bool { fn mdx_style(mdx: &str, _node: &Node, fmt: &mut dyn Renderer) -> bool {
// Parse inside of mdx: `style(<style>) <content>`
let (style, content) = {
let mdx = mdx.trim(); let mdx = mdx.trim();
if !mdx.starts_with("style(") { if !mdx.starts_with("style(") {
return false; return false;
} }
@@ -128,8 +148,11 @@ fn mdx_style(mdx: &str, _node: &Node, fmt: &mut dyn Renderer) -> bool {
return false; return false;
} }
let style = &mdx[skip..end].trim(); let style = mdx[skip..end].trim();
let content = &mdx[end + 1..].trim(); let content = mdx[end + 1..].trim();
(style, content)
};
let mut style_str = String::new(); let mut style_str = String::new();
@@ -162,9 +185,60 @@ fn mdx_style(mdx: &str, _node: &Node, fmt: &mut dyn Renderer) -> bool {
} }
} }
// Only works with text, could be reworked to do basic md styling
// (italics, bold, tab, code)
fmt.open("span", &[("style", style_str)]); fmt.open("span", &[("style", style_str)]);
fmt.text(&content); fmt.text(&content);
fmt.close("span"); fmt.close("span");
return true; return true;
} }
fn mdx_include(mdx: &str, _node: &Node, fmt: &mut dyn Renderer) -> bool {
// Parse inside of mdx: `include(<args>)`
let args = {
let mdx = mdx.trim();
if !mdx.starts_with("include(") {
return false;
}
let skip = 8;
let mut balance = 1;
let mut end = skip;
for i in mdx[skip..].bytes() {
match i {
b')' => balance -= 1,
b'(' => balance += 1,
_ => {}
}
if balance == 0 {
break;
}
end += 1;
}
if balance != 0 {
return false;
}
let args = mdx[skip..end].trim();
let trail = mdx[end + 1..].trim();
if trail != "" {
return false;
}
args
};
let str = match args {
"email_beta" => MangledBetaEmail {}.render().0,
"email_goog" => MangledGoogleEmail {}.render().0,
_ => return false,
};
fmt.text_raw(&str);
return true;
}

View File

@@ -35,11 +35,9 @@ const MD_A: &str = r#"# Mark's Handouts
[ORMC]: https://circles.math.ucla.edu/circles [ORMC]: https://circles.math.ucla.edu/circles
This page lists all the handouts I've written for my classes at the [ORMC], This page lists all the handouts I've written for my classes at the [ORMC],
a mathematics program for advanced students. We avoid "textbook" arguably the best math circle in the western world. We teach students mathematics
topics, and instead discuss interesting material that isn't seen in school. far beyond the regular school curriculum, much like [AOPS](https://artofproblemsolving.com)
and the [BMC](https://mathcircle.berkeley.edu).
{style(color_var:grey) I often tell my class that Math Circle makes no effort to teach math.
Math Circle teaches you to *think.*"}
<br></br> <br></br>
@@ -50,16 +48,15 @@ and don't start any handouts before class. That spoils all the fun!
{style(color_var:green) For everyone else:} \ {style(color_var:green) For everyone else:} \
If you're using any of these, please let me know---especially \ If you're using any of these, please let me know---especially \
if you find errors, mistakes, or a poorly designed section. \ if you find errors, mistakes, or a poorly designed section. \
Such things must be fixed! {{ email_beta() }} Such things must be fixed! { include(email_beta) }
<br></br> <br></br>
## Overview & Context ## Overview & Context
Our classes are two hours long, with a ten-minute break in between. The lessons below Our classes are two hours long, with a ten-minute break in between. The lessons below
are written with that in mind.\ are written with this in mind.\
At the end of the ideal class, an average student should I do not expect the average student to finish all problems during this two-hour session.
be nearly (but not _fully_) done with that week's handout.
If the class finishes early, the lesson is either too short or too easy. If the class finishes early, the lesson is either too short or too easy.
<br></br> <br></br>

View File

@@ -0,0 +1,45 @@
Also see [what's a "betalupi?"](/whats-a-betalupi)
## Pages
- [Handouts](/handouts): Math circle lessons I've written
- [Links](/links): Interesting parts of the internet
<hr style="margin-top: 8rem; margin-bottom: 8rem"/>
## Projects
- **RedoxOS**, a general-purpose, microkernel-based operating system written in Rust. _{ style(color_var:grey) [enthusiast] }_
- { style(color_var:grey) Status: } { style(color_var:yellow) Passive. }
- { style(color_var:grey) Website: } [:fa-link: redox-os.org](https://www.redox-os.org/)
<br/>
- **Tectonic**, the LaTeX engine that is pleasant to use.
Experimental, but fully functional. _{ style(color_var:grey) [co-maintainer] }_
- { style(color_var:grey) Status: } { style(color_var:yellow) Passive. } [Typst](https://github.com/typst/typst) is better.
- { style(color_var:grey) Main repo: } [:fa-github: Tectonic](https://github.com/tectonic-typesetting/tectonic)
- { style(color_var:grey) Bundle tools: } [:fa-github: tectonic-texlive-bundles](https://github.com/tectonic-typesetting/tectonic-texlive-bundles)
<br/>
- **Daisy**, a pretty TUI scientific calculator. _{style(color_var:grey) [author] }_
- {style(color_var:grey) Status: } {style(color_var:orange) Done. } Used this to learn Rust. [Numbat](https://numbat.dev) is better.
- {style(color_var:grey) Repository: } [:fa-github: rm-dr/daisy](https://github.com/rm-dr/daisy)
- {style(color_var:grey) Website: } [:fa-link: daisy.betalupi.com](https://daisy.betalupi.com) (WASM demo)
<br/>
- **Lamb**, a lambda calculus engine. _{style(color_var:grey) [author] }_
- {style(color_var:grey) Status: } {style(color_var:orange) Done. } Fun little project.
- {style(color_var:grey) Repository: } [:fa-github: rm-dr/lamb](https://github.com/rm-dr/lamb)
- {style(color_var:grey) PyPi: } [:fa-python: lamb-engine](https://pypi.org/project/lamb-engine)
<br/>

View File

@@ -68,180 +68,8 @@ pub async fn index() -> Markup {
br style="clear:both;" {} 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"
)
)
)
}
}
}
}
(Markdown(include_str!("index.md")))
) )
)) ))
} }