diff options
| author | Laurenz <laurmaedje@gmail.com> | 2023-04-20 14:23:26 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2023-04-20 14:23:36 +0200 |
| commit | c117e2dc276d19b022abccac0d252bd7fc1cd44e (patch) | |
| tree | 10884ac2ecd4d01053b2d38856c395e2e115775c /docs/src/contribs.rs | |
| parent | 2a682f0008b91e7c33c6e65b3ecfc690268ab405 (diff) | |
List contributors in changelog
Co-Authored-By: Martin Haug <mhaug@live.de>
Diffstat (limited to 'docs/src/contribs.rs')
| -rw-r--r-- | docs/src/contribs.rs | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/docs/src/contribs.rs b/docs/src/contribs.rs new file mode 100644 index 00000000..df1d4944 --- /dev/null +++ b/docs/src/contribs.rs @@ -0,0 +1,97 @@ +use std::cmp::Reverse; +use std::collections::HashMap; +use std::fmt::Write; + +use serde::Deserialize; + +use super::Html; + +/// Build HTML detailing the contributors between two tags. +pub fn contributors(from: &str, to: &str) -> Option<Html> { + let staff = ["laurmaedje", "reknih"]; + + let url = format!("https://api.github.com/repos/typst/typst/compare/{from}...{to}"); + let response: Response = ureq::get(&url) + .set("X-GitHub-Api-Version", "2022-11-28") + .call() + .ok()? + .into_json() + .ok()?; + + // Determine number of contributions per person. + let mut contributors = HashMap::<String, Contributor>::new(); + for commit in response.commits { + contributors + .entry(commit.author.login.clone()) + .or_insert_with(|| Contributor { + login: commit.author.login, + avatar: commit.author.avatar_url, + contributions: 0, + }) + .contributions += 1; + } + + // Keep only non-staff people. + let mut contributors: Vec<_> = contributors + .into_values() + .filter(|c| !staff.contains(&c.login.as_str())) + .collect(); + + // Sort by highest number of commits. + contributors.sort_by_key(|c| Reverse(c.contributions)); + if contributors.is_empty() { + return None; + } + + let mut html = "Thanks to everyone who contributed to this release!".to_string(); + html += "<ul class=\"contribs\">"; + + for Contributor { login, avatar, contributions } in contributors { + let login = login.replace('\"', """).replace('&', "&"); + let avatar = avatar.replace("?v=", "?s=64&v="); + let s = if contributions > 1 { "s" } else { "" }; + write!( + html, + r#"<li> + <a href="https://github.com/{login}" target="_blank"> + <img + width="64" + height="64" + src="{avatar}" + alt="GitHub avatar of {login}" + title="@{login} made {contributions} contribution{s}" + crossorigin="anonymous" + > + </a> + </li>"# + ) + .unwrap(); + } + + html += "</ul>"; + + Some(Html::new(html)) +} + +#[derive(Debug)] +struct Contributor { + login: String, + avatar: String, + contributions: usize, +} + +#[derive(Debug, Deserialize)] +struct Response { + commits: Vec<Commit>, +} + +#[derive(Debug, Deserialize)] +struct Commit { + author: Author, +} + +#[derive(Debug, Deserialize)] +struct Author { + login: String, + avatar_url: String, +} |
