in tools/sdk-lints/src/changelog.rs [228:293]
fn render(mut entries: Vec<ChangelogEntry>, version: &str, date: &str) -> String {
entries.sort_by_key(|ent| !ent.meta.tada);
let mut out = String::new();
let header = format!("{version} ({date})", version = version, date = date);
out.push_str(&header);
out.push('\n');
for _ in 0..header.len() {
out.push('=');
}
out.push('\n');
let (breaking, non_breaking) = entries
.iter()
.partition::<Vec<_>, _>(|entry| entry.meta.breaking);
if !breaking.is_empty() {
out.push_str("**Breaking Changes:**\n");
for change in breaking {
change.render(&mut out);
out.push_str("\n");
}
out.push('\n')
}
if !non_breaking.is_empty() {
out.push_str("**New this release:**\n");
for change in non_breaking {
change.render(&mut out);
out.push_str("\n");
}
out.push('\n');
}
let mut external_contribs = entries
.iter()
.map(|entry| entry.author.to_ascii_lowercase())
.filter(|author| !maintainers().contains(&author.as_str()))
.collect::<Vec<_>>();
external_contribs.sort();
external_contribs.dedup();
if !external_contribs.is_empty() {
out.push_str("**Contributors**\nThank you for your contributions! ❤\n");
for contributor_handle in external_contribs {
// retrieve all contributions this author made
let mut contribution_references = entries
.iter()
.filter(|entry| {
entry
.author
.eq_ignore_ascii_case(contributor_handle.as_str())
})
.flat_map(|entry| entry.references.iter().map(|it| it.to_md_link()))
.collect::<Vec<_>>();
contribution_references.sort();
contribution_references.dedup();
let contribution_references = contribution_references.as_slice().join(", ");
out.push_str("- @");
out.push_str(&contributor_handle);
if !contribution_references.is_empty() {
out.push_str(&format!(" ({})", contribution_references));
}
out.push('\n');
}
}
out
}