diff --git a/Cargo.lock b/Cargo.lock index 259c166..63835d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -78,9 +78,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.100" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +checksum = "5f0e0fee31ef5ed1ba1316088939cea399010ed7731dba877ed44aeb407a75ea" [[package]] name = "atomic-waker" @@ -96,9 +96,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "aws-lc-rs" -version = "1.15.2" +version = "1.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88aab2464f1f25453baa7a07c84c5b7684e274054ba06817f382357f77a288" +checksum = "7b7b6141e96a8c160799cc2d5adecd5cbbe5054cb8c7c4af53da0f83bb7ad256" dependencies = [ "aws-lc-sys", "zeroize", @@ -106,9 +106,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.35.0" +version = "0.37.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45afffdee1e7c9126814751f88dddc747f41d91da16c9551a0f1e8a11e788a1" +checksum = "b092fe214090261288111db7a2b2c2118e5a7f30dc2569f1732c4069a6840549" dependencies = [ "cc", "cmake", @@ -198,27 +198,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "blog" -version = "0.1.0" -dependencies = [ - "anyhow", - "axum", - "chrono", - "clap", - "lazy_static", - "pulldown-cmark", - "pulldown-cmark-escape", - "reqwest", - "serde", - "syntect", - "tera", - "tokio", - "tower-http", - "tracing", - "tracing-subscriber", -] - [[package]] name = "bstr" version = "1.12.1" @@ -237,15 +216,15 @@ checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" [[package]] name = "bytes" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" [[package]] name = "cc" -version = "1.2.51" +version = "1.2.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a0aeaff4ff1a90589618835a598e545176939b97874f7abc7851caa0618f203" +checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" dependencies = [ "find-msvc-tools", "jobserver", @@ -273,9 +252,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.42" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" +checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118" dependencies = [ "iana-time-zone", "js-sys", @@ -308,9 +287,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.54" +version = "4.5.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394" +checksum = "63be97961acde393029492ce0be7a1af7e323e6bae9511ebfac33751be5e6806" dependencies = [ "clap_builder", "clap_derive", @@ -318,9 +297,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.54" +version = "4.5.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa42cf4d2b7a41bc8f663a7cab4031ebafa1bf3875705bfaf8466dc60ab52c00" +checksum = "7f13174bda5dfd69d7e947827e5af4b0f2f94a4a3ee92912fba07a66150f21e2" dependencies = [ "anstream", "anstyle", @@ -330,9 +309,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.49" +version = "4.5.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" +checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" dependencies = [ "heck", "proc-macro2", @@ -342,9 +321,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.6" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" +checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" [[package]] name = "cmake" @@ -452,9 +431,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" +checksum = "cc3dc5ad92c2e2d1c193bbbbdf2ea477cb81331de4f3103f267ca18368b988c4" dependencies = [ "powerfmt", ] @@ -519,15 +498,15 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.6" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645cbb3a84e60b7531617d5ae4e57f7e27308f6445f5abf653209ea76dec8dff" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] name = "flate2" -version = "1.1.5" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" dependencies = [ "crc32fast", "miniz_oxide", @@ -625,9 +604,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "js-sys", @@ -738,6 +717,12 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "http-range-header" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9171a2ea8a68358193d15dd5d70c1c10a2afc3e7e4c5bc92bc9f025cebd7359c" + [[package]] name = "httparse" version = "1.10.1" @@ -800,14 +785,13 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ "base64", "bytes", "futures-channel", - "futures-core", "futures-util", "http", "http-body", @@ -826,9 +810,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.64" +version = "0.1.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -968,12 +952,14 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.12.1" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" dependencies = [ "equivalent", "hashbrown", + "serde", + "serde_core", ] [[package]] @@ -1038,9 +1024,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.83" +version = "0.3.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" +checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" dependencies = [ "once_cell", "wasm-bindgen", @@ -1054,15 +1040,15 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.179" +version = "0.2.182" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5a2d376baa530d1238d133232d15e239abad80d05838b4b59354e5268af431f" +checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" [[package]] name = "libm" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "linked-hash-map" @@ -1105,9 +1091,9 @@ checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" [[package]] name = "memchr" -version = "2.7.6" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "mime" @@ -1115,6 +1101,16 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "miniz_oxide" version = "0.8.9" @@ -1147,9 +1143,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" [[package]] name = "num-traits" @@ -1196,9 +1192,9 @@ dependencies = [ [[package]] name = "openssl-probe" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f50d9b3dabb09ecd771ad0aa242ca6894994c130308ca3d7684634df8037391" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "parking_lot" @@ -1240,9 +1236,9 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.8.5" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9eb05c21a464ea704b53158d358a31e6425db2f63a1a7312268b05fe2b75f7" +checksum = "e0848c601009d37dfa3430c4666e147e49cdcf1b92ecd3e63657d8a5f19da662" dependencies = [ "memchr", "ucd-trie", @@ -1250,9 +1246,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.8.5" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f9dbced329c441fa79d80472764b1a2c7e57123553b8519b36663a2fb234ed" +checksum = "11f486f1ea21e6c10ed15d5a7c77165d0ee443402f0780849d1768e7d9d6fe77" dependencies = [ "pest", "pest_generator", @@ -1260,9 +1256,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.8.5" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bb96d5051a78f44f43c8f712d8e810adb0ebf923fc9ed2655a7f66f63ba8ee5" +checksum = "8040c4647b13b210a963c1ed407c1ff4fdfa01c31d6d2a098218702e6664f94f" dependencies = [ "pest", "pest_meta", @@ -1273,9 +1269,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.8.5" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "602113b5b5e8621770cfd490cfd90b9f84ab29bd2b0e49ad83eb6d186cef2365" +checksum = "89815c69d36021a140146f26659a81d6c2afa33d216d736dd4be5381a7362220" dependencies = [ "pest", "sha2", @@ -1376,9 +1372,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.105" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] @@ -1425,7 +1421,7 @@ dependencies = [ "rustc-hash", "rustls", "socket2", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tracing", "web-time", @@ -1447,7 +1443,7 @@ dependencies = [ "rustls", "rustls-pki-types", "slab", - "thiserror 2.0.17", + "thiserror 2.0.18", "tinyvec", "tracing", "web-time", @@ -1469,9 +1465,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.43" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" dependencies = [ "proc-macro2", ] @@ -1500,7 +1496,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ "rand_chacha 0.9.0", - "rand_core 0.9.3", + "rand_core 0.9.5", ] [[package]] @@ -1520,7 +1516,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.3", + "rand_core 0.9.5", ] [[package]] @@ -1529,14 +1525,14 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", ] [[package]] name = "rand_core" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" dependencies = [ "getrandom 0.3.4", ] @@ -1552,9 +1548,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.12.2" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", @@ -1564,9 +1560,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", @@ -1575,15 +1571,15 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" +checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" [[package]] name = "reqwest" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04e9018c9d814e5f30cc16a0f03271aeab3571e609612d9fe78c1aa8d11c2f62" +checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" dependencies = [ "base64", "bytes", @@ -1627,7 +1623,7 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.16", + "getrandom 0.2.17", "libc", "untrusted", "windows-sys 0.52.0", @@ -1667,9 +1663,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.13.2" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e6f2ab2928ca4291b86736a8bd920a277a399bba1589409d72154ff87c1282" +checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" dependencies = [ "web-time", "zeroize", @@ -1704,9 +1700,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" [[package]] name = "rustls-webpki" -version = "0.103.8" +version = "0.103.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" +checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53" dependencies = [ "aws-lc-rs", "ring", @@ -1722,9 +1718,9 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] name = "same-file" @@ -1827,6 +1823,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "serde_spanned" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -1883,15 +1888,15 @@ checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" [[package]] name = "siphasher" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" +checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" [[package]] name = "slab" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "slug" @@ -1911,9 +1916,9 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "socket2" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" dependencies = [ "libc", "windows-sys 0.60.2", @@ -1939,9 +1944,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.114" +version = "2.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" +checksum = "6e614ed320ac28113fa64972c4262d5dbc89deacdfd00c34a3e4cea073243c12" dependencies = [ "proc-macro2", "quote", @@ -1984,16 +1989,16 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", "walkdir", "yaml-rust", ] [[package]] name = "system-configuration" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" dependencies = [ "bitflags", "core-foundation 0.9.4", @@ -2043,11 +2048,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl 2.0.17", + "thiserror-impl 2.0.18", ] [[package]] @@ -2063,9 +2068,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", @@ -2083,30 +2088,30 @@ dependencies = [ [[package]] name = "time" -version = "0.3.44" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", "itoa", "num-conv", "powerfmt", - "serde", + "serde_core", "time-core", "time-macros", ] [[package]] name = "time-core" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.24" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" dependencies = [ "num-conv", "time-core", @@ -2189,10 +2194,51 @@ dependencies = [ ] [[package]] -name = "tower" -version = "0.5.2" +name = "toml" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "toml_write", + "winnow", +] + +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + +[[package]] +name = "tower" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", @@ -2212,14 +2258,24 @@ checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ "bitflags", "bytes", + "futures-core", "futures-util", "http", "http-body", + "http-body-util", + "http-range-header", + "httpdate", "iri-string", + "mime", + "mime_guess", + "percent-encoding", "pin-project-lite", + "tokio", + "tokio-util", "tower", "tower-layer", "tower-service", + "tracing", ] [[package]] @@ -2318,9 +2374,9 @@ checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" [[package]] name = "unicode-ident" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" +checksum = "537dd038a89878be9b64dd4bd1b260315c1bb94f4d784956b81e27a088d9a09e" [[package]] name = "unicode-segmentation" @@ -2403,18 +2459,18 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.1+wasi-0.2.4" +version = "1.0.2+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" dependencies = [ "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.106" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" +checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566" dependencies = [ "cfg-if", "once_cell", @@ -2425,11 +2481,12 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.56" +version = "0.4.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c" +checksum = "70a6e77fd0ae8029c9ea0063f87c46fde723e7d887703d74ad2616d792e51e6f" dependencies = [ "cfg-if", + "futures-util", "js-sys", "once_cell", "wasm-bindgen", @@ -2438,9 +2495,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.106" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" +checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2448,9 +2505,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.106" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" +checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" dependencies = [ "bumpalo", "proc-macro2", @@ -2461,18 +2518,18 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.106" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" +checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12" dependencies = [ "unicode-ident", ] [[package]] name = "web-sys" -version = "0.3.83" +version = "0.3.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" +checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598" dependencies = [ "js-sys", "wasm-bindgen", @@ -2490,13 +2547,36 @@ dependencies = [ [[package]] name = "webpki-root-certs" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36a29fc0408b113f68cf32637857ab740edfafdf460c326cd2afaa2d84cc05dc" +checksum = "804f18a4ac2676ffb4e8b5b5fa9ae38af06df08162314f96a68d2a363e21a8ca" dependencies = [ "rustls-pki-types", ] +[[package]] +name = "wiki-maker" +version = "0.1.0" +dependencies = [ + "anyhow", + "axum", + "chrono", + "clap", + "indexmap", + "lazy_static", + "pulldown-cmark", + "pulldown-cmark-escape", + "reqwest", + "serde", + "syntect", + "tera", + "tokio", + "toml", + "tower-http", + "tracing", + "tracing-subscriber", +] + [[package]] name = "winapi-util" version = "0.1.11" @@ -2799,10 +2879,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] -name = "wit-bindgen" -version = "0.46.0" +name = "winnow" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" [[package]] name = "writeable" @@ -2844,18 +2933,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.32" +version = "0.8.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fabae64378cb18147bb18bca364e63bdbe72a0ffe4adf0addfec8aa166b2c56" +checksum = "db6d35d663eadb6c932438e763b262fe1a70987f9ae936e60158176d710cae4a" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.32" +version = "0.8.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9c2d862265a8bb4471d87e033e730f536e2a285cc7cb05dbce09a2a97075f90" +checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517" dependencies = [ "proc-macro2", "quote", @@ -2924,6 +3013,6 @@ dependencies = [ [[package]] name = "zmij" -version = "1.0.12" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fc5a66a20078bf1251bde995aa2fdcc4b800c70b5d92dd2c62abc5c60f679f8" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/Cargo.toml b/Cargo.toml index cad5f3e..b7f052a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "blog" +name = "wiki-maker" version = "0.1.0" edition = "2024" @@ -15,9 +15,11 @@ serde = { version = "1.0.228", features = ["derive"] } syntect = "5.3.0" tera = "1.20.1" tokio = { version = "1.49.0", features = ["full"] } -tower-http = { version = "0.6.8", features = ["cors"] } +tower-http = { version = "0.6.8", features = ["cors", "fs"] } tracing = "0.1.44" tracing-subscriber = "0.3.22" +toml = "0.8.19" +indexmap = { version = "2.7.1", features = ["serde"] } [build-dependencies] reqwest = { version = "0.13.1", features = ["blocking"] } diff --git a/example/azrak.md b/example/azrak.md new file mode 100644 index 0000000..672bb8b --- /dev/null +++ b/example/azrak.md @@ -0,0 +1,31 @@ +# Azrak the Wall-Eater + +Azrak does not eat food. + +Azrak eats **structures**. + +Concrete. +Drywall. +The concept of shelter. + +--- + +## Lore + +When humans invented houses, Azrak woke up. + +Every abandoned building is believed to be a corpse. + +--- + +## Family + +- Mother: [Voidmother](voidmother) +- Sister: [Lumina](lumina) + +--- + +## Fun Fact + +Azrak once ate half a shopping mall because a light flickered funny. + diff --git a/example/azrak.toml b/example/azrak.toml new file mode 100644 index 0000000..2c2b9e0 --- /dev/null +++ b/example/azrak.toml @@ -0,0 +1,11 @@ +title = "Azrak the Wall-Eater" +image = "azrak.png" +content_file = "azrak.md" + +[infobox] +"Espèce" = "Devourer Papoute" +"Genre" = "M" +"Domain" = "Hunger & Destruction" +"Enemy of" = "Entire buildings" +"Mother" = "Voidmother" + diff --git a/example/bernardo.md b/example/bernardo.md new file mode 100644 index 0000000..482b37c --- /dev/null +++ b/example/bernardo.md @@ -0,0 +1,5 @@ +## Biographie +Bernardo est un Papoute commun. Il est souvent considéré en tant qu'example de l'espèce, de par sa simplicité faciale et le parfait alignement de ses pates. + +## Répliques +> ... diff --git a/example/bernardo.png b/example/bernardo.png new file mode 100755 index 0000000..1df10b6 Binary files /dev/null and b/example/bernardo.png differ diff --git a/example/bernardo.toml b/example/bernardo.toml new file mode 100644 index 0000000..4c158a2 --- /dev/null +++ b/example/bernardo.toml @@ -0,0 +1,9 @@ +title = "Bernardo" +image = "bernardo.png" +content_file = "bernardo.md" + +[infobox] +"Espèce" = "Papoute Commun" +Genre = "H" +"Lieu d'habitation" = "Inside your walls" +"Créateur" = "Papoute god?" diff --git a/example/coffee@1767815445.md b/example/coffee@1767815445.md deleted file mode 100644 index 30bacbc..0000000 --- a/example/coffee@1767815445.md +++ /dev/null @@ -1,14 +0,0 @@ -# The Dark Elixir: A History of Coffee - -Coffee is more than just a drink; it's a global phenomenon. Legend has it that a goat herder named Kaldi discovered coffee in Ethiopia after noticing his goats became very energetic after eating berries from a certain tree. - -### Common Coffee Roasts - -| Roast | Color | Oil on Surface | Flavor Profile | -| :--- | :--- | :--- | :--- | -| **Light** | Light Brown | None | Toasted grain, high acidity | -| **Medium** | Medium Brown | Rare | Balanced flavor, aroma | -| **Dark** | Shiny Black | Heavy | Bitter, smoky, or burnt | - ---- -**Fun Fact:** Coffee is actually a fruit! The "beans" are the pits of a cherry-like berry. diff --git a/example/ferris@1767468388.md b/example/ferris@1767468388.md deleted file mode 100644 index 225f25f..0000000 --- a/example/ferris@1767468388.md +++ /dev/null @@ -1,16 +0,0 @@ -# The Mascot: Ferris - -**Ferris** is the unofficial mascot of the Rust community. He is a crab because Rust programmers often call themselves "Rustaceans" (a play on the word crustacean). - -### Why a crab? -- Rustaceans are known for being friendly and helpful. -- Crabs have hard shells (like Rust's safety guarantees). -- They have powerful claws (like Rust's powerful type system). - -```rust -fn main() { - println!("Hello from Ferris!"); -} -``` - -> "The Rust community is one of the most welcoming in the tech world." diff --git a/example/lumina.md b/example/lumina.md new file mode 100644 index 0000000..229ae6e --- /dev/null +++ b/example/lumina.md @@ -0,0 +1,28 @@ +# Lumina the Warm One + +Lumina is the reason blankets feel safe. + +She lives inside warm air vents, sunsets, and the feeling of soup. + +--- + +## Personality + +- Gentle +- Massive cosmic being +- Will still destroy stars if annoyed + +--- + +## Child + +Her smallest creation: + +- [Bernardo](bernardo) + +--- + +## Enemy + +- [Azrak](azrak) (he keeps eating her favorite houses) + diff --git a/example/lumina.toml b/example/lumina.toml new file mode 100644 index 0000000..b566fe7 --- /dev/null +++ b/example/lumina.toml @@ -0,0 +1,11 @@ +title = "Lumina the Warm One" +image = "lumina.png" +content_file = "lumina.md" + +[infobox] +"Espèce" = "Radiant Papoute" +"Genre" = "F" +"Domain" = "Comfort & heat" +"Children" = "Bernardo" +"Mother" = "Voidmother" + diff --git a/example/space@1767813388.md b/example/space@1767813388.md deleted file mode 100644 index 7b7ad9f..0000000 --- a/example/space@1767813388.md +++ /dev/null @@ -1,17 +0,0 @@ -# To the Stars: Voyager 1 - -Voyager 1 is a space probe launched by NASA on September 5, 1977. As of today, it is the most distant human-made object from Earth. - -### Voyager 1 Mission Checklist -- [x] Flyby of Jupiter (1979) -- [x] Flyby of Saturn (1980) -- [x] Enter Interstellar Space (2012) -- [ ] Reach the next star (Estimated in 40,000 years) - -### The Golden Record -The probe carries a gold-plated audio-visual disc in case it is ever found by intelligent life. It contains: -- Greetings in 55 languages. -- Sounds of whales, a baby crying, and waves breaking. -- Music by Bach, Mozart, and Chuck Berry. - -> "The Voyager mission is a testament to human curiosity and our desire to touch the stars." diff --git a/example/voidmother.md b/example/voidmother.md new file mode 100644 index 0000000..c826ed6 --- /dev/null +++ b/example/voidmother.md @@ -0,0 +1,32 @@ +# Voidmother + +Voidmother is not born. + +Voidmother **happened**. + +Before walls existed. +Before warmth existed. +Before Papoutes learned how to hide inside radiators. + +She tore reality like wet paper and leaked children into existence. + +--- + +## Offspring + +- [Azrak the Wall-Eater](azrak) +- [Lumina the Warm One](lumina) +- [Grubble](grubble) + +--- + +## Known Abilities + +- Creates Papoutes by accident +- Consumes timelines when annoyed +- Whispers inside electrical outlets + +> Some say Bernardo can hear her when the house is quiet. + +And she hears him too. + diff --git a/example/voidmother.toml b/example/voidmother.toml new file mode 100644 index 0000000..4570db9 --- /dev/null +++ b/example/voidmother.toml @@ -0,0 +1,11 @@ +title = "Voidmother" +image = "voidmother.png" +content_file = "voidmother.md" + +[infobox] +"Espèce" = "Primordial Papoute" +"Genre" = "Beyond gender" +"Rôle cosmique" = "Origin of all papoutes" +"Tempérament" = "Indescribable horror" +"Présence" = "Between dimensions" + diff --git a/flake.lock b/flake.lock deleted file mode 100644 index 39feaa9..0000000 --- a/flake.lock +++ /dev/null @@ -1,109 +0,0 @@ -{ - "nodes": { - "code-theme": { - "flake": false, - "locked": { - "narHash": "sha256-28LGXKITHbrmt6qrcG/W+qTlaWthre7x7izp/TPjQgA=", - "type": "file", - "url": "https://raw.githubusercontent.com/catppuccin/bat/refs/heads/main/themes/Catppuccin%20Macchiato.tmTheme" - }, - "original": { - "type": "file", - "url": "https://raw.githubusercontent.com/catppuccin/bat/refs/heads/main/themes/Catppuccin%20Macchiato.tmTheme" - } - }, - "flake-utils": { - "inputs": { - "systems": "systems" - }, - "locked": { - "lastModified": 1731533236, - "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "nixpkgs": { - "locked": { - "lastModified": 1767767207, - "narHash": "sha256-Mj3d3PfwltLmukFal5i3fFt27L6NiKXdBezC1EBuZs4=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "5912c1772a44e31bf1c63c0390b90501e5026886", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_2": { - "locked": { - "lastModified": 1744536153, - "narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "18dd725c29603f582cf1900e0d25f9f1063dbf11", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "root": { - "inputs": { - "code-theme": "code-theme", - "flake-utils": "flake-utils", - "nixpkgs": "nixpkgs", - "rust-overlay": "rust-overlay" - } - }, - "rust-overlay": { - "inputs": { - "nixpkgs": "nixpkgs_2" - }, - "locked": { - "lastModified": 1767754000, - "narHash": "sha256-znoNJs2QZFl+wCFLd6FbUJ00c74kvzOjyQYXc45uFvo=", - "owner": "oxalica", - "repo": "rust-overlay", - "rev": "0b3a5ad260479f2c9bdadf3ba5b2a4be359cfcdd", - "type": "github" - }, - "original": { - "owner": "oxalica", - "repo": "rust-overlay", - "type": "github" - } - }, - "systems": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - } - }, - "root": "root", - "version": 7 -} diff --git a/flake.nix b/flake.nix index 228d350..f9e8b4d 100644 --- a/flake.nix +++ b/flake.nix @@ -1,5 +1,5 @@ { - description = "Blog website"; + description = "Wiki maker"; inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; @@ -12,8 +12,16 @@ }; }; - outputs = { nixpkgs, flake-utils, rust-overlay, code-theme, ... }: - flake-utils.lib.eachDefaultSystem (system: + outputs = + { + nixpkgs, + flake-utils, + rust-overlay, + code-theme, + ... + }: + flake-utils.lib.eachDefaultSystem ( + system: let overlays = [ rust-overlay.overlays.default ]; pkgs = import nixpkgs { @@ -24,7 +32,7 @@ in { packages.default = pkgs.rustPlatform.buildRustPackage { - pname = "blog"; + pname = "wiki-maker"; version = "0.1.0"; src = ./.; @@ -60,5 +68,6 @@ OPENSSL_DIR = openssl.dev; PKG_CONFIG_PATH = "${openssl.dev}/lib/pkgconfig"; }; - }); + } + ); } diff --git a/src/main.rs b/src/main.rs index 8432836..b2940d9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use ax_models::Page; +use ax_models::{Page, WikiConfig}; use axum::{ Router, extract::{Path, State}, @@ -13,7 +13,6 @@ use std::sync::Arc; use std::{io::Cursor, path::PathBuf}; use syntect::{highlighting::ThemeSet, parsing::SyntaxSet}; use tera::{Context, Tera}; -use tokio::io::{AsyncBufReadExt, BufReader}; mod codeblocks; use codeblocks::*; @@ -48,7 +47,7 @@ lazy_static! { } #[derive(Parser)] -#[command(author, version, about = "A simple markdown book server/builder")] +#[command(author, version, about = "A simple wiki server/builder")] struct Cli { #[command(subcommand)] command: Commands, @@ -56,33 +55,21 @@ struct Cli { #[derive(Subcommand)] enum Commands { - /// Serve the markdown files dynamically Serve { - /// Path to the directory containing markdown files + #[arg(short, long)] path: PathBuf, - - /// Whether the home page and navbar should be removed #[arg(short, long)] no_navigation: bool, - - /// Port to listen on - #[arg(short, long, default_value = "3456")] + #[arg(short = 'P', long, default_value = "8090")] port: u16, - - /// Whether to serve on 0.0.0.0 (local network) #[arg(short = 'H', long)] host: bool, }, - /// Build static HTML files from the markdown directory Build { - /// Path to the directory containing markdown files + #[arg(short, long)] path: PathBuf, - - /// Whether the home page and navbar should be removed #[arg(short, long)] no_navigation: bool, - - /// Output directory (defaults to the input directory) #[arg(short, long)] out_dir: Option, }, @@ -118,6 +105,11 @@ async fn main() -> anyhow::Result<()> { .route("/", get(render_summary_handler)) .route("/{page}", get(render_page_handler)) .route("/style.css", get(serve_css)) + // Serve images relative to the docs directory + .nest_service( + "/assets", + tower_http::services::ServeDir::new(&shared_state.docs_dir), + ) .with_state(shared_state); let addr = if host { @@ -137,7 +129,6 @@ async fn main() -> anyhow::Result<()> { let abs_path = std::fs::canonicalize(&path)?; let output_path = out_dir.unwrap_or_else(|| abs_path.clone()); tokio::fs::create_dir_all(&output_path).await?; - run_build(abs_path, output_path, no_navigation).await?; } } @@ -149,48 +140,65 @@ async fn get_summary_data(docs_dir: &PathBuf) -> Vec { if let Ok(mut entries) = tokio::fs::read_dir(docs_dir).await { while let Ok(Some(entry)) = entries.next_entry().await { let path = entry.path(); - if path.extension().and_then(|s| s.to_str()) != Some("md") { + // We now look for TOML files as the entry points + if path.extension().and_then(|s| s.to_str()) != Some("toml") { continue; } let filename = entry.file_name(); let filename_str = filename.to_str().unwrap_or(""); - let title = if let Ok(file) = tokio::fs::File::open(&path).await { - let mut reader = BufReader::new(file); - let mut line = String::new(); - match reader.read_line(&mut line).await { - Ok(_) => line.trim_start_matches('#').trim().to_string(), - Err(_) => filename_str.to_string(), + // Read TOML to get the title + let title = if let Ok(content) = tokio::fs::read_to_string(&path).await { + if let Ok(config) = toml::from_str::(&content) { + config.title + } else { + filename_str.to_string() } } else { filename_str.to_string() }; - let datetime = filename_str - .split_once('@') - .and_then(|(_, ts_with_ext)| ts_with_ext.split('.').next()) - .map(|dt| dt.to_string()) - .unwrap_or_else(|| "Invalid Date".to_string()); + // TODO: + let datetime = "".to_string(); pages.push(Page { - filename: filename_str.to_string(), + filename: filename_str.to_string(), // Keep .toml extension here for now title, datetime, }); } } - pages.sort_by(|a, b| b.datetime.cmp(&a.datetime)); + pages.sort_by(|a, b| a.title.cmp(&b.title)); pages } -async fn render_markdown_to_html( - content: &str, +async fn render_wiki_page( filename: &str, docs_dir: &PathBuf, no_navigation: bool, is_static: bool, -) -> String { +) -> Result { + let toml_path = docs_dir.join(filename); + let toml_content = tokio::fs::read_to_string(&toml_path) + .await + .map_err(|_| "Page configuration not found".to_string())?; + + let config: WikiConfig = + toml::from_str(&toml_content).map_err(|e| format!("Invalid TOML configuration: {}", e))?; + + let markdown_content = if let Some(md_file) = &config.content_file { + let md_path = docs_dir.join(md_file); + tokio::fs::read_to_string(&md_path) + .await + .unwrap_or_else(|_| { + "# Content missing\nThe linked markdown file could not be found.".to_string() + }) + } else { + String::new() + }; + + // Render Markdown let mut options = Options::empty(); options.insert( Options::ENABLE_TABLES @@ -199,7 +207,7 @@ async fn render_markdown_to_html( | Options::ENABLE_TASKLISTS, ); - let parser = MarkdownParser::new_ext(content, options); + let parser = MarkdownParser::new_ext(&markdown_content, options); let renderer = CodeblockRenderer::new(parser); let mut html_output = String::new(); html::push_html(&mut html_output, renderer); @@ -210,21 +218,30 @@ async fn render_markdown_to_html( get_nav_links(docs_dir, filename) }; - // If building statically, rewrite .md links to .html if is_static { prev = prev.map(|s| { if s == "." { "index.html".to_string() } else { - s.replace(".md", ".html") + s.replace(".toml", ".html") } }); - next = next.map(|s| s.replace(".md", ".html")); + next = next.map(|s| s.replace(".toml", ".html")); } + let infobox_list: Vec = match config.infobox { + Some(map) => map + .into_iter() + .map(|(k, v)| InfoboxItem { key: k, value: v }) + .collect(), + None => Vec::new(), + }; + let mut context = Context::new(); - context.insert("title", filename); + context.insert("title", &config.title); context.insert("content", &html_output); + context.insert("infobox", &infobox_list); // Pass the ordered list, not the map + context.insert("main_image", &config.image); context.insert("prev_page", &prev); context.insert("next_page", &next); context.insert("no_navigation", &no_navigation); @@ -232,7 +249,7 @@ async fn render_markdown_to_html( TEMPLATES .render("page.html", &context) - .unwrap_or_else(|e| format!("Error: {}", e)) + .map_err(|e| format!("Template Error: {}", e)) } async fn run_build(docs_dir: PathBuf, out_dir: PathBuf, no_navigation: bool) -> anyhow::Result<()> { @@ -241,17 +258,16 @@ async fn run_build(docs_dir: PathBuf, out_dir: PathBuf, no_navigation: bool) -> // Build summary if !no_navigation { let pages = get_summary_data(&docs_dir).await; - // Rewrite filenames for static links in home page let static_pages: Vec = pages .into_iter() .map(|mut p| { - p.filename = p.filename.replace(".md", ".html"); + p.filename = p.filename.replace(".toml", ".html"); p }) .collect(); let mut context = Context::new(); - context.insert("title", "Pages"); + context.insert("title", "Wiki Index"); context.insert("files", &static_pages); context.insert("is_static", &true); @@ -263,19 +279,35 @@ async fn run_build(docs_dir: PathBuf, out_dir: PathBuf, no_navigation: bool) -> let css = TEMPLATES.render("style.css", &Context::new())?; tokio::fs::write(out_dir.join("style.css"), css).await?; + // Copy assets (images, etc) + // NOTE: In a real app you'd recursively copy everything not .md/.toml + // For now we just copy files that look like images if they are in root + let mut entries = tokio::fs::read_dir(&docs_dir).await?; + while let Some(entry) = entries.next_entry().await? { + let path = entry.path(); + if let Some(ext) = path.extension().and_then(|s| s.to_str()) { + if ["png", "jpg", "jpeg", "gif", "webp"].contains(&ext) { + let dest = out_dir.join(path.file_name().unwrap()); + tokio::fs::copy(path, dest).await?; + } + } + } + // Build pages let mut entries = tokio::fs::read_dir(&docs_dir).await?; while let Some(entry) = entries.next_entry().await? { let path = entry.path(); - if path.extension().and_then(|s| s.to_str()) == Some("md") { + if path.extension().and_then(|s| s.to_str()) == Some("toml") { let filename = entry.file_name().to_str().unwrap().to_string(); - let content = tokio::fs::read_to_string(&path).await?; - let rendered = - render_markdown_to_html(&content, &filename, &docs_dir, no_navigation, true).await; - let out_file = out_dir.join(filename.replace(".md", ".html")); - tokio::fs::write(out_file, rendered).await?; - tracing::info!("Generated {}", filename); + match render_wiki_page(&filename, &docs_dir, no_navigation, true).await { + Ok(rendered) => { + let out_file = out_dir.join(filename.replace(".toml", ".html")); + tokio::fs::write(out_file, rendered).await?; + tracing::info!("Generated {}", filename); + } + Err(e) => tracing::error!("Failed to generate {}: {}", filename, e), + } } } @@ -289,7 +321,7 @@ async fn render_summary_handler(State(state): State>) -> impl Into } let pages = get_summary_data(&state.docs_dir).await; let mut context = Context::new(); - context.insert("title", "Pages"); + context.insert("title", "Wiki Index"); context.insert("files", &pages); context.insert("is_static", &false); @@ -303,25 +335,15 @@ async fn render_page_handler( State(state): State>, Path(page): Path, ) -> impl IntoResponse { - let filename = if page.ends_with(".md") { + let filename = if page.ends_with(".toml") { page } else { - format!("{}.md", page) + format!("{}.toml", page) }; - let file_path = state.docs_dir.join(&filename); - match tokio::fs::read_to_string(&file_path).await { - Ok(content) => Html( - render_markdown_to_html( - &content, - &filename, - &state.docs_dir, - state.no_navigation, - false, - ) - .await, - ), - Err(_) => Html("

404

Page not found

".to_string()), + match render_wiki_page(&filename, &state.docs_dir, state.no_navigation, false).await { + Ok(html) => Html(html).into_response(), + Err(e) => (StatusCode::NOT_FOUND, format!("

404

{}

", e)).into_response(), } } @@ -335,15 +357,32 @@ async fn serve_css() -> impl IntoResponse { } } -// Helper model for Tera mod ax_models { - use serde::{Deserialize, Serialize}; + use indexmap::IndexMap; + use serde::{Deserialize, Serialize}; // Use IndexMap instead of BTreeMap + #[derive(Deserialize, Serialize, Clone)] pub struct Page { pub filename: String, pub title: String, pub datetime: String, } + + #[derive(Deserialize, Serialize, Clone)] + pub struct WikiConfig { + pub title: String, + pub image: Option, + // IndexMap preserves the order from the file + pub infobox: Option>, + pub content_file: Option, + } +} + +// Helper struct for the template +#[derive(serde::Serialize)] +struct InfoboxItem { + key: String, + value: String, } fn get_nav_links(dir: &PathBuf, current_file: &str) -> (Option, Option) { @@ -351,7 +390,7 @@ fn get_nav_links(dir: &PathBuf, current_file: &str) -> (Option, Option - {{ content | safe }} - +
+

{{ title }}

+
- +}); + {% endblock content %} diff --git a/templates/style.css b/templates/style.css index 3c936ac..6939a3f 100644 --- a/templates/style.css +++ b/templates/style.css @@ -9,285 +9,165 @@ --accent: #8aadf4; --accent-glow: #c6a0f6; - + --code-bg: var(--container-bg); --border-color: #494d64; --selection-bg: rgba(91, 96, 120, 0.4); --radius-sm: 6px; --radius-md: 12px; - --radius-lg: 20px; - --blur-amount: 12px; - --container-width: 850px; + --container-width: 1000px; /* Wider for wiki layout */ } -* { - box-sizing: border-box; -} +* { box-sizing: border-box; } body { background-color: var(--bg-color); color: var(--text-main); - font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; - line-height: 1.7; + font-family: 'Inter', system-ui, sans-serif; + line-height: 1.6; margin: 0; - padding: 40px 20px; + padding-top: 80px; display: flex; justify-content: center; min-height: 100vh; - font-size: 14px; } #content { width: 100%; max-width: var(--container-width); - min-width: 0; + padding: 0 20px; } -::selection { - background: var(--selection-bg); - color: #fff; +/* --- Wiki Layout --- */ + +.wiki-header { + border-bottom: 2px solid; + border-image-source: linear-gradient(to right, var(--accent), transparent); + border-image-slice: 1; + margin-bottom: 2rem; } -h1, h2, h3, h4, h5, h6 { - color: #fff; - margin-top: 2rem; - margin-bottom: 1rem; - font-weight: 700; - line-height: 1.25; +.wiki-header h1 { + margin: 0; + padding-bottom: 0.5rem; + font-size: 2.5rem; + color: #fff; } -h1 { - font-size: 2.5rem; - padding-bottom: 0.8rem; - margin-bottom: 2.5rem; - border-bottom: 2px solid; - border-image-source: linear-gradient(to right, var(--accent), transparent); - border-image-slice: 1; -} -h2 { - font-size: 1.8rem; - color: var(--accent); -} -h3 { - font-size: 1.5rem; +.wiki-container { + display: flex; + gap: 40px; + align-items: flex-start; } -a { - color: var(--accent); - text-decoration: none; - transition: color 0.2s ease, text-shadow 0.2s ease; +.wiki-body { + flex: 1; + min-width: 0; /* Prevents overflow in flex items */ } -a:hover { - color: var(--accent-glow); - text-shadow: 0 0 8px var(--accent-glow); +.wiki-sidebar { + width: 300px; + background: var(--container-bg); + border: 1px solid var(--border-color); + border-radius: var(--radius-md); + padding: 15px; + flex-shrink: 0; + position: sticky; + top: 90px; } -p { margin-bottom: 1.2rem; } - -ul, ol { - padding-left: 1.5rem; - margin-bottom: 1.2rem; +@media (max-width: 800px) { + .wiki-container { + flex-direction: column-reverse; + } + .wiki-sidebar { + width: 100%; + position: static; + } } -li { margin-bottom: 0.5rem; } +/* --- Sidebar Components --- */ +.sidebar-image img { + width: 100%; + border-radius: var(--radius-sm); + border: 2px solid var(--border-color); + margin-bottom: 15px; +} + +.infobox-data h3 { + margin-top: 0; + background: var(--lighter-bg); + padding: 8px; + text-align: center; + border-radius: var(--radius-sm); + font-size: 1.1rem; + color: var(--accent); +} + +.infobox-data table { + width: 100%; + margin: 0; + border-collapse: collapse; + font-size: 0.9rem; +} + +.infobox-data td { + padding: 8px; + border-bottom: 1px solid var(--border-color); +} + +.infobox-data tr:last-child td { + border-bottom: none; +} + +.info-label { + font-weight: bold; + color: var(--text-muted); +} + +.info-value { + text-align: right; +} + +/* --- Standard Markdown Elements --- */ +h2 { font-size: 1.8rem; color: var(--accent); margin-top: 2rem; } +h3 { font-size: 1.5rem; color: #fff; } +p { margin-bottom: 1rem; } +a { color: var(--accent); text-decoration: none; } +a:hover { color: var(--accent-glow); text-decoration: underline; } blockquote { - margin: 2rem 0; - padding: 0.1rem 1.5rem; - border-left: 4px solid var(--accent); - background: var(--container-bg); - border-radius: var(--radius-sm); - color: var(--text-muted); - font-style: italic; + border-left: 4px solid var(--accent); + padding-left: 1rem; + margin: 1.5rem 0; + font-style: italic; + color: var(--text-muted); } +/* Code blocks */ pre { - position: relative; - background: var(--code-bg); - background-color: var(--code-bg) !important; - padding: 1.2rem; - border-radius: var(--radius-md); - overflow-x: auto; - border: 2px solid var(--border-color); - /* margin: 1.5rem 0; */ + background: var(--container-bg); + padding: 1rem; + border-radius: var(--radius-md); + overflow-x: auto; + border: 1px solid var(--border-color); } - code { - font-size: 0.9em; - background: rgba(255, 255, 255, 0.1); - padding: 0.2rem 0.4rem; - border-radius: var(--radius-sm); - font-style: normal !important; -} - -pre code { - display: block; - background: none !important; - padding: 0; - padding-right: 40px; -} - -pre, -code, -pre span, -code span, -pre [style], -code [style] { - font-family: 'JetBrains Mono', 'Cascadia Code', 'Source Code Pro', Menlo, Consolas, monospace !important; - font-style: normal !important; - font-variant-ligatures: contextual; -} - -table { - width: 100%; - border-collapse: collapse; - margin: 2rem 0; -} - -th { - background: var(--lighter-bg); - color: var(--accent); - text-align: left; -} - -th, td { - padding: 12px; - border: 2px solid var(--border-color); -} - -tr:nth-child(even) { - background: rgba(255, 255, 255, 0.025); -} - -hr { - border: none; - height: 2px; - background: linear-gradient(to right, transparent, var(--border-color), transparent); - margin: 3rem 0; -} - -img { - max-width: 100%; - border-radius: var(--radius-md); - margin: 1.5rem 0; - border: 2px solid var(--border-color); -} - -input[type="checkbox"] { - appearance: none; - -webkit-appearance: none; - background-color: transparent; - margin: 0; - margin-right: 0.5rem; - - font: inherit; - color: var(--accent); - width: 1.25em; - height: 1.25em; - border: 2px solid var(--text-muted); - border-radius: var(--radius-sm); - transform: translateY(-0.075em); - - display: inline-grid; - place-content: center; - transition: border-color 0.2s ease, background-color 0.2s ease; -} - -input[type="checkbox"]::before { - content: ""; - width: 0.65em; - height: 0.65em; - transform: scale(0); - transition: 120ms transform ease-in-out; - box-shadow: inset 1em 1em var(--accent); - - clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%); -} - -input[type="checkbox"]:checked { - border-color: var(--accent); -} - -input[type="checkbox"]:checked::before { - transform: scale(1); -} - -body { - padding-top: 75px; + font-family: 'JetBrains Mono', monospace; + font-size: 0.9em; } +/* Navigation Bar */ nav { - position: fixed; - top: 0; - left: 0; - width: 100%; - z-index: 1000; - background: var(--container-bg); - /* backdrop-filter: blur(var(--blur-amount)); */ - /* -webkit-backdrop-filter: blur(var(--blur-amount)); */ - border-bottom: 2px solid var(--border-color); - padding: 1rem 2rem; - display: flex; - justify-content: space-between; - align-items: center; -} - -nav a { - color: var(--text-main); - text-decoration: none; - font-size: 1.2rem; - font-weight: 600; - margin-left: 20px; - transition: color 0.2s ease; -} - -.btn { - display: inline-block; - color: #fff; - padding: 0.6rem 1.2rem; - border: solid 1px var(--accent); - border-radius: var(--radius-md); - font-weight: 600; - cursor: pointer; - text-decoration: none; - transition: background 0.2s ease; -} - -.btn.disabled { - color: var(--text-muted); - cursor: not-allowed; - border-color: var(--text-muted); -} - -.code-wrapper { - position: relative; - margin: 1.5rem 0; -} - -.copy-button { - position: absolute; - top: 10px; - right: 10px; - padding: 10px 10px; - background: var(--container-bg); - border: 1px solid var(--border-color); - border-radius: var(--radius-sm); - color: var(--text-muted); - cursor: pointer; - font-size: 0.9rem; - transition: all 0.2s ease; - display: flex; - align-items: center; - justify-content: center; - z-index: 10; -} - -.copy-button:hover { - color: var(--accent); -} - -.copy-button:active { - transform: translateY(2px); + position: fixed; + top: 0; left: 0; right: 0; + height: 60px; + background: var(--container-bg); + border-bottom: 1px solid var(--border-color); + display: flex; + align-items: center; + padding: 0 2rem; + z-index: 100; } +nav a { font-weight: bold; font-size: 1.2rem; color: var(--text-main); }