summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock199
-rw-r--r--Cargo.toml2
-rw-r--r--src/blog/mod.rs96
3 files changed, 284 insertions, 13 deletions
diff --git a/Cargo.lock b/Cargo.lock
index c702c0c..ea34aff 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -264,12 +264,27 @@ dependencies = [
]
[[package]]
+name = "base64"
+version = "0.21.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
+
+[[package]]
name = "binascii"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "383d29d513d8764dcdc42ea295d979eb99c3c9f00607b3692cf68a431f7dca72"
[[package]]
+name = "bincode"
+version = "1.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
+dependencies = [
+ "serde",
+]
+
+[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -369,6 +384,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
[[package]]
+name = "crc32fast"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
name = "crossbeam-utils"
version = "0.8.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -505,6 +529,16 @@ dependencies = [
]
[[package]]
+name = "flate2"
+version = "1.0.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae"
+dependencies = [
+ "crc32fast",
+ "miniz_oxide",
+]
+
+[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -900,6 +934,12 @@ dependencies = [
]
[[package]]
+name = "latex2mathml"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "678cf5bdb3ba63a264e6e0c9eee36538ca1d2da0afa4dd801c1f96309e710765"
+
+[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -912,6 +952,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
+name = "line-wrap"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9"
+dependencies = [
+ "safemem",
+]
+
+[[package]]
+name = "linked-hash-map"
+version = "0.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
+
+[[package]]
name = "linux-raw-sys"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1012,10 +1067,12 @@ dependencies = [
"futures",
"include_dir",
"iso8601",
+ "latex2mathml",
"log",
"markdown",
"markup",
"rocket",
+ "syntect",
"tokio",
]
@@ -1126,6 +1183,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
+name = "onig"
+version = "6.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c4b31c8722ad9171c6d77d3557db078cab2bd50afcc9d09c8b315c59df8ca4f"
+dependencies = [
+ "bitflags 1.3.2",
+ "libc",
+ "once_cell",
+ "onig_sys",
+]
+
+[[package]]
+name = "onig_sys"
+version = "69.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b829e3d7e9cc74c7e315ee8edb185bf4190da5acde74afd7fc59c35b1f086e7"
+dependencies = [
+ "cc",
+ "pkg-config",
+]
+
+[[package]]
name = "overload"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1202,6 +1281,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
+name = "pkg-config"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
+
+[[package]]
+name = "plist"
+version = "1.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a4a0cfc5fb21a09dc6af4bf834cf10d4a32fccd9e2ea468c4b1751a097487aa"
+dependencies = [
+ "base64",
+ "indexmap 1.9.3",
+ "line-wrap",
+ "quick-xml",
+ "serde",
+ "time",
+]
+
+[[package]]
name = "polling"
version = "2.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1244,6 +1343,15 @@ dependencies = [
]
[[package]]
+name = "quick-xml"
+version = "0.30.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
name = "quote"
version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1356,6 +1464,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ab07dc67230e4a4718e70fd5c20055a4334b121f1f9db8fe63ef39ce9b8c846"
[[package]]
+name = "regex-syntax"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
+
+[[package]]
name = "rocket"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1483,6 +1597,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe232bdf6be8c8de797b22184ee71118d63780ea42ac85b61d1baa6d3b782ae9"
[[package]]
+name = "safemem"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072"
+
+[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
name = "scoped-tls"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1623,6 +1752,28 @@ dependencies = [
]
[[package]]
+name = "syntect"
+version = "5.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "874dcfa363995604333cf947ae9f751ca3af4522c60886774c4963943b4746b1"
+dependencies = [
+ "bincode",
+ "bitflags 1.3.2",
+ "flate2",
+ "fnv",
+ "once_cell",
+ "onig",
+ "plist",
+ "regex-syntax 0.8.3",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "thiserror",
+ "walkdir",
+ "yaml-rust",
+]
+
+[[package]]
name = "tempfile"
version = "3.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1637,6 +1788,26 @@ dependencies = [
]
[[package]]
+name = "thiserror"
+version = "1.0.55"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e3de26b0965292219b4287ff031fcba86837900fe9cd2b34ea8ad893c0953d2"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.55"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "268026685b2be38d7103e9e507c938a1fcb3d7e6eb15e87870b617bf37b6d581"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
name = "thread_local"
version = "1.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1904,6 +2075,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
[[package]]
+name = "walkdir"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
+dependencies = [
+ "same-file",
+ "winapi-util",
+]
+
+[[package]]
name = "want"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2020,6 +2201,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
+name = "winapi-util"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b"
+dependencies = [
+ "windows-sys 0.52.0",
+]
+
+[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2240,6 +2430,15 @@ dependencies = [
]
[[package]]
+name = "yaml-rust"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
+dependencies = [
+ "linked-hash-map",
+]
+
+[[package]]
name = "yansi"
version = "1.0.0-rc"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 4d267db..7d59ae5 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -16,3 +16,5 @@ anyhow = "1.0.82"
markup = "0.15.0"
markdown = "1.0.0-alpha.17"
chrono = "0.4.38"
+syntect = "5.2.0"
+latex2mathml = "0.2.3"
diff --git a/src/blog/mod.rs b/src/blog/mod.rs
index b301171..49fbd4b 100644
--- a/src/blog/mod.rs
+++ b/src/blog/mod.rs
@@ -8,8 +8,14 @@ use crate::uri;
use anyhow::anyhow;
pub use atom::r_blog_atom;
use atom::rocket_uri_macro_r_blog_atom;
+use latex2mathml::DisplayStyle;
+use markdown::mdast::Node;
+use markup::{raw, DynRender};
use rocket::{get, response::Redirect};
use std::{path::PathBuf, str::FromStr};
+use syntect::highlighting::ThemeSet;
+use syntect::html::highlighted_html_for_string;
+use syntect::parsing::SyntaxSet;
use tokio::fs::read_to_string;
pub const ARTICLE_ROOT: &'static str = "./blog/articles";
@@ -49,28 +55,92 @@ pub async fn r_blog_article(name: &str) -> MyResult<DynScaffold<'static>> {
.join(PathBuf::new().with_file_name(name).with_extension("md"));
let a = article_metadata(apath.clone()).await?;
let text = read_to_string(apath).await?;
- let html = markdown::to_html_with_options(
+ let ast = markdown::to_mdast(
&text,
- &markdown::Options {
- parse: markdown::ParseOptions {
- constructs: markdown::Constructs {
- math_flow: true,
- math_text: true,
- ..Default::default()
- },
- ..Default::default()
- },
- compile: markdown::CompileOptions {
+ &markdown::ParseOptions {
+ constructs: markdown::Constructs {
+ math_flow: true,
+ math_text: true,
..Default::default()
},
+ ..Default::default()
},
)
- .map_err(|e| anyhow!("the server had trouble compiling markdown: {e}"))?;
+ .map_err(|e| anyhow!("the server had trouble parsing markdown: {e}"))?;
+
Ok(Scaffold {
title: a.title,
content: markup::new! {
- @markup::raw(&html)
+ @node_to_render(&ast)
p{i{ "Article written by metamuffin, text licenced under CC BY-ND 4.0, non-trivial code blocks under GPL-3.0-only except where indicated otherwise" }}
},
})
}
+
+fn node_to_render<'a>(node: &'a Node) -> DynRender<'a> {
+ match node {
+ Node::Text(s) => markup::new!(@s.value),
+ Node::Paragraph(el) => markup::new!(p { @for e in &el.children { @node_to_render(e) } }),
+ Node::List(list) => markup::new!(ul { @for e in &list.children { @node_to_render(e) } }),
+ Node::Root(el) => markup::new!(article { @for e in &el.children { @node_to_render(e) } }),
+ Node::ListItem(el) => markup::new!(li { @for e in &el.children { @node_to_render(e) } }),
+ Node::Emphasis(el) => markup::new!(i { @for e in &el.children { @node_to_render(e) } }),
+ Node::Strong(el) => markup::new!(strong { @for e in &el.children { @node_to_render(e) } }),
+ Node::Html(html) => markup::new!(@raw(&html.value)),
+ Node::Link(l) => {
+ markup::new!(a[href=&l.url, alt=&l.title] { @for e in &l.children { @node_to_render(e) } })
+ }
+ Node::Break(_) => markup::new!(br;),
+ Node::InlineCode(s) => markup::new!(code { @s.value }),
+ Node::Delete(_) => markup::new!("todo1"),
+ Node::FootnoteReference(_) => markup::new!("todo3"),
+ Node::FootnoteDefinition(_) => markup::new!("todo4"),
+ Node::Image(_) => markup::new!("todo5"),
+ Node::ImageReference(_) => markup::new!("todo6"),
+ Node::LinkReference(_) => markup::new!("todo8"),
+ Node::BlockQuote(_) => markup::new!("todo10"),
+ Node::Table(_) => markup::new!("todo12"),
+ Node::ThematicBreak(_) => markup::new!("todo13"),
+ Node::TableRow(_) => markup::new!("todo14"),
+ Node::TableCell(_) => markup::new!("todo15"),
+ Node::Definition(_) => markup::new!("todo16"),
+ Node::Toml(_)
+ | Node::Yaml(_)
+ | Node::MdxjsEsm(_)
+ | Node::MdxJsxFlowElement(_)
+ | Node::MdxJsxTextElement(_)
+ | Node::MdxTextExpression(_)
+ | Node::MdxFlowExpression(_) => markup::new!("unsupported"),
+ Node::Heading(h) => {
+ let inner = markup::new!(@for e in &h.children { @node_to_render(e) });
+ match h.depth {
+ 1 => markup::new!(h2{@inner}),
+ 2 => markup::new!(h3{@inner}),
+ 3 => markup::new!(h4{@inner}),
+ 4 => markup::new!(h5{@inner}),
+ 5 => markup::new!(h6{@inner}),
+ 6 => markup::new!(h6{@inner}),
+ _ => unreachable!(),
+ }
+ }
+ Node::Code(code) => {
+ let theme = &ThemeSet::load_defaults().themes["base16-ocean.dark"];
+ let syntax = &SyntaxSet::load_defaults_newlines();
+ let lang = syntax
+ .find_syntax_by_extension(&code.lang.to_owned().unwrap_or("txt".to_owned()))
+ .unwrap_or_else(|| syntax.find_syntax_by_extension("txt").unwrap());
+ let html = highlighted_html_for_string(&code.value, syntax, lang, theme).unwrap();
+ markup::new!(@raw(&html))
+ }
+ Node::Math(s) => {
+ let mathml = latex2mathml::latex_to_mathml(&s.value, DisplayStyle::Block)
+ .expect("invalid block math");
+ markup::new!(@raw(&mathml))
+ }
+ Node::InlineMath(s) => {
+ let mathml = latex2mathml::latex_to_mathml(&s.value, DisplayStyle::Inline)
+ .expect("invalid inline math");
+ markup::new!(@raw(&mathml))
+ }
+ }
+}