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

Unified Diff: utils/apidoc/mdn/postProcess.dart

Issue 9225039: Integrate MDN content into API documentation. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Respond to review. Created 8 years, 11 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « utils/apidoc/mdn/full_run.sh ('k') | utils/apidoc/mdn/search.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: utils/apidoc/mdn/postProcess.dart
diff --git a/utils/apidoc/mdn/postProcess.dart b/utils/apidoc/mdn/postProcess.dart
new file mode 100644
index 0000000000000000000000000000000000000000..fb365a9547ef64278076faaa93c37486de95a62c
--- /dev/null
+++ b/utils/apidoc/mdn/postProcess.dart
@@ -0,0 +1,468 @@
+#library("dump");
+
+#import("../../../frog/lib/node/node.dart");
+#import('../../../frog/lib/node/fs.dart');
+#import("dart:json");
+
+Map database;
+Map allProps;
+Set matchedTypes;
+
+String orEmpty(String str) {
+ return str == null ? "" : str;
+}
+
+/** Returns whether the type has any property matching the specified name. */
+bool hasAny(String type, String prop) {
+ Map data = allProps[type];
+ return data['properties'].containsKey(prop) ||
+ data['methods'].containsKey(prop) ||
+ data['constants'].containsKey(prop);
+}
+
+List<String> sortStringCollection(Collection<String> collection) {
+ List<String> out = new List<String>();
+ out.addAll(collection);
+ out.sort((String a, String b) => a.compareTo(b));
+ return out;
+}
+
+/** Switch from a List of members to a Map of members. */
+Map getMembersMap(Map entry) {
+ List rawMembers = entry["members"];
+ Map members = new Map<String, Object>();
+ for (Map entry in rawMembers) {
+ members[entry['name']] = entry;
+ }
+ return members;
+}
+
+/**
+ * Add all missing members to the string output and return the number of
+ * missing members.
+ */
+int addMissingHelper(StringBuffer sb, String type, Map members,
+ String propType) {
+ int total = 0;
+ Map expected = allProps[type][propType];
+ if (expected == null) return total;
+ for(String name in sortStringCollection(expected.getKeys())) {
+ if (!members.containsKey(name)) {
+ total++;
+ sb.add("""
+ <tr class="missing">
+ <td>$name</td>
+ <td></td>
+ <td>Could not find documentation for $propType</td>
+ </tr>
+""");
+ }
+ }
+ return total;
+}
+
+int addMissing(StringBuffer sb, String type, Map members) {
+ int total = 0;
+ total += addMissingHelper(sb, type, members, 'properties');
+ total += addMissingHelper(sb, type, members, 'methods');
+ total += addMissingHelper(sb, type, members, 'constants');
+ return total;
+}
+
+/**
+ * Score an entry using heuristics to determine how well a entry
+ * matches the expected list of matching members.
+ * We could be much less naive and penalize spurious methods, prefer entries
+ * with class level comments, etc.
+ */
+num scoreEntry(Map entry, String type) {
+ num score = 0;
+ if (!entry.containsKey('skipped')) {
+ score++;
+ }
+ if (entry.containsKey("members")) {
+ Map members = getMembersMap(entry);
+ for (String name in members.getKeys()) {
+ if (hasAny(type, name)) {
+ score++;
+ }
+ }
+ }
+ return score;
+}
+
+/**
+ * Given a list of candidates for the documentation for a type, find the one
+ * that is the best.
+ */
+Map pickBestEntry(List entries, String type) {
+ num bestScore = -1;
+ Map bestEntry;
+ for (Map entry in entries) {
+ if (entry != null) {
+ num score = scoreEntry(entry, type);
+ if (score > bestScore) {
+ bestScore = score;
+ bestEntry = entry;
+ }
+ }
+ }
+ return bestEntry;
+}
+
+void main() {
+ // Database of code documentation.
+ database = JSON.parse(fs.readFileSync('output/database.json', 'utf8'));
+ // Database of expected property names for each type in WebKit.
+ allProps = JSON.parse(fs.readFileSync('data/dartIdl.json', 'utf8'));
+ // Types we have documentation for.
+ matchedTypes = new Set<String>();
+ int numMissingMethods = 0;
+ int numFoundMethods = 0;
+ int numExtraMethods = 0;
+ int numGen = 0;
+ int numSkipped = 0;
+ final sbSkipped = new StringBuffer();
+ final sbAllExamples = new StringBuffer();
+ final filteredDb = {};
+
+ // Table rows for all obsolete members.
+ final sbObsolete = new StringBuffer();
+ // Main documentation file.
+ final sb = new StringBuffer();
+
+ sb.add("""
+<html>
+ <head>
+ <style type="text/css">
+ body {
+ background-color: #eee;
+ margin: 10px;
+ font: 14px/1.428 "Lucida Grande", "Lucida Sans Unicode", Lucida, Arial, Helvetica, sans-serif;
+ }
+
+ .debug {
+ color: #888;
+ }
+
+ .compatibility, .links, .see-also, .summary, .members, .example {
+ border: 1px solid #CCC;
+ margin: 5px;
+ padding: 5px;
+ }
+
+ .type, #dart_summary {
+ border: 1px solid;
+ margin-top: 10px;
+ margin-bottom: 10px;
+ padding: 10px;
+ overflow: hidden;
+ background-color: white;
+ -moz-box-shadow: 5px 5px 5px #888;
+ -webkit-box-shadow: 5px 5px 5px #888;
+ box-shadow: 5px 5px 5px #888;
+ }
+
+ #dart_summary {
+ border: 2px solid #00F;
+ margin: 5px;
+ padding: 5px;
+ }
+
+ th {
+ background-color:#ccc;
+ font-weight: bold;
+ }
+
+ tr:nth-child(odd) {
+ background-color:#eee;
+ }
+ tr:nth-child(even) {
+ background-color:#fff;
+ }
+
+ tr:nth-child(odd).unknown {
+ background-color:#dd0;
+ }
+ tr:nth-child(even).unknown {
+ background-color:#ff0;
+ }
+
+ tr:nth-child(odd).missing {
+ background-color:#d88;
+ }
+ tr:nth-child(even).missing {
+ background-color:#faa;
+ }
+
+ li.unknown {
+ color: #f00;
+ }
+
+ td, th {
+ vertical-align: top;
+ }
+ </style>
+ <title>Doc Dump</title>
+ </head>
+ <body>
+ <h1>Doc Dump</h1>
+ <ul>
+ <li><a href="#dart_summary">Summary</a></li>
+ </li>
+""");
+
+ for (String type in sortStringCollection(database.getKeys())) {
+ Map entry = pickBestEntry(database[type], type);
+ filteredDb[type] = entry;
+ if (entry == null || entry.containsKey('skipped')) {
+ numSkipped++;
+ sbSkipped.add("""
+ <li id="$type">
+ <a target="_blank" href="http://www.google.com/cse?cx=017193972565947830266%3Awpqsk6dy6ee&ie=UTF-8&q=$type">
+ $type
+ </a> -- Title: ${entry == null ? "???" : entry["title"]} -- Issue: ${entry == null ? "???" : entry['cause']}
+ -- <a target="_blank" href="${entry == null ? "???" : entry["srcUrl"]}">scraped url</a>
+ </li>""");
+ continue;
+ }
+ matchedTypes.add(type);
+ numGen++;
+ StringBuffer sbSections = new StringBuffer();
+ StringBuffer sbMembers = new StringBuffer();
+ StringBuffer sbExamples = new StringBuffer();
+ if (entry.containsKey("members")) {
+ Map members = getMembersMap(entry);
+ sbMembers.add("""
+ <div class="members">
+ <h3><span class="debug">[dart]</span> Members</h3>
+ <table>
+ <tbody>
+ <tr>
+ <th>Name</th><th>Description</th><th>IDL</th><th>Status</th>
+ </tr>
+""");
+ for (String name in sortStringCollection(members.getKeys())) {
+ Map memberData = members[name];
+ bool unknown = !hasAny(type, name);
+ StringBuffer classes = new StringBuffer();
+ if (unknown) classes.add("unknown ");
+ if (unknown) {
+ numExtraMethods++;
+ } else {
+ numFoundMethods++;
+ }
+
+ final sbMember = new StringBuffer();
+
+ if (memberData.containsKey('url')) {
+ sbMember.add("""
+ <td><a href="${memberData['url']}">$name</a></td>
+""");
+ } else {
+ sbMember.add("""
+ <td>$name</td>
+""");
+ }
+ sbMember.add("""
+ <td>${memberData['help']}</td>
+ <td>
+ <pre>${orEmpty(memberData['idl'])}</pre>
+ </td>
+ <td>${memberData['obsolete'] == true ? "Obsolete" : ""}</td>
+""");
+ if (memberData['obsolete'] == true) {
+ sbObsolete.add("<tr class='$classes'><td>$type</td>$sbMember</tr>");
+ }
+ sbMembers.add("<tr class='$classes'>$sbMember</tr>");
+ }
+
+ numMissingMethods += addMissing(sbMembers, type, members);
+
+ sbMembers.add("""
+ </tbody>
+ </table>
+ </div>
+""");
+ }
+ for (String sectionName in
+ ["summary", "constructor", "compatibility", "specification", "seeAlso"])
+ if (entry.containsKey(sectionName)) {
+ sbSections.add("""
+ <div class="$sectionName">
+ <h3><span class="debug">[Dart]</span> $sectionName</h3>
+ ${entry[sectionName]}
+ </div>
+""");
+ }
+ if (entry.containsKey("links")) {
+ sbSections.add("""
+ <div class="links">
+ <h3><span class="debug">[Dart]</span> Specification</h3>
+ <ul>
+""");
+ List links = entry["links"];
+ for (Map link in links) {
+ sbSections.add("""
+ <li><a href="${link['href']}">${link['title']}</a></li>
+""");
+ }
+ sbSections.add("""
+ </ul>
+ </div>
+""");
+ }
+ if (entry.containsKey("examples")) {
+ for (String example in entry["examples"]) {
+ sbExamples.add("""
+ <div class="example">
+ <h3><span class="debug">[Dart]</span> Example</h3>
+ $example
+ </div>
+""");
+ }
+ }
+
+ String title = entry['title'];
+ if (title != type) {
+ title = '<h4>Dart type: $type</h4><h2>${title}</h2>';
+ } else {
+ title = '<h2>${title}</h2>';
+ }
+ sb.add("""
+ <div class='type' id="$type">
+ <a href='${entry['srcUrl']}'>$title</a>
+$sbSections
+$sbExamples
+$sbMembers
+ </div>
+""");
+ if (sbExamples.length > 0) {
+ sbAllExamples.add("""
+ <div class='type' id="$type">
+ <a href='${entry['srcUrl']}'>$title</a>
+ ${sbExamples.toString()}
+ </div>
+""");
+ }
+ }
+
+ for (String type in sortStringCollection(allProps.getKeys())) {
+ if (!matchedTypes.contains(type) &&
+ !database.containsKey(type)) {
+ numSkipped++;
+ sbSkipped.add("""
+ <li class="unknown" id="$type">
+ <a target="_blank" href="http://www.google.com/cse?cx=017193972565947830266%3Awpqsk6dy6ee&ie=UTF-8&q=$type">
+ $type
+ </a>
+ </li>
+""");
+ }
+ }
+
+ sb.add("""
+<div id="#dart_summary">
+ <h2>Summary</h2>
+ <h3>Generated docs for ${numGen} classes out of a possible ${allProps.getKeys().length}</h3>
+ <h3>Found documentation for $numFoundMethods methods listed in WebKit</h3>
+ <h3>Found documentation for $numExtraMethods methods not listed in WebKit</h3>
+ <h3>Unable to find documentation for $numMissingMethods methods not present in WebKit</h3>
+ <h3>Skipped generating documentation for $numSkipped classes due to no plausible matching files</h3>
+ <ul>
+$sbSkipped
+ </ul>
+</div>
+""");
+ sb.add("""
+ </body>
+</html>
+""");
+
+ fs.writeFileSync("output/database.html", sb.toString());
+
+ fs.writeFileSync("output/examples.html", """
+<html>
+ <head>
+ <style type="text/css">
+ body {
+ background-color: #eee;
+ margin: 10px;
+ font: 14px/1.428 "Lucida Grande", "Lucida Sans Unicode", Lucida, Arial, Helvetica, sans-serif;
+ }
+
+ .debug {
+ color: #888;
+ }
+
+ .example {
+ border: 1px solid #CCC;
+ margin: 5px;
+ padding: 5px;
+ }
+
+ .type {
+ border: 1px solid;
+ margin-top: 10px;
+ margin-bottom: 10px;
+ padding: 10px;
+ overflow: hidden;
+ background-color: white;
+ -moz-box-shadow: 5px 5px 5px #888;
+ -webkit-box-shadow: 5px 5px 5px #888;
+ box-shadow: 5px 5px 5px #888;
+ }
+ </style>
+ <title>All examples</title>
+ </head>
+ <body>
+ <h1>All examples</h1>
+$sbAllExamples
+ </body>
+ </html>
+""");
+
+ fs.writeFileSync("output/obsolete.html", """
+<html>
+ <head>
+ <style type="text/css">
+ body {
+ background-color: #eee;
+ margin: 10px;
+ font: 14px/1.428 "Lucida Grande", "Lucida Sans Unicode", Lucida, Arial, Helvetica, sans-serif;
+ }
+
+ .debug {
+ color: #888;
+ }
+
+ .type {
+ border: 1px solid;
+ margin-top: 10px;
+ margin-bottom: 10px;
+ padding: 10px;
+ overflow: hidden;
+ background-color: white;
+ -moz-box-shadow: 5px 5px 5px #888;
+ -webkit-box-shadow: 5px 5px 5px #888;
+ box-shadow: 5px 5px 5px #888;
+ }
+ </style>
+ <title>Methods marked as obsolete</title>
+ </head>
+ <body>
+ <h1>Methods marked as obsolete</h1>
+ <table>
+ <tbody>
+ <tr>
+ <th>Type</th><th>Name</th><th>Description</th><th>IDL</th><th>Status</th>
+ </tr>
+$sbObsolete
+ </tbody>
+ </table>
+ </body>
+ </html>
+ """);
+
+ fs.writeFileSync("output/database.filtered.json", JSON.stringify(filteredDb));
+}
« no previous file with comments | « utils/apidoc/mdn/full_run.sh ('k') | utils/apidoc/mdn/search.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698