mirror of
https://github.com/typst/typst
synced 2025-05-15 01:25:28 +08:00
87 lines
2.4 KiB
Rust
87 lines
2.4 KiB
Rust
use std::cmp::Reverse;
|
|
use std::collections::HashMap;
|
|
use std::fmt::Write;
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use crate::{Html, Resolver};
|
|
|
|
/// Build HTML detailing the contributors between two tags.
|
|
pub fn contributors(resolver: &dyn Resolver, from: &str, to: &str) -> Option<Html> {
|
|
let staff = ["laurmaedje", "reknih"];
|
|
|
|
// Determine number of contributions per person.
|
|
let mut contributors = HashMap::<String, Contributor>::new();
|
|
for commit in resolver.commits(from, to) {
|
|
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), c.login.clone()));
|
|
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,
|
|
}
|
|
|
|
/// A commit on the `typst` repository.
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
pub struct Commit {
|
|
author: Author,
|
|
}
|
|
|
|
/// A commit author.
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
pub struct Author {
|
|
login: String,
|
|
avatar_url: String,
|
|
}
|