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",
"markdown-it",
"maud",
"strum",
"tracing",
"utoipa",
]
@@ -2034,6 +2035,27 @@ version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "subtle"
version = "2.6.1"

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,10 @@
use emojis::Emoji;
use markdown_it::parser::inline::{InlineRule, InlineState};
use markdown_it::{Node, NodeValue, Renderer};
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);
@@ -26,11 +29,11 @@ impl Render for Markdown<'_> {
//
#[derive(Debug)]
pub struct InlineEmote(&'static Emoji);
pub struct InlineEmote(String);
impl NodeValue for InlineEmote {
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 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;
}
if mdx_include(&self.0, node, fmt) {
return;
}
fmt.open("code", &[]);
fmt.text(&self.0);
fmt.close("code");
@@ -101,35 +120,39 @@ impl InlineRule for InlineMdx {
}
fn mdx_style(mdx: &str, _node: &Node, fmt: &mut dyn Renderer) -> bool {
let mdx = mdx.trim();
if !mdx.starts_with("style(") {
return false;
}
let skip = 6;
let mut balance = 1;
let mut end = skip;
for i in mdx[skip..].bytes() {
match i {
b')' => balance -= 1,
b'(' => balance += 1,
_ => {}
// Parse inside of mdx: `style(<style>) <content>`
let (style, content) = {
let mdx = mdx.trim();
if !mdx.starts_with("style(") {
return false;
}
if balance == 0 {
break;
let skip = 6;
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;
}
end += 1;
}
if balance != 0 {
return false;
}
if balance != 0 {
return false;
}
let style = mdx[skip..end].trim();
let content = mdx[end + 1..].trim();
let style = &mdx[skip..end].trim();
let content = &mdx[end + 1..].trim();
(style, content)
};
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.text(&content);
fmt.close("span");
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

@@ -48,7 +48,7 @@ assets! {
}
//
// MARK:fonts
// MARK: fonts
//
FiraCode_Bold_woff2 {

View File

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