Skip to content

Commit 9c79e96

Browse files
authored
Contributors style and formatting upgrade (security-alliance#136)
* Updated the overall style and display of contributors * Minor modifications to the previous commit, improving styling on featured contribs * Updated wordlist
1 parent b0f7f4c commit 9c79e96

7 files changed

Lines changed: 750 additions & 126 deletions

File tree

plugin/mdbook-metadata/src/main.rs

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,10 +681,44 @@ fn generate_contributors_js(
681681
js.push_str("// This file is auto-generated by the tags preprocessor\n");
682682
js.push_str("const contributorsIndex = {\n");
683683

684+
// Load the contributors database once
685+
let contributors_db = load_contributors_db()?;
686+
687+
// Create a lookup from displayName/name to ID to help match contributors
688+
let mut name_to_id: HashMap<String, String> = HashMap::new();
689+
let mut id_to_display_name: HashMap<String, String> = HashMap::new();
690+
691+
for (id, data) in &contributors_db {
692+
// Map the ID directly
693+
name_to_id.insert(id.clone(), id.clone());
694+
695+
// Get display name for later use
696+
let display_name = data.get("displayName")
697+
.and_then(|v| v.as_str())
698+
.or_else(|| data.get("name").and_then(|v| v.as_str()))
699+
.unwrap_or(id);
700+
701+
id_to_display_name.insert(id.clone(), display_name.to_string());
702+
703+
// Map displayName to ID if available
704+
if let Some(display_name) = data.get("displayName").and_then(|v| v.as_str()) {
705+
name_to_id.insert(display_name.to_string(), id.clone());
706+
}
707+
708+
// Map name to ID if available
709+
if let Some(name) = data.get("name").and_then(|v| v.as_str()) {
710+
name_to_id.insert(name.to_string(), id.clone());
711+
}
712+
}
713+
714+
// Keep track of which contributors we've already processed
715+
let mut processed_contributors = std::collections::HashSet::new();
716+
684717
// Sort contributors alphabetically for consistency
685718
let mut sorted_contributors: Vec<_> = contributors_map.iter().collect();
686719
sorted_contributors.sort_by(|a, b| a.0.cmp(&b.0));
687720

721+
// First add all contributors who have contributed to chapters
688722
for (i, (contributor, chapters)) in sorted_contributors.iter().enumerate() {
689723
js.push_str(&format!(" \"{}\": {{\n", contributor));
690724
js.push_str(&format!(" \"chapters\": [\n"));
@@ -731,10 +765,139 @@ fn generate_contributors_js(
731765
}
732766
}
733767

768+
// Try to find the contributor in the database by mapped ID
769+
let contributor_id = name_to_id.get(*contributor).cloned();
770+
771+
if let Some(db_id) = &contributor_id {
772+
if let Some(contributor_data) = contributors_db.get(db_id) {
773+
// Add company if available
774+
if let Some(company) = contributor_data.get("company").and_then(|v| v.as_str()) {
775+
if !company.is_empty() {
776+
js.push_str(&format!(",\n \"company\": \"{}\"", company));
777+
}
778+
}
779+
780+
// Add role if available
781+
if let Some(role) = contributor_data.get("role").and_then(|v| v.as_str()) {
782+
if !role.is_empty() {
783+
js.push_str(&format!(",\n \"role\": \"{}\"", role));
784+
}
785+
}
786+
787+
// Add description if available
788+
if let Some(description) = contributor_data.get("description").and_then(|v| v.as_str()) {
789+
if !description.is_empty() {
790+
js.push_str(&format!(",\n \"description\": \"{}\"", description));
791+
}
792+
}
793+
794+
// Add features if available
795+
if let Some(features) = contributor_data.get("features").and_then(|v| v.as_array()) {
796+
let features_str: Vec<String> = features.iter().filter_map(|v| v.as_str().map(String::from)).collect();
797+
if !features_str.is_empty() {
798+
js.push_str(&format!(",\n \"features\": [{}]", features_str.iter().map(|f| format!("\"{}\"", f)).collect::<Vec<_>>().join(", ")));
799+
}
800+
}
801+
}
802+
}
803+
734804
js.push_str("\n }");
735805

736806
if i < sorted_contributors.len() - 1 {
737807
js.push_str(",\n");
808+
} else {
809+
// If we're the last one and there will be more contributors after this,
810+
// add a comma
811+
if processed_contributors.len() < contributors_db.len() {
812+
js.push_str(",\n");
813+
} else {
814+
js.push_str("\n");
815+
}
816+
}
817+
818+
// Mark this contributor as processed
819+
if let Some(db_id) = contributor_id {
820+
processed_contributors.insert(db_id);
821+
}
822+
}
823+
824+
// Now add contributors from the database who haven't been processed yet
825+
// These are contributors who haven't contributed to any chapters yet
826+
let mut additional_contributors: Vec<_> = contributors_db.iter()
827+
.filter(|(id, _)| !processed_contributors.contains(*id))
828+
.collect();
829+
additional_contributors.sort_by(|a, b| a.0.cmp(&b.0));
830+
831+
for (i, (id, data)) in additional_contributors.iter().enumerate() {
832+
// Get display name
833+
let display_name = id_to_display_name.get(*id).unwrap_or(id);
834+
835+
js.push_str(&format!(" \"{}\": {{\n", display_name));
836+
837+
// Add empty chapters array
838+
js.push_str(" \"chapters\": []");
839+
840+
// Add github profile if available
841+
if let Some(github) = data.get("github").and_then(|v| v.as_str()) {
842+
if !github.is_empty() {
843+
js.push_str(&format!(",\n \"github\": \"{}\"", github));
844+
}
845+
}
846+
847+
// Add avatar URL if available
848+
if let Some(avatar) = data.get("avatar").and_then(|v| v.as_str()) {
849+
if !avatar.is_empty() {
850+
js.push_str(&format!(",\n \"avatar\": \"{}\"", avatar));
851+
}
852+
}
853+
854+
// Add Twitter profile if available
855+
if let Some(twitter) = data.get("twitter").and_then(|v| v.as_str()) {
856+
if !twitter.is_empty() {
857+
js.push_str(&format!(",\n \"twitter\": \"{}\"", twitter));
858+
}
859+
}
860+
861+
// Add website if available
862+
if let Some(website) = data.get("website").and_then(|v| v.as_str()) {
863+
if !website.is_empty() {
864+
js.push_str(&format!(",\n \"website\": \"{}\"", website));
865+
}
866+
}
867+
868+
// Add company if available
869+
if let Some(company) = data.get("company").and_then(|v| v.as_str()) {
870+
if !company.is_empty() {
871+
js.push_str(&format!(",\n \"company\": \"{}\"", company));
872+
}
873+
}
874+
875+
// Add role if available
876+
if let Some(role) = data.get("role").and_then(|v| v.as_str()) {
877+
if !role.is_empty() {
878+
js.push_str(&format!(",\n \"role\": \"{}\"", role));
879+
}
880+
}
881+
882+
// Add description if available
883+
if let Some(description) = data.get("description").and_then(|v| v.as_str()) {
884+
if !description.is_empty() {
885+
js.push_str(&format!(",\n \"description\": \"{}\"", description));
886+
}
887+
}
888+
889+
// Add features if available
890+
if let Some(features) = data.get("features").and_then(|v| v.as_array()) {
891+
let features_str: Vec<String> = features.iter().filter_map(|v| v.as_str().map(String::from)).collect();
892+
if !features_str.is_empty() {
893+
js.push_str(&format!(",\n \"features\": [{}]", features_str.iter().map(|f| format!("\"{}\"", f)).collect::<Vec<_>>().join(", ")));
894+
}
895+
}
896+
897+
js.push_str("\n }");
898+
899+
if i < additional_contributors.len() - 1 {
900+
js.push_str(",\n");
738901
} else {
739902
js.push_str("\n");
740903
}

src/community-management/discord.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ tags:
44
- Security Specialist
55
contributors:
66
- mattaereal
7-
- nft_dreww
7+
- nftdreww
88
---
99

1010
# Discord Security

src/config/contributors.json

Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,44 @@
66
"github": "https://github.com/mattaereal",
77
"twitter": "https://twitter.com/mattaereal",
88
"website": "https://theredguild.org",
9-
"bio": "The Red Guild | SEAL"
9+
"features": ["lead"],
10+
"role": "Security Frameworks Lead",
11+
"description": "Initiative lead and maintainer of the Security Frameworks",
12+
"company": "The Red Guild | SEAL"
1013
},
11-
"nft_dreww": {
12-
"name": "NFT_Dreww.eth",
13-
"displayName": "NFT_Dreww.eth",
14+
"fredriksvantes": {
15+
"name": "Fredrik Svantes",
16+
"displayName": "Fredrik Svantes",
17+
"avatar": "https://github.com/fredriksvantes.png",
18+
"github": "https://github.com/fredriksvantes",
19+
"twitter": "https://twitter.com/fredriksvantes",
20+
"website": "https://fredriksvantes.com",
21+
"features": ["core"],
22+
"role": "Security Frameworks core",
23+
"description": "Initial contributor to the Security Frameworks",
24+
"company": "Ethereum Foundation"
25+
},
26+
"zedt3ster": {
27+
"name": "zedt3ster",
28+
"displayName": "zedt3ster",
29+
"avatar": "https://github.com/zedt3ster.png",
30+
"github": "https://github.com/zedt3ster",
31+
"twitter": "https://twitter.com/zedt3ster",
32+
"features": ["core"],
33+
"role": "Security Frameworks core",
34+
"description": "Initial contributor to the Security Frameworks",
35+
"company": "Sigma Prime"
36+
},
37+
"nftdreww": {
38+
"name": "NFTDreww",
39+
"displayName": "NFTDreww",
1440
"avatar": "https://pbs.twimg.com/profile_images/1589726471249174536/pEqaw6FO_400x400.png",
15-
"github": null,
41+
"github": "https://github.com/NFTDreww",
1642
"twitter": "https://twitter.com/nft_dreww",
17-
"bio": "Community manager and security enthusiast"
43+
"features": ["steward"],
44+
"role": "Community Management",
45+
"description": "Managing and curating the Community Management framework",
46+
"company": "Community DAO"
1847
},
1948
"robert": {
2049
"name": "Robert MacWha",
@@ -23,6 +52,28 @@
2352
"github": "https://github.com/Robert-MacWha",
2453
"twitter": null,
2554
"website": "https://robertmacwha.com",
26-
"bio": "Full-stack developer and security enthusiast"
55+
"features": ["core"],
56+
"role": "Security Frameworks webs collaborator",
57+
"description": "Full-stack developer and security enthusiast",
58+
"company": "Skylock"
59+
},
60+
"tebayoso": {
61+
"name": "tebayoso",
62+
"displayName": "tebayoso",
63+
"avatar": "https://github.com/tebayoso.png",
64+
"github": "https://github.com/tebayoso",
65+
"twitter": "https://twitter.com/tebayoso",
66+
"features": ["featured"],
67+
"description": "Initial implementation of tag filtering",
68+
"company": "The Red Guild"
69+
},
70+
"engn33r": {
71+
"name": "engn33r",
72+
"displayName": "engn33r",
73+
"avatar": "https://github.com/engn33r.png",
74+
"github": "https://github.com/engn33r",
75+
"twitter": "https://twitter.com/engn33r",
76+
"features": ["featured"],
77+
"description": "Signing scheme content"
2778
}
2879
}

theme/contributors/contributorsindex.js

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,28 @@
11
// This file is auto-generated by the tags preprocessor
22
const contributorsIndex = {
3-
"NFT_Dreww.eth": {
3+
"NFTDreww": {
44
"chapters": [
55
"community-management/discord.html"
66
],
7+
"github": "https://github.com/NFTDreww",
78
"avatar": "https://pbs.twimg.com/profile_images/1589726471249174536/pEqaw6FO_400x400.png",
8-
"twitter": "https://twitter.com/nft_dreww"
9+
"twitter": "https://twitter.com/nft_dreww",
10+
"company": "Community DAO",
11+
"role": "Community Management",
12+
"description": "Managing and curating the Community Management framework",
13+
"features": ["steward"]
914
},
1015
"Robert": {
1116
"chapters": [
1217
"community-management/index.html"
1318
],
1419
"github": "https://github.com/Robert-MacWha",
1520
"avatar": "https://github.com/Robert-MacWha.png",
16-
"website": "https://robertmacwha.com"
21+
"website": "https://robertmacwha.com",
22+
"company": "Skylock",
23+
"role": "Security Frameworks webs collaborator",
24+
"description": "Full-stack developer and security enthusiast",
25+
"features": ["core"]
1726
},
1827
"matta": {
1928
"chapters": [
@@ -27,6 +36,48 @@ const contributorsIndex = {
2736
"github": "https://github.com/mattaereal",
2837
"avatar": "https://github.com/mattaereal.png",
2938
"twitter": "https://twitter.com/mattaereal",
30-
"website": "https://theredguild.org"
39+
"website": "https://theredguild.org",
40+
"company": "The Red Guild | SEAL",
41+
"role": "Security Frameworks Lead",
42+
"description": "Initiative lead and maintainer of the Security Frameworks",
43+
"features": ["lead"]
44+
},
45+
"engn33r": {
46+
"chapters": [],
47+
"github": "https://github.com/engn33r",
48+
"avatar": "https://github.com/engn33r.png",
49+
"twitter": "https://twitter.com/engn33r",
50+
"description": "Signing scheme content",
51+
"features": ["featured"]
52+
},
53+
"Fredrik Svantes": {
54+
"chapters": [],
55+
"github": "https://github.com/fredriksvantes",
56+
"avatar": "https://github.com/fredriksvantes.png",
57+
"twitter": "https://twitter.com/fredriksvantes",
58+
"website": "https://fredriksvantes.com",
59+
"company": "Ethereum Foundation",
60+
"role": "Security Frameworks core",
61+
"description": "Initial contributor to the Security Frameworks",
62+
"features": ["core"]
63+
},
64+
"tebayoso": {
65+
"chapters": [],
66+
"github": "https://github.com/tebayoso",
67+
"avatar": "https://github.com/tebayoso.png",
68+
"twitter": "https://twitter.com/tebayoso",
69+
"company": "The Red Guild",
70+
"description": "Initial implementation of tag filtering",
71+
"features": ["featured"]
72+
},
73+
"zedt3ster": {
74+
"chapters": [],
75+
"github": "https://github.com/zedt3ster",
76+
"avatar": "https://github.com/zedt3ster.png",
77+
"twitter": "https://twitter.com/zedt3ster",
78+
"company": "Sigma Prime",
79+
"role": "Security Frameworks core",
80+
"description": "Initial contributor to the Security Frameworks",
81+
"features": ["core"]
3182
}
3283
};

0 commit comments

Comments
 (0)