| OLD | NEW |
| 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 * |
| 11 * This will create a "docs" directory with the docs for your libraries. To | 11 * This will create a "docs" directory with the docs for your libraries. To |
| 12 * create these beautiful docs, dartdoc parses your library and every library | 12 * create these beautiful docs, dartdoc parses your library and every library |
| 13 * it imports (recursively). From each library, it parses all classes and | 13 * it imports (recursively). From each library, it parses all classes and |
| 14 * members, finds the associated doc comments and builds crosslinked docs from | 14 * members, finds the associated doc comments and builds crosslinked docs from |
| 15 * them. | 15 * them. |
| 16 */ | 16 */ |
| 17 #library('dartdoc'); | 17 #library('dartdoc'); |
| 18 | 18 |
| 19 #import('dart:io'); | 19 #import('dart:io'); |
| 20 #import('dart:math'); | 20 #import('dart:math'); |
| 21 #import('dart:uri'); | 21 #import('dart:uri'); |
| 22 #import('dart:json'); | 22 #import('dart:json'); |
| 23 #import('mirrors/mirrors.dart'); | 23 |
| 24 #import('mirrors/mirrors_util.dart'); | 24 // TODO(rnystrom): Use "package:" URL (#4968). |
| 25 #import('mirrors/dart2js_mirror.dart', prefix: 'dart2js'); | 25 #import('mirrors.dart'); |
| 26 #import('mirrors_util.dart'); |
| 27 #import('src/mirrors/dart2js_mirror.dart', prefix: 'dart2js'); |
| 26 #import('classify.dart'); | 28 #import('classify.dart'); |
| 27 #import('markdown.dart', prefix: 'md'); | 29 #import('markdown.dart', prefix: 'md'); |
| 28 #import('../../lib/compiler/implementation/scanner/scannerlib.dart', | 30 #import('../../../lib/compiler/implementation/scanner/scannerlib.dart', |
| 29 prefix: 'dart2js'); | 31 prefix: 'dart2js'); |
| 30 #import('../../lib/_internal/libraries.dart'); | 32 #import('../../../lib/_internal/libraries.dart'); |
| 31 | 33 |
| 32 #source('comment_map.dart'); | 34 // TODO(rnystrom): Use "package:" URL (#4968). |
| 33 #source('nav.dart'); | 35 #source('src/dartdoc/comment_map.dart'); |
| 34 #source('utils.dart'); | 36 #source('src/dartdoc/nav.dart'); |
| 35 | 37 #source('src/dartdoc/utils.dart'); |
| 36 // TODO(johnniwinther): Note that [IN_SDK] gets initialized to true when this | |
| 37 // file is modified by the SDK deployment script. If you change, be sure to test | |
| 38 // that dartdoc still works when run from the built SDK directory. | |
| 39 const bool IN_SDK = false; | |
| 40 | 38 |
| 41 /** | 39 /** |
| 42 * Generates completely static HTML containing everything you need to browse | 40 * Generates completely static HTML containing everything you need to browse |
| 43 * the docs. The only client side behavior is trivial stuff like syntax | 41 * the docs. The only client side behavior is trivial stuff like syntax |
| 44 * highlighting code. | 42 * highlighting code. |
| 45 */ | 43 */ |
| 46 const MODE_STATIC = 0; | 44 const MODE_STATIC = 0; |
| 47 | 45 |
| 48 /** | 46 /** |
| 49 * Generated docs do not include baked HTML navigation. Instead, a single | 47 * Generated docs do not include baked HTML navigation. Instead, a single |
| 50 * `nav.json` file is created and the appropriate navigation is generated | 48 * `nav.json` file is created and the appropriate navigation is generated |
| 51 * client-side by parsing that and building HTML. | 49 * client-side by parsing that and building HTML. |
| 52 * | 50 * |
| 53 * This dramatically reduces the generated size of the HTML since a large | 51 * This dramatically reduces the generated size of the HTML since a large |
| 54 * fraction of each static page is just redundant navigation links. | 52 * fraction of each static page is just redundant navigation links. |
| 55 * | 53 * |
| 56 * In this mode, the browser will do a XHR for nav.json which means that to | 54 * In this mode, the browser will do a XHR for nav.json which means that to |
| 57 * preview docs locally, you will need to enable requesting file:// links in | 55 * preview docs locally, you will need to enable requesting file:// links in |
| 58 * your browser or run a little local server like `python -m SimpleHTTPServer`. | 56 * your browser or run a little local server like `python -m SimpleHTTPServer`. |
| 59 */ | 57 */ |
| 60 const MODE_LIVE_NAV = 1; | 58 const MODE_LIVE_NAV = 1; |
| 61 | 59 |
| 62 const API_LOCATION = 'http://api.dartlang.org/'; | 60 const API_LOCATION = 'http://api.dartlang.org/'; |
| 63 | 61 |
| 64 /** | 62 /** |
| 65 * Run this from the `pkg/dartdoc` directory. | |
| 66 */ | |
| 67 void main() { | |
| 68 final args = new Options().arguments; | |
| 69 | |
| 70 final dartdoc = new Dartdoc(); | |
| 71 | |
| 72 if (args.isEmpty()) { | |
| 73 print('No arguments provided.'); | |
| 74 printUsage(); | |
| 75 return; | |
| 76 } | |
| 77 | |
| 78 final entrypoints = <Path>[]; | |
| 79 | |
| 80 var i = 0; | |
| 81 while (i < args.length) { | |
| 82 final arg = args[i]; | |
| 83 if (!arg.startsWith('--')) { | |
| 84 // The remaining arguments must be entry points. | |
| 85 break; | |
| 86 } | |
| 87 | |
| 88 switch (arg) { | |
| 89 case '--no-code': | |
| 90 dartdoc.includeSource = false; | |
| 91 break; | |
| 92 | |
| 93 case '--mode=static': | |
| 94 dartdoc.mode = MODE_STATIC; | |
| 95 break; | |
| 96 | |
| 97 case '--mode=live-nav': | |
| 98 dartdoc.mode = MODE_LIVE_NAV; | |
| 99 break; | |
| 100 | |
| 101 case '--generate-app-cache': | |
| 102 case '--generate-app-cache=true': | |
| 103 dartdoc.generateAppCache = true; | |
| 104 break; | |
| 105 | |
| 106 case '--omit-generation-time': | |
| 107 dartdoc.omitGenerationTime = true; | |
| 108 break; | |
| 109 case '--verbose': | |
| 110 dartdoc.verbose = true; | |
| 111 break; | |
| 112 case '--include-api': | |
| 113 dartdoc.includeApi = true; | |
| 114 break; | |
| 115 case '--link-api': | |
| 116 dartdoc.linkToApi = true; | |
| 117 break; | |
| 118 | |
| 119 default: | |
| 120 if (arg.startsWith('--out=')) { | |
| 121 dartdoc.outputDir = | |
| 122 new Path.fromNative(arg.substring('--out='.length)); | |
| 123 } else if (arg.startsWith('--include-lib=')) { | |
| 124 dartdoc.includedLibraries = | |
| 125 arg.substring('--include-lib='.length).split(','); | |
| 126 } else if (arg.startsWith('--exclude-lib=')) { | |
| 127 dartdoc.excludedLibraries = | |
| 128 arg.substring('--exclude-lib='.length).split(','); | |
| 129 } else { | |
| 130 print('Unknown option: $arg'); | |
| 131 printUsage(); | |
| 132 return; | |
| 133 } | |
| 134 break; | |
| 135 } | |
| 136 i++; | |
| 137 } | |
| 138 while (i < args.length) { | |
| 139 final arg = args[i]; | |
| 140 entrypoints.add(new Path.fromNative(arg)); | |
| 141 i++; | |
| 142 } | |
| 143 | |
| 144 if (entrypoints.isEmpty()) { | |
| 145 print('No entrypoints provided.'); | |
| 146 printUsage(); | |
| 147 return; | |
| 148 } | |
| 149 | |
| 150 cleanOutputDirectory(dartdoc.outputDir); | |
| 151 | |
| 152 dartdoc.documentLibraries(entrypoints, libPath); | |
| 153 | |
| 154 // Compile the client-side code to JS. | |
| 155 final clientScript = (dartdoc.mode == MODE_STATIC) ? 'static' : 'live-nav'; | |
| 156 Future compiled = compileScript( | |
| 157 scriptDir.append('client-$clientScript.dart'), | |
| 158 dartdoc.outputDir.append('client-$clientScript.js')); | |
| 159 | |
| 160 Future filesCopied = copyDirectory(scriptDir.append('static'), | |
| 161 dartdoc.outputDir); | |
| 162 | |
| 163 Futures.wait([compiled, filesCopied]).then((_) { | |
| 164 dartdoc.cleanup(); | |
| 165 print('Documented ${dartdoc._totalLibraries} libraries, ' | |
| 166 '${dartdoc._totalTypes} types, and ' | |
| 167 '${dartdoc._totalMembers} members.'); | |
| 168 }); | |
| 169 } | |
| 170 | |
| 171 void printUsage() { | |
| 172 print(''' | |
| 173 Usage dartdoc [options] <entrypoint(s)> | |
| 174 [options] include | |
| 175 --no-code Do not include source code in the documentation. | |
| 176 | |
| 177 --mode=static Generates completely static HTML containing | |
| 178 everything you need to browse the docs. The only | |
| 179 client side behavior is trivial stuff like syntax | |
| 180 highlighting code. | |
| 181 | |
| 182 --mode=live-nav (default) Generated docs do not include baked HTML | |
| 183 navigation. Instead, a single `nav.json` file is | |
| 184 created and the appropriate navigation is generated | |
| 185 client-side by parsing that and building HTML. | |
| 186 This dramatically reduces the generated size of | |
| 187 the HTML since a large fraction of each static page | |
| 188 is just redundant navigation links. | |
| 189 In this mode, the browser will do a XHR for | |
| 190 nav.json which means that to preview docs locally, | |
| 191 you will need to enable requesting file:// links in | |
| 192 your browser or run a little local server like | |
| 193 `python -m SimpleHTTPServer`. | |
| 194 | |
| 195 --generate-app-cache Generates the App Cache manifest file, enabling | |
| 196 offline doc viewing. | |
| 197 | |
| 198 --out=<dir> Generates files into directory <dir>. If omitted | |
| 199 the files are generated into ./docs/ | |
| 200 | |
| 201 --link-api Link to the online language API in the generated | |
| 202 documentation. The option overrides inclusion | |
| 203 through --include-api or --include-lib. | |
| 204 | |
| 205 --include-api Include the used API libraries in the generated | |
| 206 documentation. If the --link-api option is used, | |
| 207 this option is ignored. | |
| 208 | |
| 209 --include-lib=<libs> Use this option to explicitly specify which | |
| 210 libraries to include in the documentation. If | |
| 211 omitted, all used libraries are included by | |
| 212 default. <libs> is comma-separated list of library | |
| 213 names. | |
| 214 | |
| 215 --exclude-lib=<libs> Use this option to explicitly specify which | |
| 216 libraries to exclude from the documentation. If | |
| 217 omitted, no libraries are excluded. <libs> is | |
| 218 comma-separated list of library names. | |
| 219 | |
| 220 --verbose Print verbose information during generation. | |
| 221 '''); | |
| 222 } | |
| 223 | |
| 224 /** | |
| 225 * Gets the full path to the directory containing the entrypoint of the current | 63 * Gets the full path to the directory containing the entrypoint of the current |
| 226 * script. In other words, if you invoked dartdoc, directly, it will be the | 64 * script. In other words, if you invoked dartdoc, directly, it will be the |
| 227 * path to the directory containing `dartdoc.dart`. If you're running a script | 65 * path to the directory containing `dartdoc.dart`. If you're running a script |
| 228 * that imports dartdoc, it will be the path to that script. | 66 * that imports dartdoc, it will be the path to that script. |
| 229 */ | 67 */ |
| 230 // TODO(johnniwinther): Convert to final (lazily initialized) variables when | 68 // TODO(johnniwinther): Convert to final (lazily initialized) variables when |
| 231 // the feature is supported. | 69 // the feature is supported. |
| 232 Path get scriptDir => | 70 Path get scriptDir => |
| 233 new Path.fromNative(new Options().script).directoryPath; | 71 new Path.fromNative(new Options().script).directoryPath; |
| 234 | 72 |
| 235 // TODO(johnniwinther): Trailing slashes matter due to the use of [libPath] as | |
| 236 // a base URI with [Uri.resolve]. | |
| 237 /// Relative path to the library in which dart2js resides. | |
| 238 Path get libPath => IN_SDK | |
| 239 ? scriptDir.append('../../lib/dart2js/') | |
| 240 : scriptDir.append('../../'); | |
| 241 | |
| 242 /** | 73 /** |
| 243 * Deletes and recreates the output directory at [path] if it exists. | 74 * Deletes and recreates the output directory at [path] if it exists. |
| 244 */ | 75 */ |
| 245 void cleanOutputDirectory(Path path) { | 76 void cleanOutputDirectory(Path path) { |
| 246 final outputDir = new Directory.fromPath(path); | 77 final outputDir = new Directory.fromPath(path); |
| 247 if (outputDir.existsSync()) { | 78 if (outputDir.existsSync()) { |
| 248 outputDir.deleteRecursivelySync(); | 79 outputDir.deleteRecursivelySync(); |
| 249 } | 80 } |
| 250 | 81 |
| 251 try { | 82 try { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 277 | 108 |
| 278 File fromFile = new File(path); | 109 File fromFile = new File(path); |
| 279 File toFile = new File.fromPath(to.append(name)); | 110 File toFile = new File.fromPath(to.append(name)); |
| 280 fromFile.openInputStream().pipe(toFile.openOutputStream()); | 111 fromFile.openInputStream().pipe(toFile.openOutputStream()); |
| 281 }; | 112 }; |
| 282 lister.onDone = (done) => completer.complete(true); | 113 lister.onDone = (done) => completer.complete(true); |
| 283 return completer.future; | 114 return completer.future; |
| 284 } | 115 } |
| 285 | 116 |
| 286 /** | 117 /** |
| 287 * Compiles the given Dart script to a JavaScript file at [jsPath] using the | 118 * Compiles the dartdoc client-side code to JavaScript using Dart2js. |
| 288 * Dart2js compiler. | |
| 289 */ | 119 */ |
| 290 Future<bool> compileScript(Path dartPath, Path jsPath) { | 120 Future<bool> compileScript(int mode, Path outputDir, Path libPath) { |
| 121 var clientScript = (mode == MODE_STATIC) ? 'static' : 'live-nav'; |
| 122 var dartPath = libPath.append( |
| 123 'pkg/dartdoc/lib/src/client/client-$clientScript.dart'); |
| 124 var jsPath = outputDir.append('client-$clientScript.js'); |
| 125 |
| 291 var completer = new Completer<bool>(); | 126 var completer = new Completer<bool>(); |
| 292 var compilation = new Compilation(dartPath, libPath); | 127 var compilation = new Compilation(dartPath, libPath); |
| 293 Future<String> result = compilation.compileToJavaScript(); | 128 Future<String> result = compilation.compileToJavaScript(); |
| 294 result.then((jsCode) { | 129 result.then((jsCode) { |
| 295 writeString(new File.fromPath(jsPath), jsCode); | 130 writeString(new File.fromPath(jsPath), jsCode); |
| 296 completer.complete(true); | 131 completer.complete(true); |
| 297 }); | 132 }); |
| 298 result.handleException((e) => completer.completeException(e)); | 133 result.handleException((e) => completer.completeException(e)); |
| 299 return completer.future; | 134 return completer.future; |
| 300 } | 135 } |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 /** The path to the file currently being written to, relative to [outdir]. */ | 220 /** The path to the file currently being written to, relative to [outdir]. */ |
| 386 Path _filePath; | 221 Path _filePath; |
| 387 | 222 |
| 388 /** The file currently being written to. */ | 223 /** The file currently being written to. */ |
| 389 StringBuffer _file; | 224 StringBuffer _file; |
| 390 | 225 |
| 391 int _totalLibraries = 0; | 226 int _totalLibraries = 0; |
| 392 int _totalTypes = 0; | 227 int _totalTypes = 0; |
| 393 int _totalMembers = 0; | 228 int _totalMembers = 0; |
| 394 | 229 |
| 230 int get totalLibraries => _totalLibraries; |
| 231 int get totalTypes => _totalTypes; |
| 232 int get totalMembers => _totalMembers; |
| 233 |
| 395 Dartdoc() | 234 Dartdoc() |
| 396 : _comments = new CommentMap(), | 235 : _comments = new CommentMap(), |
| 397 dartdocPath = scriptDir { | 236 dartdocPath = scriptDir { |
| 398 // Patch in support for [:...:]-style code to the markdown parser. | 237 // Patch in support for [:...:]-style code to the markdown parser. |
| 399 // TODO(rnystrom): Markdown already has syntax for this. Phase this out? | 238 // TODO(rnystrom): Markdown already has syntax for this. Phase this out? |
| 400 md.InlineParser.syntaxes.insertRange(0, 1, | 239 md.InlineParser.syntaxes.insertRange(0, 1, |
| 401 new md.CodeSyntax(@'\[\:((?:.|\n)*?)\:\]')); | 240 new md.CodeSyntax(@'\[\:((?:.|\n)*?)\:\]')); |
| 402 | 241 |
| 403 md.setImplicitLinkResolver((name) => resolveNameReference(name, | 242 md.setImplicitLinkResolver((name) => resolveNameReference(name, |
| 404 currentLibrary: _currentLibrary, currentType: _currentType, | 243 currentLibrary: _currentLibrary, currentType: _currentType, |
| (...skipping 1324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1729 | 1568 |
| 1730 /** | 1569 /** |
| 1731 * Used to report an unexpected error in the DartDoc tool or the | 1570 * Used to report an unexpected error in the DartDoc tool or the |
| 1732 * underlying data | 1571 * underlying data |
| 1733 */ | 1572 */ |
| 1734 class InternalError { | 1573 class InternalError { |
| 1735 final String message; | 1574 final String message; |
| 1736 const InternalError(this.message); | 1575 const InternalError(this.message); |
| 1737 String toString() => "InternalError: '$message'"; | 1576 String toString() => "InternalError: '$message'"; |
| 1738 } | 1577 } |
| OLD | NEW |