Markdown upgrades
This commit is contained in:
22
Cargo.lock
generated
22
Cargo.lock
generated
@@ -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"
|
||||
|
||||
@@ -19,3 +19,4 @@ utoipa = { workspace = true }
|
||||
maud = { workspace = true }
|
||||
markdown-it = { workspace = true }
|
||||
emojis = { workspace = true }
|
||||
strum = { workspace = true }
|
||||
|
||||
@@ -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: "> ";
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ assets! {
|
||||
}
|
||||
|
||||
//
|
||||
// MARK:fonts
|
||||
// MARK: fonts
|
||||
//
|
||||
|
||||
FiraCode_Bold_woff2 {
|
||||
|
||||
@@ -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>
|
||||
|
||||
45
crates/service/service-webpage/src/routes/index.md
Normal file
45
crates/service/service-webpage/src/routes/index.md
Normal 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/>
|
||||
@@ -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")))
|
||||
)
|
||||
))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user