Skip to content

Commit 7353904

Browse files
authored
Merge pull request #2237 from Kobzol/funding-page
Add a funding page that lists Project members with GitHub Sponsors
2 parents 299bba0 + c099a6f commit 7353904

File tree

9 files changed

+145
-18
lines changed

9 files changed

+145
-18
lines changed

locales/en-US/funding.ftl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
## Works in conjunction with team data from teams.ftl
2+
3+
## funding.html.hbs
4+
funding-page-title = Funding
5+
funding-intro = Rust contributors shown on this page can be funded via GitHub Sponsors. Consider sponsoring them if you want to support the development of Rust.

src/assets.rs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -56,36 +56,44 @@ fn concat_files(
5656
files: &[&str],
5757
directory: &str,
5858
extension: &str,
59+
prefix: &str,
5960
) -> anyhow::Result<String> {
6061
let mut concatted = String::new();
6162
for filestem in files {
62-
let vendor_path = root_dir
63+
let file_path = root_dir
6364
.join("static")
6465
.join(directory)
6566
.join(format!("{filestem}.{extension}"));
66-
let contents = fs::read_to_string(vendor_path)
67-
.with_context(|| anyhow::anyhow!("couldn't read vendor {extension}"))?;
67+
let contents = fs::read_to_string(file_path)
68+
.with_context(|| anyhow::anyhow!("couldn't read {prefix} {extension}"))?;
6869
concatted.push_str(&contents);
6970
}
7071

71-
let file_sha = format!("vendor_{}", hash_string(&concatted));
72+
let file_sha = format!("{prefix}_{}", hash_string(&concatted));
7273
let out_file_path = out_dir
7374
.join("static")
7475
.join(directory)
7576
.join(format!("{file_sha}.{extension}"));
7677

7778
write_file(Path::new(&out_file_path), concatted.as_bytes())
78-
.with_context(|| anyhow::anyhow!("couldn't write vendor {extension}"))?;
79+
.with_context(|| anyhow::anyhow!("couldn't write {prefix} {extension}"))?;
7980

8081
relative_url(&out_file_path, out_dir)
8182
}
8283

8384
fn concat_vendor_css(root_dir: &Path, out_dir: &Path, files: Vec<&str>) -> anyhow::Result<String> {
84-
concat_files(root_dir, out_dir, &files, "styles", "css")
85+
concat_files(root_dir, out_dir, &files, "styles", "css", "vendor")
8586
}
8687

87-
fn concat_app_js(root_dir: &Path, out_dir: &Path, files: Vec<&str>) -> anyhow::Result<String> {
88-
concat_files(root_dir, out_dir, &files, "scripts", "js")
88+
fn build_js_file(root_dir: &Path, out_dir: &Path, file: &str) -> anyhow::Result<String> {
89+
concat_files(
90+
root_dir,
91+
out_dir,
92+
&[file],
93+
"scripts",
94+
"js",
95+
Path::new(file).file_stem().unwrap().to_str().unwrap(),
96+
)
8997
}
9098

9199
#[derive(Serialize, Debug)]
@@ -97,7 +105,8 @@ pub struct CSSFiles {
97105

98106
#[derive(Serialize, Debug)]
99107
pub struct JSFiles {
100-
app: String,
108+
tools_install: String,
109+
funding_shuffle: String,
101110
}
102111

103112
#[derive(Serialize, Debug)]
@@ -116,7 +125,8 @@ pub fn compile_assets(
116125
let app_css_file = compile_sass(root_dir, out_dir, "app", base_url)?;
117126
let fonts_css_file = compile_sass(root_dir, out_dir, "fonts", base_url)?;
118127
let vendor_css_file = concat_vendor_css(root_dir, out_dir, vec!["tachyons"])?;
119-
let app_js_file = concat_app_js(root_dir, out_dir, vec!["tools-install"])?;
128+
let tools_install_js = build_js_file(root_dir, out_dir, "tools-install")?;
129+
let funding_shuffle_js = build_js_file(root_dir, out_dir, "funding-shuffle")?;
120130

121131
Ok(AssetFiles {
122132
css: CSSFiles {
@@ -125,7 +135,8 @@ pub fn compile_assets(
125135
vendor: format!("{base_url}/{vendor_css_file}"),
126136
},
127137
js: JSFiles {
128-
app: format!("{base_url}/{app_js_file}"),
138+
tools_install: format!("{base_url}/{tools_install_js}"),
139+
funding_shuffle: format!("{base_url}/{funding_shuffle_js}"),
129140
},
130141
})
131142
}

src/main.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::assets::compile_assets;
22
use crate::i18n::{TeamHelper, create_loader};
33
use crate::redirect::create_redirects;
4-
use crate::render::{RenderCtx, render_directory, render_governance, render_index};
4+
use crate::render::{RenderCtx, render_directory, render_funding, render_governance, render_index};
55
use crate::rust_version::fetch_rust_version;
66
use crate::teams::{encode_zulip_stream, load_rust_teams};
77
use anyhow::Context;
@@ -110,8 +110,11 @@ fn main() -> anyhow::Result<()> {
110110
".well-known/security.txt",
111111
)?;
112112

113+
let all_team_members = ctx.teams.all_team_members();
114+
113115
render_index(&ctx)?;
114-
render_governance(&ctx)?;
116+
render_governance(&ctx, &all_team_members)?;
117+
render_funding(&ctx, &all_team_members)?;
115118
render_directory(&ctx, "community")?;
116119
render_directory(&ctx, "learn")?;
117120
render_directory(&ctx, "policies")?;

src/render.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::assets::AssetFiles;
22
use crate::fs::{copy_dir_all, ensure_directory};
33
use crate::i18n::{EXPLICIT_LOCALE_INFO, LocaleInfo, SUPPORTED_LOCALES};
44
use crate::rust_version::RustVersion;
5-
use crate::teams::{PageData, RustTeamData};
5+
use crate::teams::{AllTeamMembers, PageData, RustTeamData};
66
use crate::{BaseUrl, ENGLISH, LAYOUT};
77
use anyhow::Context;
88
use handlebars::Handlebars;
@@ -179,7 +179,10 @@ pub fn render_index(render_ctx: &RenderCtx) -> anyhow::Result<()> {
179179
})
180180
}
181181

182-
pub fn render_governance(render_ctx: &RenderCtx) -> anyhow::Result<()> {
182+
pub fn render_governance(
183+
render_ctx: &RenderCtx,
184+
all_team_members: &AllTeamMembers,
185+
) -> anyhow::Result<()> {
183186
let data = render_ctx.teams.index_data();
184187

185188
// Index page
@@ -226,13 +229,12 @@ pub fn render_governance(render_ctx: &RenderCtx) -> anyhow::Result<()> {
226229
})?;
227230

228231
// Page with all team members
229-
let all_team_members_data = render_ctx.teams.all_team_members();
230232
for_all_langs("governance/people/index.html", |dst_path, lang| {
231233
render_ctx
232234
.page(
233235
"governance/all-team-members",
234236
"governance-all-team-members-title",
235-
&all_team_members_data,
237+
all_team_members,
236238
lang,
237239
)
238240
.render(dst_path)
@@ -263,6 +265,22 @@ pub fn render_governance(render_ctx: &RenderCtx) -> anyhow::Result<()> {
263265
Ok(())
264266
}
265267

268+
pub fn render_funding(
269+
render_ctx: &RenderCtx,
270+
all_team_members: &AllTeamMembers,
271+
) -> anyhow::Result<()> {
272+
let data = render_ctx.teams.funding_data(all_team_members);
273+
274+
// Index page
275+
for_all_langs("funding/index.html", |dst_path, lang| {
276+
render_ctx
277+
.page("funding", "funding-page-title", &data, lang)
278+
.render(dst_path)
279+
})?;
280+
281+
Ok(())
282+
}
283+
266284
/// Render all templates found in the given directory.
267285
pub fn render_directory(render_ctx: &RenderCtx, category: &str) -> anyhow::Result<()> {
268286
for dir in std::fs::read_dir(render_ctx.template_dir.join(category))? {

src/teams.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,27 @@ impl RustTeamData {
346346
people
347347
}
348348

349+
pub fn funding_data(&self, all_team_members: &AllTeamMembers) -> FundingData {
350+
let people_with_sponsors = all_team_members
351+
.active
352+
.iter()
353+
.filter_map(|member| {
354+
let person = self.people.get(&member.github)?;
355+
if person.github_sponsors {
356+
Some(FundablePerson {
357+
name: member.name.clone(),
358+
github: member.github.to_string(),
359+
})
360+
} else {
361+
None
362+
}
363+
})
364+
.collect();
365+
FundingData {
366+
people: people_with_sponsors,
367+
}
368+
}
369+
349370
fn get_toplevel_team_url<'a>(&'a self, mut team: &'a Team) -> Option<String> {
350371
while !is_toplevel_team(team) {
351372
let Some(parent) = &team.subteam_of else {
@@ -476,6 +497,17 @@ pub struct PersonData {
476497
alumni_teams: Vec<PersonTeam>,
477498
}
478499

500+
#[derive(Serialize)]
501+
pub struct FundablePerson {
502+
name: String,
503+
github: String,
504+
}
505+
506+
#[derive(Serialize)]
507+
pub struct FundingData {
508+
people: Vec<FundablePerson>,
509+
}
510+
479511
pub fn load_rust_teams() -> anyhow::Result<RustTeamData> {
480512
println!("Downloading Team API data");
481513

static/scripts/funding-shuffle.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// From https://stackoverflow.com/a/2450976/1107768
2+
function shuffle(array) {
3+
let currentIndex = array.length;
4+
5+
// While there remain elements to shuffle...
6+
while (currentIndex !== 0) {
7+
// Pick a remaining element...
8+
let randomIndex = Math.floor(Math.random() * currentIndex);
9+
currentIndex--;
10+
11+
// And swap it with the current element.
12+
[array[currentIndex], array[randomIndex]] = [
13+
array[randomIndex], array[currentIndex]];
14+
}
15+
}
16+
17+
document.addEventListener("DOMContentLoaded", () => {
18+
// Shuffle people to reduce ordering bias
19+
const wrapper = document.querySelector("#people");
20+
const children = Array(...wrapper.children);
21+
shuffle(children);
22+
wrapper.replaceChildren(...children);
23+
});

templates/components/tools/rustup.html.hbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,4 @@
3838
</div>
3939
</div>
4040

41-
<script type="text/javascript" src="{{assets.js.app}}"></script>
41+
<script type="text/javascript" src="{{assets.js.tools_install}}"></script>

templates/funding.html.hbs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{{#*inline "member"}}
2+
<div class="person w-100 w-25-l mb3 flex flex-row items-center">
3+
<a class="mr4 w4 h4 flex-shrink-0" href="{{baseurl}}/governance/people/{{member.github}}">
4+
<img class="w-100 h-100 bg-white br2"
5+
src="https://avatars.githubusercontent.com/{{member.github}}"
6+
alt="{{member.name}}">
7+
</a>
8+
<div class="flex flex-column">
9+
<a href="{{baseurl}}/governance/people/{{member.github}}">{{member.name}}</a>
10+
<a href="https://github.com/sponsors/{{member.github}}" class="button button-secondary mt2">Sponsor</a>
11+
</div>
12+
</div>
13+
{{/inline}}
14+
15+
{{#*inline "page"}}
16+
<section class="green" style="padding-bottom: 10px;">
17+
<div class="w-100 mw-none mw-8-m mw9-l center f2 ph3">
18+
<p>{{fluent "funding-intro"}}</p>
19+
</div>
20+
</section>
21+
22+
<section class="green" style="padding-bottom: 15px;">
23+
<div id="people" class="w-100 mw-none mw-8-m mw9-l flex flex-column flex-row-l flex-wrap-l center ph3">
24+
{{#each data.people as |member|}}
25+
{{> member member=member baseurl=../baseurl }}
26+
{{/each}}
27+
</div>
28+
<script type="text/javascript" src="{{assets.js.funding_shuffle}}"></script>
29+
</section>
30+
{{/inline}}
31+
32+
{{~> (lookup this "parent")~}}

templates/governance/all-team-members.html.hbs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
<p>{{#fluent "governance-all-team-members-intro"}}{{#fluentparam
2121
"count"}}{{len data.active}}{{/fluentparam}}{{/fluent}}</p>
2222
</div>
23+
<div class="w-100 mw-none mw9-l center">
24+
<a href="{{baseurl}}/funding" class="button button-secondary mw6">Sponsor Rust contributors</a>
25+
</div>
2326
</section>
2427

2528
<section class="green" style="padding-bottom: 15px;">

0 commit comments

Comments
 (0)