1
Fork 0

Generate multiple pages & metadata collection

Signed-off-by: prescientmoon <git@moonythm.dev>
This commit is contained in:
prescientmoon 2024-10-31 18:43:13 +01:00
parent 10769956cf
commit ec65fafa1a
Signed by: prescientmoon
SSH key fingerprint: SHA256:WFp/cO76nbarETAoQcQXuV+0h7XJsEsOCI0UsyPIy6U
15 changed files with 352 additions and 738 deletions

4
.gitignore vendored
View file

@ -1 +1,3 @@
/target
target
dist
oldicons

624
Cargo.lock generated
View file

@ -2,48 +2,12 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "ahash"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
dependencies = [
"cfg-if",
"once_cell",
"version_check",
"zerocopy",
]
[[package]]
name = "allocator-api2"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
[[package]]
name = "anyhow"
version = "1.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6"
[[package]]
name = "autocfg"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "bumpalo"
version = "3.16.0"
@ -51,193 +15,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]]
name = "byteorder"
version = "1.5.0"
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cached"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4d73155ae6b28cf5de4cfc29aeb02b8a1c6dab883cb015d15cd514e42766846"
dependencies = [
"ahash",
"cached_proc_macro",
"cached_proc_macro_types",
"directories",
"hashbrown",
"once_cell",
"rmp-serde",
"serde",
"sled",
"thiserror",
"web-time",
]
[[package]]
name = "cached_proc_macro"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f42a145ed2d10dce2191e1dcf30cfccfea9026660e143662ba5eec4017d5daa"
dependencies = [
"darling",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "cached_proc_macro_types"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ade8366b8bd5ba243f0a58f036cc0ca8a2f069cff1a2351ef1cac6b083e16fc0"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "crc32fast"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
dependencies = [
"cfg-if",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
[[package]]
name = "darling"
version = "0.20.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.20.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn",
]
[[package]]
name = "darling_macro"
version = "0.20.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
dependencies = [
"darling_core",
"quote",
"syn",
]
[[package]]
name = "directories"
version = "5.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35"
dependencies = [
"dirs-sys",
]
[[package]]
name = "dirs-sys"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
dependencies = [
"libc",
"option-ext",
"redox_users",
"windows-sys",
]
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "fs2"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "fxhash"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
dependencies = [
"byteorder",
]
[[package]]
name = "getrandom"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "hashbrown"
version = "0.14.5"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
dependencies = [
"ahash",
"allocator-api2",
]
checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb"
[[package]]
name = "ident_case"
version = "1.0.1"
name = "indexmap"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "instant"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
dependencies = [
"cfg-if",
"equivalent",
"hashbrown",
]
[[package]]
@ -247,63 +43,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19fa1db3b285830176c8a940d4e3376679772bee9f58a83dd9285a4a54e30f6e"
[[package]]
name = "js-sys"
version = "0.3.72"
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "libc"
version = "0.2.159"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5"
[[package]]
name = "libredox"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
dependencies = [
"bitflags 2.6.0",
"libc",
]
[[package]]
name = "lock_api"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
dependencies = [
"autocfg",
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "moonythm"
version = "0.1.0"
dependencies = [
"anyhow",
"cached",
"jotdown",
"once_cell",
"pulldown-latex",
]
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
"serde",
"toml",
]
[[package]]
@ -312,48 +66,11 @@ version = "1.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
[[package]]
name = "option-ext"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]]
name = "parking_lot"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
dependencies = [
"instant",
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc"
dependencies = [
"cfg-if",
"instant",
"libc",
"redox_syscall",
"smallvec",
"winapi",
]
[[package]]
name = "paste"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "proc-macro2"
version = "1.0.87"
version = "1.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a"
checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
dependencies = [
"unicode-ident",
]
@ -376,68 +93,20 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "redox_users"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"
dependencies = [
"getrandom",
"libredox",
"thiserror",
]
[[package]]
name = "rmp"
version = "0.8.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4"
dependencies = [
"byteorder",
"num-traits",
"paste",
]
[[package]]
name = "rmp-serde"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52e599a477cf9840e92f2cde9a7189e67b42c57532749bf90aea6ec10facd4db"
dependencies = [
"byteorder",
"rmp",
"serde",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "serde"
version = "1.0.210"
version = "1.0.214"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.210"
version = "1.0.214"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766"
dependencies = [
"proc-macro2",
"quote",
@ -445,38 +114,19 @@ dependencies = [
]
[[package]]
name = "sled"
version = "0.34.7"
name = "serde_spanned"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f96b4737c2ce5987354855aed3797279def4ebf734436c6aa4552cf8e169935"
checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1"
dependencies = [
"crc32fast",
"crossbeam-epoch",
"crossbeam-utils",
"fs2",
"fxhash",
"libc",
"log",
"parking_lot",
"serde",
]
[[package]]
name = "smallvec"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
version = "2.0.79"
version = "2.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590"
checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56"
dependencies = [
"proc-macro2",
"quote",
@ -484,23 +134,37 @@ dependencies = [
]
[[package]]
name = "thiserror"
version = "1.0.64"
name = "toml"
version = "0.8.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84"
checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
dependencies = [
"thiserror-impl",
"serde",
"serde_spanned",
"toml_datetime",
"toml_edit",
]
[[package]]
name = "thiserror-impl"
version = "1.0.64"
name = "toml_datetime"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3"
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
dependencies = [
"proc-macro2",
"quote",
"syn",
"serde",
]
[[package]]
name = "toml_edit"
version = "0.22.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
dependencies = [
"indexmap",
"serde",
"serde_spanned",
"toml_datetime",
"winnow",
]
[[package]]
@ -510,186 +174,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
[[package]]
name = "version_check"
version = "0.9.5"
name = "winnow"
version = "0.6.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e"
checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b"
dependencies = [
"cfg-if",
"once_cell",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d"
[[package]]
name = "web-time"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "zerocopy"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
"syn",
"memchr",
]

View file

@ -5,6 +5,11 @@ edition = "2021"
[dependencies]
anyhow = "1.0.89"
cached = { version = "0.53.1", features = ["disk_store"] }
jotdown = "0.6.0"
pulldown-latex = "0.7.0"
serde = { version = "1.0.214", features = ["derive"] }
toml = "0.8.19"
# Waiting for https://github.com/rust-lang/rust/issues/109737
# before switching to the std version.
once_cell = "1.20.2"

View file

@ -1,16 +0,0 @@
#!/usr/bin/env nix-shell
#!nix-shell -p python3 -i python3
import shutil
import subprocess
shutil.rmtree("dist", ignore_errors=True)
shutil.copytree("public", "dist")
with open("dist/index.html", "r") as file:
template = file.read()
output = subprocess.check_output("cargo run", shell=True).decode("utf-8")
result = template.replace("$CONTENT", output)
with open("dist/index.html", "w") as file:
file.write(result)

14
content/index.dj Normal file
View file

@ -0,0 +1,14 @@
# Hiii
Welcome to my ethereal realm (read: website). This place is still being conjured (read: under construction), so some things might be startlingly empty. Enjoy your stay on the moon!
I'm known as `prescientmoon`, or sometimes `PGW`. I study mathematics, but I also really like coding and all computer-related sorcery. I love games of all kinds, although rhythm games have a special place in my heart.
{ title="Contact me" character="canyou" }
::: aside
You can message me in the following places \^-\^
- via email at `hi@thisdomain`
- on discord as `@prescientmoon`
- on the ~ IRC network as `prescientmoon`
:::

View file

@ -1,5 +1,5 @@
``` =toml
created-at: 2024-10-31 15:28
created-at = "2024-10-31T15:28:OO"
```
# Why I love arcaea

1
content/posts/games.dj Normal file
View file

@ -0,0 +1 @@
# My game tier list

View file

@ -0,0 +1,15 @@
# The realm's secrets
## Djot (why not markdown?)
- extensionability
- writing my own html generator
- templating
- metadata
## Hosting
- hosted on my nixos server
- there's interesting stuff happening there too, but that deserves it's own post
## LaTeX
- tried using `cached` with `latexmlmath`, but results were slow.
- ended up using the `pulldown-latex` crate.

View file

@ -16,8 +16,7 @@
pkgs.clippy
pkgs.rust-analyzer
pkgs.rustfmt
pkgs.ruff
pkgs.perl538Packages.LaTeXML
pkgs.imagemagick
];
buildInputs = with pkgs; [ ];

View file

@ -6,6 +6,7 @@ html {
max-width: 70ch;
margin-left: auto;
margin-right: auto;
padding: 1em;
}
blockquote {
@ -28,19 +29,11 @@ ol {
align-items: center;
}
.aside-summary > .aside-title {
text-decoration: underline;
}
.aside-summary > * {
padding: 0;
margin: 0;
}
img.aside-icon {
/* display: inline-block; */
height: 1.75rem;
margin-right: 0.5rem;
transform: translateY(-2px);
/* transform: translateY(-100px); */
}
.aside {
@ -53,6 +46,7 @@ img.aside-icon {
.aside-summary {
display: inline-flex;
align-items: center;
box-sizing: border-box;
}
.aside-summary::marker {
@ -66,6 +60,15 @@ img.aside-icon {
box-sizing: border-box;
}
.aside-summary > .aside-title {
text-decoration: underline;
}
.aside-summary > * {
padding: 0;
margin: 0;
}
.aside[open] .aside_summary:before {
content: "▼";
}

View file

@ -12,66 +12,26 @@ use jotdown::OrderedListNumbering::*;
use jotdown::SpanLinkType;
use crate::template;
use crate::template::Template;
use crate::template::TemplateRenderer;
// {{{ Renderer
/// Render events into a string.
pub fn render_to_string<'s, I>(events: I) -> anyhow::Result<String>
where
I: Iterator<Item = Event<'s>>,
{
let mut s = String::new();
Renderer::new()?.push(events, &mut s)?;
Ok(s)
}
/// Render djot content as HTML.
pub fn render_html<'s>(
mut events: impl Iterator<Item = Event<'s>>,
mut out: impl std::fmt::Write,
) -> anyhow::Result<()> {
let mut w = Writer::new();
events.try_for_each(|e| w.render_event(&e, &mut out))?;
w.render_epilogue(&mut out)?;
/// [`Render`] implementor that writes HTML output.
#[derive(Clone, Debug)]
pub struct Renderer {
templates: BuiltinTempaltes,
}
impl Renderer {
pub fn new() -> anyhow::Result<Self> {
Ok(Self {
templates: BuiltinTempaltes::new()?,
})
}
pub fn push<'s>(
&self,
mut events: impl Iterator<Item = Event<'s>>,
mut out: impl std::fmt::Write,
) -> anyhow::Result<()> {
let mut w = Writer::new(self);
events.try_for_each(|e| w.render_event(&e, &mut out))?;
w.render_epilogue(&mut out)?;
Ok(())
}
}
// }}}
// {{{ Bring in templates
#[derive(Clone, Debug)]
struct BuiltinTempaltes {
aside_template: Template,
}
impl BuiltinTempaltes {
fn new() -> anyhow::Result<Self> {
Ok(BuiltinTempaltes {
aside_template: template!("./templates/aside.html")?,
})
}
Ok(())
}
// }}}
struct Writer<'s> {
pub struct Writer<'s> {
list_tightness: Vec<bool>,
states: Vec<State<'s>>,
footnotes: Footnotes<'s>,
renderer: &'s Renderer,
}
#[derive(Debug, Clone)]
@ -84,20 +44,20 @@ enum State<'s> {
}
impl<'s> Writer<'s> {
fn new(renderer: &'s Renderer) -> Self {
pub fn new() -> Self {
Self {
list_tightness: Vec::new(),
states: Vec::new(),
footnotes: Footnotes::default(),
renderer,
}
}
#[allow(clippy::single_match)]
fn render_event<W>(&mut self, e: &Event<'s>, mut out: W) -> anyhow::Result<()>
where
W: std::fmt::Write,
{
pub fn render_event(
&mut self,
e: &Event<'s>,
mut out: impl std::fmt::Write,
) -> anyhow::Result<()> {
// {{{ Handle footnotes
if let Event::Start(Container::Footnote { label }, ..) = e {
self.footnotes.start(label, Vec::new());
@ -157,7 +117,7 @@ impl<'s> Writer<'s> {
}
match &c {
Container::RawBlock { .. } => unreachable!(),
Container::RawBlock { .. } => {}
Container::RawInline { .. } => unreachable!(),
Container::Footnote { .. } => unreachable!(),
// {{{ List
@ -226,7 +186,7 @@ impl<'s> Writer<'s> {
})?;
let mut renderer =
TemplateRenderer::new(&self.renderer.templates.aside_template);
TemplateRenderer::new(template!("templates/aside.html")?);
while let Some(label) = renderer.current(&mut out)? {
if label == "character" {
@ -378,7 +338,7 @@ impl<'s> Writer<'s> {
}
match c {
Container::RawBlock { .. } => unreachable!(),
Container::RawBlock { .. } => {}
Container::RawInline { .. } => unreachable!(),
Container::Footnote { .. } => unreachable!(),
// {{{ List
@ -463,7 +423,6 @@ impl<'s> Writer<'s> {
Some(State::TextOnly) => write_attr(s, &mut out)?,
Some(State::Raw) => out.write_str(s)?,
Some(State::Math(display)) => {
// let string: String = format!("{}{s}{}", delim, delim);
let config = pulldown_latex::RenderConfig {
display_mode: {
use pulldown_latex::config::DisplayMode::*;

View file

@ -1,14 +1,15 @@
use std::fs::{self};
use std::path::{Path, PathBuf};
use std::process::Command;
use std::str::FromStr;
use anyhow::Context;
use html::Renderer;
use anyhow::{anyhow, Context};
use html::render_html;
use template::TemplateRenderer;
mod html;
mod metadata;
mod template;
mod tex;
fn copy_recursively(from: &Path, to: &Path) -> anyhow::Result<()> {
Command::new("cp").arg("-r").arg(from).arg(to).output()?;
@ -16,9 +17,68 @@ fn copy_recursively(from: &Path, to: &Path) -> anyhow::Result<()> {
Ok(())
}
// {{{ Generate single page
fn generate_page(path: &Path) -> anyhow::Result<()> {
let content_path = PathBuf::from_str("content")?.join(path);
let djot_input = std::fs::read_to_string(content_path).unwrap();
let mut out = String::new();
let page_template = template!("templates/page.html")?;
let mut page_renderer = TemplateRenderer::new(page_template);
// let events = jotdown::Parser::new(&djot_input);
// let meta = PageMetadata::new(events)?;
// println!("Metadata: {meta:?}");
while let Some(label) = page_renderer.next(&mut out)? {
if label == "content" {
let events = jotdown::Parser::new(&djot_input);
render_html(events, &mut out)?;
} else {
break;
}
}
page_renderer.finish(&mut out)?;
let mut out_path = PathBuf::from_str("dist")?.join(path);
out_path.set_file_name(format!(
"{}.html",
path.file_stem()
.ok_or_else(|| anyhow!("Empty filestem encountered"))?
.to_str()
.unwrap()
));
std::fs::write(out_path, out).with_context(|| "Failed to write `arcaea.html` post")?;
Ok(())
}
// }}}
// {{{ Generate an entire directory
fn generate_dir(path: &Path) -> anyhow::Result<()> {
let content_path = PathBuf::from_str("content")?.join(path);
let out_path = PathBuf::from_str("dist")?.join(path);
fs::create_dir_all(out_path)
.with_context(|| format!("Could not generate directory {path:?}"))?;
for file in fs::read_dir(content_path)? {
let file_path = file?.path();
let path = path.join(file_path.file_name().unwrap());
if file_path.is_dir() {
generate_dir(&path)?;
} else {
generate_page(&path)?;
}
}
Ok(())
}
// }}}
fn main() -> anyhow::Result<()> {
let dist_path = PathBuf::from_str("dist")?;
let public_path = PathBuf::from_str("public")?;
let dist_path = PathBuf::from_str("dist")?;
if dist_path.exists() {
std::fs::remove_dir_all(&dist_path).with_context(|| "Cannot delete `dist` directory")?;
@ -31,30 +91,7 @@ fn main() -> anyhow::Result<()> {
.with_context(|| "Cannot copy `public` -> `dist`")?;
}
// {{{ Generate contents
let djot_input = std::fs::read_to_string("content/arcaea.dj").unwrap();
let mut out = String::new();
let page_template = template!("templates/page.html")?;
let mut page_renderer = TemplateRenderer::new(&page_template);
while let Some(label) = page_renderer.next(&mut out)? {
if label == "content" {
let events = jotdown::Parser::new(&djot_input);
let html = Renderer::new()?;
html.push(events, &mut out)?;
} else {
break;
}
}
page_renderer.finish(&mut out)?;
// }}}
let posts_dir = dist_path.join("posts");
std::fs::create_dir(&posts_dir).with_context(|| "Cannot create `dist/posts` directory")?;
std::fs::write(posts_dir.join("arcaea.html"), out)
.with_context(|| "Failed to write `arcaea.html` post")?;
generate_dir(&PathBuf::new())?;
Ok(())
}

138
src/metadata.rs Normal file
View file

@ -0,0 +1,138 @@
#![allow(dead_code)]
use std::fmt::Write;
use anyhow::{anyhow, bail, Context};
use jotdown::{Container, Event};
use serde::Deserialize;
use crate::html;
#[derive(Deserialize, Debug, Default)]
pub struct PageConfig {
created_at: Option<String>,
}
impl PageConfig {
/// Merge another config into the current one. Might error out on duplicate values.
fn merge(&mut self, other: PageConfig) -> anyhow::Result<()> {
match &self.created_at {
None => self.created_at = other.created_at,
Some(first_created) => {
if let Some(second_created) = other.created_at {
if second_created != *first_created {
bail!("Conflicting values for `created_at` page attribute: {first_created} and {second_created}");
}
}
}
};
Ok(())
}
}
#[derive(Debug)]
pub struct PageMetadata {
title: Heading,
config: PageConfig,
toc: Vec<Heading>,
}
impl PageMetadata {
pub fn new<'s>(mut events: impl Iterator<Item = Event<'s>>) -> anyhow::Result<Self> {
let mut w = Writer::new();
events.try_for_each(|e| w.render_event(&e))?;
let title = w
.toc
.first()
.ok_or_else(|| anyhow!("No heading found to infer title from"))?;
Ok(Self {
title: title.to_owned(),
config: w.config,
toc: w.toc,
})
}
}
#[derive(Debug, Clone)]
struct Heading {
pub level: u8,
pub id: String,
pub text: String,
pub html: String,
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
enum State {
Toplevel,
Heading,
Toml,
}
struct Writer<'s> {
html_renderer: html::Writer<'s>,
config: PageConfig,
toc: Vec<Heading>,
toml_text: String,
state: State,
}
impl<'s> Writer<'s> {
fn new() -> Self {
Self {
html_renderer: html::Writer::new(),
config: PageConfig::default(),
toc: Vec::new(),
toml_text: String::new(),
state: State::Toplevel,
}
}
fn render_event(&mut self, e: &jotdown::Event<'s>) -> anyhow::Result<()> {
match e {
Event::Start(Container::Heading { level, id, .. }, _) => {
assert_eq!(self.state, State::Toplevel);
self.state = State::Heading;
self.toc.push(Heading {
level: *level as u8,
id: id.to_string(),
text: String::new(),
html: String::new(),
})
}
Event::End(Container::Heading { .. }) => {
assert_eq!(self.state, State::Heading);
self.state = State::Toplevel;
}
Event::Start(Container::RawBlock { format: "toml" }, _) => {
assert_eq!(self.state, State::Toplevel);
self.state = State::Toml
}
Event::End(Container::RawBlock { format: "toml" }) => {
assert_eq!(self.state, State::Toml);
self.state = State::Toplevel;
let config: PageConfig = toml::from_str(&self.toml_text)
.with_context(|| "Failed to parse page config in TOML format")?;
self.config.merge(config)?;
self.toml_text.clear();
}
Event::Str(str) if self.state == State::Toml => {
self.toml_text.write_str(str)?;
}
other if self.state == State::Heading => {
let last_heading = self.toc.last_mut().unwrap();
self.html_renderer.render_event(e, &mut last_heading.html)?;
if let Event::Str(str) = other {
last_heading.text.write_str(str)?;
}
}
_ => {}
}
Ok(())
}
}

View file

@ -1,25 +1,23 @@
use std::fmt::Write;
use anyhow::bail;
// {{{ Templates & stops
#[derive(Clone, Debug)]
struct Stop {
label: String,
struct Stop<'s> {
label: &'s str,
start: usize,
length: usize,
}
#[derive(Clone, Debug)]
pub struct Template {
text: String,
stops: Vec<Stop>,
pub struct Template<'s> {
text: &'s str,
stops: Vec<Stop<'s>>,
}
impl Template {
impl<'s> Template<'s> {
// {{{ Parse template
#[allow(clippy::iter_nth_zero)]
pub fn parse(text: String) -> anyhow::Result<Template> {
pub fn parse(text: &'s str) -> anyhow::Result<Template<'s>> {
let mut stops = Vec::new();
let open_stop = "{{";
@ -27,25 +25,23 @@ impl Template {
let mut current_stop: Option<Stop> = None;
let mut prev_ix = None;
for (ix, c) in text.char_indices() {
for (ix, _) in text.char_indices() {
if let Some(prev) = prev_ix {
// This char, together with the previous one
let last_two = &text[prev..=ix];
if close_stop == last_two {
if let Some(mut stop) = current_stop.take() {
stop.label.pop().unwrap();
// I think this is safe, as } is ascii
// I think this is safe, as { and } are ascii
stop.label = &text[stop.start + 2..=ix - 2];
stop.length = ix + 1 - stop.start;
stops.push(stop);
}
} else if open_stop == last_two && current_stop.is_none() {
current_stop = Some(Stop {
label: String::new(),
label: "",
start: prev,
length: 0,
});
} else if let Some(stop) = current_stop.as_mut() {
stop.label.write_char(c)?;
}
}
@ -67,7 +63,7 @@ enum RendererState {
#[derive(Clone, Debug)]
pub struct TemplateRenderer<'a> {
template: &'a Template,
template: &'a Template<'a>,
state: RendererState,
}
@ -84,7 +80,7 @@ impl<'a> TemplateRenderer<'a> {
pub fn current(&mut self, w: impl std::fmt::Write) -> anyhow::Result<Option<&'a str>> {
let current_label = match self.state {
RendererState::Started => self.next(w)?,
RendererState::InStop(ix) => Some(self.template.stops[ix].label.as_str()),
RendererState::InStop(ix) => Some(self.template.stops[ix].label),
RendererState::Finished => None,
};
@ -125,7 +121,7 @@ impl<'a> TemplateRenderer<'a> {
w.write_str(&self.template.text[current_pos..next_pos])?;
let current_label = match self.state {
RendererState::InStop(ix) => Some(self.template.stops[ix].label.as_str()),
RendererState::InStop(ix) => Some(self.template.stops[ix].label),
_ => None,
};
@ -150,8 +146,13 @@ impl<'a> TemplateRenderer<'a> {
#[macro_export]
macro_rules! template {
($path:literal) => {{
use once_cell::sync::OnceCell;
use $crate::template::Template;
static TEMPLATE_TEXT: &str = include_str!($path);
$crate::template::Template::parse(TEMPLATE_TEXT.to_owned())
static CELL: OnceCell<Template<'static>> = OnceCell::new();
CELL.get_or_try_init(|| Template::parse(TEMPLATE_TEXT))
}};
}
// }}}

View file

@ -1,32 +0,0 @@
use anyhow::anyhow;
use cached::{proc_macro::io_cached, DiskCache};
fn make_cache() -> DiskCache<&'static str, String> {
DiskCache::new("tex-cache")
.set_disk_directory("/home/moon/.cache/moonythm")
.build()
.unwrap()
}
#[io_cached(
disk = true,
map_error = r##"|err| anyhow::Error::from(err)"##,
create = r"{ make_cache() }"
)]
pub fn compile_tex(string: &str) -> Result<String, anyhow::Error> {
let res = std::process::Command::new("latexmlmath")
.arg("--preload=amsfonts")
.arg("--strict")
.arg("--quiet")
.arg(string)
.output()
.expect("failed to execute latexmathml process");
if res.status.success() {
let output = String::from_utf8_lossy(&res.stdout);
Ok(output.trim().to_owned())
} else {
let output = String::from_utf8_lossy(&res.stderr);
Err(anyhow!("{}", output.trim()))
}
}