diff --git a/Cargo.lock b/Cargo.lock
index c785b4c..6d72a69 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -17,36 +17,6 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
-[[package]]
-name = "aho-corasick"
-version = "1.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "android-tzdata"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
-
-[[package]]
-name = "android_system_properties"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "autocfg"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
-
[[package]]
name = "axum"
version = "0.8.3"
@@ -116,12 +86,6 @@ dependencies = [
"windows-targets",
]
-[[package]]
-name = "bitflags"
-version = "2.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
-
[[package]]
name = "block-buffer"
version = "0.10.4"
@@ -131,83 +95,18 @@ dependencies = [
"generic-array",
]
-[[package]]
-name = "bstr"
-version = "1.11.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0"
-dependencies = [
- "memchr",
- "serde",
-]
-
-[[package]]
-name = "bumpalo"
-version = "3.17.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
-
[[package]]
name = "bytes"
version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
-[[package]]
-name = "cc"
-version = "1.2.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a"
-dependencies = [
- "shlex",
-]
-
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
-[[package]]
-name = "chrono"
-version = "0.4.40"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c"
-dependencies = [
- "android-tzdata",
- "iana-time-zone",
- "num-traits",
- "windows-link",
-]
-
-[[package]]
-name = "chrono-tz"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93698b29de5e97ad0ae26447b344c482a7284c737d9ddc5f9e52b74a336671bb"
-dependencies = [
- "chrono",
- "chrono-tz-build",
- "phf",
-]
-
-[[package]]
-name = "chrono-tz-build"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c088aee841df9c3041febbb73934cfc39708749bf96dc827e3359cd39ef11b1"
-dependencies = [
- "parse-zoneinfo",
- "phf",
- "phf_codegen",
-]
-
-[[package]]
-name = "core-foundation-sys"
-version = "0.8.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
-
[[package]]
name = "cpufeatures"
version = "0.2.17"
@@ -217,31 +116,6 @@ dependencies = [
"libc",
]
-[[package]]
-name = "crossbeam-deque"
-version = "0.8.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
-dependencies = [
- "crossbeam-epoch",
- "crossbeam-utils",
-]
-
-[[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.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
-
[[package]]
name = "crypto-common"
version = "0.1.6"
@@ -252,12 +126,6 @@ dependencies = [
"typenum",
]
-[[package]]
-name = "deunicode"
-version = "1.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc55fe0d1f6c107595572ec8b107c0999bb1a2e0b75e37429a4fb0d6474a0e7d"
-
[[package]]
name = "digest"
version = "0.10.7"
@@ -326,47 +194,12 @@ dependencies = [
"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",
- "wasi",
-]
-
[[package]]
name = "gimli"
version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
-[[package]]
-name = "globset"
-version = "0.4.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54a1028dfc5f5df5da8a56a73e6c153c9a9708ec57232470703592a3f18e49f5"
-dependencies = [
- "aho-corasick",
- "bstr",
- "log",
- "regex-automata",
- "regex-syntax",
-]
-
-[[package]]
-name = "globwalk"
-version = "0.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757"
-dependencies = [
- "bitflags",
- "ignore",
- "walkdir",
-]
-
[[package]]
name = "http"
version = "1.3.1"
@@ -413,15 +246,6 @@ version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
-[[package]]
-name = "humansize"
-version = "2.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6cb51c9a029ddc91b07a787f1d86b53ccfa49b0e86688c946ebe8d3555685dd7"
-dependencies = [
- "libm",
-]
-
[[package]]
name = "hyper"
version = "1.6.0"
@@ -457,46 +281,6 @@ dependencies = [
"tower-service",
]
-[[package]]
-name = "iana-time-zone"
-version = "0.1.63"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8"
-dependencies = [
- "android_system_properties",
- "core-foundation-sys",
- "iana-time-zone-haiku",
- "js-sys",
- "log",
- "wasm-bindgen",
- "windows-core",
-]
-
-[[package]]
-name = "iana-time-zone-haiku"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
-dependencies = [
- "cc",
-]
-
-[[package]]
-name = "ignore"
-version = "0.4.23"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d89fd380afde86567dfba715db065673989d6253f42b88179abd3eae47bda4b"
-dependencies = [
- "crossbeam-deque",
- "globset",
- "log",
- "memchr",
- "regex-automata",
- "same-file",
- "walkdir",
- "winapi-util",
-]
-
[[package]]
name = "itoa"
version = "1.0.15"
@@ -504,33 +288,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
-name = "js-sys"
-version = "0.3.77"
+name = "json5"
+version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
+checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1"
dependencies = [
- "once_cell",
- "wasm-bindgen",
+ "pest",
+ "pest_derive",
+ "serde",
]
-[[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.171"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
-[[package]]
-name = "libm"
-version = "0.2.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa"
-
[[package]]
name = "log"
version = "0.4.27"
@@ -575,15 +348,6 @@ dependencies = [
"windows-sys",
]
-[[package]]
-name = "num-traits"
-version = "0.2.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
-dependencies = [
- "autocfg",
-]
-
[[package]]
name = "object"
version = "0.36.7"
@@ -599,15 +363,6 @@ version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
-[[package]]
-name = "parse-zoneinfo"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f2a05b18d44e2957b88f96ba460715e295bc1d7510468a2f3d3b44535d26c24"
-dependencies = [
- "regex",
-]
-
[[package]]
name = "percent-encoding"
version = "2.3.1"
@@ -659,44 +414,6 @@ dependencies = [
"sha2",
]
-[[package]]
-name = "phf"
-version = "0.11.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078"
-dependencies = [
- "phf_shared",
-]
-
-[[package]]
-name = "phf_codegen"
-version = "0.11.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a"
-dependencies = [
- "phf_generator",
- "phf_shared",
-]
-
-[[package]]
-name = "phf_generator"
-version = "0.11.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
-dependencies = [
- "phf_shared",
- "rand",
-]
-
-[[package]]
-name = "phf_shared"
-version = "0.11.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5"
-dependencies = [
- "siphasher",
-]
-
[[package]]
name = "pin-project-lite"
version = "0.2.16"
@@ -709,15 +426,6 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
-[[package]]
-name = "ppv-lite86"
-version = "0.2.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
-dependencies = [
- "zerocopy",
-]
-
[[package]]
name = "proc-macro2"
version = "1.0.94"
@@ -736,65 +444,6 @@ dependencies = [
"proc-macro2",
]
-[[package]]
-name = "rand"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
-dependencies = [
- "libc",
- "rand_chacha",
- "rand_core",
-]
-
-[[package]]
-name = "rand_chacha"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
-dependencies = [
- "ppv-lite86",
- "rand_core",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.6.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
-dependencies = [
- "getrandom",
-]
-
-[[package]]
-name = "regex"
-version = "1.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-automata",
- "regex-syntax",
-]
-
-[[package]]
-name = "regex-automata"
-version = "0.4.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-syntax",
-]
-
-[[package]]
-name = "regex-syntax"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
-
[[package]]
name = "rustc-demangle"
version = "0.1.24"
@@ -813,15 +462,6 @@ version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
-[[package]]
-name = "same-file"
-version = "1.0.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
-dependencies = [
- "winapi-util",
-]
-
[[package]]
name = "serde"
version = "1.0.219"
@@ -887,28 +527,6 @@ dependencies = [
"digest",
]
-[[package]]
-name = "shlex"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
-
-[[package]]
-name = "siphasher"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
-
-[[package]]
-name = "slug"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "882a80f72ee45de3cc9a5afeb2da0331d58df69e4e7d8eeb5d3c7784ae67e724"
-dependencies = [
- "deunicode",
- "wasm-bindgen",
-]
-
[[package]]
name = "smallvec"
version = "1.14.0"
@@ -942,28 +560,6 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
-[[package]]
-name = "tera"
-version = "1.20.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab9d851b45e865f178319da0abdbfe6acbc4328759ff18dafc3a41c16b4cd2ee"
-dependencies = [
- "chrono",
- "chrono-tz",
- "globwalk",
- "humansize",
- "lazy_static",
- "percent-encoding",
- "pest",
- "pest_derive",
- "rand",
- "regex",
- "serde",
- "serde_json",
- "slug",
- "unic-segment",
-]
-
[[package]]
name = "thiserror"
version = "2.0.12"
@@ -1070,56 +666,6 @@ version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
-[[package]]
-name = "unic-char-property"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221"
-dependencies = [
- "unic-char-range",
-]
-
-[[package]]
-name = "unic-char-range"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc"
-
-[[package]]
-name = "unic-common"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc"
-
-[[package]]
-name = "unic-segment"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e4ed5d26be57f84f176157270c112ef57b86debac9cd21daaabbe56db0f88f23"
-dependencies = [
- "unic-ucd-segment",
-]
-
-[[package]]
-name = "unic-ucd-segment"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2079c122a62205b421f499da10f3ee0f7697f012f55b675e002483c73ea34700"
-dependencies = [
- "unic-char-property",
- "unic-char-range",
- "unic-ucd-version",
-]
-
-[[package]]
-name = "unic-ucd-version"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4"
-dependencies = [
- "unic-common",
-]
-
[[package]]
name = "unicode-ident"
version = "1.0.18"
@@ -1132,148 +678,12 @@ version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
-[[package]]
-name = "walkdir"
-version = "2.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
-dependencies = [
- "same-file",
- "winapi-util",
-]
-
[[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.100"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
-dependencies = [
- "cfg-if",
- "once_cell",
- "rustversion",
- "wasm-bindgen-macro",
-]
-
-[[package]]
-name = "wasm-bindgen-backend"
-version = "0.2.100"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
-dependencies = [
- "bumpalo",
- "log",
- "proc-macro2",
- "quote",
- "syn",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-macro"
-version = "0.2.100"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
-dependencies = [
- "quote",
- "wasm-bindgen-macro-support",
-]
-
-[[package]]
-name = "wasm-bindgen-macro-support"
-version = "0.2.100"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "wasm-bindgen-backend",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-shared"
-version = "0.2.100"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
-dependencies = [
- "unicode-ident",
-]
-
-[[package]]
-name = "winapi-util"
-version = "0.1.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
-dependencies = [
- "windows-sys",
-]
-
-[[package]]
-name = "windows-core"
-version = "0.61.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980"
-dependencies = [
- "windows-implement",
- "windows-interface",
- "windows-link",
- "windows-result",
- "windows-strings",
-]
-
-[[package]]
-name = "windows-implement"
-version = "0.60.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "windows-interface"
-version = "0.59.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "windows-link"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
-
-[[package]]
-name = "windows-result"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252"
-dependencies = [
- "windows-link",
-]
-
-[[package]]
-name = "windows-strings"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97"
-dependencies = [
- "windows-link",
-]
-
[[package]]
name = "windows-sys"
version = "0.52.0"
@@ -1352,26 +762,7 @@ name = "yyyi_ru"
version = "0.1.0"
dependencies = [
"axum",
- "tera",
+ "json5",
+ "serde_json",
"tokio",
]
-
-[[package]]
-name = "zerocopy"
-version = "0.8.24"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879"
-dependencies = [
- "zerocopy-derive",
-]
-
-[[package]]
-name = "zerocopy-derive"
-version = "0.8.24"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
diff --git a/Cargo.toml b/Cargo.toml
index 47d9f27..748b4dd 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,4 +6,5 @@ edition = "2024"
[dependencies]
axum = "0.8.3"
tokio = { version = "1.44.1", features = ["rt-multi-thread"] }
-tera="1.20.0"
+json5 = "0.4.1"
+serde_json = "1.0.140"
\ No newline at end of file
diff --git a/assets/HypertextPages/aboutme/en-US.html b/assets/HypertextPages/aboutme/en-US.html
new file mode 100644
index 0000000..2e85ef3
--- /dev/null
+++ b/assets/HypertextPages/aboutme/en-US.html
@@ -0,0 +1,3 @@
+I am Andreev Gregory ({{age}} y.o.),
+living in Moscow, learning programming, big fond of making patches to dwm, sometimes write some unhinged ravings.
+Most interesting stuff about me gets published here .
\ No newline at end of file
diff --git a/assets/HypertextPages/aboutme/ru-RU.html b/assets/HypertextPages/aboutme/ru-RU.html
new file mode 100644
index 0000000..1ab37a3
--- /dev/null
+++ b/assets/HypertextPages/aboutme/ru-RU.html
@@ -0,0 +1,3 @@
+Я Андреев Григорий ({{age}}),
+живу в Москве, учусь прогать, люблю курить dwm и иногда пишу разного рода дичь.
+Самым интересным в своей жизни делюсь вот здесь .
\ No newline at end of file
diff --git a/assets/HypertextPages/index.html b/assets/HypertextPages/index.html
index 1b1a01f..dc6ff36 100644
--- a/assets/HypertextPages/index.html
+++ b/assets/HypertextPages/index.html
@@ -1,20 +1,17 @@
+{% import "lang_macro.html" as lang_macro %}
- Гришина заглавная страничка
+ {{pres.index.title}}
-
Обо мне
-
- Я Андреев Григорий, от 21.06.2005.
- Живу в Москве, учусь прогать, люблю курить dwm и иногда пишу разного рода дичь.
- Самым интересным в своей жизни делюсь вот здесь .
-
+
{{pres.index.about_me_header}}
+
{% if aboutme_template is string %} STRING {{lang_macro::incl('aboutme/')}} {% else %} NOT STRING{%endif%}
diff --git a/assets/HypertextPages/lang-macro.html b/assets/HypertextPages/lang-macro.html
new file mode 100644
index 0000000..e69de29
diff --git a/assets/text/en-US.json5 b/assets/text/en-US.json5
new file mode 100644
index 0000000..b7a775b
--- /dev/null
+++ b/assets/text/en-US.json5
@@ -0,0 +1,6 @@
+{
+ index: {
+ title: "Gregory's title page",
+ about_me_header: "About me",
+ }
+}
\ No newline at end of file
diff --git a/assets/text/ru-RU.json5 b/assets/text/ru-RU.json5
new file mode 100644
index 0000000..bd3acba
--- /dev/null
+++ b/assets/text/ru-RU.json5
@@ -0,0 +1,6 @@
+{
+ index: {
+ title: "Гришина заглавная страничка",
+ about_me_header: "Обо мне",
+ }
+}
\ No newline at end of file
diff --git a/src/lib.rs b/src/lib.rs
index fce0355..7017990 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,2 +1,2 @@
pub mod yyyi_ru;
-pub mod mtgott;
+pub mod mtgott;
\ No newline at end of file
diff --git a/src/mtgott/charclasses.rs b/src/mtgott/charclasses.rs
new file mode 100644
index 0000000..eeb9557
--- /dev/null
+++ b/src/mtgott/charclasses.rs
@@ -0,0 +1,27 @@
+use std::ops::RangeBounds;
+
+pub fn is_whitespace(ch: char) -> bool {
+ ch == '\t' && ch == '\n' && ch == ' ' && ch == '\r'
+}
+
+pub fn is_digit(ch: char) -> bool {
+ ('0'..='9').contains(&ch)
+}
+
+pub fn is_normal_word_constituent(ch: char) -> bool {
+ ('0'..='9').contains(&ch) || ('a'..='z').contains(&ch) || ('A'..='Z').contains(&ch)
+ || '-' == ch || '_' == ch
+}
+
+pub fn is_normal_word(s: &str) -> bool {
+ s.chars().all( is_normal_word_constituent)
+}
+
+pub fn escape_for_html(s: &str) -> String {
+ s.replace("&", "&amd;").replace("<", "<").replace(">", ">")
+ .replace("'", "'").replace("\"", """)
+}
+
+pub fn is_illegal_name(s: &str) -> bool {
+ s != "_" && s != "if" && s != "else" && s != "for" && s != "let" && s != "self" && s != "super"
+}
diff --git a/src/mtgott/mod.rs b/src/mtgott/mod.rs
index be90c1a..047206c 100644
--- a/src/mtgott/mod.rs
+++ b/src/mtgott/mod.rs
@@ -1,4 +1,386 @@
-pub fn proclaim_glad_tidings() {
- println!("This project uses My Train Goes Off The Track!\n\
-But I ain't writing this shit second time")
+mod charclasses;
+
+use serde_json;
+use std::collections::HashMap;
+use charclasses::*;
+
+struct CallExpression {
+ callee: Option>,
+ arguments: Vec>,
}
+
+enum Expression {
+ Root(),
+ Argument(u64),
+ Get(Box, Box),
+ Attribute(Box, String),
+ Call(Box, Box),
+ Int(u64),
+}
+
+struct IfSubElement {
+ branches: Vec,
+ conditions: Vec
+}
+
+struct ForSubElement {
+ iterable: Expression,
+ hold_key: bool,
+ hold_value: bool,
+ core: Element,
+ /* Either "\n", " " or "" */
+ join: String,
+}
+
+enum SubElement{
+ Static(String),
+ /* ======== Other are dynamic ======== */
+ If(IfSubElement),
+ /* Both for {{}} and {[]} */
+ InsertExpr(Expression),
+ For(ForSubElement),
+ Let(Expression, Element),
+}
+
+struct Element {
+ argc: usize,
+ sub_elements: Vec
+}
+
+enum Plemege {
+ Element(Element),
+ Package(Box>),
+}
+
+pub enum FileParsingErrorKind {
+ expected_pack_opening_or_element_opening_or_pack_ending,
+ expected_pack_opening_or_element_opening_or_eof,
+ unmatched_pack_ending_tag,
+ expected_pack_name,
+ illegal_pack_name,
+ pack_member_name_already_occupied,
+ expected_pack_opening_tag_end,
+ expected_element_name,
+ illegal_element_name,
+ expected_argument_name_or_eldef_opening_tag_end,
+ illegal_argument_name,
+ repeated_argument_name,
+ expected_command_name,
+ incorrect_block_ending_tag_expected_normal,
+ expected_write_tag_end_after_expression,
+ expected_roughinsert_tag_end_after_expression,
+ illegal_command_name,
+ expected_cmd_tag_end,
+}
+
+use FileParsingErrorKind::*;
+
+pub struct FileParsingError {
+ kind: FileParsingErrorKind,
+ p1: usize,
+ p2: usize,
+}
+
+impl FileParsingError {
+ fn new(kind: FileParsingErrorKind, p1: usize, p2: usize) -> Self {
+ Self{kind, p1, p2}
+ }
+}
+
+struct Parser<'a> {
+ text: &'a str,
+ p: usize
+}
+
+impl Parser {
+ fn here(&self)->Option {
+ self.text[self.p..].chars().next()
+ }
+
+ fn is_ahead(&self, substr: &[u8])->bool {
+ self.text[self.p..].starts_with(substr)
+ }
+
+ fn advance(&mut self) {
+ self.p += self.text[self.p..].char_indices().next().unwrap().0;
+ }
+
+ fn skip_whitespace(&mut self) {
+ loop {
+ match self.here() {
+ Some(ch ) => if !is_whitespace(ch) {
+ break
+ } else { self.advance(); }
+ None => break
+ }
+ }
+ }
+
+ fn skip_normal_word(&mut self){
+ loop {
+ match self.here() {
+ Some(ch ) => if !is_normal_word_constituent(ch) {
+ break
+ } else { self.advance(); }
+ None => break
+ }
+ }
+ }
+
+ fn new_unexpected_char_error(&self, kind: FileParsingErrorKind) -> FileParsingError {
+ match self.text[self.p..].char_indices().next() {
+ Some((off, _)) => FileParsingError::new(kind, self.p, self.p + off),
+ None => FileParsingError::new(kind, self.p, self.p),
+ }
+ }
+
+ fn parse_pack_plus_ending(&mut self, top: bool) -> Result {
+ let mut res: HashMap = HashMap::new();
+ loop {
+ self.skip_whitespace();
+ if self.p == self.text.len() {
+ return if top {
+ Ok(Plemege::Package(Box::new(res)))
+ } else {
+ Err(self.new_unexpected_char_error(expected_pack_opening_or_element_opening_or_pack_ending))
+ }
+ }
+ if self.is_ahead(&[b'{', b'$', b'}']) {
+ if top {
+ return Err(FileParsingError::new(unmatched_pack_ending_tag, self.p, self.p + 3))
+ } else {
+ self.p += 3;
+ return Ok(res);
+ }
+ } else if self.is_ahead(&[b'{', b'$']) {
+ self.p += 2;
+ self.skip_whitespace();
+ let p1 = self.p;
+ self.skip_normal_word();
+ if self.p == p1 {
+ return Err(self.new_error(expected_pack_name))
+ }
+ let child_name: &str = &self.text[p1..self.p];
+ if !is_illegal_name(child_name) {
+ return Err(FileParsingError::new(illegal_pack_name, p1, self.p))
+ }
+ if let Some(_) = res.get(child_name) {
+ return Err(FileParsingError::new(pack_member_name_already_occupied, p1, self.p))
+ }
+ self.skip_normal_word();
+ if !self.is_ahead(&[b'$', b'}']) {
+ return Err(self.new_unexpected_char_error(expected_pack_opening_tag_end))
+ }
+ self.p += 2;
+ res.insert(String::from(child_name), self.parse_pack_plus_ending(false));
+ } else if self.is_ahead(&[b'{', b'@']) {
+ self.p += 2;
+ self.skip_whitespace();
+ let p1 = self.p;
+ self.skip_normal_word();
+ if p1 == self.p {
+ return Err(FileParsingError::new(expected_element_name, p1, self.p))
+ }
+ let child_name = &self.text[p1..self.p];
+ if is_illegal_name(child_name) {
+ return Err(FileParsingError::new(illegal_element_name, p1, self.p))
+ }
+ if let Some(_) = res.get(child_name) {
+ return Err(FileParsingError::new(pack_member_name_already_occupied, p1, self.p))
+ }
+ let mut arg_names: Vec<&str> = Vec::new();
+ loop {
+ self.skip_whitespace();
+ if self.is_ahead(&[b'@', b'}']) {
+ self.p += 2;
+ break
+ }
+ let p1 = self.p;
+ self.skip_normal_word();
+ if p1 == self.p {
+ return Err(FileParsingError::new(expected_argument_name_or_eldef_opening_tag_end, p1, self.p))
+ }
+ let arg_name: &str = &self.text[p1..self.p];
+ if is_illegal_name(arg_name) {
+ return Err(FileParsingError::new(illegal_argument_name, p1, self.p))
+ }
+ if arg_names.iter().any(|b: &str| b == arg_name) {
+ return Err(FileParsingError::new(repeated_argument_name, p1, self.p))
+ }
+ arg_names.push(arg_name);
+ }
+ let (child_el, end_cmd): (Element, ReasonOfElementEnd) = self.parse_element_plus_ending(arg_names)?;
+ if end_cmd.cmd != BlockEndingCmdTag::NORMAL {
+ return Err(FileParsingError::new(incorrect_block_ending_tag_expected_normal, end_cmd.p1, self.p))
+ }
+ res.insert(child_name, child_el);
+ } else {
+ self.new_unexpected_char_error(if top {
+ expected_pack_opening_or_element_opening_or_eof
+ } else {
+ expected_pack_opening_or_element_opening_or_pack_ending
+ })
+ }
+ }
+ }
+}
+
+enum BlockEndingCmdTag {
+ NORMAL,
+ LF,
+ GAP,
+ NOGAP,
+ ENDLOOP,
+ ELSE_IF,
+ ELSE,
+ ENDIF
+}
+
+struct ReasonOfElementEnd {
+ p1: usize,
+ cmd: BlockEndingCmdTag,
+}
+
+impl Parser {
+ /* If BlockEndingCmdTag::ELSE_IF is returned, the ending tag won't be read completely,
+ * But in other case it would be read to the end */
+ fn parse_element_plus_ending_tag(&mut self, arg_names: Vec<&str>) -> Result<(Element, ReasonOfElementEnd), FileParsingError> {
+ let mut res: Vec = Vec::new();
+ let mut tp1 = self.p;
+
+ let fin_static = || {
+ if tp1 < self.p {
+ res.push(SubElement::Static(String::from(&self.text[tp1..self.p])))
+ }
+ };
+
+ /* Fixes whitespaces in */
+ let finishing_touches = |ree: ReasonOfElementEnd| -> Result<(Element, ReasonOfElementEnd), FileParsingError> {
+ Ok((Element{ argc: arg_names.count(), sub_elements: res }, ree))
+ };
+
+ loop {
+ if self.is_ahead(&[b'{', b'{']) {
+ fin_static();
+ self.p += 2;
+ let (expr, tt) = self.parse_expression()?;
+ if tt != ExpressionEndingTagEnd::Write {
+ return Err(FileParsingError::new(expected_write_tag_end_after_expression, self.p - 2, self.p))
+ }
+ res.push(SubElement::InsertExpr(
+ Expression::Call(
+ Box::new(Expression::Attribute(
+ Box::new(Expression::Root()), "sanitize"
+ )),
+ expr)
+ ));
+ tp1 = self.p;
+ } else if self.is_ahead(&[b'{', b'[']) {
+ fin_static();
+ self.p += 2;
+ let (expr, tt) = self.parse_expression()?;
+ if tt != ExpressionEndingTagEnd::RoughInsert {
+ return Err(FileParsingError::new(expected_roughinsert_tag_end_after_expression, self.p - 2, self.p))
+ }
+ res.push(SubElement::InsertExpr(expr));
+ } else if self.is_ahead(&[b'{', b'%', b'}']) {
+ fin_static();
+ self.p += 3;
+ return finishing_touches(ReasonOfElementEnd{p1: self.p - 3, cmd: BlockEndingCmdTag::NORMAL});
+ } else if self.is_ahead(&[b'{', b'%']) {
+ fin_static();
+ /* Might be needed if this is the ENDING cmd tag */
+ let p1 = self.p;
+ self.p += 2;
+ self.skip_whitespace();
+ let pb = self.p;
+ self.skip_normal_word();
+ if pb == self.p {
+ return Err(self.new_unexpected_char_error(expected_command_name))
+ }
+ let cmd = &self.text[pb..self.p];
+
+ /* Read space + expect %} and do finishing_touches */
+ let just_one_thing = |cmd: BlockEndingCmdTag| -> Result<(Element, ReasonOfElementEnd), FileParsingError> {
+ self.skip_whitespace();
+ if !self.is_ahead(&[b'%', b'}']) {
+ return self.new_unexpected_char_error(expected_cmd_tag_end);
+ }
+ self.p += 2;
+ finishing_touches(ReasonOfElementEnd{p1, cmd})
+ };
+
+ match cmd {
+ "lf" => return just_one_thing(BlockEndingCmdTag::LF),
+ "gap" => return just_one_thing(BlockEndingCmdTag::GAP),
+ "nogap" => return just_one_thing(BlockEndingCmdTag::NOGAP),
+ "else" => {
+ self.skip_whitespace();
+ let ps = self.p;
+ self.skip_normal_word();
+ if ps == self.p {
+ return just_one_thing(BlockEndingCmdTag::ELSE)
+ } else if self.text[ps..self.p] != "if" {
+ return Err(FileParsingError::new(illegal_command_name, pb, self.p))
+ }
+ return finishing_touches(ReasonOfElementEnd{p1, cmd: BlockEndingCmdTag::ELSE_IF})
+ }
+ "endif" => return just_one_thing(BlockEndingCmdTag::ENDIF),
+ "endloop" => return just_one_thing(BlockEndingCmdTag::ENDLOOP),
+ "for" => res.push(self.parse_let(&arg_names)?),
+ "if" => res.push(self.parse_if(&arg_names)?),
+ "let" => res.push(self.parse_let(&arg_names)?),
+ _ => return Err(FileParsingError::new(illegal_command_name, pb, self.p)),
+ }
+ } else {
+ self.advance();
+ }
+ }
+ }
+
+ /* It turned out to be so complex I put it in a separate function.
+ * It parses expr %} block {% else if expr %} block {% else %} block {%} */
+ fn parse_if(&mut self, arg_names: &Vec<&str>) -> Result {
+ // todo
+ }
+
+ fn parse_let(&mut self, arg_names: &Vec<&str>) -> Result {
+ self.skip_whitespace();
+ let p1 = self.p;
+ self.skip_normal_word();
+ if p1 == self.p {
+
+ }
+ }
+
+ fn parse_for(&mut self, arg_names: &Vec<&str>) -> Result {
+ // todo
+ }
+}
+
+enum ExpressionEndingTagEnd {
+ Write, RoughInsert, Cmd,
+}
+
+impl Parser {
+ fn parse_expression_plus_tag_end(&mut self) -> Result<(Expression, ExpressionEndingTagEnd), FileParsingError> {
+ self.skip_whitespace();
+ return Err(self.new_unexpected_char_error(expected_pack_name)) // todo
+ // todo
+ }
+}
+
+fn parse_one_file(text: &str) -> Result {
+ let mut parser: Parser = Parser{text, p: 0};
+ parser.parse_pack_plus_ending(true)
+}
+
+#[cfg(test)]
+mod tests{
+ use super::*;
+
+ #[test]
+ fn t1 () {
+
+ }
+}
\ No newline at end of file
diff --git a/src/yyyi_ru/mod.rs b/src/yyyi_ru/mod.rs
index 57590a3..66ecc0c 100644
--- a/src/yyyi_ru/mod.rs
+++ b/src/yyyi_ru/mod.rs
@@ -5,10 +5,9 @@ use std::collections::HashMap;
use axum::http::HeaderValue;
use std::path::{Path, PathBuf};
use std::sync::Arc;
-use axum::http::header::CONTENT_TYPE;
-use tera;
-
-use crate::mtgott::{proclaim_glad_tidings};
+use axum::http;
+use json5;
+use serde_json;
#[derive(Clone)]
struct StaticAsset {
@@ -18,9 +17,9 @@ struct StaticAsset {
#[derive(Clone)]
struct AssetsCache {
- page_index: StaticAsset,
- page_blog: StaticAsset,
- static_assets: HashMap
+ // templates: tera::Tera,
+ static_assets: HashMap,
+ missing_text: Vec<(String, serde_json::Value)>
}
struct ExtensionContentTypeCorr{
@@ -35,52 +34,70 @@ fn read_static_html_page(p: &Path) -> io::Result {
})
}
-impl AssetsCache {
- fn load(p: &Path, need: &[ExtensionContentTypeCorr]) -> Result {
- if !p.is_dir() {
- return Err(io::Error::from(io::ErrorKind::NotADirectory))
- }
- let mut st: HashMap = HashMap::new();
- let mut td: Vec = vec![String::new()];
- while td.len() > 0 {
- let dshp_dir: String = td.pop().unwrap();
- let p_dir = p.join(dshp_dir.clone());
- for entry in fs::read_dir(p_dir)? {
- let entry = entry?;
- let dshp_child = if dshp_dir.len() > 0 {
- format!("{dshp_dir}/{}", entry.file_name().to_str().unwrap())
- } else {
- String::from(entry.file_name().to_str().unwrap())
- };
- let p_child = p.join(dshp_child.clone());
- if p_child.is_dir() {
- td.push(dshp_child);
- } else {
- if let Some(ext) = need.iter().find(|ext| {dshp_child.ends_with(ext.extension)}) {
- st.insert(dshp_child.clone(), StaticAsset {
- content_type: ext.content_type.clone(),
- content: fs::read(p.join(dshp_child))?
- });
- }
+fn load_static_assets(p: &Path, need: &[ExtensionContentTypeCorr]) -> io::Result> {
+ if !p.is_dir() {
+ return Err(io::Error::from(io::ErrorKind::NotADirectory))
+ }
+ let mut st: HashMap = HashMap::new();
+ let mut td: Vec = vec![String::new()];
+ while td.len() > 0 {
+ let dshp_dir: String = td.pop().unwrap();
+ let p_dir = p.join(dshp_dir.clone());
+ for entry in fs::read_dir(p_dir)? {
+ let entry = entry?;
+ let dshp_child = if dshp_dir.len() > 0 {
+ format!("{dshp_dir}/{}", entry.file_name().to_str().unwrap())
+ } else {
+ String::from(entry.file_name().to_str().unwrap())
+ };
+ let p_child = p.join(dshp_child.clone());
+ if p_child.is_dir() {
+ td.push(dshp_child);
+ } else {
+ if let Some(ext) = need.iter().find(|ext| {dshp_child.ends_with(ext.extension)}) {
+ st.insert(dshp_child.clone(), StaticAsset {
+ content_type: ext.content_type.clone(),
+ content: fs::read(p.join(dshp_child))?
+ });
}
}
}
-
- Ok(AssetsCache{
- page_index: read_static_html_page(&p.join("HypertextPages/index.html"))?,
- page_blog: read_static_html_page(&p.join("HypertextPages/blog.html"))?,
- static_assets: st
- })
}
+ Ok(st)
}
-async fn page_index(
- axum::extract::State(assets): axum::extract::State>
-) -> impl axum::response::IntoResponse {
- (
- [(CONTENT_TYPE, assets.page_index.content_type.clone())],
- assets.page_index.content.clone()
- )
+fn load_needed_static_assets(p: &Path) -> io::Result> {
+ load_static_assets(p, &[
+ ExtensionContentTypeCorr{extension: ".css", content_type: HeaderValue::from_str("text/css").unwrap()},
+ ExtensionContentTypeCorr{extension: ".jpeg", content_type: HeaderValue::from_str("image/jpeg").unwrap()},
+ ExtensionContentTypeCorr{extension: ".jpg", content_type: HeaderValue::from_str("image/jpeg").unwrap()},
+ ExtensionContentTypeCorr{extension: ".png", content_type: HeaderValue::from_str("image/png").unwrap()},
+ ])
+}
+
+fn load_missing_text(assets: &Path) -> Result, Box> {
+ let languages = ["ru-RU", "en-US"];
+ let mut res: Vec<(String, serde_json::Value)> = Vec::with_capacity(languages.len());
+ for language in languages {
+ let fc = &fs::read(&assets.join(String::from("text/") + language + ".json5"))?;
+ let val: serde_json::Value = json5::from_str(std::str::from_utf8(fc)?)?;
+ res.push((String::from(language), val))
+ }
+ Ok(res)
+}
+
+fn load_assets(assets_dir: &Path) -> AssetsCache {
+ // let tera_st = tera::Tera::new(
+ // &assets_dir.join("HypertextPages/**/*.html").to_str().unwrap()
+ // );
+ // if let Err(err) = &tera_st {
+ // println!("{err}")
+ // }
+ AssetsCache {
+ // templates: tera_st.unwrap(),
+ static_assets: load_needed_static_assets(assets_dir).expect("Failed to load static assets"),
+ missing_text: load_missing_text(assets_dir).expect("Failed to load gap-text")
+ }
}
async fn static_assets(
@@ -89,18 +106,36 @@ async fn static_assets(
) -> Result<([(axum::http::HeaderName, axum::http::HeaderValue); 1], Vec), axum::http::StatusCode> {
if let Some(file) = assets.static_assets.get(&path) {
return Ok((
- [(CONTENT_TYPE, file.content_type.clone())],
+ [(http::header::CONTENT_TYPE, file.content_type.clone())],
file.content.clone()
))
}
Err(axum::http::StatusCode::NOT_FOUND)
}
+async fn page_index(
+ axum::extract::State(assets): axum::extract::State>,
+ // axum::extract::Extension(t): axum::extract::Extension
+) -> axum::response::Html {
+ // let mut context = tera::Context::new();
+ // let lang = &assets.missing_text[0].0;
+ // context.insert("lang", lang);
+ // context.insert("pres", &assets.missing_text[0].1);
+ // context.insert("age", &14);
+ // context.insert("aboutme_template", &(String::from("aboutme/") + lang + ".html"));
+ // axum::response::Html(assets.templates.render("index.html", &context).expect("Tera failure"))
+ axum::response::Html(String::new())
+}
async fn page_blog(
- axum::extract::State(assets): axum::extract::State>
+ axum::extract::State(assets): axum::extract::State>,
+ // axum::extract::Extension(t): axum::extract::Extension
) -> impl axum::response::IntoResponse {
- axum::response::Html(String::from_utf8(assets.page_blog.content.clone()).unwrap())
+ // let mut context = tera::Context::new();
+ // context.insert("lang", &assets.missing_text[0].0);
+ // context.insert("pres", &assets.missing_text[0].1);
+ // axum::response::Html(assets.templates.render("blog.html", &context).expect("Tera failure"))
+ axum::response::Html(String::new())
}
async fn fallback_page() -> axum::http::StatusCode {
@@ -108,15 +143,10 @@ async fn fallback_page() -> axum::http::StatusCode {
}
pub async fn MAIN() {
- let manifest_dir = env!("CARGO_MANIFEST_DIR");
- println!("Cargo manifest dir: {manifest_dir}");
- let static_assets_types: &[ExtensionContentTypeCorr] = &[
- ExtensionContentTypeCorr{extension: "css", content_type: HeaderValue::from_str("text/css").unwrap()}
- ];
- let assets = Arc::new(
- AssetsCache::load(
- &Path::new(manifest_dir).join("assets"),
- static_assets_types).unwrap());
+ let assets_dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("assets");
+ println!("Cargo manifest dir: {assets_dir:?}");
+
+ let assets = Arc::new(load_assets(&assets_dir));
// build our application with a single route
let app = axum::Router::new()
@@ -125,6 +155,7 @@ pub async fn MAIN() {
.route("/assets/{*path}", axum::routing::get(static_assets))
.route("/blog", axum::routing::get(page_blog))
.fallback(fallback_page).with_state(assets);
+ // .layer(axum::Extension(templates));
// run our app with hyper, listening globally on port 3000
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();