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

Side by Side Diff: chrome/common/extensions/docs/js/api_page_generator.js

Issue 2957009: Change the existing extension samples page to an automatically-generated searchable directory. (Closed) Base URL: http://src.chromium.org/git/chromium.git
Patch Set: Make changes suggested by Antony Created 10 years, 4 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
OLDNEW
1 /** 1 /**
2 * @fileoverview This file is the controller for generating extension 2 * @fileoverview This file is the controller for generating extension
3 * doc pages. 3 * doc pages.
4 * 4 *
5 * It expects to have available via XHR (relative path): 5 * It expects to have available via XHR (relative path):
6 * 1) API_TEMPLATE which is the main template for the api pages. 6 * 1) API_TEMPLATE which is the main template for the api pages.
7 * 2) A file located at SCHEMA which is shared with the extension system and 7 * 2) A file located at SCHEMA which is shared with the extension system and
8 * defines the methods and events contained in one api. 8 * defines the methods and events contained in one api.
9 * 3) (Possibly) A static version of the current page url in /static/. I.e. 9 * 3) (Possibly) A static version of the current page url in /static/. I.e.
10 * if called as ../foo.html, it will look for ../static/foo.html. 10 * if called as ../foo.html, it will look for ../static/foo.html.
11 * 11 *
12 * The "shell" page may have a renderering already contained within it so that 12 * The "shell" page may have a renderering already contained within it so that
13 * the docs can be indexed. 13 * the docs can be indexed.
14 * 14 *
15 */ 15 */
16 16
17 var API_TEMPLATE = "template/api_template.html"; 17 var API_TEMPLATE = "template/api_template.html";
18 var SCHEMA = "../api/extension_api.json"; 18 var SCHEMA = "../api/extension_api.json";
19 var SAMPLES = "samples.json";
19 var REQUEST_TIMEOUT = 2000; 20 var REQUEST_TIMEOUT = 2000;
20 21
21 function staticResource(name) { return "static/" + name + ".html"; } 22 function staticResource(name) { return "static/" + name + ".html"; }
22 23
23 // Base name of this page. (i.e. "tabs", "overview", etc...). 24 // Base name of this page. (i.e. "tabs", "overview", etc...).
24 var pageBase; 25 var pageBase;
25 26
26 // Data to feed as context into the template. 27 // Data to feed as context into the template.
27 var pageData = {}; 28 var pageData = {};
28 29
29 // The full extension api schema 30 // The full extension api schema
30 var schema; 31 var schema;
31 32
33 // List of Chrome extension samples.
34 var samples;
35
36 // Mappings of api calls to URLs
37 var apiMapping;
38
32 // The current module for this page (if this page is an api module); 39 // The current module for this page (if this page is an api module);
33 var module; 40 var module;
34 41
35 // Mapping from typeId to module. 42 // Mapping from typeId to module.
36 var typeModule = {}; 43 var typeModule = {};
37 44
38 // Auto-created page name as default 45 // Auto-created page name as default
39 var pageName; 46 var pageName;
40 47
41 // If this page is an apiModule, the name of the api module 48 // If this page is an apiModule, the name of the api module
42 var apiModuleName; 49 var apiModuleName;
43 50
44 Array.prototype.each = function(f) {
45 for (var i = 0; i < this.length; i++) {
46 f(this[i], i);
47 }
48 }
49 51
50 // Visits each item in the list in-order. Stops when f returns any truthy 52 // Visits each item in the list in-order. Stops when f returns any truthy
51 // value and returns that node. 53 // value and returns that node.
52 Array.prototype.select = function(f) { 54 Array.prototype.select = function(f) {
53 for (var i = 0; i < this.length; i++) { 55 for (var i = 0; i < this.length; i++) {
54 if (f(this[i], i)) 56 if (f(this[i], i))
55 return this[i]; 57 return this[i];
56 } 58 }
57 } 59 }
58 60
59 Array.prototype.map = function(f) {
60 var retval = [];
61 for (var i = 0; i < this.length; i++) {
62 retval.push(f(this[i], i));
63 }
64 return retval;
65 }
66
67 // Assigns all keys & values of |obj2| to |obj1|. 61 // Assigns all keys & values of |obj2| to |obj1|.
68 function extend(obj, obj2) { 62 function extend(obj, obj2) {
69 for (var k in obj2) { 63 for (var k in obj2) {
70 obj[k] = obj2[k]; 64 obj[k] = obj2[k];
71 } 65 }
72 } 66 }
73 67
74 /* 68 /*
75 * Main entry point for composing the page. It will fetch it's template, 69 * Main entry point for composing the page. It will fetch it's template,
76 * the extension api, and attempt to fetch the matching static content. 70 * the extension api, and attempt to fetch the matching static content.
(...skipping 30 matching lines...) Expand all
107 // Not fatal. Some api pages may not have matching static content. 101 // Not fatal. Some api pages may not have matching static content.
108 fetchSchema(); 102 fetchSchema();
109 }); 103 });
110 } 104 }
111 105
112 function fetchSchema() { 106 function fetchSchema() {
113 // Now the page is composed with the authored content, we fetch the schema 107 // Now the page is composed with the authored content, we fetch the schema
114 // and populate the templates. 108 // and populate the templates.
115 fetchContent(SCHEMA, function(schemaContent) { 109 fetchContent(SCHEMA, function(schemaContent) {
116 schema = JSON.parse(schemaContent); 110 schema = JSON.parse(schemaContent);
117 renderTemplate(); 111 if (pageName.toLowerCase() == "samples") {
118 112 fetchSamples();
113 } else {
114 renderTemplate();
115 }
119 }, function(error) { 116 }, function(error) {
120 alert("Failed to load " + SCHEMA); 117 alert("Failed to load " + SCHEMA);
121 }); 118 });
122 } 119 }
123 120
121 function fetchSamples() {
122 // If we're rendering the samples directory, fetch the samples manifest.
123 fetchContent(SAMPLES, function(sampleManifest) {
124 var data = JSON.parse(sampleManifest);
125 samples = data.samples;
126 apiMapping = data.api;
127 renderTemplate();
128 }, function(error) {
129 renderTemplate();
130 });
131 }
132
124 /** 133 /**
125 * Fetches |url| and returns it's text contents from the xhr.responseText in 134 * Fetches |url| and returns it's text contents from the xhr.responseText in
126 * onSuccess(content) 135 * onSuccess(content)
127 */ 136 */
128 function fetchContent(url, onSuccess, onError) { 137 function fetchContent(url, onSuccess, onError) {
129 var localUrl = url; 138 var localUrl = url;
130 var xhr = new XMLHttpRequest(); 139 var xhr = new XMLHttpRequest();
131 var abortTimerId = window.setTimeout(function() { 140 var abortTimerId = window.setTimeout(function() {
132 xhr.abort(); 141 xhr.abort();
133 console.log("XHR Timed out"); 142 console.log("XHR Timed out");
(...skipping 26 matching lines...) Expand all
160 xhr.open("GET", url, true); 169 xhr.open("GET", url, true);
161 xhr.send(null); 170 xhr.send(null);
162 } catch(e) { 171 } catch(e) {
163 console.log("ex: " + e); 172 console.log("ex: " + e);
164 console.error("exception: " + e); 173 console.error("exception: " + e);
165 handleError(); 174 handleError();
166 } 175 }
167 } 176 }
168 177
169 function renderTemplate() { 178 function renderTemplate() {
170 schema.each(function(mod) { 179 schema.forEach(function(mod) {
171 if (mod.namespace == pageBase) { 180 if (mod.namespace == pageBase) {
172 // Do not render page for modules which are marked as "nodoc": true. 181 // Do not render page for modules which are marked as "nodoc": true.
173 if (mod.nodoc) { 182 if (mod.nodoc) {
174 return; 183 return;
175 } 184 }
176 // This page is an api page. Setup types and apiDefinition. 185 // This page is an api page. Setup types and apiDefinition.
177 module = mod; 186 module = mod;
178 apiModuleName = "chrome." + module.namespace; 187 apiModuleName = "chrome." + module.namespace;
179 pageData.apiDefinition = module; 188 pageData.apiDefinition = module;
180 } 189 }
181 190
182 if (mod.types) { 191 if (mod.types) {
183 mod.types.each(function(type) { 192 mod.types.forEach(function(type) {
184 typeModule[type.id] = mod; 193 typeModule[type.id] = mod;
185 }); 194 });
186 } 195 }
187 }); 196 });
188 197
198 /**
199 * Special pages like the samples gallery may want to modify their template
200 * data to include additional information. This hook allows a page template
201 * to specify code that runs in the context of the api_page_generator.js
202 * file before the jstemplate is rendered.
203 *
204 * To specify such code, the page template should include a script block with
205 * a type of "text/prerenderjs" containing the code to be executed. Note that
206 * linking to an external file is not supported - code must be accessible
207 * via the script block's innerText property.
208 *
209 * Code that is run this way may modify the data sent to jstemplate by
210 * modifying the window.pageData variable. This code will also have access
211 * to any methods declared in the api_page_generator.js file. The code
212 * does not need to return any specific value to function.
213 *
214 * Note that code specified in this manner will be removed before the
215 * template is rendered, and will therefore not be exposed to the end user
216 * in the final rendered template.
217 */
218 var preRender = document.querySelector('script[type="text/prerenderjs"]');
219 if (preRender) {
220 preRender.parentElement.removeChild(preRender);
221 eval(preRender.innerText);
222 }
223
189 // Render to template 224 // Render to template
190 var input = new JsEvalContext(pageData); 225 var input = new JsEvalContext(pageData);
191 var output = document.getElementsByTagName("body")[0]; 226 var output = document.getElementsByTagName("body")[0];
192 jstProcess(input, output); 227 jstProcess(input, output);
193 228
194 selectCurrentPageOnLeftNav(); 229 selectCurrentPageOnLeftNav();
195 230
196 document.title = getPageTitle(); 231 document.title = getPageTitle();
197 // Show 232 // Show
198 if (window.postRender) 233 if (window.postRender)
199 window.postRender(); 234 window.postRender();
200 235
201 if (parent && parent.done) 236 if (parent && parent.done)
202 parent.done(); 237 parent.done();
203 } 238 }
204 239
205 function removeJsTemplateAttributes(root) { 240 function removeJsTemplateAttributes(root) {
206 var jsattributes = ["jscontent", "jsselect", "jsdisplay", "transclude", 241 var jsattributes = ["jscontent", "jsselect", "jsdisplay", "transclude",
207 "jsvalues", "jsvars", "jseval", "jsskip", "jstcache", 242 "jsvalues", "jsvars", "jseval", "jsskip", "jstcache",
208 "jsinstance"]; 243 "jsinstance"];
209 244
210 var nodes = root.getElementsByTagName("*"); 245 var nodes = root.getElementsByTagName("*");
211 for (var i = 0; i < nodes.length; i++) { 246 for (var i = 0; i < nodes.length; i++) {
212 var n = nodes[i] 247 var n = nodes[i]
213 jsattributes.each(function(attributeName) { 248 jsattributes.forEach(function(attributeName) {
214 n.removeAttribute(attributeName); 249 n.removeAttribute(attributeName);
215 }); 250 });
216 } 251 }
217 } 252 }
218 253
219 function serializePage() { 254 function serializePage() {
220 removeJsTemplateAttributes(document); 255 removeJsTemplateAttributes(document);
221 var s = new XMLSerializer(); 256 var s = new XMLSerializer();
222 return s.serializeToString(document); 257 return s.serializeToString(document);
223 } 258 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 } 293 }
259 parent.removeChild(node); 294 parent.removeChild(node);
260 parent.insertBefore(node.firstChild, parent.firstChild); 295 parent.insertBefore(node.firstChild, parent.firstChild);
261 return true; 296 return true;
262 } 297 }
263 }); 298 });
264 } 299 }
265 300
266 /* 301 /*
267 * Template Callout Functions 302 * Template Callout Functions
268 * The jstProcess() will call out to these functions from within the page templa te 303 * The jstProcess() will call out to these functions from within the page
304 * template
269 */ 305 */
270 306
271 function stableAPIs() { 307 function stableAPIs() {
272 return schema.filter(function(module) { 308 return schema.filter(function(module) {
273 return !module.nodoc && module.namespace.indexOf("experimental") < 0; 309 return !module.nodoc && module.namespace.indexOf("experimental") < 0;
274 }).map(function(module) { 310 }).map(function(module) {
275 return module.namespace; 311 return module.namespace;
276 }).sort(); 312 }).sort();
277 } 313 }
278 314
279 function experimentalAPIs() { 315 function experimentalAPIs() {
280 return schema.filter(function(module) { 316 return schema.filter(function(module) {
281 return !module.nodoc && module.namespace.indexOf("experimental") == 0; 317 return !module.nodoc && module.namespace.indexOf("experimental") == 0;
282 }).map(function(module) { 318 }).map(function(module) {
283 return module.namespace; 319 return module.namespace;
284 }).sort(); 320 }).sort();
285 } 321 }
286 322
287 function getDataFromPageHTML(id) { 323 function getDataFromPageHTML(id) {
288 var node = document.getElementById(id); 324 var node = document.getElementById(id);
(...skipping 24 matching lines...) Expand all
313 349
314 function showSideNav() { 350 function showSideNav() {
315 return getDataFromPageHTML("pageData-showSideNav") != "false"; 351 return getDataFromPageHTML("pageData-showSideNav") != "false";
316 } 352 }
317 353
318 function getStaticTOC() { 354 function getStaticTOC() {
319 var staticHNodes = evalXPathFromId(".//h2|h3", "static"); 355 var staticHNodes = evalXPathFromId(".//h2|h3", "static");
320 var retval = []; 356 var retval = [];
321 var lastH2; 357 var lastH2;
322 358
323 staticHNodes.each(function(n, i) { 359 staticHNodes.forEach(function(n, i) {
324 var anchorName = n.id || n.nodeName + "-" + i; 360 var anchorName = n.id || n.nodeName + "-" + i;
325 if (!n.id) { 361 if (!n.id) {
326 var a = document.createElement('a'); 362 var a = document.createElement('a');
327 a.name = anchorName; 363 a.name = anchorName;
328 n.parentNode.insertBefore(a, n); 364 n.parentNode.insertBefore(a, n);
329 } 365 }
330 var dataNode = { name: n.innerHTML, href: anchorName }; 366 var dataNode = { name: n.innerHTML, href: anchorName };
331 367
332 if (n.nodeName == "H2") { 368 if (n.nodeName == "H2") {
333 retval.push(dataNode); 369 retval.push(dataNode);
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 } 436 }
401 return propertyList; 437 return propertyList;
402 } 438 }
403 439
404 function getTypeName(schema) { 440 function getTypeName(schema) {
405 if (schema.$ref) 441 if (schema.$ref)
406 return schema.$ref; 442 return schema.$ref;
407 443
408 if (schema.choices) { 444 if (schema.choices) {
409 var typeNames = []; 445 var typeNames = [];
410 schema.choices.each(function(c) { 446 schema.choices.forEach(function(c) {
411 typeNames.push(getTypeName(c)); 447 typeNames.push(getTypeName(c));
412 }); 448 });
413 449
414 return typeNames.join(" or "); 450 return typeNames.join(" or ");
415 } 451 }
416 452
417 if (schema.type == "array") 453 if (schema.type == "array")
418 return "array of " + getTypeName(schema.items); 454 return "array of " + getTypeName(schema.items);
419 455
420 if (schema.isInstanceOf) 456 if (schema.isInstanceOf)
421 return schema.isInstanceOf; 457 return schema.isInstanceOf;
422 458
423 return schema.type; 459 return schema.type;
424 } 460 }
425 461
426 function getSignatureString(parameters) { 462 function getSignatureString(parameters) {
427 var retval = []; 463 var retval = [];
428 parameters.each(function(param, i) { 464 parameters.forEach(function(param, i) {
429 retval.push(getTypeName(param) + " " + param.name); 465 retval.push(getTypeName(param) + " " + param.name);
430 }); 466 });
431 467
432 return retval.join(", "); 468 return retval.join(", ");
433 } 469 }
434 470
435 function sortByName(a, b) { 471 function sortByName(a, b) {
436 if (a.name < b.name) { 472 if (a.name < b.name) {
437 return -1; 473 return -1;
438 } 474 }
439 if (a.name > b.name) { 475 if (a.name > b.name) {
440 return 1; 476 return 1;
441 } 477 }
442 return 0; 478 return 0;
443 } 479 }
OLDNEW
« no previous file with comments | « chrome/common/extensions/docs/images/sample-default-icon.png ('k') | chrome/common/extensions/docs/js/sample_search.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698