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