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

Side by Side Diff: lib/dartdoc/dartdoc.dart

Issue 10201012: add appcache generation to apidocs (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: use a specific analytics num Created 8 years, 7 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 | « no previous file | utils/apidoc/apidoc.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /** 5 /**
6 * To generate docs for a library, run this script with the path to an 6 * To generate docs for a library, run this script with the path to an
7 * entrypoint .dart file, like: 7 * entrypoint .dart file, like:
8 * 8 *
9 * $ dart dartdoc.dart foo.dart 9 * $ dart dartdoc.dart foo.dart
10 * 10 *
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 /** 51 /**
52 * Run this from the `lib/dartdoc` directory. 52 * Run this from the `lib/dartdoc` directory.
53 */ 53 */
54 void main() { 54 void main() {
55 final args = new Options().arguments; 55 final args = new Options().arguments;
56 56
57 // Parse the dartdoc options. 57 // Parse the dartdoc options.
58 bool includeSource; 58 bool includeSource;
59 int mode; 59 int mode;
60 String outputDir; 60 String outputDir;
61 bool generateAppCache;
61 62
62 for (int i = 0; i < args.length - 1; i++) { 63 for (int i = 0; i < args.length - 1; i++) {
63 final arg = args[i]; 64 final arg = args[i];
64 65
65 switch (arg) { 66 switch (arg) {
66 case '--no-code': 67 case '--no-code':
67 includeSource = false; 68 includeSource = false;
68 break; 69 break;
69 70
70 case '--mode=static': 71 case '--mode=static':
71 mode = MODE_STATIC; 72 mode = MODE_STATIC;
72 break; 73 break;
73 74
74 case '--mode=live-nav': 75 case '--mode=live-nav':
75 mode = MODE_LIVE_NAV; 76 mode = MODE_LIVE_NAV;
76 break; 77 break;
77 78
79 case '--generate-app-cache':
80 case '--generate-app-cache=true':
81 generateAppCache = true;
82 break;
83
78 default: 84 default:
79 if (arg.startsWith('--out=')) { 85 if (arg.startsWith('--out=')) {
80 outputDir = arg.substring('--out='.length); 86 outputDir = arg.substring('--out='.length);
81 } else { 87 } else {
82 print('Unknown option: $arg'); 88 print('Unknown option: $arg');
83 return; 89 return;
84 } 90 }
85 break; 91 break;
86 } 92 }
87 } 93 }
(...skipping 11 matching lines...) Expand all
99 final compilerPath = joinPaths(frogPath, 'minfrog'); 105 final compilerPath = joinPaths(frogPath, 'minfrog');
100 106
101 parseOptions(frogPath, ['', '', '--libdir=$libDir'], files); 107 parseOptions(frogPath, ['', '', '--libdir=$libDir'], files);
102 initializeWorld(files); 108 initializeWorld(files);
103 109
104 final dartdoc = new Dartdoc(); 110 final dartdoc = new Dartdoc();
105 111
106 if (includeSource != null) dartdoc.includeSource = includeSource; 112 if (includeSource != null) dartdoc.includeSource = includeSource;
107 if (mode != null) dartdoc.mode = mode; 113 if (mode != null) dartdoc.mode = mode;
108 if (outputDir != null) dartdoc.outputDir = outputDir; 114 if (outputDir != null) dartdoc.outputDir = outputDir;
115 if (generateAppCache != null) dartdoc.generateAppCache = generateAppCache;
109 116
110 cleanOutputDirectory(dartdoc.outputDir); 117 cleanOutputDirectory(dartdoc.outputDir);
111 118
112 // Compile the client-side code to JS. 119 // Compile the client-side code to JS.
113 final clientScript = (dartdoc.mode == MODE_STATIC) ? 'static' : 'live-nav'; 120 final clientScript = (dartdoc.mode == MODE_STATIC) ? 'static' : 'live-nav';
114 compileScript(compilerPath, libDir, '$scriptDir/client-$clientScript.dart', 121 final Future scriptCompiled = compileScript(compilerPath, libDir,
115 '${dartdoc.outputDir}/client-$clientScript.js'); 122 '$scriptDir/client-$clientScript.dart',
123 '${dartdoc.outputDir}/client-$clientScript.js');
116 124
117 copyFiles('$scriptDir/static', dartdoc.outputDir); 125 final Future filesCopied = copyFiles('$scriptDir/static', dartdoc.outputDir);
118 126
119 dartdoc.document(entrypoint); 127 Futures.wait([scriptCompiled, filesCopied]).then((_) {
128 dartdoc.document(entrypoint);
129 });
120 130
121 print('Documented ${dartdoc._totalLibraries} libraries, ' + 131 print('Documented ${dartdoc._totalLibraries} libraries, ' +
122 '${dartdoc._totalTypes} types, and ' + 132 '${dartdoc._totalTypes} types, and ' +
123 '${dartdoc._totalMembers} members.'); 133 '${dartdoc._totalMembers} members.');
124 } 134 }
125 135
126 /** 136 /**
127 * Gets the full path to the directory containing the entrypoint of the current 137 * Gets the full path to the directory containing the entrypoint of the current
128 * script. In other words, if you invoked dartdoc, directly, it will be the 138 * script. In other words, if you invoked dartdoc, directly, it will be the
129 * path to the directory containing `dartdoc.dart`. If you're running a script 139 * path to the directory containing `dartdoc.dart`. If you're running a script
(...skipping 15 matching lines...) Expand all
145 outputDir.createSync(); 155 outputDir.createSync();
146 } 156 }
147 157
148 /** 158 /**
149 * Copies all of the files in the directory [from] to [to]. Does *not* 159 * Copies all of the files in the directory [from] to [to]. Does *not*
150 * recursively copy subdirectories. 160 * recursively copy subdirectories.
151 * 161 *
152 * Note: runs asynchronously, so you won't see any files copied until after the 162 * Note: runs asynchronously, so you won't see any files copied until after the
153 * event loop has had a chance to pump (i.e. after `main()` has returned). 163 * event loop has had a chance to pump (i.e. after `main()` has returned).
154 */ 164 */
155 void copyFiles(String from, String to) { 165 Future copyFiles(String from, String to) {
166 final completer = new Completer();
156 final fromDir = new Directory(from); 167 final fromDir = new Directory(from);
157 fromDir.onFile = (path) { 168 fromDir.onFile = (path) {
158 final name = basename(path); 169 final name = basename(path);
159 // TODO(rnystrom): Hackish. Ignore 'hidden' files like .DS_Store. 170 // TODO(rnystrom): Hackish. Ignore 'hidden' files like .DS_Store.
160 if (name.startsWith('.')) return; 171 if (name.startsWith('.')) return;
161 172
162 new File(path).readAsBytes((bytes) { 173 new File(path).readAsBytes((bytes) {
163 final outFile = new File('$to/$name'); 174 final outFile = new File('$to/$name');
164 final stream = outFile.openOutputStream(FileMode.WRITE); 175 final stream = outFile.openOutputStream(FileMode.WRITE);
165 stream.write(bytes, copyBuffer: false); 176 stream.write(bytes, copyBuffer: false);
166 stream.close(); 177 stream.close();
167 }); 178 });
168 }; 179 };
180 fromDir.onDone = (done) => completer.complete(true);
169 fromDir.list(recursive: false); 181 fromDir.list(recursive: false);
182 return completer.future;
170 } 183 }
171 184
172 /** 185 /**
173 * Compiles the given Dart script to a JavaScript file at [jsPath] using the 186 * Compiles the given Dart script to a JavaScript file at [jsPath] using the
174 * Dart-to-JS compiler located at [compilerPath]. 187 * Dart-to-JS compiler located at [compilerPath].
175 */ 188 */
176 void compileScript(String compilerPath, String libDir, 189 Future compileScript(String compilerPath, String libDir,
177 String dartPath, String jsPath) { 190 String dartPath, String jsPath) {
191 final completer = new Completer();
178 onExit(int exitCode, String stdout, String stderr) { 192 onExit(int exitCode, String stdout, String stderr) {
179 if (exitCode != 0) { 193 if (exitCode != 0) {
180 final message = 'Non-zero exit code from $compilerPath'; 194 final message = 'Non-zero exit code from $compilerPath';
181 print('$message.'); 195 print('$message.');
182 print(stdout); 196 print(stdout);
183 print(stderr); 197 print(stderr);
184 throw message; 198 throw message;
185 } 199 }
200 completer.complete(true);
186 } 201 }
187 202
188 onError(error) { 203 onError(error) {
189 final message = 'Error trying to execute $compilerPath. Error: $error'; 204 final message = 'Error trying to execute $compilerPath. Error: $error';
190 print('$message.'); 205 print('$message.');
191 throw message; 206 throw message;
192 } 207 }
193 208
194 print('Compiling $dartPath to $jsPath'); 209 print('Compiling $dartPath to $jsPath');
195 new Process.run(compilerPath, [ 210 new Process.run(compilerPath, [
196 '--libdir=$libDir', '--out=$jsPath', 211 '--libdir=$libDir', '--out=$jsPath',
197 '--compile-only', '--enable-type-checks', '--warnings-as-errors', 212 '--compile-only', '--enable-type-checks', '--warnings-as-errors',
198 dartPath], null, onExit).onError = onError; 213 dartPath], null, onExit).onError = onError;
214 return completer.future;
199 } 215 }
200 216
201 class Dartdoc { 217 class Dartdoc {
202 218
203 /** Set to `false` to not include the source code in the generated docs. */ 219 /** Set to `false` to not include the source code in the generated docs. */
204 bool includeSource = true; 220 bool includeSource = true;
205 221
206 /** 222 /**
207 * Dartdoc can generate docs in a few different ways based on how dynamic you 223 * Dartdoc can generate docs in a few different ways based on how dynamic you
208 * want the client-side behavior to be. The value for this should be one of 224 * want the client-side behavior to be. The value for this should be one of
209 * the `MODE_` constants. 225 * the `MODE_` constants.
210 */ 226 */
211 int mode = MODE_LIVE_NAV; 227 int mode = MODE_LIVE_NAV;
212 228
229 /**
230 * Generates the App Cache manifest file, enabling offline doc viewing.
231 */
232 bool generateAppCache = false;
233
213 /** Path to generate HTML files into. */ 234 /** Path to generate HTML files into. */
214 String outputDir = 'docs'; 235 String outputDir = 'docs';
215 236
216 /** 237 /**
217 * The title used for the overall generated output. Set this to change it. 238 * The title used for the overall generated output. Set this to change it.
218 */ 239 */
219 String mainTitle = 'Dart Documentation'; 240 String mainTitle = 'Dart Documentation';
220 241
221 /** 242 /**
222 * The URL that the Dart logo links to. Defaults "index.html", the main 243 * The URL that the Dart logo links to. Defaults "index.html", the main
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 return a.name.toUpperCase().compareTo(b.name.toUpperCase()); 321 return a.name.toUpperCase().compareTo(b.name.toUpperCase());
301 }); 322 });
302 323
303 // Generate the docs. 324 // Generate the docs.
304 if (mode == MODE_LIVE_NAV) docNavigationJson(); 325 if (mode == MODE_LIVE_NAV) docNavigationJson();
305 326
306 docIndex(); 327 docIndex();
307 for (final library in _sortedLibraries) { 328 for (final library in _sortedLibraries) {
308 docLibrary(library); 329 docLibrary(library);
309 } 330 }
331
332 if (generateAppCache) {
333 generateAppCacheManifest();
334 }
310 } finally { 335 } finally {
311 options.dietParse = oldDietParse; 336 options.dietParse = oldDietParse;
312 } 337 }
313 } 338 }
314 339
315 void startFile(String path) { 340 void startFile(String path) {
316 _filePath = path; 341 _filePath = path;
317 _file = new StringBuffer(); 342 _file = new StringBuffer();
318 } 343 }
319 344
(...skipping 23 matching lines...) Expand all
343 * breadcrumbs are an interleaved list of links and titles. If a link is null, 368 * breadcrumbs are an interleaved list of links and titles. If a link is null,
344 * then no link will be generated. For example, given: 369 * then no link will be generated. For example, given:
345 * 370 *
346 * ['foo', 'foo.html', 'bar', null] 371 * ['foo', 'foo.html', 'bar', null]
347 * 372 *
348 * It will output: 373 * It will output:
349 * 374 *
350 * <a href="foo.html">foo</a> &rsaquo; bar 375 * <a href="foo.html">foo</a> &rsaquo; bar
351 */ 376 */
352 void writeHeader(String title, List<String> breadcrumbs) { 377 void writeHeader(String title, List<String> breadcrumbs) {
378 final htmlAttributes = generateAppCache ?
379 'manifest="/appcache.manifest"' : '';
380
353 write( 381 write(
354 ''' 382 '''
355 <!DOCTYPE html> 383 <!DOCTYPE html>
356 <html> 384 <html${htmlAttributes == '' ? '' : ' $htmlAttributes'}>
357 <head> 385 <head>
358 '''); 386 ''');
359 writeHeadContents(title); 387 writeHeadContents(title);
360 388
361 // Add data attributes describing what the page documents. 389 // Add data attributes describing what the page documents.
362 var data = ''; 390 var data = '';
363 if (_currentLibrary != null) { 391 if (_currentLibrary != null) {
364 data += ' data-library="${md.escapeHtml(_currentLibrary.name)}"'; 392 data += ' data-library="${md.escapeHtml(_currentLibrary.name)}"';
365 } 393 }
366 394
(...skipping 922 matching lines...) Expand 10 before | Expand all | Expand 10 after
1289 // * Type parameters of the enclosing type. 1317 // * Type parameters of the enclosing type.
1290 1318
1291 return new md.Element.text('code', name); 1319 return new md.Element.text('code', name);
1292 } 1320 }
1293 1321
1294 // TODO(rnystrom): Move into SourceSpan? 1322 // TODO(rnystrom): Move into SourceSpan?
1295 int getSpanColumn(SourceSpan span) { 1323 int getSpanColumn(SourceSpan span) {
1296 final line = span.file.getLine(span.start); 1324 final line = span.file.getLine(span.start);
1297 return span.file.getColumn(line, span.start); 1325 return span.file.getColumn(line, span.start);
1298 } 1326 }
1327
1328 generateAppCacheManifest() {
1329 print('Generating app cache manifest from output $outputDir');
1330 startFile('appcache.manifest');
1331 write("CACHE MANIFEST\n\n");
1332 write("# VERSION: ${new Date.now()}\n\n");
1333 write("NETWORK:\n*\n\n");
1334 write("CACHE:\n");
1335 var toCache = new Directory(outputDir);
1336 var pathPrefix = new File(outputDir).fullPathSync();
1337 var pathPrefixLength = pathPrefix.length;
1338 toCache.onFile = (filename) {
1339 if (filename.endsWith('appcache.manifest')) {
1340 return;
1341 }
1342 var relativePath = filename.substring(pathPrefixLength + 1);
1343 write("$relativePath\n");
1344 };
1345 toCache.onDone = (done) => endFile();
1346 toCache.list(recursive: true);
1347 }
1299 } 1348 }
OLDNEW
« no previous file with comments | « no previous file | utils/apidoc/apidoc.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698