OLD | NEW |
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. |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 | 46 |
47 /* | 47 /* |
48 * Main entry point for composing the page. It will fetch it's template, | 48 * Main entry point for composing the page. It will fetch it's template, |
49 * the extension api, and attempt to fetch the matching static content. | 49 * the extension api, and attempt to fetch the matching static content. |
50 * It will insert the static content, if any, prepare it's pageData then | 50 * It will insert the static content, if any, prepare it's pageData then |
51 * render the template from |pageData|. | 51 * render the template from |pageData|. |
52 */ | 52 */ |
53 function renderPage() { | 53 function renderPage() { |
54 var pathParts = document.location.href.split(/\/|\./); | 54 var pathParts = document.location.href.split(/\/|\./); |
55 pageName = pathParts[pathParts.length - 2]; | 55 pageName = pathParts[pathParts.length - 2]; |
56 | 56 if (!pageName) { |
| 57 alert("Empty page name for: " + document.location.href); |
| 58 return; |
| 59 } |
| 60 |
57 // Fetch the api template and insert into the <body>. | 61 // Fetch the api template and insert into the <body>. |
58 fetchContent(API_TEMPLATE, function(templateContent) { | 62 fetchContent(API_TEMPLATE, function(templateContent) { |
59 document.getElementsByTagName("body")[0].innerHTML = templateContent; | 63 document.getElementsByTagName("body")[0].innerHTML = templateContent; |
60 fetchStatic(); | 64 fetchStatic(); |
61 }, function(error) { | 65 }, function(error) { |
62 alert("Failed to load " + API_TEMPLATE + ". " + error); | 66 alert("Failed to load " + API_TEMPLATE + ". " + error); |
63 }); | 67 }); |
64 } | 68 } |
65 | 69 |
66 function fetchStatic() { | 70 function fetchStatic() { |
67 // Fetch the static content and insert into the "static" <div>. | 71 // Fetch the static content and insert into the "static" <div>. |
68 fetchContent(staticResource(pageName), function(overviewContent) { | 72 fetchContent(staticResource(pageName), function(overviewContent) { |
69 document.getElementById("static").innerHTML = overviewContent; | 73 document.getElementById("static").innerHTML = overviewContent; |
70 fetchSchema(); | 74 fetchSchema(); |
71 | 75 |
72 }, function(error) { | 76 }, function(error) { |
73 // Not fatal. Some api pages may not have matching static content. | 77 // Not fatal. Some api pages may not have matching static content. |
74 fetchSchema(); | 78 fetchSchema(); |
75 }); | 79 }); |
76 } | 80 } |
77 | 81 |
78 function fetchSchema() { | 82 function fetchSchema() { |
79 // Now the page is composed with the authored content, we fetch the schema | 83 // Now the page is composed with the authored content, we fetch the schema |
80 // and populate the templates. | 84 // and populate the templates. |
81 fetchContent(SCHEMA, renderTemplate, function(error) { | 85 fetchContent(SCHEMA, renderTemplate, function(error) { |
82 alert("Failed to load " + SCHEMA); | 86 alert("Failed to load " + SCHEMA); |
83 }); | 87 }); |
84 } | 88 } |
85 | 89 |
86 /** | 90 /** |
87 * Fetches |url| and returns it's text contents from the xhr.responseText in | 91 * Fetches |url| and returns it's text contents from the xhr.responseText in |
88 * onSuccess(content) | 92 * onSuccess(content) |
89 */ | 93 */ |
90 function fetchContent(url, onSuccess, onError) { | 94 function fetchContent(url, onSuccess, onError) { |
| 95 var localUrl = url; |
91 var xhr = new XMLHttpRequest(); | 96 var xhr = new XMLHttpRequest(); |
92 var abortTimerId = window.setTimeout(function() { | 97 var abortTimerId = window.setTimeout(function() { |
93 xhr.abort(); | 98 xhr.abort(); |
94 console.log("XHR Timed out"); | 99 console.log("XHR Timed out"); |
95 }, REQUEST_TIMEOUT); | 100 }, REQUEST_TIMEOUT); |
96 | 101 |
97 function handleError(error) { | 102 function handleError(error) { |
98 window.clearTimeout(abortTimerId); | 103 window.clearTimeout(abortTimerId); |
99 if (onError) { | 104 if (onError) { |
100 onError(error); | 105 onError(error); |
101 } | 106 } |
102 console.error("XHR Failed: " + error); | 107 console.error("XHR Failed fetching: " + localUrl + "..." + error); |
103 } | 108 } |
104 | 109 |
105 try { | 110 try { |
106 xhr.onreadystatechange = function(){ | 111 xhr.onreadystatechange = function(){ |
107 if (xhr.readyState == 4) { | 112 if (xhr.readyState == 4) { |
108 if (xhr.responseText) { | 113 if (xhr.responseText) { |
109 window.clearTimeout(abortTimerId); | 114 window.clearTimeout(abortTimerId); |
110 onSuccess(xhr.responseText); | 115 onSuccess(xhr.responseText); |
111 } else { | 116 } else { |
112 handleError("responseText empty."); | 117 handleError("responseText empty."); |
113 } | 118 } |
114 } | 119 } |
115 } | 120 } |
116 | 121 |
117 xhr.onerror = handleError; | 122 xhr.onerror = handleError; |
118 | 123 |
119 xhr.open("GET", url, true); | 124 xhr.open("GET", url, true); |
120 xhr.send(null); | 125 xhr.send(null); |
121 } catch(e) { | 126 } catch(e) { |
122 console.log("ex: " + e); | 127 console.log("ex: " + e); |
123 console.error("exception: " + e); | 128 console.error("exception: " + e); |
124 handleError(); | 129 handleError(); |
125 } | 130 } |
126 } | 131 } |
127 | 132 |
128 /** | 133 /** |
129 * Parses the content in |schemaContent| to json, find appropriate api, adds any | 134 * Parses the content in |schemaContent| to json, find appropriate api, adds any |
130 * additional required values, renders to html via JSTemplate, and unhides the | 135 * additional required values, renders to html via JSTemplate, and unhides the |
131 * <body>. | 136 * <body>. |
132 * This uses the root <html> element (the entire document) as the template. | 137 * This uses the root <html> element (the entire document) as the template. |
133 */ | 138 */ |
134 function renderTemplate(schemaContent) { | 139 function renderTemplate(schemaContent) { |
135 pageData = {}; | 140 pageData = {}; |
136 var schema = JSON.parse(schemaContent); | 141 var schema = JSON.parse(schemaContent); |
137 | 142 |
138 schema.each(function(module) { | 143 schema.each(function(module) { |
139 if (module.namespace == pageName) { | 144 if (module.namespace == pageName) { |
140 // This page is an api page. Setup types and apiDefinition. | 145 // This page is an api page. Setup types and apiDefinition. |
141 if (module.types) { | 146 if (module.types) { |
142 module.types.each(function(t) { | 147 module.types.each(function(t) { |
143 types[t.id] = t; | 148 types[t.id] = t; |
144 }); | 149 }); |
145 } | 150 } |
146 pageData.apiDefinition = module; | 151 pageData.apiDefinition = module; |
147 preprocessApi(pageData, schema); | 152 preprocessApi(pageData, schema); |
148 } | 153 } |
149 }); | 154 }); |
150 | 155 |
151 setupPageData(pageData, schema); | 156 setupPageData(pageData, schema); |
152 | 157 |
153 // Render to template | 158 // Render to template |
154 var input = new JsEvalContext(pageData); | 159 var input = new JsEvalContext(pageData); |
155 var output = document.getElementsByTagName("html")[0]; | 160 var output = document.getElementsByTagName("html")[0]; |
156 jstProcess(input, output); | 161 jstProcess(input, output); |
157 | 162 |
158 // Show. | 163 // Show. |
159 document.getElementsByTagName("body")[0].className = ""; | 164 document.getElementsByTagName("body")[0].className = ""; |
| 165 |
| 166 if (parent && parent.done) |
| 167 parent.done(); |
| 168 } |
| 169 |
| 170 function serializePage() { |
| 171 var s = new XMLSerializer(); |
| 172 return s.serializeToString(document); |
160 } | 173 } |
161 | 174 |
162 function setupPageData(pageData, schema) { | 175 function setupPageData(pageData, schema) { |
163 // Add a list of modules for the master TOC. | 176 // Add a list of modules for the master TOC. |
164 pageData.apiModules = []; | 177 pageData.apiModules = []; |
165 schema.each(function(s) { | 178 schema.each(function(s) { |
166 var m = {}; | 179 var m = {}; |
167 m.module = s.namespace; | 180 m.module = s.namespace; |
168 m.name = s.namespace.substring(0, 1).toUpperCase() + | 181 m.name = s.namespace.substring(0, 1).toUpperCase() + |
169 s.namespace.substring(1); | 182 s.namespace.substring(1); |
170 pageData.apiModules.push(m); | 183 pageData.apiModules.push(m); |
171 }); | 184 }); |
172 pageData.apiModules.sort(function(a, b) { return a.name > b.name; }); | 185 pageData.apiModules.sort(function(a, b) { return a.name > b.name; }); |
173 | 186 |
174 if (!pageData.pageTitle) { | 187 if (!pageData.pageTitle) { |
175 pageData.pageTitle = pageName; | 188 pageData.pageTitle = pageName; |
176 pageData.h1Header = pageName; | 189 pageData.h1Header = pageName; |
177 } | 190 } |
178 } | 191 } |
179 | 192 |
180 /** | 193 /** |
181 * Augment the |module| with additional values that are required by the | 194 * Augment the |module| with additional values that are required by the |
182 * template. |schema| is the full schema (including all modules). | 195 * template. |schema| is the full schema (including all modules). |
183 */ | 196 */ |
(...skipping 12 matching lines...) Expand all Loading... |
196 if (lastParam.type == "function" && lastParam.parameters) { | 209 if (lastParam.type == "function" && lastParam.parameters) { |
197 linkTypeReferences(lastParam.parameters); | 210 linkTypeReferences(lastParam.parameters); |
198 assignTypeNames(lastParam.parameters); | 211 assignTypeNames(lastParam.parameters); |
199 f.callbackParameters = lastParam.parameters; | 212 f.callbackParameters = lastParam.parameters; |
200 f.callbackSignature = generateSignatureString(lastParam.parameters); | 213 f.callbackSignature = generateSignatureString(lastParam.parameters); |
201 f.callbackParameters.each(function(p) { | 214 f.callbackParameters.each(function(p) { |
202 addPropertyListIfObject(p); | 215 addPropertyListIfObject(p); |
203 }); | 216 }); |
204 } | 217 } |
205 } | 218 } |
206 | 219 |
207 // Setup any type: "object" pameters to have an array of params (rather than
| 220 // Setup any type: "object" pameters to have an array of params (rather than
|
208 // named properties). | 221 // named properties). |
209 f.parameters.each(function(param) { | 222 f.parameters.each(function(param) { |
210 addPropertyListIfObject(param); | 223 addPropertyListIfObject(param); |
211 }); | 224 }); |
212 | 225 |
213 // Setup return typeName & _propertyList, if any. | 226 // Setup return typeName & _propertyList, if any. |
214 if (f.returns) { | 227 if (f.returns) { |
215 linkTypeReference(f.returns); | 228 linkTypeReference(f.returns); |
216 f.returns.typeName = typeName(f.returns); | 229 f.returns.typeName = typeName(f.returns); |
217 addPropertyListIfObject(f.returns); | 230 addPropertyListIfObject(f.returns); |
218 } | 231 } |
219 }); | 232 }); |
220 | 233 |
221 module.events.each(function(e) { | 234 module.events.each(function(e) { |
222 linkTypeReferences(e.parameters); | 235 linkTypeReferences(e.parameters); |
223 assignTypeNames(e.parameters); | 236 assignTypeNames(e.parameters); |
224 e.callSignature = generateSignatureString(e.parameters); | 237 e.callSignature = generateSignatureString(e.parameters); |
225 e.parameters.each(function(p) { | 238 e.parameters.each(function(p) { |
226 addPropertyListIfObject(p); | 239 addPropertyListIfObject(p); |
227 }); | 240 }); |
228 }); | 241 }); |
229 } | 242 } |
230 | 243 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 p.typeName = typeName(p); | 280 p.typeName = typeName(p); |
268 }); | 281 }); |
269 } | 282 } |
270 | 283 |
271 /** | 284 /** |
272 * Generates a short text summary of the |schema| type | 285 * Generates a short text summary of the |schema| type |
273 */ | 286 */ |
274 function typeName(schema) { | 287 function typeName(schema) { |
275 if (schema.$ref) | 288 if (schema.$ref) |
276 schema = types[schema.$ref]; | 289 schema = types[schema.$ref]; |
277 | 290 |
278 if (schema.choice) { | 291 if (schema.choice) { |
279 var typeNames = []; | 292 var typeNames = []; |
280 schema.choice.each(function(c) { | 293 schema.choice.each(function(c) { |
281 typeNames.push(typeName(c)); | 294 typeNames.push(typeName(c)); |
282 }); | 295 }); |
283 | 296 |
284 return typeNames.join(" or "); | 297 return typeNames.join(" or "); |
285 } | 298 } |
286 | 299 |
287 if (schema.type == "array") | 300 if (schema.type == "array") |
288 return "array of " + typeName(schema.items); | 301 return "array of " + typeName(schema.items); |
289 | 302 |
290 return schema.type; | 303 return schema.type; |
291 } | 304 } |
292 | 305 |
293 /** | 306 /** |
294 * Generates a simple string representation of the signature of a function | 307 * Generates a simple string representation of the signature of a function |
295 * whose |parameters| are json schemas. | 308 * whose |parameters| are json schemas. |
296 */ | 309 */ |
297 function generateSignatureString(parameters) { | 310 function generateSignatureString(parameters) { |
298 var retval = []; | 311 var retval = []; |
299 parameters.each(function(param, i) { | 312 parameters.each(function(param, i) { |
300 retval.push(param.typeName + " " + param.name); | 313 retval.push(param.typeName + " " + param.name); |
301 }); | 314 }); |
302 | 315 |
303 return retval.join(", "); | 316 return retval.join(", "); |
304 } | 317 } |
OLD | NEW |