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 @@
+[](https://git.pogmom.me/pogmommy/pogmomme/src/branch/main/assets/img/webring/pogmommy/)
+
+[](https://cassiecandles.net)
+
+[](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 @@
+
+
+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}
+
+
+
+
+
+
+
+
+
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}
+
+
+
+
+
+
+
+
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

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;
}