4a1c2ca0ad8512a9c4f7ba71348fe467faf6ec3b
[WebKit-https.git] / Websites / webkit.org / team.html
1 <?php 
2 $title = "WebKit Team";
3 include("header.inc");
4 ?>
5
6 <h2>WebKit Team</h2>
7
8 <div id="container">
9 <h2>Reviewers</h2>
10 <ul id="reviewers"></ul>
11
12 <h2>Committers</h2>
13 <ul id="committers"></ul>
14
15 <h2>Contributors</h2>
16 <ul id="contributors"></ul>
17 </div>
18
19 <script>
20
21 var svnTrunkUrl = 'http://svn.webkit.org/repository/webkit/trunk/';
22 var domainAffiliations = {
23     'apple.com': 'Apple',
24     'collabora.co.uk': 'Collabora',
25     'google.com': 'Google',
26     'igalia.com': 'Igalia',
27     'motorola.com': 'Motorola Mobility',
28     'nokia.com': 'Nokia',
29     'openbossa.org': 'INdT / Nokia',
30     'profusion.mobi': 'ProFUSION',
31     'rim.com': 'Research In Motion',
32     'samsung.com': 'Samsung Electronics',
33     'sencha.com': 'Sencha',
34     'torchmobile.com.cn': 'Torch Mobile (Beijing) Co. Ltd.',
35
36     // Universities
37     'inf.u-szeged.hu': 'University of Szeged',
38
39     // Open source communities
40     'chromium.org': 'Chromium',
41     'gnome.org': 'GNOME',
42     'kde.org': 'KDE'
43 };
44
45 function parseCommittersPy(text) {
46     var lines = text.split('\n');
47     var contributors = [];
48     for (var i = 0; i < lines.length; i++) {
49         var contributorLine = /^\s+(Reviewer|Committer|Contributor)\((.+)\),?$/;
50         var match = contributorLine.exec(lines[i]);
51         if (!match)
52             continue;
53
54         try {
55             var nameEmailsNicks = JSON.parse('[' + match[2].replace(/^u"/,'"') + ']');
56         } catch (e) {
57             continue;
58         }
59         contributors.push({
60             name: nameEmailsNicks[0],
61             kind: match[1].toLowerCase(),
62             emails: typeof nameEmailsNicks[1] == 'string' ? [nameEmailsNicks[1]] : nameEmailsNicks[1],
63             nicks: typeof nameEmailsNicks[2] == 'string' ? [nameEmailsNicks[2]] : nameEmailsNicks[2],
64             area: nameEmailsNicks[3]
65         });
66     }
67     return contributors;
68 }
69
70 function formatAffiliation(contributor) {
71     if (contributor.affiliation)
72         return contributor.affiliation;
73
74     if (!contributor.emails || !contributor.emails.length)
75         return null;
76
77     var affiliations = [];
78     for (var domain in domainAffiliations) {
79         for (var i = 0; i < contributor.emails.length; i++) {
80             if (contributor.emails[i].indexOf('@' + domain) > 0 && affiliations.indexOf(domainAffiliations[domain]) < 0)
81                 affiliations.push(domainAffiliations[domain]);
82         }
83     }
84     return affiliations.join(' / ');
85 }
86
87 function addText(container, text) { container.appendChild(document.createTextNode(text)); }
88
89 function addWrappedText(container, tagName, attributes, text) {
90     var element = document.createElement(tagName);
91     for (var name in attributes)
92         element.setAttribute(name, attributes[name]);
93     addText(element, text);
94     container.appendChild(element);
95 }
96
97 function populateContributorListItem(listItem, contributor) {
98     addWrappedText(listItem, 'strong', {'class': 'name'}, contributor.name);
99     if (contributor.nicks) {
100         addText(listItem, ' (');
101         addWrappedText(listItem, 'span', {'class': 'nicks'}, contributor.nicks.join(', '));
102         addText(listItem, ')');
103     }
104
105     var affiliation = formatAffiliation(contributor);
106     if (affiliation) {
107         addText(listItem, ' ');
108         addWrappedText(listItem, 'em', {'class': 'affiliation'}, affiliation);        
109     }
110 }
111
112 function populateContributorList(contributors, kind) {
113     var contributorsOfKind = contributors.filter(function(contributor) { return contributor.kind == kind; });
114     var listElement = document.getElementById(kind + 's');
115     for (var i = 0; i < contributorsOfKind.length; i++) {
116         var listItem = document.createElement('li');
117         listElement.appendChild(listItem);
118         populateContributorListItem(listItem, contributorsOfKind[i]);
119     }
120 }
121
122 function nicksInListItem(listItem) {
123     var nicksContainer = listItem.querySelector('.nicks');
124     if (!nicksContainer || !nicksContainer.textContent)
125         return null;
126     return nicksContainer.textContent.split(/,\s*/);
127 }
128
129 function findListChildForContributor(contributor) {
130     var listChildren = document.getElementsByTagName('li');
131     for (var i = 0; i < listChildren.length; i++) {
132         var nameContainer = listChildren[i].querySelector('.name');
133         if (nameContainer && nameContainer.textContent.toLowerCase().indexOf(contributor.name.toLowerCase()) >= 0)
134             return listChildren[i];
135         var nicksInContainer = nicksInListItem(listChildren[i]);
136         if (nicksInContainer && contributor.nicks) {
137             for (var j = 0; j < contributor.nicks.length; j++) {
138                 if (nicksInContainer.indexOf(contributor.nicks[j]) >= 0)
139                     return listChildren[i];
140             }
141         }
142     }
143     return null;
144 }
145
146 function annotateWithWikiData() {
147     function annotateForContributor(contributor) {
148         var listItem = findListChildForContributor(contributor);
149         if (!listItem) {
150             var listElement = document.getElementById(contributor.kind + 's');
151             var listItem = document.createElement('li');
152             listElement.appendChild(listItem);
153             listItem.style.backgroundColor = 'red';
154             populateContributorListItem(listItem, contributor);
155         } else {
156             var affiliationContainer = listItem.querySelector('.affiliation');
157             var affiliation = formatAffiliation(contributor);
158             if (affiliation && (!affiliationContainer || affiliationContainer.textContent != affiliation)) {
159                 addText(listItem, ' ');
160                 addWrappedText(listItem, 'em', {'style': 'background-color:red'}, affiliation);
161             }
162         }
163     }
164
165     var webkitTeamWikiUrl = 'http://trac.webkit.org/wiki/WebKit%20Team';
166     var xhr = new XMLHttpRequest();
167     xhr.onload = function () {
168         if (this.status !== 200)
169             return this.onerror();
170
171         var lines = this.responseText.split('\n');
172         // Match lines like * '''Ryosuke Niwa''' (rniwa) ''Google''
173         var teamWikiContributorEntryPattern = /^\s+\*\s+'''([^']+)'''\s*(\(([^']+)\)\s*)?(''([^']+)'')?\s*$/;
174         for (var i = 0; i < lines.length; i++) {
175             var match = lines[i].match(/\=\s+(Reviewer|Committer|Contributor)s\s+=/i);
176             if (match) {
177                 var currentKind = match[1].toLowerCase();
178                 continue;
179             }
180
181             // Strip special HTML characters
182             match = lines[i].replace(/[{}<>"%;&+/]/g, '').match(teamWikiContributorEntryPattern);
183             if (currentKind && match) {
184                 annotateForContributor({
185                     kind: currentKind,
186                     name: match[1],
187                     nicks: match[3] ? match[3].split(/,\s*/) : null,
188                     affiliation: match[5]
189                 });
190             }
191         }
192     }
193     xhr.onerror = function () { alert('Could not obtain http://trac.webkit.org/wiki/WebKit%20Team'); };
194     xhr.open('GET', webkitTeamWikiUrl + '?format=txt');
195     xhr.send();
196 }
197
198 var xhr = new XMLHttpRequest();
199 xhr.onload = function () {
200     if (this.status !== 200)
201         return this.onerror();
202     var contributors = parseCommittersPy(this.responseText);
203
204     populateContributorList(contributors, 'reviewer');
205     populateContributorList(contributors, 'committer');
206     populateContributorList(contributors, 'contributor');
207
208     if (location.search.indexOf('annotate') >= 0)
209         annotateWithWikiData();
210 };
211 xhr.onerror = function () { document.getElementById('container').textContent = 'Could not obtain committers.py'; };
212 xhr.open('GET', svnTrunkUrl + 'Tools/Scripts/webkitpy/common/config/committers.py');
213 xhr.send();
214
215 </script>
216
217 <?php
218 include("footer.inc");
219 ?>