From 1683af87f63d66d538f37bfc61401f92f3ffe692 Mon Sep 17 00:00:00 2001 From: zopsicle Date: Wed, 30 Apr 2025 19:12:35 +0200 Subject: [PATCH 01/21] Add copyright notice to LICENSE-MIT --- LICENSE-MIT | 2 ++ 1 file changed, 2 insertions(+) diff --git a/LICENSE-MIT b/LICENSE-MIT index 31aa79387..47e8d61a8 100644 --- a/LICENSE-MIT +++ b/LICENSE-MIT @@ -1,3 +1,5 @@ +Copyright 2025 The Rust Programming Language Team + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the From 2daf37d3af84656f4f2febc4cd95f63b2806d909 Mon Sep 17 00:00:00 2001 From: zopsicle Date: Wed, 30 Apr 2025 21:50:03 +0200 Subject: [PATCH 02/21] Match copyright notices with those in rust-lang/rust --- LICENSE-APACHE | 2 +- LICENSE-MIT | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LICENSE-APACHE b/LICENSE-APACHE index d88f6f26c..4c45d9d1a 100644 --- a/LICENSE-APACHE +++ b/LICENSE-APACHE @@ -186,7 +186,7 @@ APPENDIX: How to apply the Apache License to your work. same "printed page" as the copyright notice for easier identification within third-party archives. -Copyright 2018 The Rust Programming Language Team +Copyright (c) The Rust Project Contributors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/LICENSE-MIT b/LICENSE-MIT index 47e8d61a8..a2070c4be 100644 --- a/LICENSE-MIT +++ b/LICENSE-MIT @@ -1,4 +1,4 @@ -Copyright 2025 The Rust Programming Language Team +Copyright (c) The Rust Project Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated From 246b098ccf76d2c1690304c363bb114af3a5fe11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 17 May 2025 11:03:39 +0200 Subject: [PATCH 03/21] Include marker and unknown teams with a website section Before, they were not shown on the website, even though they had a website section in `team`. --- src/teams.rs | 7 ++++++- templates/governance/group.html.hbs | 7 +++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/teams.rs b/src/teams.rs index 24bd5c4c3..23a9983f4 100644 --- a/src/teams.rs +++ b/src/teams.rs @@ -31,6 +31,8 @@ pub struct PageData { subteams: Vec, wgs: Vec, project_groups: Vec, + // Marker teams and other kinds of groups that have a website entry + other_teams: Vec, } #[derive(Clone)] @@ -112,6 +114,7 @@ impl Data { let mut raw_subteams = Vec::new(); let mut wgs = Vec::new(); let mut project_groups = Vec::new(); + let mut other_teams = Vec::new(); let superteams: HashMap<_, _> = self .teams @@ -142,12 +145,13 @@ impl Data { TeamKind::Team => raw_subteams.push(team), TeamKind::WorkingGroup => wgs.push(team), TeamKind::ProjectGroup => project_groups.push(team), - _ => {} + TeamKind::MarkerTeam | TeamKind::Unknown => other_teams.push(team), }); raw_subteams.sort_by_key(|team| Reverse(team.website_data.as_ref().unwrap().weight)); wgs.sort_by_key(|team| Reverse(team.website_data.as_ref().unwrap().weight)); project_groups.sort_by_key(|team| Reverse(team.website_data.as_ref().unwrap().weight)); + other_teams.sort_by_key(|team| Reverse(team.website_data.as_ref().unwrap().weight)); // Lay out subteams according to their hierarchy. // Superteams come first and subteams come after, recursively. @@ -181,6 +185,7 @@ impl Data { subteams, wgs, project_groups, + other_teams, }) } } diff --git a/templates/governance/group.html.hbs b/templates/governance/group.html.hbs index c36ee8d7f..dd67bcec5 100644 --- a/templates/governance/group.html.hbs +++ b/templates/governance/group.html.hbs @@ -26,6 +26,13 @@ {{/each}} {{/if}} +{{#if data.other_teams}} +
+ {{#each data.other_teams as |team|}} + {{> governance/group-team}} + {{/each}} +
+{{/if}} {{/inline}} {{~> (lookup this "parent")~}} From 5fb95f65f779acfabdb0b1e9689c9779aaa4b60b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Jun 2025 06:49:23 +0000 Subject: [PATCH 04/21] Bump tar-fs from 3.0.8 to 3.0.9 Bumps [tar-fs](https://github.com/mafintosh/tar-fs) from 3.0.8 to 3.0.9. - [Commits](https://github.com/mafintosh/tar-fs/compare/v3.0.8...v3.0.9) --- updated-dependencies: - dependency-name: tar-fs dependency-version: 3.0.9 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 23d36e1a3..b48a81de2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2768,9 +2768,9 @@ } }, "node_modules/tar-fs": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.8.tgz", - "integrity": "sha512-ZoROL70jptorGAlgAYiLoBLItEKw/fUxg9BSYK/dF/GAGYFJOJJJMvjPAKDJraCXFwadD456FCuvLWgfhMsPwg==", + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.9.tgz", + "integrity": "sha512-XF4w9Xp+ZQgifKakjZYmFdkLoSWd34VGKcsTCwlNWM7QG3ZbaxnTsaBwnjFZqHRf/rROxaR8rXnbtwdvaDI+lA==", "dev": true, "license": "MIT", "dependencies": { From ac83ff4eff42bb7370d2a88310053e16d544a056 Mon Sep 17 00:00:00 2001 From: TrueNorthNinja Date: Fri, 6 Jun 2025 14:49:36 -0400 Subject: [PATCH 05/21] Added Zed to the Tools -> First-class Editor Support and updated the CSS to be 3 item grid on large. --- locales/de/tools.ftl | 1 + locales/en-US/tools.ftl | 5 +++-- locales/es/tools.ftl | 1 + locales/fa/tools.ftl | 1 + locales/fr/tools.ftl | 1 + locales/it/tools.ftl | 1 + locales/ja/tools.ftl | 1 + locales/ko/tools.ftl | 1 + locales/pl/tools.ftl | 1 + locales/pt-BR/tools.ftl | 1 + locales/ru/tools.ftl | 1 + locales/tr/tools.ftl | 1 + locales/zh-CN/tools.ftl | 1 + locales/zh-TW/tools.ftl | 1 + templates/components/tools/editors.html.hbs | 20 ++++++++++++-------- 15 files changed, 28 insertions(+), 10 deletions(-) diff --git a/locales/de/tools.ftl b/locales/de/tools.ftl index 7c4f22dd4..63b043a88 100644 --- a/locales/de/tools.ftl +++ b/locales/de/tools.ftl @@ -34,3 +34,4 @@ tools-editor-helix = Helix tools-editor-vim = Vim/Neovim tools-editor-emacs = Emacs tools-editor-visual-studio = Visual Studio +tools-editor-zed = Zed diff --git a/locales/en-US/tools.ftl b/locales/en-US/tools.ftl index 1885dd3ff..d0a4ac591 100644 --- a/locales/en-US/tools.ftl +++ b/locales/en-US/tools.ftl @@ -71,7 +71,7 @@ install-notes-getting-started-description = If you're just getting started with getting started page. install-notes-rustup-heading = Toolchain management with rustup -install-notes-rustup-description = +install-notes-rustup-description =

Rust is installed and managed by the rustup @@ -106,7 +106,7 @@ install-notes-uninstall-description = install-notes-path-heading = Configuring the PATH environment variable -install-notes-path-description = +install-notes-path-description =

In the Rust development environment, all tools are installed to the @@ -172,3 +172,4 @@ tools-editor-helix = Helix tools-editor-vim = Vim/Neovim tools-editor-emacs = Emacs tools-editor-visual-studio = Visual Studio +tools-editor-zed = Zed diff --git a/locales/es/tools.ftl b/locales/es/tools.ftl index 62ae6d246..7589b4116 100644 --- a/locales/es/tools.ftl +++ b/locales/es/tools.ftl @@ -122,3 +122,4 @@ tools-editor-helix = Helix tools-editor-vim = Vim/Neovim tools-editor-emacs = Emacs tools-editor-visual-studio = Visual Studio +tools-editor-zed = Zed diff --git a/locales/fa/tools.ftl b/locales/fa/tools.ftl index e523b960a..b8f44eb2c 100644 --- a/locales/fa/tools.ftl +++ b/locales/fa/tools.ftl @@ -26,3 +26,4 @@ tools-editor-helix = Helix tools-editor-vim = Vim/Neovim tools-editor-emacs = Emacs tools-editor-visual-studio = Visual Studio +tools-editor-zed = Zed diff --git a/locales/fr/tools.ftl b/locales/fr/tools.ftl index f45a43f6c..1664c76fa 100644 --- a/locales/fr/tools.ftl +++ b/locales/fr/tools.ftl @@ -109,3 +109,4 @@ tools-editor-helix = Helix tools-editor-vim = Vim/Neovim tools-editor-emacs = Emacs tools-editor-visual-studio = Visual Studio +tools-editor-zed = Zed diff --git a/locales/it/tools.ftl b/locales/it/tools.ftl index f6d686e50..0c07edb1b 100644 --- a/locales/it/tools.ftl +++ b/locales/it/tools.ftl @@ -97,3 +97,4 @@ tools-editor-helix = Helix tools-editor-vim = Vim/Neovim tools-editor-emacs = Emacs tools-editor-visual-studio = Visual Studio +tools-editor-zed = Zed diff --git a/locales/ja/tools.ftl b/locales/ja/tools.ftl index c643e1bfd..e233bbf6c 100644 --- a/locales/ja/tools.ftl +++ b/locales/ja/tools.ftl @@ -98,3 +98,4 @@ tools-editor-helix = Helix tools-editor-vim = Vim/Neovim tools-editor-emacs = Emacs tools-editor-visual-studio = Visual Studio +tools-editor-zed = Zed diff --git a/locales/ko/tools.ftl b/locales/ko/tools.ftl index a62002a36..2afcc5d4d 100644 --- a/locales/ko/tools.ftl +++ b/locales/ko/tools.ftl @@ -61,3 +61,4 @@ tools-editor-helix = Helix tools-editor-vim = Vim/Neovim tools-editor-emacs = Emacs tools-editor-visual-studio = Visual Studio +tools-editor-zed = Zed diff --git a/locales/pl/tools.ftl b/locales/pl/tools.ftl index 7bd6b6354..537735e8c 100644 --- a/locales/pl/tools.ftl +++ b/locales/pl/tools.ftl @@ -45,3 +45,4 @@ tools-editor-helix = Helix tools-editor-vim = Vim/Neovim tools-editor-emacs = Emacs tools-editor-visual-studio = Visual Studio +tools-editor-zed = Zed diff --git a/locales/pt-BR/tools.ftl b/locales/pt-BR/tools.ftl index ee81445eb..485d4be07 100644 --- a/locales/pt-BR/tools.ftl +++ b/locales/pt-BR/tools.ftl @@ -147,3 +147,4 @@ tools-editor-helix = Helix tools-editor-vim = Vim/Neovim tools-editor-emacs = Emacs tools-editor-visual-studio = Visual Studio +tools-editor-zed = Zed diff --git a/locales/ru/tools.ftl b/locales/ru/tools.ftl index 25073f17b..cc18e665c 100644 --- a/locales/ru/tools.ftl +++ b/locales/ru/tools.ftl @@ -120,3 +120,4 @@ tools-editor-helix = Helix tools-editor-vim = Vim/Neovim tools-editor-emacs = Emacs tools-editor-visual-studio = Visual Studio +tools-editor-zed = Zed diff --git a/locales/tr/tools.ftl b/locales/tr/tools.ftl index b8b5dafd4..6459be9dd 100644 --- a/locales/tr/tools.ftl +++ b/locales/tr/tools.ftl @@ -131,3 +131,4 @@ tools-editor-helix = { ENGLISH("Helix") } tools-editor-vim = { ENGLISH("Vim/Neovim") } tools-editor-emacs = { ENGLISH("Emacs") } tools-editor-visual-studio = { ENGLISH("Visual Studio") } +tools-editor-zed = { ENGLISH("Zed") } diff --git a/locales/zh-CN/tools.ftl b/locales/zh-CN/tools.ftl index 4a00a9790..7e60069c9 100644 --- a/locales/zh-CN/tools.ftl +++ b/locales/zh-CN/tools.ftl @@ -134,3 +134,4 @@ tools-editor-helix = Helix tools-editor-vim = Vim/Neovim tools-editor-emacs = Emacs tools-editor-visual-studio = Visual Studio +tools-editor-zed = Zed diff --git a/locales/zh-TW/tools.ftl b/locales/zh-TW/tools.ftl index 99abe8fdd..04cce83e1 100644 --- a/locales/zh-TW/tools.ftl +++ b/locales/zh-TW/tools.ftl @@ -108,3 +108,4 @@ tools-editor-helix = Helix tools-editor-vim = Vim/Neovim tools-editor-emacs = Emacs tools-editor-visual-studio = Visual Studio +tools-editor-zed = Zed diff --git a/templates/components/tools/editors.html.hbs b/templates/components/tools/editors.html.hbs index e957ec1be..29a89e9c2 100644 --- a/templates/components/tools/editors.html.hbs +++ b/templates/components/tools/editors.html.hbs @@ -1,34 +1,38 @@

-
+ -
+ -
+ -
+ -
+ -
+ -
+ - From a75a9c90274b5859f115f8874c0989f349c6917a Mon Sep 17 00:00:00 2001 From: Remo Senekowitsch Date: Fri, 6 Jun 2025 23:04:02 +0200 Subject: [PATCH 06/21] Fix broken links on tools page rust-analyzer seems to have moved its documentation to mdbook and broke some links in the process. --- templates/components/tools/editors.html.hbs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/components/tools/editors.html.hbs b/templates/components/tools/editors.html.hbs index e957ec1be..e3dd24c64 100644 --- a/templates/components/tools/editors.html.hbs +++ b/templates/components/tools/editors.html.hbs @@ -12,7 +12,7 @@ class="button button-secondary">{{fluent "tools-editor-rover"}}
@@ -24,7 +24,7 @@ class="button button-secondary">{{fluent "tools-editor-sublime"}}
From a1382a23f07617c937f57bd29f7eebaa0033238d Mon Sep 17 00:00:00 2001 From: TrueNorthNinja Date: Fri, 6 Jun 2025 18:37:52 -0400 Subject: [PATCH 07/21] Removed Eclipse from the Editors page and locals references. --- locales/de/tools.ftl | 1 - locales/en-US/tools.ftl | 1 - locales/es/tools.ftl | 1 - locales/fa/tools.ftl | 1 - locales/fr/tools.ftl | 1 - locales/it/tools.ftl | 1 - locales/ja/tools.ftl | 1 - locales/ko/tools.ftl | 1 - locales/pl/tools.ftl | 1 - locales/pt-BR/tools.ftl | 1 - locales/ru/tools.ftl | 1 - locales/zh-CN/tools.ftl | 1 - locales/zh-TW/tools.ftl | 1 - templates/components/tools/editors.html.hbs | 20 ++++++++------------ 14 files changed, 8 insertions(+), 25 deletions(-) diff --git a/locales/de/tools.ftl b/locales/de/tools.ftl index 63b043a88..da2087fc6 100644 --- a/locales/de/tools.ftl +++ b/locales/de/tools.ftl @@ -29,7 +29,6 @@ tools-automation-cargo-doc-link = Zur Webseite tools-editor-vscode = VS Code tools-editor-sublime = Sublime Text tools-editor-rover = RustRover -tools-editor-eclipse = Eclipse tools-editor-helix = Helix tools-editor-vim = Vim/Neovim tools-editor-emacs = Emacs diff --git a/locales/en-US/tools.ftl b/locales/en-US/tools.ftl index d0a4ac591..00781f49c 100644 --- a/locales/en-US/tools.ftl +++ b/locales/en-US/tools.ftl @@ -167,7 +167,6 @@ tools-rustup-manual-default-windows = If you are running Windows,
download an tools-editor-vscode = VS Code tools-editor-sublime = Sublime Text tools-editor-rover = RustRover -tools-editor-eclipse = Eclipse tools-editor-helix = Helix tools-editor-vim = Vim/Neovim tools-editor-emacs = Emacs diff --git a/locales/es/tools.ftl b/locales/es/tools.ftl index 7589b4116..ab05e6aad 100644 --- a/locales/es/tools.ftl +++ b/locales/es/tools.ftl @@ -117,7 +117,6 @@ tools-rustup-manual-default-windows = Si usas Windows,
descarga y ejecuta télécharge tools-editor-vscode = VS Code tools-editor-sublime = Sublime Text tools-editor-rover = RustRover -tools-editor-eclipse = Eclipse tools-editor-helix = Helix tools-editor-vim = Vim/Neovim tools-editor-emacs = Emacs diff --git a/locales/it/tools.ftl b/locales/it/tools.ftl index 0c07edb1b..34031ee23 100644 --- a/locales/it/tools.ftl +++ b/locales/it/tools.ftl @@ -92,7 +92,6 @@ tools-rustup-manual-default-windows = Se stai usando Windows,
scarica ed eseg tools-editor-vscode = VS Code tools-editor-sublime = Sublime Text tools-editor-rover = RustRover -tools-editor-eclipse = Eclipse tools-editor-helix = Helix tools-editor-vim = Vim/Neovim tools-editor-emacs = Emacs diff --git a/locales/ja/tools.ftl b/locales/ja/tools.ftl index e233bbf6c..246c4de73 100644 --- a/locales/ja/tools.ftl +++ b/locales/ja/tools.ftl @@ -93,7 +93,6 @@ tools-rustup-manual-default-windows = Windows上であれば、
-
+ -
+ -
+ -
+ -
+ -
+ -
+ - -
+ From 9f9ef0a2b4a8716d3eadbb71c96e41984e1a96d9 Mon Sep 17 00:00:00 2001 From: TrueNorthNinja Date: Fri, 6 Jun 2025 18:40:01 -0400 Subject: [PATCH 08/21] Updating Zed Link --- templates/components/tools/editors.html.hbs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/components/tools/editors.html.hbs b/templates/components/tools/editors.html.hbs index fe3ca503e..42de70e06 100644 --- a/templates/components/tools/editors.html.hbs +++ b/templates/components/tools/editors.html.hbs @@ -28,7 +28,7 @@ class="button button-secondary">{{fluent "tools-editor-visual-studio"}}
From d997533fbc7dcc8668e2e5069c774ea338fe68da Mon Sep 17 00:00:00 2001 From: TrueNorthNinja Date: Sat, 7 Jun 2025 06:21:13 -0400 Subject: [PATCH 09/21] Removed Eclipse from TR locals file --- locales/tr/tools.ftl | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/locales/tr/tools.ftl b/locales/tr/tools.ftl index 6459be9dd..1075956d0 100644 --- a/locales/tr/tools.ftl +++ b/locales/tr/tools.ftl @@ -13,7 +13,7 @@ tools-build-description = bir tek komuta paketler. Şablon gerektirmez. tools-build-install-heading = Yükle tools-build-install-description = - Crates.io içindeki binlerce paket ile birlikte çok büyük + Crates.io içindeki binlerce paket ile birlikte çok büyük ihtimalle aradığınız çözüme sahip. Devlerin omuzlarında durun ve ekibinizi tekerrürden yeniliğe taşıyın. tools-build-test-heading = Test et @@ -26,7 +26,7 @@ tools-build-deploy-heading = Yayınla tools-build-deploy-description = cargo build kodu her platform için ekstra bilgi taşımayan ikili kod oluşturur. Kodunuz tek bir komutla Windows'u, - Linux'u, macOS'i ve webi hedef alabilir. Hepsi sipariş usulü yapı dosyalarına gerek + Linux'u, macOS'i ve webi hedef alabilir. Hepsi sipariş usulü yapı dosyalarına gerek olmadan modern bir arayüzün parçası. tools-automation-heading = Otomasyonla gelen hız tools-automation-description = @@ -41,12 +41,12 @@ tools-automation-rustfmt-link = Depoya git tools-automation-clippy-heading = Clippy tools-automation-clippy-description = “Görünüşe bakılırsa bir yineleyici - yazıyorsunuz.”
Clippy her seviyedeki geliştiriciye deyimsel kod + yazıyorsunuz.”
Clippy her seviyedeki geliştiriciye deyimsel kod yazmakta ve standartları uygulamakta yardımcı olur. tools-automation-clippy-link = Depoya git tools-automation-cargo-doc-heading = Cargo Belgeleri tools-automation-cargo-doc-description = - Cargo'nun belgelendirmecisi işinizi halleder. Bu da + Cargo'nun belgelendirmecisi işinizi halleder. Bu da hiçbir UPA'nın belgelendirmesiz ortaya çıkmamasını sağlar. cargo doc ile yerel olarak erişebilirsiniz ve docs.rs ile herkese açık cratelere çevrimiçi ulaşabilirsiniz. @@ -60,8 +60,8 @@ install-rustup32-button = rustup-init.exe indir rustup-init.exe indir (64-bit) install-notes-heading = Rust kurulumu hakkında notlar install-notes-getting-started-description = - Eğer Rust'a yeni başlıyorsanız ve daha - detaylı bir gidiş yolu arıyorsanız + Eğer Rust'a yeni başlıyorsanız ve daha + detaylı bir gidiş yolu arıyorsanız başlarken sayfamıza göz atın. install-notes-rustup-heading = Rustup ile araç zincirinin yönetimi install-notes-rustup-description = @@ -69,10 +69,10 @@ install-notes-rustup-description = Rust, rustup aracı ile yüklenir ve yönetilir. Rust'ın 6 haftalık hızlı yayımlama süreci - vardır ve + vardır ve çok sayıda platformu destekler. Bu yüzden her zaman Rust'ın birçok yapısı vardır. rustup Rust'ın desteklediği her platformda bu yapıları tutarlı bir şekilde - yönetir. Bu durum, Rust'ın beta ve nightly yayın kanallarından yüklenmesine ve farklı hedeflere + yönetir. Bu durum, Rust'ın beta ve nightly yayın kanallarından yüklenmesine ve farklı hedeflere derlenmesine katkıda bulunur.

@@ -126,7 +126,6 @@ tools-rustup-manual-default-windows = Eğer Windows kullanıyorsanız
Date: Mon, 2 Jun 2025 15:56:20 +0000 Subject: [PATCH 10/21] Remove discord from the website --- locales/de/common.ftl | 2 - locales/en-US/code-of-conduct.ftl | 2 +- locales/en-US/common.ftl | 2 - locales/en-US/community.ftl | 2 +- locales/en-US/governance.ftl | 1 - locales/en-US/teams.ftl | 3 - locales/es/code-of-conduct.ftl | 2 +- locales/es/common.ftl | 2 - locales/es/community.ftl | 2 +- locales/es/governance.ftl | 1 - locales/es/teams.ftl | 2 - locales/fa/common.ftl | 2 - locales/fa/governance.ftl | 1 - locales/fr/code-of-conduct.ftl | 2 +- locales/fr/common.ftl | 2 - locales/fr/community.ftl | 2 +- locales/fr/governance.ftl | 1 - locales/fr/teams.ftl | 2 - locales/it/code-of-conduct.ftl | 2 +- locales/it/common.ftl | 2 - locales/it/community.ftl | 2 +- locales/it/governance.ftl | 1 - locales/it/teams.ftl | 2 - locales/ja/code-of-conduct.ftl | 2 +- locales/ja/common.ftl | 2 - locales/ja/community.ftl | 2 +- locales/ja/governance.ftl | 1 - locales/ja/teams.ftl | 2 - locales/ko/common.ftl | 2 - locales/ko/community.ftl | 2 +- locales/ko/governance.ftl | 1 - locales/ko/teams.ftl | 1 - locales/pl/code-of-conduct.ftl | 2 +- locales/pl/common.ftl | 2 - locales/pl/community.ftl | 2 +- locales/pl/governance.ftl | 1 - locales/pl/teams.ftl | 2 - locales/pt-BR/code-of-conduct.ftl | 2 +- locales/pt-BR/common.ftl | 2 - locales/pt-BR/community.ftl | 2 +- locales/pt-BR/governance.ftl | 1 - locales/pt-BR/teams.ftl | 2 - locales/ru/code-of-conduct.ftl | 2 +- locales/ru/common.ftl | 2 - locales/ru/community.ftl | 2 +- locales/ru/governance.ftl | 1 - locales/ru/teams.ftl | 2 - locales/tr/code-of-conduct.ftl | 2 +- locales/tr/common.ftl | 2 - locales/tr/community.ftl | 2 +- locales/tr/governance.ftl | 1 - locales/tr/teams.ftl | 2 - locales/xx-AU/common.ftl | 1 - locales/xx-AU/governance.ftl | 1 - locales/xx-AU/teams.ftl | 2 - locales/zh-CN/code-of-conduct.ftl | 2 +- locales/zh-CN/common.ftl | 2 - locales/zh-CN/community.ftl | 2 +- locales/zh-CN/governance.ftl | 1 - locales/zh-CN/teams.ftl | 2 - locales/zh-TW/code-of-conduct.ftl | 2 +- locales/zh-TW/common.ftl | 2 - locales/zh-TW/community.ftl | 2 +- locales/zh-TW/governance.ftl | 1 - locales/zh-TW/teams.ftl | 2 - templates/community/index.html.hbs | 76 ++++++----- templates/components/footer.html.hbs | 19 ++- templates/governance/group-team.html.hbs | 156 ++++++++++++----------- 68 files changed, 155 insertions(+), 211 deletions(-) diff --git a/locales/de/common.ftl b/locales/de/common.ftl index 9c6da63bc..c76a81d0a 100644 --- a/locales/de/common.ftl +++ b/locales/de/common.ftl @@ -6,7 +6,6 @@ getting-started = Erste Schritte why-rust = Warum Rust? production-use = Im Einsatz learn-more = Mehr lesen -discord = Discord mastodon = Mastodon ## components/layout.hbs @@ -40,7 +39,6 @@ footer-social = Soziales footer-get-help = Hilfe bekommen! footer-youtube-alt = Twitter footer-alt-youtube = Youtube-Logo -footer-discord-alt = { discord } footer-github-alt = GitHub footer-attribution = Gepflegt vom Rust-Team. Fehler gefunden? diff --git a/locales/en-US/code-of-conduct.ftl b/locales/en-US/code-of-conduct.ftl index dbc0f7ada..27ce387d6 100644 --- a/locales/en-US/code-of-conduct.ftl +++ b/locales/en-US/code-of-conduct.ftl @@ -34,7 +34,7 @@ coc-moderation-description =

In the Rust community we strive to go the extra step to look out for each other. Don’t just aim to be technically unimpeachable, try to be your best self. In particular, avoid flirting with offensive or sensitive issues, particularly if they’re off-topic; this all too often leads to unnecessary fights, hurt feelings, and damaged trust; worse, it can drive people away from the community entirely.

And if someone takes issue with something you said or did, resist the urge to be defensive. Just stop doing what it was they complained about and apologize. Even if you feel you were misinterpreted or unfairly accused, chances are good there was something you could’ve communicated better — remember that it’s your responsibility to make your fellow Rustaceans comfortable. Everyone wants to get along and we are all here first and foremost because we want to talk about cool technology. You will find that people will be eager to assume good intent and forgive as long as you earn their trust.

-

The enforcement policies listed above apply to all official Rust venues; including Discord channels (https://discord.gg/rust-lang); GitHub repositories under rust-lang, rust-lang-nursery, and rust-lang-deprecated; and all forums under rust-lang.org (users.rust-lang.org, internals.rust-lang.org). For other projects adopting the Rust Code of Conduct, please contact the maintainers of those projects for enforcement. If you wish to use this code of conduct for your own project, consider explicitly mentioning your moderation policy or making a copy with your own moderation policy so as to avoid confusion.

+

The enforcement policies listed above apply to all official Rust venues; including Zulip channels (https://rust-lang.zulipchat.com/); GitHub repositories under rust-lang, rust-lang-nursery, and rust-lang-deprecated; and all forums under rust-lang.org (users.rust-lang.org, internals.rust-lang.org). For other projects adopting the Rust Code of Conduct, please contact the maintainers of those projects for enforcement. If you wish to use this code of conduct for your own project, consider explicitly mentioning your moderation policy or making a copy with your own moderation policy so as to avoid confusion.

Adapted from the Node.js Policy on Trolling as well as the Contributor Covenant v1.3.0.

coc-moderation-description-team-anchor-text = Rust moderation team diff --git a/locales/en-US/common.ftl b/locales/en-US/common.ftl index 4d2a8a576..c42ecb3ad 100644 --- a/locales/en-US/common.ftl +++ b/locales/en-US/common.ftl @@ -8,7 +8,6 @@ getting-started = Getting started why-rust = Why Rust? production-use = Production use learn-more = Learn More -discord = Discord zulip = Zulip mastodon = Mastodon bluesky = Bluesky @@ -56,7 +55,6 @@ footer-get-help = Get help! footer-youtube-alt = Twitter footer-alt-youtube = youtube logo -footer-discord-alt = { discord } footer-github-alt = GitHub footer-attribution = Maintained by the Rust Team. See a bug? diff --git a/locales/en-US/community.ftl b/locales/en-US/community.ftl index feba34b42..885391cf3 100644 --- a/locales/en-US/community.ftl +++ b/locales/en-US/community.ftl @@ -28,7 +28,7 @@ community-irlo = The Rust Internals Forum is a place for discussion about the as well as the design of the language and the standard library. community-chat-header = Chat platforms -community-chat = Development of Rust, and general chatter happens on several chat platforms. Check out general channels and more on the Rust Discord server, or check out the teams page to find where specific teams meet. +community-chat = Development of Rust, and general chatter happens on several chat platforms. Check out general channels and more on the Rust Zulip server, or check out the teams page to find where specific teams meet. community-teams-learn = Learn more about teams diff --git a/locales/en-US/governance.ftl b/locales/en-US/governance.ftl index 60d65ca79..c741fe4c0 100644 --- a/locales/en-US/governance.ftl +++ b/locales/en-US/governance.ftl @@ -17,7 +17,6 @@ governance-members = Members & Contacts ## governance/group-team.hbs governance-team-email = Email the { $teamname } governance-team-repository = { $teamname } repository -governance-team-discord = { $channel } on Discord governance-team-zulip = { $stream } on Zulip governance-team-matrix-room = { $room } on Matrix governance-user-github = GitHub: { $link } diff --git a/locales/en-US/teams.ftl b/locales/en-US/teams.ftl index 07dd667ac..22ec41671 100644 --- a/locales/en-US/teams.ftl +++ b/locales/en-US/teams.ftl @@ -77,9 +77,6 @@ governance-team-miri-description = Designing and implementing the Miri interpret governance-team-mods-name = Moderation team governance-team-mods-description = Helping uphold the code of conduct and community standards -governance-team-mods-discord-name = Discord moderators -governance-team-mods-discord-description = Moderating the Discord server - governance-team-mods-discourse-name = Discourse moderators governance-team-mods-discourse-description = Moderating users.rust-lang.org and internals.rust-lang.org diff --git a/locales/es/code-of-conduct.ftl b/locales/es/code-of-conduct.ftl index 8b9e3e4fe..c0b430be0 100644 --- a/locales/es/code-of-conduct.ftl +++ b/locales/es/code-of-conduct.ftl @@ -33,6 +33,6 @@ coc-moderation-description =

En la comunidad de Rust aspiramos a superarnos en cuanto cómo nos tratamos entre nosotros. No intentes mantenerte intachable solo en lo técnico, trata de dar lo mejor de tí. En particular, evita los temas sensibles u ofensivos, especialmente si no guardan relación: muy a menudo llevan a disputas innecesarias, agravios y pérdida de confianza; aún peor, pueden apartar a gente de la comunidad por completo.

Si alguien se muestra en desacuerdo con algo que digas o hagas, resiste el reflejo de ponerte a la defensiva. Simplemente para de hacer lo que fuera que provocó la queja y discúlpate. Incluso si crees que ha habido un malentendido o acusado injustamente, es probable que hubiera algo que podrías haber comunicado mejor; recuerda que es tu responsabilidad hacer que tus colegas Rustáceos se sientan cómodos. Todos queremos llevarnos bien y todos estamos aquí principalmente porque queremos hablar de una tecnología maravillosa. Te darás cuenta de que la gente tiende a asumir buena fé y a perdonar siempre que te ganes su cofianza.

-

Las políticas de moderación listadas más arriba se aplican en todos los canales oficiales de Rust, incluyendo canales en Discord (https://discord.gg/rust-lang), repositorios de GitHub bajo rust-lang, rust-lang-nursery y rust-lang-deprecated, y todos los foros bajo rust-lang.org (users.rust-lang.org, internals.rust-lang.org). En otros proyectos que adopten el código de conducta de Rust, contacta con sus encargados para su aplicación. Si quieres usar este código de conducta en tu propio proyecto, valora si mencionar tu política de moderación explícitamente o hacer una copia con tu propia política de moderación para evitar confusiones.

+

Las políticas de moderación listadas más arriba se aplican en todos los canales oficiales de Rust, incluyendo canales en Zulip (https://rust-lang.zulipchat.com/), repositorios de GitHub bajo rust-lang, rust-lang-nursery y rust-lang-deprecated, y todos los foros bajo rust-lang.org (users.rust-lang.org, internals.rust-lang.org). En otros proyectos que adopten el código de conducta de Rust, contacta con sus encargados para su aplicación. Si quieres usar este código de conducta en tu propio proyecto, valora si mencionar tu política de moderación explícitamente o hacer una copia con tu propia política de moderación para evitar confusiones.

Adaptado a partir de la Node.js Policy on Trolling así como del Contributor Covenant v1.3.0.

coc-moderation-description-team-anchor-text = Equipo de moderación de Rust diff --git a/locales/es/common.ftl b/locales/es/common.ftl index 419c37d0b..73d0a2dc1 100644 --- a/locales/es/common.ftl +++ b/locales/es/common.ftl @@ -6,7 +6,6 @@ getting-started = Comienza why-rust = ¿Por qué Rust? production-use = Uso en producción learn-more = Saber más -discord = Discord zulip = Zulip mastodon = Mastodon @@ -50,7 +49,6 @@ footer-social = Redes sociales footer-get-help = ¡Pide ayuda! footer-youtube-alt = Twitter footer-alt-youtube = logo de youtube -footer-discord-alt = { discord } footer-github-alt = GitHub footer-attribution = Mantenida por el equipo de Rust. ¿Hay algún error? diff --git a/locales/es/community.ftl b/locales/es/community.ftl index 2d0e2ccdc..109d5fbb1 100644 --- a/locales/es/community.ftl +++ b/locales/es/community.ftl @@ -29,7 +29,7 @@ community-irlo = community-chat-header = Plataformas de chat community-chat = Las charlas sobre el desarrollo de Rust y otros asuntos tienen lugar en diversos chats. - Echa un vistazo a los canales generales en el servidor de Discord de Rust, o a las páginas de los equipos si quieres averiguar dónde se comunican los miembros de un equipo específico. + Echa un vistazo a los canales generales en el servidor de Zulip de Rust, o a las páginas de los equipos si quieres averiguar dónde se comunican los miembros de un equipo específico. community-teams-learn = Saber más sobre los equipos community-events-header = Eventos community-meetup-header = Encuentra un meetup o una conferencia local diff --git a/locales/es/governance.ftl b/locales/es/governance.ftl index f199cdf8e..79da51af0 100644 --- a/locales/es/governance.ftl +++ b/locales/es/governance.ftl @@ -21,7 +21,6 @@ governance-members = Miembros y contactos governance-team-email = Escribe al { $teamname } governance-team-repository = Repositorio del { $teamname } -governance-team-discord = { $channel } en Discord governance-team-zulip = { $stream } en Zulip governance-user-github = GitHub: { $link } governance-user-team-leader = Líder del equipo diff --git a/locales/es/teams.ftl b/locales/es/teams.ftl index 53fb7d1ef..389e958e2 100644 --- a/locales/es/teams.ftl +++ b/locales/es/teams.ftl @@ -25,8 +25,6 @@ governance-team-wg-parallel-rustc-name = rustc paralelo governance-team-wg-parallel-rustc-description = Hacer que rustc compile en paralelo por defecto governance-team-wg-cli-name = Grupo de trabajo de interfaces de línea de comandos (CLI) governance-team-wg-cli-description = Centrarse en la experiencia integral de crear aplicaciones de CLI, grandes o pequeñas, en Rust. -governance-team-mods-discord-name = Moderadores de Discord -governance-team-mods-discord-description = Moderar el servidor de Discord governance-team-wg-compiler-performance-name = Rendimiento del compilador governance-team-wg-compiler-performance-description = Mejorar el rendimiento de rustc (tiempo de compilación). governance-team-community-content-name = Equipo de contenidos diff --git a/locales/fa/common.ftl b/locales/fa/common.ftl index 659713fca..0520bb614 100644 --- a/locales/fa/common.ftl +++ b/locales/fa/common.ftl @@ -4,7 +4,6 @@ rust = Rust get-started-exclamation = شروع کنید! why-rust = چرا Rust؟ learn-more = یادگیری بیشتر -discord = دیسکورد mastodon = Mastodon ## components/panels/domain.hbs @@ -38,7 +37,6 @@ footer-social = اجتماعی footer-get-help = کمک بگیر! footer-youtube-alt = توییتر footer-alt-youtube = لوگوی Youtube -footer-discord-alt = { discord } footer-github-alt = گیت هاب footer-old-site = به دنبال وب سایت قبلی هستید؟ diff --git a/locales/fa/governance.ftl b/locales/fa/governance.ftl index 62de7fc5a..014a1bfc1 100644 --- a/locales/fa/governance.ftl +++ b/locales/fa/governance.ftl @@ -15,7 +15,6 @@ governance-members = اعضا و مخاطبین ## governance/group-team.hbs governance-team-email = ایمیل کنید به { $teamname } -governance-team-discord = { $channel } در دیسکورد governance-user-github = گیت هاب: { $link } governance-user-team-leader = رهبر تیم governance-members-header = اعضا diff --git a/locales/fr/code-of-conduct.ftl b/locales/fr/code-of-conduct.ftl index eaba7ef9b..85e370cf7 100644 --- a/locales/fr/code-of-conduct.ftl +++ b/locales/fr/code-of-conduct.ftl @@ -37,6 +37,6 @@ coc-moderation-description =

Dans la communauté Rust, nous nous efforçons de nous occuper les uns des autres. N’essayez pas simplement d’être techniquement irréprochable, essayez de faire au mieux. En particulier, évitez de jouer avec des sujet offensants ou sensibles, en particulier si c’est hors-sujet; cela mène trop souvent à des disputes inutiles, des sentiments heurtés et une confiance endommagée; pire, cela peut faire totalement partir des gens de la communauté.

Et si une personne relève quelque chose que vous avez dit ou fait, ne soyez pas sur la défensive. Arrêtez simplement de faire ce qui vous a été reproché et excusez-vous. Même si vous pensez avoir été mal interprété ou accusé injustement, il y a probablement quelque chose que vous pourriez avoir mieux communiqué — rappelez-vous que c’est votre responsabilité de mettre à l’aise les autres Rustacé·e·s. Tout le monde veut bien s’entendre et nous sommes ici en premier lieu car nous voulons parler de technologie cool. Vous verrez que les gens accepteront votre bonne foi et vous pardonneront si vous faites en sorte de gagner leur confiance.

-

Les règles d’application listées ci-dessus s’appliquent à tous les lieux officiels de Rust; incluant les canaux Discord (https://discord.gg/rust-lang); les dépôts GitHub sous rust-lang, rust-lang-nursery et rust-lang-deprecated; et tous les forums sous rust-lang.org (users.rust-lang.org, internals.rust-lang.org). Pour les autres projets adoptant le code de conduite Rust, contactez la maintenance de ces projets pour son application. Si vous souhaitez utiliser ce code de conduite pour votre propre projet, envisagez de mentionner explicitement votre politique de modération ou faites une copie avec votre propre politique de modération pour éviter toute confusion.

+

Les règles d’application listées ci-dessus s’appliquent à tous les lieux officiels de Rust; incluant les canaux Zulip (https://rust-lang.zulipchat.com/); les dépôts GitHub sous rust-lang, rust-lang-nursery et rust-lang-deprecated; et tous les forums sous rust-lang.org (users.rust-lang.org, internals.rust-lang.org). Pour les autres projets adoptant le code de conduite Rust, contactez la maintenance de ces projets pour son application. Si vous souhaitez utiliser ce code de conduite pour votre propre projet, envisagez de mentionner explicitement votre politique de modération ou faites une copie avec votre propre politique de modération pour éviter toute confusion.

Adapté de la Node.js Policy on Trolling ainsi que du Contributor Covenant v1.3.0.

coc-moderation-description-team-anchor-text = L'équipe Rust de modération diff --git a/locales/fr/common.ftl b/locales/fr/common.ftl index 373b95f72..003030492 100644 --- a/locales/fr/common.ftl +++ b/locales/fr/common.ftl @@ -6,7 +6,6 @@ getting-started = Commencer why-rust = Pourquoi Rust ? production-use = Utilisation en production learn-more = En savoir plus -discord = Discord zulip = Zulip mastodon = Mastodon @@ -50,7 +49,6 @@ footer-social = Réseaux sociaux footer-get-help = Aidez-moi ! footer-youtube-alt = Twitter footer-alt-youtube = Logo YouTube -footer-discord-alt = { discord } footer-github-alt = GitHub footer-attribution = Maintenu par l’équipe de Rust. Vous avez trouvé une erreur ? Envoyez-nous une correction! footer-old-site = Vous cherchez l'ancien site web ? diff --git a/locales/fr/community.ftl b/locales/fr/community.ftl index 4dd96293d..47e874cc1 100644 --- a/locales/fr/community.ftl +++ b/locales/fr/community.ftl @@ -16,7 +16,7 @@ community-discourse-button = Visiter le forum community-irlo-header = Forum interne community-irlo = Le forum interne est un endroit pour discuter à propos du développement de Rust lui-même – en incluant le travail sur le compilateur, la conception du langage et la bibliothèque standard. community-chat-header = Plateformes de discussions -community-chat = Le développement de Rust ainsi que les discussions générales ont lieu sur diverses plateformes de chat. Consultez le contenu des canaux généraux et plus sur le serveur Discord de Rust, ou jetez un œil à la page des équipes pour découvrir où elles se rencontrent. +community-chat = Le développement de Rust ainsi que les discussions générales ont lieu sur diverses plateformes de chat. Consultez le contenu des canaux généraux et plus sur le serveur Zulip de Rust, ou jetez un œil à la page des équipes pour découvrir où elles se rencontrent. community-teams-learn = En savoir plus sur les équipes community-events-header = Événements community-meetup-header = Trouver une rencontre locale ou une conférence diff --git a/locales/fr/governance.ftl b/locales/fr/governance.ftl index 5c6faa875..80f9b0402 100644 --- a/locales/fr/governance.ftl +++ b/locales/fr/governance.ftl @@ -18,7 +18,6 @@ governance-members = Membres et contacts governance-team-email = Envoyer un email à { $teamname } governance-team-repository = dépôt de { $teamname } -governance-team-discord = { $channel } sur Discord governance-team-zulip = { $stream } dans Zulip governance-user-github = GitHub: { $link } governance-user-team-leader = Chef d'équipe diff --git a/locales/fr/teams.ftl b/locales/fr/teams.ftl index d9d7afece..63bae3b12 100644 --- a/locales/fr/teams.ftl +++ b/locales/fr/teams.ftl @@ -25,8 +25,6 @@ governance-team-wg-parallel-rustc-name = Parallélisation de rustc governance-team-wg-parallel-rustc-description = Faire de la compilation parallèle le fonctionnement par défaut de rustc governance-team-wg-cli-name = Interfaces en ligne de commande (CLI) governance-team-wg-cli-description = Concentrer nos efforts pour fournir une expérience complète d’écriture d’applications en ligne de commande en Rust, qu’il s’agisse de gros projets ou de plus modestes. -governance-team-mods-discord-name = Modérateurs Discord -governance-team-mods-discord-description = Modérer le serveur Discord governance-team-wg-compiler-performance-name = Performances du compilateur governance-team-wg-compiler-performance-description = Améliorer les performances (temps de compilation) de rustc governance-team-community-content-name = Équipe contenu diff --git a/locales/it/code-of-conduct.ftl b/locales/it/code-of-conduct.ftl index 139c1bbd3..5fd6f4565 100644 --- a/locales/it/code-of-conduct.ftl +++ b/locales/it/code-of-conduct.ftl @@ -33,6 +33,6 @@ coc-moderation-description =

Nella comunità di Rust ci impegniamo a fare quel passo in più per aiutarci a vicenda. Non mirare semplicemente a essere tecnicamente inoppugnabile, cerca di fare il tuo meglio. In particolare, evita di toccare tematiche offensive o sensibili, in particolare se sono fuori tema; questo porta troppo spesso a litigi inutili, danneggia la fiducia e i sentimenti; peggio ancora, può allontanare completamente le persone dalla comunità.

Se qualcuno mette in discussione qualcosa che hai detto o fatto, resisti all'impulso di metterti sulla difensiva. Semplicemente smettila di fare ciò che ha creato lamentele e scusati. Anche se ritieni di essere stato interpretato male o accusato ingiustamente, ci sono buone probabilità che avresti potuto comunicare meglio qualcosa - ricorda che è tua responsabilità mettere i tuoi amici Rustaceans a proprio agio. Tutti vogliono andare d'accordo e siamo qui prima di tutto perché vogliamo parlare di tecnologia. Scoprirai che le persone, man mano che guadagnerai la loro fiducia, saranno più propense a dare per assunto le tue buone intenzioni e a perdonare.

-

Le linee guida elencate qui sopra si applicano a tutte le sedi officiali di Rust; inclusi i canali Discord (https://discord.gg/rust-lang); i repository Github ospitati in rust-lang, rust-lang-nursery e rust-lang-deprecated e tutti i forum che fanno capo a rust-lang.org (users.rust-lang.org, internals.rust-lang.org). Per altri progetti che adottano il codice di condotta Rust, si prega di contattare i manutentori di tali progetti per far sì che sia applicato. Se desideri utilizzare questo codice di condotta per il tuo progetto, valuta se menzionare esplicitamente la tua policy di moderazione o di fare una copia con la tua propria policy di moderazione in modo da evitare confusione.

+

Le linee guida elencate qui sopra si applicano a tutte le sedi officiali di Rust; inclusi i canali Zulip (https://rust-lang.zulipchat.com/); i repository Github ospitati in rust-lang, rust-lang-nursery e rust-lang-deprecated e tutti i forum che fanno capo a rust-lang.org (users.rust-lang.org, internals.rust-lang.org). Per altri progetti che adottano il codice di condotta Rust, si prega di contattare i manutentori di tali progetti per far sì che sia applicato. Se desideri utilizzare questo codice di condotta per il tuo progetto, valuta se menzionare esplicitamente la tua policy di moderazione o di fare una copia con la tua propria policy di moderazione in modo da evitare confusione.

Adattamento della Node.js Policy on Trolling e del Contributor Covenant v1.3.0.

coc-moderation-description-team-anchor-text = Rust moderation team diff --git a/locales/it/common.ftl b/locales/it/common.ftl index ede9db0a4..acce300ae 100644 --- a/locales/it/common.ftl +++ b/locales/it/common.ftl @@ -6,7 +6,6 @@ getting-started = Per iniziare why-rust = Perché Rust? production-use = Uso in produzione learn-more = Scopri di più -discord = Discord zulip = Zulip mastodon = Mastodon @@ -50,7 +49,6 @@ footer-social = Social footer-get-help = Ricevi supporto! footer-youtube-alt = Twitter footer-alt-youtube = logo youtube -footer-discord-alt = { discord } footer-github-alt = GitHub footer-attribution = Mantenuto dal Team Rust. Vedi un errore? diff --git a/locales/it/community.ftl b/locales/it/community.ftl index 5fab9f1c4..2f38480ee 100644 --- a/locales/it/community.ftl +++ b/locales/it/community.ftl @@ -16,7 +16,7 @@ community-discourse-button = Visita il Forum community-irlo-header = Forum internals community-irlo = Il forum per gli "internals" di Rust è dedicato alle discussioni sullo sviluppo di Rust stesso: dal design del linguaggio e dalla libreria standard fino allo sviluppo del compilatore. community-chat-header = Piattaforme social -community-chat = Lo sviluppo di Rust e le discussioni in generale si tengono su molteplici piattaforme. Dai un'occhiata ai vari canali sul server Discord Rust, oppure visita la pagina per trovare i ritrovi dei vari team. +community-chat = Lo sviluppo di Rust e le discussioni in generale si tengono su molteplici piattaforme. Dai un'occhiata ai vari canali sul server Zulip Rust, oppure visita la pagina per trovare i ritrovi dei vari team. community-teams-learn = Scopri di più sui team community-events-header = Eventi community-meetup-header = Cerca una conferenza o un meetup locale diff --git a/locales/it/governance.ftl b/locales/it/governance.ftl index d8f87278a..69ac882e8 100644 --- a/locales/it/governance.ftl +++ b/locales/it/governance.ftl @@ -21,7 +21,6 @@ governance-members = Membri e Contatti governance-team-email = Manda un'email al { $teamname } governance-team-repository = repository { $teamname } -governance-team-discord = { $channel } su Discord governance-team-zulip = { $stream } su Zulip governance-user-github = GitHub: { $link } governance-user-team-leader = Team leader diff --git a/locales/it/teams.ftl b/locales/it/teams.ftl index 294403205..5b4481a38 100644 --- a/locales/it/teams.ftl +++ b/locales/it/teams.ftl @@ -25,8 +25,6 @@ governance-team-wg-parallel-rustc-name = rustc parallelo governance-team-wg-parallel-rustc-description = Parallelizzare di default la compilazione di rustc. governance-team-wg-cli-name = Gruppo di lavoro Command-line interfaces (CLI) governance-team-wg-cli-description = Si concentra sull'esperienza end-to-end per scrivere piccole e grandi applicazioni CLI in Rust. -governance-team-mods-discord-name = Moderatori Discord -governance-team-mods-discord-description = Moderazione del server Discord governance-team-wg-compiler-performance-name = Performance del compilatore governance-team-wg-compiler-performance-description = Migliorare le performance del compilatore rustc (tempi di compilazione) governance-team-community-content-name = Team Contenuti diff --git a/locales/ja/code-of-conduct.ftl b/locales/ja/code-of-conduct.ftl index 327a58685..7635ea8e0 100644 --- a/locales/ja/code-of-conduct.ftl +++ b/locales/ja/code-of-conduct.ftl @@ -33,6 +33,6 @@ coc-moderation-description =

Rustコミュニティでは、お互いに気を配るためのさらなる一歩を踏み出そうと努力しています。技術的に非の打ち所がないだけではなく、最高の自分になりましょう。特に、攻撃的あるいはセンシティブな問題、とりわけ話題から外れているような問題には触れないようにしてください。これは、非常に多くの場合、不必要な争い、感情の傷つき、そして信用の喪失につながるためです。さらに悪いことに、人々をコミュニティから完全に遠ざけてしまうこともあります。

そして、誰かがあなたの言動に異を唱えたら、自衛に走ろうとする衝動を抑えましょう。指摘された言動をやめて、謝りましょう。誤解されている、あるいは不当に非難されていると感じた場合でも、よりよいコミュニケーションをとることができた可能性は高いです。あなたの仲間であるRustaceansが快適だと感じられるようにするのは、あなたの責任だということを覚えておいてください。誰もが仲良くしたいと思っていますし、何よりもまず、素晴らしい技術について話したいがために、私たちはここにいます。あなたが信頼されている限り、人々は善意を持って寛容に接することを心がけてくれるでしょう。

-

上記の実施方針は、Discordチャンネル(https://discord.gg/rust-lang)、rust-lang/rust-lang-nursery/rust-lang-deprecatedの管理下にあるGitHubリポジトリ、そしてrust-lang.orgの管理下にあるすべてのフォーラム(users.rust-lang.org、internals.rust-lang.org)を含むすべてのRustの公式の場で適用されます。Rustの行動規範を適用している他のプロジェクトについては、それぞれのプロジェクトのメンテナに連絡して実施してください。この行動規範をあなたのプロジェクトで使いたい場合は、混乱を避けるために、あなた自身のモデレーションポリシーに明示的に言及するか、それをコピーすることを検討してください。

+

上記の実施方針は、Zulipチャンネル(https://rust-lang.zulipchat.com/)、rust-lang/rust-lang-nursery/rust-lang-deprecatedの管理下にあるGitHubリポジトリ、そしてrust-lang.orgの管理下にあるすべてのフォーラム(users.rust-lang.org、internals.rust-lang.org)を含むすべてのRustの公式の場で適用されます。Rustの行動規範を適用している他のプロジェクトについては、それぞれのプロジェクトのメンテナに連絡して実施してください。この行動規範をあなたのプロジェクトで使いたい場合は、混乱を避けるために、あなた自身のモデレーションポリシーに明示的に言及するか、それをコピーすることを検討してください。

Node.js Policy on TrollingContributor Covenant v1.3.0から改変。

coc-moderation-description-team-anchor-text = Rustモデレーションチーム diff --git a/locales/ja/common.ftl b/locales/ja/common.ftl index cf1a64298..b8fbf86ea 100644 --- a/locales/ja/common.ftl +++ b/locales/ja/common.ftl @@ -6,7 +6,6 @@ getting-started = はじめに why-rust = なぜRustか? production-use = 本番環境での利用 learn-more = もっと読む -discord = Discord zulip = Zulip mastodon = Mastodon @@ -50,7 +49,6 @@ footer-social = ソーシャルメディア footer-get-help = ヘルプ footer-youtube-alt = Twitter footer-alt-youtube = youtubeのロゴ -footer-discord-alt = { discord } footer-github-alt = GitHub footer-attribution = Rustチームによって管理されています。誤字を見つけましたか?修正を送ってください! footer-old-site = 以前のウェブサイトをお探しですか? diff --git a/locales/ja/community.ftl b/locales/ja/community.ftl index 7ae86baaf..aafcf7e36 100644 --- a/locales/ja/community.ftl +++ b/locales/ja/community.ftl @@ -16,7 +16,7 @@ community-discourse-button = フォーラムにアクセスする community-irlo-header = インターナルフォーラム community-irlo = Rust内部フォーラムはRustそのものの開発に関する議論をする場所です。コンパイラだけでなく言語設計や標準ライブラリの開発が議論の対象です。 community-chat-header = チャットプラットフォーム -community-chat = Rustの開発や一般的な話し合いは、いくつかのチャットプラットフォーム上で行われています。RustのDiscordサーバにあるgeneral等のチャンネルを確認いただくか、チームページを見て特定のチームがどこで話し合っているかを確認してみてください。 +community-chat = Rustの開発や一般的な話し合いは、いくつかのチャットプラットフォーム上で行われています。RustのZulipサーバにあるgeneral等のチャンネルを確認いただくか、チームページを見て特定のチームがどこで話し合っているかを確認してみてください。 community-teams-learn = チームについてもっと知る community-events-header = イベント community-meetup-header = 近くのミートアップやカンファレンスを探す diff --git a/locales/ja/governance.ftl b/locales/ja/governance.ftl index 836d72452..169816c0d 100644 --- a/locales/ja/governance.ftl +++ b/locales/ja/governance.ftl @@ -21,7 +21,6 @@ governance-members = メンバー&連絡先 governance-team-email = { $teamname } にメールを送る governance-team-repository = { $teamname } リポジトリ -governance-team-discord = Discord { $channel } governance-team-zulip = Zulip { $stream } governance-user-github = GitHub: { $link } governance-user-team-leader = チームリーダー diff --git a/locales/ja/teams.ftl b/locales/ja/teams.ftl index 969e79b55..24046b9b9 100644 --- a/locales/ja/teams.ftl +++ b/locales/ja/teams.ftl @@ -25,8 +25,6 @@ governance-team-wg-parallel-rustc-name = rustc並列化ワーキンググルー governance-team-wg-parallel-rustc-description = 並列コンパイルをrustcのデフォルトにします governance-team-wg-cli-name = コマンドラインインターフェイス(CLI)ワーキンググループ governance-team-wg-cli-description = Rustで大小様々なCLIアプリを書くという、エンドツーエンドの体験に焦点を絞っています。 -governance-team-mods-discord-name = Discordモデレータ -governance-team-mods-discord-description = Discordサーバのモデレーションを行います governance-team-wg-compiler-performance-name = コンパイラパフォーマンスワーキンググループ governance-team-wg-compiler-performance-description = rustcコンパイルパフォーマンス(ビルド時間)の改善を行います。 governance-team-community-content-name = コンテンツチーム diff --git a/locales/ko/common.ftl b/locales/ko/common.ftl index 8aab89db8..9e4581a22 100644 --- a/locales/ko/common.ftl +++ b/locales/ko/common.ftl @@ -6,7 +6,6 @@ getting-started = 시작하기 why-rust = 왜 Rust일까요? production-use = 실사용 learn-more = 더 알아보기 -discord = Discord zulip = Zulip mastodon = Mastodon @@ -45,7 +44,6 @@ footer-policies-all = 모든 정책 footer-get-help = 도움 받기 footer-youtube-alt = Twitter footer-alt-youtube = YouTube 로고 -footer-discord-alt = { discord } footer-github-alt = GitHub footer-old-site = 이전 웹사이트 diff --git a/locales/ko/community.ftl b/locales/ko/community.ftl index d4e2f080d..098c6a384 100644 --- a/locales/ko/community.ftl +++ b/locales/ko/community.ftl @@ -10,7 +10,7 @@ community-discourse-button = 포럼 방문하기 community-irlo-header = 내부 포럼 community-irlo = Rust 내부 포럼은 언어와 표준 라이브러리의 설계뿐만 아니라 컴파일러에 대한 작업을 포함하여 Rust 자체의 개발에 대해 논의하기 위한 곳입니다. community-chat-header = 채팅 플랫폼 -community-chat = Rust 개발, 일반적인 잡담은 여러 채팅 플랫폼에서 이루어집니다. Rust Discord 서버에서 일반 채널 및 기타 정보를 확인하거나 팀 페이지를 확인하여 특정 팀이 만나는 위치를 확인하세요. +community-chat = Rust 개발, 일반적인 잡담은 여러 채팅 플랫폼에서 이루어집니다. Rust Zulip 서버에서 일반 채널 및 기타 정보를 확인하거나 팀 페이지를 확인하여 특정 팀이 만나는 위치를 확인하세요. community-teams-learn = 팀 더 알아보기 community-events-header = 행사 community-calendar = 일정표 보기 diff --git a/locales/ko/governance.ftl b/locales/ko/governance.ftl index 5666f745d..0d2c424cf 100644 --- a/locales/ko/governance.ftl +++ b/locales/ko/governance.ftl @@ -16,7 +16,6 @@ governance-members = 멤버 및 연락처 governance-team-email = { $teamname } 에 메일 보내기 governance-team-repository = { $teamname } 저장소 -governance-team-discord = Discord { $channel } 채널 governance-team-zulip = Zulip: { $stream } governance-user-github = GitHub: { $link } governance-user-team-leader = 팀 리더 diff --git a/locales/ko/teams.ftl b/locales/ko/teams.ftl index 2efbbc3a3..9481a95c6 100644 --- a/locales/ko/teams.ftl +++ b/locales/ko/teams.ftl @@ -6,7 +6,6 @@ governance-team-miri-name = Miri governance-team-wg-debugging-name = 디버깅 작업 그룹 governance-team-compiler-name = 컴파일러 팀 governance-team-core-name = 코어 팀 -governance-team-mods-discord-name = 디스코드 중재자 governance-team-wg-llvm-name = LLVM 작업 그룹 governance-team-wg-grammar-name = 문법 작업 그룹 governance-team-lang-name = 언어 팀 diff --git a/locales/pl/code-of-conduct.ftl b/locales/pl/code-of-conduct.ftl index 71b2cc940..819295133 100644 --- a/locales/pl/code-of-conduct.ftl +++ b/locales/pl/code-of-conduct.ftl @@ -33,6 +33,6 @@ coc-moderation-description = ¶

W ramach społeczności Rusta staramy się dbać o siebie nawzajem. Nie staraj się być "nie do zagięcia" względem zasad, zamiast tego postaraj się dogadać z innymi. Prosimy o unikanie nawiązywania do tematów potencjalnie raniących czy wyraźnie kontrowersyjnych, zwłaszcza jeśli nie są one związane z tematem dyskusji; takie zachowanie zbyt często prowadzi do niepotrzebnych starć, zranionych uczuć, utraty zaufania; nawet gorzej, może to doprowadzić osoby do trwałego odcięcia się od naszej społeczności.

Jeśli komuś nie pasuje coś, co mówisz lub robisz, postaraj się nie wchodzić automatycznie w tryb defensywny. Po prostu przestań robić to, co nie podobało się innym i przeproś. Nawet jeśli uważasz, że Twoje słowa wyjęto z kontekstu lub oskarżono Cię bezpodstawnie, zawsze jest szansa, że mogłeś zakomunikować swoją pozycję lepiej — pamiętaj, że również po Twojej stronie leży odpowiedzialność za komfort innych Rustowców w tej wspólnej przestrzeni. Wszyscy tu obecni chcą żyć ze sobą w zgodzie i w zgodzie móc dyskutować o technologii. Zobaczysz, że inni też będą gotowi założyć dobre intencje z Twojej strony i wybaczyć Ci jakiekolwiek potknięcia w miarę jak będziesz zdobywać ich zaufanie.

¶ -

Powyższe zasady stosuje się na wszystkich oficjalnych kanałach komunikacji Rusta; w tym kanały na Discordzie (https://discord.gg/rust-lang); repozytoria na GitHubie przypisane do rust-lang, rust-lang-nursery, oraz rust-lang-deprecated; wszystkie fora pod adresem rust-lang.org (users.rust-lang.org, internals.rust-lang.org). W przypadku innych projektów działających zgodnie z Kodeksem Postępowania Rusta prosimy o kontakt z osobami odpowiedzialnymi za dany projekt. Jeśli chcesz użyć podobnego kodeksu we własnym projekcie, rozważ wyraźne rozpisanie zasad moderacji podobnych do niniejszego tekstu lub skopiuj naszą wersję i nanieś odpowiednie zmiany. Zaoszczędzisz sobie w ten sposób kłopotów w przyszłości.

¶ +

Powyższe zasady stosuje się na wszystkich oficjalnych kanałach komunikacji Rusta; w tym kanały na Zulipzie (https://rust-lang.zulipchat.com/); repozytoria na GitHubie przypisane do rust-lang, rust-lang-nursery, oraz rust-lang-deprecated; wszystkie fora pod adresem rust-lang.org (users.rust-lang.org, internals.rust-lang.org). W przypadku innych projektów działających zgodnie z Kodeksem Postępowania Rusta prosimy o kontakt z osobami odpowiedzialnymi za dany projekt. Jeśli chcesz użyć podobnego kodeksu we własnym projekcie, rozważ wyraźne rozpisanie zasad moderacji podobnych do niniejszego tekstu lub skopiuj naszą wersję i nanieś odpowiednie zmiany. Zaoszczędzisz sobie w ten sposób kłopotów w przyszłości.

Dokument inspirowany Node.js Policy on Trolling oraz Contributor Covenant v1.3.0.

coc-moderation-description-team-anchor-text = Zespół moderacyjny Rusta diff --git a/locales/pl/common.ftl b/locales/pl/common.ftl index 67bdbb6f4..9da0f8f2c 100644 --- a/locales/pl/common.ftl +++ b/locales/pl/common.ftl @@ -6,7 +6,6 @@ getting-started = Jak zacząć why-rust = Dlaczego Rust? production-use = Użycie w produkcji learn-more = Dowiedz się więcej -discord = Discord zulip = Zulip mastodon = Mastodon @@ -50,7 +49,6 @@ footer-social = Media Społecznościowe footer-get-help = Uzyskaj pomoc! footer-youtube-alt = Twitter footer-alt-youtube = logo youtube -footer-discord-alt = { discord } footer-github-alt = Github footer-attribution = Strona utrzymywana przez Zespół Rusta. Widzisz błąd? diff --git a/locales/pl/community.ftl b/locales/pl/community.ftl index 11fe59550..8066e00fb 100644 --- a/locales/pl/community.ftl +++ b/locales/pl/community.ftl @@ -24,7 +24,7 @@ community-irlo = samego języka – m.in. odnośnie prac nad kompilatorem oraz związane z projektowaniem języka i jego podstawowych bibliotek. community-chat-header = Platformy czatowe -community-chat = Rozmowy związane z pracą nad Rustem jak i bardziej ogólne pogawędki odbywają na kilku różnych platformach. Przejrzyj ogólne kanały na naszym serwerze Discord, lub dowiedz się więcej na temat miejsc spotkań poszczególnych zespołów. +community-chat = Rozmowy związane z pracą nad Rustem jak i bardziej ogólne pogawędki odbywają na kilku różnych platformach. Przejrzyj ogólne kanały na naszym serwerze Zulip, lub dowiedz się więcej na temat miejsc spotkań poszczególnych zespołów. community-teams-learn = Dowiedz się więcej o zespołach community-events-header = Wydarzenia community-meetup-header = Znajdź lokalne spotkanie lub konferencję diff --git a/locales/pl/governance.ftl b/locales/pl/governance.ftl index cf40e6719..ab7ea1acc 100644 --- a/locales/pl/governance.ftl +++ b/locales/pl/governance.ftl @@ -21,7 +21,6 @@ governance-members = Członkowie i Kontakty governance-team-email = Napisz do { $teamname } governance-team-repository = repozytorium { $teamname } -governance-team-discord = { $channel } na Discordzie governance-team-zulip = { $stream } na Zulip governance-user-github = GitHub: { $link } governance-user-team-leader = Lider zespołu diff --git a/locales/pl/teams.ftl b/locales/pl/teams.ftl index 949dfa58d..8f13b1ca1 100644 --- a/locales/pl/teams.ftl +++ b/locales/pl/teams.ftl @@ -25,8 +25,6 @@ governance-team-wg-parallel-rustc-name = Grupa robocza ds. współbieżności ko governance-team-wg-parallel-rustc-description = Praca nad implementacją współbieżności procesu kompilacji w rustc governance-team-wg-cli-name = Grupa robocza ds. interfejsów wiersza poleceń (CLI) governance-team-wg-cli-description = Skupia się na całościowym doświadczeniu twórców aplikacji wiersza poleceń z użyciem Rusta, zarówno tych małych, jak i tych dużych. -governance-team-mods-discord-name = Moderatorzy Discorda -governance-team-mods-discord-description = Moderowanie serwera na Discordzie governance-team-wg-compiler-performance-name = Grupa robocza ds. wydajności kompilatora governance-team-wg-compiler-performance-description = Poprawianie wydajności kompilacji rustc (czas kompilacji) governance-team-community-content-name = Zespół ds. treści diff --git a/locales/pt-BR/code-of-conduct.ftl b/locales/pt-BR/code-of-conduct.ftl index 9e5d405e4..ebbe29764 100644 --- a/locales/pt-BR/code-of-conduct.ftl +++ b/locales/pt-BR/code-of-conduct.ftl @@ -37,6 +37,6 @@ coc-moderation-description =

Na comunidade Rust nós nos esforçamos para fazer mais uns pelos outros. Não tente ser tecnicamente incontestável, tente ser o melhor de si próprio. Em particular, evite flertar com problemas ofensivos ou sensíveis, especialmente se estiverem fora do assunto da discussão. Essas atitudes podem causar brigas desnecessárias, sentimentos feridos e abalo na confiança. Ou ainda pior, elas podem afastar as pessoas completamente da comunidade.

E se alguém tiver problemas com algo que você disse ou fez, resista à vontade de se defender. Apenas pare de fazer o que está incomodando e se desculpe. Mesmo que você se sinta mal interpretado ou injustamente acusado, provavelmente havia uma forma melhor de se expressar. Lembre-se que é sua responsabilidade fazer seus colegas Rustaceans se sentirem confortáveis. Todos nós queremos se relacionar e estamos aqui primeiramente e principalmente porque queremos conversar sobre tecnologias interessantes. Você notará que as pessoas sempre tentarão ver boas intenções e te perdoarão com mais facilidade conforme você ganhar a confiança delas.

-

As políticas listadas acima se aplicam a todos os ambientes oficiais Rust, incluindo: os canais Discord (https://discord.gg/rust-lang); repositórios no GitHub dentro de rust-lang, rust-lang-nursery, and rust-lang-deprecated; e todos os fóruns dentro de rust-lang.org (users.rust-lang.org, internals.rust-lang.org). Para outros projetos que adotam o Código de Conduta Rust, por favor entre em contato com os mantenedores sobre a aplicação. Se você deseja usar esse código de conduta no seu próprio projeto, considere mencionar explicitamente a sua política de moderação ou fazer uma cópia contendo essa informações para evitar qualquer engano.

+

As políticas listadas acima se aplicam a todos os ambientes oficiais Rust, incluindo: os canais Zulip (https://rust-lang.zulipchat.com/); repositórios no GitHub dentro de rust-lang, rust-lang-nursery, and rust-lang-deprecated; e todos os fóruns dentro de rust-lang.org (users.rust-lang.org, internals.rust-lang.org). Para outros projetos que adotam o Código de Conduta Rust, por favor entre em contato com os mantenedores sobre a aplicação. Se você deseja usar esse código de conduta no seu próprio projeto, considere mencionar explicitamente a sua política de moderação ou fazer uma cópia contendo essa informações para evitar qualquer engano.

Adaptado de Node.js Policy on Trolling assim como de Contributor Covenant v1.3.0.

coc-moderation-description-team-anchor-text = Time de Moderação Rust diff --git a/locales/pt-BR/common.ftl b/locales/pt-BR/common.ftl index 6f2b66945..1d2b0a509 100644 --- a/locales/pt-BR/common.ftl +++ b/locales/pt-BR/common.ftl @@ -6,7 +6,6 @@ getting-started = Iniciando why-rust = Por que Rust? production-use = Uso em produção learn-more = Aprenda mais -discord = Discord zulip = Zulip mastodon = Mastodon @@ -50,7 +49,6 @@ footer-social = Social footer-get-help = Busque ajuda! footer-youtube-alt = Twitter footer-alt-youtube = logo do youtube -footer-discord-alt = { discord } footer-github-alt = GitHub footer-attribution = Mantido pela Equipe Rust. Encontrou algum erro? diff --git a/locales/pt-BR/community.ftl b/locales/pt-BR/community.ftl index 7e5c46e04..12c0329c5 100644 --- a/locales/pt-BR/community.ftl +++ b/locales/pt-BR/community.ftl @@ -27,7 +27,7 @@ community-irlo = de Rust – desde o trabalho no compilador até o design da linguagem e a biblioteca padrão. community-chat-header = Plataformas de comunicação -community-chat = As conversas sobre desenvolvimento de Rust e outros assuntos gerais acontecem em diversas plataformas de comunicação. Confira os diversos canais no servidor sobre Rust no Discord, ou confira na página de Equipes onde cada uma das equipes se encontram. +community-chat = As conversas sobre desenvolvimento de Rust e outros assuntos gerais acontecem em diversas plataformas de comunicação. Confira os diversos canais no servidor sobre Rust no Zulip, ou confira na página de Equipes onde cada uma das equipes se encontram. community-teams-learn = Conheça mais sobre as equipes community-events-header = Eventos community-meetup-header = Descubra um encontro local ou conferências diff --git a/locales/pt-BR/governance.ftl b/locales/pt-BR/governance.ftl index 0c38dd48a..ee9e1b709 100644 --- a/locales/pt-BR/governance.ftl +++ b/locales/pt-BR/governance.ftl @@ -21,7 +21,6 @@ governance-members = Membros & Contatos governance-team-email = Envie um email para { $teamname } governance-team-repository = Repositório da equipe { $teamname } -governance-team-discord = { $channel } no Discord governance-team-zulip = { $stream } no Zulip governance-user-github = GitHub: { $link } governance-user-team-leader = Líder da equipe diff --git a/locales/pt-BR/teams.ftl b/locales/pt-BR/teams.ftl index 5a62575eb..8708a38a2 100644 --- a/locales/pt-BR/teams.ftl +++ b/locales/pt-BR/teams.ftl @@ -25,8 +25,6 @@ governance-team-wg-parallel-rustc-name = rustc paralelo governance-team-wg-parallel-rustc-description = Tornando compilação paralela o padrão no rustc governance-team-wg-cli-name = Grupo de trabalho sobre interfaces de linha de comando (CLI) governance-team-wg-cli-description = Focando na experiência de ponta a ponta ao escrever aplicações CLI, grandes ou pequenas, em Rust. -governance-team-mods-discord-name = Moderadores do Discord -governance-team-mods-discord-description = Moderando o servidor Discord governance-team-wg-compiler-performance-name = Performance do Compilador governance-team-wg-compiler-performance-description = Aprimorando a performance de compilação do rustc (tempo de compilação). governance-team-community-content-name = Time de conteúdo diff --git a/locales/ru/code-of-conduct.ftl b/locales/ru/code-of-conduct.ftl index 962ea868e..ba37dc439 100644 --- a/locales/ru/code-of-conduct.ftl +++ b/locales/ru/code-of-conduct.ftl @@ -33,6 +33,6 @@ coc-moderation-description =

В сообществе Rust мы стремимся сделать ещё один шаг, чтобы заботиться друг о друге. Не стремитесь быть технически безупречными, старайтесь быть самим собой. В частности, избегайте заигрывать с оскорбительными или деликатными вопросами, особенно если они не по теме; это слишком часто приводит к ненужным дракам, обидным чувствам и подрыву доверия; хуже того, это может полностью оттолкнуть людей от сообщества.

И если кто-то не согласен с тем, что вы сказали или сделали, не поддавайтесь желанию защищаться. Просто прекратите делать то, на что они жаловались, и извинитесь. Даже если вы чувствуете, что вас неправильно истолковали или несправедливо обвинили, велика вероятность того, что вы могли лучше донести информацию - помните, что вы несёте ответственность за то, чтобы ваши друзья-Растациане были довольны. Все хотят ладить, и мы все здесь, в первую очередь, потому что мы хотим поговорить о крутых технологиях. Вы обнаружите, что люди будут стремиться к добрым намерениям и прощать, если вы заслужили их доверие.

-

Политики принудительного исполнения, перечисленные выше, распространяются на все официальные площадки, включая каналы Discord (https://discord.gg/rust-lang); GitHub репозитории организаций rust-lang, rust-lang-nursery и rust-lang-deprecated и все форумы rust-lang.org (users.rust-lang.org, internals.rust-lang.org). Для других проектов, принимающих Кодекс поведения Rust, пожалуйста, свяжитесь с разработчиками этих проектов для обеспечения исполнения. Если вы хотите использовать этот кодекс поведения для своего собственного проекта, рассмотрите возможность явного упоминания вашей политики модерации или создания копии с вашей собственной политикой модерации, чтобы избежать путаницы.

+

Политики принудительного исполнения, перечисленные выше, распространяются на все официальные площадки, включая каналы Zulip (https://rust-lang.zulipchat.com/); GitHub репозитории организаций rust-lang, rust-lang-nursery и rust-lang-deprecated и все форумы rust-lang.org (users.rust-lang.org, internals.rust-lang.org). Для других проектов, принимающих Кодекс поведения Rust, пожалуйста, свяжитесь с разработчиками этих проектов для обеспечения исполнения. Если вы хотите использовать этот кодекс поведения для своего собственного проекта, рассмотрите возможность явного упоминания вашей политики модерации или создания копии с вашей собственной политикой модерации, чтобы избежать путаницы.

Адаптировано из Node.js Policy on Trolling, а также из Contributor Covenant v1.3.0.

coc-moderation-description-team-anchor-text = Команда модераторов Rust diff --git a/locales/ru/common.ftl b/locales/ru/common.ftl index e0592ce44..5ba1f8d58 100644 --- a/locales/ru/common.ftl +++ b/locales/ru/common.ftl @@ -6,7 +6,6 @@ getting-started = Начало работы why-rust = Почему Rust? production-use = Промышленное использование learn-more = Узнать больше -discord = Discord zulip = Zulip mastodon = Mastodon @@ -50,7 +49,6 @@ footer-social = Социальные сети footer-get-help = Получить помощь! footer-youtube-alt = Twitter footer-alt-youtube = Логотип youtube -footer-discord-alt = { discord } footer-github-alt = GitHub footer-attribution = Поддерживается Rust Team. Увидели опечатку? Исправьте здесь! footer-old-site = Ищете предыдущий сайт? diff --git a/locales/ru/community.ftl b/locales/ru/community.ftl index 0be8edd88..f9c11a75f 100644 --- a/locales/ru/community.ftl +++ b/locales/ru/community.ftl @@ -16,7 +16,7 @@ community-discourse-button = Посетить форум community-irlo-header = Форум internals community-irlo = Форум Rust Internals - это место, где можно подискутировать о разработке самого Rust – включая работу над компилятором, дизайном языка и стандартной библиотеки. community-chat-header = Чат-платформы -community-chat = Разработка Rust и общение происходит на нескольких чат-платформах. Посмотрите общие и другие каналы на Discord сервере Rust или посетите страницу команд, чтобы узнать где проводят встречи конкретные команды. +community-chat = Разработка Rust и общение происходит на нескольких чат-платформах. Посмотрите общие и другие каналы на Zulip сервере Rust или посетите страницу команд, чтобы узнать где проводят встречи конкретные команды. community-teams-learn = Узнать больше о командах community-events-header = Мероприятия community-meetup-header = Найти встречу или конференцию diff --git a/locales/ru/governance.ftl b/locales/ru/governance.ftl index 8d23038d2..53a18fe93 100644 --- a/locales/ru/governance.ftl +++ b/locales/ru/governance.ftl @@ -18,7 +18,6 @@ governance-members = Участники и контакты governance-team-email = Email { $teamname } governance-team-repository = Репозиторий { $teamname } -governance-team-discord = { $channel } в Discord governance-team-zulip = { $stream } в Zulip governance-user-github = GitHub: { $link } governance-user-team-leader = Лидер группы diff --git a/locales/ru/teams.ftl b/locales/ru/teams.ftl index c32855ec0..7eab03ae7 100644 --- a/locales/ru/teams.ftl +++ b/locales/ru/teams.ftl @@ -25,8 +25,6 @@ governance-team-wg-parallel-rustc-name = Parallel rustc governance-team-wg-parallel-rustc-description = Делают параллельную компиляцию режимом по умолчанию для rustc governance-team-wg-cli-name = Command-line interfaces (CLI) working group governance-team-wg-cli-description = Направлена на сквозной опыт написания больших и маленьких консольных приложения на Rust. -governance-team-mods-discord-name = Модераторы Discord -governance-team-mods-discord-description = Модерирование сервера Discord governance-team-wg-compiler-performance-name = Производительность компилятора governance-team-wg-compiler-performance-description = Улучшение производительности компилятора rustc (уменьшение времени сборки). governance-team-community-content-name = Content team diff --git a/locales/tr/code-of-conduct.ftl b/locales/tr/code-of-conduct.ftl index 1ead6ec30..a6e9998c6 100644 --- a/locales/tr/code-of-conduct.ftl +++ b/locales/tr/code-of-conduct.ftl @@ -33,6 +33,6 @@ coc-moderation-description =

Rust topluluğunda, birbirimize göz kulak olmak için daha çok çaba sarf ederiz. Sadece teknik olarak ileride olmanın yanı sıra iyi biri olmak da gerekir. Hassas konuları, özellikle kanalın konusuyla ilgisiz olanları, kışkırtıcı nitelikte davranışlardan kaçınmalıyız. Bu tarz davranışlar genellikle gereksiz kavgalara, incinmiş duygulara ve zedelenen güvenlere yol açmakla birlikte, insanları topluluktan uzaklaştırabilir.

Eğer birisi söylediğiniz veya yaptığınız bir şey tarafından alınırsa, savunmaya geçmeyiniz. Sadece şikayet edilen davranışı sonlandırıp, özür dileyiniz. Yanlış anlaşıldığınızı düşündüğünüz veya haksız olarak suçlandığınız durumlarda bile, daha iyi iletişim kurma şansınızın olduğunu unutmayınız. Diğer Rustaceanların huzurunu düşünmenin sorumluluklarımızdan biri olduğunu unutmayınız. Burada herkes iyi geçinmek istiyor ve her şeyden önce, burada iyi bir teknolojiyle ilgili fikir alışverişi yapmak için bulunmaktayız. Güvenlerini kazandığınız sürece, insanların iyi niyetli yaklaştığınızı düşündüğüne ve affetmeye daha açık olduğuna tanıklık edeceksiniz.

-

Yukarıda listelenen kurallar, her bir Rust topluluğu buluşma yeri için geçerlidir. Buna Discord kanalları (https://discord.gg/rust-lang), rust-lang, rust-lang-nursery ve rust-lang-deprecated'e ait GitHub depoları ve rust-lang.org altındaki bütün forumlar (users.rust-lang.org, internals.rust-lang.org) dahildir. Rust Davranış Kuralları'nı benimseyen bütün projeler için, proje devamlılığını sürdüren kişilerle kuralların uygulanması için irtibata geçin. Bu davranış kurallarını kendi projenizde uygulamak istediğiniz takdirde karışıklığa yol açmamak için açıkça bundan bahsetmeyi ya da bu kuralların bir kopyasını oluşturmayı unutmayın.

+

Yukarıda listelenen kurallar, her bir Rust topluluğu buluşma yeri için geçerlidir. Buna Zulip kanalları (https://rust-lang.zulipchat.com/), rust-lang, rust-lang-nursery ve rust-lang-deprecated'e ait GitHub depoları ve rust-lang.org altındaki bütün forumlar (users.rust-lang.org, internals.rust-lang.org) dahildir. Rust Davranış Kuralları'nı benimseyen bütün projeler için, proje devamlılığını sürdüren kişilerle kuralların uygulanması için irtibata geçin. Bu davranış kurallarını kendi projenizde uygulamak istediğiniz takdirde karışıklığa yol açmamak için açıkça bundan bahsetmeyi ya da bu kuralların bir kopyasını oluşturmayı unutmayın.

Node.js Policy on Trolling ve Contributor Covenant v1.3.0'dan uyarlanmıştır.

coc-moderation-description-team-anchor-text = Rust yönetim ekibi diff --git a/locales/tr/common.ftl b/locales/tr/common.ftl index ac8c423c0..3980756a7 100644 --- a/locales/tr/common.ftl +++ b/locales/tr/common.ftl @@ -6,7 +6,6 @@ getting-started = Başlarken why-rust = Neden Rust? production-use = Üretimde kullanım learn-more = Daha fazla bilgi edinin -discord = Discord mastodon = Mastodon ## components/panels/domain.hbs @@ -48,7 +47,6 @@ footer-social = Sosyal footer-get-help = Yardım alın! footer-youtube-alt = Twitter footer-alt-youtube = youtube logosu -footer-discord-alt = { discord } footer-github-alt = GitHub footer-attribution = Rust Ekibi tarafından geliştirilmektedir. Yazım hatasına mı rastladınız? diff --git a/locales/tr/community.ftl b/locales/tr/community.ftl index 6d25753f4..c2d47ae24 100644 --- a/locales/tr/community.ftl +++ b/locales/tr/community.ftl @@ -13,7 +13,7 @@ community-discourse-button = Forumu Ziyaret Et community-irlo-header = İç Forum community-irlo = Rust İç Forumu, Rust'ın geliştirilmesi– derleyici, dilin tasarımı ve standart kütüphane dahil olmak üzere bu konuların tartışıldığı yerdir. community-chat-header = Sohbet platformları -community-chat = Rust'ın geliştirilmesi ve genel konuşmalar çeşitli sohbet platformlarında gerçekleşir. Genel kanallar ve daha fazlası için Rust Discord sunucusuna göz atın veya ekipler sayfasından hangi takımların nerede buluşacağına bakın. +community-chat = Rust'ın geliştirilmesi ve genel konuşmalar çeşitli sohbet platformlarında gerçekleşir. Genel kanallar ve daha fazlası için Rust Zulip sunucusuna göz atın veya ekipler sayfasından hangi takımların nerede buluşacağına bakın. community-teams-learn = Ekipler hakkında daha fazla bilgi edinin community-events-header = Etkinlikler community-meetup-header = Yerel bir buluşma veya konferans bulun diff --git a/locales/tr/governance.ftl b/locales/tr/governance.ftl index 36f53a295..fb92da67f 100644 --- a/locales/tr/governance.ftl +++ b/locales/tr/governance.ftl @@ -21,7 +21,6 @@ governance-members = Üyeler & İrtibatlar governance-team-email = { $teamname }ne E-Posta Gönder governance-team-repository = { $teamname } deposu -governance-team-discord = Discord'da { $channel } kanalı governance-user-github = GitHub: { $link } governance-user-team-leader = Ekip lideri governance-members-header = Üyeler diff --git a/locales/tr/teams.ftl b/locales/tr/teams.ftl index 9ab71173f..4b8fbc18b 100644 --- a/locales/tr/teams.ftl +++ b/locales/tr/teams.ftl @@ -24,8 +24,6 @@ governance-team-wg-parallel-rustc-name = Paralel rustc governance-team-wg-parallel-rustc-description = Rustc için paralel derlemeyi varsayılan yapar governance-team-wg-cli-name = Komut satırı arayüzleri (KSA) çalışma grubu governance-team-wg-cli-description = Rust'ta, küçük ya da büyük, KSA uygulamaları yazmanın uçtan uca deneyimine odaklanır. -governance-team-mods-discord-name = Discord yönetim ekibi -governance-team-mods-discord-description = Discord sunucusunu yönetir governance-team-wg-compiler-performance-name = Derleyici Performansı governance-team-wg-compiler-performance-description = Rustc derleme performansını (yapım süresi) geliştirir. governance-team-community-content-name = İçerik ekibi diff --git a/locales/xx-AU/common.ftl b/locales/xx-AU/common.ftl index cdf3c4a08..6414da206 100644 --- a/locales/xx-AU/common.ftl +++ b/locales/xx-AU/common.ftl @@ -29,7 +29,6 @@ footer-get-help = ¡dlǝɥ ʇǝפ footer-youtube-alt = ɹǝʇʇᴉʍ┴ footer-alt-youtube = oƃol ǝqnʇnoʎ -footer-discord-alt = pɹoɔsᴉp footer-github-alt = qnHʇᴉפ footer-attribution = ¡ ǝɹǝɥ xᴉɟ ɐ puǝS ¿odʎʇ ɐ ǝǝS ˙ɯɐǝ┴ ʇsnɹ ǝɥʇ ʎq pǝuᴉɐʇuᴉɐW diff --git a/locales/xx-AU/governance.ftl b/locales/xx-AU/governance.ftl index 0f964d184..c10bcda99 100644 --- a/locales/xx-AU/governance.ftl +++ b/locales/xx-AU/governance.ftl @@ -10,7 +10,6 @@ governance-wgs-header = sdnoɹפ ƃuᴉʞɹoM governance-members = sʇɔɐʇuoƆ ⅋ sɹǝqɯǝW governance-team-email = {$teamname}⁨ ǝɥʇ lᴉɐɯƎ governance-team-repository = ʎɹoʇᴉsodǝɹ {$teamname}⁨ -governance-team-discord = pɹoɔsᴉp uo ⁩{$channel} governance-user-github = ⁩{$link} :qnHʇᴉפ governance-user-team-leader = ɹǝpɐǝl ɯɐǝ┴ governance-members-header = sɹǝqɯǝW diff --git a/locales/xx-AU/teams.ftl b/locales/xx-AU/teams.ftl index 30fc00090..4181e6429 100644 --- a/locales/xx-AU/teams.ftl +++ b/locales/xx-AU/teams.ftl @@ -93,8 +93,6 @@ governance-team-wg-rls-2-name = 0˙ᄅ S˥ɹ governance-team-wg-rls-2-description = sƎpI ɹoɟ pǝɹolᴉɐʇ ǝɹnʇɔǝʇᴉɥɔɹɐ ɹǝlᴉdɯoɔ ʍǝu ɐ ɥʇᴉʍ ƃuᴉʇuǝɯᴉɹǝdxƎ governance-team-cargo-name = ɯɐǝʇ oƃɹɐƆ governance-team-cargo-description = oƃɹɐƆ ɟo uoᴉʇɐʇuǝɯǝldɯᴉ puɐ uƃᴉsǝp -governance-team-mods-discord-name = sɹoʇɐɹǝpoɯ pɹoɔsᴉp -governance-team-mods-discord-description = ɹǝʌɹǝs pɹoɔsᴉp ǝɥʇ ƃuᴉʇɐɹǝpoW governance-team-wg-llvm-name = WΛ˥˥ governance-team-wg-llvm-description = ʇuǝɯdolǝʌǝp sʇᴉ uᴉ ʇsnɹ ʇuǝsǝɹdǝɹ oʇ ɯɐǝɹʇsdn WΛ˥˥ ɥʇᴉʍ ƃuᴉʞɹoM governance-team-mods-discourse-name = sɹoʇɐɹǝpoɯ ǝsɹnoɔsᴉp diff --git a/locales/zh-CN/code-of-conduct.ftl b/locales/zh-CN/code-of-conduct.ftl index dac1decda..4872cb57c 100644 --- a/locales/zh-CN/code-of-conduct.ftl +++ b/locales/zh-CN/code-of-conduct.ftl @@ -33,6 +33,6 @@ coc-moderation-description =

在 Rust 社区,我们努力多付出一些,互相照顾。不要只关注在技术上无懈可击,尽量做好您自己。特别是,避免陷入攻击性或敏感性问题的纠缠。尤其是当他们偏离主题时,这通常会导致不必要的斗争,伤害情感,损害信任。更糟糕的是,它会把人们推离社区。

如果有人对您所说或做过的事情提出异议,不要急于自卫。停止做他们抱怨的事情并道歉。即使您觉得自己被误解或受到不公平的指控,也很有可能会有更好的沟通方式 - 请记住,让您的同伴 Rustaceans 感到舒服是您的责任。每个人都希望好好相处,我们来这里最初和最根本的目的是想谈论很酷的技术。您会发现,只要您赢得他们的信任,人们就会渴望表现出善意和宽恕。

-

上述强制执行政策适用于所有 Rust 官方场所; 包括Discord频道(https://discord.gg/rust-lang);rust-lang,rust-lang-nursery和rust-lang-deprecated在GitHub的仓库;rust-lang.org(users.rust-lang.org,internals.rust-lang.org)的所有论坛。对于采用Rust行为准则的其他项目,请联系这些项目的维护人员以便执行。如果您希望将此行为准则用于您自己的项目,请考虑明确提及您的审查政策或使用您自己的审查政策制作副本,以避免混淆。

+

上述强制执行政策适用于所有 Rust 官方场所; 包括Zulip频道(https://rust-lang.zulipchat.com/);rust-lang,rust-lang-nursery和rust-lang-deprecated在GitHub的仓库;rust-lang.org(users.rust-lang.org,internals.rust-lang.org)的所有论坛。对于采用Rust行为准则的其他项目,请联系这些项目的维护人员以便执行。如果您希望将此行为准则用于您自己的项目,请考虑明确提及您的审查政策或使用您自己的审查政策制作副本,以避免混淆。

改编自《Node.js 关于恶意破坏的政策》以及《贡献者公约 v1.3.0 》。

coc-moderation-description-team-anchor-text = Rust 审查团队 diff --git a/locales/zh-CN/common.ftl b/locales/zh-CN/common.ftl index df6d739b5..21d17d7e3 100644 --- a/locales/zh-CN/common.ftl +++ b/locales/zh-CN/common.ftl @@ -6,7 +6,6 @@ getting-started = 入门 why-rust = 为什么选择 Rust? production-use = 产品应用 learn-more = 了解更多 -discord = Discord zulip = Zulip mastodon = Mastodon @@ -50,7 +49,6 @@ footer-social = 社交 footer-get-help = 获得帮助! footer-youtube-alt = Twitter footer-alt-youtube = youtube 标志 -footer-discord-alt = { discord } footer-github-alt = GitHub footer-attribution = 由 Rust 团队维护。发现了错别字? diff --git a/locales/zh-CN/community.ftl b/locales/zh-CN/community.ftl index b95eefff1..424d8ddfe 100644 --- a/locales/zh-CN/community.ftl +++ b/locales/zh-CN/community.ftl @@ -16,7 +16,7 @@ community-discourse-button = 访问论坛 community-irlo-header = 内部论坛 community-irlo = Rust 内部论坛是开发者们讨论 Rust 编程语言自身开发的地方。话题包括编译器、语言设计以及标准库等相关工作。 community-chat-header = 聊天平台 -community-chat = Rust 的开发和日常讨论通常是在一些聊天平台上面。可以浏览 Discord Rust 服务器的相关频道,或者访问团队主页寻找专门的团队会议。 +community-chat = Rust 的开发和日常讨论通常是在一些聊天平台上面。可以浏览 Zulip Rust 服务器的相关频道,或者访问团队主页寻找专门的团队会议。 community-teams-learn = 了解关于团队的更多信息 community-events-header = 活动 community-meetup-header = 参与线下聚会或会议 diff --git a/locales/zh-CN/governance.ftl b/locales/zh-CN/governance.ftl index b07587d94..ea28edbf5 100644 --- a/locales/zh-CN/governance.ftl +++ b/locales/zh-CN/governance.ftl @@ -21,7 +21,6 @@ governance-members = 成员和联系方式 governance-team-email = 发送邮件至{ $teamname } governance-team-repository = { $teamname } 仓库 -governance-team-discord = Discord 上的 { $channel } governance-team-zulip = Zulip 上的 { $stream } governance-user-github = GitHub: { $link } governance-user-team-leader = 团队领导 diff --git a/locales/zh-CN/teams.ftl b/locales/zh-CN/teams.ftl index 42fe7fee1..86acce7ff 100644 --- a/locales/zh-CN/teams.ftl +++ b/locales/zh-CN/teams.ftl @@ -25,8 +25,6 @@ governance-team-wg-parallel-rustc-name = rustc 并行化工作组 governance-team-wg-parallel-rustc-description = 让 rustc 默认支持并行编译 governance-team-wg-cli-name = 命令行交互(CLI)工作组 governance-team-wg-cli-description = 专注于用 Rust 编写大型/小型 CLI 应用的端到端体验。 -governance-team-mods-discord-name = Discord 管理员 -governance-team-mods-discord-description = 管理 Discord 服务器 governance-team-wg-compiler-performance-name = 编译器性能工作组 governance-team-wg-compiler-performance-description = 改善 rustc 编译性能(编译耗时方面)。 governance-team-community-content-name = 内容团队 diff --git a/locales/zh-TW/code-of-conduct.ftl b/locales/zh-TW/code-of-conduct.ftl index 574b8fbca..638fe9e03 100644 --- a/locales/zh-TW/code-of-conduct.ftl +++ b/locales/zh-TW/code-of-conduct.ftl @@ -33,6 +33,6 @@ coc-moderation-description =

在 Rust 社群,我們努力多付出一些,互相照顧。不要只關注在技術上無懈可擊,盡量做好您自己。特別是避免陷入攻擊性或被敏感性問題糾纏。尤其是當別人偏離主題時,這通常會導致不必要的鬥爭、傷害情感、損害信任,更糟糕的是,這些事情會讓人們離開社群。

如果有人對您所說或做過的事情提出異議,不要急於自衛,先停止做他們抱怨的事情並道歉。即使您覺得自己被誤解或受到不公平的指控,也很有可能會有更好的溝通方式——請記住,讓您的 Rustaceans 同伴感到舒適是您的責任。每個人都希望好好相處,我們來這裡最初和最根本的目的是想談論很酷的技術。您會發現,只要您贏得他們的信任,人們就會積極地表現出善意和寬恕。

-

上述執行政策強制適用於所有 Rust 官方場所;包括 Discord 頻道(https://discord.gg/rust-lang)、rust-lang、rust-lang-nursery 和 rust-lang-deprecated 的 Github repository、rust-lang.org(users.rust-lang.org、internals.rust-lang.org)的所有論壇。對於採用 Rust 行為準則的其他專案,請聯繫這些專案的維護人員以便執行此公約。如果您希望將此行為準則用於您自己的專案,請考慮明確提出您的審查政策或使用您自己的審查政策的改編副本,以避免混淆。

+

上述執行政策強制適用於所有 Rust 官方場所;包括 Zulip 頻道(https://rust-lang.zulipchat.com/)、rust-lang、rust-lang-nursery 和 rust-lang-deprecated 的 Github repository、rust-lang.org(users.rust-lang.org、internals.rust-lang.org)的所有論壇。對於採用 Rust 行為準則的其他專案,請聯繫這些專案的維護人員以便執行此公約。如果您希望將此行為準則用於您自己的專案,請考慮明確提出您的審查政策或使用您自己的審查政策的改編副本,以避免混淆。

改編自《Node.js 關於惡意破壞的政策》以及《 貢獻者公約 v1.3.0 》。

coc-moderation-description-team-anchor-text = Rust 審核團隊 diff --git a/locales/zh-TW/common.ftl b/locales/zh-TW/common.ftl index 8efa57f9f..9e4ee5fc9 100644 --- a/locales/zh-TW/common.ftl +++ b/locales/zh-TW/common.ftl @@ -6,7 +6,6 @@ getting-started = 新手入門 why-rust = 為何選擇 Rust? production-use = 產品應用 learn-more = 了解更多 -discord = Discord zulip = Zulip mastodon = Mastodon @@ -50,7 +49,6 @@ footer-social = 社群媒體 footer-get-help = 取得協助! footer-youtube-alt = Twitter footer-alt-youtube = youtube 標誌 -footer-discord-alt = { discord } footer-github-alt = GitHub footer-attribution = 由 Rust 團隊維護,發現錯字了嗎?請在此提交修復! footer-old-site = 想查看舊版網站嗎? diff --git a/locales/zh-TW/community.ftl b/locales/zh-TW/community.ftl index a5362b1d0..3c9193e88 100644 --- a/locales/zh-TW/community.ftl +++ b/locales/zh-TW/community.ftl @@ -16,7 +16,7 @@ community-discourse-button = 前往論壇 community-irlo-header = 內部論壇 community-irlo = Rust 的內部論壇是一個討論 Rust 本身的開發的地方;包含編譯器的運作以及其語言設計,和標準函式庫。 community-chat-header = 聊天室 -community-chat = 從閒聊、學習到 Rust 的開發都能在不同的聊天室討論。在 Rust Discord 的頻道查看「一般主題」或其他主題,或者查看「團隊」頁面來尋找適切的團隊。 +community-chat = 從閒聊、學習到 Rust 的開發都能在不同的聊天室討論。在 Rust Zulip 的頻道查看「一般主題」或其他主題,或者查看「團隊」頁面來尋找適切的團隊。 community-teams-learn = 更多團隊相關資訊 community-events-header = 活動 community-meetup-header = 各地聚會或研討會 diff --git a/locales/zh-TW/governance.ftl b/locales/zh-TW/governance.ftl index 34de9eb5d..9bd4ddc29 100644 --- a/locales/zh-TW/governance.ftl +++ b/locales/zh-TW/governance.ftl @@ -18,7 +18,6 @@ governance-members = 成員與聯絡方式 governance-team-email = 寄信至 { $teamname } governance-team-repository = { $teamname } repository -governance-team-discord = Discord 上的 { $channel } governance-team-zulip = 於 Zulip governance-user-github = GitHub: { $link } governance-user-team-leader = 團隊領袖 diff --git a/locales/zh-TW/teams.ftl b/locales/zh-TW/teams.ftl index 05156adf4..2cba7887a 100644 --- a/locales/zh-TW/teams.ftl +++ b/locales/zh-TW/teams.ftl @@ -25,8 +25,6 @@ governance-team-wg-parallel-rustc-name = 平行化 rustc governance-team-wg-parallel-rustc-description = 使平行化編譯在 rustc 中成為常態 governance-team-wg-cli-name = 命令列界面(CLI)工作組 governance-team-wg-cli-description = 專注於用 Rust 寫大型/小型 CLI 程式的端對端體驗 -governance-team-mods-discord-name = Discord 管理員 -governance-team-mods-discord-description = 管理 Discord 伺服器 governance-team-wg-compiler-performance-name = 編譯器效能 governance-team-wg-compiler-performance-description = 增進 rustc 編譯效能(編譯時間) governance-team-community-content-name = 內容團隊 diff --git a/templates/community/index.html.hbs b/templates/community/index.html.hbs index d6be2097a..ef90ebf9c 100644 --- a/templates/community/index.html.hbs +++ b/templates/community/index.html.hbs @@ -22,7 +22,8 @@
- {{fluent "community-discourse-button"}} + {{fluent + "community-discourse-button"}}
@@ -35,7 +36,8 @@
- {{fluent "community-discourse-button"}} + {{fluent + "community-discourse-button"}}
@@ -49,9 +51,6 @@ {{!-- TODO: remove padding and margin once global declarations are gone --}}
-

{{fluent "community-learn"}}

-
+

{{fluent "community-learn"}}

+
@@ -116,18 +115,21 @@

- {{fluent "community-team-button"}} + {{fluent + "community-team-button"}}
@@ -161,13 +163,14 @@ {{fluent "community-event-run"}}
- {{fluent + {{fluent
@@ -180,15 +183,18 @@

{{#fluent "community-standards"}} - {{#fluentparam "url"}}{{baseurl}}/policies/code-of-conduct{{/fluentparam}} + {{#fluentparam "url"}}{{baseurl}}/policies/code-of-conduct{{/fluentparam}} {{/fluent}}

diff --git a/templates/components/footer.html.hbs b/templates/components/footer.html.hbs index c7ae27d4f..b7b2817b5 100644 --- a/templates/components/footer.html.hbs +++ b/templates/components/footer.html.hbs @@ -22,20 +22,25 @@

{{fluent "footer-social"}}

- {{fluent - {{fluent - {{fluent - discord logo - github logo + {{fluent + {{fluent + {{fluent + github logo
diff --git a/templates/governance/group-team.html.hbs b/templates/governance/group-team.html.hbs index ad16675a8..8bc133216 100644 --- a/templates/governance/group-team.html.hbs +++ b/templates/governance/group-team.html.hbs @@ -1,7 +1,9 @@
-

{{team-text team name}}

+ +

{{team-text team name}}

+
@@ -9,96 +11,96 @@

{{team-text team description}}

{{#if team.members}} -
-

{{fluent "governance-members-header"}}

-
-
- {{#each team.members as |member|}} -
- - {{member.name}} - -
-

{{member.name}}

-
- {{#fluent "governance-user-github"}} - {{#fluentparam "link"}} - {{member.github}} - {{/fluentparam}} - {{/fluent}} -
- {{#if member.is_lead}} -
{{fluent "governance-user-team-leader"}}
- {{else}} - {{#if member.roles}} -
{{team-text team role (lookup member.roles 0)}}
- {{/if}} - {{/if}} -
+
+

{{fluent "governance-members-header"}}

+
+
+ {{#each team.members as |member|}} +
+ + {{member.name}} + +
+

{{member.name}}

+
+ {{#fluent "governance-user-github"}} + {{#fluentparam "link"}} + {{member.github}} + {{/fluentparam}} + {{/fluent}}
- {{/each}} + {{#if member.is_lead}} +
{{fluent "governance-user-team-leader"}}
+ {{else}} + {{#if member.roles}} +
{{team-text team role (lookup member.roles 0)}}
+ {{/if}} + {{/if}} +
- {{#if team.alumni}} -
-

{{fluent "governance-alumni-header"}}

-
-

{{fluent "governance-alumni-thanks"}}

-
- {{#each team.alumni as |member|}} -
- - {{member.name}} - -
- {{member.name}} -
- GitHub: {{member.github}} -
- {{#if member.roles}} -
{{team-text team role (lookup member.roles 0)}}
- {{/if}} -
+ {{/each}} +
+ {{#if team.alumni}} +
+

{{fluent "governance-alumni-header"}}

+
+

{{fluent "governance-alumni-thanks"}}

+
+ {{#each team.alumni as |member|}} +
+ + {{member.name}} + +
+ {{member.name}} +
+ GitHub: {{member.github}}
- {{/each}} + {{#if member.roles}} +
{{team-text team role (lookup member.roles 0)}}
+ {{/if}}
- {{/if}} +
+ {{/each}} +
+ {{/if}} {{/if}}
From 5cafc1b0a22902eac7c6ce3fd1bba05fbd99c3a8 Mon Sep 17 00:00:00 2001 From: Remo Senekowitsch Date: Fri, 4 Jul 2025 20:08:35 +0200 Subject: [PATCH 11/21] Fix clippy warnings --- src/category.rs | 2 +- src/i18n.rs | 4 ++-- src/main.rs | 16 ++++++++-------- src/redirect.rs | 4 ++-- src/teams.rs | 6 +++--- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/category.rs b/src/category.rs index 52b7b00c2..174ce0610 100644 --- a/src/category.rs +++ b/src/category.rs @@ -31,7 +31,7 @@ impl<'r> FromParam<'r> for Category { if is_category(&url) { Ok(Category { name: url }) } else { - Err(format!("No category called <{}>", url)) + Err(format!("No category called <{url}>")) } } } diff --git a/src/i18n.rs b/src/i18n.rs index a2f8b5c24..3b2eb75cf 100644 --- a/src/i18n.rs +++ b/src/i18n.rs @@ -22,7 +22,7 @@ fn add_bundle_functions(bundle: &mut FluentBundle<&'static FluentResource>) { Some(FluentValue::String(s)) => s, _ => return FluentValue::None, }; - FluentValue::String(format!("{0}", email).into()) + FluentValue::String(format!("{email}").into()) }) .expect("could not add function"); @@ -32,7 +32,7 @@ fn add_bundle_functions(bundle: &mut FluentBundle<&'static FluentResource>) { Some(FluentValue::String(s)) => s, _ => return FluentValue::None, }; - FluentValue::String(format!("{0}", text).into()) + FluentValue::String(format!("{text}").into()) }) .expect("could not add function"); } diff --git a/src/main.rs b/src/main.rs index eaa8285ed..a7d5c270a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -125,7 +125,7 @@ fn baseurl(lang: &str) -> String { if lang == "en-US" { String::new() } else { - format!("/{}", lang) + format!("/{lang}") } } @@ -274,13 +274,13 @@ fn hash_css(css: &str) -> String { } fn compile_sass(filename: &str) -> String { - let scss_file = format!("./src/styles/{}.scss", filename); + 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", css_sha); + 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)); @@ -291,7 +291,7 @@ fn compile_sass(filename: &str) -> String { fn concat_vendor_css(files: Vec<&str>) -> String { let mut concatted = String::new(); for filestem in files { - let vendor_path = format!("./static/styles/{}.css", filestem); + 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); } @@ -307,7 +307,7 @@ fn concat_vendor_css(files: Vec<&str>) -> String { fn concat_app_js(files: Vec<&str>) -> String { let mut concatted = String::new(); for filestem in files { - let vendor_path = format!("./static/scripts/{}.js", filestem); + 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); } @@ -354,7 +354,7 @@ async fn render_governance( Ok(Template::render(page, context)) } Err(err) => { - eprintln!("error while loading the governance page: {}", err); + eprintln!("error while loading the governance page: {err}"); Err(Status::InternalServerError) } } @@ -377,7 +377,7 @@ async fn render_team( if err.is::() { Err(Status::NotFound) } else { - eprintln!("error while loading the team page: {}", err); + eprintln!("error while loading the team page: {err}"); Err(Status::InternalServerError) } } @@ -392,7 +392,7 @@ fn render_subject(category: Category, subject: &str, lang: String) -> Result Option { 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); + 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::Present(locale) => Some(Redirect::permanent(format!("/{locale}{dest}"))), Locale::SpecifiedButMissing => Some(Redirect::temporary(dest)), } } else { diff --git a/src/teams.rs b/src/teams.rs index 23a9983f4..bc0c65f28 100644 --- a/src/teams.rs +++ b/src/teams.rs @@ -254,7 +254,7 @@ impl Cached for RustTeams { self.1 } async fn fetch() -> Result> { - let resp: Teams = reqwest::get(format!("{}/teams.json", BASE_URL)) + let resp: Teams = reqwest::get(format!("{BASE_URL}/teams.json")) .await? .error_for_status()? .json() @@ -332,8 +332,8 @@ mod tests { ], alumni: Vec::new(), website_data: Some(TeamWebsite { - name: format!("Team {}", name), - description: format!("Description of {}", name), + name: format!("Team {name}"), + description: format!("Description of {name}"), page: name.into(), email: None, repo: None, From f736d72c8ca26eca4ce4bf5412b60a39164ec799 Mon Sep 17 00:00:00 2001 From: Remo Senekowitsch Date: Fri, 4 Jul 2025 19:59:15 +0200 Subject: [PATCH 12/21] Fix title of footer logos --- templates/components/footer.html.hbs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/templates/components/footer.html.hbs b/templates/components/footer.html.hbs index b7b2817b5..38f1ac9cf 100644 --- a/templates/components/footer.html.hbs +++ b/templates/components/footer.html.hbs @@ -34,13 +34,13 @@

{{fluent "footer-social"}}

{{fluent + alt="{{fluent "mastodon"}}" title="{{fluent "mastodon"}}" /> {{fluent + src="/static/images/bluesky.svg" alt="{{fluent "bluesky"}}" title="{{fluent "bluesky"}}" /> {{fluent + src="/static/images/youtube.svg" alt="{{fluent "footer-alt-youtube"}}" title="YouTube" /> github logo + title="{{fluent "footer-github-alt"}}" />
From c5bd23ceac17676e7b1d1c5aa1063a1da6405285 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 26 Jul 2025 12:10:42 +0200 Subject: [PATCH 13/21] Add rendering of the web into a directory --- Cargo.lock | 399 ++++++++++++----------- Cargo.toml | 5 +- src/cache.rs | 2 +- src/i18n.rs | 2 +- src/main.rs | 109 ++++--- src/render/assets.rs | 125 +++++++ src/render/fs.rs | 11 + src/render/mod.rs | 244 ++++++++++++++ src/rust_version.rs | 4 +- src/teams.rs | 4 +- templates/governance/index-team.html.hbs | 2 +- templates/governance/index.html.hbs | 2 +- 12 files changed, 670 insertions(+), 239 deletions(-) create mode 100644 src/render/assets.rs create mode 100644 src/render/fs.rs create mode 100644 src/render/mod.rs diff --git a/Cargo.lock b/Cargo.lock index a01260ba9..3a626f725 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,6 +26,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "anyhow" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" + [[package]] name = "async-stream" version = "0.3.6" @@ -45,7 +51,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", ] [[package]] @@ -56,7 +62,7 @@ checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", ] [[package]] @@ -146,12 +152,6 @@ 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" @@ -234,6 +234,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" @@ -243,6 +278,37 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "derive_builder" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" +dependencies = [ + "derive_builder_core", + "syn", +] + [[package]] name = "devise" version = "0.4.2" @@ -273,7 +339,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.100", + "syn", ] [[package]] @@ -294,7 +360,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", ] [[package]] @@ -367,22 +433,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 +442,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,22 +474,26 @@ 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" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac0f7e83d14cccbf26e165d8881dcac5891af0d85a88543c09dd72ebd31d91ba" +checksum = "2a530c4694a6a8d528794ee9bbd8ba0122e779629ac908d15ad5a7ae7763a33d" +dependencies = [ + "thiserror 1.0.69", +] [[package]] name = "fluent-syntax" -version = "0.11.1" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a530c4694a6a8d528794ee9bbd8ba0122e779629ac908d15ad5a7ae7763a33d" +checksum = "54f0d287c53ffd184d04d8677f590f4ac5379785529e5e08b1c8083acdd5c198" dependencies = [ - "thiserror 1.0.69", + "memchr", + "thiserror 2.0.12", ] [[package]] @@ -538,15 +600,6 @@ dependencies = [ "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" @@ -657,20 +710,37 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "handlebars" +version = "6.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "759e2d5aea3287cb1190c8ec394f42866cb5bf74fcbf213f354e3c856ea26098" +dependencies = [ + "derive_builder", + "log", + "num-order", + "pest", + "pest_derive", + "serde", + "serde_json", + "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", - "handlebars", + "fluent-bundle 0.16.0", + "fluent-langneg", + "fluent-syntax 0.12.0", + "handlebars 6.3.2", "lazy_static", "serde_json", - "unic-langid 0.8.0", + "unic-langid", ] [[package]] @@ -876,7 +946,7 @@ checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" dependencies = [ "displaydoc", "litemap", - "tinystr 0.7.6", + "tinystr", "writeable", "zerovec", ] @@ -891,7 +961,7 @@ dependencies = [ "icu_locid", "icu_locid_transform_data", "icu_provider", - "tinystr 0.7.6", + "tinystr", "zerovec", ] @@ -936,7 +1006,7 @@ dependencies = [ "icu_locid_transform", "icu_properties_data", "icu_provider", - "tinystr 0.7.6", + "tinystr", "zerovec", ] @@ -956,7 +1026,7 @@ dependencies = [ "icu_locid", "icu_provider_macros", "stable_deref_trait", - "tinystr 0.7.6", + "tinystr", "writeable", "yoke", "zerofrom", @@ -971,9 +1041,15 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "1.0.3" @@ -1034,41 +1110,32 @@ dependencies = [ [[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" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe22e020fce238ae18a6d5d8c502ee76a52a6e880d99477657e6acc30ec57bda" +checksum = "310da2e345f5eb861e7a07ee182262e94975051db9e4223e909ba90f392f163f" dependencies = [ - "type-map 0.5.0", - "unic-langid 0.9.5", + "type-map", + "unic-langid", ] [[package]] name = "intl_pluralrules" -version = "6.0.0" +version = "7.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82c14d8eece42c03353e0ce86a4d3f97b1f1cef401e4d962dca6c6214a85002" +checksum = "078ea7b7c29a2b4df841a7f6ac8775ff6074020c6776d48491ce2268e068f972" dependencies = [ - "tinystr 0.3.4", - "unic-langid 0.8.0", + "unic-langid", ] [[package]] -name = "intl_pluralrules" -version = "7.0.2" +name = "io-uring" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "078ea7b7c29a2b4df841a7f6ac8775ff6074020c6776d48491ce2268e068f972" +checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" dependencies = [ - "unic-langid 0.9.5", + "bitflags 2.9.0", + "cfg-if", + "libc", ] [[package]] @@ -1323,6 +1390,21 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +[[package]] +name = "num-modular" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17bb261bf36fa7d83f4c294f834e91256769097b3cb505d44831e0a179ac647f" + +[[package]] +name = "num-order" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "537b596b97c40fcf8056d153049eb22f481c17ebce72a513ec9286e4986d1bb6" +dependencies = [ + "num-modular", +] + [[package]] name = "num_cpus" version = "1.16.0" @@ -1371,7 +1453,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", ] [[package]] @@ -1441,7 +1523,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.100", + "syn", ] [[package]] @@ -1481,7 +1563,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.100", + "syn", ] [[package]] @@ -1551,7 +1633,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", "version_check", "yansi", ] @@ -1627,7 +1709,7 @@ checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", ] [[package]] @@ -1674,27 +1756,6 @@ 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" @@ -1802,7 +1863,7 @@ dependencies = [ "proc-macro2", "quote", "rocket_http", - "syn 2.0.100", + "syn", "unicode-xid", "version_check", ] @@ -1813,7 +1874,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bbab919c9e67df3f7ac6624a32ef897df4cd61c0969f4d66f3ced0534660d7a" dependencies = [ - "handlebars", + "handlebars 5.1.2", "normpath", "notify", "rocket", @@ -1868,6 +1929,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + [[package]] name = "rustix" version = "1.0.5" @@ -2039,7 +2106,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", ] [[package]] @@ -2166,21 +2233,16 @@ dependencies = [ ] [[package]] -name = "subtle" -version = "2.6.1" +name = "strsim" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] -name = "syn" -version = "1.0.109" +name = "subtle" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" @@ -2210,7 +2272,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", ] [[package]] @@ -2273,7 +2335,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", ] [[package]] @@ -2284,7 +2346,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", ] [[package]] @@ -2328,12 +2390,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" @@ -2346,16 +2402,19 @@ dependencies = [ [[package]] name = "tokio" -version = "1.44.2" +version = "1.46.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" +checksum = "0cc3a2344dafbe23a245241fe8b09735b521110d30fcefbbd5feb1797ca35d17" dependencies = [ "backtrace", "bytes", + "io-uring", "libc", "mio 1.0.3", + "parking_lot", "pin-project-lite", "signal-hook-registry", + "slab", "socket2", "tokio-macros", "windows-sys 0.52.0", @@ -2369,7 +2428,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", ] [[package]] @@ -2503,7 +2562,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", ] [[package]] @@ -2551,22 +2610,13 @@ 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]] @@ -2600,32 +2650,14 @@ dependencies = [ "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", -] - [[package]] name = "unic-langid" 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]] @@ -2634,31 +2666,31 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a5422c1f65949306c99240b81de9f3f15929f5a8bfe05bb44b034cc8bf593e5" dependencies = [ - "tinystr 0.7.6", + "tinystr", ] [[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", + "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]] @@ -2776,7 +2808,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.100", + "syn", "wasm-bindgen-shared", ] @@ -2811,7 +2843,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3156,6 +3188,8 @@ checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" name = "www-rust-lang-org" version = "0.1.0" dependencies = [ + "anyhow", + "handlebars 6.3.2", "handlebars-fluent", "percent-encoding", "reqwest", @@ -3166,6 +3200,7 @@ dependencies = [ "serde", "serde_json", "time", + "tokio", "toml", ] @@ -3198,7 +3233,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", "synstructure", ] @@ -3219,7 +3254,7 @@ checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", ] [[package]] @@ -3239,7 +3274,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", "synstructure", ] @@ -3268,5 +3303,5 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn", ] diff --git a/Cargo.toml b/Cargo.toml index 29c5346ce..50b06cb6b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,10 @@ authors = ["The Rust Project Developers"] edition = "2024" [dependencies] -handlebars-fluent = "0.4.0" +anyhow = "1" +tokio = { version = "1", features = ["full"] } +handlebars = { version = "6", features = ["dir_source"] } +handlebars-fluent = "0.5" rocket = "0.5.1" rocket_dyn_templates = { version = "0.2.0", features = ["handlebars"] } serde = { version = "1.0", features = ["derive"] } diff --git a/src/cache.rs b/src/cache.rs index ec5adb61d..652c7b91d 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -13,7 +13,7 @@ pub type Cache = State>>; pub trait Cached: Send + Sync + Clone + 'static { fn get_timestamp(&self) -> Instant; - fn fetch() -> impl Future>> + Send; + fn fetch() -> impl Future> + Send; async fn get(cache: &Cache) -> Self { let cached = cache.read().await.clone(); let timestamp = cached.get_timestamp(); diff --git a/src/i18n.rs b/src/i18n.rs index 3b2eb75cf..5f2cce7a1 100644 --- a/src/i18n.rs +++ b/src/i18n.rs @@ -1,4 +1,4 @@ -use rocket_dyn_templates::handlebars::{ +use handlebars::{ Context, Handlebars, Helper, HelperDef, HelperResult, Output, RenderContext, RenderErrorReason, }; diff --git a/src/main.rs b/src/main.rs index a7d5c270a..a928eac33 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,7 @@ mod i18n; mod redirect; mod rust_version; mod teams; +mod render; use cache::Cache; use cache::Cached; @@ -20,11 +21,14 @@ use teams::encode_zulip_stream; use std::collections::hash_map::DefaultHasher; use std::env; use std::fs; +use std::fs::File; use std::hash::Hasher; +use std::io::BufWriter; use std::path::{Path, PathBuf}; use std::sync::Arc; use std::sync::LazyLock; - +use anyhow::Context as _; +use handlebars::{DirectorySourceOptions, Handlebars}; use rocket::{ fs::NamedFile, http::Status, @@ -38,7 +42,7 @@ use sass_rs::{Options, compile_file}; use category::Category; use caching::CachedNamedFile; -use handlebars_fluent::{FluentHelper, loader::Loader}; +use handlebars_fluent::{FluentHelper, loader::Loader, simple_loader}; use i18n::{EXPLICIT_LOCALE_INFO, LocaleInfo, SupportedLocale, TeamHelper, create_loader}; const ZULIP_DOMAIN: &str = "https://rust-lang.zulipchat.com"; @@ -404,50 +408,59 @@ fn render_subject(category: Category, subject: &str, lang: String) -> Result _ { - 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], - ) +// #[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], +// ) +// } + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + let rust_version = RustVersion::fetch().await?; + let teams = RustTeams::fetch().await?; + render::render(rust_version, teams)?; + + Ok(()) } diff --git a/src/render/assets.rs b/src/render/assets.rs new file mode 100644 index 000000000..4806ba655 --- /dev/null +++ b/src/render/assets.rs @@ -0,0 +1,125 @@ +use crate::render::fs::ensure_directory; +use anyhow::Context; +use rocket::serde::Serialize; +use sass_rs::{Options, compile_file}; +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) -> 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_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()))?; + + Ok(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}"))?; + + Ok(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, + baseurl: &str, +) -> anyhow::Result { + let app_css_file = compile_sass(root_dir, out_dir, "app")?; + let fonts_css_file = compile_sass(root_dir, out_dir, "fonts")?; + 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!("{baseurl}{app_css_file}"), + fonts: format!("{baseurl}{fonts_css_file}"), + vendor: format!("{baseurl}{vendor_css_file}"), + }, + js: JSFiles { + app: format!("{baseurl}{app_js_file}"), + }, + }) +} diff --git a/src/render/fs.rs b/src/render/fs.rs new file mode 100644 index 000000000..d6d2e27ea --- /dev/null +++ b/src/render/fs.rs @@ -0,0 +1,11 @@ +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(()) +} diff --git a/src/render/mod.rs b/src/render/mod.rs new file mode 100644 index 000000000..bdbf80488 --- /dev/null +++ b/src/render/mod.rs @@ -0,0 +1,244 @@ +mod assets; +mod fs; + +use crate::i18n::{EXPLICIT_LOCALE_INFO, LocaleInfo, SUPPORTED_LOCALES, TeamHelper, create_loader}; +use crate::render::assets::{AssetFiles, compile_assets}; +use crate::render::fs::ensure_directory; +use crate::rust_version::RustVersion; +use crate::teams::RustTeams; +use crate::{ENGLISH, LAYOUT, PONTOON_ENABLED, baseurl}; +use anyhow::Context; +use handlebars::{DirectorySourceOptions, Handlebars}; +use handlebars_fluent::{FluentHelper, Loader, SimpleLoader}; +use rust_team_data::v1::{Team, TeamKind}; +use serde::Serialize; +use std::cmp::Reverse; +use std::fs::File; +use std::io::BufWriter; +use std::path::{Path, PathBuf}; + +#[derive(Serialize)] +struct TemplateCtx<'a, T: Serialize> { + page: String, + title: String, + parent: &'static str, + is_landing: bool, + data: &'a T, + lang: String, + baseurl: String, + pontoon_enabled: bool, + assets: &'a AssetFiles, + locales: &'static [LocaleInfo], + is_translation: bool, +} + +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 + } + + fn render>(self, template: &str, path: P) -> anyhow::Result<()> { + let path = path.as_ref(); + + let out_path = self.output_dir.join(path); + ensure_directory(&out_path)?; + let mut output_file = BufWriter::new(File::create(&out_path)?); + 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(()) + } +} + +struct RenderCtx<'a> { + handlebars: Handlebars<'a>, + fluent_loader: SimpleLoader, + output_dir: PathBuf, + version: RustVersion, + teams: RustTeams, + assets: AssetFiles, +} + +impl<'a> RenderCtx<'a> { + 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: baseurl(&lang), + is_translation: lang != "en-US", + lang: lang.to_string(), + pontoon_enabled: *PONTOON_ENABLED, + assets: &self.assets, + locales: EXPLICIT_LOCALE_INFO, + }, + output_dir: &self.output_dir, + handlebars: &self.handlebars, + } + } + + fn copy_static_assets>(&self, src_dir: P, dst_dir: P) -> anyhow::Result<()> { + copy_dir_all(src_dir.as_ref(), self.output_dir.join(dst_dir.as_ref()))?; + Ok(()) + } +} + +fn all_langs(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 => path.to_string(), + l => format!("{l}/{path}"), + }; + func(&path, lang).with_context(|| anyhow::anyhow!("could not handle language {lang}"))?; + } + Ok(()) +} + +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(()) +} + +pub fn render(version: RustVersion, teams: RustTeams) -> anyhow::Result<()> { + // Prepare build directory + let output_dir = PathBuf::from("html"); + let _ = std::fs::remove_dir_all(&output_dir); + std::fs::create_dir_all(&output_dir)?; + + // Compile assets + let assets = compile_assets(Path::new("."), &output_dir, "/")?; + + // Setup handlebars + let mut template_ctx: Handlebars<'static> = Handlebars::new(); + template_ctx.set_strict_mode(true); + + let mut options = DirectorySourceOptions::default(); + options.tpl_extension = ".html.hbs".to_string(); + template_ctx + .register_templates_directory("templates", options) + .context("cannot register template directory")?; + + let loader = create_loader(); + let helper = FluentHelper::new(loader); + template_ctx.register_helper("fluent", Box::new(helper)); + template_ctx.register_helper("team-text", Box::new(TeamHelper::new())); + + let ctx = RenderCtx { + fluent_loader: create_loader(), + assets, + version, + teams, + handlebars: template_ctx, + output_dir, + }; + ctx.copy_static_assets("static", "static")?; + + render_index(&ctx)?; + render_governance(&ctx)?; + + Ok(()) +} + +fn render_index(render_ctx: &RenderCtx) -> anyhow::Result<()> { + #[derive(Serialize)] + struct IndexData { + rust_version: String, + foo: Vec, + } + let data = IndexData { + rust_version: render_ctx.version.0.clone(), + foo: vec![1, 2, 3], + }; + all_langs("index.html", |path, lang| { + render_ctx + .page("index", "", &data, lang) + .make_landing() + .render("index", path) + }) +} + +fn render_governance(render_ctx: &RenderCtx) -> anyhow::Result<()> { + #[derive(Default, Serialize)] + pub struct IndexData { + teams: Vec, + } + + #[derive(Serialize)] + struct IndexTeam { + #[serde(flatten)] + team: Team, + url: String, + } + + let mut data = IndexData::default(); + + render_ctx + .teams + .0 + .as_ref() + .unwrap() + .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 { + url: format!( + "{}/{}", + crate::teams::kind_to_str(team.kind), + team.website_data.as_ref().unwrap().page + ), + team: team.clone(), + }) + .for_each(|team| data.teams.push(team)); + + data.teams + .sort_by_key(|index_team| Reverse(index_team.team.website_data.as_ref().unwrap().weight)); + + all_langs("governance/index.html", |path, lang| { + render_ctx + .page("governance/index", "governance-page-title", &data, lang) + .render("governance/index", path) + }) +} diff --git a/src/rust_version.rs b/src/rust_version.rs index e1ce547cf..83ddf2856 100644 --- a/src/rust_version.rs +++ b/src/rust_version.rs @@ -10,7 +10,7 @@ enum FetchTarget { Manifest, } -async fn fetch(target: FetchTarget) -> Result> { +async fn fetch(target: FetchTarget) -> anyhow::Result { let proxy_env = env::var("http_proxy") .or_else(|_| env::var("HTTPS_PROXY")) .ok(); @@ -43,7 +43,7 @@ impl Cached for RustVersion { fn get_timestamp(&self) -> Instant { self.1 } - async fn fetch() -> Result> { + async fn fetch() -> anyhow::Result { let manifest = fetch(FetchTarget::Manifest) .await? .text() diff --git a/src/teams.rs b/src/teams.rs index bc0c65f28..e26d9bfb3 100644 --- a/src/teams.rs +++ b/src/teams.rs @@ -253,7 +253,7 @@ impl Cached for RustTeams { fn get_timestamp(&self) -> Instant { self.1 } - async fn fetch() -> Result> { + async fn fetch() -> anyhow::Result { let resp: Teams = reqwest::get(format!("{BASE_URL}/teams.json")) .await? .error_for_status()? @@ -272,7 +272,7 @@ impl Cached for RustTeams { } } -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", diff --git a/templates/governance/index-team.html.hbs b/templates/governance/index-team.html.hbs index e5967a5c7..371a32a23 100644 --- a/templates/governance/index-team.html.hbs +++ b/templates/governance/index-team.html.hbs @@ -1,7 +1,7 @@

{{team-text team name}}

{{team-text team description}}

- + {{fluent "governance-members"}}
diff --git a/templates/governance/index.html.hbs b/templates/governance/index.html.hbs index 20ae88fdb..82492294e 100644 --- a/templates/governance/index.html.hbs +++ b/templates/governance/index.html.hbs @@ -31,7 +31,7 @@
{{#each data.teams as |team| ~}} - {{> governance/index-team}} + {{> governance/index-team team=team baseurl=baseurl}} {{/each~}}
From aed991f04fccddd0538b62434383e66fb56669f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 5 Aug 2025 21:39:50 +0200 Subject: [PATCH 14/21] Remove old code and render individual categories --- src/{render => }/assets.rs | 2 +- src/cache.rs | 32 -- src/caching.rs | 21 -- src/category.rs | 37 --- src/{render => }/fs.rs | 0 src/main.rs | 610 ++++++++++++------------------------- src/render/mod.rs | 244 --------------- src/rust_version.rs | 69 +---- src/teams.rs | 219 +++++-------- 9 files changed, 299 insertions(+), 935 deletions(-) rename src/{render => }/assets.rs (98%) delete mode 100644 src/cache.rs delete mode 100644 src/caching.rs delete mode 100644 src/category.rs rename src/{render => }/fs.rs (100%) delete mode 100644 src/render/mod.rs diff --git a/src/render/assets.rs b/src/assets.rs similarity index 98% rename from src/render/assets.rs rename to src/assets.rs index 4806ba655..dcbd5f10e 100644 --- a/src/render/assets.rs +++ b/src/assets.rs @@ -1,4 +1,4 @@ -use crate::render::fs::ensure_directory; +use crate::fs::ensure_directory; use anyhow::Context; use rocket::serde::Serialize; use sass_rs::{Options, compile_file}; diff --git a/src/cache.rs b/src/cache.rs deleted file mode 100644 index 652c7b91d..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/render/fs.rs b/src/fs.rs similarity index 100% rename from src/render/fs.rs rename to src/fs.rs diff --git a/src/main.rs b/src/main.rs index a928eac33..c4937b753 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,466 +1,260 @@ -mod cache; -mod caching; -mod category; -mod headers; -mod i18n; -mod redirect; -mod rust_version; -mod teams; -mod render; - -use cache::Cache; -use cache::Cached; -use rocket::catch; -use rocket::get; -use rocket::tokio::sync::RwLock; -use rust_version::RustVersion; +use crate::assets::{AssetFiles, compile_assets}; +use crate::category::Category; +use crate::fs::ensure_directory; +use crate::i18n::{EXPLICIT_LOCALE_INFO, LocaleInfo, SUPPORTED_LOCALES, TeamHelper, create_loader}; +use crate::rust_version::{RustVersion, fetch_rust_version}; +use crate::teams::{RustTeams, load_rust_teams}; +use anyhow::Context; +use handlebars::{DirectorySourceOptions, Handlebars}; +use handlebars_fluent::{FluentHelper, Loader, SimpleLoader}; 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::fs::File; -use std::hash::Hasher; use std::io::BufWriter; use std::path::{Path, PathBuf}; -use std::sync::Arc; -use std::sync::LazyLock; -use anyhow::Context as _; -use handlebars::{DirectorySourceOptions, Handlebars}; -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; +mod assets; +mod category; +mod fs; +mod i18n; +mod rust_version; +mod teams; -use caching::CachedNamedFile; -use handlebars_fluent::{FluentHelper, loader::Loader, simple_loader}; -use i18n::{EXPLICIT_LOCALE_INFO, LocaleInfo, SupportedLocale, TeamHelper, create_loader}; +static PONTOON_ENABLED: bool = false; 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"]); +static LAYOUT: &str = "components/layout"; +static ENGLISH: &str = "en-US"; - AssetFiles { - css: CSSFiles { - app: app_css_file, - fonts: fonts_css_file, - vendor: vendor_css_file, - }, - js: JSFiles { app: app_js_file }, +fn baseurl(lang: &str) -> String { + if lang == "en-US" { + String::new() + } else { + format!("/{lang}") } -}); -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 { +struct TemplateCtx<'a, T: Serialize> { page: String, title: String, parent: &'static str, is_landing: bool, - data: T, + data: &'a T, lang: String, baseurl: String, pontoon_enabled: bool, - assets: &'static AssetFiles, + assets: &'a 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, +struct PageCtx<'a, T: Serialize> { + template_ctx: TemplateCtx<'a, T>, + output_dir: &'a Path, + handlebars: &'a Handlebars<'a>, } -#[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}") +impl<'a, T: Serialize> PageCtx<'a, T> { + fn make_landing(mut self) -> Self { + self.template_ctx.is_landing = true; + self } -} -#[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)) -} - -#[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 + 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)?); + 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(()) } } -#[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("/") +struct RenderCtx<'a> { + handlebars: Handlebars<'a>, + fluent_loader: SimpleLoader, + output_dir: PathBuf, + rust_version: RustVersion, + teams: RustTeams, + assets: AssetFiles, } -#[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); - } - - let lang = if let Some(next) = req.uri().path().segments().next() { - if let Ok(lang) = SupportedLocale::from_param(next) { - lang.0 +impl<'a> RenderCtx<'a> { + 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 { - ENGLISH.into() + 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: baseurl(&lang), + is_translation: lang != "en-US", + lang: lang.to_string(), + pontoon_enabled: PONTOON_ENABLED, + assets: &self.assets, + locales: EXPLICIT_LOCALE_INFO, + }, + output_dir: &self.output_dir, + handlebars: &self.handlebars, } - } 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 copy_static_assets>(&self, src_dir: P, dst_dir: P) -> anyhow::Result<()> { + let dst = self.output_dir.join(dst_dir.as_ref()); + println!( + "Copying static assets from {} to {}", + src_dir.as_ref().display(), + dst.display() + ); + copy_dir_all(src_dir.as_ref(), dst)?; + Ok(()) + } } -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..]) +/// 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. +fn 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(()) } -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); +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(()) +} - let css_sha = format!("vendor_{}", hash_css(&concatted)); - let css_path = format!("./static/styles/{}.css", &css_sha); +fn setup_handlebars() -> anyhow::Result> { + let mut handlebars: Handlebars<'static> = Handlebars::new(); + handlebars.set_strict_mode(true); - fs::write(&css_path, &concatted).expect("couldn't write vendor css"); + let mut options = DirectorySourceOptions::default(); + options.tpl_extension = ".html.hbs".to_string(); + handlebars + .register_templates_directory("templates", options) + .context("cannot register template directory")?; - String::from(&css_path[1..]) + 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())); + Ok(handlebars) } -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); - } +#[tokio::main] +async fn main() -> anyhow::Result<()> { + let rust_version = fetch_rust_version().await?; + let teams = load_rust_teams().await?; + + // Prepare build directory + let output_dir = PathBuf::from("html"); + let _ = std::fs::remove_dir_all(&output_dir); + std::fs::create_dir_all(&output_dir)?; + + let assets = compile_assets(Path::new("."), &output_dir, "/")?; + let handlebars = setup_handlebars()?; + + let ctx = RenderCtx { + fluent_loader: create_loader(), + assets, + rust_version, + teams, + handlebars, + output_dir, + }; + ctx.copy_static_assets("static", "static")?; - let js_sha = format!("app_{}", hash_css(&concatted)); - let js_path = format!("./static/scripts/{}.js", &js_sha); + render_index(&ctx)?; + render_governance(&ctx)?; + render_category(&ctx, "community")?; + render_category(&ctx, "learn")?; + render_category(&ctx, "policies")?; + render_category(&ctx, "tools")?; + render_category(&ctx, "what")?; - fs::write(&js_path, &concatted).expect("couldn't write app js"); + // TODO: 404, redirects - String::from(&js_path[1..]) + Ok(()) } -async fn render_index(lang: String, version_cache: &Cache) -> Template { +fn render_index(render_ctx: &RenderCtx) -> anyhow::Result<()> { #[derive(Serialize)] struct IndexData { rust_version: String, } - - let page = "index"; let data = IndexData { - rust_version: rust_version::rust_version(version_cache).await, + rust_version: render_ctx.rust_version.0.clone(), }; - 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], -// ) -// } - -#[tokio::main] -async fn main() -> anyhow::Result<()> { - let rust_version = RustVersion::fetch().await?; - let teams = RustTeams::fetch().await?; - render::render(rust_version, teams)?; - - Ok(()) + all_langs("index.html", |path, lang| { + render_ctx + .page("index", "", &data, lang) + .make_landing() + .render(path) + }) +} + +fn render_governance(render_ctx: &RenderCtx) -> anyhow::Result<()> { + let data = render_ctx.teams.index_data(); + + all_langs("governance/index.html", |dst_path, lang| { + render_ctx + .page("governance/index", "governance-page-title", &data, lang) + .render(dst_path) + }) +} + +fn render_category(render_ctx: &RenderCtx, category: &str) -> anyhow::Result<()> { + all_langs(&format!("{category}/index.html"), |dst_path, lang| { + render_ctx + .page( + &format!("{category}/index"), + &format!("{category}-page-title"), + &(), + lang, + ) + .render(dst_path) + }) } diff --git a/src/render/mod.rs b/src/render/mod.rs deleted file mode 100644 index bdbf80488..000000000 --- a/src/render/mod.rs +++ /dev/null @@ -1,244 +0,0 @@ -mod assets; -mod fs; - -use crate::i18n::{EXPLICIT_LOCALE_INFO, LocaleInfo, SUPPORTED_LOCALES, TeamHelper, create_loader}; -use crate::render::assets::{AssetFiles, compile_assets}; -use crate::render::fs::ensure_directory; -use crate::rust_version::RustVersion; -use crate::teams::RustTeams; -use crate::{ENGLISH, LAYOUT, PONTOON_ENABLED, baseurl}; -use anyhow::Context; -use handlebars::{DirectorySourceOptions, Handlebars}; -use handlebars_fluent::{FluentHelper, Loader, SimpleLoader}; -use rust_team_data::v1::{Team, TeamKind}; -use serde::Serialize; -use std::cmp::Reverse; -use std::fs::File; -use std::io::BufWriter; -use std::path::{Path, PathBuf}; - -#[derive(Serialize)] -struct TemplateCtx<'a, T: Serialize> { - page: String, - title: String, - parent: &'static str, - is_landing: bool, - data: &'a T, - lang: String, - baseurl: String, - pontoon_enabled: bool, - assets: &'a AssetFiles, - locales: &'static [LocaleInfo], - is_translation: bool, -} - -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 - } - - fn render>(self, template: &str, path: P) -> anyhow::Result<()> { - let path = path.as_ref(); - - let out_path = self.output_dir.join(path); - ensure_directory(&out_path)?; - let mut output_file = BufWriter::new(File::create(&out_path)?); - 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(()) - } -} - -struct RenderCtx<'a> { - handlebars: Handlebars<'a>, - fluent_loader: SimpleLoader, - output_dir: PathBuf, - version: RustVersion, - teams: RustTeams, - assets: AssetFiles, -} - -impl<'a> RenderCtx<'a> { - 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: baseurl(&lang), - is_translation: lang != "en-US", - lang: lang.to_string(), - pontoon_enabled: *PONTOON_ENABLED, - assets: &self.assets, - locales: EXPLICIT_LOCALE_INFO, - }, - output_dir: &self.output_dir, - handlebars: &self.handlebars, - } - } - - fn copy_static_assets>(&self, src_dir: P, dst_dir: P) -> anyhow::Result<()> { - copy_dir_all(src_dir.as_ref(), self.output_dir.join(dst_dir.as_ref()))?; - Ok(()) - } -} - -fn all_langs(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 => path.to_string(), - l => format!("{l}/{path}"), - }; - func(&path, lang).with_context(|| anyhow::anyhow!("could not handle language {lang}"))?; - } - Ok(()) -} - -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(()) -} - -pub fn render(version: RustVersion, teams: RustTeams) -> anyhow::Result<()> { - // Prepare build directory - let output_dir = PathBuf::from("html"); - let _ = std::fs::remove_dir_all(&output_dir); - std::fs::create_dir_all(&output_dir)?; - - // Compile assets - let assets = compile_assets(Path::new("."), &output_dir, "/")?; - - // Setup handlebars - let mut template_ctx: Handlebars<'static> = Handlebars::new(); - template_ctx.set_strict_mode(true); - - let mut options = DirectorySourceOptions::default(); - options.tpl_extension = ".html.hbs".to_string(); - template_ctx - .register_templates_directory("templates", options) - .context("cannot register template directory")?; - - let loader = create_loader(); - let helper = FluentHelper::new(loader); - template_ctx.register_helper("fluent", Box::new(helper)); - template_ctx.register_helper("team-text", Box::new(TeamHelper::new())); - - let ctx = RenderCtx { - fluent_loader: create_loader(), - assets, - version, - teams, - handlebars: template_ctx, - output_dir, - }; - ctx.copy_static_assets("static", "static")?; - - render_index(&ctx)?; - render_governance(&ctx)?; - - Ok(()) -} - -fn render_index(render_ctx: &RenderCtx) -> anyhow::Result<()> { - #[derive(Serialize)] - struct IndexData { - rust_version: String, - foo: Vec, - } - let data = IndexData { - rust_version: render_ctx.version.0.clone(), - foo: vec![1, 2, 3], - }; - all_langs("index.html", |path, lang| { - render_ctx - .page("index", "", &data, lang) - .make_landing() - .render("index", path) - }) -} - -fn render_governance(render_ctx: &RenderCtx) -> anyhow::Result<()> { - #[derive(Default, Serialize)] - pub struct IndexData { - teams: Vec, - } - - #[derive(Serialize)] - struct IndexTeam { - #[serde(flatten)] - team: Team, - url: String, - } - - let mut data = IndexData::default(); - - render_ctx - .teams - .0 - .as_ref() - .unwrap() - .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 { - url: format!( - "{}/{}", - crate::teams::kind_to_str(team.kind), - team.website_data.as_ref().unwrap().page - ), - team: team.clone(), - }) - .for_each(|team| data.teams.push(team)); - - data.teams - .sort_by_key(|index_team| Reverse(index_team.team.website_data.as_ref().unwrap().weight)); - - all_langs("governance/index.html", |path, lang| { - render_ctx - .page("governance/index", "governance-page-title", &data, lang) - .render("governance/index", path) - }) -} diff --git a/src/rust_version.rs b/src/rust_version.rs index 83ddf2856..a805497d7 100644 --- a/src/rust_version.rs +++ b/src/rust_version.rs @@ -1,60 +1,17 @@ -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) -> anyhow::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()) - } -} - -impl Cached for RustVersion { - fn get_timestamp(&self) -> Instant { - self.1 - } - async fn fetch() -> anyhow::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 +pub struct RustVersion(pub String); + +/// Fetch the latest stable version of Rust. +pub async fn fetch_rust_version() -> anyhow::Result { + println!("Downloading Rust version"); + let manifest = reqwest::get(MANIFEST_URL) + .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)) } diff --git a/src/teams.rs b/src/teams.rs index e26d9bfb3..2a64005ee 100644 --- a/src/teams.rs +++ b/src/teams.rs @@ -8,59 +8,58 @@ 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 @@ -74,22 +73,19 @@ 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_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)) .find(|team| kind_to_str(team.kind) == section) @@ -116,13 +112,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,86 +185,38 @@ 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 { + teams: Vec, } -pub async fn index_data( - teams_cache: &Cache, -) -> Result> { - Data::load(teams_cache).await?.index_data() +#[derive(Serialize)] +pub struct IndexTeam { + #[serde(flatten)] + team: Team, + url: 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 { + 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, } -#[derive(Debug, Clone)] -pub struct RustTeams(pub Option>, pub Instant); +pub async fn load_rust_teams() -> anyhow::Result { + println!("Downloading Team API data"); + let resp: Teams = reqwest::get(format!("{BASE_URL}/teams.json")) + .await? + .error_for_status()? + .json() + .await?; -impl Default for RustTeams { - fn default() -> Self { - Self(Default::default(), Instant::now()) - } -} - -impl Cached for RustTeams { - fn get_timestamp(&self) -> Instant { - self.1 - } - async fn fetch() -> anyhow::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(), - )) - } + Ok(RustTeams(resp.teams.into_values().collect())) } pub(crate) fn kind_to_str(kind: TeamKind) -> &'static str { @@ -299,7 +246,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 +300,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 +312,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 +337,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 +366,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 +394,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") From ef1ab10e2bc6d357cfa9401e7cc3bfcd1ea7e86b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 6 Aug 2025 12:00:58 +0200 Subject: [PATCH 15/21] Add governance pages --- src/main.rs | 135 ++++++++++++++---- src/teams.rs | 24 ++-- templates/governance/group-team.html.hbs | 172 +++++++++++------------ templates/governance/group.html.hbs | 10 +- 4 files changed, 215 insertions(+), 126 deletions(-) diff --git a/src/main.rs b/src/main.rs index c4937b753..abc34b469 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,19 +1,18 @@ use crate::assets::{AssetFiles, compile_assets}; -use crate::category::Category; use crate::fs::ensure_directory; use crate::i18n::{EXPLICIT_LOCALE_INFO, LocaleInfo, SUPPORTED_LOCALES, TeamHelper, create_loader}; use crate::rust_version::{RustVersion, fetch_rust_version}; -use crate::teams::{RustTeams, load_rust_teams}; +use crate::teams::{PageData, RustTeams, encode_zulip_stream, load_rust_teams}; use anyhow::Context; use handlebars::{DirectorySourceOptions, Handlebars}; use handlebars_fluent::{FluentHelper, Loader, SimpleLoader}; use serde::Serialize; +use std::ffi::OsStr; use std::fs::File; use std::io::BufWriter; use std::path::{Path, PathBuf}; mod assets; -mod category; mod fs; mod i18n; mod rust_version; @@ -67,7 +66,10 @@ impl<'a, T: Serialize> PageCtx<'a, T> { let out_path = self.output_dir.join(path); ensure_directory(&out_path)?; - let mut output_file = BufWriter::new(File::create(&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 @@ -84,6 +86,7 @@ impl<'a, T: Serialize> PageCtx<'a, T> { struct RenderCtx<'a> { handlebars: Handlebars<'a>, + template_dir: PathBuf, fluent_loader: SimpleLoader, output_dir: PathBuf, rust_version: RustVersion, @@ -124,16 +127,28 @@ impl<'a> RenderCtx<'a> { } } - fn copy_static_assets>(&self, src_dir: P, dst_dir: P) -> anyhow::Result<()> { + 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 assets from {} to {}", + "Copying static asset directory from {} to {}", src_dir.as_ref().display(), dst.display() ); copy_dir_all(src_dir.as_ref(), dst)?; Ok(()) } + + 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. @@ -181,6 +196,7 @@ fn setup_handlebars() -> anyhow::Result> { 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) } @@ -194,10 +210,12 @@ async fn main() -> anyhow::Result<()> { let _ = std::fs::remove_dir_all(&output_dir); std::fs::create_dir_all(&output_dir)?; - let assets = compile_assets(Path::new("."), &output_dir, "/")?; + let root_dir = Path::new("."); + let assets = compile_assets(root_dir, &output_dir, "/")?; let handlebars = setup_handlebars()?; let ctx = RenderCtx { + template_dir: root_dir.join("templates"), fluent_loader: create_loader(), assets, rust_version, @@ -205,17 +223,22 @@ async fn main() -> anyhow::Result<()> { handlebars, output_dir, }; - ctx.copy_static_assets("static", "static")?; + 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_category(&ctx, "community")?; - render_category(&ctx, "learn")?; - render_category(&ctx, "policies")?; - render_category(&ctx, "tools")?; - render_category(&ctx, "what")?; + 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")?; - // TODO: 404, redirects + // TODO: redirects Ok(()) } @@ -243,18 +266,78 @@ fn render_governance(render_ctx: &RenderCtx) -> anyhow::Result<()> { 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 + all_langs( + &format!("governance/{}/index.html", team.url), + |dst_path, lang| { + render_ctx + .page( + "governance/group", + &format!("governance-team-{}-title", team.team.name), + &data, + lang, + ) + .render(dst_path) + }, + )?; + } + + Ok(()) } -fn render_category(render_ctx: &RenderCtx, category: &str) -> anyhow::Result<()> { - all_langs(&format!("{category}/index.html"), |dst_path, lang| { - render_ctx - .page( - &format!("{category}/index"), - &format!("{category}-page-title"), - &(), - lang, - ) - .render(dst_path) - }) +/// Render all templates found in the given directory. +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" { + 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. + 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(()) } diff --git a/src/teams.rs b/src/teams.rs index 2a64005ee..7a7f79bf5 100644 --- a/src/teams.rs +++ b/src/teams.rs @@ -1,7 +1,7 @@ -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; @@ -66,6 +66,8 @@ impl RustTeams { // 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), @@ -81,13 +83,15 @@ impl RustTeams { IndexData { teams } } - pub fn page_data(&self, section: &str, team_name: &str) -> anyhow::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 = 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)?; @@ -187,19 +191,21 @@ impl RustTeams { #[derive(Serialize)] pub struct IndexData { - teams: Vec, + pub teams: Vec, } -#[derive(Serialize)] +#[derive(Serialize, Debug)] pub struct IndexTeam { #[serde(flatten)] - team: Team, - url: String, + pub team: Team, + pub url: String, + pub section: &'static str, + pub page_name: String, } #[derive(Serialize)] pub struct PageData { - pub team: Team, + team: Team, zulip_domain: &'static str, subteams: Vec, wgs: Vec, diff --git a/templates/governance/group-team.html.hbs b/templates/governance/group-team.html.hbs index 8bc133216..3da321283 100644 --- a/templates/governance/group-team.html.hbs +++ b/templates/governance/group-team.html.hbs @@ -1,106 +1,106 @@
-
- -

{{team-text team name}}

-
-
-
-
- +
+ +

{{team-text team name}}

+
+
+
+ + {{#if team.members}}
-

{{fluent "governance-members-header"}}

+

{{fluent "governance-members-header"}}

- {{#each team.members as |member|}} + {{#each team.members as |member|}}
- - {{member.name}} - -
-

{{member.name}}

-
- {{#fluent "governance-user-github"}} - {{#fluentparam "link"}} - {{member.github}} - {{/fluentparam}} - {{/fluent}} -
- {{#if member.is_lead}} -
{{fluent "governance-user-team-leader"}}
- {{else}} - {{#if member.roles}} -
{{team-text team role (lookup member.roles 0)}}
- {{/if}} - {{/if}} + + {{member.name}} + +
+

{{member.name}}

+
+ {{#fluent "governance-user-github"}} + {{#fluentparam "link"}} + {{member.github}} + {{/fluentparam}} + {{/fluent}}
+ {{#if member.is_lead}} +
{{fluent "governance-user-team-leader"}}
+ {{else}} + {{#if member.roles}} +
{{team-text ../team role (lookup member.roles 0)}}
+ {{/if}} + {{/if}} +
- {{/each}} + {{/each}}
{{#if team.alumni}} -
+

{{fluent "governance-alumni-header"}}

-
-

{{fluent "governance-alumni-thanks"}}

-
+
+

{{fluent "governance-alumni-thanks"}}

+
{{#each team.alumni as |member|}} -
+
- {{member.name}} + {{member.name}}
- {{member.name}} -
- GitHub: {{member.github}} -
- {{#if member.roles}} -
{{team-text team role (lookup member.roles 0)}}
- {{/if}} + {{member.name}} +
+ GitHub: {{member.github}} +
+ {{#if member.roles}} +
{{team-text ../team role (lookup member.roles 0)}}
+ {{/if}}
-
+
{{/each}} -
- {{/if}} +
{{/if}} + {{/if}}
diff --git a/templates/governance/group.html.hbs b/templates/governance/group.html.hbs index dd67bcec5..9f135ee0a 100644 --- a/templates/governance/group.html.hbs +++ b/templates/governance/group.html.hbs @@ -2,34 +2,34 @@ {{#with data.team as |team|}}
- {{> governance/group-team}} + {{> governance/group-team team=team zulip_domain=data.zulip_domain}}
{{/with}} {{#if data.subteams}}
{{#each data.subteams as |team|}} - {{> governance/group-team}} + {{> governance/group-team team=team zulip_domain=data.zulip_domain}} {{/each}}
{{/if}} {{#if data.project_groups}}
{{#each data.project_groups as |team|}} - {{> governance/group-team}} + {{> governance/group-team team=team zulip_domain=data.zulip_domain}} {{/each}}
{{/if}} {{#if data.wgs}}
{{#each data.wgs as |team|}} - {{> governance/group-team}} + {{> governance/group-team team=team zulip_domain=data.zulip_domain}} {{/each}}
{{/if}} {{#if data.other_teams}}
{{#each data.other_teams as |team|}} - {{> governance/group-team}} + {{> governance/group-team team=team zulip_domain=data.zulip_domain}} {{/each}}
{{/if}} From c3701454dc43943c6028e8b321c07a86c946cd77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 6 Aug 2025 12:06:48 +0200 Subject: [PATCH 16/21] Remove rocket --- Cargo.lock | 1081 +++---------------------------------------------- Cargo.toml | 2 - src/assets.rs | 2 +- src/i18n.rs | 15 - 4 files changed, 55 insertions(+), 1045 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3a626f725..c91e9a2dd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,69 +17,12 @@ 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 = "anyhow" version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" -[[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", -] - -[[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", -] - -[[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" @@ -113,18 +56,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" @@ -146,12 +77,6 @@ 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 = "bytes" version = "1.10.1" @@ -173,17 +98,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "cookie" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" -dependencies = [ - "percent-encoding", - "time", - "version_check", -] - [[package]] name = "core-foundation" version = "0.9.4" @@ -209,21 +123,6 @@ dependencies = [ "libc", ] -[[package]] -name = "crossbeam-channel" -version = "0.5.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - [[package]] name = "crypto-common" version = "0.1.6" @@ -309,39 +208,6 @@ dependencies = [ "syn", ] -[[package]] -name = "devise" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1d90b0c4c777a2cad215e3c7be59ac7c15adf45cf76317009b7d096d46f651d" -dependencies = [ - "devise_codegen", - "devise_core", -] - -[[package]] -name = "devise_codegen" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71b28680d8be17a570a2334922518be6adc3f58ecc880cbb404eaeb8624fd867" -dependencies = [ - "devise_core", - "quote", -] - -[[package]] -name = "devise_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b035a542cf7abf01f2e3c4d5a7acbaebfefe120ae4efc7bde3df98186e4b8af7" -dependencies = [ - "bitflags 2.9.0", - "proc-macro2", - "proc-macro2-diagnostics", - "quote", - "syn", -] - [[package]] name = "digest" version = "0.10.7" @@ -363,12 +229,6 @@ dependencies = [ "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" @@ -400,32 +260,6 @@ 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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" -dependencies = [ - "cfg-if", - "libc", - "libredox", - "windows-sys 0.59.0", -] - [[package]] name = "fluent" version = "0.16.1" @@ -526,29 +360,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" @@ -556,7 +367,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", - "futures-sink", ] [[package]] @@ -565,12 +375,6 @@ 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" @@ -589,28 +393,10 @@ 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 = "generator" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" -dependencies = [ - "cc", - "libc", - "log", - "rustversion", - "windows", ] [[package]] @@ -652,31 +438,6 @@ 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" @@ -688,7 +449,7 @@ dependencies = [ "fnv", "futures-core", "futures-sink", - "http 1.3.1", + "http", "indexmap", "slab", "tokio", @@ -696,20 +457,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "handlebars" -version = "5.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d08485b96a0e6393e9e4d1b8d48cf74ad6c063cd905eb33f42c1ce3f0377539b" -dependencies = [ - "log", - "pest", - "pest_derive", - "serde", - "serde_json", - "thiserror 1.0.69", -] - [[package]] name = "handlebars" version = "6.3.2" @@ -737,7 +484,7 @@ dependencies = [ "fluent-bundle 0.16.0", "fluent-langneg", "fluent-syntax 0.12.0", - "handlebars 6.3.2", + "handlebars", "lazy_static", "serde_json", "unic-langid", @@ -755,23 +502,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" @@ -783,17 +513,6 @@ 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" @@ -801,7 +520,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.3.1", + "http", ] [[package]] @@ -812,8 +531,8 @@ checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", "futures-core", - "http 1.3.1", - "http-body 1.0.1", + "http", + "http-body", "pin-project-lite", ] @@ -823,36 +542,6 @@ 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" @@ -862,9 +551,9 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.9", - "http 1.3.1", - "http-body 1.0.1", + "h2", + "http", + "http-body", "httparse", "itoa", "pin-project-lite", @@ -880,8 +569,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" dependencies = [ "futures-util", - "http 1.3.1", - "hyper 1.6.0", + "http", + "hyper", "hyper-util", "rustls", "rustls-pki-types", @@ -898,7 +587,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.6.0", + "hyper", "hyper-util", "native-tls", "tokio", @@ -915,9 +604,9 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "http 1.3.1", - "http-body 1.0.1", - "hyper 1.6.0", + "http", + "http-body", + "hyper", "libc", "pin-project-lite", "socket2", @@ -1082,32 +771,6 @@ 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.5.3" @@ -1133,7 +796,7 @@ version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" dependencies = [ - "bitflags 2.9.0", + "bitflags", "cfg-if", "libc", ] @@ -1144,17 +807,6 @@ 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", -] - [[package]] name = "itoa" version = "1.0.15" @@ -1171,26 +823,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "kqueue" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" -dependencies = [ - "kqueue-sys", - "libc", -] - -[[package]] -name = "kqueue-sys" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" -dependencies = [ - "bitflags 1.3.2", - "libc", -] - [[package]] name = "lazy_static" version = "1.5.0" @@ -1203,17 +835,6 @@ 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" @@ -1242,30 +863,6 @@ 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" @@ -1287,18 +884,6 @@ 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" @@ -1310,25 +895,6 @@ dependencies = [ "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" @@ -1346,44 +912,6 @@ dependencies = [ "tempfile", ] -[[package]] -name = "normpath" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8911957c4b1549ac0dc74e30db9c8b0e66ddcd6d7acc33098f4c63a64a6d7ed" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "notify" -version = "6.1.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", -] - -[[package]] -name = "nu-ansi-term" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" -dependencies = [ - "overload", - "winapi", -] - [[package]] name = "num-conv" version = "0.1.0" @@ -1411,7 +939,7 @@ 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", ] @@ -1436,7 +964,7 @@ version = "0.10.72" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" dependencies = [ - "bitflags 2.9.0", + "bitflags", "cfg-if", "foreign-types", "libc", @@ -1474,12 +1002,6 @@ dependencies = [ "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" @@ -1503,29 +1025,6 @@ dependencies = [ "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", -] - [[package]] name = "percent-encoding" version = "2.3.1" @@ -1587,174 +1086,58 @@ checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" 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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "proc-macro-hack" -version = "0.5.20+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" - -[[package]] -name = "proc-macro2" -version = "1.0.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" -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", - "version_check", - "yansi", -] - -[[package]] -name = "quote" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" -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", -] +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] -name = "ref-cast" -version = "1.0.24" +name = "pkg-config" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" -dependencies = [ - "ref-cast-impl", -] +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] -name = "ref-cast-impl" -version = "1.0.24" +name = "powerfmt" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] -name = "regex" -version = "1.11.1" +name = "proc-macro-hack" +version = "0.5.20+deprecated" 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", -] +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] -name = "regex-automata" -version = "0.1.10" +name = "proc-macro2" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ - "regex-syntax 0.6.29", + "unicode-ident", ] [[package]] -name = "regex-automata" -version = "0.4.9" +name = "quote" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax 0.8.5", + "proc-macro2", ] [[package]] -name = "regex-syntax" -version = "0.6.29" +name = "r-efi" +version = "5.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" [[package]] -name = "regex-syntax" -version = "0.8.5" +name = "redox_syscall" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" +dependencies = [ + "bitflags", +] [[package]] name = "reqwest" @@ -1767,11 +1150,11 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "h2 0.4.9", - "http 1.3.1", - "http-body 1.0.1", + "h2", + "http", + "http-body", "http-body-util", - "hyper 1.6.0", + "hyper", "hyper-rustls", "hyper-tls", "hyper-util", @@ -1814,100 +1197,6 @@ dependencies = [ "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", - "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 5.1.2", - "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", -] - [[package]] name = "rust_team_data" version = "1.0.0" @@ -1941,7 +1230,7 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf" dependencies = [ - "bitflags 2.9.0", + "bitflags", "errno", "libc", "linux-raw-sys", @@ -2039,12 +1328,6 @@ 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" @@ -2057,7 +1340,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.9.0", + "bitflags", "core-foundation", "core-foundation-sys", "libc", @@ -2153,15 +1436,6 @@ 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" @@ -2202,36 +1476,12 @@ dependencies = [ "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" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" -[[package]] -name = "state" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b8c4a4445d81357df8b1a650d0d0d6fbbbfe99d064aa5e02f3e4022061476d8" -dependencies = [ - "loom", -] - [[package]] name = "strsim" version = "0.11.1" @@ -2281,7 +1531,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags 2.9.0", + "bitflags", "core-foundation", "system-configuration-sys", ] @@ -2349,16 +1599,6 @@ dependencies = [ "syn", ] -[[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", -] - [[package]] name = "time" version = "0.3.41" @@ -2366,7 +1606,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" dependencies = [ "deranged", - "itoa", "num-conv", "powerfmt", "serde", @@ -2410,7 +1649,7 @@ dependencies = [ "bytes", "io-uring", "libc", - "mio 1.0.3", + "mio", "parking_lot", "pin-project-lite", "signal-hook-registry", @@ -2451,17 +1690,6 @@ dependencies = [ "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" @@ -2550,21 +1778,9 @@ 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", -] - [[package]] name = "tracing-core" version = "0.1.33" @@ -2572,36 +1788,6 @@ 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]] @@ -2625,31 +1811,12 @@ 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.9.5" @@ -2699,12 +1866,6 @@ 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" @@ -2734,12 +1895,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" @@ -2867,22 +2022,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - [[package]] name = "winapi-util" version = "0.1.9" @@ -2892,21 +2031,6 @@ 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" @@ -2942,15 +2066,6 @@ 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" @@ -2969,21 +2084,6 @@ 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", -] - [[package]] name = "windows-targets" version = "0.52.6" @@ -3016,12 +2116,6 @@ dependencies = [ "windows_x86_64_msvc 0.53.0", ] -[[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" @@ -3034,12 +2128,6 @@ 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" @@ -3052,12 +2140,6 @@ 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" @@ -3082,12 +2164,6 @@ 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" @@ -3100,12 +2176,6 @@ 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" @@ -3118,12 +2188,6 @@ 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" @@ -3136,12 +2200,6 @@ 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" @@ -3169,7 +2227,7 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ - "bitflags 2.9.0", + "bitflags", ] [[package]] @@ -3189,12 +2247,10 @@ name = "www-rust-lang-org" version = "0.1.0" dependencies = [ "anyhow", - "handlebars 6.3.2", + "handlebars", "handlebars-fluent", "percent-encoding", "reqwest", - "rocket", - "rocket_dyn_templates", "rust_team_data", "sass-rs", "serde", @@ -3204,15 +2260,6 @@ dependencies = [ "toml", ] -[[package]] -name = "yansi" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" -dependencies = [ - "is-terminal", -] - [[package]] name = "yoke" version = "0.7.5" @@ -3237,26 +2284,6 @@ dependencies = [ "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", -] - [[package]] name = "zerofrom" version = "0.1.6" diff --git a/Cargo.toml b/Cargo.toml index 50b06cb6b..b5f98900c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,8 +9,6 @@ anyhow = "1" tokio = { version = "1", features = ["full"] } handlebars = { version = "6", features = ["dir_source"] } handlebars-fluent = "0.5" -rocket = "0.5.1" -rocket_dyn_templates = { version = "0.2.0", features = ["handlebars"] } serde = { version = "1.0", features = ["derive"] } sass-rs = "0.2.1" reqwest = { version = "0.12.15", features = ["json"] } diff --git a/src/assets.rs b/src/assets.rs index dcbd5f10e..f486d5ff3 100644 --- a/src/assets.rs +++ b/src/assets.rs @@ -1,7 +1,7 @@ use crate::fs::ensure_directory; use anyhow::Context; -use rocket::serde::Serialize; use sass_rs::{Options, compile_file}; +use serde::Serialize; use std::fs; use std::hash::{DefaultHasher, Hasher}; use std::path::Path; diff --git a/src/i18n.rs b/src/i18n.rs index 5f2cce7a1..c29f84540 100644 --- a/src/i18n.rs +++ b/src/i18n.rs @@ -2,7 +2,6 @@ use handlebars::{ Context, Handlebars, Helper, HelperDef, HelperResult, Output, RenderContext, RenderErrorReason, }; -use rocket::request::FromParam; use serde::Serialize; use std::{collections::HashSet, sync::LazyLock}; @@ -235,17 +234,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(()) - } - } -} From c3c85fca99c1843e2ce1120fd0706009fb18169e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 6 Aug 2025 12:44:45 +0200 Subject: [PATCH 17/21] Restructure code around and add redirect template --- src/fs.rs | 14 ++ src/main.rs | 270 ++--------------------------------- src/redirect.rs | 103 +++++++------- src/render.rs | 275 ++++++++++++++++++++++++++++++++++++ templates/redirect.html.hbs | 6 + 5 files changed, 357 insertions(+), 311 deletions(-) create mode 100644 src/render.rs create mode 100644 templates/redirect.html.hbs diff --git a/src/fs.rs b/src/fs.rs index d6d2e27ea..06bc864f1 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -9,3 +9,17 @@ pub fn ensure_directory(path: &Path) -> anyhow::Result<()> { } 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/main.rs b/src/main.rs index abc34b469..1f43357df 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,20 +1,19 @@ -use crate::assets::{AssetFiles, compile_assets}; -use crate::fs::ensure_directory; -use crate::i18n::{EXPLICIT_LOCALE_INFO, LocaleInfo, SUPPORTED_LOCALES, TeamHelper, create_loader}; -use crate::rust_version::{RustVersion, fetch_rust_version}; -use crate::teams::{PageData, RustTeams, encode_zulip_stream, load_rust_teams}; +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::RustVersion; +use crate::teams::{encode_zulip_stream, load_rust_teams}; use anyhow::Context; use handlebars::{DirectorySourceOptions, Handlebars}; -use handlebars_fluent::{FluentHelper, Loader, SimpleLoader}; -use serde::Serialize; -use std::ffi::OsStr; -use std::fs::File; -use std::io::BufWriter; +use handlebars_fluent::FluentHelper; use std::path::{Path, PathBuf}; mod assets; mod fs; mod i18n; +mod redirect; +mod render; mod rust_version; mod teams; @@ -33,155 +32,6 @@ fn baseurl(lang: &str) -> String { } } -#[derive(Serialize)] -struct TemplateCtx<'a, T: Serialize> { - page: String, - title: String, - parent: &'static str, - is_landing: bool, - data: &'a T, - lang: String, - baseurl: String, - pontoon_enabled: bool, - assets: &'a AssetFiles, - locales: &'static [LocaleInfo], - is_translation: bool, -} - -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 - } - - 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(()) - } -} - -struct RenderCtx<'a> { - handlebars: Handlebars<'a>, - template_dir: PathBuf, - fluent_loader: SimpleLoader, - output_dir: PathBuf, - rust_version: RustVersion, - teams: RustTeams, - assets: AssetFiles, -} - -impl<'a> RenderCtx<'a> { - 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: baseurl(&lang), - is_translation: lang != "en-US", - lang: lang.to_string(), - pontoon_enabled: PONTOON_ENABLED, - assets: &self.assets, - locales: EXPLICIT_LOCALE_INFO, - }, - output_dir: &self.output_dir, - handlebars: &self.handlebars, - } - } - - 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(()) - } - - 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. -fn 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(()) -} - -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(()) -} - fn setup_handlebars() -> anyhow::Result> { let mut handlebars: Handlebars<'static> = Handlebars::new(); handlebars.set_strict_mode(true); @@ -237,107 +87,7 @@ async fn main() -> anyhow::Result<()> { render_directory(&ctx, "tools")?; render_directory(&ctx, "what")?; ctx.page("404", "", &(), ENGLISH).render("404.html")?; + create_redirects(&ctx)?; - // TODO: redirects - - Ok(()) -} - -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(), - }; - all_langs("index.html", |path, lang| { - render_ctx - .page("index", "", &data, lang) - .make_landing() - .render(path) - }) -} - -fn render_governance(render_ctx: &RenderCtx) -> anyhow::Result<()> { - let data = render_ctx.teams.index_data(); - - 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 - all_langs( - &format!("governance/{}/index.html", team.url), - |dst_path, lang| { - render_ctx - .page( - "governance/group", - &format!("governance-team-{}-title", team.team.name), - &data, - lang, - ) - .render(dst_path) - }, - )?; - } - - Ok(()) -} - -/// Render all templates found in the given directory. -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" { - 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. - 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(()) } diff --git a/src/redirect.rs b/src/redirect.rs index 74f751a3e..c0aba45c3 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,7 +44,7 @@ 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", @@ -84,52 +81,56 @@ 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("/"); +pub fn create_redirects(ctx: &RenderCtx) -> anyhow::Result<()> { + // Static file redirects, no need to support languages + // for (src, dst) in STATIC_FILES_REDIRECTS { + // render_redirect(ctx, src, dst)?; + // } - 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 - } + // 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..0ee8d8568 --- /dev/null +++ b/src/render.rs @@ -0,0 +1,275 @@ +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::{ENGLISH, LAYOUT, PONTOON_ENABLED, baseurl}; +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, + baseurl: String, + pontoon_enabled: bool, + 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, +} + +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: baseurl(&lang), + is_translation: lang != "en-US", + lang: lang.to_string(), + pontoon_enabled: PONTOON_ENABLED, + 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-{}-title", 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/templates/redirect.html.hbs b/templates/redirect.html.hbs new file mode 100644 index 000000000..5f6b3b126 --- /dev/null +++ b/templates/redirect.html.hbs @@ -0,0 +1,6 @@ + + + + Please go to {{ data.url }} + + From b51ddd7ed0715e32e4bffb0be5b2065f42f8a5e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 6 Aug 2025 14:01:17 +0200 Subject: [PATCH 18/21] Fill missing `baseurl` prefixes in templates --- templates/404.html.hbs | 2 +- templates/community/index.html.hbs | 2 +- templates/components/footer.html.hbs | 8 +++---- templates/components/layout.html.hbs | 22 +++++++++---------- templates/components/nav.html.hbs | 2 +- templates/components/panels/domains.html.hbs | 8 +++---- .../components/what/cli/maintainable.html.hbs | 4 ++-- templates/components/what/cli/pitch.html.hbs | 12 +++++----- .../components/what/cli/production.html.hbs | 4 ++-- .../what/embedded/get-started.html.hbs | 6 ++--- .../components/what/embedded/pitch.html.hbs | 12 +++++----- .../what/embedded/testimonials.html.hbs | 8 +++---- .../components/what/networking/pitch.html.hbs | 6 ++--- .../what/networking/production.html.hbs | 4 ++-- .../components/what/wasm/get-started.html.hbs | 6 ++--- templates/components/what/wasm/pitch.html.hbs | 6 ++--- .../components/what/wasm/production.html.hbs | 6 ++--- templates/learn/get-started.html.hbs | 2 +- templates/learn/index.html.hbs | 6 ++--- 19 files changed, 63 insertions(+), 63 deletions(-) diff --git a/templates/404.html.hbs b/templates/404.html.hbs index e2e252718..eb5174920 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..c58828d43 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..32006872a 100644 --- a/templates/components/footer.html.hbs +++ b/templates/components/footer.html.hbs @@ -33,13 +33,13 @@

{{fluent "footer-social"}}

- {{fluent {{fluent + src="{{baseurl}}/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..ac3144b25 100644 --- a/templates/components/layout.html.hbs +++ b/templates/components/layout.html.hbs @@ -28,20 +28,20 @@ - + - - - - - - + + + + + + - + {{#if is_landing}} @@ -54,8 +54,8 @@ - - + + {{> components/nav}} @@ -66,6 +66,6 @@ {{#if pontoon_enabled}} {{/if}} - + diff --git a/templates/components/nav.html.hbs b/templates/components/nav.html.hbs index e8311d871..d3440c7fa 100644 --- a/templates/components/nav.html.hbs +++ b/templates/components/nav.html.hbs @@ -1,7 +1,7 @@