From 485abd8d8163196d7d0b0927aaff09350092c06b Mon Sep 17 00:00:00 2001 From: spencer Date: Tue, 28 Apr 2026 16:16:59 -0400 Subject: [PATCH] add markdown template rendering --- Cargo.lock | 289 +++++++++++++++++++++++++++ Cargo.toml | 2 + src/functions.rs | 15 ++ src/main.rs | 33 ++- static/en/content.md | 13 ++ static/en/test2.md | 2 + templates/common.html | 4 +- templates/en/homelab/index.html | 2 + templates/en/index.html | 8 +- templates/en/publications/index.html | 2 + templates/en/resume/index.html | 3 +- templates/fr/index.html | 2 + templates/fr/resume/index.html | 6 +- update_static.sh | 8 + 14 files changed, 371 insertions(+), 18 deletions(-) create mode 100644 src/functions.rs create mode 100644 static/en/content.md create mode 100644 static/en/test2.md create mode 100755 update_static.sh diff --git a/Cargo.lock b/Cargo.lock index d86062f..d3aa536 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,6 +20,23 @@ dependencies = [ "libc", ] +[[package]] +name = "arraydeque" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -89,6 +106,9 @@ name = "bitflags" version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" +dependencies = [ + "serde_core", +] [[package]] name = "block-buffer" @@ -170,6 +190,55 @@ dependencies = [ "phf_codegen", ] +[[package]] +name = "config" +version = "0.15.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e68cfe19cd7d23ffde002c24ffa5cda73931913ef394d5eaaa32037dc940c0c" +dependencies = [ + "async-trait", + "convert_case", + "json5", + "pathdiff", + "ron", + "rust-ini", + "serde-untagged", + "serde_core", + "serde_json", + "toml", + "winnow", + "yaml-rust2", +] + +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom", + "once_cell", + "tiny-keccak", +] + +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -210,6 +279,12 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + [[package]] name = "crypto-common" version = "0.1.7" @@ -236,6 +311,35 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "dlv-list" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f" +dependencies = [ + "const-random", +] + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "erased-serde" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2add8a07dd6a8d93ff627029c51de145e12686fbc36ecb298ac22e74cf02dec" +dependencies = [ + "serde", + "serde_core", + "typeid", +] + [[package]] name = "errno" version = "0.3.14" @@ -252,6 +356,12 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + [[package]] name = "form_urlencoded" version = "1.2.2" @@ -345,6 +455,30 @@ dependencies = [ "walkdir", ] +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashlink" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" +dependencies = [ + "hashbrown 0.15.5", +] + [[package]] name = "http" version = "1.4.0" @@ -496,6 +630,17 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "json5" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" +dependencies = [ + "pest", + "pest_derive", + "serde", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -529,6 +674,15 @@ version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +[[package]] +name = "markdown" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5cab8f2cadc416a82d2e783a1946388b31654d391d1c7d92cc1f03e295b1deb" +dependencies = [ + "unicode-id", +] + [[package]] name = "matchit" version = "0.8.4" @@ -583,6 +737,16 @@ version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" +[[package]] +name = "ordered-multimap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79" +dependencies = [ + "dlv-list", + "hashbrown 0.14.5", +] + [[package]] name = "parking_lot" version = "0.12.5" @@ -615,6 +779,12 @@ dependencies = [ "regex", ] +[[package]] +name = "pathdiff" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" + [[package]] name = "percent-encoding" version = "2.3.2" @@ -803,6 +973,30 @@ version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" +[[package]] +name = "ron" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4147b952f3f819eca0e99527022f7d6a8d05f111aeb0a62960c74eb283bec8fc" +dependencies = [ + "bitflags", + "once_cell", + "serde", + "serde_derive", + "typeid", + "unicode-ident", +] + +[[package]] +name = "rust-ini" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "796e8d2b6696392a43bea58116b667fb4c29727dc5abd27d6acf338bb4f688c7" +dependencies = [ + "cfg-if", + "ordered-multimap", +] + [[package]] name = "rustversion" version = "1.0.22" @@ -839,6 +1033,18 @@ dependencies = [ "serde_core", ] +[[package]] +name = "serde-untagged" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9faf48a4a2d2693be24c6289dbe26552776eb7737074e6722891fadbe6c5058" +dependencies = [ + "erased-serde", + "serde", + "serde_core", + "typeid", +] + [[package]] name = "serde_core" version = "1.0.228" @@ -883,6 +1089,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "serde_spanned" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" +dependencies = [ + "serde_core", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -999,6 +1214,15 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "tokio" version = "1.52.1" @@ -1040,6 +1264,37 @@ dependencies = [ "tokio", ] +[[package]] +name = "toml" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" +dependencies = [ + "serde_core", + "serde_spanned", + "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_parser" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +dependencies = [ + "winnow", +] + [[package]] name = "tower" version = "0.5.3" @@ -1114,6 +1369,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "typeid" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" + [[package]] name = "typenum" version = "1.20.0" @@ -1132,6 +1393,12 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" +[[package]] +name = "unicode-id" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ba288e709927c043cbe476718d37be306be53fb1fafecd0dbe36d072be2580" + [[package]] name = "unicode-ident" version = "1.0.24" @@ -1216,7 +1483,9 @@ name = "website" version = "0.1.0" dependencies = [ "axum", + "config", "lazy_static", + "markdown", "tera", "tokio", "tower-http", @@ -1299,6 +1568,26 @@ dependencies = [ "windows-link", ] +[[package]] +name = "winnow" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0" +dependencies = [ + "memchr", +] + +[[package]] +name = "yaml-rust2" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2462ea039c445496d8793d052e13787f2b90e750b833afee748e601c17621ed9" +dependencies = [ + "arraydeque", + "encoding_rs", + "hashlink", +] + [[package]] name = "zerocopy" version = "0.8.48" diff --git a/Cargo.toml b/Cargo.toml index 440cb86..6b5b2bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,9 @@ edition = "2021" [dependencies] axum = "0.8.9" +config = "0.15.22" lazy_static = "1.5.0" +markdown = "1.0.0" tera = "1.20.1" tokio = { version = "1", features = ["full"] } tower-http = { version = "0.6.8", features = ["fs"] } diff --git a/src/functions.rs b/src/functions.rs new file mode 100644 index 0000000..8a2b54b --- /dev/null +++ b/src/functions.rs @@ -0,0 +1,15 @@ +use std::collections::HashMap; +use tera::{ + Value, to_value, try_get_value +}; + +pub fn load_markdown(args: &HashMap) -> tera::Result { + let value = args.get("path").ok_or("path not provided")?; + let path = try_get_value!("load_markdown", "path", String, value); + let content = std::fs::read_to_string(format!("static/{}", path))?; + + let html = markdown::to_html(&content); + dbg!(&html); + Ok(to_value(&html)?) +} + diff --git a/src/main.rs b/src/main.rs index e037ba1..a231be7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,5 @@ +pub mod functions; + use std::collections::HashMap; use tera::{Context, Tera}; use axum::{ @@ -16,7 +18,11 @@ use axum::{ use tower_http::services::{ServeDir, ServeFile}; lazy_static::lazy_static! { - pub static ref TEMPLATES: Tera = Tera::new("templates/**/*").expect("failed to parse templates"); + pub static ref TEMPLATES: Tera = { + let mut tera = Tera::new("templates/**/*").expect("failed to parse templates"); + tera.register_function("load_markdown", functions::load_markdown); + tera + }; } #[tokio::main] @@ -51,15 +57,20 @@ async fn render_template(Path(params): Path>) -> Result Ok(Html(html)), Err(e) => { eprintln!("Tera error: {}", e); @@ -67,3 +78,13 @@ async fn render_template(Path(params): Path>) -> Result std::path::PathBuf { + let mut pb = std::path::PathBuf::from(input.clone()); + if !input.ends_with("index.html") { + pb.push("index.html"); + } + pb +} diff --git a/static/en/content.md b/static/en/content.md new file mode 100644 index 0000000..5cd7434 --- /dev/null +++ b/static/en/content.md @@ -0,0 +1,13 @@ +## Home Page — Spencer Whitehead + +Pour accéder à la version française, veuillez cliquer [ici](/fr/). + +This is the personal website of Spencer Whitehead. I am a fourth-year Ph.D. candidate at Duke University, expecting to graduate in early 2027. My primary research interests are in gauge theory, four- and eight-dimensional differential geometry, and the applications of computer algebra systems to solving problems in geometry. + +[Resume](resume) + +[Publications](publications) + +[Homelab](homelab) + +[View the code for this website](https://git.touhou.ca/spencer/website) diff --git a/static/en/test2.md b/static/en/test2.md new file mode 100644 index 0000000..897b9f3 --- /dev/null +++ b/static/en/test2.md @@ -0,0 +1,2 @@ +* dynamically scoped +* very cool diff --git a/templates/common.html b/templates/common.html index 02fe8dc..8966e17 100644 --- a/templates/common.html +++ b/templates/common.html @@ -6,7 +6,9 @@ {{ title }} - + {% endmacro %} diff --git a/templates/en/homelab/index.html b/templates/en/homelab/index.html index 7f8e97e..12ac43f 100644 --- a/templates/en/homelab/index.html +++ b/templates/en/homelab/index.html @@ -3,6 +3,7 @@ {{ common::nav() }}

Homelab

+
The website you are currently viewing is being served by my personal computing homelab, a cluster of three nodes orchestrated by k3s.

crusader

@@ -20,4 +21,5 @@

blackprince

blackprince was built in 2025. It has an AMD Ryzen 7 7700XD chip, an Nvidia GeForce 1080 GPU, and 64GB of DDR5 3200 RAM, running Linux Mint 22. It is primarily used as a personal computing node, and for running more intense computations for research purposes. +
diff --git a/templates/en/index.html b/templates/en/index.html index 77423eb..faf12f2 100644 --- a/templates/en/index.html +++ b/templates/en/index.html @@ -1,11 +1,5 @@ {% import "common.html" as common %} {{ common::meta(title="Home Page", lang="en") }} -

Home Page — Spencer Whitehead

-

Pour accéder à la version française, veuillez cliquer ici.

-

This is the personal website of Spencer Whitehead. I am a fourth-year Ph.D. candidate at Duke University, expecting to graduate in early 2027. - My primary research interests are in gauge theory, four- and eight-dimensional differential geometry, and the applications of computer algebra systems to solving problems in geometry.

-

Resume

-

Publications

-

Homelab

+ {{ load_markdown(path=path ~ "content.md") | safe }} diff --git a/templates/en/publications/index.html b/templates/en/publications/index.html index 53a76d4..b9dc86e 100644 --- a/templates/en/publications/index.html +++ b/templates/en/publications/index.html @@ -3,6 +3,7 @@ {{ common::nav() }}

Publications

+

This page contains a list of my published (scholarly) works with plain-language descriptions of the results.

On a smoothness characterization for good moduli spaces, joint with Dan Edidin and Matt Satriano, published in Advances in Mathematics in April 2024.

@@ -38,5 +39,6 @@

Any time one builds a four-dimensional object in three-dimensions, it is necessary to "project a dimension away": for example, by placing the skeleton of a three-dimensional cube in front of a light source, one can project it to a two-dimensional image on a wall. Not all projections are equal: some (like the stereographic projection distort lengths, while others (such as the orthogonal projection, where we imagine an infinitely strong light source placed infinitely far away) may cause edges to cross each other. In this project, we created a software package in Maple to determine what projections could actually be constructed in the Zometool building system, and to generate plans for building complicated geometric projections in Zometool. We focused especially on a class of shapes called Wythoff constructions, which are the result of looking at images of a point in a system of mirrors called a kaleidoscope.

+
diff --git a/templates/en/resume/index.html b/templates/en/resume/index.html index 944c664..2612eb3 100644 --- a/templates/en/resume/index.html +++ b/templates/en/resume/index.html @@ -11,6 +11,7 @@ +

Education

@@ -148,7 +149,7 @@
- +
diff --git a/templates/fr/index.html b/templates/fr/index.html index a1c1e68..b34e76a 100644 --- a/templates/fr/index.html +++ b/templates/fr/index.html @@ -5,10 +5,12 @@

Page d'accueil — Spencer Whitehead

+

To access the English version, click here.

N.B. : ma langue maternelle est l'anglais ; je m'en excuse d'avance pour les éventuelles fautes sur cette page. En cas d'erreur, veuillez m'envoyer un e-mail à spencer@firemail.cc.

Ceci est le site web personnel de Spencer Whitehead. Je suis doctorant en quatrième année à l'université Duke. Je m'intéresse à la recherche en géométrie différentielle, particulièrement en dimension 4 et 8. J'étudie aussi les applications des systèmes de calcul formel aux problèmes de géométrie. Je prévois de soutenir ma thèse en avril 2027.

CV

+
diff --git a/templates/fr/resume/index.html b/templates/fr/resume/index.html index b2bfe6f..0fa1d63 100644 --- a/templates/fr/resume/index.html +++ b/templates/fr/resume/index.html @@ -4,14 +4,14 @@ {{ common::nav() }} -
+

Spencer Whitehead

Courriel : spencer@firemail.cc
Tél. : +1 984 312 9089
- +

Formation

@@ -148,7 +148,7 @@
- +
diff --git a/update_static.sh b/update_static.sh new file mode 100755 index 0000000..4d95ba9 --- /dev/null +++ b/update_static.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +# updates static files in the deployment without a full rebuild +POD=$(sudo k3s kubectl get pods | grep website | awk '{ print $1 }') +echo "Recursive copy static to $POD:/app/static/" +sudo k3s kubectl exec $POD -- sh -c "rm -rf /app/static/" || echo "Error in deleting directory" +sudo k3s kubectl cp static "$POD:/app/static/" || echo "Error in copying new files" +