| 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 use it, from this directory, run: | 6 * To use it, from this directory, run: |
| 7 * | 7 * |
| 8 * $ ./dartdoc <path to .dart file> | 8 * $ ./dartdoc <path to .dart file> |
| 9 * | 9 * |
| 10 * This will create a "docs" directory with the docs for your libraries. To | 10 * This will create a "docs" directory with the docs for your libraries. To |
| 11 * create these beautiful docs, dartdoc parses your library and every library | 11 * create these beautiful docs, dartdoc parses your library and every library |
| 12 * it imports (recursively). From each library, it parses all classes and | 12 * it imports (recursively). From each library, it parses all classes and |
| 13 * members, finds the associated doc comments and builds crosslinked docs from | 13 * members, finds the associated doc comments and builds crosslinked docs from |
| 14 * them. | 14 * them. |
| 15 */ | 15 */ |
| 16 #library('dartdoc'); | 16 #library('dartdoc'); |
| 17 | 17 |
| 18 #import('dart:io'); | 18 #import('dart:io'); |
| 19 #import('dart:json'); | 19 #import('dart:json'); |
| 20 #import('../../frog/lang.dart'); | 20 #import('../../frog/lang.dart'); |
| 21 #import('../../frog/file_system.dart'); | 21 #import('../../frog/file_system.dart'); |
| 22 #import('../../frog/file_system_vm.dart'); | 22 #import('../../frog/file_system_vm.dart'); |
| 23 #import('classify.dart'); | 23 #import('classify.dart'); |
| 24 #import('markdown.dart', prefix: 'md'); | 24 #import('markdown.dart', prefix: 'md'); |
| 25 | 25 |
| 26 #source('comment_map.dart'); | 26 #source('comment_map.dart'); |
| 27 #source('utils.dart'); | 27 #source('utils.dart'); |
| 28 | 28 |
| 29 /** Path to generate HTML files into. */ | |
| 30 final _outdir = 'docs'; | |
| 31 | |
| 32 /** | 29 /** |
| 33 * Generates completely static HTML containing everything you need to browse | 30 * Generates completely static HTML containing everything you need to browse |
| 34 * the docs. The only client side behavior is trivial stuff like syntax | 31 * the docs. The only client side behavior is trivial stuff like syntax |
| 35 * highlighting code. | 32 * highlighting code. |
| 36 */ | 33 */ |
| 37 final MODE_STATIC = 0; | 34 final MODE_STATIC = 0; |
| 38 | 35 |
| 39 /** | 36 /** |
| 40 * Generated docs do not include baked HTML navigation. Instead, a single | 37 * Generated docs do not include baked HTML navigation. Instead, a single |
| 41 * `nav.json` file is created and the appropriate navigation is generated | 38 * `nav.json` file is created and the appropriate navigation is generated |
| 42 * client-side by parsing that and building HTML. | 39 * client-side by parsing that and building HTML. |
| 43 * | 40 * |
| 44 * This dramatically reduces the generated size of the HTML since a large | 41 * This dramatically reduces the generated size of the HTML since a large |
| 45 * fraction of each static page is just redundant navigation links. | 42 * fraction of each static page is just redundant navigation links. |
| 46 * | 43 * |
| 47 * In this mode, the browser will do a XHR for nav.json which means that to | 44 * In this mode, the browser will do a XHR for nav.json which means that to |
| 48 * preview docs locally, you will need to enable requesting file:// links in | 45 * preview docs locally, you will need to enable requesting file:// links in |
| 49 * your browser or run a little local server like `python -m SimpleHTTPServer`. | 46 * your browser or run a little local server like `python -m SimpleHTTPServer`. |
| 50 */ | 47 */ |
| 51 final MODE_LIVE_NAV = 1; | 48 final MODE_LIVE_NAV = 1; |
| 52 | 49 |
| 53 /** | 50 /** |
| 54 * Run this from the `lib/dartdoc` directory. | 51 * Run this from the `lib/dartdoc` directory. |
| 55 */ | 52 */ |
| 56 void main() { | 53 void main() { |
| 57 final args = new Options().arguments; | 54 final args = new Options().arguments; |
| 58 | 55 |
| 59 // The entrypoint of the library to generate docs for. | 56 // Parse the dartdoc options. |
| 60 final entrypoint = args[args.length - 1]; | 57 bool includeSource; |
| 58 String mode; |
| 59 String outputDir; |
| 61 | 60 |
| 62 // Parse the dartdoc options. | 61 for (int i = 0; i < args.length - 1; i++) { |
| 63 bool includeSource = true; | 62 final arg = args[i]; |
| 64 var mode = MODE_LIVE_NAV; | |
| 65 | 63 |
| 66 for (int i = 2; i < args.length - 1; i++) { | |
| 67 final arg = args[i]; | |
| 68 switch (arg) { | 64 switch (arg) { |
| 69 case '--no-code': | 65 case '--no-code': |
| 70 includeSource = false; | 66 includeSource = false; |
| 71 break; | 67 break; |
| 72 | 68 |
| 73 case '--mode=static': | 69 case '--mode=static': |
| 74 mode = MODE_STATIC; | 70 mode = MODE_STATIC; |
| 75 break; | 71 break; |
| 76 | 72 |
| 77 case '--mode=live-nav': | 73 case '--mode=live-nav': |
| 78 mode = MODE_LIVE_NAV; | 74 mode = MODE_LIVE_NAV; |
| 79 break; | 75 break; |
| 80 | 76 |
| 81 default: | 77 default: |
| 82 print('Unknown option: $arg'); | 78 if (arg.startsWith('--out=')) { |
| 79 outputDir = arg.substring('--out='.length); |
| 80 } else { |
| 81 print('Unknown option: $arg'); |
| 82 return; |
| 83 } |
| 84 break; |
| 83 } | 85 } |
| 84 } | 86 } |
| 85 | 87 |
| 88 // The entrypoint of the library to generate docs for. |
| 89 final entrypoint = args[args.length - 1]; |
| 90 |
| 86 final files = new VMFileSystem(); | 91 final files = new VMFileSystem(); |
| 87 // TODO(rnystrom): Note that the following line gets munged by create-sdk to | 92 // TODO(rnystrom): Note that the following line gets munged by create-sdk to |
| 88 // work with the SDK's different file layout. If you change it here, make | 93 // work with the SDK's different file layout. If you change it here, make |
| 89 // sure SDK builds still work. | 94 // sure SDK builds still work. |
| 90 parseOptions('../../frog', ['', '', '--libdir=../../frog/lib'], files); | 95 parseOptions('../../frog', ['', '', '--libdir=../../frog/lib'], files); |
| 91 initializeWorld(files); | 96 initializeWorld(files); |
| 92 | 97 |
| 93 var dartdoc; | 98 var dartdoc; |
| 94 final elapsed = time(() { | 99 final elapsed = time(() { |
| 95 dartdoc = new Dartdoc(); | 100 dartdoc = new Dartdoc(); |
| 96 dartdoc.includeSource = includeSource; | 101 |
| 97 dartdoc.mode = mode; | 102 if (includeSource != null) dartdoc.includeSource = includeSource; |
| 103 if (mode != null) dartdoc.mode = mode; |
| 104 if (outputDir != null) dartdoc.outputDir = outputDir; |
| 105 |
| 106 cleanOutputDirectory(outputDir); |
| 107 |
| 108 // TODO(rnystrom): Use platform-specific path separator. |
| 109 copyFiles('$scriptDir/static', outputDir); |
| 98 | 110 |
| 99 dartdoc.document(entrypoint); | 111 dartdoc.document(entrypoint); |
| 100 }); | 112 }); |
| 101 | 113 |
| 102 print('Documented ${dartdoc._totalLibraries} libraries, ' + | 114 print('Documented ${dartdoc._totalLibraries} libraries, ' + |
| 103 '${dartdoc._totalTypes} types, and ' + | 115 '${dartdoc._totalTypes} types, and ' + |
| 104 '${dartdoc._totalMembers} members in ${elapsed}msec.'); | 116 '${dartdoc._totalMembers} members in ${elapsed}msec.'); |
| 105 } | 117 } |
| 106 | 118 |
| 119 /** |
| 120 * Gets the full path to the directory containing the entrypoint of the current |
| 121 * script. In other words, if you invoked dartdoc, directly, it will be the |
| 122 * path to the directory containing `dartdoc.dart`. If you're running a script |
| 123 * that imports dartdoc, it will be the path to that script. |
| 124 */ |
| 125 String get scriptDir() { |
| 126 return dirname(new File(new Options().script).fullPathSync()); |
| 127 } |
| 128 |
| 129 /** |
| 130 * Deletes and recreates the output directory at [path] if it exists. |
| 131 */ |
| 132 void cleanOutputDirectory(String path) { |
| 133 final outputDir = new Directory(path); |
| 134 if (outputDir.existsSync()) { |
| 135 outputDir.deleteRecursivelySync(); |
| 136 outputDir.createSync(); |
| 137 } |
| 138 } |
| 139 |
| 140 /** |
| 141 * Copies all of the files in the directory [from] to [to]. Does *not* |
| 142 * recursively copy subdirectories. |
| 143 * |
| 144 * Note: runs asynchronously, so you won't see any files copied until after the |
| 145 * event loop has had a chance to pump (i.e. after `main()` has returned). |
| 146 */ |
| 147 void copyFiles(String from, String to) { |
| 148 final fromDir = new Directory(from); |
| 149 fromDir.onFile = (path) { |
| 150 final name = basename(path); |
| 151 // TODO(rnystrom): Hackish. Ignore 'hidden' files like .DS_Store. |
| 152 if (name.startsWith('.')) return; |
| 153 |
| 154 new File(path).readAsBytes((bytes) { |
| 155 final outFile = new File('$to/$name'); |
| 156 final stream = outFile.openOutputStream(FileMode.WRITE); |
| 157 stream.write(bytes, copyBuffer: false); |
| 158 stream.close(); |
| 159 }); |
| 160 }; |
| 161 fromDir.list(recursive: false); |
| 162 } |
| 163 |
| 107 class Dartdoc { | 164 class Dartdoc { |
| 108 /** Set to `false` to not include the source code in the generated docs. */ | 165 /** Set to `false` to not include the source code in the generated docs. */ |
| 109 bool includeSource = true; | 166 bool includeSource = true; |
| 110 | 167 |
| 111 /** | 168 /** |
| 112 * Dartdoc can generate docs in a few different ways based on how dynamic you | 169 * Dartdoc can generate docs in a few different ways based on how dynamic you |
| 113 * want the client-side behavior to be. The value for this should be one of | 170 * want the client-side behavior to be. The value for this should be one of |
| 114 * the `MODE_` constants. | 171 * the `MODE_` constants. |
| 115 */ | 172 */ |
| 116 int mode = MODE_LIVE_NAV; | 173 int mode = MODE_LIVE_NAV; |
| 117 | 174 |
| 175 /** Path to generate HTML files into. */ |
| 176 String outputDir = 'docs'; |
| 177 |
| 118 /** | 178 /** |
| 119 * The title used for the overall generated output. Set this to change it. | 179 * The title used for the overall generated output. Set this to change it. |
| 120 */ | 180 */ |
| 121 String mainTitle = 'Dart Documentation'; | 181 String mainTitle = 'Dart Documentation'; |
| 122 | 182 |
| 123 /** | 183 /** |
| 124 * The URL that the Dart logo links to. Defaults "index.html", the main | 184 * The URL that the Dart logo links to. Defaults "index.html", the main |
| 125 * page for the generated docs, but can be anything. | 185 * page for the generated docs, but can be anything. |
| 126 */ | 186 */ |
| 127 String mainUrl = 'index.html'; | 187 String mainUrl = 'index.html'; |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 238 options.dietParse = oldDietParse; | 298 options.dietParse = oldDietParse; |
| 239 } | 299 } |
| 240 } | 300 } |
| 241 | 301 |
| 242 void startFile(String path) { | 302 void startFile(String path) { |
| 243 _filePath = path; | 303 _filePath = path; |
| 244 _file = new StringBuffer(); | 304 _file = new StringBuffer(); |
| 245 } | 305 } |
| 246 | 306 |
| 247 void endFile() { | 307 void endFile() { |
| 248 final outPath = '$_outdir/$_filePath'; | 308 final outPath = '$outputDir/$_filePath'; |
| 249 final dir = new Directory(dirname(outPath)); | 309 final dir = new Directory(dirname(outPath)); |
| 250 if (!dir.existsSync()) { | 310 if (!dir.existsSync()) { |
| 251 dir.createSync(); | 311 dir.createSync(); |
| 252 } | 312 } |
| 253 | 313 |
| 254 world.files.writeString(outPath, _file.toString()); | 314 world.files.writeString(outPath, _file.toString()); |
| 255 _filePath = null; | 315 _filePath = null; |
| 256 _file = null; | 316 _file = null; |
| 257 } | 317 } |
| 258 | 318 |
| (...skipping 953 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1212 | 1272 |
| 1213 return new md.Element.text('code', name); | 1273 return new md.Element.text('code', name); |
| 1214 } | 1274 } |
| 1215 | 1275 |
| 1216 // TODO(rnystrom): Move into SourceSpan? | 1276 // TODO(rnystrom): Move into SourceSpan? |
| 1217 int getSpanColumn(SourceSpan span) { | 1277 int getSpanColumn(SourceSpan span) { |
| 1218 final line = span.file.getLine(span.start); | 1278 final line = span.file.getLine(span.start); |
| 1219 return span.file.getColumn(line, span.start); | 1279 return span.file.getColumn(line, span.start); |
| 1220 } | 1280 } |
| 1221 } | 1281 } |
| OLD | NEW |