diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index eb61fe8a5..6034d4352 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,5 +1,5 @@ name: CI -on: [push, pull_request] +on: [ push, pull_request ] env: RUST_BACKTRACE: 1 jobs: @@ -12,8 +12,7 @@ jobs: with: components: rustfmt - - name: Formatting - run: cargo fmt --all -- --check + - uses: Swatinem/rust-cache@v2 - name: Test run: | @@ -22,3 +21,33 @@ jobs: cargo build --all --locked cargo clippy -- --deny warnings cargo test --all --locked + + - name: Formatting + run: cargo fmt --all -- --check + + - name: Build website + run: cargo run + env: + BASE_URL: "/www.rust-lang.org" + + - name: Configure GitHub Pages + uses: actions/configure-pages@v5 + + - name: Upload website + uses: actions/upload-pages-artifact@v3 + with: + path: build + + deploy: + needs: [ build ] + if: github.ref == 'refs/heads/master' + environment: + name: github-pages + permissions: + contents: read + pages: write + id-token: write + runs-on: ubuntu-latest + steps: + - name: Deploy to GitHub Pages + uses: actions/deploy-pages@v4 diff --git a/.gitignore b/.gitignore index 2f8c49019..a8bf0d405 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .DS_Store /target/ +/build/ **/*.rs.bk /node_modules /static/styles/*.map diff --git a/Cargo.lock b/Cargo.lock index a01260ba9..6e5f26741 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,104 +2,17 @@ # It is not intended for manual editing. version = 4 -[[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 = "async-stream" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" -dependencies = [ - "async-stream-impl", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-stream-impl" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "async-trait" -version = "0.1.88" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "atomic" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" - -[[package]] -name = "atomic" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d818003e740b63afc82337e3160717f4f63078720a810b7b903e70a5d1d2994" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "atomic-waker" -version = "1.1.2" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] -name = "autocfg" -version = "1.4.0" +name = "anyhow" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" - -[[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 0.52.6", -] +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] name = "base64" @@ -107,24 +20,6 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" -[[package]] -name = "binascii" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "383d29d513d8764dcdc42ea295d979eb99c3c9f00607b3692cf68a431f7dca72" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[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" @@ -134,24 +29,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "bumpalo" -version = "3.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" - -[[package]] -name = "bytemuck" -version = "1.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - [[package]] name = "bytes" version = "1.10.1" @@ -185,21 +62,23 @@ dependencies = [ ] [[package]] -name = "core-foundation" -version = "0.9.4" +name = "cookie_store" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +checksum = "2eac901828f88a5241ee0600950ab981148a18f2f756900ffba1b125ca6a3ef9" dependencies = [ - "core-foundation-sys", - "libc", + "cookie", + "document-features", + "idna", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "time", + "url", ] -[[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" @@ -210,20 +89,14 @@ dependencies = [ ] [[package]] -name = "crossbeam-channel" -version = "0.5.15" +name = "crc32fast" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ - "crossbeam-utils", + "cfg-if", ] -[[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" @@ -234,6 +107,41 @@ dependencies = [ "typenum", ] +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core", + "quote", + "syn", +] + [[package]] name = "deranged" version = "0.4.0" @@ -244,36 +152,34 @@ dependencies = [ ] [[package]] -name = "devise" -version = "0.4.2" +name = "derive_builder" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1d90b0c4c777a2cad215e3c7be59ac7c15adf45cf76317009b7d096d46f651d" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" dependencies = [ - "devise_codegen", - "devise_core", + "derive_builder_macro", ] [[package]] -name = "devise_codegen" -version = "0.4.2" +name = "derive_builder_core" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71b28680d8be17a570a2334922518be6adc3f58ecc880cbb404eaeb8624fd867" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" dependencies = [ - "devise_core", + "darling", + "proc-macro2", "quote", + "syn", ] [[package]] -name = "devise_core" -version = "0.4.2" +name = "derive_builder_macro" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b035a542cf7abf01f2e3c4d5a7acbaebfefe120ae4efc7bde3df98186e4b8af7" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ - "bitflags 2.9.0", - "proc-macro2", - "proc-macro2-diagnostics", - "quote", - "syn 2.0.100", + "derive_builder_core", + "syn", ] [[package]] @@ -294,22 +200,16 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", ] [[package]] -name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" - -[[package]] -name = "encoding_rs" -version = "0.8.35" +name = "document-features" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d" dependencies = [ - "cfg-if", + "litrs", ] [[package]] @@ -319,45 +219,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] -name = "errno" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" -dependencies = [ - "libc", - "windows-sys 0.59.0", -] - -[[package]] -name = "fastrand" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" - -[[package]] -name = "figment" -version = "0.10.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cb01cd46b0cf372153850f4c6c272d9cbea2da513e07538405148f95bd789f3" -dependencies = [ - "atomic 0.6.0", - "pear", - "serde", - "toml", - "uncased", - "version_check", -] - -[[package]] -name = "filetime" -version = "0.2.25" +name = "flate2" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" dependencies = [ - "cfg-if", - "libc", - "libredox", - "windows-sys 0.59.0", + "crc32fast", + "miniz_oxide", ] [[package]] @@ -367,22 +235,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb74634707bebd0ce645a981148e8fb8c7bccd4c33c652aeffd28bf2f96d555a" dependencies = [ "fluent-bundle 0.15.3", - "unic-langid 0.9.5", -] - -[[package]] -name = "fluent-bundle" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27ade33328521266c81cc0924523988f43ccd7359f64689a1b6e818afca3a646" -dependencies = [ - "fluent-langneg 0.12.1", - "fluent-syntax 0.9.3", - "intl-memoizer 0.4.0", - "intl_pluralrules 6.0.0", - "rental", - "smallvec", - "unic-langid 0.8.0", + "unic-langid", ] [[package]] @@ -391,23 +244,30 @@ version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fe0a21ee80050c678013f82edf4b705fe2f26f1f9877593d13198612503f493" dependencies = [ - "fluent-langneg 0.13.0", + "fluent-langneg", "fluent-syntax 0.11.1", - "intl-memoizer 0.5.2", - "intl_pluralrules 7.0.2", - "rustc-hash", + "intl-memoizer", + "intl_pluralrules", + "rustc-hash 1.1.0", "self_cell 0.10.3", "smallvec", - "unic-langid 0.9.5", + "unic-langid", ] [[package]] -name = "fluent-langneg" -version = "0.12.1" +name = "fluent-bundle" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe5815efd5542e40841cd34ef9003822352b04c67a70c595c6758597c72e1f56" +checksum = "01203cb8918f5711e73891b347816d932046f95f54207710bda99beaeb423bf4" dependencies = [ - "unic-langid 0.8.0", + "fluent-langneg", + "fluent-syntax 0.12.0", + "intl-memoizer", + "intl_pluralrules", + "rustc-hash 2.1.1", + "self_cell 1.2.0", + "smallvec", + "unic-langid", ] [[package]] @@ -416,15 +276,9 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c4ad0989667548f06ccd0e306ed56b61bd4d35458d54df5ec7587c0e8ed5e94" dependencies = [ - "unic-langid 0.9.5", + "unic-langid", ] -[[package]] -name = "fluent-syntax" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac0f7e83d14cccbf26e165d8881dcac5891af0d85a88543c09dd72ebd31d91ba" - [[package]] name = "fluent-syntax" version = "0.11.1" @@ -435,25 +289,20 @@ dependencies = [ ] [[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foreign-types" -version = "0.3.2" +name = "fluent-syntax" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +checksum = "54f0d287c53ffd184d04d8677f590f4ac5379785529e5e08b1c8083acdd5c198" dependencies = [ - "foreign-types-shared", + "memchr", + "thiserror 2.0.12", ] [[package]] -name = "foreign-types-shared" -version = "0.1.1" +name = "fnv" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" @@ -464,102 +313,6 @@ 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" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" - -[[package]] -name = "futures-io" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" - -[[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-channel", - "futures-core", - "futures-io", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - -[[package]] -name = "generator" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" -dependencies = [ - "cc", - "libc", - "log", - "rustversion", - "windows", -] - [[package]] name = "generic-array" version = "0.14.7" @@ -572,105 +325,46 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", -] - -[[package]] -name = "getrandom" -version = "0.3.2" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", - "r-efi", - "wasi 0.14.2+wasi-0.2.4", -] - -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - -[[package]] -name = "glob" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" - -[[package]] -name = "h2" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.12", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "h2" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75249d144030531f8dee69fe9cea04d3edf809a017ae445e2abdff6629e86633" -dependencies = [ - "atomic-waker", - "bytes", - "fnv", - "futures-core", - "futures-sink", - "http 1.3.1", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", + "wasi", ] [[package]] name = "handlebars" -version = "5.1.2" +version = "6.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d08485b96a0e6393e9e4d1b8d48cf74ad6c063cd905eb33f42c1ce3f0377539b" +checksum = "759e2d5aea3287cb1190c8ec394f42866cb5bf74fcbf213f354e3c856ea26098" dependencies = [ + "derive_builder", "log", + "num-order", "pest", "pest_derive", "serde", "serde_json", - "thiserror 1.0.69", + "thiserror 2.0.12", + "walkdir", ] [[package]] name = "handlebars-fluent" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bb39cffd370c96a5de57ec5242f385bfb7d52facd774881d81e89621ce7d87e" +checksum = "37b8edde54ea32a8db20ef42b0b30f8bb3244ec87c4801bdd3db53046b3807eb" dependencies = [ "fluent", - "fluent-bundle 0.11.0", - "fluent-langneg 0.12.1", - "fluent-syntax 0.11.1", + "fluent-bundle 0.16.0", + "fluent-langneg", + "fluent-syntax 0.12.0", "handlebars", "lazy_static", "serde_json", - "unic-langid 0.8.0", + "unic-langid", ] [[package]] @@ -685,23 +379,6 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" -[[package]] -name = "hermit-abi" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbd780fe5cc30f81464441920d82ac8740e2e46b29a6fad543ddd075229ce37e" - -[[package]] -name = "http" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - [[package]] name = "http" version = "1.3.1" @@ -713,199 +390,43 @@ dependencies = [ "itoa", ] -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http 0.2.12", - "pin-project-lite", -] - -[[package]] -name = "http-body" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http 1.3.1", -] - -[[package]] -name = "http-body-util" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" -dependencies = [ - "bytes", - "futures-core", - "http 1.3.1", - "http-body 1.0.1", - "pin-project-lite", -] - [[package]] name = "httparse" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hyper" -version = "0.14.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "h2 0.4.9", - "http 1.3.1", - "http-body 1.0.1", - "httparse", - "itoa", - "pin-project-lite", - "smallvec", - "tokio", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.27.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" -dependencies = [ - "futures-util", - "http 1.3.1", - "hyper 1.6.0", - "hyper-util", - "rustls", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tower-service", -] - -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper 1.6.0", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", -] - -[[package]] -name = "hyper-util" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497bbc33a26fdd4af9ed9c70d63f61cf56a938375fbb32df34db9b1cd6d643f2" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "http 1.3.1", - "http-body 1.0.1", - "hyper 1.6.0", - "libc", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", -] - [[package]] name = "icu_collections" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" dependencies = [ "displaydoc", + "potential_utf", "yoke", "zerofrom", "zerovec", ] [[package]] -name = "icu_locid" -version = "1.5.0" +name = "icu_locale_core" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" dependencies = [ "displaydoc", "litemap", - "tinystr 0.7.6", + "tinystr 0.8.1", "writeable", "zerovec", ] -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr 0.7.6", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" - [[package]] name = "icu_normalizer" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" dependencies = [ "displaydoc", "icu_collections", @@ -913,66 +434,59 @@ dependencies = [ "icu_properties", "icu_provider", "smallvec", - "utf16_iter", - "utf8_iter", - "write16", "zerovec", ] [[package]] name = "icu_normalizer_data" -version = "1.5.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" [[package]] name = "icu_properties" -version = "1.5.1" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" dependencies = [ "displaydoc", "icu_collections", - "icu_locid_transform", + "icu_locale_core", "icu_properties_data", "icu_provider", - "tinystr 0.7.6", + "potential_utf", + "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "1.5.1" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" [[package]] name = "icu_provider" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" dependencies = [ "displaydoc", - "icu_locid", - "icu_provider_macros", + "icu_locale_core", "stable_deref_trait", - "tinystr 0.7.6", + "tinystr 0.8.1", "writeable", "yoke", "zerofrom", + "zerotrie", "zerovec", ] [[package]] -name = "icu_provider_macros" -version = "1.5.0" +name = "ident_case" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" @@ -987,9 +501,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ "icu_normalizer", "icu_properties", @@ -1006,60 +520,14 @@ dependencies = [ "serde", ] -[[package]] -name = "inlinable_string" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" - -[[package]] -name = "inotify" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" -dependencies = [ - "bitflags 1.3.2", - "inotify-sys", - "libc", -] - -[[package]] -name = "inotify-sys" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" -dependencies = [ - "libc", -] - [[package]] name = "intl-memoizer" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9867e2d65d82936ef34217ed0f87b639a94384e93a0676158142c861c705391f" -dependencies = [ - "type-map 0.3.0", - "unic-langid 0.8.0", -] - -[[package]] -name = "intl-memoizer" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe22e020fce238ae18a6d5d8c502ee76a52a6e880d99477657e6acc30ec57bda" -dependencies = [ - "type-map 0.5.0", - "unic-langid 0.9.5", -] - -[[package]] -name = "intl_pluralrules" -version = "6.0.0" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82c14d8eece42c03353e0ce86a4d3f97b1f1cef401e4d962dca6c6214a85002" +checksum = "310da2e345f5eb861e7a07ee182262e94975051db9e4223e909ba90f392f163f" dependencies = [ - "tinystr 0.3.4", - "unic-langid 0.8.0", + "type-map", + "unic-langid", ] [[package]] @@ -1068,24 +536,7 @@ version = "7.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "078ea7b7c29a2b4df841a7f6ac8775ff6074020c6776d48491ce2268e068f972" dependencies = [ - "unic-langid 0.9.5", -] - -[[package]] -name = "ipnet" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" - -[[package]] -name = "is-terminal" -version = "0.4.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" -dependencies = [ - "hermit-abi 0.5.0", - "libc", - "windows-sys 0.59.0", + "unic-langid", ] [[package]] @@ -1094,36 +545,6 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" -[[package]] -name = "js-sys" -version = "0.3.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" -dependencies = [ - "once_cell", - "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" @@ -1136,38 +557,17 @@ version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" -[[package]] -name = "libredox" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" -dependencies = [ - "bitflags 2.9.0", - "libc", - "redox_syscall", -] - -[[package]] -name = "linux-raw-sys" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" - [[package]] name = "litemap" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] -name = "lock_api" -version = "0.4.12" +name = "litrs" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] +checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" [[package]] name = "log" @@ -1175,275 +575,58 @@ version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" -[[package]] -name = "loom" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" -dependencies = [ - "cfg-if", - "generator", - "scoped-tls", - "serde", - "serde_json", - "tracing", - "tracing-subscriber", -] - -[[package]] -name = "matchers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" -dependencies = [ - "regex-automata 0.1.10", -] - [[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 = "miniz_oxide" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", ] [[package]] -name = "mio" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" -dependencies = [ - "libc", - "log", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.48.0", -] - -[[package]] -name = "mio" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" -dependencies = [ - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", -] - -[[package]] -name = "multer" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83e87776546dc87511aa5ee218730c92b666d7264ab6ed41f9d215af9cd5224b" -dependencies = [ - "bytes", - "encoding_rs", - "futures-util", - "http 1.3.1", - "httparse", - "memchr", - "mime", - "spin", - "tokio", - "tokio-util", - "version_check", -] - -[[package]] -name = "native-tls" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - -[[package]] -name = "normpath" -version = "1.3.0" +name = "num-conv" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8911957c4b1549ac0dc74e30db9c8b0e66ddcd6d7acc33098f4c63a64a6d7ed" -dependencies = [ - "windows-sys 0.59.0", -] +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] -name = "notify" -version = "6.1.1" +name = "num-modular" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" -dependencies = [ - "bitflags 2.9.0", - "crossbeam-channel", - "filetime", - "fsevent-sys", - "inotify", - "kqueue", - "libc", - "log", - "mio 0.8.11", - "walkdir", - "windows-sys 0.48.0", -] +checksum = "17bb261bf36fa7d83f4c294f834e91256769097b3cb505d44831e0a179ac647f" [[package]] -name = "nu-ansi-term" -version = "0.46.0" +name = "num-order" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +checksum = "537b596b97c40fcf8056d153049eb22f481c17ebce72a513ec9286e4986d1bb6" dependencies = [ - "overload", - "winapi", + "num-modular", ] -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - [[package]] name = "num_cpus" version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.3.9", + "hermit-abi", "libc", ] -[[package]] -name = "object" -version = "0.36.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" -[[package]] -name = "openssl" -version = "0.10.72" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" -dependencies = [ - "bitflags 2.9.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "openssl-probe" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" - -[[package]] -name = "openssl-sys" -version = "0.9.107" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - -[[package]] -name = "parking_lot" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.52.6", -] - -[[package]] -name = "pear" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdeeaa00ce488657faba8ebf44ab9361f9365a97bd39ffb8a60663f57ff4b467" -dependencies = [ - "inlinable_string", - "pear_codegen", - "yansi", -] - -[[package]] -name = "pear_codegen" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bab5b985dc082b345f812b7df84e1bef27e7207b39e448439ba8bd69c93f147" -dependencies = [ - "proc-macro2", - "proc-macro2-diagnostics", - "quote", - "syn 2.0.100", -] - [[package]] name = "percent-encoding" version = "2.3.1" @@ -1481,7 +664,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.100", + "syn", ] [[package]] @@ -1495,18 +678,6 @@ dependencies = [ "sha2", ] -[[package]] -name = "pin-project-lite" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - [[package]] name = "pkg-config" version = "0.3.32" @@ -1514,19 +685,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] -name = "powerfmt" -version = "0.2.0" +name = "potential_utf" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" +checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +dependencies = [ + "zerovec", +] [[package]] -name = "ppv-lite86" -version = "0.2.21" +name = "powerfmt" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "proc-macro-hack" @@ -1543,19 +714,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "proc-macro2-diagnostics" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", - "version_check", - "yansi", -] - [[package]] name = "quote" version = "1.0.40" @@ -1565,286 +723,18 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "r-efi" -version = "5.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" - -[[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 0.2.15", -] - -[[package]] -name = "redox_syscall" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" -dependencies = [ - "bitflags 2.9.0", -] - -[[package]] -name = "ref-cast" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" -dependencies = [ - "ref-cast-impl", -] - -[[package]] -name = "ref-cast-impl" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[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 0.4.9", - "regex-syntax 0.8.5", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", -] - -[[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 0.8.5", -] - -[[package]] -name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "regex-syntax" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" - -[[package]] -name = "rental" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc89fe2acac36d212474d138aaf939c04a82df5b61d07011571ebce5aef81f2e" -dependencies = [ - "rental-impl", - "stable_deref_trait", -] - -[[package]] -name = "rental-impl" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "475e68978dc5b743f2f40d8e0a8fdc83f1c5e78cbf4b8fa5e74e73beebc340de" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "reqwest" -version = "0.12.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" -dependencies = [ - "base64", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2 0.4.9", - "http 1.3.1", - "http-body 1.0.1", - "http-body-util", - "hyper 1.6.0", - "hyper-rustls", - "hyper-tls", - "hyper-util", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls-pemfile", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "system-configuration", - "tokio", - "tokio-native-tls", - "tower", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "windows-registry", -] - [[package]] name = "ring" version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" -dependencies = [ - "cc", - "cfg-if", - "getrandom 0.2.15", - "libc", - "untrusted", - "windows-sys 0.52.0", -] - -[[package]] -name = "rocket" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a516907296a31df7dc04310e7043b61d71954d703b603cc6867a026d7e72d73f" -dependencies = [ - "async-stream", - "async-trait", - "atomic 0.5.3", - "binascii", - "bytes", - "either", - "figment", - "futures", - "indexmap", - "log", - "memchr", - "multer", - "num_cpus", - "parking_lot", - "pin-project-lite", - "rand", - "ref-cast", - "rocket_codegen", - "rocket_http", - "serde", - "state", - "tempfile", - "time", - "tokio", - "tokio-stream", - "tokio-util", - "ubyte", - "version_check", - "yansi", -] - -[[package]] -name = "rocket_codegen" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "575d32d7ec1a9770108c879fc7c47815a80073f96ca07ff9525a94fcede1dd46" -dependencies = [ - "devise", - "glob", - "indexmap", - "proc-macro2", - "quote", - "rocket_http", - "syn 2.0.100", - "unicode-xid", - "version_check", -] - -[[package]] -name = "rocket_dyn_templates" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bbab919c9e67df3f7ac6624a32ef897df4cd61c0969f4d66f3ced0534660d7a" -dependencies = [ - "handlebars", - "normpath", - "notify", - "rocket", - "walkdir", -] - -[[package]] -name = "rocket_http" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e274915a20ee3065f611c044bd63c40757396b6dbc057d6046aec27f14f882b9" -dependencies = [ - "cookie", - "either", - "futures", - "http 0.2.12", - "hyper 0.14.32", - "indexmap", - "log", - "memchr", - "pear", - "percent-encoding", - "pin-project-lite", - "ref-cast", - "serde", - "smallvec", - "stable-pattern", - "state", - "time", - "tokio", - "uncased", +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "untrusted", + "windows-sys 0.52.0", ] [[package]] @@ -1856,12 +746,6 @@ dependencies = [ "serde", ] -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - [[package]] name = "rustc-hash" version = "1.1.0" @@ -1869,25 +753,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] -name = "rustix" -version = "1.0.5" +name = "rustc-hash" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf" -dependencies = [ - "bitflags 2.9.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.59.0", -] +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rustls" -version = "0.23.26" +version = "0.23.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df51b5869f3a441595eac5e8ff14d486ff285f7b8c0df8770e49c3b56351f0f0" +checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" dependencies = [ + "log", "once_cell", + "ring", "rustls-pki-types", "rustls-webpki", "subtle", @@ -1905,27 +784,24 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +dependencies = [ + "zeroize", +] [[package]] name = "rustls-webpki" -version = "0.103.1" +version = "0.103.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03" +checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" dependencies = [ "ring", "rustls-pki-types", "untrusted", ] -[[package]] -name = "rustversion" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" - [[package]] name = "ryu" version = "1.0.20" @@ -1963,50 +839,6 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "schannel" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags 2.9.0", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "self_cell" version = "0.10.3" @@ -2039,7 +871,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", ] [[package]] @@ -2063,18 +895,6 @@ dependencies = [ "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" @@ -2086,70 +906,18 @@ dependencies = [ "digest", ] -[[package]] -name = "sharded-slab" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" -dependencies = [ - "lazy_static", -] - [[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 = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - [[package]] name = "smallvec" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" -[[package]] -name = "socket2" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - -[[package]] -name = "stable-pattern" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4564168c00635f88eaed410d5efa8131afa8d8699a612c80c455a0ba05c21045" -dependencies = [ - "memchr", -] - [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -2157,13 +925,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] -name = "state" -version = "0.6.0" +name = "strsim" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b8c4a4445d81357df8b1a650d0d0d6fbbbfe99d064aa5e02f3e4022061476d8" -dependencies = [ - "loom", -] +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "subtle" @@ -2171,17 +936,6 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - [[package]] name = "syn" version = "2.0.100" @@ -2193,58 +947,15 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "sync_wrapper" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" -dependencies = [ - "futures-core", -] - [[package]] name = "synstructure" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", -] - -[[package]] -name = "system-configuration" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" -dependencies = [ - "bitflags 2.9.0", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "tempfile" -version = "3.19.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" -dependencies = [ - "fastrand", - "getrandom 0.3.2", - "once_cell", - "rustix", - "windows-sys 0.59.0", + "syn", ] [[package]] @@ -2273,7 +984,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", ] [[package]] @@ -2284,17 +995,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", -] - -[[package]] -name = "thread_local" -version = "1.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" -dependencies = [ - "cfg-if", - "once_cell", + "syn", ] [[package]] @@ -2328,12 +1029,6 @@ dependencies = [ "time-core", ] -[[package]] -name = "tinystr" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29738eedb4388d9ea620eeab9384884fc3f06f586a2eddb56bedc5885126c7c1" - [[package]] name = "tinystr" version = "0.7.6" @@ -2341,79 +1036,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" dependencies = [ "displaydoc", - "zerovec", -] - -[[package]] -name = "tokio" -version = "1.44.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio 1.0.3", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys 0.52.0", -] - -[[package]] -name = "tokio-macros" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - -[[package]] -name = "tokio-rustls" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" -dependencies = [ - "rustls", - "tokio", -] - -[[package]] -name = "tokio-stream" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", ] [[package]] -name = "tokio-util" -version = "0.7.14" +name = "tinystr" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b9590b93e6fcc1739458317cccd391ad3955e2bde8913edf6f95f9e65a8f034" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", + "displaydoc", + "zerovec", ] [[package]] @@ -2457,116 +1089,13 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfb942dfe1d8e29a7ee7fcbde5bd2b9a25fb89aa70caea2eba3bee836ff41076" -[[package]] -name = "tower" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" -dependencies = [ - "futures-core", - "futures-util", - "pin-project-lite", - "sync_wrapper", - "tokio", - "tower-layer", - "tower-service", -] - -[[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.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" -dependencies = [ - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "tracing-core" -version = "0.1.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" -dependencies = [ - "once_cell", - "valuable", -] - -[[package]] -name = "tracing-log" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" -dependencies = [ - "matchers", - "nu-ansi-term", - "once_cell", - "regex", - "sharded-slab", - "smallvec", - "thread_local", - "tracing", - "tracing-core", - "tracing-log", -] - -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "type-map" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d2741b1474c327d95c1f1e3b0a2c3977c8e128409c572a33af2914e7d636717" -dependencies = [ - "fxhash", -] - [[package]] name = "type-map" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "deb68604048ff8fa93347f02441e4487594adc20bb8a084f9e564d2b827a0a9f" dependencies = [ - "rustc-hash", + "rustc-hash 1.1.0", ] [[package]] @@ -2575,40 +1104,11 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" -[[package]] -name = "ubyte" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f720def6ce1ee2fc44d40ac9ed6d3a59c361c80a75a7aa8e75bb9baed31cf2ea" -dependencies = [ - "serde", -] - [[package]] name = "ucd-trie" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" - -[[package]] -name = "uncased" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1b88fcfe09e89d3866a5c11019378088af2d24c3fbd4f0543f96b479ec90697" -dependencies = [ - "serde", - "version_check", -] - -[[package]] -name = "unic-langid" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d81136159f779c35b10655f45210c71cd5ca5a45aadfe9840a61c7071735ed" -dependencies = [ - "unic-langid-impl 0.8.0", - "unic-langid-macros", -] +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" [[package]] name = "unic-langid" @@ -2616,16 +1116,8 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23dd9d1e72a73b25e07123a80776aae3e7b0ec461ef94f9151eed6ec88005a44" dependencies = [ - "unic-langid-impl 0.9.5", -] - -[[package]] -name = "unic-langid-impl" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c43c61e94492eb67f20facc7b025778a904de83d953d8fcb60dd9adfd6e2d0ea" -dependencies = [ - "tinystr 0.3.4", + "unic-langid-impl", + "unic-langid-macros", ] [[package]] @@ -2639,26 +1131,26 @@ dependencies = [ [[package]] name = "unic-langid-macros" -version = "0.8.0" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49bd90791278634d57e3ed4a4073108e3f79bfb87ab6a7b8664ba097425703df" +checksum = "0da1cd2c042d3c7569a1008806b02039e7a4a2bdf8f8e96bd3c792434a0e275e" dependencies = [ "proc-macro-hack", - "tinystr 0.3.4", - "unic-langid-impl 0.8.0", + "tinystr 0.7.6", + "unic-langid-impl", "unic-langid-macros-impl", ] [[package]] name = "unic-langid-macros-impl" -version = "0.8.0" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0098f77bd754f8fb7850cdf4ab143aa821898c4ac6dc16bcb2aa3e62ce858d1" +checksum = "1ed7f4237ba393424195053097c1516bd4590dc82b84f2f97c5c69e12704555b" dependencies = [ "proc-macro-hack", "quote", - "syn 1.0.109", - "unic-langid-impl 0.8.0", + "syn", + "unic-langid-impl", ] [[package]] @@ -2667,18 +1159,45 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" - [[package]] name = "untrusted" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" +[[package]] +name = "ureq" +version = "3.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f0fde9bc91026e381155f8c67cb354bcd35260b2f4a29bcc84639f762760c39" +dependencies = [ + "base64", + "cookie_store", + "flate2", + "log", + "percent-encoding", + "rustls", + "rustls-pemfile", + "rustls-pki-types", + "serde", + "serde_json", + "ureq-proto", + "utf-8", + "webpki-roots 0.26.11", +] + +[[package]] +name = "ureq-proto" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59db78ad1923f2b1be62b6da81fe80b173605ca0d57f85da2e005382adf693f7" +dependencies = [ + "base64", + "http", + "httparse", + "log", +] + [[package]] name = "url" version = "2.5.4" @@ -2691,10 +1210,10 @@ dependencies = [ ] [[package]] -name = "utf16_iter" -version = "1.0.5" +name = "utf-8" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" [[package]] name = "utf8_iter" @@ -2702,18 +1221,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" -[[package]] -name = "valuable" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - [[package]] name = "version_check" version = "0.9.5" @@ -2730,127 +1237,30 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - [[package]] name = "wasi" -version = "0.14.2+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" -dependencies = [ - "wit-bindgen-rt", -] - -[[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 2.0.100", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" -dependencies = [ - "cfg-if", - "js-sys", - "once_cell", - "wasm-bindgen", - "web-sys", -] - -[[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 2.0.100", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" -dependencies = [ - "unicode-ident", -] +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "web-sys" -version = "0.3.77" +name = "webpki-roots" +version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "js-sys", - "wasm-bindgen", + "webpki-roots 1.0.2", ] [[package]] -name = "winapi" -version = "0.3.9" +name = "webpki-roots" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", + "rustls-pki-types", ] -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - [[package]] name = "winapi-util" version = "0.1.9" @@ -2860,72 +1270,13 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-link" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" - -[[package]] -name = "windows-registry" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" -dependencies = [ - "windows-result", - "windows-strings", - "windows-targets 0.53.0", -] - -[[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.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -2934,22 +1285,7 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", + "windows-targets", ] [[package]] @@ -2958,170 +1294,64 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" -dependencies = [ - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", + "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.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - [[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_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" -[[package]] -name = "windows_i686_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" - [[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_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_i686_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" - [[package]] name = "winnow" version = "0.7.6" @@ -3131,58 +1361,34 @@ dependencies = [ "memchr", ] -[[package]] -name = "wit-bindgen-rt" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags 2.9.0", -] - -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - [[package]] name = "writeable" -version = "0.5.5" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" [[package]] name = "www-rust-lang-org" version = "0.1.0" dependencies = [ + "anyhow", + "handlebars", "handlebars-fluent", "percent-encoding", - "reqwest", - "rocket", - "rocket_dyn_templates", "rust_team_data", "sass-rs", "serde", "serde_json", "time", "toml", -] - -[[package]] -name = "yansi" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" -dependencies = [ - "is-terminal", + "ureq", ] [[package]] name = "yoke" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" dependencies = [ "serde", "stable_deref_trait", @@ -3192,36 +1398,16 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", "synstructure", ] -[[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 2.0.100", -] - [[package]] name = "zerofrom" version = "0.1.6" @@ -3239,7 +1425,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", "synstructure", ] @@ -3249,11 +1435,22 @@ version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +[[package]] +name = "zerotrie" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + [[package]] name = "zerovec" -version = "0.10.4" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" dependencies = [ "yoke", "zerofrom", @@ -3262,11 +1459,11 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.10.3" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", ] diff --git a/Cargo.toml b/Cargo.toml index 29c5346ce..672e17569 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,12 +5,12 @@ authors = ["The Rust Project Developers"] edition = "2024" [dependencies] -handlebars-fluent = "0.4.0" -rocket = "0.5.1" -rocket_dyn_templates = { version = "0.2.0", features = ["handlebars"] } +anyhow = "1" +handlebars = { version = "6", features = ["dir_source"] } +handlebars-fluent = "0.5" serde = { version = "1.0", features = ["derive"] } sass-rs = "0.2.1" -reqwest = { version = "0.12.15", features = ["json"] } +ureq = { version = "3", features = ["json"] } toml = "0.8" serde_json = "1.0" rust_team_data = { git = "https://github.com/rust-lang/team" } diff --git a/src/assets.rs b/src/assets.rs new file mode 100644 index 000000000..3222e6a5a --- /dev/null +++ b/src/assets.rs @@ -0,0 +1,132 @@ +use crate::BaseUrl; +use crate::fs::ensure_directory; +use anyhow::Context; +use sass_rs::{Options, compile_file}; +use serde::Serialize; +use std::fs; +use std::hash::{DefaultHasher, Hasher}; +use std::path::Path; + +fn write_file(path: &Path, bytes: &[u8]) -> anyhow::Result<()> { + ensure_directory(path)?; + Ok(fs::write(path, bytes)?) +} + +fn hash_string(content: &str) -> String { + let mut hasher = DefaultHasher::new(); + hasher.write(content.as_bytes()); + hasher.finish().to_string() +} + +fn relative_url(path: &Path, out_dir: &Path) -> anyhow::Result { + Ok(path.strip_prefix(out_dir)?.to_str().unwrap().to_string()) +} + +/// Compiles SASS file, stores it in `out_dir` and returns the relative URL to it. +fn compile_sass( + root_dir: &Path, + out_dir: &Path, + filename: &str, + base_url: &str, +) -> anyhow::Result { + let scss_file = root_dir + .join("src") + .join("styles") + .join(format!("{filename}.scss")); + + let css = compile_file(&scss_file, Options::default()) + .map_err(|e| anyhow::anyhow!("{e}")) + .with_context(|| anyhow::anyhow!("couldn't compile sass: {}", scss_file.display()))?; + let css = css.replace("$BASEURL", base_url); + + let css_sha = format!("{filename}_{}", hash_string(&css)); + let out_css_path = out_dir + .join("static") + .join("styles") + .join(format!("{css_sha}.css")); + + write_file(&out_css_path, &css.into_bytes()) + .with_context(|| anyhow::anyhow!("couldn't write css file: {}", out_css_path.display()))?; + + relative_url(&out_css_path, out_dir) +} + +fn concat_files( + root_dir: &Path, + out_dir: &Path, + files: &[&str], + directory: &str, + extension: &str, +) -> anyhow::Result { + let mut concatted = String::new(); + for filestem in files { + let vendor_path = root_dir + .join("static") + .join(directory) + .join(format!("{filestem}.{extension}")); + let contents = fs::read_to_string(vendor_path) + .with_context(|| anyhow::anyhow!("couldn't read vendor {extension}"))?; + concatted.push_str(&contents); + } + + let file_sha = format!("vendor_{}", hash_string(&concatted)); + let out_file_path = out_dir + .join("static") + .join(directory) + .join(format!("{file_sha}.{extension}")); + + write_file(Path::new(&out_file_path), concatted.as_bytes()) + .with_context(|| anyhow::anyhow!("couldn't write vendor {extension}"))?; + + relative_url(&out_file_path, out_dir) +} + +fn concat_vendor_css(root_dir: &Path, out_dir: &Path, files: Vec<&str>) -> anyhow::Result { + concat_files(root_dir, out_dir, &files, "styles", "css") +} + +fn concat_app_js(root_dir: &Path, out_dir: &Path, files: Vec<&str>) -> anyhow::Result { + concat_files(root_dir, out_dir, &files, "scripts", "js") +} + +#[derive(Serialize, Debug)] +pub struct CSSFiles { + app: String, + fonts: String, + vendor: String, +} + +#[derive(Serialize, Debug)] +pub struct JSFiles { + app: String, +} + +#[derive(Serialize, Debug)] +pub struct AssetFiles { + css: CSSFiles, + js: JSFiles, +} + +/// Compile all statics JS/CSS assets into the `out_dir` directory and return a structure +/// that holds paths to them, based on the passed `baseurl`. +pub fn compile_assets( + root_dir: &Path, + out_dir: &Path, + base_url: &str, +) -> anyhow::Result { + let app_css_file = compile_sass(root_dir, out_dir, "app", base_url)?; + let fonts_css_file = compile_sass(root_dir, out_dir, "fonts", base_url)?; + let vendor_css_file = concat_vendor_css(root_dir, out_dir, vec!["tachyons"])?; + let app_js_file = concat_app_js(root_dir, out_dir, vec!["tools-install"])?; + + Ok(AssetFiles { + css: CSSFiles { + app: format!("{base_url}/{app_css_file}"), + fonts: format!("{base_url}/{fonts_css_file}"), + vendor: format!("{base_url}/{vendor_css_file}"), + }, + js: JSFiles { + app: format!("{base_url}/{app_js_file}"), + }, + }) +} diff --git a/src/cache.rs b/src/cache.rs deleted file mode 100644 index ec5adb61d..000000000 --- a/src/cache.rs +++ /dev/null @@ -1,32 +0,0 @@ -use std::error::Error; -use std::future::Future; -use std::sync::Arc; -use std::time::Instant; - -use rocket::State; -use rocket::tokio::sync::RwLock; -use rocket::tokio::task; - -const CACHE_TTL_SECS: u64 = 120; - -pub type Cache = State>>; - -pub trait Cached: Send + Sync + Clone + 'static { - fn get_timestamp(&self) -> Instant; - fn fetch() -> impl Future>> + Send; - async fn get(cache: &Cache) -> Self { - let cached = cache.read().await.clone(); - let timestamp = cached.get_timestamp(); - if timestamp.elapsed().as_secs() > CACHE_TTL_SECS { - // Update the cache in the background - let cache: Arc<_> = cache.inner().clone(); - task::spawn(async move { - match Self::fetch().await { - Ok(data) => *cache.write().await = data, - Err(e) => eprintln!("failed to update cache: {e}"), - } - }); - } - cached - } -} diff --git a/src/caching.rs b/src/caching.rs deleted file mode 100644 index 0de9e88a1..000000000 --- a/src/caching.rs +++ /dev/null @@ -1,21 +0,0 @@ -use rocket::fs::NamedFile; -use rocket::http::{Header, hyper}; -use rocket::response::Responder; - -#[derive(Responder)] -pub struct CachedNamedFile { - file: NamedFile, - header: Header<'static>, -} - -impl CachedNamedFile { - pub fn max_age(file: NamedFile, max_age: u32) -> Self { - Self { - file, - header: Header::new( - hyper::header::CACHE_CONTROL.as_str(), - format!("max-age={max_age}"), - ), - } - } -} diff --git a/src/category.rs b/src/category.rs deleted file mode 100644 index 174ce0610..000000000 --- a/src/category.rs +++ /dev/null @@ -1,37 +0,0 @@ -use std::path::PathBuf; - -use rocket::request::FromParam; - -fn is_category(name: &str) -> bool { - let mut path = PathBuf::from("templates"); - path.push(name); - path.push("index.html.hbs"); - path.exists() -} - -pub struct Category { - name: String, -} - -impl Category { - pub fn name(&self) -> &str { - self.name.as_str() - } - - pub fn index(&self) -> String { - format!("{}/index", self.name()) - } -} - -impl<'r> FromParam<'r> for Category { - type Error = String; - - fn from_param(param: &'r str) -> Result { - let url = param.to_string(); - if is_category(&url) { - Ok(Category { name: url }) - } else { - Err(format!("No category called <{url}>")) - } - } -} diff --git a/src/fs.rs b/src/fs.rs new file mode 100644 index 000000000..06bc864f1 --- /dev/null +++ b/src/fs.rs @@ -0,0 +1,25 @@ +use anyhow::Context; +use std::path::Path; + +pub fn ensure_directory(path: &Path) -> anyhow::Result<()> { + if let Some(parent) = path.parent() { + std::fs::create_dir_all(parent).with_context(|| { + anyhow::anyhow!("Could not create parent directory for {}", path.display()) + })?; + } + Ok(()) +} + +pub fn copy_dir_all(src: impl AsRef, dst: impl AsRef) -> std::io::Result<()> { + std::fs::create_dir_all(&dst)?; + for entry in std::fs::read_dir(src)? { + let entry = entry?; + let ty = entry.file_type()?; + if ty.is_dir() { + copy_dir_all(entry.path(), dst.as_ref().join(entry.file_name()))?; + } else { + std::fs::copy(entry.path(), dst.as_ref().join(entry.file_name()))?; + } + } + Ok(()) +} diff --git a/src/headers.rs b/src/headers.rs deleted file mode 100644 index 79e2e38ee..000000000 --- a/src/headers.rs +++ /dev/null @@ -1,46 +0,0 @@ -use rocket::fairing::{Fairing, Info, Kind}; -use rocket::http::{ContentType, Header}; -use rocket::{Request, Response}; - -static HEADERS: &[(&str, &str)] = &[ - ("x-xss-protection", "1; mode=block"), - ("strict-transport-security", "max-age=63072000"), - ("x-content-type-options", "nosniff"), - ( - "referrer-policy", - "no-referrer, strict-origin-when-cross-origin", - ), -]; - -static HEADER_CSP_NORMAL: &str = "default-src 'self'; frame-ancestors 'self'; img-src 'self' avatars.githubusercontent.com; frame-src 'self' player.vimeo.com"; -static HEADER_CSP_SVG: &str = - "default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'none'"; -static HEADER_CSP_PONTOON: &str = "default-src 'self' pontoon.rust-lang.org pontoon.mozilla.org; frame-ancestors 'self' pontoon.rust-lang.org; img-src 'self' avatars.githubusercontent.com pontoon.rust-lang.org pontoon.mozilla.org; frame-src 'self' pontoon.rust-lang.org player.vimeo.com"; - -pub(crate) struct InjectHeaders; - -#[rocket::async_trait] -impl Fairing for InjectHeaders { - fn info(&self) -> Info { - Info { - name: "HTTP headers injector", - kind: Kind::Response, - } - } - - async fn on_response<'r>(&self, _request: &'r Request<'_>, response: &mut Response<'r>) { - for (key, value) in HEADERS { - response.set_header(Header::new(*key, *value)); - } - let csp = if response.content_type() == Some(ContentType::SVG) { - // SVGs adhere to Content Security Policy, and they often include inline styles. - // This uses a custom CSP when the Content-Type is SVG. - HEADER_CSP_SVG - } else if *super::PONTOON_ENABLED { - HEADER_CSP_PONTOON - } else { - HEADER_CSP_NORMAL - }; - response.set_header(Header::new("content-security-policy", csp)); - } -} diff --git a/src/i18n.rs b/src/i18n.rs index 3b2eb75cf..b868201f4 100644 --- a/src/i18n.rs +++ b/src/i18n.rs @@ -1,11 +1,11 @@ -use rocket_dyn_templates::handlebars::{ +use handlebars::{ Context, Handlebars, Helper, HelperDef, HelperResult, Output, RenderContext, RenderErrorReason, }; -use rocket::request::FromParam; use serde::Serialize; use std::{collections::HashSet, sync::LazyLock}; +use crate::ENGLISH; use handlebars_fluent::{ fluent_bundle::{FluentResource, FluentValue, concurrent::FluentBundle}, loader::SimpleLoader, @@ -216,7 +216,7 @@ impl HelperDef for TeamHelper { let team_name = team.as_json()["name"].as_str().unwrap(); // English uses the team data directly, so that it gets autoupdated - if lang == "en-US" { + if lang == ENGLISH { let english = param.english(team.as_json()); out.write(english) .map_err(|e| RenderErrorReason::NestedError(Box::new(e)))?; @@ -235,17 +235,3 @@ impl HelperDef for TeamHelper { Ok(()) } } - -pub struct SupportedLocale(pub String); - -impl<'r> FromParam<'r> for SupportedLocale { - type Error = (); - - fn from_param(param: &'r str) -> Result { - if SUPPORTED_LOCALES.contains(param) { - Ok(SupportedLocale(param.parse().map_err(|_| ())?)) - } else { - Err(()) - } - } -} diff --git a/src/main.rs b/src/main.rs index a7d5c270a..c086eae17 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,453 +1,119 @@ -mod cache; -mod caching; -mod category; -mod headers; +#![allow(unused)] + +use crate::assets::compile_assets; +use crate::i18n::{TeamHelper, create_loader}; +use crate::redirect::create_redirects; +use crate::render::{RenderCtx, render_directory, render_governance, render_index}; +use crate::rust_version::fetch_rust_version; +use crate::teams::{encode_zulip_stream, load_rust_teams}; +use anyhow::Context; +use handlebars::{DirectorySourceOptions, Handlebars}; +use handlebars_fluent::FluentHelper; +use std::path::{Path, PathBuf}; + +mod assets; +mod fs; mod i18n; mod redirect; +mod render; mod rust_version; mod teams; -use cache::Cache; -use cache::Cached; -use rocket::catch; -use rocket::get; -use rocket::tokio::sync::RwLock; -use rust_version::RustVersion; -use serde::Serialize; -use teams::RustTeams; -use teams::encode_zulip_stream; - -use std::collections::hash_map::DefaultHasher; -use std::env; -use std::fs; -use std::hash::Hasher; -use std::path::{Path, PathBuf}; -use std::sync::Arc; -use std::sync::LazyLock; - -use rocket::{ - fs::NamedFile, - http::Status, - request::{FromParam, Request}, - response::{Redirect, content}, -}; -use rocket_dyn_templates::Template; - -use sass_rs::{Options, compile_file}; - -use category::Category; - -use caching::CachedNamedFile; -use handlebars_fluent::{FluentHelper, loader::Loader}; -use i18n::{EXPLICIT_LOCALE_INFO, LocaleInfo, SupportedLocale, TeamHelper, create_loader}; - const ZULIP_DOMAIN: &str = "https://rust-lang.zulipchat.com"; -static ASSETS: LazyLock = LazyLock::new(|| { - let app_css_file = compile_sass("app"); - let fonts_css_file = compile_sass("fonts"); - let vendor_css_file = concat_vendor_css(vec!["tachyons"]); - let app_js_file = concat_app_js(vec!["tools-install"]); - - AssetFiles { - css: CSSFiles { - app: app_css_file, - fonts: fonts_css_file, - vendor: vendor_css_file, - }, - js: JSFiles { app: app_js_file }, - } -}); -static PONTOON_ENABLED: LazyLock = LazyLock::new(|| env::var("RUST_WWW_PONTOON").is_ok()); -static ROBOTS_TXT_DISALLOW_ALL: LazyLock = - LazyLock::new(|| env::var("ROBOTS_TXT_DISALLOW_ALL").is_ok()); - -#[derive(Serialize)] -struct Context { - page: String, - title: String, - parent: &'static str, - is_landing: bool, - data: T, - lang: String, - baseurl: String, - pontoon_enabled: bool, - assets: &'static AssetFiles, - locales: &'static [LocaleInfo], - is_translation: bool, -} - -impl Context { - fn new(page: &str, title_id: &str, is_landing: bool, data: T, lang: String) -> Self { - let helper = create_loader(); - let title = if title_id.is_empty() { - "".into() - } else { - let lang = lang.parse().expect("lang should be valid"); - helper.lookup(&lang, title_id, None) - }; - Self { - page: page.to_owned(), - title, - parent: LAYOUT, - is_landing, - data, - baseurl: baseurl(&lang), - is_translation: lang != "en-US", - lang, - pontoon_enabled: *PONTOON_ENABLED, - assets: &ASSETS, - locales: EXPLICIT_LOCALE_INFO, - } - } -} - -#[derive(Clone, Serialize)] -struct CSSFiles { - app: String, - fonts: String, - vendor: String, -} -#[derive(Clone, Serialize)] -struct JSFiles { - app: String, -} -#[derive(Clone, Serialize)] -struct AssetFiles { - css: CSSFiles, - js: JSFiles, -} - static LAYOUT: &str = "components/layout"; static ENGLISH: &str = "en-US"; -fn baseurl(lang: &str) -> String { - if lang == "en-US" { - String::new() - } else { - format!("/{lang}") - } -} - -#[get("/logos/", rank = 1)] -async fn logos(file: PathBuf) -> Option { - NamedFile::open(Path::new("static/logos").join(file)) - .await - .ok() - .map(|file| CachedNamedFile::max_age(file, 3600)) +/// Relative base url from the root of the website +/// `url` can be e.g. `` or `/foo-bar`. +struct BaseUrl { + url: String, } -#[get("/static/", rank = 1)] -async fn files(file: PathBuf) -> Option { - NamedFile::open(Path::new("static/").join(file)) - .await - .ok() - .map(|file| CachedNamedFile::max_age(file, 3600)) -} - -#[get("/robots.txt", rank = 1)] -fn robots_txt() -> Option> { - if *ROBOTS_TXT_DISALLOW_ALL { - Some(content::RawText("User-agent: *\nDisallow: /")) - } else { - None +impl BaseUrl { + fn new(url: &str) -> Self { + let url = url.strip_suffix('/').unwrap_or(url).to_string(); + Self { url } } -} - -#[get("/")] -async fn index(version_cache: &Cache) -> Template { - render_index(ENGLISH.into(), version_cache).await -} - -#[get("/", rank = 3)] -async fn index_locale(locale: SupportedLocale, version_cache: &Cache) -> Template { - render_index(locale.0, version_cache).await -} - -#[get("/")] -fn category_en(category: Category) -> Template { - render_category(category, ENGLISH.into()) -} - -#[get("//", rank = 9)] -fn category_locale(category: Category, locale: SupportedLocale) -> Template { - render_category(category, locale.0) -} - -#[get("/governance")] -async fn governance(teams_cache: &Cache) -> Result { - render_governance(ENGLISH.into(), teams_cache).await -} - -#[get("/governance/
/", rank = 2)] -async fn team( - section: &str, - team: &str, - teams_cache: &Cache, -) -> Result { - render_team(section, team, ENGLISH.into(), teams_cache).await -} - -#[get("//governance", rank = 8)] -async fn governance_locale( - locale: SupportedLocale, - teams_cache: &Cache, -) -> Result { - render_governance(locale.0, teams_cache).await -} - -#[get("//governance/
/", rank = 12)] -async fn team_locale( - section: &str, - team: &str, - locale: SupportedLocale, - teams_cache: &Cache, -) -> Result { - render_team(section, team, locale.0, teams_cache).await -} - -#[get("//", rank = 4)] -fn subject(category: Category, subject: &str) -> Result { - render_subject(category, subject, ENGLISH.into()) -} - -#[get("///", rank = 14)] -fn subject_locale( - category: Category, - subject: &str, - locale: SupportedLocale, -) -> Result { - render_subject(category, subject, locale.0) -} - -#[get("/en-US", rank = 1)] -fn redirect_bare_en_us() -> Redirect { - Redirect::permanent("/") -} - -#[get("/.well-known/security.txt")] -fn well_known_security() -> &'static str { - include_str!("../static/text/well_known_security.txt") -} -#[catch(404)] -#[allow(clippy::result_large_err)] -fn not_found(req: &Request) -> Result { - if let Some(redirect) = crate::redirect::maybe_redirect(req.uri().path()) { - return Err(redirect); + fn get(&self) -> &str { + &self.url } - let lang = if let Some(next) = req.uri().path().segments().next() { - if let Ok(lang) = SupportedLocale::from_param(next) { - lang.0 + fn resolve_translated(&self, lang: &str) -> String { + if lang == ENGLISH { + self.url.clone() } else { - ENGLISH.into() + format!("{}/{lang}", self.url) } - } else { - ENGLISH.into() - }; - - Ok(not_found_locale(lang)) -} - -#[catch(422)] -#[allow(clippy::result_large_err)] -fn unprocessable_content(req: &Request) -> Result { - not_found(req) -} - -fn not_found_locale(lang: String) -> Template { - let page = "404"; - let context = Context::new(page, "error404-page-title", false, (), lang); - Template::render(page, context) -} - -#[catch(500)] -fn catch_error() -> Template { - not_found_locale(ENGLISH.into()) -} - -fn hash_css(css: &str) -> String { - let mut hasher = DefaultHasher::new(); - hasher.write(css.as_bytes()); - hasher.finish().to_string() -} - -fn compile_sass(filename: &str) -> String { - let scss_file = format!("./src/styles/{filename}.scss"); - - let css = compile_file(&scss_file, Options::default()) - .unwrap_or_else(|_| panic!("couldn't compile sass: {}", &scss_file)); - - let css_sha = format!("{}_{}", filename, hash_css(&css)); - let css_file = format!("./static/styles/{css_sha}.css"); - - fs::write(&css_file, css.into_bytes()) - .unwrap_or_else(|_| panic!("couldn't write css file: {}", &css_file)); - - String::from(&css_file[1..]) -} - -fn concat_vendor_css(files: Vec<&str>) -> String { - let mut concatted = String::new(); - for filestem in files { - let vendor_path = format!("./static/styles/{filestem}.css"); - let contents = fs::read_to_string(vendor_path).expect("couldn't read vendor css"); - concatted.push_str(&contents); } - - let css_sha = format!("vendor_{}", hash_css(&concatted)); - let css_path = format!("./static/styles/{}.css", &css_sha); - - fs::write(&css_path, &concatted).expect("couldn't write vendor css"); - - String::from(&css_path[1..]) -} - -fn concat_app_js(files: Vec<&str>) -> String { - let mut concatted = String::new(); - for filestem in files { - let vendor_path = format!("./static/scripts/{filestem}.js"); - let contents = fs::read_to_string(vendor_path).expect("couldn't read app js"); - concatted.push_str(&contents); - } - - let js_sha = format!("app_{}", hash_css(&concatted)); - let js_path = format!("./static/scripts/{}.js", &js_sha); - - fs::write(&js_path, &concatted).expect("couldn't write app js"); - - String::from(&js_path[1..]) } -async fn render_index(lang: String, version_cache: &Cache) -> Template { - #[derive(Serialize)] - struct IndexData { - rust_version: String, - } - - let page = "index"; - let data = IndexData { - rust_version: rust_version::rust_version(version_cache).await, +fn setup_handlebars() -> anyhow::Result> { + let mut handlebars: Handlebars<'static> = Handlebars::new(); + handlebars.set_strict_mode(true); + + let mut options = DirectorySourceOptions::default(); + options.tpl_extension = ".html.hbs".to_string(); + handlebars + .register_templates_directory("templates", options) + .context("cannot register template directory")?; + + let loader = create_loader(); + let helper = FluentHelper::new(loader); + handlebars.register_helper("fluent", Box::new(helper)); + handlebars.register_helper("team-text", Box::new(TeamHelper::new())); + handlebars.register_helper("encode-zulip-stream", Box::new(encode_zulip_stream)); + Ok(handlebars) +} + +fn main() -> anyhow::Result<()> { + // It is possible to set a base URL for the web. + // This should set to the path under which the web is hosted. + // For example, if the web is hosted at https://foo.bar/rust-web/, then BASE_URL should be set + // to "/rust-web". + // This is mainly useful to host the website e.g. on GitHub pages without a custom CNAME. + let base_url = std::env::var("BASE_URL").unwrap_or_else(|_| "".to_string()); + assert!(base_url.is_empty() || base_url.starts_with("/")); + let base_url = BaseUrl::new(&base_url); + + let rust_version = fetch_rust_version()?; + let teams = load_rust_teams()?; + + // Prepare build directory + let output_dir = PathBuf::from("build"); + let _ = std::fs::remove_dir_all(&output_dir); + std::fs::create_dir_all(&output_dir)?; + + let root_dir = Path::new("."); + let assets = compile_assets(root_dir, &output_dir, &base_url.get())?; + let handlebars = setup_handlebars()?; + + let ctx = RenderCtx { + template_dir: root_dir.join("templates"), + fluent_loader: create_loader(), + assets, + rust_version, + teams, + handlebars, + output_dir, + base_url, }; - let context = Context::new(page, "", true, data, lang); - Template::render(page, context) -} - -fn render_category(category: Category, lang: String) -> Template { - let page = category.index(); - let title_id = format!("{}-page-title", category.name()); - let context = Context::new(category.name(), &title_id, false, (), lang); - - Template::render(page, context) -} - -async fn render_governance( - lang: String, - teams_cache: &Cache, -) -> Result { - match teams::index_data(teams_cache).await { - Ok(data) => { - let page = "governance/index"; - let context = Context::new(page, "governance-page-title", false, data, lang); - - Ok(Template::render(page, context)) - } - Err(err) => { - eprintln!("error while loading the governance page: {err}"); - Err(Status::InternalServerError) - } - } -} - -async fn render_team( - section: &str, - team: &str, - lang: String, - teams_cache: &Cache, -) -> Result { - match teams::page_data(section, team, teams_cache).await { - Ok(data) => { - let page = "governance/group"; - let name = format!("governance-team-{}-name", data.team.name); - let context = Context::new(page, &name, false, data, lang); - Ok(Template::render(page, context)) - } - Err(err) => { - if err.is::() { - Err(Status::NotFound) - } else { - eprintln!("error while loading the team page: {err}"); - Err(Status::InternalServerError) - } - } - } -} - -fn render_subject(category: Category, subject: &str, lang: String) -> Result { - // Rocket's Template::render method is not really designed to accept arbitrary templates: if a - // template is missing, it just returns a Status::InternalServerError, without a way to - // distinguish it from a syntax error in the template itself. - // - // To work around the problem we check whether the template exists beforehand. - let path = Path::new("templates") - .join(category.name()) - .join(format!("{subject}.html.hbs")); - if !path.is_file() { - return Err(Status::NotFound); - } - - let page = format!("{}/{}", category.name(), subject); - let title_id = format!("{}-{}-page-title", category.name(), subject); - let context = Context::new(subject, &title_id, false, (), lang); - - Ok(Template::render(page, context)) -} - -#[rocket::launch] -async fn rocket() -> _ { - let templating = Template::custom(|engine| { - engine - .handlebars - .register_helper("fluent", Box::new(FluentHelper::new(create_loader()))); - engine - .handlebars - .register_helper("team-text", Box::new(TeamHelper::new())); - engine - .handlebars - .register_helper("encode-zulip-stream", Box::new(encode_zulip_stream)); - }); - - let rust_version = RustVersion::fetch().await.unwrap_or_default(); - let teams = RustTeams::fetch().await.unwrap_or_default(); - - rocket::build() - .attach(templating) - .attach(headers::InjectHeaders) - .manage(Arc::new(RwLock::new(rust_version))) - .manage(Arc::new(RwLock::new(teams))) - .mount( - "/", - rocket::routes![ - index, - category_en, - governance, - team, - subject, - files, - robots_txt, - logos, - index_locale, - category_locale, - governance_locale, - team_locale, - subject_locale, - redirect_bare_en_us, - well_known_security, - ], - ) - .register( - "/", - rocket::catchers![not_found, unprocessable_content, catch_error], - ) + ctx.copy_asset_dir("static", "static")?; + ctx.copy_asset_file( + "static/text/well_known_security.txt", + ".well-known/security.txt", + )?; + + render_index(&ctx)?; + render_governance(&ctx)?; + render_directory(&ctx, "community")?; + render_directory(&ctx, "learn")?; + render_directory(&ctx, "policies")?; + render_directory(&ctx, "tools")?; + render_directory(&ctx, "what")?; + ctx.page("404", "", &(), ENGLISH).render("404.html")?; + create_redirects(&ctx)?; + + Ok(()) } diff --git a/src/redirect.rs b/src/redirect.rs index 74f751a3e..15e8cc9dd 100644 --- a/src/redirect.rs +++ b/src/redirect.rs @@ -1,10 +1,7 @@ use crate::i18n::SUPPORTED_LOCALES; -use rocket::http::uri::Path; -use rocket::response::Redirect; +use crate::render::RenderCtx; -static PAGE_REDIRECTS: &[(&str, &str)] = &[ - // Migrate pre-2018 locale for the index page - ("", ""), +pub static PAGE_REDIRECTS: &[(&str, &str)] = &[ // Pre-2018 website pages ("community.html", "community"), ("conduct.html", "policies/code-of-conduct"), @@ -47,15 +44,15 @@ static PAGE_REDIRECTS: &[(&str, &str)] = &[ ("governance/wgs", "governance#working-groups"), ]; -static STATIC_FILES_REDIRECTS: &[(&str, &str)] = &[ +pub static STATIC_FILES_REDIRECTS: &[(&str, &str)] = &[ // Pre-2018 whitepaper locations ( "pdfs/Rust-npm-Whitepaper.pdf", - "/static/pdfs/Rust-npm-Whitepaper.pdf", + "static/pdfs/Rust-npm-Whitepaper.pdf", ), ( "pdfs/Rust-Tilde-Whitepaper.pdf", - "/static/pdfs/Rust-Tilde-Whitepaper.pdf", + "static/pdfs/Rust-Tilde-Whitepaper.pdf", ), ]; @@ -84,52 +81,58 @@ static PRE_2018_LOCALES: &[&str] = &[ "ru-RU", "sv-SE", "vi-VN", ]; -pub(crate) fn maybe_redirect(path: Path) -> Option { - let path = path.segments().collect::>().join("/"); - - if let Some((_, dest)) = STATIC_FILES_REDIRECTS.iter().find(|(src, _)| src == &path) { - return Some(Redirect::permanent(*dest)); +pub fn create_redirects(ctx: &RenderCtx) -> anyhow::Result<()> { + // Static file redirects, no need to support languages + // We cannot really make non-HTML redirects easily, so we just duplicate the file contents + // under both paths. + for (src, dst) in STATIC_FILES_REDIRECTS { + ctx.copy_asset_file(dst, src)?; } - let (locale, path) = if let Some((first, rest)) = path.split_once('/') { - if SUPPORTED_LOCALES.contains(&first) { - (Locale::Present(first), rest) - // After the 2018 website redesign some of the locales were removed and some were - // renamed (removing the country code). This handles both cases, either calculating the - // renamed locale or marking the locale as "specified but missing", which triggers a - // temporary redirect instead of a permanent redirect. - } else if PRE_2018_LOCALES.contains(&first) { - if let Some(locale) = convert_locale_from_pre_2018(first) { - (Locale::Present(locale), rest) - } else { - (Locale::SpecifiedButMissing, rest) - } - } else { - (Locale::NotSpecified, path.as_str()) - } - } else if PRE_2018_LOCALES.contains(&path.as_str()) { - // If the whole path is a pre-2018 locale handle it as a localized index page. - if let Some(locale) = convert_locale_from_pre_2018(&path) { - (Locale::Present(locale), "") - } else { - (Locale::SpecifiedButMissing, "") - } - } else { - (Locale::NotSpecified, path.as_str()) - }; - - if let Some((_, dest)) = EXTERNAL_REDIRECTS.iter().find(|(src, _)| *src == path) { - Some(Redirect::permanent(*dest)) - } else if let Some((_, dest)) = PAGE_REDIRECTS.iter().find(|(src, _)| *src == path) { - let dest = format!("/{dest}"); - match locale { - Locale::Present("en-US") | Locale::NotSpecified => Some(Redirect::permanent(dest)), - Locale::Present(locale) => Some(Redirect::permanent(format!("/{locale}{dest}"))), - Locale::SpecifiedButMissing => Some(Redirect::temporary(dest)), - } - } else { - None - } + // if let Some((_, dest)) = STATIC_FILES_REDIRECTS.iter().find(|(src, _)| src == &path) { + // return Some(Redirect::permanent(*dest)); + // } + // + // let (locale, path) = if let Some((first, rest)) = path.split_once('/') { + // if SUPPORTED_LOCALES.contains(&first) { + // (Locale::Present(first), rest) + // // After the 2018 website redesign some of the locales were removed and some were + // // renamed (removing the country code). This handles both cases, either calculating the + // // renamed locale or marking the locale as "specified but missing", which triggers a + // // temporary redirect instead of a permanent redirect. + // } else if PRE_2018_LOCALES.contains(&first) { + // if let Some(locale) = convert_locale_from_pre_2018(first) { + // (Locale::Present(locale), rest) + // } else { + // (Locale::SpecifiedButMissing, rest) + // } + // } else { + // (Locale::NotSpecified, path.as_str()) + // } + // } else if PRE_2018_LOCALES.contains(&path.as_str()) { + // // If the whole path is a pre-2018 locale handle it as a localized index page. + // if let Some(locale) = convert_locale_from_pre_2018(&path) { + // (Locale::Present(locale), "") + // } else { + // (Locale::SpecifiedButMissing, "") + // } + // } else { + // (Locale::NotSpecified, path.as_str()) + // }; + // + // if let Some((_, dest)) = EXTERNAL_REDIRECTS.iter().find(|(src, _)| *src == path) { + // Some(Redirect::permanent(*dest)) + // } else if let Some((_, dest)) = PAGE_REDIRECTS.iter().find(|(src, _)| *src == path) { + // let dest = format!("/{dest}"); + // match locale { + // Locale::Present("en-US") | Locale::NotSpecified => Some(Redirect::permanent(dest)), + // Locale::Present(locale) => Some(Redirect::permanent(format!("/{locale}{dest}"))), + // Locale::SpecifiedButMissing => Some(Redirect::temporary(dest)), + // } + // } else { + // None + // } + Ok(()) } fn convert_locale_from_pre_2018(pre_2018: &str) -> Option<&str> { diff --git a/src/render.rs b/src/render.rs new file mode 100644 index 000000000..994b146a8 --- /dev/null +++ b/src/render.rs @@ -0,0 +1,280 @@ +use crate::assets::AssetFiles; +use crate::fs::{copy_dir_all, ensure_directory}; +use crate::i18n::{EXPLICIT_LOCALE_INFO, LocaleInfo, SUPPORTED_LOCALES}; +use crate::rust_version::RustVersion; +use crate::teams::{PageData, RustTeams}; +use crate::{BaseUrl, ENGLISH, LAYOUT}; +use anyhow::Context; +use handlebars::Handlebars; +use handlebars_fluent::{Loader, SimpleLoader}; +use serde::Serialize; +use std::ffi::OsStr; +use std::fs::File; +use std::io::BufWriter; +use std::path::{Path, PathBuf}; + +#[derive(Serialize)] +pub struct TemplateCtx<'a, T: Serialize> { + page: String, + title: String, + parent: &'static str, + is_landing: bool, + data: &'a T, + lang: String, + /// Base URL for the current page, e.g. /foo/bar + /// This includes translations, so it can be also /foo/bar/es + baseurl: String, + /// Base URL for the current page, e.g. /foo/bar + /// This **does not** include translations, and is used for the <...>/static links. + baseurl_assets: String, + assets: &'a AssetFiles, + locales: &'static [LocaleInfo], + is_translation: bool, +} + +pub struct PageCtx<'a, T: Serialize> { + template_ctx: TemplateCtx<'a, T>, + output_dir: &'a Path, + handlebars: &'a Handlebars<'a>, +} + +impl<'a, T: Serialize> PageCtx<'a, T> { + fn make_landing(mut self) -> Self { + self.template_ctx.is_landing = true; + self + } + + pub fn render>(self, dst_path: P) -> anyhow::Result<()> { + let path = dst_path.as_ref(); + let template = &self.template_ctx.page; + + let out_path = self.output_dir.join(path); + ensure_directory(&out_path)?; + let mut output_file = BufWriter::new( + File::create(&out_path) + .with_context(|| anyhow::anyhow!("Cannot create file at {}", path.display()))?, + ); + eprintln!("Rendering `{template}` into {}", out_path.display()); + + self.handlebars + .render_to_write(template, &self.template_ctx, &mut output_file) + .with_context(|| { + anyhow::anyhow!( + "cannot render template {template} into {}", + out_path.display() + ) + })?; + Ok(()) + } +} + +pub struct RenderCtx<'a> { + pub handlebars: Handlebars<'a>, + pub template_dir: PathBuf, + pub fluent_loader: SimpleLoader, + pub output_dir: PathBuf, + pub rust_version: RustVersion, + pub teams: RustTeams, + pub assets: AssetFiles, + pub base_url: BaseUrl, +} + +impl<'a> RenderCtx<'a> { + pub fn page( + &'a self, + page: &str, + title_id: &str, + data: &'a T, + lang: &str, + ) -> PageCtx<'a, T> { + let title = if title_id.is_empty() { + "".into() + } else { + let lang = lang.parse().expect("lang should be valid"); + self.fluent_loader.lookup(&lang, title_id, None) + }; + PageCtx { + template_ctx: TemplateCtx { + page: page.to_string(), + title, + parent: LAYOUT, + is_landing: false, + data, + baseurl: self.base_url.resolve_translated(lang), + baseurl_assets: self.base_url.get().to_string(), + is_translation: lang != ENGLISH, + lang: lang.to_string(), + assets: &self.assets, + locales: EXPLICIT_LOCALE_INFO, + }, + output_dir: &self.output_dir, + handlebars: &self.handlebars, + } + } + + pub fn copy_asset_dir>(&self, src_dir: P, dst_dir: P) -> anyhow::Result<()> { + let dst = self.output_dir.join(dst_dir.as_ref()); + println!( + "Copying static asset directory from {} to {}", + src_dir.as_ref().display(), + dst.display() + ); + copy_dir_all(src_dir.as_ref(), dst)?; + Ok(()) + } + + pub fn copy_asset_file>(&self, src: P, dst: P) -> anyhow::Result<()> { + let dst = self.output_dir.join(dst.as_ref()); + println!( + "Copying static asset file from {} to {}", + src.as_ref().display(), + dst.display() + ); + ensure_directory(&dst)?; + std::fs::copy(src.as_ref(), dst)?; + Ok(()) + } +} + +/// Calls `func` for all supported languages. +/// Passes it the destination path into which should a given page be rendered, and the language +/// in which it should be rendered. +pub fn for_all_langs(dst_path: &str, func: F) -> anyhow::Result<()> +where + F: Fn(&str, &str) -> anyhow::Result<()>, +{ + for lang in SUPPORTED_LOCALES.iter() { + let path = match lang { + l if *l == ENGLISH => dst_path.to_string(), + l => format!("{l}/{dst_path}"), + }; + func(&path, lang).with_context(|| anyhow::anyhow!("could not handle language {lang}"))?; + } + Ok(()) +} + +pub fn render_index(render_ctx: &RenderCtx) -> anyhow::Result<()> { + #[derive(Serialize)] + struct IndexData { + rust_version: String, + } + let data = IndexData { + rust_version: render_ctx.rust_version.0.clone(), + }; + for_all_langs("index.html", |path, lang| { + render_ctx + .page("index", "", &data, lang) + .make_landing() + .render(path) + }) +} + +pub fn render_governance(render_ctx: &RenderCtx) -> anyhow::Result<()> { + let data = render_ctx.teams.index_data(); + + for_all_langs("governance/index.html", |dst_path, lang| { + render_ctx + .page("governance/index", "governance-page-title", &data, lang) + .render(dst_path) + })?; + for team in data.teams { + let data: PageData = render_ctx + .teams + .page_data(team.section, &team.page_name) + .unwrap_or_else(|error| panic!("Page data for team {team:?} not found: {error:?}")); + + // We need to render into index.html to have an extensionless URL + for_all_langs( + &format!("governance/{}/index.html", team.url), + |dst_path, lang| { + render_ctx + .page( + "governance/group", + &format!("governance-team-{}-name", team.team.name), + &data, + lang, + ) + .render(dst_path) + }, + )?; + } + + Ok(()) +} + +/// Render all templates found in the given directory. +pub fn render_directory(render_ctx: &RenderCtx, category: &str) -> anyhow::Result<()> { + for dir in std::fs::read_dir(render_ctx.template_dir.join(category))? { + let path = dir?.path(); + if path.is_file() && path.extension() == Some(OsStr::new("hbs")) { + // foo.html.hbs => foo + let subject = path + .file_stem() + .unwrap() + .to_str() + .unwrap() + .split(".") + .next() + .unwrap(); + + // The "root" page of a category + if subject == "index" { + for_all_langs(&format!("{category}/index.html"), |dst_path, lang| { + render_ctx + .page( + &format!("{category}/index"), + &format!("{category}-page-title"), + &(), + lang, + ) + .render(dst_path) + })?; + } else { + // A subpage (subject) of the category + // We need to render the page into a subdirectory, so that /foo/bar works without + // needing a HTML suffix. + for_all_langs( + &format!("{category}/{subject}/index.html"), + |dst_path, lang| { + render_ctx + .page( + &format!("{category}/{subject}"), + &format!("{category}-{subject}-page-title"), + &(), + lang, + ) + .render(dst_path) + }, + )?; + } + } + } + Ok(()) +} + +pub fn render_redirect(render_ctx: &RenderCtx, from: &str, to: &str) -> anyhow::Result<()> { + #[derive(Serialize)] + struct Data { + url: String, + } + + let url = if !to.starts_with("http") { + format!("/{to}") + } else { + to.to_string() + }; + let data = Data { url }; + + let from = if Path::new(from).extension().is_none() { + // We need to add /index.html to make the extensionless URL work + format!("{from}/index.html") + } else { + from.to_string() + }; + + println!("Redirecting {from} to {to}"); + render_ctx + .page("redirect", "", &data, ENGLISH) + .make_landing() + .render(from) +} diff --git a/src/rust_version.rs b/src/rust_version.rs index e1ce547cf..299c9ae9c 100644 --- a/src/rust_version.rs +++ b/src/rust_version.rs @@ -1,60 +1,22 @@ -use std::env; -use std::error::Error; -use std::time::Instant; - -use crate::cache::{Cache, Cached}; - static MANIFEST_URL: &str = "https://static.rust-lang.org/dist/channel-rust-stable.toml"; -enum FetchTarget { - Manifest, -} - -async fn fetch(target: FetchTarget) -> Result> { - let proxy_env = env::var("http_proxy") - .or_else(|_| env::var("HTTPS_PROXY")) - .ok(); - - let client = match proxy_env { - Some(proxy_env) => { - let proxy = reqwest::Proxy::https(proxy_env).unwrap(); - reqwest::ClientBuilder::new().proxy(proxy).build().unwrap() - } - None => reqwest::Client::new(), - }; - - let url = match target { - FetchTarget::Manifest => MANIFEST_URL, - }; - - Ok(client.get(url).send().await?) -} - #[derive(Debug, Clone)] -pub struct RustVersion(pub String, pub Instant); - -impl Default for RustVersion { - fn default() -> Self { - Self(Default::default(), Instant::now()) +pub struct RustVersion(pub String); + +/// Fetch the latest stable version of Rust. +pub fn fetch_rust_version() -> anyhow::Result { + println!("Downloading Rust version"); + let mut response = ureq::get(MANIFEST_URL).call()?; + if !response.status().is_success() { + return Err(anyhow::anyhow!( + "Failed to download Rust version (HTTP status {}): {}", + response.status(), + response.body_mut().read_to_string()? + )); } -} - -impl Cached for RustVersion { - fn get_timestamp(&self) -> Instant { - self.1 - } - async fn fetch() -> Result> { - let manifest = fetch(FetchTarget::Manifest) - .await? - .text() - .await? - .parse::()?; - let rust_version = manifest["pkg"]["rust"]["version"].as_str().unwrap(); - let version: String = rust_version.split(' ').next().unwrap().to_owned(); - Ok(RustVersion(version, Instant::now())) - } -} -pub async fn rust_version(version_cache: &Cache) -> String { - RustVersion::get(version_cache).await.0 + let manifest: toml::Value = toml::from_str(&response.body_mut().read_to_string()?)?; + let rust_version = manifest["pkg"]["rust"]["version"].as_str().unwrap(); + let version: String = rust_version.split(' ').next().unwrap().to_owned(); + Ok(RustVersion(version)) } diff --git a/src/styles/fonts.scss b/src/styles/fonts.scss index 0b940d2f7..f73e4a511 100644 --- a/src/styles/fonts.scss +++ b/src/styles/fonts.scss @@ -119,7 +119,7 @@ $format-names: ( @function urls($filename, $range, $extensions) { $urls: (); @each $extension in $extensions { - $url: url("/static/fonts/#{$extension}/#{$filename}.#{$range}.#{$extension}"); + $url: url("$BASEURL/static/fonts/#{$extension}/#{$filename}.#{$range}.#{$extension}"); $format: format(map-get($format-names, $extension)); $urls: append($urls, $url $format, comma); diff --git a/src/teams.rs b/src/teams.rs index bc0c65f28..853732fb6 100644 --- a/src/teams.rs +++ b/src/teams.rs @@ -1,72 +1,73 @@ -use percent_encoding::{AsciiSet, NON_ALPHANUMERIC, utf8_percent_encode}; -use rocket_dyn_templates::handlebars::{ +use handlebars::{ Context, Handlebars, Helper, HelperResult, Output, RenderContext, RenderErrorReason, }; +use percent_encoding::{AsciiSet, NON_ALPHANUMERIC, utf8_percent_encode}; use rust_team_data::v1::{BASE_URL, Team, TeamKind, Teams}; use serde::Serialize; use std::cmp::Reverse; use std::collections::HashMap; use std::error::Error; use std::fmt; -use std::time::Instant; -use crate::cache::{Cache, Cached}; - -#[derive(Default, Serialize)] -pub struct IndexData { - teams: Vec, -} +const ENCODING_SET: AsciiSet = NON_ALPHANUMERIC.remove(b'-').remove(b'_'); -#[derive(Serialize)] -struct IndexTeam { - #[serde(flatten)] - team: Team, - url: String, -} +pub fn encode_zulip_stream( + h: &Helper, + _: &Handlebars, + _: &Context, + _: &mut RenderContext, + out: &mut dyn Output, +) -> HelperResult { + let zulip_stream = if let Some(p) = h.param(0) { + p.value() + } else { + return Err(RenderErrorReason::ParamNotFoundForIndex( + "{{encode-zulip-stream takes 1 parameter}}", + 0, + ) + .into()); + }; + let zulip_stream = if let Some(s) = zulip_stream.as_str() { + s + } else { + return Err(RenderErrorReason::ParamTypeMismatchForName( + "encode-zulip-stream", + "0".into(), + "string".into(), + ) + .into()); + }; -#[derive(Serialize)] -pub struct PageData { - pub team: Team, - zulip_domain: &'static str, - subteams: Vec, - wgs: Vec, - project_groups: Vec, - // Marker teams and other kinds of groups that have a website entry - other_teams: Vec, -} + // https://github.com/zulip/zulip/blob/159641bab8c248f5b72a4e736462fb0b48e7fa24/static/js/hash_util.js#L20-L25 + let stream_encoded = utf8_percent_encode(zulip_stream, &ENCODING_SET) + .to_string() + .replace('%', "."); -#[derive(Clone)] -struct Data { - teams: Vec, + out.write(&stream_encoded)?; + Ok(()) } -const ENCODING_SET: AsciiSet = NON_ALPHANUMERIC.remove(b'-').remove(b'_'); - -impl Data { - async fn load(teams_cache: &Cache) -> Result> { - Ok(Data { - teams: RustTeams::get(teams_cache) - .await - .0 - .ok_or_else(|| Box::::from("failed to load teams"))?, - }) - } +#[derive(Debug, Clone)] +pub struct RustTeams(pub Vec); +impl RustTeams { #[cfg(test)] fn dummy(teams: Vec) -> Self { - Data { teams } + RustTeams(teams) } - fn index_data(self) -> Result> { - let mut data = IndexData::default(); - - self.teams + pub fn index_data(&self) -> IndexData { + let mut teams = self + .0 + .clone() .into_iter() .filter(|team| team.website_data.is_some()) // On the main page, show the leadership-council and all top-level // teams. .filter(|team| team.kind == TeamKind::Team && team.subteam_of.is_none()) .map(|team| IndexTeam { + section: kind_to_str(team.kind), + page_name: team.website_data.clone().unwrap().page, url: format!( "{}/{}", kind_to_str(team.kind), @@ -74,24 +75,23 @@ impl Data { ), team, }) - .for_each(|team| data.teams.push(team)); + .collect::>(); - data.teams.sort_by_key(|index_team| { + teams.sort_by_key(|index_team| { Reverse(index_team.team.website_data.as_ref().unwrap().weight) }); - Ok(data) + IndexData { teams } } - pub fn page_data( - self, - section: &str, - team_name: &str, - ) -> Result> { + pub fn page_data(&self, section: &str, team_page_name: &str) -> anyhow::Result { + let teams = self.0.clone(); + // Find the main team first - let main_team = self - .teams + let main_team = teams .iter() - .filter(|team| team.website_data.as_ref().map(|ws| ws.page.as_str()) == Some(team_name)) + .filter(|team| { + team.website_data.as_ref().map(|ws| ws.page.as_str()) == Some(team_page_name) + }) .find(|team| kind_to_str(team.kind) == section) .cloned() .ok_or(TeamNotFound)?; @@ -116,13 +116,12 @@ impl Data { let mut project_groups = Vec::new(); let mut other_teams = Vec::new(); - let superteams: HashMap<_, _> = self - .teams + let superteams: HashMap<_, _> = teams .iter() .filter_map(|team| Some((team.name.clone(), team.subteam_of.clone()?))) .collect(); - self.teams + teams .into_iter() .filter(|team| team.website_data.is_some()) .filter(|team| { @@ -190,89 +189,49 @@ impl Data { } } -pub fn encode_zulip_stream( - h: &Helper, - _: &Handlebars, - _: &Context, - _: &mut RenderContext, - out: &mut dyn Output, -) -> HelperResult { - let zulip_stream = if let Some(p) = h.param(0) { - p.value() - } else { - return Err(RenderErrorReason::ParamNotFoundForIndex( - "{{encode-zulip-stream takes 1 parameter}}", - 0, - ) - .into()); - }; - let zulip_stream = if let Some(s) = zulip_stream.as_str() { - s - } else { - return Err(RenderErrorReason::ParamTypeMismatchForName( - "encode-zulip-stream", - "0".into(), - "string".into(), - ) - .into()); - }; - - // https://github.com/zulip/zulip/blob/159641bab8c248f5b72a4e736462fb0b48e7fa24/static/js/hash_util.js#L20-L25 - let stream_encoded = utf8_percent_encode(zulip_stream, &ENCODING_SET) - .to_string() - .replace('%', "."); - - out.write(&stream_encoded)?; - Ok(()) +#[derive(Serialize)] +pub struct IndexData { + pub teams: Vec, } -pub async fn index_data( - teams_cache: &Cache, -) -> Result> { - Data::load(teams_cache).await?.index_data() +#[derive(Serialize, Debug)] +pub struct IndexTeam { + #[serde(flatten)] + pub team: Team, + pub url: String, + pub section: &'static str, + pub page_name: String, } -pub async fn page_data( - section: &str, - team_name: &str, - teams_cache: &Cache, -) -> Result> { - Data::load(teams_cache).await?.page_data(section, team_name) +#[derive(Serialize)] +pub struct PageData { + team: Team, + zulip_domain: &'static str, + subteams: Vec, + wgs: Vec, + project_groups: Vec, + // Marker teams and other kinds of groups that have a website entry + other_teams: Vec, } -#[derive(Debug, Clone)] -pub struct RustTeams(pub Option>, pub Instant); +pub fn load_rust_teams() -> anyhow::Result { + println!("Downloading Team API data"); -impl Default for RustTeams { - fn default() -> Self { - Self(Default::default(), Instant::now()) + let mut response = ureq::get(format!("{BASE_URL}/teams.json")).call()?; + if !response.status().is_success() { + return Err(anyhow::anyhow!( + "Failed to download team API (HTTP status {}): {}", + response.status(), + response.body_mut().read_to_string()? + )); } -} -impl Cached for RustTeams { - fn get_timestamp(&self) -> Instant { - self.1 - } - async fn fetch() -> Result> { - let resp: Teams = reqwest::get(format!("{BASE_URL}/teams.json")) - .await? - .error_for_status()? - .json() - .await?; - - Ok(RustTeams( - Some( - resp.teams - .into_iter() - .map(|(_key, value)| value) - .collect::>(), - ), - Instant::now(), - )) - } + let resp: Teams = response.body_mut().read_json()?; + + Ok(RustTeams(resp.teams.into_values().collect())) } -fn kind_to_str(kind: TeamKind) -> &'static str { +pub(crate) fn kind_to_str(kind: TeamKind) -> &'static str { match kind { TeamKind::Team => "teams", TeamKind::WorkingGroup => "wgs", @@ -299,7 +258,7 @@ impl fmt::Display for TeamNotFound { #[cfg(test)] mod tests { - use super::{Data, TeamNotFound}; + use super::{RustTeams, TeamNotFound}; use rust_team_data::v1::{Team, TeamKind, TeamMember, TeamWebsite}; fn dummy_team(name: &str) -> Team { @@ -353,9 +312,9 @@ mod tests { fn test_index_data() { let mut foo = dummy_team("foo"); foo.kind = TeamKind::WorkingGroup; - let data = Data::dummy(vec![foo, dummy_team("bar")]); + let data = RustTeams::dummy(vec![foo, dummy_team("bar")]); - let res = data.index_data().unwrap(); + let res = data.index_data(); assert_eq!(res.teams.len(), 1); assert_eq!(res.teams[0].url, "teams/bar"); assert_eq!(res.teams[0].team.name, "bar"); @@ -365,9 +324,9 @@ mod tests { fn test_index_subteams_are_hidden() { let mut foo = dummy_team("foo"); foo.subteam_of = Some(String::new()); - let data = Data::dummy(vec![foo]); + let data = RustTeams::dummy(vec![foo]); - assert_eq!(data.index_data().unwrap().teams.len(), 0); + assert_eq!(data.index_data().teams.len(), 0); } #[test] @@ -390,7 +349,7 @@ mod tests { other_wg.subteam_of = Some("other".into()); other_wg.kind = TeamKind::WorkingGroup; - let data = Data::dummy(vec![ + let data = RustTeams::dummy(vec![ main, subteam, subteam2, @@ -419,7 +378,7 @@ mod tests { let foo = dummy_team("foo"); let mut bar = dummy_team("bar"); bar.kind = TeamKind::WorkingGroup; - let data = Data::dummy(vec![foo, bar]); + let data = RustTeams::dummy(vec![foo, bar]); assert!( data.clone() @@ -447,7 +406,7 @@ mod tests { fn test_subteams_cant_be_loaded() { let mut foo = dummy_team("foo"); foo.subteam_of = Some("bar".into()); - let data = Data::dummy(vec![foo, dummy_team("bar")]); + let data = RustTeams::dummy(vec![foo, dummy_team("bar")]); assert!( data.page_data("teams", "foo") diff --git a/static/scripts/languages.js b/static/scripts/languages.js index bcacd4391..8e23fa1d3 100644 --- a/static/scripts/languages.js +++ b/static/scripts/languages.js @@ -12,11 +12,25 @@ function langChange() { } else { lang = `/${lang}`; } + + // Base URL of the web, without a leading slash. + // For example "" or "/foo/bar". + let base_url = window.RUST_BASE_URL; + + // If we have a path like /foo/bar///, we want to extract only + // // let path = window.location.pathname; + // Remove /foo/bar + if (path.startsWith(base_url)) { + path = path.slice(base_url.length); + } + // Remove / if (current_lang != "en-US") { - path = `/${window.location.pathname.split('/').slice(2).join('/')}`; + path = path.slice(current_lang.length + 1); // +1 for leading / } - window.location = `${lang}${path}`; + + // Now reconstruct back /foo/bar + window.location = `${base_url}${lang}${path}`; } nav_dropdown.onchange = langChange; diff --git a/templates/404.html.hbs b/templates/404.html.hbs index e2e252718..24285a699 100644 --- a/templates/404.html.hbs +++ b/templates/404.html.hbs @@ -7,7 +7,7 @@

{{fluent "error404-subtitle"}}

- {{fluent "error404-img-alt"}} + {{fluent "error404-img-alt"}}
diff --git a/templates/community/index.html.hbs b/templates/community/index.html.hbs index ef90ebf9c..a802feff8 100644 --- a/templates/community/index.html.hbs +++ b/templates/community/index.html.hbs @@ -170,7 +170,7 @@ - {{fluent + {{fluent
diff --git a/templates/components/footer.html.hbs b/templates/components/footer.html.hbs index 38f1ac9cf..dae0ca34e 100644 --- a/templates/components/footer.html.hbs +++ b/templates/components/footer.html.hbs @@ -33,13 +33,13 @@

{{fluent "footer-social"}}

- {{fluent {{fluent + src="{{baseurl_assets}}/static/images/bluesky.svg" alt="{{fluent "bluesky"}}" title="{{fluent "bluesky"}}" /> {{fluent - github logo + github logo
diff --git a/templates/components/layout.html.hbs b/templates/components/layout.html.hbs index a85ebcab4..3b4ed812e 100644 --- a/templates/components/layout.html.hbs +++ b/templates/components/layout.html.hbs @@ -28,20 +28,20 @@ - + - - - - - - + + + + + + - + {{#if is_landing}} @@ -52,10 +52,15 @@ {{/if}} + + - - + + {{> components/nav}} @@ -63,9 +68,6 @@ {{~> page}} {{> components/footer}} - {{#if pontoon_enabled}} - - {{/if}} - + diff --git a/templates/components/nav.html.hbs b/templates/components/nav.html.hbs index e8311d871..5d5df4b5c 100644 --- a/templates/components/nav.html.hbs +++ b/templates/components/nav.html.hbs @@ -1,7 +1,7 @@
{{/inline}} diff --git a/templates/learn/index.html.hbs b/templates/learn/index.html.hbs index 75dc864df..06cb8eba8 100644 --- a/templates/learn/index.html.hbs +++ b/templates/learn/index.html.hbs @@ -154,7 +154,7 @@
- {{fluent
@@ -168,7 +168,7 @@
- {{fluent
@@ -184,7 +184,7 @@
- {{fluent
diff --git a/templates/redirect.html.hbs b/templates/redirect.html.hbs new file mode 100644 index 000000000..e828aecf3 --- /dev/null +++ b/templates/redirect.html.hbs @@ -0,0 +1,6 @@ + + + + Redirecting to {{ data.url }}... + +