Chromium Code Reviews| 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 var includeSource; |
| 58 var mode; | |
| 59 var outputDir; | |
|
nweiz
2012/03/15 23:45:48
These should have types declared, since they're no
Bob Nystrom
2012/03/15 23:58:23
Done.
| |
| 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); | |
|
nweiz
2012/03/15 23:45:48
Is there a bug filed against Options to support op
Bob Nystrom
2012/03/15 23:58:23
No, but I don't really think arg parsing should be
nweiz
2012/03/16 00:15:49
What's the Options class for if not arg parsing?
Bob Nystrom
2012/03/16 00:22:37
It's for being able to access them at all. I would
nweiz
2012/03/16 18:25:51
Maybe this is more of an API design issue, but the
| |
| 80 } else { | |
| 81 print('Unknown option: $arg'); | |
| 82 return; | |
| 83 } | |
|
mattsh
2012/03/15 23:52:55
missing break
Bob Nystrom
2012/03/15 23:58:23
Done.
| |
| 83 } | 84 } |
| 84 } | 85 } |
| 85 | 86 |
| 87 // The entrypoint of the library to generate docs for. | |
| 88 final entrypoint = args[args.length - 1]; | |
| 89 | |
| 86 final files = new VMFileSystem(); | 90 final files = new VMFileSystem(); |
| 87 // TODO(rnystrom): Note that the following line gets munged by create-sdk to | 91 // 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 | 92 // work with the SDK's different file layout. If you change it here, make |
| 89 // sure SDK builds still work. | 93 // sure SDK builds still work. |
| 90 parseOptions('../../frog', ['', '', '--libdir=../../frog/lib'], files); | 94 parseOptions('../../frog', ['', '', '--libdir=../../frog/lib'], files); |
| 91 initializeWorld(files); | 95 initializeWorld(files); |
| 92 | 96 |
| 93 var dartdoc; | 97 var dartdoc; |
| 94 final elapsed = time(() { | 98 final elapsed = time(() { |
| 95 dartdoc = new Dartdoc(); | 99 dartdoc = new Dartdoc(); |
| 96 dartdoc.includeSource = includeSource; | 100 |
| 97 dartdoc.mode = mode; | 101 if (includeSource != null) dartdoc.includeSource = includeSource; |
| 102 if (mode != null) dartdoc.mode = mode; | |
| 103 if (outputDir != null) dartdoc.outputDir = outputDir; | |
| 104 | |
| 105 cleanOutputDirectory(outputDir); | |
| 106 | |
| 107 // TODO(rnystrom): Use platform-specific path separator. | |
|
nweiz
2012/03/15 23:45:48
Won't Windows understand "/", even if it doesn't p
Bob Nystrom
2012/03/15 23:58:23
Not sure. The Platform class in Dart does have a p
nweiz
2012/03/16 00:15:49
If we don't have to use the separator constant for
Bob Nystrom
2012/03/16 00:22:37
Works for me. I won't plan to change this until I
| |
| 108 copyFiles('$scriptDir/static', outputDir); | |
| 98 | 109 |
| 99 dartdoc.document(entrypoint); | 110 dartdoc.document(entrypoint); |
| 100 }); | 111 }); |
| 101 | 112 |
| 102 print('Documented ${dartdoc._totalLibraries} libraries, ' + | 113 print('Documented ${dartdoc._totalLibraries} libraries, ' + |
| 103 '${dartdoc._totalTypes} types, and ' + | 114 '${dartdoc._totalTypes} types, and ' + |
| 104 '${dartdoc._totalMembers} members in ${elapsed}msec.'); | 115 '${dartdoc._totalMembers} members in ${elapsed}msec.'); |
| 105 } | 116 } |
| 106 | 117 |
| 118 /** | |
| 119 * Gets the full path to the directory containing the entrypoint of the current | |
| 120 * script. In other words, if you invoked dartdoc, directly, it will be the | |
| 121 * path to the directory containing `dartdoc.dart`. If you're running a script | |
| 122 * that imports dartdoc, it will be the path to that script. | |
| 123 */ | |
| 124 String get scriptDir() { | |
| 125 return dirname(new File(new Options().script).fullPathSync()); | |
| 126 } | |
| 127 | |
| 128 /** | |
| 129 * Deletes and recreates the output directory at [path] if it exists. | |
| 130 */ | |
| 131 void cleanOutputDirectory(String path) { | |
| 132 final outputDir = new Directory(path); | |
| 133 if (outputDir.existsSync()) { | |
| 134 outputDir.deleteRecursivelySync(); | |
| 135 outputDir.createSync(); | |
| 136 } | |
| 137 } | |
| 138 | |
| 139 /** | |
| 140 * Copies all of the files in the directory [from] to [to]. Does *not* | |
| 141 * recursively copy subdirectories. | |
| 142 * | |
| 143 * Note: runs asynchronously, so you won't see any files copied until after the | |
| 144 * event loop has had a chance to pump (i.e. after `main()` has returned). | |
| 145 */ | |
| 146 void copyFiles(String from, String to) { | |
| 147 final fromDir = new Directory(from); | |
| 148 fromDir.onFile = (path) { | |
| 149 final name = basename(path); | |
| 150 // TODO(rnystrom): Hackish. Ignore 'hidden' files like .DS_Store. | |
| 151 if (name.startsWith('.')) return; | |
| 152 | |
| 153 new File(path).readAsBytes((bytes) { | |
| 154 final outFile = new File('$to/$name'); | |
| 155 final stream = outFile.openOutputStream(FileMode.WRITE); | |
| 156 stream.write(bytes, copyBuffer: false); | |
| 157 stream.close(); | |
| 158 }); | |
| 159 }; | |
| 160 fromDir.list(recursive: false); | |
| 161 } | |
| 162 | |
| 107 class Dartdoc { | 163 class Dartdoc { |
| 108 /** Set to `false` to not include the source code in the generated docs. */ | 164 /** Set to `false` to not include the source code in the generated docs. */ |
| 109 bool includeSource = true; | 165 bool includeSource = true; |
| 110 | 166 |
| 111 /** | 167 /** |
| 112 * Dartdoc can generate docs in a few different ways based on how dynamic you | 168 * 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 | 169 * want the client-side behavior to be. The value for this should be one of |
| 114 * the `MODE_` constants. | 170 * the `MODE_` constants. |
| 115 */ | 171 */ |
| 116 int mode = MODE_LIVE_NAV; | 172 int mode = MODE_LIVE_NAV; |
| 117 | 173 |
| 174 /** Path to generate HTML files into. */ | |
| 175 String outputDir = 'docs'; | |
| 176 | |
| 118 /** | 177 /** |
| 119 * The title used for the overall generated output. Set this to change it. | 178 * The title used for the overall generated output. Set this to change it. |
| 120 */ | 179 */ |
| 121 String mainTitle = 'Dart Documentation'; | 180 String mainTitle = 'Dart Documentation'; |
| 122 | 181 |
| 123 /** | 182 /** |
| 124 * The URL that the Dart logo links to. Defaults "index.html", the main | 183 * The URL that the Dart logo links to. Defaults "index.html", the main |
| 125 * page for the generated docs, but can be anything. | 184 * page for the generated docs, but can be anything. |
| 126 */ | 185 */ |
| 127 String mainUrl = 'index.html'; | 186 String mainUrl = 'index.html'; |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 238 options.dietParse = oldDietParse; | 297 options.dietParse = oldDietParse; |
| 239 } | 298 } |
| 240 } | 299 } |
| 241 | 300 |
| 242 void startFile(String path) { | 301 void startFile(String path) { |
| 243 _filePath = path; | 302 _filePath = path; |
| 244 _file = new StringBuffer(); | 303 _file = new StringBuffer(); |
| 245 } | 304 } |
| 246 | 305 |
| 247 void endFile() { | 306 void endFile() { |
| 248 final outPath = '$_outdir/$_filePath'; | 307 final outPath = '$outputDir/$_filePath'; |
| 249 final dir = new Directory(dirname(outPath)); | 308 final dir = new Directory(dirname(outPath)); |
| 250 if (!dir.existsSync()) { | 309 if (!dir.existsSync()) { |
| 251 dir.createSync(); | 310 dir.createSync(); |
| 252 } | 311 } |
| 253 | 312 |
| 254 world.files.writeString(outPath, _file.toString()); | 313 world.files.writeString(outPath, _file.toString()); |
| 255 _filePath = null; | 314 _filePath = null; |
| 256 _file = null; | 315 _file = null; |
| 257 } | 316 } |
| 258 | 317 |
| (...skipping 953 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1212 | 1271 |
| 1213 return new md.Element.text('code', name); | 1272 return new md.Element.text('code', name); |
| 1214 } | 1273 } |
| 1215 | 1274 |
| 1216 // TODO(rnystrom): Move into SourceSpan? | 1275 // TODO(rnystrom): Move into SourceSpan? |
| 1217 int getSpanColumn(SourceSpan span) { | 1276 int getSpanColumn(SourceSpan span) { |
| 1218 final line = span.file.getLine(span.start); | 1277 final line = span.file.getLine(span.start); |
| 1219 return span.file.getColumn(line, span.start); | 1278 return span.file.getColumn(line, span.start); |
| 1220 } | 1279 } |
| 1221 } | 1280 } |
| OLD | NEW |