Compare commits

..

No commits in common. "bb50e3b2e5075f0cea730de3e2e1033fa00bb98f" and "b8e56c87b4a948760aad689cc7a9d39b74c97e7f" have entirely different histories.

7 changed files with 568 additions and 183 deletions

1
.gitignore vendored
View file

@ -1,2 +1 @@
/target
/output

555
Cargo.lock generated
View file

@ -2,6 +2,21 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "addr2line"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "adler2"
version = "2.0.0"
@ -79,6 +94,17 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "askama_axum"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a41603f7cdbf5ac4af60760f17253eb6adf6ec5b6f14a7ed830cf687d375f163"
dependencies = [
"askama",
"axum-core",
"http",
]
[[package]]
name = "askama_derive"
version = "0.12.5"
@ -92,7 +118,7 @@ dependencies = [
"proc-macro2",
"quote",
"serde",
"syn 2.0.77",
"syn 2.0.76",
]
[[package]]
@ -110,12 +136,93 @@ dependencies = [
"nom",
]
[[package]]
name = "async-trait"
version = "0.1.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.76",
]
[[package]]
name = "autocfg"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]]
name = "axum"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf"
dependencies = [
"async-trait",
"axum-core",
"bytes",
"futures-util",
"http",
"http-body",
"http-body-util",
"hyper",
"hyper-util",
"itoa",
"matchit",
"memchr",
"mime",
"percent-encoding",
"pin-project-lite",
"rustversion",
"serde",
"serde_json",
"serde_path_to_error",
"serde_urlencoded",
"sync_wrapper 1.0.1",
"tokio",
"tower",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "axum-core"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3"
dependencies = [
"async-trait",
"bytes",
"futures-util",
"http",
"http-body",
"http-body-util",
"mime",
"pin-project-lite",
"rustversion",
"sync_wrapper 0.1.2",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "backtrace"
version = "0.3.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide 0.7.4",
"object",
"rustc-demangle",
]
[[package]]
name = "base64"
version = "0.22.1"
@ -179,6 +286,12 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bytes"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50"
[[package]]
name = "caseless"
version = "0.2.1"
@ -236,7 +349,7 @@ dependencies = [
"heck",
"proc-macro2",
"quote",
"syn 2.0.77",
"syn 2.0.76",
]
[[package]]
@ -302,7 +415,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim",
"syn 2.0.77",
"syn 2.0.76",
]
[[package]]
@ -313,7 +426,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
dependencies = [
"darling_core",
"quote",
"syn 2.0.77",
"syn 2.0.76",
]
[[package]]
@ -327,33 +440,33 @@ dependencies = [
[[package]]
name = "derive_builder"
version = "0.20.1"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd33f37ee6a119146a1781d3356a7c26028f83d779b2e04ecd45fdc75c76877b"
checksum = "0350b5cb0331628a5916d6c5c0b72e97393b8b6b03b47a9284f4e7f5a405ffd7"
dependencies = [
"derive_builder_macro",
]
[[package]]
name = "derive_builder_core"
version = "0.20.1"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7431fa049613920234f22c47fdc33e6cf3ee83067091ea4277a3f8c4587aae38"
checksum = "d48cda787f839151732d396ac69e3473923d54312c070ee21e9effcaa8ca0b1d"
dependencies = [
"darling",
"proc-macro2",
"quote",
"syn 2.0.77",
"syn 2.0.76",
]
[[package]]
name = "derive_builder_macro"
version = "0.20.1"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4abae7035bf79b9877b779505d8cf3749285b80c43941eda66604841889451dc"
checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b"
dependencies = [
"derive_builder_core",
"syn 2.0.77",
"syn 2.0.76",
]
[[package]]
@ -421,7 +534,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253"
dependencies = [
"crc32fast",
"miniz_oxide",
"miniz_oxide 0.8.0",
]
[[package]]
@ -430,6 +543,54 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "form_urlencoded"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
dependencies = [
"percent-encoding",
]
[[package]]
name = "futures-channel"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
dependencies = [
"futures-core",
]
[[package]]
name = "futures-core"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
[[package]]
name = "futures-sink"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
[[package]]
name = "futures-task"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
[[package]]
name = "futures-util"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
dependencies = [
"futures-core",
"futures-task",
"pin-project-lite",
"pin-utils",
]
[[package]]
name = "getrandom"
version = "0.2.15"
@ -453,6 +614,12 @@ dependencies = [
"syn 1.0.109",
]
[[package]]
name = "gimli"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
[[package]]
name = "hashbrown"
version = "0.12.3"
@ -471,6 +638,64 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hermit-abi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]]
name = "http"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258"
dependencies = [
"bytes",
"fnv",
"itoa",
]
[[package]]
name = "http-body"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
dependencies = [
"bytes",
"http",
]
[[package]]
name = "http-body-util"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f"
dependencies = [
"bytes",
"futures-util",
"http",
"http-body",
"pin-project-lite",
]
[[package]]
name = "http-range-header"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08a397c49fec283e3d6211adbe480be95aae5f304cfb923e9970e08956d5168a"
[[package]]
name = "httparse"
version = "1.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9"
[[package]]
name = "httpdate"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "humansize"
version = "2.1.3"
@ -480,6 +705,40 @@ dependencies = [
"libm",
]
[[package]]
name = "hyper"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05"
dependencies = [
"bytes",
"futures-channel",
"futures-util",
"http",
"http-body",
"httparse",
"httpdate",
"itoa",
"pin-project-lite",
"smallvec",
"tokio",
]
[[package]]
name = "hyper-util"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9"
dependencies = [
"bytes",
"futures-util",
"http",
"http-body",
"hyper",
"pin-project-lite",
"tokio",
]
[[package]]
name = "ident_case"
version = "1.0.1"
@ -498,9 +757,9 @@ dependencies = [
[[package]]
name = "indexmap"
version = "2.5.0"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5"
checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c"
dependencies = [
"equivalent",
"hashbrown 0.14.5",
@ -572,6 +831,12 @@ dependencies = [
"toml",
]
[[package]]
name = "matchit"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
[[package]]
name = "memchr"
version = "2.7.4"
@ -600,6 +865,15 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
dependencies = [
"adler",
]
[[package]]
name = "miniz_oxide"
version = "0.8.0"
@ -609,6 +883,18 @@ dependencies = [
"adler2",
]
[[package]]
name = "mio"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec"
dependencies = [
"hermit-abi",
"libc",
"wasi",
"windows-sys 0.52.0",
]
[[package]]
name = "nom"
version = "7.1.3"
@ -634,6 +920,15 @@ dependencies = [
"autocfg",
]
[[package]]
name = "object"
version = "0.36.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9"
dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
version = "1.19.0"
@ -668,6 +963,38 @@ version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "pin-project"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.76",
]
[[package]]
name = "pin-project-lite"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
version = "0.3.30"
@ -681,7 +1008,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016"
dependencies = [
"base64",
"indexmap 2.5.0",
"indexmap 2.4.0",
"quick-xml",
"serde",
"time",
@ -818,6 +1145,12 @@ version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
[[package]]
name = "rustc-demangle"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
[[package]]
name = "rustix"
version = "0.38.35"
@ -831,17 +1164,26 @@ dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "rustversion"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
[[package]]
name = "rusty_duck"
version = "0.1.0"
dependencies = [
"askama",
"askama_axum",
"axum",
"comrak",
"markdown-parser",
"rand",
"serde",
"serde_yaml 0.9.34+deprecated",
"syntect",
"tokio",
"tower-http",
]
[[package]]
@ -876,7 +1218,7 @@ checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.77",
"syn 2.0.76",
]
[[package]]
@ -891,6 +1233,28 @@ dependencies = [
"serde",
]
[[package]]
name = "serde_path_to_error"
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6"
dependencies = [
"itoa",
"serde",
]
[[package]]
name = "serde_urlencoded"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
dependencies = [
"form_urlencoded",
"itoa",
"ryu",
"serde",
]
[[package]]
name = "serde_yaml"
version = "0.8.26"
@ -909,7 +1273,7 @@ version = "0.9.34+deprecated"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
dependencies = [
"indexmap 2.5.0",
"indexmap 2.4.0",
"itoa",
"ryu",
"serde",
@ -938,6 +1302,22 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "smallvec"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "socket2"
version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c"
dependencies = [
"libc",
"windows-sys 0.52.0",
]
[[package]]
name = "strsim"
version = "0.11.1"
@ -957,15 +1337,27 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.77"
version = "2.0.76"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed"
checksum = "578e081a14e0cefc3279b0472138c513f37b41a08d5a3cca9b6e4e8ceb6cd525"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "sync_wrapper"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
[[package]]
name = "sync_wrapper"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394"
[[package]]
name = "syntect"
version = "5.2.0"
@ -1016,7 +1408,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.77",
"syn 2.0.76",
]
[[package]]
@ -1065,6 +1457,46 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
version = "1.39.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5"
dependencies = [
"backtrace",
"bytes",
"libc",
"mio",
"pin-project-lite",
"socket2",
"tokio-macros",
"windows-sys 0.52.0",
]
[[package]]
name = "tokio-macros"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.76",
]
[[package]]
name = "tokio-util"
version = "0.7.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1"
dependencies = [
"bytes",
"futures-core",
"futures-sink",
"pin-project-lite",
"tokio",
]
[[package]]
name = "toml"
version = "0.5.11"
@ -1074,6 +1506,79 @@ dependencies = [
"serde",
]
[[package]]
name = "tower"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
dependencies = [
"futures-core",
"futures-util",
"pin-project",
"pin-project-lite",
"tokio",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "tower-http"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5"
dependencies = [
"bitflags 2.6.0",
"bytes",
"futures-util",
"http",
"http-body",
"http-body-util",
"http-range-header",
"httpdate",
"mime",
"mime_guess",
"percent-encoding",
"pin-project-lite",
"tokio",
"tokio-util",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "tower-layer"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e"
[[package]]
name = "tower-service"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
[[package]]
name = "tracing"
version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
dependencies = [
"log",
"pin-project-lite",
"tracing-core",
]
[[package]]
name = "tracing-core"
version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
dependencies = [
"once_cell",
]
[[package]]
name = "typed-arena"
version = "2.0.2"
@ -1166,7 +1671,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.77",
"syn 2.0.76",
"wasm-bindgen-shared",
]
@ -1188,7 +1693,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.77",
"syn 2.0.76",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@ -1389,5 +1894,5 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.77",
"syn 2.0.76",
]

View file

@ -11,10 +11,13 @@ panic = 'abort' # Abort on panic
strip = "symbols" # Strip symbols from binary
[dependencies]
askama = { version = "0.12.1" }
comrak = { version = "0.27.0", features = ["syntect"] }
askama = { version = "0.12.1", features = ["with-axum"] }
askama_axum = "0.4.0"
axum = "0.7.5"
comrak = "0.27.0"
markdown-parser = "0.1.2"
rand = "0.8.5"
serde = { version = "1.0.209", features = ["derive"] }
serde_yaml = "0.9.34"
syntect = "5.2.0"
tokio = { version = "1.39.3", features = ["macros", "rt-multi-thread"] }
tower-http = { version = "0.5.2", features = ["fs"] }

View file

@ -12,7 +12,7 @@ This time inspied by [this article](https://blog.transrights.art/blogs/2024_Scre
[theprimeagen](https://www.youtube.com/watch?v=rcZSOLAI1lM), and everpresent desire to rewrite everything in Rust,
the new website is a complete rewrite using rust and adjacent techniques.
Using only
Using only
```
[dependencies]
askama = { version = "0.12.1", features = ["with-axum"] }
@ -26,81 +26,11 @@ serde_yaml = "0.9.34"
tokio = { version = "1.39.3", features = ["macros", "rt-multi-thread"] }
tower-http = { version = "0.5.2", features = ["fs"] }
```
as dependencies in the end we get a clean~ish, 2.8MB executable.
as dependancies in the end we get a clean~ish, 2.8MB executable.
All markdown compilation gets done every time page is loaded, which is sub-optimal,
But reading time for all posts is non-significant compared to other loading times.
And voila, there is the new post.
## Update
This approach however had few issues.
As fun as it is writing your own routing logic, It feels purely unnecessary.
Even scaling down from `axum` to `tiny_http`, it doesn't change the binary size, and because of the limited resources and location of the VPS,
it does not affect the load times.
Short of rewriting it all in [Yew](yew.rs) and loading the wasm as a SPA (which comes with it's own complexity) loading times would not improve.
Therefore the goal has been slightly changed.
From serving the files the goal is now using askama like a sort of static site generator.
# DIY Hugo?
Not exactly. In the current state it is basically Saait again, but with extra steps.
Additional pages require source code intervention, which isn't hard, but tidious.
//TODO: use some enum for pages, with derive as EnumString, so new pages can be added simply by adding a template.
But for now, the new dependencies now look like this:
```toml
[dependencies]
askama = { version = "0.12.1" }
comrak = "0.27.0"
markdown-parser = "0.1.2"
rand = "0.8.5"
serde = { version = "1.0.209", features = ["derive"] }
serde_yaml = "0.9.34"
syntect = "5.2.0"
```
Syntect providing oh so nice code highlighting in the markdown.
```json
{
"firstName": "John",
"lastName": "Smith",
"age": 25
}
```
```rust
std::fs::write(format!("{output_path}/index.html"), handlers::index().as_bytes()).expect("Couldnt write index file");
std::fs::write(format!("{output_path}/about.html"), handlers::about().as_bytes()).expect("Couldnt write about file");
std::fs::write(format!("{output_path}/404.html"), handlers::not_found().as_bytes()).expect("Couldnt write 404 file");
for entry in post_dir_iter {
if let Ok(entry) = entry {
let filename = entry.file_name().into_string().unwrap().split(".").collect::<Vec<_>>()[0].to_string();
fs::write(format!("{output_path}/blog/{filename}.html"), handlers::blog(filename).as_bytes()).expect("Couldnt write blog entry");
};
}
```
For now, I am rather happy with the result.
Built for release profile, binary is just 3.1M (majority of it is syntact), and produces a output folder with it's contents in a rather pleasant amount of time.
> ./target/release/rusty_duck 0.03s user 0.01s system 97% cpu 0.035 total
This is no **BLAZING** speed, but it's honest work.

View file

@ -29,7 +29,7 @@ pub fn get_all_markdowns() -> Vec<IndexPostEntry> {
post_vec.push(IndexPostEntry{
title: front_matter.title,
date: front_matter.date,
path: format!("/blog/{filename}.html"),
path: format!("/blog/{filename}"),
});
}

View file

@ -1,50 +1,36 @@
use axum::{extract::Path,response::Html};
use crate::structs::*;
use crate::rand_quote::get_quote;
use crate::blog_entries::{get_all_markdowns, get_blog_entry_markdown};
pub fn index() -> String {
pub async fn index() -> Html<String> {
let all_entries = get_all_markdowns();
let quote = get_quote();
let new_page = IndexTemplate { random_quote: quote, index_post_entries:&all_entries};
new_page.to_string()
Html(new_page.to_string())
}
pub fn about() -> String {
pub async fn about() -> Html<String> {
let about_content = parse_markdown("about");
let about_content = comrak::markdown_to_html("about", &comrak::Options::default());
let page_content = AboutTemplate{about_content: &about_content};
page_content.to_string()
Html(page_content.to_string())
}
pub fn blog(blog_path:String) -> String {
pub async fn blog(Path(blog_path):Path<String>) -> Html<String> {
match get_blog_entry_markdown(&blog_path){
Ok(markdown) =>
Ok(markdown) => Html(
BlogTemplate{
blog_content: &parse_markdown(markdown.content()),
blog_content: &comrak::markdown_to_html(markdown.content(), &comrak::Options::default()),
front_matter:&serde_yaml::from_str(markdown.front_matter()).unwrap()}.to_string()
,
Err(..) => not_found(),
),
Err(..) => not_found().await,
}
}
pub fn not_found() -> String {
NotFoundTemplate{}.to_string()
}
fn parse_markdown(content: &str) -> String {
let mut options = comrak::Options::default();
options.extension.underline = true;
options.extension.strikethrough = true;
let mut plugins = comrak::Plugins::default();
let adapter = comrak::plugins::syntect::SyntectAdapterBuilder::new()
.theme("base16-mocha.dark")
.build();
plugins.render.codefence_syntax_highlighter = Some(&adapter);
comrak::markdown_to_html_with_plugins(content, &options, &plugins)
pub async fn not_found() -> Html<String> {
Html(NotFoundTemplate{}.to_string())
}

View file

@ -1,4 +1,6 @@
use std::{fs::{write, read_dir, DirBuilder},path::Path};
use axum::{routing::get, Router};
use tower_http::services::{ServeDir, ServeFile};
mod handlers;
mod structs;
@ -7,59 +9,19 @@ pub mod rand_quote;
fn main() {
let output_path = "output";
match DirBuilder::new()
.recursive(true)
.create(output_path) {
Ok(_) => (),
Err(_) => (),
}
#[tokio::main]
async fn main() {
match copy_dir_all("assets", format!("{output_path}/assets")) {
Ok(_) => (),
Err(err) => println!("Couldnt copy assets directory, err: {err}"),
}
let app: axum::Router = Router::new()
.route("/", get(handlers::index))
.route("/about", get(handlers::about))
.route("/blog",get(handlers::index))
.route("/blog/:blog_path",get(handlers::blog))
.route_service("/robots.txt", ServeFile::new("assets/robots.txt"))
.fallback(get(handlers::not_found))
.nest_service("/assets", ServeDir::new("assets"));
write(format!("{output_path}/index.html"), handlers::index().as_bytes()).expect("Couldnt write index file");
write(format!("{output_path}/about.html"), handlers::about().as_bytes()).expect("Couldnt write about file");
write(format!("{output_path}/404.html"), handlers::not_found().as_bytes()).expect("Couldnt write 404 file");
match DirBuilder::new()
.create(format!("{output_path}/blog")) {
Ok(_) => (),
Err(err) => println!("Error detected: {err}"),
}
let post_dir_iter = match read_dir("posts/") {
Ok(iter) => iter,
Err(err) => panic!("could ls files, err {err}")
};
for entry in post_dir_iter {
if let Ok(entry) = entry {
let filename = entry.file_name().into_string().unwrap().split(".").collect::<Vec<_>>()[0].to_string();
write(format!("{output_path}/blog/{filename}.html"), handlers::blog(filename).as_bytes()).expect("Couldnt write blog entry");
};
}
}
fn copy_dir_all(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> std::io::Result<()> {
std::fs::create_dir_all(&dst)?;
for entry in std::fs::read_dir(src)? {
let entry = entry?;
let ty = entry.file_type()?;
if ty.is_dir() {
copy_dir_all(entry.path(), dst.as_ref().join(entry.file_name()))?;
} else {
std::fs::copy(entry.path(), dst.as_ref().join(entry.file_name()))?;
}
}
Ok(())
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000").await.unwrap();
axum::serve(listener, app).await.unwrap();
}