From 9d91e829c889be68ba21ea6248bd8a7a670f2dc9 Mon Sep 17 00:00:00 2001 From: slonkazoid Date: Tue, 13 Aug 2024 15:53:18 +0300 Subject: [PATCH] switch to handlebars --- .gitignore | 1 + Cargo.lock | 939 ++++++++++++++++++++++++++++----------- Cargo.toml | 5 + README.md | 2 +- partials/post_table.hbs | 18 + partials/span_date.hbs | 1 + src/app.rs | 137 ++++-- src/config.rs | 2 +- src/error.rs | 9 +- src/filters.rs | 56 --- src/helpers.rs | 24 + src/main.rs | 58 ++- src/post/mod.rs | 1 + src/templates/mod.rs | 186 ++++++++ src/templates/watcher.rs | 126 ++++++ templates/index.hbs | 63 +++ templates/index.html | 70 --- templates/macros.askama | 31 -- templates/post.hbs | 71 +++ templates/post.html | 71 --- 20 files changed, 1330 insertions(+), 541 deletions(-) create mode 100644 partials/post_table.hbs create mode 100644 partials/span_date.hbs delete mode 100644 src/filters.rs create mode 100644 src/helpers.rs create mode 100644 src/templates/mod.rs create mode 100644 src/templates/watcher.rs create mode 100644 templates/index.hbs delete mode 100644 templates/index.html delete mode 100644 templates/macros.askama create mode 100644 templates/post.hbs delete mode 100644 templates/post.html diff --git a/.gitignore b/.gitignore index fd34989..f87a7e8 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ !/posts/README.md /cache /config.toml +/custom diff --git a/Cargo.lock b/Cargo.lock index faf9699..ebb7741 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -28,9 +28,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.82" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "askama" @@ -64,7 +64,7 @@ dependencies = [ "mime_guess", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.73", ] [[package]] @@ -84,9 +84,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.8" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07dbbf24db18d609b1462965249abdf49129ccad073ec257da372adc83259c60" +checksum = "fec134f64e2bc57411226dfc4e52dec859ddfc7e711fc5e07b612584f000e4aa" dependencies = [ "flate2", "futures-core", @@ -114,38 +114,38 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.73", ] [[package]] name = "async-trait" -version = "0.1.80" +version = "0.1.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" +checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.73", ] [[package]] name = "atom_syndication" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "571832dcff775e26562e8e6930cd483de5587301d40d3a3b85d532b6383e15a7" +checksum = "f2f34613907f31c9dbef0240156db3c9263f34842b6e1a8999d2304ea62c8a30" dependencies = [ "chrono", - "derive_builder", + "derive_builder 0.20.0", "diligent-date-parser", "never", - "quick-xml 0.30.0", + "quick-xml 0.31.0", ] [[package]] name = "autocfg" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "axum" @@ -160,7 +160,7 @@ dependencies = [ "futures-util", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.28", + "hyper 0.14.30", "itoa", "matchit", "memchr", @@ -187,9 +187,9 @@ dependencies = [ "bytes", "futures-util", "http 1.1.0", - "http-body 1.0.0", + "http-body 1.0.1", "http-body-util", - "hyper 1.3.1", + "hyper 1.4.1", "hyper-util", "itoa", "matchit", @@ -237,7 +237,7 @@ dependencies = [ "bytes", "futures-util", "http 1.1.0", - "http-body 1.0.0", + "http-body 1.0.1", "http-body-util", "mime", "pin-project-lite", @@ -257,7 +257,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.73", ] [[package]] @@ -281,6 +281,12 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "bincode" version = "1.3.3" @@ -304,9 +310,14 @@ dependencies = [ "console-subscriber", "derive_more", "fronma", + "handlebars", + "include_dir", + "mime_guess", + "notify-debouncer-full", "rss", "scc", "serde", + "serde_json", "syntect", "thiserror", "tokio", @@ -336,9 +347,9 @@ checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" [[package]] name = "bitcode" -version = "0.6.0" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48bc1c27654127a24c476d40198746860ef56475f41a601bfa5c4d0f832968f0" +checksum = "ee1bce7608560cd4bf0296a4262d0dbf13e6bcec5ff2105724c8ab88cc7fc784" dependencies = [ "bytemuck", "serde", @@ -352,9 +363,18 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] [[package]] name = "bumpalo" @@ -364,9 +384,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.15.0" +version = "1.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15" +checksum = "102087e286b4677862ea56cf8fc58bb2cdfa8725c40ffb80fe3a008eb7f2fc83" [[package]] name = "byteorder" @@ -376,15 +396,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "cc" -version = "1.0.94" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17f6e324229dc011159fcc089755d1e2e216a90d43a7dea6853ca740b84f35e7" +checksum = "e9e8aabfac534be767c909e0690571677d49f41bd8465ae876fe043d52ba5292" dependencies = [ "jobserver", "libc", @@ -439,7 +459,7 @@ version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0436149c9f6a1935b13306206c739b1ba84fa81f551b5eb87fc2ca7a13700af" dependencies = [ - "derive_builder", + "derive_builder 0.12.0", "entities", "memchr", "once_cell", @@ -494,28 +514,47 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" [[package]] -name = "crc32fast" -version = "1.4.0" +name = "cpufeatures" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[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-channel" -version = "0.5.12" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] [[package]] name = "darling" @@ -523,8 +562,18 @@ version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.14.4", + "darling_macro 0.14.4", +] + +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core 0.20.10", + "darling_macro 0.20.10", ] [[package]] @@ -537,21 +586,46 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim", + "strsim 0.10.0", "syn 1.0.109", ] +[[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 0.11.1", + "syn 2.0.73", +] + [[package]] name = "darling_macro" version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" dependencies = [ - "darling_core", + "darling_core 0.14.4", "quote", "syn 1.0.109", ] +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core 0.20.10", + "quote", + "syn 2.0.73", +] + [[package]] name = "deranged" version = "0.3.11" @@ -567,7 +641,16 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8" dependencies = [ - "derive_builder_macro", + "derive_builder_macro 0.12.0", +] + +[[package]] +name = "derive_builder" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0350b5cb0331628a5916d6c5c0b72e97393b8b6b03b47a9284f4e7f5a405ffd7" +dependencies = [ + "derive_builder_macro 0.20.0", ] [[package]] @@ -576,40 +659,72 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" dependencies = [ - "darling", + "darling 0.14.4", "proc-macro2", "quote", "syn 1.0.109", ] +[[package]] +name = "derive_builder_core" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d48cda787f839151732d396ac69e3473923d54312c070ee21e9effcaa8ca0b1d" +dependencies = [ + "darling 0.20.10", + "proc-macro2", + "quote", + "syn 2.0.73", +] + [[package]] name = "derive_builder_macro" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e" dependencies = [ - "derive_builder_core", + "derive_builder_core 0.12.0", "syn 1.0.109", ] [[package]] -name = "derive_more" -version = "0.99.17" +name = "derive_builder_macro" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b" +dependencies = [ + "derive_builder_core 0.20.0", + "syn 2.0.73", +] + +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "convert_case", "proc-macro2", "quote", "rustc_version", - "syn 1.0.109", + "syn 2.0.73", ] [[package]] name = "deunicode" -version = "1.4.4" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322ef0094744e63628e6f0eb2295517f79276a5b342a4c2ff3042566ca181d4e" +checksum = "339544cc9e2c4dc3fc7149fd630c5f22263a4fdf18a98afd0075784968b5cf00" + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] [[package]] name = "diligent-date-parser" @@ -622,9 +737,9 @@ dependencies = [ [[package]] name = "either" -version = "1.11.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "encoding_rs" @@ -668,10 +783,31 @@ dependencies = [ ] [[package]] -name = "flate2" -version = "1.0.28" +name = "file-id" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "6584280525fb2059cba3db2c04abf947a1a29a45ddae89f3870f8281704fafc9" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "filetime" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf401df4a4e3872c4fe8151134cf483738e74b67fc934d6532c882b3d24a4550" +dependencies = [ + "cfg-if", + "libc", + "libredox", + "windows-sys 0.59.0", +] + +[[package]] +name = "flate2" +version = "1.0.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f211bbe8e69bbd0cfdea405084f128ae8b4aaa6b0b522fc8f2b009084797920" dependencies = [ "crc32fast", "miniz_oxide", @@ -702,6 +838,15 @@ dependencies = [ "serde_yaml", ] +[[package]] +name = "fsevent-sys" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +dependencies = [ + "libc", +] + [[package]] name = "futures-channel" version = "0.3.30" @@ -742,10 +887,20 @@ dependencies = [ ] [[package]] -name = "getrandom" -version = "0.2.14" +name = "generic-array" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -770,13 +925,27 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.2.6", + "indexmap 2.3.0", "slab", "tokio", "tokio-util", "tracing", ] +[[package]] +name = "handlebars" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5226a0e122dc74917f3a701484482bed3ee86d016c7356836abbaa033133a157" +dependencies = [ + "log", + "pest", + "pest_derive", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -785,9 +954,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hdrhistogram" @@ -795,7 +964,7 @@ version = "7.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "765c9198f173dd59ce26ff9f95ef0aafd0a0fe01fb9d72841bc5066a4c06511d" dependencies = [ - "base64", + "base64 0.21.7", "byteorder", "flate2", "nom", @@ -849,9 +1018,9 @@ dependencies = [ [[package]] name = "http-body" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", "http 1.1.0", @@ -859,28 +1028,28 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", - "futures-core", + "futures-util", "http 1.1.0", - "http-body 1.0.0", + "http-body 1.0.1", "pin-project-lite", ] [[package]] name = "http-range-header" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ce4ef31cda248bbdb6e6820603b82dfcd9e833db65a43e997a0ccec777d11fe" +checksum = "08a397c49fec283e3d6211adbe480be95aae5f304cfb923e9970e08956d5168a" [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] name = "httpdate" @@ -896,9 +1065,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.28" +version = "0.14.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" dependencies = [ "bytes", "futures-channel", @@ -920,15 +1089,15 @@ dependencies = [ [[package]] name = "hyper" -version = "1.3.1" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" dependencies = [ "bytes", "futures-channel", "futures-util", "http 1.1.0", - "http-body 1.0.0", + "http-body 1.0.1", "httparse", "httpdate", "itoa", @@ -943,7 +1112,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" dependencies = [ - "hyper 0.14.28", + "hyper 0.14.30", "pin-project-lite", "tokio", "tokio-io-timeout", @@ -951,17 +1120,16 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.3" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" dependencies = [ "bytes", "futures-util", "http 1.1.0", - "http-body 1.0.0", - "hyper 1.3.1", + "http-body 1.0.1", + "hyper 1.4.1", "pin-project-lite", - "socket2", "tokio", ] @@ -981,6 +1149,25 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "include_dir" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "923d117408f1e49d914f1a379a309cffe4f18c05cf4e3d12e613a15fc81bd0dd" +dependencies = [ + "include_dir_macros", +] + +[[package]] +name = "include_dir_macros" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cab85a7ed0bd5f0e76d93846e0147172bed2e2d3f859bcc33a8d9699cad1a75" +dependencies = [ + "proc-macro2", + "quote", +] + [[package]] name = "indenter" version = "0.3.3" @@ -999,12 +1186,32 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.6" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.14.5", +] + +[[package]] +name = "inotify" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +dependencies = [ + "bitflags 1.3.2", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", ] [[package]] @@ -1024,30 +1231,55 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jobserver" -version = "0.1.30" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685a7d121ee3f65ae4fddd72b25a04bb36b6af81bc0828f7d5434c0fe60fa3a2" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] [[package]] -name = "lazy_static" -version = "1.4.0" +name = "kqueue" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" +dependencies = [ + "bitflags 1.3.2", + "libc", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] -name = "line-wrap" -version = "0.2.0" +name = "libredox" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd1bc4d24ad230d21fb898d1116b1801d7adfc449d42026475862ab48b11e70e" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.6.0", + "libc", + "redox_syscall", +] [[package]] name = "linked-hash-map" @@ -1056,10 +1288,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] -name = "log" -version = "0.4.21" +name = "lock_api" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "matchers" @@ -1078,9 +1320,9 @@ checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "mime" @@ -1090,9 +1332,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "mime_guess" -version = "2.0.4" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" dependencies = [ "mime", "unicase", @@ -1106,9 +1348,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", ] @@ -1120,10 +1362,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", + "log", "wasi", "windows-sys 0.48.0", ] +[[package]] +name = "mio" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" +dependencies = [ + "hermit-abi", + "libc", + "wasi", + "windows-sys 0.52.0", +] + [[package]] name = "never" version = "0.1.0" @@ -1140,6 +1395,38 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "notify" +version = "6.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" +dependencies = [ + "bitflags 2.6.0", + "crossbeam-channel", + "filetime", + "fsevent-sys", + "inotify", + "kqueue", + "libc", + "log", + "mio 0.8.11", + "walkdir", + "windows-sys 0.48.0", +] + +[[package]] +name = "notify-debouncer-full" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f5dab59c348b9b50cf7f261960a20e389feb2713636399cd9082cd4b536154" +dependencies = [ + "file-id", + "log", + "notify", + "parking_lot", + "walkdir", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -1158,23 +1445,13 @@ checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - [[package]] name = "object" version = "0.32.2" @@ -1224,12 +1501,80 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + [[package]] name = "percent-encoding" version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "pest" +version = "2.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.73", +] + +[[package]] +name = "pest_meta" +version = "2.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f" +dependencies = [ + "once_cell", + "pest", + "sha2", +] + [[package]] name = "pin-project" version = "1.1.5" @@ -1247,7 +1592,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.73", ] [[package]] @@ -1270,14 +1615,13 @@ checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "plist" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9d34169e64b3c7a80c8621a48adaf44e0cf62c78a9b25dd9dd35f1881a17cf9" +checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016" dependencies = [ - "base64", - "indexmap 2.2.6", - "line-wrap", - "quick-xml 0.31.0", + "base64 0.22.1", + "indexmap 2.3.0", + "quick-xml 0.32.0", "serde", "time", ] @@ -1290,24 +1634,27 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "proc-macro2" -version = "1.0.81" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] [[package]] name = "prost" -version = "0.12.4" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0f5d036824e4761737860779c906171497f6d55681139d8312388f8fe398922" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" dependencies = [ "bytes", "prost-derive", @@ -1315,41 +1662,41 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.12.4" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19de2de2a00075bf566bee3bd4db014b11587e84184d3f7a791bc17f1a8e9e48" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", "itertools", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.73", ] [[package]] name = "prost-types" -version = "0.12.4" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3235c33eb02c1f1e212abdbe34c78b264b038fb58ca612664343271e36e55ffe" +checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" dependencies = [ "prost", ] -[[package]] -name = "quick-xml" -version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956" -dependencies = [ - "encoding_rs", - "memchr", -] - [[package]] name = "quick-xml" version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" +dependencies = [ + "encoding_rs", + "memchr", +] + +[[package]] +name = "quick-xml" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2" dependencies = [ "memchr", ] @@ -1394,15 +1741,24 @@ dependencies = [ ] [[package]] -name = "regex" -version = "1.10.4" +name = "redox_syscall" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "regex" +version = "1.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.6", - "regex-syntax 0.8.3", + "regex-automata 0.4.7", + "regex-syntax 0.8.4", ] [[package]] @@ -1416,13 +1772,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.3", + "regex-syntax 0.8.4", ] [[package]] @@ -1433,27 +1789,27 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "rss" -version = "2.0.7" +version = "2.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7b2c77eb4450d7d5f98df52c381cd6c4e19b75dad9209a9530b85a44510219a" +checksum = "2f374fd66bb795938b78c021db1662d43a8ffbc42ec1ac25429fc4833b732751" dependencies = [ "atom_syndication", - "derive_builder", + "derive_builder 0.20.0", "never", - "quick-xml 0.30.0", + "quick-xml 0.31.0", ] [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc_version" @@ -1466,15 +1822,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -1487,19 +1843,25 @@ dependencies = [ [[package]] name = "scc" -version = "2.1.0" +version = "2.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec96560eea317a9cc4e0bb1f6a2c93c09a19b8c4fc5cb3fcc0ec1c094cd783e2" +checksum = "c76e6f627d67cd14a317d7909585f4d06609acafd7891432ea45ce519211a8e9" dependencies = [ "sdd", "serde", ] [[package]] -name = "sdd" -version = "0.2.0" +name = "scopeguard" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b84345e4c9bd703274a082fb80caaa99b7612be48dfaa1dd9266577ec412309d" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sdd" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f081bcf2e6c4d1d88d2b8d1c9d8a308993eafbdabb851050be4b2ff14d2c5649" [[package]] name = "semver" @@ -1509,31 +1871,33 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.198" +version = "1.0.206" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" +checksum = "5b3e4cd94123dd520a128bcd11e34d9e9e423e7e3e50425cb1b4b1e3549d0284" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.198" +version = "1.0.206" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" +checksum = "fabfb6138d2383ea8208cf98ccf69cdfb1aff4088460681d84189aa259762f97" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.73", ] [[package]] name = "serde_json" -version = "1.0.116" +version = "1.0.124" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" +checksum = "66ad62847a56b3dba58cc891acd13884b9c61138d330c0d7b6181713d4fce38d" dependencies = [ + "indexmap 2.3.0", "itoa", + "memchr", "ryu", "serde", ] @@ -1550,9 +1914,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.5" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" dependencies = [ "serde", ] @@ -1581,6 +1945,17 @@ dependencies = [ "yaml-rust", ] +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -1626,9 +2001,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", "windows-sys 0.52.0", @@ -1640,6 +2015,12 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "syn" version = "1.0.109" @@ -1653,9 +2034,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.60" +version = "2.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +checksum = "837a7e8026c6ce912ff01cefbe8cafc2f8010ac49682e2a3d9decc3bce1ecaaf" dependencies = [ "proc-macro2", "quote", @@ -1688,7 +2069,7 @@ dependencies = [ "once_cell", "onig", "plist", - "regex-syntax 0.8.3", + "regex-syntax 0.8.4", "serde", "serde_derive", "serde_json", @@ -1699,22 +2080,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.58" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.58" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.73", ] [[package]] @@ -1760,9 +2141,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -1775,21 +2156,20 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.37.0" +version = "1.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" dependencies = [ "backtrace", "bytes", "libc", - "mio", - "num_cpus", + "mio 1.0.1", "pin-project-lite", "signal-hook-registry", "socket2", "tokio-macros", "tracing", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1804,13 +2184,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.73", ] [[package]] @@ -1826,23 +2206,22 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] name = "toml" -version = "0.8.12" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" dependencies = [ "serde", "serde_spanned", @@ -1852,20 +2231,20 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.5" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.12" +version = "0.22.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3328d4f68a705b2a4498da1d580585d39a6510f98318a2cec3018a7ec61ddef" +checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.3.0", "serde", "serde_spanned", "toml_datetime", @@ -1881,12 +2260,12 @@ dependencies = [ "async-stream", "async-trait", "axum 0.6.20", - "base64", + "base64 0.21.7", "bytes", "h2", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.28", + "hyper 0.14.30", "hyper-timeout", "percent-encoding", "pin-project", @@ -1926,12 +2305,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" dependencies = [ "async-compression", - "bitflags 2.5.0", + "bitflags 2.6.0", "bytes", "futures-core", "futures-util", "http 1.1.0", - "http-body 1.0.0", + "http-body 1.0.1", "http-body-util", "http-range-header", "httpdate", @@ -1977,7 +2356,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.73", ] [[package]] @@ -2041,6 +2420,18 @@ version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + [[package]] name = "unicase" version = "2.7.0" @@ -2079,9 +2470,9 @@ checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" [[package]] name = "url" -version = "2.5.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", @@ -2097,9 +2488,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "walkdir" @@ -2147,7 +2538,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.73", "wasm-bindgen-shared", ] @@ -2169,7 +2560,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.73", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2198,11 +2589,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "winapi", + "windows-sys 0.59.0", ] [[package]] @@ -2226,7 +2617,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -2246,18 +2646,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -2268,9 +2668,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -2280,9 +2680,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -2292,15 +2692,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -2310,9 +2710,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -2322,9 +2722,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -2334,9 +2734,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -2346,15 +2746,15 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.6" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c976aaaa0e1f90dbb21e9587cdaf1d9679a1cde8875c0d6bd83ab96a208352" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" dependencies = [ "memchr", ] @@ -2369,28 +2769,49 @@ dependencies = [ ] [[package]] -name = "zstd" -version = "0.13.1" +name = "zerocopy" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d789b1514203a1120ad2429eae43a7bd32b90976a7bb8a05f7ec02fa88cc23a" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "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 2.0.73", +] + +[[package]] +name = "zstd" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "7.1.0" +version = "7.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd99b45c6bc03a018c8b8a86025678c87e55526064e38f9df301989dce7ec0a" +checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" dependencies = [ "zstd-sys", ] [[package]] name = "zstd-sys" -version = "2.0.10+zstd.1.5.6" +version = "2.0.13+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" dependencies = [ "cc", "pkg-config", diff --git a/Cargo.toml b/Cargo.toml index b708cc5..b94d7a1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,9 +38,14 @@ comrak = { version = "0.22.0", features = [ console-subscriber = { version = "0.2.0", optional = true } derive_more = "0.99.17" fronma = "0.2.0" +handlebars = "6.0.0" +include_dir = "0.7.4" +mime_guess = "2.0.5" +notify-debouncer-full = { version = "0.3.1", default-features = false } rss = "2.0.7" scc = { version = "2.1.0", features = ["serde"] } serde = { version = "1.0.197", features = ["derive"] } +serde_json = { version = "1.0.124", features = ["preserve_order"] } syntect = "5.2.0" thiserror = "1.0.58" tokio = { version = "1.37.0", features = [ diff --git a/README.md b/README.md index e87220f..f131b72 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ date_format = "RFC3339" # format string used to format dates in the backend # so the date can be formatted by the browser. # format: https://docs.rs/chrono/latest/chrono/format/strftime/index.html#specifiers default_sort = "date" # default sorting method ("date" or "name") -default_color = "#f5c2e7" # default embed color, optional +#default_color = "#f5c2e7" # default embed color, optional [rss] enable = false # serve an rss field under /feed.xml diff --git a/partials/post_table.hbs b/partials/post_table.hbs new file mode 100644 index 0000000..8655ca6 --- /dev/null +++ b/partials/post_table.hbs @@ -0,0 +1,18 @@ +
+ {{#if (ne this.created_at null)}} +
written
+
{{>span_date date_time=this.created_at}}
+ {{/if}} + {{#if (ne this.modified_at null)}} +
last modified
+
{{>span_date date_time=this.modified_at}}
+ {{/if}} + {{#if (gt (len this.tags) 0)}} +
tags
+
+ {{#each this.tags}} + {{this}} + {{/each}} +
+ {{/if}} +
diff --git a/partials/span_date.hbs b/partials/span_date.hbs new file mode 100644 index 0000000..a8c92f5 --- /dev/null +++ b/partials/span_date.hbs @@ -0,0 +1 @@ +{{date date_time df}} diff --git a/src/app.rs b/src/app.rs index b3e7337..db8d723 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,32 +1,35 @@ +use std::collections::HashMap; use std::sync::Arc; use std::time::Duration; -use askama_axum::Template; use axum::extract::{Path, Query, State}; use axum::http::header::CONTENT_TYPE; -use axum::http::{header, Request}; +use axum::http::Request; use axum::response::{IntoResponse, Redirect, Response}; use axum::routing::get; use axum::{Json, Router}; +use handlebars::Handlebars; use rss::{Category, ChannelBuilder, ItemBuilder}; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; +use serde_json::Map; +use tokio::sync::RwLock; use tower_http::services::ServeDir; use tower_http::trace::TraceLayer; use tracing::{info, info_span, Span}; use crate::config::{Config, DateFormat, Sort}; use crate::error::{AppError, AppResult}; -use crate::filters; use crate::post::{MarkdownPosts, PostManager, PostMetadata, RenderStats, ReturnedPost}; #[derive(Clone)] +#[non_exhaustive] pub struct AppState { pub config: Arc, pub posts: Arc>>, + pub reg: Arc>>, } -#[derive(Template)] -#[template(path = "index.html")] +#[derive(Serialize)] struct IndexTemplate<'a> { title: &'a str, description: &'a str, @@ -36,10 +39,11 @@ struct IndexTemplate<'a> { js: bool, color: Option<&'a str>, sort: Sort, + tags: Map, + joined_tags: String, } -#[derive(Template)] -#[template(path = "post.html")] +#[derive(Serialize)] struct PostTemplate<'a> { meta: &'a PostMetadata, rendered: String, @@ -48,6 +52,7 @@ struct PostTemplate<'a> { df: &'a DateFormat, js: bool, color: Option<&'a str>, + joined_tags: String, } #[derive(Deserialize)] @@ -57,25 +62,77 @@ struct QueryParams { num_posts: Option, } +fn collect_tags(posts: &Vec) -> Map { + let mut tags = HashMap::new(); + + for post in posts { + for tag in &post.tags { + if let Some((existing_tag, count)) = tags.remove_entry(tag) { + tags.insert(existing_tag, count + 1); + } else { + tags.insert(tag.clone(), 1); + } + } + } + + let mut tags: Vec<(String, u64)> = tags.into_iter().collect(); + + tags.sort_unstable_by_key(|(v, _)| v.clone()); + tags.sort_by_key(|(_, v)| -(*v as i64)); + + let mut map = Map::new(); + + for tag in tags.into_iter() { + map.insert(tag.0, tag.1.into()); + } + + map +} + +fn join_tags_for_meta(tags: &Map, delim: &str) -> String { + let mut s = String::new(); + let tags = tags.keys().enumerate(); + let len = tags.len(); + for (i, tag) in tags { + s += tag; + if i != len - 1 { + s += delim; + } + } + s +} + async fn index<'a>( - State(AppState { config, posts }): State, + State(AppState { + config, posts, reg, .. + }): State, Query(query): Query, -) -> AppResult { +) -> AppResult { let posts = posts .get_max_n_post_metadata_with_optional_tag_sorted(query.num_posts, query.tag.as_ref()) .await?; - Ok(IndexTemplate { - title: &config.title, - description: &config.description, - posts, - rss: config.rss.enable, - df: &config.date_format, - js: config.js_enable, - color: config.default_color.as_deref(), - sort: config.default_sort, - } - .into_response()) + let tags = collect_tags(&posts); + let joined_tags = join_tags_for_meta(&tags, ", "); + + let reg = reg.read().await; + let rendered = reg.render( + "index", + &IndexTemplate { + title: &config.title, + description: &config.description, + posts, + rss: config.rss.enable, + df: &config.date_format, + js: config.js_enable, + color: config.default_color.as_deref(), + sort: config.default_sort, + tags, + joined_tags, + }, + ); + drop(reg); + Ok(([(CONTENT_TYPE, "text/html")], rendered?)) } async fn all_posts( @@ -90,7 +147,7 @@ async fn all_posts( } async fn rss( - State(AppState { config, posts }): State, + State(AppState { config, posts, .. }): State, Query(query): Query, ) -> AppResult { if !config.rss.enable { @@ -145,24 +202,36 @@ async fn rss( let body = channel.build().to_string(); drop(channel); - Ok(([(header::CONTENT_TYPE, "text/xml")], body).into_response()) + Ok(([(CONTENT_TYPE, "text/xml")], body).into_response()) } async fn post( - State(AppState { config, posts }): State, + State(AppState { + config, posts, reg, .. + }): State, Path(name): Path, -) -> AppResult { +) -> AppResult { match posts.get_post(&name).await? { - ReturnedPost::Rendered(ref meta, rendered, rendered_in) => Ok(PostTemplate { - meta, - rendered, - rendered_in, - markdown_access: config.markdown_access, - df: &config.date_format, - js: config.js_enable, - color: meta.color.as_deref().or(config.default_color.as_deref()), + ReturnedPost::Rendered(ref meta, rendered, rendered_in) => { + let joined_tags = meta.tags.join(", "); + + let reg = reg.read().await; + let rendered = reg.render( + "post", + &PostTemplate { + meta, + rendered, + rendered_in, + markdown_access: config.markdown_access, + df: &config.date_format, + js: config.js_enable, + color: meta.color.as_deref().or(config.default_color.as_deref()), + joined_tags, + }, + ); + drop(reg); + Ok(([(CONTENT_TYPE, "text/html")], rendered?).into_response()) } - .into_response()), ReturnedPost::Raw(body, content_type) => { Ok(([(CONTENT_TYPE, content_type)], body).into_response()) } diff --git a/src/config.rs b/src/config.rs index 24c2b72..92ec628 100644 --- a/src/config.rs +++ b/src/config.rs @@ -102,7 +102,7 @@ impl Default for Config { js_enable: true, date_format: Default::default(), default_sort: Default::default(), - default_color: Some("#f5c2e7".into()), + default_color: None, // i have a love-hate relationship with serde // it was engimatic at first, but then i started actually using it // writing my own serialize and deserialize implementations.. spending diff --git a/src/error.rs b/src/error.rs index 25dda7e..7790493 100644 --- a/src/error.rs +++ b/src/error.rs @@ -53,6 +53,8 @@ pub type AppResult = Result; pub enum AppError { #[error("failed to fetch post: {0}")] PostError(#[from] PostError), + #[error(transparent)] + HandlebarsError(#[from] handlebars::RenderError), #[error("rss is disabled")] RssDisabled, #[error(transparent)] @@ -75,12 +77,9 @@ struct ErrorTemplate { impl IntoResponse for AppError { fn into_response(self) -> Response { let status_code = match &self { - AppError::PostError(err) => match err { - PostError::NotFound(_) => StatusCode::NOT_FOUND, - _ => StatusCode::INTERNAL_SERVER_ERROR, - }, + AppError::PostError(PostError::NotFound(_)) => StatusCode::NOT_FOUND, AppError::RssDisabled => StatusCode::FORBIDDEN, - AppError::UrlError(_) => StatusCode::INTERNAL_SERVER_ERROR, + _ => StatusCode::INTERNAL_SERVER_ERROR, }; ( status_code, diff --git a/src/filters.rs b/src/filters.rs deleted file mode 100644 index 4e40ac9..0000000 --- a/src/filters.rs +++ /dev/null @@ -1,56 +0,0 @@ -use std::collections::HashMap; -use std::fmt::Display; -use std::time::Duration; - -use chrono::{DateTime, TimeZone}; - -use crate::config::DateFormat; -use crate::post::PostMetadata; - -fn format_date(date: &DateTime, date_format: &DateFormat) -> String -where - T: TimeZone, - T::Offset: Display, -{ - match date_format { - DateFormat::RFC3339 => date.to_rfc3339_opts(chrono::SecondsFormat::Secs, true), - DateFormat::Strftime(ref format_string) => date.format(format_string).to_string(), - } -} - -pub fn date(date: &DateTime, date_format: &DateFormat) -> Result -where - T: TimeZone, - T::Offset: Display, -{ - Ok(format_date(date, date_format)) -} - -pub fn duration(duration: &&Duration) -> Result { - Ok(format!("{:?}", duration)) -} - -pub fn collect_tags(posts: &Vec) -> Result, askama::Error> { - let mut tags = HashMap::new(); - - for post in posts { - for tag in &post.tags { - if let Some((existing_tag, count)) = tags.remove_entry(tag) { - tags.insert(existing_tag, count + 1); - } else { - tags.insert(tag.clone(), 1); - } - } - } - - let mut tags: Vec<(String, u64)> = tags.into_iter().collect(); - - tags.sort_unstable_by_key(|(v, _)| v.clone()); - tags.sort_by_key(|(_, v)| -(*v as i64)); - - Ok(tags) -} - -pub fn join_tags_for_meta(tags: &Vec) -> Result { - Ok(tags.join(", ")) -} diff --git a/src/helpers.rs b/src/helpers.rs new file mode 100644 index 0000000..a0d4f8d --- /dev/null +++ b/src/helpers.rs @@ -0,0 +1,24 @@ +use std::fmt::Display; +use std::time::Duration; + +use chrono::{DateTime, TimeZone, Utc}; +use handlebars::handlebars_helper; + +use crate::config::DateFormat; + +fn date_impl(date_time: &DateTime, date_format: &DateFormat) -> String +where + T: TimeZone, + T::Offset: Display, +{ + match date_format { + DateFormat::RFC3339 => date_time.to_rfc3339_opts(chrono::SecondsFormat::Secs, true), + DateFormat::Strftime(ref format_string) => date_time.format(format_string).to_string(), + } +} + +handlebars_helper!(date: |date_time: Option>, date_format: DateFormat| { + date_impl(date_time.as_ref().unwrap(), &date_format) +}); + +handlebars_helper!(duration: |duration_: Duration| format!("{:?}", duration_)); diff --git a/src/main.rs b/src/main.rs index 86cae0e..9b0a620 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,13 +3,14 @@ mod app; mod config; mod error; -mod filters; mod hash_arc_store; +mod helpers; mod markdown_render; mod platform; mod post; mod ranged_i128_visitor; mod systemtime_as_secs; +mod templates; use std::future::IntoFuture; use std::net::SocketAddr; @@ -19,31 +20,40 @@ use std::time::Duration; use color_eyre::eyre::{self, Context}; use tokio::net::TcpListener; +use tokio::sync::RwLock; use tokio::task::JoinSet; +use tokio::time::Instant; use tokio::{select, signal}; use tokio_util::sync::CancellationToken; use tracing::level_filters::LevelFilter; -use tracing::{debug, info, warn}; +use tracing::{debug, error, info, info_span, warn, Instrument}; use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::{util::SubscriberInitExt, EnvFilter}; use crate::app::AppState; use crate::post::{MarkdownPosts, PostManager}; +use crate::templates::new_registry; +use crate::templates::watcher::watch_templates; #[tokio::main] async fn main() -> eyre::Result<()> { - #[cfg(feature = "tokio-console")] - console_subscriber::init(); color_eyre::install()?; - #[cfg(not(feature = "tokio-console"))] - tracing_subscriber::registry() + let reg = tracing_subscriber::registry(); + #[cfg(feature = "tokio-console")] + let reg = reg .with( EnvFilter::builder() - .with_default_directive(LevelFilter::INFO.into()) + .with_default_directive(LevelFilter::TRACE.into()) .from_env_lossy(), ) - .with(tracing_subscriber::fmt::layer()) - .init(); + .with(console_subscriber::spawn()); + #[cfg(not(feature = "tokio-console"))] + let reg = reg.with( + EnvFilter::builder() + .with_default_directive(LevelFilter::INFO.into()) + .from_env_lossy(), + ); + reg.with(tracing_subscriber::fmt::layer()).init(); let config = Arc::new( config::load() @@ -56,22 +66,41 @@ async fn main() -> eyre::Result<()> { let mut tasks = JoinSet::new(); let cancellation_token = CancellationToken::new(); + let start = Instant::now(); + // NOTE: use tokio::task::spawn_blocking if this ever turns into a concurrent task + let mut reg = + new_registry("custom/templates").context("failed to create handlebars registry")?; + reg.register_helper("date", Box::new(helpers::date)); + reg.register_helper("duration", Box::new(helpers::duration)); + debug!(duration = ?start.elapsed(), "registered all templates"); + + let reg = Arc::new(RwLock::new(reg)); + + let watcher_token = cancellation_token.child_token(); + let posts = Arc::new(MarkdownPosts::new(Arc::clone(&config)).await?); let state = AppState { config: Arc::clone(&config), posts: Arc::clone(&posts), + reg: Arc::clone(®), }; + debug!("setting up watcher"); + tasks.spawn( + watch_templates("custom/templates", watcher_token.clone(), reg) + .instrument(info_span!("custom_template_watcher")), + ); + if config.cache.enable && config.cache.cleanup { - if let Some(t) = config.cache.cleanup_interval { + if let Some(millis) = config.cache.cleanup_interval { let posts = Arc::clone(&posts); let token = cancellation_token.child_token(); debug!("setting up cleanup task"); tasks.spawn(async move { - let mut interval = tokio::time::interval(Duration::from_millis(t)); + let mut interval = tokio::time::interval(Duration::from_millis(millis)); loop { select! { - _ = token.cancelled() => break, + _ = token.cancelled() => break Ok(()), _ = interval.tick() => { posts.cleanup().await } @@ -122,7 +151,10 @@ async fn main() -> eyre::Result<()> { cancellation_token.cancel(); server.await.context("failed to serve app")?; while let Some(task) = tasks.join_next().await { - task.context("failed to join task")?; + let res = task.context("failed to join task")?; + if let Err(err) = res { + error!("task failed with error: {err}"); + } } drop(state); diff --git a/src/post/mod.rs b/src/post/mod.rs index 202d78b..111b156 100644 --- a/src/post/mod.rs +++ b/src/post/mod.rs @@ -24,6 +24,7 @@ pub struct PostMetadata { pub tags: Vec, } +#[derive(Serialize)] pub enum RenderStats { Cached(Duration), // format: Total, Parsed in, Rendered in diff --git a/src/templates/mod.rs b/src/templates/mod.rs new file mode 100644 index 0000000..3fe61f3 --- /dev/null +++ b/src/templates/mod.rs @@ -0,0 +1,186 @@ +pub mod watcher; + +use std::{io, path::Path}; + +use handlebars::{Handlebars, Template}; +use include_dir::{include_dir, Dir}; +use thiserror::Error; +use tracing::{debug, error, info_span, trace}; + +const TEMPLATES: Dir<'static> = include_dir!("$CARGO_MANIFEST_DIR/templates"); +const PARTIALS: Dir<'static> = include_dir!("$CARGO_MANIFEST_DIR/partials"); + +#[derive(Error, Debug)] +#[allow(clippy::enum_variant_names)] +pub enum TemplateError { + #[error(transparent)] + IoError(#[from] std::io::Error), + #[error("file doesn't contain valid UTF-8")] + UTF8Error, + #[error(transparent)] + TemplateError(#[from] handlebars::TemplateError), +} + +fn is_ext(path: impl AsRef, ext: &str) -> bool { + match path.as_ref().extension() { + Some(path_ext) if path_ext != ext => false, + None => false, + _ => true, + } +} + +pub(self) fn get_template_name<'a>(path: &'a Path) -> Option<&'a str> { + if !is_ext(path, "hbs") { + return None; + } + + path.file_stem()?.to_str() +} + +fn register_included_file( + file: &include_dir::File<'_>, + name: &str, + registry: &mut Handlebars, +) -> Result<(), TemplateError> { + let template = compile_included_file(file)?; + registry.register_template(name, template); + Ok(()) +} + +fn register_path<'a>( + path: impl AsRef, + name: &str, + registry: &mut Handlebars<'a>, +) -> Result<(), TemplateError> { + let template = compile_path(path)?; + registry.register_template(name, template); + Ok(()) +} + +fn register_partial( + file: &include_dir::File<'_>, + name: &str, + registry: &mut Handlebars, +) -> Result<(), TemplateError> { + registry.register_partial(name, file.contents_utf8().ok_or(TemplateError::UTF8Error)?)?; + Ok(()) +} + +fn compile_included_file(file: &include_dir::File<'_>) -> Result { + let contents = file.contents_utf8().ok_or(TemplateError::UTF8Error)?; + + let template = Template::compile(contents)?; + Ok(template) +} + +fn compile_path(path: impl AsRef) -> Result { + use std::fs::OpenOptions; + use std::io::Read; + + let mut file = OpenOptions::new().read(true).open(path)?; + let mut buf = String::new(); + file.read_to_string(&mut buf)?; + + let template = Template::compile(&buf)?; + Ok(template) +} + +pub(self) async fn compile_path_async_io( + path: impl AsRef, +) -> Result { + use tokio::fs::OpenOptions; + use tokio::io::AsyncReadExt; + + let mut file = OpenOptions::new().read(true).open(path).await?; + let mut buf = String::new(); + file.read_to_string(&mut buf).await?; + + let template = Template::compile(&buf)?; + Ok(template) +} + +pub fn new_registry<'a>(custom_templates_path: impl AsRef) -> io::Result> { + let mut reg = Handlebars::new(); + + for entry in TEMPLATES.entries() { + let file = match entry.as_file() { + Some(file) => file, + None => continue, + }; + + let span = info_span!("register_included_template", path = ?file.path()); + let _handle = span.enter(); + + let name = match get_template_name(file.path()) { + Some(v) => v, + None => { + trace!("skipping file"); + continue; + } + }; + + match register_included_file(file, name, &mut reg) { + Ok(()) => debug!("registered template {name:?}"), + Err(err) => error!("error while registering template: {err}"), + }; + } + + for entry in PARTIALS.entries() { + let file = match entry.as_file() { + Some(file) => file, + None => continue, + }; + + let span = info_span!("register_partial", path = ?file.path()); + let _handle = span.enter(); + + let name = match get_template_name(file.path()) { + Some(v) => v, + None => { + trace!("skipping file"); + continue; + } + }; + + match register_partial(file, name, &mut reg) { + Ok(()) => debug!("registered partial {name:?}"), + Err(err) => error!("error while registering partial: {err}"), + }; + } + + let read_dir = match std::fs::read_dir(custom_templates_path) { + Ok(v) => v, + Err(err) => match err.kind() { + io::ErrorKind::NotFound => return Ok(reg), + _ => panic!("{:?}", err), + }, + }; + for entry in read_dir { + let entry = entry.unwrap(); + + let file_type = entry.file_type()?; + if !file_type.is_file() { + continue; + } + + let path = entry.path(); + + let span = info_span!("register_custom_template", ?path); + let _handle = span.enter(); + + let name = match get_template_name(&path) { + Some(v) => v, + None => { + trace!("skipping file"); + continue; + } + }; + + match register_path(&path, name, &mut reg) { + Ok(()) => debug!("registered template {name:?}"), + Err(err) => error!("error while registering template: {err}"), + }; + } + + Ok(reg) +} diff --git a/src/templates/watcher.rs b/src/templates/watcher.rs new file mode 100644 index 0000000..19acc22 --- /dev/null +++ b/src/templates/watcher.rs @@ -0,0 +1,126 @@ +use std::path::Path; +use std::sync::Arc; +use std::time::Duration; + +use handlebars::{Handlebars, Template}; +use notify_debouncer_full::notify::{self, Watcher}; +use notify_debouncer_full::{new_debouncer, DebouncedEvent}; +use tokio::select; +use tokio::sync::RwLock; +use tokio_util::sync::CancellationToken; +use tracing::{debug, error, info, trace, trace_span}; + +use crate::templates::*; + +async fn process_event( + event: DebouncedEvent, + templates: &mut Vec<(String, Template)>, +) -> Result<(), Box> { + match event.kind { + notify::EventKind::Create(notify::event::CreateKind::File) + | notify::EventKind::Modify(_) => { + for path in &event.paths { + let span = trace_span!("modify_event", ?path); + let _handle = span.enter(); + + let template_name = match get_template_name(path) { + Some(v) => v, + None => { + trace!("skipping event"); + continue; + } + }; + + trace!("processing recompilation"); + let compiled = compile_path_async_io(path).await?; + trace!("compiled template {template_name:?}"); + templates.push((template_name.to_owned(), compiled)); + } + } + notify::EventKind::Remove(notify::event::RemoveKind::File) => { + for path in &event.paths { + let span = trace_span!("remove_event", ?path); + let _handle = span.enter(); + + let (file_name, template_name) = match path + .file_name() + .and_then(|o| o.to_str()) + .and_then(|file_name| { + get_template_name(Path::new(file_name)) + .map(|template_name| (file_name, template_name)) + }) { + Some(v) => v, + None => { + trace!("skipping event"); + continue; + } + }; + + trace!("processing removal"); + let file = TEMPLATES.get_file(file_name); + if let Some(file) = file { + let compiled = compile_included_file(file)?; + trace!("compiled template {template_name:?}"); + templates.push((template_name.to_owned(), compiled)); + } + } + } + _ => {} + }; + + Ok(()) +} + +pub async fn watch_templates<'a>( + path: impl AsRef, + watcher_token: CancellationToken, + reg: Arc>>, +) -> Result<(), Box> { + let path = path.as_ref(); + + let (tx, mut rx) = tokio::sync::mpsc::channel(1); + + let mut debouncer = new_debouncer(Duration::from_millis(100), None, move |events| { + tx.blocking_send(events) + .expect("failed to send message over channel") + })?; + + debouncer + .watcher() + .watch(path, notify::RecursiveMode::NonRecursive)?; + + 'event_loop: while let Some(events) = select! { + _ = watcher_token.cancelled() => { + debug!("exiting watcher loop"); + break 'event_loop; + }, + events = rx.recv() => events + } { + let events = match events { + Ok(events) => events, + Err(err) => { + error!("error getting events: {err:?}"); + continue; + } + }; + + let mut templates = Vec::new(); + + for event in events { + trace!("file event: {event:?}"); + if let Err(err) = process_event(event, &mut templates).await { + error!("error while processing event: {err}"); + } + } + + let mut reg = reg.write().await; + for template in templates.into_iter() { + debug!("registered template {}", template.0); + reg.register_template(&template.0, template.1); + } + drop(reg); + info!("updated custom templates"); + } + + Ok(()) +} diff --git a/templates/index.hbs b/templates/index.hbs new file mode 100644 index 0000000..549c547 --- /dev/null +++ b/templates/index.hbs @@ -0,0 +1,63 @@ + + + + + + + + + {{#if (ne color null)}} + + {{/if}} + {{title}} + + {{#if rss}} + + {{/if}} + {{#if js}} + + + + {{/if}} + + +
+

{{title}}

+

{{description}}

+

posts

+
+ {{#if js}} + + {{/if}} + {{#each posts}} +
+
+ {{title}} + +
+ {{description}}
+ {{>post_table post df=@root.df}} +
+
+ {{else}} there are no posts right now. check back later! {{/each}} +
+ + {{#if (gt (len tags) 0)}} +

tags

+ clear tags +
+ {{/if}} + {{#each tags}} + {{@key}} +
+ {{/each}} +
+ + diff --git a/templates/index.html b/templates/index.html deleted file mode 100644 index fd00eb1..0000000 --- a/templates/index.html +++ /dev/null @@ -1,70 +0,0 @@ -{%- import "macros.askama" as macros -%} - - - - - - - - - {% match color %} {% when Some with (color) %} - - {% when None %} {% endmatch %} - {{ title }} - - - - {% if rss %} - - {% endif %} - - {% if js %} - - - - {% endif %} - - -
-

{{ title }}

-

{{ description }}

-

posts

-
- {% if posts.is_empty() %} - there are no posts right now. check back later! - {% else %} - {% if js %} - - {% endif %} -
- {% for post in posts %} -
- {{ post.title }} - -
- {{ post.description }}
- {% call macros::table(post) %} -
- {% endfor %} -
- {% endif %} -
- {% let tags = posts|collect_tags %} - {% if !tags.is_empty() %} -

tags

- clear tags -
- {% endif %} - {% for tag in tags %} - {{ tag.0 }} -
- {% endfor %} -
- - diff --git a/templates/macros.askama b/templates/macros.askama deleted file mode 100644 index bd21a25..0000000 --- a/templates/macros.askama +++ /dev/null @@ -1,31 +0,0 @@ -{% macro span_date(value) %} -{{ value|date(df) }} -{% endmacro %} -{% macro table(post) %} -
- {% match post.created_at %} - {% when Some(created_at) %} -
written
-
{% call span_date(created_at) %}
- {% when None %} - {% endmatch %} - {% match post.modified_at %} - {% when Some(modified_at) %} -
last modified
-
{% call span_date(modified_at) %}
- {% when None %} - {% endmatch %} - {% if !post.tags.is_empty() %} -
tags
-
- {% for tag in post.tags %} - {{ tag }} - {% endfor %} -
- {% endif %} -
-{% endmacro %} diff --git a/templates/post.hbs b/templates/post.hbs new file mode 100644 index 0000000..81788de --- /dev/null +++ b/templates/post.hbs @@ -0,0 +1,71 @@ + + + + + + + + + + + + + {{#if (ne meta.icon null)}} + + + + {{#if (ne meta.icon_alt null)}} + + + {{/if}}{{/if}} + {{#if (ne color null)}} + + {{/if}} + {{meta.title}} + + + + + {{#if js}} + + + {{/if}} + + +
+

+ {{meta.title}} + +

+

{{meta.description}}

+
+ {{>post_table meta df=@root.df}} + link
+ back to home +
+
+ {{{rendered}}} +
+
+ {{#each rendered_in}} + {{#if (eq @key "ParsedAndRendered")}} + parsed + and + rendered + in + {{duration this.[0]}} + + {{else if (eq @key "Cached")}} + retrieved from cache in + {{duration this}} + {{/if}} + {{/each}} + {{#if markdown_access}} + - + view raw + {{/if}} +
+ + diff --git a/templates/post.html b/templates/post.html deleted file mode 100644 index 38fed50..0000000 --- a/templates/post.html +++ /dev/null @@ -1,71 +0,0 @@ -{%- import "macros.askama" as macros -%} - - - - - - - - - - - - - - {% match meta.icon %} {% when Some with (url) %} - - - - {% match meta.icon_alt %} {% when Some with (alt) %} - - - {% when None %} {% endmatch %} - - {% when None %} {% endmatch %} - - {% match color %} {% when Some with (color) %} - - {% when None %} {% endmatch %} - {{ meta.title }} - - - - - {% if js %} - - - {% endif %} - - -
-

- {{ meta.title }} - -

-

{{ meta.description }}

-
- - {% call macros::table(meta) %} - link
- back to home -
-
- {{ rendered|escape("none") }} -
- - - -