Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(172)

Side by Side Diff: utils/apidoc/mdn/postProcess.dart

Issue 9315026: Cleanup mdn scripts (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Code review fixes Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « utils/apidoc/mdn/extractRunner.js ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #library("dump"); 1 #library("postProcess");
2 2
3 #import("../../../frog/lib/node/node.dart"); 3 #import("../../../frog/lib/node/node.dart");
4 #import("dart:json"); 4 #import("dart:json");
5 5
6 Map database; 6 // TODO(jacobr): this file conflates pretty printing of the JSON database with
7 Map allProps; 7 // filtering the database to select the best matches per file.
8 Set matchedTypes; 8 // Separate out the two tasks as quick and dirty coding is correct for pretty
9 // printing but more carefully documented code is required for the code
10 // filtering the database.
11 Map<String, List> database;
12 Map<String, Map> allProps;
13 Set<String> matchedTypes;
9 14
10 String orEmpty(String str) { 15 String orEmpty(String str) {
11 return str == null ? "" : str; 16 return str == null ? "" : str;
12 } 17 }
13 18
14 /** Returns whether the type has any property matching the specified name. */ 19 /** Returns whether the type has any member matching the specified name. */
15 bool hasAny(String type, String prop) { 20 bool hasAny(String type, String prop) {
16 Map data = allProps[type]; 21 final data = allProps[type];
17 return data['properties'].containsKey(prop) || 22 return data['properties'].containsKey(prop) ||
18 data['methods'].containsKey(prop) || 23 data['methods'].containsKey(prop) ||
19 data['constants'].containsKey(prop); 24 data['constants'].containsKey(prop);
20 } 25 }
21 26
22 List<String> sortStringCollection(Collection<String> collection) { 27 List<String> sortStringCollection(Collection<String> collection) {
23 List<String> out = new List<String>(); 28 final out = <String>[];
24 out.addAll(collection); 29 out.addAll(collection);
25 out.sort((String a, String b) => a.compareTo(b)); 30 out.sort((String a, String b) => a.compareTo(b));
26 return out; 31 return out;
27 } 32 }
28 33
29 /** Switch from a List of members to a Map of members. */ 34 /**
35 * Return the members from an [entry] as Map of member names to member
36 * objects.
37 */
30 Map getMembersMap(Map entry) { 38 Map getMembersMap(Map entry) {
31 List rawMembers = entry["members"]; 39 List<Map> rawMembers = entry["members"];
32 Map members = new Map<String, Object>(); 40 final members = {};
33 for (Map entry in rawMembers) { 41 for (final entry in rawMembers) {
34 members[entry['name']] = entry; 42 members[entry['name']] = entry;
35 } 43 }
36 return members; 44 return members;
37 } 45 }
38 46
39 /** 47 int addMissing(StringBuffer sb, String type, Map members) {
40 * Add all missing members to the string output and return the number of
41 * missing members.
42 */
43 int addMissingHelper(StringBuffer sb, String type, Map members,
44 String propType) {
45 int total = 0; 48 int total = 0;
46 Map expected = allProps[type][propType]; 49 /**
47 if (expected == null) return total; 50 * Add all missing members to the string output and return the number of
48 for(String name in sortStringCollection(expected.getKeys())) { 51 * missing members.
49 if (!members.containsKey(name)) { 52 */
50 total++; 53 void addMissingHelper(String propType) {
51 sb.add(""" 54 Map expected = allProps[type][propType];
52 <tr class="missing"> 55 if (expected != null) {
53 <td>$name</td> 56 for(final name in sortStringCollection(expected.getKeys())) {
54 <td></td> 57 if (!members.containsKey(name)) {
55 <td>Could not find documentation for $propType</td> 58 total++;
56 </tr> 59 sb.add("""
57 """); 60 <tr class="missing">
61 <td>$name</td>
62 <td></td>
63 <td>Could not find documentation for $propType</td>
64 </tr>
65 """);
66 }
67 }
58 } 68 }
59 } 69 }
60 return total;
61 }
62 70
63 int addMissing(StringBuffer sb, String type, Map members) { 71 addMissingHelper('properties');
64 int total = 0; 72 addMissingHelper('methods');
65 total += addMissingHelper(sb, type, members, 'properties'); 73 addMissingHelper('constants');
66 total += addMissingHelper(sb, type, members, 'methods');
67 total += addMissingHelper(sb, type, members, 'constants');
68 return total; 74 return total;
69 } 75 }
70 76
71 /** 77 /**
72 * Score an entry using heuristics to determine how well a entry 78 * Score entries using similarity heuristics calculated from the observed and
73 * matches the expected list of matching members. 79 * expected list of members. We could be much less naive and penalize spurious
74 * We could be much less naive and penalize spurious methods, prefer entries 80 * methods, prefer entries with class level comments, etc. This method is
75 * with class level comments, etc. 81 * needed becase we extract entries for each of the top search results for
82 * each class name and rely on these scores to determine which entry was
83 * best. Typically all scores but one will be zero. Multiple pages have
84 * non-zero scores when MDN has multiple pages on the same class or pages on
85 * similar classes (e.g. HTMLElement and Element), or pages on Mozilla
86 * specific classes that are similar to DOM classes (Console).
76 */ 87 */
77 num scoreEntry(Map entry, String type) { 88 num scoreEntry(Map entry, String type) {
78 num score = 0; 89 num score = 0;
90 // TODO(jacobr): consider removing skipped entries completely instead of
91 // just giving them lower scores.
79 if (!entry.containsKey('skipped')) { 92 if (!entry.containsKey('skipped')) {
80 score++; 93 score++;
81 } 94 }
82 if (entry.containsKey("members")) { 95 if (entry.containsKey("members")) {
83 Map members = getMembersMap(entry); 96 Map members = getMembersMap(entry);
84 for (String name in members.getKeys()) { 97 for (String name in members.getKeys()) {
85 if (hasAny(type, name)) { 98 if (hasAny(type, name)) {
86 score++; 99 score++;
87 } 100 }
88 } 101 }
89 } 102 }
90 return score; 103 return score;
91 } 104 }
92 105
93 /** 106 /**
94 * Given a list of candidates for the documentation for a type, find the one 107 * Given a list of candidates for the documentation for a type, find the one
95 * that is the best. 108 * that is the best.
96 */ 109 */
97 Map pickBestEntry(List entries, String type) { 110 Map pickBestEntry(List entries, String type) {
98 num bestScore = -1; 111 num bestScore = -1;
99 Map bestEntry; 112 Map bestEntry;
100 for (Map entry in entries) { 113 for (Map entry in entries) {
101 if (entry != null) { 114 if (entry != null) {
102 num score = scoreEntry(entry, type); 115 num score = scoreEntry(entry, type);
103 if (score > bestScore) { 116 if (score > bestScore) {
104 bestScore = score; 117 bestScore = score;
105 bestEntry = entry; 118 bestEntry = entry;
119 }
106 } 120 }
107 } 121 }
108 }
109 return bestEntry; 122 return bestEntry;
110 } 123 }
111 124
112 void main() { 125 void main() {
113 // Database of code documentation. 126 // Database of code documentation.
114 database = JSON.parse(fs.readFileSync('output/database.json', 'utf8')); 127 database = JSON.parse(fs.readFileSync('output/database.json', 'utf8'));
115 // Database of expected property names for each type in WebKit. 128 // Database of expected property names for each type in WebKit.
116 allProps = JSON.parse(fs.readFileSync('data/dartIdl.json', 'utf8')); 129 allProps = JSON.parse(fs.readFileSync('data/dartIdl.json', 'utf8'));
117 // Types we have documentation for. 130 // Types we have documentation for.
118 matchedTypes = new Set<String>(); 131 matchedTypes = new Set<String>();
119 int numMissingMethods = 0; 132 int numMissingMethods = 0;
120 int numFoundMethods = 0; 133 int numFoundMethods = 0;
121 int numExtraMethods = 0; 134 int numExtraMethods = 0;
122 int numGen = 0; 135 int numGen = 0;
123 int numSkipped = 0; 136 int numSkipped = 0;
124 final sbSkipped = new StringBuffer(); 137 final sbSkipped = new StringBuffer();
125 final sbAllExamples = new StringBuffer(); 138 final sbAllExamples = new StringBuffer();
126 final filteredDb = {}; 139 final filteredDb = {};
127 140
128 // Table rows for all obsolete members. 141 // Table rows for all obsolete members.
129 final sbObsolete = new StringBuffer(); 142 final sbObsolete = new StringBuffer();
130 // Main documentation file. 143 // Main documentation file.
131 final sb = new StringBuffer(); 144 final sb = new StringBuffer();
132 145
146 // TODO(jacobr): switch to using a real template system instead of string
147 // interpolation combined with StringBuffers.
133 sb.add(""" 148 sb.add("""
134 <html> 149 <html>
135 <head> 150 <head>
136 <style type="text/css"> 151 <style type="text/css">
137 body { 152 body {
138 background-color: #eee; 153 background-color: #eee;
139 margin: 10px; 154 margin: 10px;
140 » font: 14px/1.428 "Lucida Grande", "Lucida Sans Unicode", Lucida, Arial, Helvetica, sans-serif; 155 » font: 14px/1.428 "Lucida Grande", "Lucida Sans Unicode", Lucida,
156 Arial, Helvetica, sans-serif;
141 } 157 }
142 158
143 .debug { 159 .debug {
144 color: #888; 160 color: #888;
145 } 161 }
146 162
147 .compatibility, .links, .see-also, .summary, .members, .example { 163 .compatibility, .links, .see-also, .summary, .members, .example {
148 border: 1px solid #CCC; 164 border: 1px solid #CCC;
149 margin: 5px; 165 margin: 5px;
150 padding: 5px; 166 padding: 5px;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 229
214 for (String type in sortStringCollection(database.getKeys())) { 230 for (String type in sortStringCollection(database.getKeys())) {
215 Map entry = pickBestEntry(database[type], type); 231 Map entry = pickBestEntry(database[type], type);
216 filteredDb[type] = entry; 232 filteredDb[type] = entry;
217 if (entry == null || entry.containsKey('skipped')) { 233 if (entry == null || entry.containsKey('skipped')) {
218 numSkipped++; 234 numSkipped++;
219 sbSkipped.add(""" 235 sbSkipped.add("""
220 <li id="$type"> 236 <li id="$type">
221 <a target="_blank" href="http://www.google.com/cse?cx=01719397256594783026 6%3Awpqsk6dy6ee&ie=UTF-8&q=$type"> 237 <a target="_blank" href="http://www.google.com/cse?cx=01719397256594783026 6%3Awpqsk6dy6ee&ie=UTF-8&q=$type">
222 $type 238 $type
223 </a> -- Title: ${entry == null ? "???" : entry["title"]} -- Issue: ${entry == null ? "???" : entry['cause']} 239 </a>
224 -- <a target="_blank" href="${entry == null ? "???" : entry["srcUrl"]}">sc raped url</a> 240 --
241 Title: ${entry == null ? "???" : entry["title"]} -- Issue:
242 ${entry == null ? "???" : entry['cause']}
243 --
244 <a target="_blank" href="${entry == null ? "???" : entry["srcUrl"]}">
245 scraped url
246 </a>
225 </li>"""); 247 </li>""");
226 continue; 248 continue;
227 } 249 }
228 matchedTypes.add(type); 250 matchedTypes.add(type);
229 numGen++; 251 numGen++;
230 StringBuffer sbSections = new StringBuffer(); 252 StringBuffer sbSections = new StringBuffer();
231 StringBuffer sbMembers = new StringBuffer(); 253 StringBuffer sbMembers = new StringBuffer();
232 StringBuffer sbExamples = new StringBuffer(); 254 StringBuffer sbExamples = new StringBuffer();
233 if (entry.containsKey("members")) { 255 if (entry.containsKey("members")) {
234 » Map members = getMembersMap(entry); 256 Map members = getMembersMap(entry);
235 » sbMembers.add(""" 257 sbMembers.add("""
236 <div class="members"> 258 <div class="members">
237 <h3><span class="debug">[dart]</span> Members</h3> 259 <h3><span class="debug">[dart]</span> Members</h3>
238 <table> 260 <table>
239 <tbody> 261 <tbody>
240 <tr> 262 <tr>
241 <th>Name</th><th>Description</th><th>IDL</th><th>Status</th> 263 <th>Name</th><th>Description</th><th>IDL</th><th>Status</th>
242 </tr> 264 </tr>
243 """); 265 """);
244 for (String name in sortStringCollection(members.getKeys())) { 266 for (String name in sortStringCollection(members.getKeys())) {
245 Map memberData = members[name]; 267 Map memberData = members[name];
246 bool unknown = !hasAny(type, name); 268 bool unknown = !hasAny(type, name);
247 StringBuffer classes = new StringBuffer(); 269 StringBuffer classes = new StringBuffer();
248 if (unknown) classes.add("unknown "); 270 if (unknown) classes.add("unknown ");
249 if (unknown) { 271 if (unknown) {
250 numExtraMethods++; 272 numExtraMethods++;
251 } else { 273 } else {
252 numFoundMethods++; 274 numFoundMethods++;
253 } 275 }
254 276
255 final sbMember = new StringBuffer(); 277 final sbMember = new StringBuffer();
256 278
257 if (memberData.containsKey('url')) { 279 if (memberData.containsKey('url')) {
258 sbMember.add(""" 280 sbMember.add("""
259 <td><a href="${memberData['url']}">$name</a></td> 281 <td><a href="${memberData['url']}">$name</a></td>
260 """); 282 """);
261 } else { 283 } else {
262 sbMember.add(""" 284 sbMember.add("""
263 <td>$name</td> 285 <td>$name</td>
264 """); 286 """);
265 } 287 }
266 sbMember.add(""" 288 sbMember.add("""
267 <td>${memberData['help']}</td> 289 <td>${memberData['help']}</td>
268 <td> 290 <td>
269 <pre>${orEmpty(memberData['idl'])}</pre> 291 <pre>${orEmpty(memberData['idl'])}</pre>
270 </td> 292 </td>
271 <td>${memberData['obsolete'] == true ? "Obsolete" : ""}</td> 293 <td>${memberData['obsolete'] == true ? "Obsolete" : ""}</td>
272 """); 294 """);
273 if (memberData['obsolete'] == true) { 295 if (memberData['obsolete'] == true) {
274 sbObsolete.add("<tr class='$classes'><td>$type</td>$sbMember</tr>"); 296 sbObsolete.add("<tr class='$classes'><td>$type</td>$sbMember</tr>");
275 } 297 }
276 sbMembers.add("<tr class='$classes'>$sbMember</tr>"); 298 sbMembers.add("<tr class='$classes'>$sbMember</tr>");
277 } 299 }
278 300
279 numMissingMethods += addMissing(sbMembers, type, members); 301 numMissingMethods += addMissing(sbMembers, type, members);
280 302
281 sbMembers.add(""" 303 sbMembers.add("""
282 </tbody> 304 </tbody>
283 </table> 305 </table>
284 </div> 306 </div>
285 """); 307 """);
286 } 308 }
287 for (String sectionName in 309 for (String sectionName in
288 ["summary", "constructor", "compatibility", "specification", "seeAlso"]) 310 ["summary", "constructor", "compatibility", "specification",
289 if (entry.containsKey(sectionName)) { 311 "seeAlso"]) {
290 sbSections.add(""" 312 if (entry.containsKey(sectionName)) {
313 sbSections.add("""
291 <div class="$sectionName"> 314 <div class="$sectionName">
292 <h3><span class="debug">[Dart]</span> $sectionName</h3> 315 <h3><span class="debug">[Dart]</span> $sectionName</h3>
293 ${entry[sectionName]} 316 ${entry[sectionName]}
294 </div> 317 </div>
295 """); 318 """);
319 }
296 } 320 }
297 if (entry.containsKey("links")) { 321 if (entry.containsKey("links")) {
298 sbSections.add(""" 322 sbSections.add("""
299 <div class="links"> 323 <div class="links">
300 <h3><span class="debug">[Dart]</span> Specification</h3> 324 <h3><span class="debug">[Dart]</span> Specification</h3>
301 <ul> 325 <ul>
302 """); 326 """);
303 List links = entry["links"]; 327 List links = entry["links"];
304 for (Map link in links) { 328 for (Map link in links) {
305 sbSections.add(""" 329 sbSections.add("""
306 <li><a href="${link['href']}">${link['title']}</a></li> 330 <li><a href="${link['href']}">${link['title']}</a></li>
307 """); 331 """);
308 » } 332 }
309 sbSections.add(""" 333 sbSections.add("""
310 </ul> 334 </ul>
311 </div> 335 </div>
312 """); 336 """);
313 } 337 }
314 if (entry.containsKey("examples")) { 338 if (entry.containsKey("examples")) {
315 for (String example in entry["examples"]) { 339 for (String example in entry["examples"]) {
316 sbExamples.add(""" 340 sbExamples.add("""
317 <div class="example"> 341 <div class="example">
318 <h3><span class="debug">[Dart]</span> Example</h3> 342 <h3><span class="debug">[Dart]</span> Example</h3>
319 $example 343 $example
320 </div> 344 </div>
321 """); 345 """);
322 } 346 }
323 } 347 }
324 348
325 String title = entry['title']; 349 String title = entry['title'];
326 if (title != type) { 350 if (title != type) {
327 » title = '<h4>Dart type: $type</h4><h2>${title}</h2>'; 351 title = '<h4>Dart type: $type</h4><h2>$title</h2>';
328 } else { 352 } else {
329 » title = '<h2>${title}</h2>'; 353 title = '<h2>$title</h2>';
330 } 354 }
331 sb.add(""" 355 sb.add("""
332 <div class='type' id="$type"> 356 <div class='type' id="$type">
333 <a href='${entry['srcUrl']}'>$title</a> 357 <a href='${entry['srcUrl']}'>$title</a>
334 $sbSections 358 $sbSections
335 $sbExamples 359 $sbExamples
336 $sbMembers 360 $sbMembers
337 </div> 361 </div>
338 """); 362 """);
339 if (sbExamples.length > 0) { 363 if (sbExamples.length > 0) {
340 sbAllExamples.add(""" 364 sbAllExamples.add("""
341 <div class='type' id="$type"> 365 <div class='type' id="$type">
342 <a href='${entry['srcUrl']}'>$title</a> 366 <a href='${entry['srcUrl']}'>$title</a>
343 ${sbExamples.toString()} 367 $sbExamples
344 </div> 368 </div>
345 """); 369 """);
346 } 370 }
347 } 371 }
348 372
349 for (String type in sortStringCollection(allProps.getKeys())) { 373 for (String type in sortStringCollection(allProps.getKeys())) {
350 if (!matchedTypes.contains(type) && 374 if (!matchedTypes.contains(type) &&
351 !database.containsKey(type)) { 375 !database.containsKey(type)) {
352 numSkipped++; 376 numSkipped++;
353 sbSkipped.add(""" 377 sbSkipped.add("""
354 <li class="unknown" id="$type"> 378 <li class="unknown" id="$type">
355 <a target="_blank" href="http://www.google.com/cse?cx=01719397256594783026 6%3Awpqsk6dy6ee&ie=UTF-8&q=$type"> 379 <a target="_blank" href="http://www.google.com/cse?cx=01719397256594783026 6%3Awpqsk6dy6ee&ie=UTF-8&q=$type">
356 $type 380 $type
357 </a> 381 </a>
358 </li> 382 </li>
359 """); 383 """);
360 } 384 }
361 } 385 }
362 386
363 sb.add(""" 387 sb.add("""
364 <div id="#dart_summary"> 388 <div id="#dart_summary">
365 <h2>Summary</h2> 389 <h2>Summary</h2>
366 <h3>Generated docs for ${numGen} classes out of a possible ${allProps.getKeys( ).length}</h3> 390 <h3>
391 Generated docs for $numGen classes out of a possible
392 ${allProps.getKeys().length}
393 </h3>
367 <h3>Found documentation for $numFoundMethods methods listed in WebKit</h3> 394 <h3>Found documentation for $numFoundMethods methods listed in WebKit</h3>
368 <h3>Found documentation for $numExtraMethods methods not listed in WebKit</h3> 395 <h3>
369 <h3>Unable to find documentation for $numMissingMethods methods not present in WebKit</h3> 396 Found documentation for $numExtraMethods methods not listed in WebKit
370 <h3>Skipped generating documentation for $numSkipped classes due to no plausib le matching files</h3> 397 </h3>
398 <h3>
399 Unable to find documentation for $numMissingMethods methods present in
400 WebKit
401 </h3>
402 <h3>
403 Skipped generating documentation for $numSkipped classes due to no
404 plausible matching files
405 </h3>
371 <ul> 406 <ul>
372 $sbSkipped 407 $sbSkipped
373 </ul> 408 </ul>
374 </div> 409 </div>
375 """); 410 """);
376 sb.add(""" 411 sb.add("""
377 </body> 412 </body>
378 </html> 413 </html>
379 """); 414 """);
380 415
381 fs.writeFileSync("output/database.html", sb.toString()); 416 fs.writeFileSync("output/database.html", sb.toString());
382 417
383 fs.writeFileSync("output/examples.html", """ 418 fs.writeFileSync("output/examples.html", """
384 <html> 419 <html>
385 <head> 420 <head>
386 <style type="text/css"> 421 <style type="text/css">
387 body { 422 body {
388 background-color: #eee; 423 background-color: #eee;
389 margin: 10px; 424 margin: 10px;
390 » font: 14px/1.428 "Lucida Grande", "Lucida Sans Unicode", Lucida, Arial, Helvetica, sans-serif; 425 » font: 14px/1.428 "Lucida Grande", "Lucida Sans Unicode", Lucida, Arial,
426 Helvetica, sans-serif;
391 } 427 }
392 428
393 .debug { 429 .debug {
394 color: #888; 430 color: #888;
395 } 431 }
396 432
397 .example { 433 .example {
398 border: 1px solid #CCC; 434 border: 1px solid #CCC;
399 margin: 5px; 435 margin: 5px;
400 padding: 5px; 436 padding: 5px;
(...skipping 20 matching lines...) Expand all
421 </html> 457 </html>
422 """); 458 """);
423 459
424 fs.writeFileSync("output/obsolete.html", """ 460 fs.writeFileSync("output/obsolete.html", """
425 <html> 461 <html>
426 <head> 462 <head>
427 <style type="text/css"> 463 <style type="text/css">
428 body { 464 body {
429 background-color: #eee; 465 background-color: #eee;
430 margin: 10px; 466 margin: 10px;
431 font: 14px/1.428 "Lucida Grande", "Lucida Sans Unicode", Lucida, Arial, Helvetica, sans-serif; 467 font: 14px/1.428 "Lucida Grande", "Lucida Sans Unicode", Lucida,
468 Arial, Helvetica, sans-serif;
432 } 469 }
433 470
434 .debug { 471 .debug {
435 color: #888; 472 color: #888;
436 } 473 }
437 474
438 .type { 475 .type {
439 border: 1px solid; 476 border: 1px solid;
440 margin-top: 10px; 477 margin-top: 10px;
441 margin-bottom: 10px; 478 margin-bottom: 10px;
442 padding: 10px; 479 padding: 10px;
443 overflow: hidden; 480 overflow: hidden;
444 background-color: white; 481 background-color: white;
445 -moz-box-shadow: 5px 5px 5px #888; 482 -moz-box-shadow: 5px 5px 5px #888;
446 -webkit-box-shadow: 5px 5px 5px #888; 483 -webkit-box-shadow: 5px 5px 5px #888;
447 box-shadow: 5px 5px 5px #888; 484 box-shadow: 5px 5px 5px #888;
448 } 485 }
449 </style> 486 </style>
450 <title>Methods marked as obsolete</title> 487 <title>Methods marked as obsolete</title>
451 </head> 488 </head>
452 <body> 489 <body>
453 <h1>Methods marked as obsolete</h1> 490 <h1>Methods marked as obsolete</h1>
454 <table> 491 <table>
455 <tbody> 492 <tbody>
456 <tr> 493 <tr>
457 <th>Type</th><th>Name</th><th>Description</th><th>IDL</th><th>St atus</th> 494 <th>Type</th>
458 </tr> 495 <th>Name</th>
496 <th>Description</th>
497 <th>IDL</th>
498 <th>Status</th>
499 </tr>
459 $sbObsolete 500 $sbObsolete
460 </tbody> 501 </tbody>
461 </table> 502 </table>
462 </body> 503 </body>
463 </html> 504 </html>
464 """); 505 """);
465 506
466 fs.writeFileSync("output/database.filtered.json", JSON.stringify(filteredDb)); 507 fs.writeFileSync("output/database.filtered.json",
508 JSON.stringify(filteredDb));
467 } 509 }
OLDNEW
« no previous file with comments | « utils/apidoc/mdn/extractRunner.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698