From b9d41c7fc4f1d97c424c9aa68b67715479ef4ebc Mon Sep 17 00:00:00 2001 From: Ivan Reshetnikov Date: Sat, 26 Oct 2024 19:11:54 +0500 Subject: [PATCH] Initial commit --- .dockerignore | 4 + .editorconfig | 11 + .gitignore | 1 + Cargo.lock | 1608 ++++++++++++++++++++++++++ Cargo.toml | 12 + Dockerfile | 15 + src/internal/mod.rs | 0 src/main.rs | 41 + src/web/assets/css/home.css | 36 + src/web/assets/css/layout.css | 76 ++ src/web/assets/favicons/16.png | Bin 0 -> 650 bytes src/web/assets/favicons/180.png | Bin 0 -> 2246 bytes src/web/assets/favicons/192.png | Bin 0 -> 2269 bytes src/web/assets/favicons/32.png | Bin 0 -> 858 bytes src/web/assets/favicons/shortcut.ico | Bin 0 -> 7406 bytes src/web/assets/favicons/vector.svg | 1 + src/web/assets/icons/code.svg | 1 + src/web/assets/icons/external.svg | 1 + src/web/assets/icons/mail.svg | 1 + src/web/assets/icons/mastodon.svg | 1 + src/web/assets/icons/matrix.svg | 1 + src/web/assets/icons/xmpp.svg | 1 + src/web/controllers/home.rs | 6 + src/web/controllers/mod.rs | 3 + src/web/mod.rs | 2 + src/web/templates.rs | 29 + src/web/templates/home.html | 85 ++ src/web/templates/layout.html | 60 + 28 files changed, 1996 insertions(+) create mode 100644 .dockerignore create mode 100644 .editorconfig create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 Dockerfile create mode 100644 src/internal/mod.rs create mode 100644 src/main.rs create mode 100644 src/web/assets/css/home.css create mode 100644 src/web/assets/css/layout.css create mode 100644 src/web/assets/favicons/16.png create mode 100644 src/web/assets/favicons/180.png create mode 100644 src/web/assets/favicons/192.png create mode 100644 src/web/assets/favicons/32.png create mode 100644 src/web/assets/favicons/shortcut.ico create mode 100644 src/web/assets/favicons/vector.svg create mode 100644 src/web/assets/icons/code.svg create mode 100644 src/web/assets/icons/external.svg create mode 100644 src/web/assets/icons/mail.svg create mode 100644 src/web/assets/icons/mastodon.svg create mode 100644 src/web/assets/icons/matrix.svg create mode 100644 src/web/assets/icons/xmpp.svg create mode 100644 src/web/controllers/home.rs create mode 100644 src/web/controllers/mod.rs create mode 100644 src/web/mod.rs create mode 100644 src/web/templates.rs create mode 100644 src/web/templates/home.html create mode 100644 src/web/templates/layout.html diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..bc85211 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,4 @@ +/.git +/target +/.editorconfig +/.gitignore diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..f6c6821 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +insert_final_newline = true +trim_trailing_whitespace = true +charset = utf-8 +indent_style = space +indent_size = 2 + +[*.rs] +indent_size = 4 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..61560ae --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1608 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +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 = "async-trait" +version = "0.1.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "axum" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" +dependencies = [ + "async-trait", + "axum-core", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-util", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", + "sync_wrapper 1.0.1", + "tokio", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum-core" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "sync_wrapper 1.0.1", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bstr" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" + +[[package]] +name = "cc" +version = "1.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" +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.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "windows-targets", +] + +[[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 = "comfycamp" +version = "0.1.0" +dependencies = [ + "axum", + "lazy_static", + "notify", + "tera", + "tokio", + "tower-http", +] + +[[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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +dependencies = [ + "libc", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +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.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +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 = "deunicode" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +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 = "filetime" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" +dependencies = [ + "cfg-if", + "libc", + "libredox", + "windows-sys 0.59.0", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "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.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +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", + "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.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15f1ce686646e7f1e19bf7d5533fe443a45dbfb990e00629110797578b42fb19" +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 2.6.0", + "ignore", + "walkdir", +] + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "http-range-header" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08a397c49fec283e3d6211adbe480be95aae5f304cfb923e9970e08956d5168a" + +[[package]] +name = "httparse" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "humansize" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cb51c9a029ddc91b07a787f1d86b53ccfa49b0e86688c946ebe8d3555685dd7" +dependencies = [ + "libm", +] + +[[package]] +name = "hyper" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", +] + +[[package]] +name = "hyper-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "tokio", + "tower-service", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "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 = "inotify" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdd168d97690d0b8c412d6b6c10360277f4d7ee495c5d0d5d5fe0854923255cc" +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]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "kqueue" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +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.161" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.6.0", + "libc", + "redox_syscall", +] + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi", + "libc", + "log", + "wasi", + "windows-sys 0.52.0", +] + +[[package]] +name = "notify" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c533b4c39709f9ba5005d8002048266593c1cfaf3c5f0739d5b8ab0c6c504009" +dependencies = [ + "bitflags 2.6.0", + "filetime", + "fsevent-sys", + "inotify", + "kqueue", + "libc", + "log", + "mio", + "notify-types", + "walkdir", + "windows-sys 0.52.0", +] + +[[package]] +name = "notify-types" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7393c226621f817964ffb3dc5704f9509e107a8b024b489cc2c1b217378785df" +dependencies = [ + "instant", +] + +[[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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[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", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pest" +version = "2.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d214365f632b123a47fd913301e14c946c61d1c183ee245fa76eb752e59a02dd" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb55586734301717aea2ac313f50b2eb8f60d2fc3dc01d190eefa2e625f60c4e" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pest_meta" +version = "2.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b75da2a70cf4d9cb76833c990ac9cd3923c9a8905a8929789ce347c84564d03d" +dependencies = [ + "once_cell", + "pest", + "sha2", +] + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_codegen" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" +dependencies = [ + "phf_generator", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared", + "rand", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +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 = "redox_syscall" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags 2.6.0", +] + +[[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.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustversion" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[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 = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "serde" +version = "1.0.213" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ea7893ff5e2466df8d720bb615088341b295f849602c6956047f8f80f0e9bc1" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.213" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e85ad2009c50b58e87caa8cd6dac16bdf511bbfb7af6c33df902396aa480fa5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.132" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_path_to_error" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" +dependencies = [ + "itoa", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[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.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "syn" +version = "2.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" + +[[package]] +name = "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 = "1.0.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio" +version = "1.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-macros" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper 0.1.2", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8437150ab6bbc8c5f0f519e3d5ed4aa883a83dd4cdd3d1b21f9482936046cb97" +dependencies = [ + "bitflags 2.6.0", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "http-range-header", + "httpdate", + "mime", + "mime_guess", + "percent-encoding", + "pin-project-lite", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "log", + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "ucd-trie" +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 = "unicase" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "version_check" +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.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +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", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..3768a77 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "comfycamp" +version = "0.1.0" +edition = "2021" + +[dependencies] +tokio = { version = "1.41.0", features = ["full"] } +axum = "0.7.7" +tera = "1.20.0" +lazy_static = "1.5.0" +tower-http = { version = "0.6.1", features = ["fs"] } +notify = "7.0.0" diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..088b3dc --- /dev/null +++ b/Dockerfile @@ -0,0 +1,15 @@ +FROM rust:1.82-slim-bookworm AS builder + +WORKDIR /usr/src/comfycamp +COPY . . +RUN cargo install --path . + +FROM debian:bookworm-slim + +WORKDIR /usr/src/comfycamp +RUN mkdir -p src/web +COPY src/web/assets src/web/assets +COPY src/web/templates src/web/templates + +COPY --from=builder /usr/local/cargo/bin/comfycamp /usr/local/bin/comfycamp +CMD ["comfycamp"] diff --git a/src/internal/mod.rs b/src/internal/mod.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..2831118 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,41 @@ +use axum::{routing::get, Router}; +use tower_http::services::ServeDir; +use tokio::signal; + +use crate::web::controllers; + +mod internal; +mod web; + +#[tokio::main] +async fn main() { + let app = Router::new() + .route("/", get(controllers::home)) + .nest_service("/assets", ServeDir::new("src/web/assets")); + let listener = tokio::net::TcpListener::bind("0.0.0.0:4000").await.unwrap(); + + axum::serve(listener, app) + .with_graceful_shutdown(shutdown_signal()) + .await + .unwrap(); +} + +async fn shutdown_signal() { + let ctrl_c = async { + signal::ctrl_c() + .await + .expect("failed to start CTRL+C handler"); + }; + + let terminate = async { + signal::unix::signal(signal::unix::SignalKind::terminate()) + .expect("failed to install signal handler") + .recv() + .await; + }; + + tokio::select!( + _ = ctrl_c => {}, + _ = terminate => {}, + ); +} diff --git a/src/web/assets/css/home.css b/src/web/assets/css/home.css new file mode 100644 index 0000000..a21693d --- /dev/null +++ b/src/web/assets/css/home.css @@ -0,0 +1,36 @@ +.service { + margin-top: 28px; +} + +.service .title { + display: flex; + gap: 8px; + align-items: center; + flex-wrap: wrap; + margin-bottom: 8px; +} + +.service .title h3 { + margin-right: 8px; + margin-top: 0; + margin-bottom: 0; +} + +.service .tag { + font-size: 12px; + background-color: #333; + padding: 4px 6px; + border-radius: 6px; +} + +.service .link { + color: var(--accent); + display: flex; + gap: 8px; + align-items: center; +} + +.service svg { + width: 16px; + height: 16px; +} diff --git a/src/web/assets/css/layout.css b/src/web/assets/css/layout.css new file mode 100644 index 0000000..77d3be1 --- /dev/null +++ b/src/web/assets/css/layout.css @@ -0,0 +1,76 @@ +:root { + --bg: #13151a; + --accent: #b283e5; + --input-bg: #28253c; + --input-border: #4c4c6d; +} + +html { + font-family: Georgia, serif; + background-color: var(--bg); + color: white; + font-size: 16px; +} + +* { + box-sizing: border-box; +} + +*::selection { + background-color: var(--accent); + color: var(--bg); +} + +a { + color: var(--accent); + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +h1 { + margin-top: 36px; + margin-bottom: 24px; +} + +h2 { + margin-top: 32px; +} + +nav, +main, +footer { + max-width: 800px; + width: 100%; + margin-left: auto; + margin-right: auto; +} + +nav { + display: flex; + gap: 16px; + padding-top: 16px; +} + +nav .space { + flex-grow: 1; +} + +footer { + margin-top: 32px; +} + +footer .link-row { + margin-top: 12px; + display: flex; + flex-wrap: wrap; + gap: 12px; +} + +footer .link-row a { + display: flex; + align-items: center; + gap: 8px; +} diff --git a/src/web/assets/favicons/16.png b/src/web/assets/favicons/16.png new file mode 100644 index 0000000000000000000000000000000000000000..fefe5655baaac332ae9ce60d687a08b21a09fab5 GIT binary patch literal 650 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 literal 0 HcmV?d00001 diff --git a/src/web/assets/favicons/192.png b/src/web/assets/favicons/192.png new file mode 100644 index 0000000000000000000000000000000000000000..998d32864f7b0d60eae20a94b462d95d3da1deef GIT binary patch literal 2269 zcmbW1X*kqv7r_4>Awt?8iaeDu3fO|g9K3ElsVVK8omtr2 z+~RV%_pA~W1Z*!!yAxlKR+d)T%WGLUvc8Omm1b~bWp8s8^|m%zQP5UN_>M31`M2T8 zAEQ(LcaoGu>@^QNC57cL&aW)7*vXNFT1T7|1fVAJK4p1LTbo;3Tic}k7E?uEN2BPz z_Obr1aVJQOsyHmd3qL(E$C#Rr@=jOV56em>udi;buW@oxDlW;mTWJJ0SM}Z2#wZEf z``SMLK039?T3K3Pf6C>(xs5Q6rgqSrA+f4r4iTRCwOw!{JEcNj#@&ZE+sLH!*T$s^RC;1h0egGlzuI+M;)*>_i2#NOd* z1aq2Ys~5U3zq~NFY^xhO`IBj?=%;`H%NVB*Q zmzS}AnF;8eIKRwAJw9XJH|2A>W@32YS2>u%3xs_kb^!n&-ngrLtv>HucuAo^Q*$FB zx(J`30^c9Em68Bp569H-igobl9DdXO@a+>V@gveIRcA837$*m6;*QX64ehmkbobgo zTd8b=;bTknkA-$e$E{~Ga*`(HW<3$8Zsk;m3;W8S*w}C_GFO4luC$TyfG?t879F~p zwp^?3R=bRiS2yYB_5SCn1JD@RKSig}FlL)gt*YnBs}kqd1Q}#Z_170-KeyCdjwGCO z39YYCU(O%$R5N*wzYVz&@SyK+$`D2^HbXa3l(?>^L!94p6dZm^vOxf6_G+krX5fsw zW-5iW`jtCGp%E?8HPb~;tNw0C@;eQ(2|G}dO|(4D*ZSUMt6;Im4~U?k;KGb-PI4)_gy7dHZ%!q$=omaIlkWE^NF2M-d|@MgAHNude#X}{KX=S;ZEGFu(-wWN!PhZOl&gU9*TMiLc<<_cZQ!diHp(E0a{DNv$ zA`NX9Yvaevf4%FE*(}Z*w^Xpp=4Ce6$pl(D^RLewv!2ZhWv@d7p*n;sc^HbBD>w); zzozW39-pow@dyonPHUa(pyl4BOoe?xOtAA1^C3NUohN<4MONXX2U6b>!0QsM4t;!k zO5R4hiMEgz#<~HUS?tg%>5q-85$)F*3J@pX|FB@!q^aks5Bs$^l^`@g_%YajPU~T< zAje90tdEh~^hq1xIy=+6nl~X?|5A2k)_APGbPlj>ucqJIPgz8lbRL?{?S5d;J<~=K z>df+jebi-4nL7~#jiGPZm-F%8sG~#u4ax@ZA|2g2{PB?!8Pa8JBj%c!So)O`K}998 zvdJxiNL4kVz}it3T zk$G#lKSQGd5Uu+^q>ej!*^u_S@?ju<smu%!jFvBKyxB3C`Qbo1T3MTpF2V)x+Uhude+`_b7YAK+rMX&cgP4- z=}d%*Q}k1+G_^u2;g3U~4jwL_DEg9?TI_iSdr11yLU~kty;jwJ$c7a8BxepKgkpYm#5C+_py+1q`f?MzCVU@pjc{mlwdvKVjXb?q#5eSaU znEpTa56_?3+BZ`PsWX?uyYnKsKqK2g7epXZ$JrmrGk_XMOa7F(+@KyhaC=ZbTZ-+n+Z)89q!rS-XnMlQpyDL+2m$CA3 p4MZXQkpK#XQues-72u5UMJoIFyS^9G{Rc%cao7L= literal 0 HcmV?d00001 diff --git a/src/web/assets/favicons/32.png b/src/web/assets/favicons/32.png new file mode 100644 index 0000000000000000000000000000000000000000..5b3f815367e73f7307809599aff4c54830336918 GIT binary patch literal 858 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7e6l0AZa85pY67#JE_7#My5g&JNk zFq9fFFuY1&V6d9Oz#v{QXIG#NP~uO3Pl&5Fd!!~yxE5Q4E@xDTd8H<6xT#R$#QK%* zUVoZYztU7VQG+GiO)YQBilcx3{{8>||JD^p-PH56*dn!9BjR0}E}yxZ;M%0g8lle< z(~vd$)${j1zWrQ0W&7gE+rNMN*^oWQfG5^QI_>9=UoW4&t4*J&#~q``9sTm@+a*)B z+eoJenv@^ieevSS+p$g!v5pNvCguKyrMIs>{`2SWrlp5nRC8TaayKnKq|O{xl`{R) zhp+uL%S{9mcC0y}%Nf0K$srw%NNu)ABmQ_pzBohvxWdQ@fB*h_^YX*-eV32#z3i%% zcjwv@SGC+UpZ2Tg?*01t+fFtk-M7O|E<=MkT!T3*+WycRU^p-)dAqytOYCB}3FL4V zctjR6Fz_7)VaDV6D^h@h>?NMQuI$gb7}+$LX2;ZM1BL#2x;TbdoIX1#y8NJnNNaM( zC6k+?7d2I*g08Gx@!K@yZkO2q|NF0OiaEy7AG>e4<>v2m_MV%i%yGT_Y+0aMS^HtX zbFUYDKK8Wee%JGomwsUkPwy#5o>~?DIkEZu!E8Zi`M-=0G$k%II{cV9Z%aL=Tf>Tv zQpS%QR6ZU%Iw2+NuJzo7tGqV9{A&2MZi>>gPYw?k@2FIpdWuzHescTDkjALJ8}|xH zf0YVYyMc{4W7{`h&()j~dlsHe+qRZxuJhfUQOybOye=1U?Y#Z_&ZXC<_ALD0daz(i zx<$jKblwsh#^XdtG{ zBEW!9Epd$~Nl7e8wMs5Z1yT$~21drZh6cI@h9L%KRwjm421eQj237_J)4I0nqG-s? zPsvQH#I51^b^eJ!4H|G8N-}d(i%Sx73vlb%a7fP&s7Df{CpbT?q&%@Gm7%=6TrV>( dyEr+qAXP8FD1G)j8!4b722WQ%mvv4FO#rn@WP|_! literal 0 HcmV?d00001 diff --git a/src/web/assets/favicons/shortcut.ico b/src/web/assets/favicons/shortcut.ico new file mode 100644 index 0000000000000000000000000000000000000000..51926b6348012dac083abcddc89089f0ce2588a8 GIT binary patch literal 7406 zcmeHL2~1RH5dOq{cFitwhyq=yY=C8Pmtz5`K>-!P6;Q-yQBmaZKugiprnQIS)y5{Z z@u;n>wMJXD8jZ&LO0|I+tI=BPkv86~_kGj@IqdxZ+hrfSi`52Wo9rat`;YnNKZf^a zX8@X^IlR3=trDXIAOS#duryww1QyX;OpJBh3P>mDi9;qJ8n>f{bx=t<2G(cD^$169 z^KcAM=m`-RAVgpwLyHa=#PE^Sg;+mxAvVokjBWFmWB1BU z*t=#s_O9KIeQS5%z{XuTzV{GL?E4ib_aDK@14nTB;4xf0eg;?1p2zibmvH;ab=Am%mUfJFhp1Rp3*HJQ@ZD4T8{!u zODn{TtdaPrcL`<>8i)DA-@}(BlknB+Qz(v4!FLm9VddmGgt^%A>9^Q2k6|e)maap^ zvh}DW>|U{vun9k{-ikvzcH{8(dvJK?9v;(A?mvuEKOe=PM~~y&u@ks{{xWV5ZeF~C zTbHll&ea<{u2tlOuO$};mYf(pd{P?ltXZO?Xf&YmIRR0z606gsCbSh1R z(O|5X2#o{5keZb(ldM!j1A;b9bdWTyjDSc{%t(<*hA2kDPC&FMc5W?`&Y~FYpii{Z zRjNc6dbNz;N-tBZUFl`^&qXiW-_`k(JnaO}B!~M&iDG7~zd~Xt{9`jkF-qniMMw{F zf1;KX6k58S*dxTsmTW?kX|9`|4fNfpn;a_5+n$QRj=e?E9PQ~DZ5GAsgun*YjO7zU zirxtwvxsK$vDwMni0-s7N%s!&S$kihr9UhEp`~Nm=j(e4|G12dINLSrr)3>aolfQ^ znZnjpIGx+3c|q-q4pS^op%M{=g!(+CrE{LrA7Q*6e5zc9YD1ocimyi5U5EXP%$1++=k7u9TOg@w{ZL-V95G8RHBY7;ntvwd456EW91p7Zc)g z@J@orbCgL*gHWC_7?TN8Q-|UMb1^6ixKY=CSt*; zax54<84IcYTvRq4i^fdHib=DvqI@=1me0YeY4fmp`e#^2HR6*#!H0>5mlwC6Weud1(;qo%qVwKY;sR99Pvy1F`dZba|5TmHQVUQl>^&fBVGKk84l)wA-SYEc#a zpH31F50->UeW5X1!B=OBi{%o>B{nuLHqNB;ZNwt9SFy!~jOgX?8*klD+s_4=PxT9S zv4c9bF}lT)>cU+CBJoQ{Fd508)<-E#ivdn|7J~9fk)~s!m!49SM$>sgP6rZ#^GT5i z!9kEn)A`O95Q2v=z6aY_{x%4VKg1QEuh04N!+JCs-+rE_Tfb@e{J#I-ANhHnmEX93 zn&$jXyMD6sdzJj8_o1MZx7;}@m3OBC;uko-KdQi7QdmZ(2FSJ$0#Zk_+1$W}tME~R z^!4@$t2YqB`Y^VoxRVRIN^RsjSO&&ezdm)$Ku*s!y7(Mv1tBDh>qjK{(H4SV7iq(+ zkopZBwh`KO=#axZdGTHji#iM=vN^A?kT-oJ z9Mn!jL6gpz{LxeMgtJ&p1>eLX$)Y&1vB=qQ7pr3%b7Mm?8wnv9rKOpTy3vI}Tcfe< bKObFY=;0KIWJ-6p={#Wjg?6_u#shx?Y>xE4 literal 0 HcmV?d00001 diff --git a/src/web/assets/favicons/vector.svg b/src/web/assets/favicons/vector.svg new file mode 100644 index 0000000..2549504 --- /dev/null +++ b/src/web/assets/favicons/vector.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/web/assets/icons/code.svg b/src/web/assets/icons/code.svg new file mode 100644 index 0000000..90fc631 --- /dev/null +++ b/src/web/assets/icons/code.svg @@ -0,0 +1 @@ + diff --git a/src/web/assets/icons/external.svg b/src/web/assets/icons/external.svg new file mode 100644 index 0000000..a0d260a --- /dev/null +++ b/src/web/assets/icons/external.svg @@ -0,0 +1 @@ + diff --git a/src/web/assets/icons/mail.svg b/src/web/assets/icons/mail.svg new file mode 100644 index 0000000..32d50f6 --- /dev/null +++ b/src/web/assets/icons/mail.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/web/assets/icons/mastodon.svg b/src/web/assets/icons/mastodon.svg new file mode 100644 index 0000000..73e3484 --- /dev/null +++ b/src/web/assets/icons/mastodon.svg @@ -0,0 +1 @@ + diff --git a/src/web/assets/icons/matrix.svg b/src/web/assets/icons/matrix.svg new file mode 100644 index 0000000..a6c31d5 --- /dev/null +++ b/src/web/assets/icons/matrix.svg @@ -0,0 +1 @@ + diff --git a/src/web/assets/icons/xmpp.svg b/src/web/assets/icons/xmpp.svg new file mode 100644 index 0000000..cacb051 --- /dev/null +++ b/src/web/assets/icons/xmpp.svg @@ -0,0 +1 @@ + diff --git a/src/web/controllers/home.rs b/src/web/controllers/home.rs new file mode 100644 index 0000000..e2a529a --- /dev/null +++ b/src/web/controllers/home.rs @@ -0,0 +1,6 @@ +use axum::response::Html; +use crate::web::templates; + +pub async fn home() -> Html { + templates::render("home.html", &tera::Context::new()) +} diff --git a/src/web/controllers/mod.rs b/src/web/controllers/mod.rs new file mode 100644 index 0000000..90f9e35 --- /dev/null +++ b/src/web/controllers/mod.rs @@ -0,0 +1,3 @@ +pub mod home; + +pub use home::home; diff --git a/src/web/mod.rs b/src/web/mod.rs new file mode 100644 index 0000000..deae542 --- /dev/null +++ b/src/web/mod.rs @@ -0,0 +1,2 @@ +pub mod controllers; +pub mod templates; diff --git a/src/web/templates.rs b/src/web/templates.rs new file mode 100644 index 0000000..81a3a97 --- /dev/null +++ b/src/web/templates.rs @@ -0,0 +1,29 @@ +use lazy_static::lazy_static; +use axum::response::Html; +use tera::Tera; + +lazy_static! { + pub static ref TEMPLATES: Tera = { + let mut tera = match Tera::new("src/web/templates/**/*") { + Ok(t) => t, + Err(e) => { + println!("Templates parsing error(s): {}", e); + ::std::process::exit(1); + } + }; + tera.autoescape_on(vec![".html"]); + tera + }; +} + +/// Render HTML template. +/// +/// Parameters: +/// - `name`: html file path relative to `templates` dir. +/// - `ctx`: context with parameters for rendering. +pub fn render(name: &str, ctx: &tera::Context) -> Html { + match TEMPLATES.render(name, ctx) { + Ok(res) => Html(res), + Err(err) => Html(err.to_string()), + } +} diff --git a/src/web/templates/home.html b/src/web/templates/home.html new file mode 100644 index 0000000..6b3c0a9 --- /dev/null +++ b/src/web/templates/home.html @@ -0,0 +1,85 @@ +{% extends "layout.html" %} + +{% block head %} + +{% endblock %} + +{% block content %} +

Уютный домик

+ +

+ У меня есть несколько проектов, запущенных на домашнем сервере. + Я буду рад, если они будут полезны другим людям. +

+ +

+ Создайте один аккаунт, чтобы получить доступ к большинству сервисов. +

+ +

+ Не стоит ожидать большой надёжности, однако я прикладываю все усилия, + чтобы сервисы были доступны 24/7. +

+ +

- Иван, администратор comfycamp.space

+ +
+
+

Mastodon

+
+ + m.comfycamp.space + +

+ Микроблоги с поддержкой fediverse. +

+
+ +
+
+

Peertube

+
+ + v.comfycamp.space + +

+ Видеохостинг, альтернатива YouTube. +

+
+ +
+
+

Matrix

+
+ + matrix.comfycamp.space + +

+ Современный протокол для общения. +

+
+ +
+
+

Forgejo

+
+ + git.comfycamp.space + +

+ Хостинг для git-проектов. +

+
+ +
+
+

Nextcloud

+
+ + nc.comfycamp.space + +

+ Облако, календарь, задачи. +

+
+{% endblock %} diff --git a/src/web/templates/layout.html b/src/web/templates/layout.html new file mode 100644 index 0000000..60d267b --- /dev/null +++ b/src/web/templates/layout.html @@ -0,0 +1,60 @@ + + + + + Comfy Camp + + + + + + + + + {% block head %}{% endblock %} + + + + +
+
+ {% block content %}{% endblock %} +
+
+ + + +