diff --git a/Cargo.lock b/Cargo.lock index 4c54007..779a17f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -860,6 +860,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + [[package]] name = "fontconfig-parser" version = "0.5.8" @@ -964,6 +970,19 @@ dependencies = [ "wasip2", ] +[[package]] +name = "getrandom" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", + "wasip3", +] + [[package]] name = "gif" version = "0.14.1" @@ -1010,6 +1029,15 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + [[package]] name = "hashbrown" version = "0.16.1" @@ -1244,6 +1272,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + [[package]] name = "idna" version = "1.1.0" @@ -1318,7 +1352,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.16.1", + "serde", + "serde_core", ] [[package]] @@ -1419,6 +1455,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + [[package]] name = "lebe" version = "0.5.3" @@ -1986,6 +2028,16 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + [[package]] name = "proc-macro2" version = "1.0.106" @@ -2427,6 +2479,15 @@ dependencies = [ "zmij", ] +[[package]] +name = "serde_spanned" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776" +dependencies = [ + "serde_core", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -2443,15 +2504,20 @@ dependencies = [ name = "server" version = "0.1.0" dependencies = [ + "anyhow", "chrono", + "http", "lipgloss", "markdown", "mdriver", "mq-markdown", "mq-view", + "serde", "termimad", "text-template", "tokio", + "toml 1.0.1+spec-1.1.0", + "toml-frontmatter", "warp", ] @@ -2701,7 +2767,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0136791f7c95b1f6dd99f9cc786b91bb81c3800b639b3478e561ddb7be95e5f1" dependencies = [ "fastrand", - "getrandom 0.3.4", + "getrandom 0.4.1", "once_cell", "rustix", "windows-sys 0.61.2", @@ -2914,6 +2980,65 @@ dependencies = [ "tokio", ] +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "toml" +version = "1.0.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbe30f93627849fa362d4a602212d41bb237dc2bd0f8ba0b2ce785012e124220" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime", + "toml_parser", + "toml_writer", + "winnow", +] + +[[package]] +name = "toml-frontmatter" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5865e866fed03091c20d7b59453b2cbd86ecfcdb668f5f2265cf61a0fa5c711" +dependencies = [ + "anyhow", + "serde", + "toml 0.5.11", +] + +[[package]] +name = "toml_datetime" +version = "1.0.0+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32c2555c699578a4f59f0cc68e5116c8d7cabbd45e1409b989d4be085b53f13e" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_parser" +version = "1.0.8+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0742ff5ff03ea7e67c8ae6c93cac239e0d9784833362da3f9a9c1da8dfefcbdc" +dependencies = [ + "winnow", +] + +[[package]] +name = "toml_writer" +version = "1.0.6+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" + [[package]] name = "tower-service" version = "0.3.3" @@ -3176,6 +3301,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + [[package]] name = "untrusted" version = "0.9.0" @@ -3344,6 +3475,15 @@ dependencies = [ "wit-bindgen", ] +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen", +] + [[package]] name = "wasm-bindgen" version = "0.2.108" @@ -3389,6 +3529,40 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.10.0", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + [[package]] name = "webpki-roots" version = "0.26.11" @@ -3659,11 +3833,99 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" +[[package]] +name = "winnow" +version = "0.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" + [[package]] name = "wit-bindgen" version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.10.0", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] [[package]] name = "writeable" diff --git a/Cargo.toml b/Cargo.toml index e8e67d0..3fc413c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,3 +14,8 @@ lipgloss = "0.1.1" mdriver = "0.14.0" mq-view = "0.1.9" mq-markdown = { version = "0.5.14", features = ["color"] } +toml = "1.0.1" +http = "1.4.0" +anyhow = "1.0.101" +toml-frontmatter = "0.1.0" +serde = "1.0.228" diff --git a/assets/template.html b/assets/template.html deleted file mode 100644 index bd0377c..0000000 --- a/assets/template.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - title! - - - - ${time} - ${header} - ${body} - ${footer} - - diff --git a/serve/assets/css/style.css b/serve/assets/css/style.css new file mode 100644 index 0000000..fb23669 --- /dev/null +++ b/serve/assets/css/style.css @@ -0,0 +1,38 @@ + +.body { + display: flex; + flex-direction: row; + justify-content: center; + flex-wrap: wrap-reverse; +/* max-width: 80vmax; + margin: auto;*/ + gap: 2vw; +} +.sidebar { + min-width: 30%; + max-width: 400px; + flex-grow: 1; + background-color: rgba(255,0,0,0.3); +} +.content { + background-color: rgba(0,255,0,0.3); + max-width: 60vmax; +} + +#buttons { + img { + display: block; + margin: auto; + width: 60%; + aspect-ratio: 88 / 31; + } +} + +img { + width: 10vmax; +} +.markdown-module { + padding: 1vmax 2vmax; + margin: 1vmax 0; + background-color: #f0f0f044; +} diff --git a/serve/assets/sidebar/buttons.md b/serve/assets/sidebar/buttons.md new file mode 100644 index 0000000..c5c0f98 --- /dev/null +++ b/serve/assets/sidebar/buttons.md @@ -0,0 +1,6 @@ +[![Want to link back to my site? Feel free to use this button!](http://pogmom.me/assets/img/webring/pogmommy/1056x372.webp)](https://git.pogmom.me/pogmommy/pogmomme/src/branch/main/assets/img/webring/pogmommy/) + +[![Cassie Candles](http://pogmom.me/assets/img/webring/cassiecandles/1056x372.webp)](https://cassiecandles.net) + +[![TerminalLesbian](http://pogmom.me/assets/img/webring/terminallesbian/1080x380.webp)](https://hotn.gay) + diff --git a/serve/assets/sidebar/rats.md b/serve/assets/sidebar/rats.md new file mode 100644 index 0000000..c3c5aff --- /dev/null +++ b/serve/assets/sidebar/rats.md @@ -0,0 +1,3 @@ +![${filename}](${}) + +Please enjoy a picture of my sons :) diff --git a/serve/assets/template.html b/serve/assets/template.html new file mode 100644 index 0000000..60200d7 --- /dev/null +++ b/serve/assets/template.html @@ -0,0 +1,24 @@ + + + + ${title} + + + + + +
+ +
+ ${content} +
+
+ + + diff --git a/serve/assets/templates/page.html b/serve/assets/templates/page.html new file mode 100644 index 0000000..0d1ad29 --- /dev/null +++ b/serve/assets/templates/page.html @@ -0,0 +1,23 @@ + + + + ${title} + + + + +
+ +
+ ${content} +
+
+ + + diff --git a/serve/favicon.ico b/serve/favicon.ico new file mode 100644 index 0000000..316c254 Binary files /dev/null and b/serve/favicon.ico differ diff --git a/serve/home.md b/serve/home.md new file mode 100644 index 0000000..f55c2b7 --- /dev/null +++ b/serve/home.md @@ -0,0 +1,8 @@ +---toml +title = "home" +index = 0 +--- + +# test + +test diff --git a/plog/esp32s3-fidokey.md b/serve/plog/esp32s3-fidokey.md similarity index 100% rename from plog/esp32s3-fidokey.md rename to serve/plog/esp32s3-fidokey.md diff --git a/plog/esp32s3-fidokey/2026-02-03.md b/serve/plog/esp32s3-fidokey/2026-02-03.md similarity index 100% rename from plog/esp32s3-fidokey/2026-02-03.md rename to serve/plog/esp32s3-fidokey/2026-02-03.md diff --git a/serve/plog/header.md b/serve/plog/header.md new file mode 100644 index 0000000..0212377 --- /dev/null +++ b/serve/plog/header.md @@ -0,0 +1,3 @@ +# project blog + +## This will ideally create more problems than it could ever possibly solve diff --git a/plog/imac-g3-debian.md b/serve/plog/imac-g3-debian.md similarity index 67% rename from plog/imac-g3-debian.md rename to serve/plog/imac-g3-debian.md index 054b482..e3bf4a1 100644 --- a/plog/imac-g3-debian.md +++ b/serve/plog/imac-g3-debian.md @@ -1,3 +1,8 @@ +---toml +title = "Debian on an iMac G3" +date_created = "2026-01-08" +date_updated = "2026-02-03" +--- # Debian Sid on an iMac G3 ![A photograph of an orange iMac G3 running Debian Buster logged into a TTY](https://pogmom.me/assets/img/plog/imac_g3/2025-07-25.jpg) diff --git a/plog/imac-g3-debian/2026-02-03.md b/serve/plog/imac-g3-debian/2026-02-03.md similarity index 100% rename from plog/imac-g3-debian/2026-02-03.md rename to serve/plog/imac-g3-debian/2026-02-03.md diff --git a/plog/op6t-cyberdeck.md b/serve/plog/op6t-cyberdeck.md similarity index 100% rename from plog/op6t-cyberdeck.md rename to serve/plog/op6t-cyberdeck.md diff --git a/plog/op6t-cyberdeck/2026-02-03.md b/serve/plog/op6t-cyberdeck/2026-02-03.md similarity index 100% rename from plog/op6t-cyberdeck/2026-02-03.md rename to serve/plog/op6t-cyberdeck/2026-02-03.md diff --git a/plog/todo.md b/serve/plog/todo.md similarity index 75% rename from plog/todo.md rename to serve/plog/todo.md index ef42ee3..d56356f 100644 --- a/plog/todo.md +++ b/serve/plog/todo.md @@ -1,6 +1,8 @@ +---toml +title = "To-Do List" +--- # to-do list - Wearable Variable Power Supply - Arc Lighter - Long-range WiFi Antenna with POE - diff --git a/serve/pogmom-suite.md b/serve/pogmom-suite.md new file mode 100644 index 0000000..0c718fb --- /dev/null +++ b/serve/pogmom-suite.md @@ -0,0 +1,15 @@ +---toml +title = "Pogmom Suite" +date_created = "2026-02-14" +index = 1 +--- + +# Pogmom Suite + +In response to predatory data collection, hostile platform siezure, and [enshittification](/vocab#enshittification) of the centralized internet, I host a collection of online services called the 'Pogmom Suite'. + +These services utilize federated social networking standards and rely on free and open source software as exclusively as possible. + +While security and practicality require that registration not be open to the general public, I am more than happy to offer advice and guidance to those interested in pursuing similar projects. + +[Learn More](https://suite.pogmom.me) diff --git a/vocab/test b/serve/vocab/test similarity index 100% rename from vocab/test rename to serve/vocab/test diff --git a/vocab/test.md b/serve/vocab/test.md similarity index 100% rename from vocab/test.md rename to serve/vocab/test.md diff --git a/vocab/test.txt b/serve/vocab/test.txt similarity index 100% rename from vocab/test.txt rename to serve/vocab/test.txt diff --git a/vocab/top-and-bottom-cables.md b/serve/vocab/top-and-bottom-cables.md similarity index 100% rename from vocab/top-and-bottom-cables.md rename to serve/vocab/top-and-bottom-cables.md diff --git a/src/lib/curl.rs b/src/lib/curl.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/lib/html.rs b/src/lib/html.rs new file mode 100644 index 0000000..71257ad --- /dev/null +++ b/src/lib/html.rs @@ -0,0 +1,75 @@ +use crate::markdowner::MarkdownModule; +use warp::Reply; + +fn get_header_html(page_contents: &Vec) -> String { + let header = page_contents + .iter() + .find(|m| m.path.file_name().unwrap_or_default().eq("header.md")); + match header { + Some(h) => markdown::to_html_with_options(h.content.as_str(), &markdown::Options::gfm()) + .unwrap_or_default(), + None => "".to_string(), + } +} + +fn get_content_html(page_contents: &Vec) -> String { + let content: Vec<&MarkdownModule> = page_contents + .iter() + .filter(|m| m.path.file_name().unwrap_or_default().ne("header.md")) + .collect(); + let content_html: Vec = content + .iter() + .filter_map(|m| { + markdown::to_html_with_options(m.content.as_str(), &markdown::Options::gfm()) + .ok() + .and_then(|c| { + format!( + "
{}
", + m.path + .file_stem() + .unwrap_or_default() + .to_str() + .unwrap_or_default(), + c + ) + .into() + }) + }) + .collect(); + content_html.join("\n") +} + +fn fill_template( + header_html: String, + content_html: String, + sidebar_html: String, + page_title: String, +) -> String { + let template_html = std::fs::read_to_string("./serve/assets/templates/page.html") + .expect("could not read page.html template"); + let template = text_template::Template::from(template_html.as_str()); + let mut values = std::collections::HashMap::new(); + values.insert("title", page_title.as_str()); + values.insert("header", header_html.as_str()); + values.insert("sidebar", sidebar_html.as_str()); + values.insert("content", content_html.as_str()); + template.fill_in(&values).to_string() +} + +pub fn html_response( + page_contents: Vec, + sidebar_contents: Vec, + page_title: String, +) -> Box { + let header_html = get_header_html(&page_contents); + + let content_html = get_content_html(&page_contents); + let sidebar_html = get_content_html(&sidebar_contents); + + Box::new(warp::reply::html(fill_template( + header_html, + content_html, + sidebar_html, + page_title, + ))) +} diff --git a/src/lib/markdowner.rs b/src/lib/markdowner.rs new file mode 100644 index 0000000..c2d7862 --- /dev/null +++ b/src/lib/markdowner.rs @@ -0,0 +1,88 @@ +use std::path::PathBuf; + +#[derive(serde::Deserialize, Debug)] +pub struct FrontMatter { + pub title: String, + pub date_created: Option, + pub date_updated: Option, + pub index: Option, +} +#[derive(Debug)] +pub struct MarkdownModule { + pub path: PathBuf, + pub content: String, + pub metadata: FrontMatter, +} + +fn build_markdown_module(markdown_path: &PathBuf) -> Option { + std::fs::read_to_string(markdown_path).ok().map(|t| { + match toml_frontmatter::parse::(t.as_str()) { + Ok((fm, md)) => MarkdownModule { + path: markdown_path.to_owned(), + content: md.to_string(), + metadata: fm, + }, + Err(_) => MarkdownModule { + path: markdown_path.to_owned(), + content: t.to_string(), + metadata: FrontMatter { + title: markdown_path + .file_stem() + .unwrap_or_default() + .to_str() + .unwrap_or_default() + .to_string(), + date_created: None, + date_updated: None, + index: None, + }, + }, + } + }) +} + +pub fn get_markdown_modules(target_path: &PathBuf) -> Vec { + //if target_path.exists() {} + + let mut mds: Vec = std::fs::read_dir(target_path.clone()) + .expect("could not read target directory") + .filter_map(|d| { + println!("found file! {:?}", d); + d.ok().and_then(|f| build_markdown_module(&f.path())) + }) + .collect(); + mds.sort_by_key(|e| e.metadata.index); + mds + //println!("{:#?}", mds); + /*for md in mds { + println!("title: {:?}", md.metadata.title); + println!("path: {:?}", md.path); + println!("content: {:?}", md.content); + }*/ + + /*std::fs::read_dir(target_path.clone()) + .unwrap() + .filter(|x| { + x.as_ref() + .unwrap() + .path() + .extension() + .unwrap_or_default() + .eq("md") + && !x.as_ref().unwrap().file_name().eq("header.md") + }) + .map(|x| x.unwrap().path()) + .collect();*/ + + /*let test = MarkdownModule { + path: "".to_owned().into(), + content: "".to_string(), + metadata: Some(FrontMatter { + title: "".to_string(), + date_created: Some("".to_string()), + date_updated: Some("".to_string()), + index: Some(0), + }), + }; + vec![test]*/ +} diff --git a/src/lib/sidebar.rs b/src/lib/sidebar.rs new file mode 100644 index 0000000..e227459 --- /dev/null +++ b/src/lib/sidebar.rs @@ -0,0 +1,3 @@ +pub fn sidebar_content() -> Vec { + vec!["test".to_string()] +} diff --git a/src/main.rs b/src/main.rs index 8befef1..e57d029 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,141 +1,140 @@ #![warn(unused_extern_crates)] #![allow(clippy::style)] + use std::{path::PathBuf, str::FromStr}; +use http::uri::Authority; use lipgloss::Border; use mq_markdown::{ColorTheme, ListStyle, RenderOptions, UrlSurroundStyle}; use mq_view::{RenderConfig, render_markdown_with_config}; use warp::{Filter, filters::path::FullPath}; +#[path = "lib/html.rs"] +mod html; +#[path = "lib/markdowner.rs"] +mod markdowner; +#[path = "lib/sidebar.rs"] +mod sidebar; +use crate::{ + html::html_response, + markdowner::{FrontMatter, MarkdownModule}, +}; +use sidebar::sidebar_content; + +fn router(request_path: PathBuf) -> PathBuf { + std::env::current_dir() + .expect("unable to determine current directory") + .join("serve") + .join(request_path) +} fn renderer(path: FullPath, user_agent: String) -> Box { - let time = chrono::Local::now().to_rfc2822(); + //let time = chrono::Local::now().to_rfc2822(); println!("{:?} requested by {}", path, user_agent); - let path_as_buf = PathBuf::from_str(path.as_str()) - .unwrap_or_default() - .strip_prefix("/") - .unwrap() - .to_owned(); - let target_path = std::env::current_dir() - .expect("could not determine current directory") - .join(path_as_buf); - - if target_path.exists() { - let page_contents: Vec = match target_path.is_dir() { - true => std::fs::read_dir(target_path) - .unwrap() - .filter(|x| { - x.as_ref() - .unwrap() - .path() - .extension() - .unwrap_or_default() - .eq("md") - }) - .map(|x| x.unwrap().path()) - .collect(), - false => vec![target_path], - }; - - if user_agent.starts_with("curl/") { - println!("displaying curl formatting"); - let page_markdowns: Vec = page_contents - .iter() - .map(|x| { - let source = std::fs::read_to_string(x).unwrap(); - let mut mq: mq_markdown::Markdown = source.parse().unwrap(); - let render_opts = RenderOptions { - list_style: ListStyle::Dash, - link_url_style: UrlSurroundStyle::None, - link_title_style: mq_markdown::TitleSurroundStyle::Single, - }; - mq.set_options(render_opts); - let theme = ColorTheme::parse_colors("heading=34:code=31"); - mq.to_colored_string_with_theme(&theme); - let render_conf = RenderConfig { - header_full_width_highlight: false, - }; - - let _styled_mq = mq_view::render_markdown_to_string(&mq).unwrap(); - - let mut writer: Vec = Vec::new(); - - render_markdown_with_config(&mq, &mut writer, &render_conf).unwrap(); - - let render_string = String::from_utf8(writer).unwrap(); - - println!("{}", render_string); - - let _md = mdriver::StreamingParser::new().feed( - termimad::text(std::fs::read_to_string(x).unwrap_or_default().as_str()) - .to_string() - .as_str(), - ); - let border_style = lipgloss::Style::new() - .border(Border::new( - "─", "─", "│", "│", "╭", "╮", "╰", "╯", "", "", "", "", "", - )) - .width(80) - .padding(0, 2, 0, 2) - .align_horizontal(lipgloss::position::CENTER); - border_style.render(render_string.as_str()) - }) - .collect(); - - for c in &page_markdowns { - println!("{}\n", c); - } - let page_md_collected = format!("{}\n", page_markdowns.join("\n")); - - Box::new(warp::reply::with_status( - page_md_collected, - warp::http::StatusCode::OK, - )) - } else { - println!("displaying html formatting"); - let page_md_packed: Vec = page_contents - .iter() - .map(|x| { - format!( - "
{}
", - x.file_stem() - .unwrap_or_default() - .to_str() - .unwrap_or_default(), - markdown::to_html_with_options( - std::fs::read_to_string(x).unwrap_or_default().as_str(), - &markdown::Options::gfm() - ) - .unwrap_or_default() - ) - }) - .collect(); - let page_md_collected = page_md_packed.join("\n"); - let template_html = - std::fs::read_to_string("./assets/template.html").unwrap_or_default(); - let template = text_template::Template::from(template_html.as_str()); - let mut values = std::collections::HashMap::new(); - values.insert("time", time.as_str()); - values.insert("body", page_md_collected.as_str()); - let html = template.fill_in(&values); - Box::new(warp::reply::html(html.to_string())) - } - } else { - println!("could not find path!"); - Box::new(warp::reply::with_status( - "uh oh", - warp::http::StatusCode::NOT_FOUND, - )) + let request_path: PathBuf = path.as_str().strip_prefix("/").unwrap_or_default().into(); + let target_path = router(request_path); + if !target_path.exists() || target_path.is_file() { + return Box::new(warp::redirect( + warp::http::uri::Builder::new() + .authority(".") + .build() + .unwrap(), + )); } + + println!("serving path: {:?}", target_path); + + let page_contents = markdowner::get_markdown_modules(&target_path); + let sidebar_dir = PathBuf::from("assets/sidebar/"); + let sidebar_contents = markdowner::get_markdown_modules(&router(sidebar_dir)); + + let response = if user_agent.starts_with("curl/") { + todo!("reimplement curl return") + } else { + html_response( + page_contents, + sidebar_contents, + target_path + .file_stem() + .unwrap_or_default() + .to_str() + .unwrap_or_default() + .to_owned(), + ) + }; + response + + /* + if user_agent.starts_with("curl/") { + println!("displaying curl formatting"); + let page_markdowns: Vec = page_contents + .iter() + .map(|x| { + let source = std::fs::read_to_string(x).unwrap(); + let mut mq: mq_markdown::Markdown = source.parse().unwrap(); + let render_opts = RenderOptions { + list_style: ListStyle::Dash, + link_url_style: UrlSurroundStyle::None, + link_title_style: mq_markdown::TitleSurroundStyle::Single, + }; + mq.set_options(render_opts); + let theme = ColorTheme::parse_colors("heading=34:code=31"); + mq.to_colored_string_with_theme(&theme); + let render_conf = RenderConfig { + header_full_width_highlight: false, + }; + + let _styled_mq = mq_view::render_markdown_to_string(&mq).unwrap(); + + let mut writer: Vec = Vec::new(); + + render_markdown_with_config(&mq, &mut writer, &render_conf).unwrap(); + + let render_string = String::from_utf8(writer).unwrap(); + + println!("{}", render_string); + + let _md = mdriver::StreamingParser::new().feed( + termimad::text(std::fs::read_to_string(x).unwrap_or_default().as_str()) + .to_string() + .as_str(), + ); + let border_style = lipgloss::Style::new() + .border(Border::new( + "─", "─", "│", "│", "╭", "╮", "╰", "╯", "", "", "", "", "", + )) + .width(80) + .padding(0, 2, 0, 2) + .align_horizontal(lipgloss::position::LEFT); + border_style.render(render_string.as_str()) + }) + .collect(); + + for c in &page_markdowns { + println!("{}\n", c); + } + let page_md_collected = format!("{}\n", page_markdowns.join("\n")); + + Box::new(warp::reply::with_status( + page_md_collected, + warp::http::StatusCode::OK, + )) + }*/ } #[tokio::main] async fn main() { println!("Hello, world!"); + let assets = warp::path("assets").and(warp::fs::dir("./serve/assets/")); + let favicon = warp::path("favicon.ico").and(warp::fs::file("./serve/favicon.ico")); - let readme = warp::any() //path::end() + // let no_meta = warp:: + + let markdowns = warp::any() //path::end() .and(warp::path::full()) .and(warp::header("user-agent")) .map(|path: FullPath, agent: String| renderer(path, agent)); - warp::serve(readme).run(([127, 0, 0, 1], 3030)).await; + let routes = favicon.or(assets).or(markdowns); + + warp::serve(routes).run(([127, 0, 0, 1], 3030)).await; }