| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 #source('classify.dart'); | 23 #source('classify.dart'); |
| 24 #source('files.dart'); | 24 #source('files.dart'); |
| 25 #source('utils.dart'); | 25 #source('utils.dart'); |
| 26 | 26 |
| 27 /** Path to corePath library. */ | 27 /** Path to corePath library. */ |
| 28 final corePath = 'lib'; | 28 final corePath = 'lib'; |
| 29 | 29 |
| 30 /** Path to generate html files into. */ | 30 /** Path to generate html files into. */ |
| 31 final outdir = 'docs'; | 31 final outdir = 'docs'; |
| 32 | 32 |
| 33 /** Set to `true` to include the source code in the generated docs. */ | 33 /** Set to `false` to not include the source code in the generated docs. */ |
| 34 bool includeSource = false; | 34 bool includeSource = true; |
| 35 | 35 |
| 36 /** Special comment position used to store the library-level doc comment. */ | 36 /** Special comment position used to store the library-level doc comment. */ |
| 37 final _libraryDoc = -1; | 37 final _libraryDoc = -1; |
| 38 | 38 |
| 39 /** The library that we're currently generating docs for. */ | 39 /** The library that we're currently generating docs for. */ |
| 40 Library _currentLibrary; | 40 Library _currentLibrary; |
| 41 | 41 |
| 42 /** The type that we're currently generating docs for. */ | 42 /** The type that we're currently generating docs for. */ |
| 43 Type _currentType; | 43 Type _currentType; |
| 44 | 44 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 56 | 56 |
| 57 int _totalLibraries = 0; | 57 int _totalLibraries = 0; |
| 58 int _totalTypes = 0; | 58 int _totalTypes = 0; |
| 59 int _totalMembers = 0; | 59 int _totalMembers = 0; |
| 60 | 60 |
| 61 /** | 61 /** |
| 62 * Run this from the `utils/dartdoc` directory. | 62 * Run this from the `utils/dartdoc` directory. |
| 63 */ | 63 */ |
| 64 void main() { | 64 void main() { |
| 65 // The entrypoint of the library to generate docs for. | 65 // The entrypoint of the library to generate docs for. |
| 66 final libPath = process.argv[2]; | 66 final entrypoint = process.argv[2]; |
| 67 | 67 |
| 68 // Parse the dartdoc options. | 68 // Parse the dartdoc options. |
| 69 for (int i = 3; i < process.argv.length; i++) { | 69 for (int i = 3; i < process.argv.length; i++) { |
| 70 final arg = process.argv[i]; | 70 final arg = process.argv[i]; |
| 71 switch (arg) { | 71 switch (arg) { |
| 72 case '--no-code': | 72 case '--no-code': |
| 73 includeSource = false; | 73 includeSource = false; |
| 74 break; | 74 break; |
| 75 | 75 |
| 76 default: | 76 default: |
| 77 print('Unknown option: $arg'); | 77 print('Unknown option: $arg'); |
| 78 } | 78 } |
| 79 } | 79 } |
| 80 | 80 |
| 81 files = new NodeFileSystem(); | 81 files = new NodeFileSystem(); |
| 82 parseOptions('../../frog', [] /* args */, files); | 82 parseOptions('../../frog', [] /* args */, files); |
| 83 options.dietParse = true; |
| 83 | 84 |
| 84 // Patch in support for [:...:]-style code to the markdown parser. | 85 // Patch in support for [:...:]-style code to the markdown parser. |
| 85 // TODO(rnystrom): Markdown already has syntax for this. Phase this out? | 86 // TODO(rnystrom): Markdown already has syntax for this. Phase this out? |
| 86 md.InlineParser.syntaxes.insertRange(0, 1, | 87 md.InlineParser.syntaxes.insertRange(0, 1, |
| 87 new md.CodeSyntax(@'\[\:((?:.|\n)*?)\:\]')); | 88 new md.CodeSyntax(@'\[\:((?:.|\n)*?)\:\]')); |
| 88 | 89 |
| 89 md.setImplicitLinkResolver(resolveNameReference); | 90 md.setImplicitLinkResolver(resolveNameReference); |
| 90 | 91 |
| 91 final elapsed = time(() { | 92 final elapsed = time(() { |
| 92 initializeDartDoc(); | 93 initializeDartDoc(); |
| 93 | 94 |
| 94 initializeWorld(files); | 95 initializeWorld(files); |
| 95 | 96 |
| 96 world.processDartScript(libPath); | 97 // Handle the built-in entrypoints. |
| 98 switch (entrypoint) { |
| 99 case 'corelib': |
| 100 world.getOrAddLibrary('dart:core'); |
| 101 world.getOrAddLibrary('dart:coreimpl'); |
| 102 world.process(); |
| 103 break; |
| 104 |
| 105 case 'dom': |
| 106 world.getOrAddLibrary('dart:core'); |
| 107 world.getOrAddLibrary('dart:coreimpl'); |
| 108 world.getOrAddLibrary('dart:dom'); |
| 109 world.process(); |
| 110 break; |
| 111 |
| 112 case 'html': |
| 113 world.getOrAddLibrary('dart:core'); |
| 114 world.getOrAddLibrary('dart:coreimpl'); |
| 115 world.getOrAddLibrary('dart:dom'); |
| 116 world.getOrAddLibrary('dart:html'); |
| 117 world.process(); |
| 118 break; |
| 119 |
| 120 default: |
| 121 // Normal entrypoint script. |
| 122 world.processDartScript(entrypoint); |
| 123 } |
| 124 |
| 97 world.resolveAll(); | 125 world.resolveAll(); |
| 98 | 126 |
| 99 // Generate the docs. | 127 // Generate the docs. |
| 128 docIndex(); |
| 100 for (final library in world.libraries.getValues()) { | 129 for (final library in world.libraries.getValues()) { |
| 101 docLibrary(library); | 130 docLibrary(library); |
| 102 } | 131 } |
| 103 | |
| 104 docIndex(world.libraries.getValues()); | |
| 105 }); | 132 }); |
| 106 | 133 |
| 107 print('Documented $_totalLibraries libraries, $_totalTypes types, and ' + | 134 print('Documented $_totalLibraries libraries, $_totalTypes types, and ' + |
| 108 '$_totalMembers members in ${elapsed}msec.'); | 135 '$_totalMembers members in ${elapsed}msec.'); |
| 109 } | 136 } |
| 110 | 137 |
| 111 void initializeDartDoc() { | 138 void initializeDartDoc() { |
| 112 _comments = <String, Map<int, String>>{}; | 139 _comments = <String, Map<int, String>>{}; |
| 113 } | 140 } |
| 114 | 141 |
| 115 docIndex(List<Library> libraries) { | |
| 116 startFile('index.html'); | |
| 117 // TODO(rnystrom): Need to figure out what this should look like. | |
| 118 writeln( | |
| 119 ''' | |
| 120 <html><head> | |
| 121 <title>Index</title> | |
| 122 <link rel="stylesheet" type="text/css" href="styles.css" /> | |
| 123 </head> | |
| 124 <body> | |
| 125 <div class="content"> | |
| 126 <ul> | |
| 127 '''); | |
| 128 | |
| 129 final sorted = new List<Library>.from(libraries); | |
| 130 sorted.sort((a, b) => a.name.compareTo(b.name)); | |
| 131 | |
| 132 for (final library in sorted) { | |
| 133 writeln( | |
| 134 ''' | |
| 135 <li>${a(libraryUrl(library), "Library ${library.name}")}</li> | |
| 136 '''); | |
| 137 } | |
| 138 | |
| 139 writeln( | |
| 140 ''' | |
| 141 </ul> | |
| 142 </div> | |
| 143 </body></html> | |
| 144 '''); | |
| 145 | |
| 146 endFile(); | |
| 147 } | |
| 148 | |
| 149 writeHeader(String title) { | 142 writeHeader(String title) { |
| 150 writeln( | 143 writeln( |
| 151 ''' | 144 ''' |
| 152 <!DOCTYPE html> | 145 <!DOCTYPE html> |
| 153 <html> | 146 <html> |
| 154 <head> | 147 <head> |
| 155 <meta charset="utf-8"> | 148 <meta charset="utf-8"> |
| 156 <title>$title</title> | 149 <title>$title</title> |
| 157 <link rel="stylesheet" type="text/css" | 150 <link rel="stylesheet" type="text/css" |
| 158 href="${relativePath('styles.css')}" /> | 151 href="${relativePath('styles.css')}" /> |
| 159 <link href="http://fonts.googleapis.com/css?family=Open+Sans:400,600,700,8
00" rel="stylesheet" type="text/css"> | 152 <link href="http://fonts.googleapis.com/css?family=Open+Sans:400,600,700,8
00" rel="stylesheet" type="text/css"> |
| 160 <script src="${relativePath('interact.js')}"></script> | 153 <script src="${relativePath('interact.js')}"></script> |
| 161 </head> | 154 </head> |
| 162 <body> | 155 <body> |
| 163 <div class="page"> | 156 <div class="page"> |
| 164 '''); | 157 '''); |
| 165 docNavigation(); | 158 docNavigation(); |
| 166 writeln('<div class="content">'); | 159 writeln('<div class="content">'); |
| 167 } | 160 } |
| 168 | 161 |
| 169 writeFooter() { | 162 writeFooter() { |
| 170 writeln( | 163 writeln( |
| 171 ''' | 164 ''' |
| 172 </div> | 165 </div> |
| 173 <div class="footer"</div> | 166 <div class="footer"</div> |
| 174 </body></html> | 167 </body></html> |
| 175 '''); | 168 '''); |
| 176 } | 169 } |
| 177 | 170 |
| 171 docIndex() { |
| 172 startFile('index.html'); |
| 173 |
| 174 writeHeader('Dart Documentation'); |
| 175 |
| 176 writeln('<h1>Dart Documentation</h1>'); |
| 177 writeln('<h3>Libraries</h3>'); |
| 178 |
| 179 for (final library in orderByName(world.libraries)) { |
| 180 writeln( |
| 181 ''' |
| 182 <h4>${a(libraryUrl(library), "Library ${library.name}")}</h4> |
| 183 '''); |
| 184 } |
| 185 |
| 186 writeFooter(); |
| 187 endFile(); |
| 188 } |
| 189 |
| 178 docNavigation() { | 190 docNavigation() { |
| 179 writeln( | 191 writeln( |
| 180 ''' | 192 ''' |
| 181 <div class="nav"> | 193 <div class="nav"> |
| 182 <h1>Libraries</h1> | 194 <h1>${a("index.html", "Dart Documentation")}</h1> |
| 183 '''); | 195 '''); |
| 184 | 196 |
| 185 for (final library in orderValuesByKeys(world.libraries)) { | 197 for (final library in orderByName(world.libraries)) { |
| 186 write('<h2><div class="icon-library"></div> '); | 198 write('<h2><div class="icon-library"></div>'); |
| 187 | 199 |
| 188 if ((_currentLibrary == library) && (_currentType == null)) { | 200 if ((_currentLibrary == library) && (_currentType == null)) { |
| 189 write('<strong>${library.name}</strong>'); | 201 write('<strong>${library.name}</strong>'); |
| 190 } else { | 202 } else { |
| 191 write('${a(libraryUrl(library), library.name)}'); | 203 write('${a(libraryUrl(library), library.name)}'); |
| 192 } | 204 } |
| 193 write('</h2>'); | 205 write('</h2>'); |
| 194 | 206 |
| 195 final types = orderValuesByKeys(library.types); | 207 // Only expand classes in navigation for current library. |
| 196 if (types.length > 0) { | 208 if (_currentLibrary == library) docLibraryNavigation(library); |
| 197 writeln('<ul>'); | |
| 198 for (final type in types) { | |
| 199 if (type.isTop) continue; | |
| 200 if (type.name.startsWith('_')) continue; | |
| 201 | |
| 202 var icon = type.isClass ? 'icon-class' : 'icon-interface'; | |
| 203 write('<li><div class="$icon"></div> '); | |
| 204 | |
| 205 if (_currentType == type) { | |
| 206 write('<strong>${type.name}</strong>'); | |
| 207 } else { | |
| 208 write('${a(typeUrl(type), type.name)}'); | |
| 209 } | |
| 210 | |
| 211 writeln('</li>'); | |
| 212 } | |
| 213 | |
| 214 writeln('</ul>'); | |
| 215 } | |
| 216 } | 209 } |
| 217 | 210 |
| 218 writeln('</div>'); | 211 writeln('</div>'); |
| 219 } | 212 } |
| 220 | 213 |
| 214 /** Writes the navigation for the types contained by the given library. */ |
| 215 docLibraryNavigation(Library library) { |
| 216 final types = orderByName(library.types).filter( |
| 217 (type) => !type.isTop && !type.name.startsWith('_')); |
| 218 |
| 219 if (types.length == 0) return; |
| 220 |
| 221 writeln('<ul>'); |
| 222 for (final type in types) { |
| 223 var icon = type.isClass ? 'icon-class' : 'icon-interface'; |
| 224 write('<li><div class="$icon"></div>'); |
| 225 |
| 226 if (_currentType == type) { |
| 227 write('<strong>${typeName(type)}</strong>'); |
| 228 } else { |
| 229 write('${a(typeUrl(type), typeName(type))}'); |
| 230 } |
| 231 |
| 232 writeln('</li>'); |
| 233 } |
| 234 writeln('</ul>'); |
| 235 } |
| 236 |
| 221 docLibrary(Library library) { | 237 docLibrary(Library library) { |
| 222 _totalLibraries++; | 238 _totalLibraries++; |
| 223 _currentLibrary = library; | 239 _currentLibrary = library; |
| 224 _currentType = null; | 240 _currentType = null; |
| 225 | 241 |
| 226 startFile(libraryUrl(library)); | 242 startFile(libraryUrl(library)); |
| 227 writeHeader(library.name); | 243 writeHeader(library.name); |
| 228 writeln('<h1>Library <strong>${library.name}</strong></h1>'); | 244 writeln('<h1>Library <strong>${library.name}</strong></h1>'); |
| 229 | 245 |
| 230 // Look for a comment for the entire library. | 246 // Look for a comment for the entire library. |
| 231 final comment = findCommentInFile(library.baseSource, _libraryDoc); | 247 final comment = findCommentInFile(library.baseSource, _libraryDoc); |
| 232 if (comment != null) { | 248 if (comment != null) { |
| 233 final html = md.markdownToHtml(comment); | 249 final html = md.markdownToHtml(comment); |
| 234 writeln('<div class="doc">$html</div>'); | 250 writeln('<div class="doc">$html</div>'); |
| 235 } | 251 } |
| 236 | 252 |
| 237 // Document the top-level members. | 253 // Document the top-level members. |
| 238 docMembers(library.topType); | 254 docMembers(library.topType); |
| 239 | 255 |
| 240 // TODO(rnystrom): Link to types. | |
| 241 writeln('<h3>Types</h3>'); | 256 writeln('<h3>Types</h3>'); |
| 242 | 257 |
| 243 for (final type in orderValuesByKeys(library.types)) { | 258 for (final type in orderByName(library.types)) { |
| 244 if (type.isTop) continue; | 259 if (type.isTop) continue; |
| 245 if (type.name.startsWith('_')) continue; | 260 if (type.name.startsWith('_')) continue; |
| 246 writeln( | 261 writeln( |
| 247 ''' | 262 ''' |
| 248 <div class="type"> | 263 <div class="type"> |
| 249 <h4> | 264 <h4> |
| 250 ${type.isClass ? "class" : "interface"} | 265 ${type.isClass ? "class" : "interface"} |
| 251 ${a(typeUrl(type), "<strong>${typeName(type)}</strong>")} | 266 ${a(typeUrl(type), "<strong>${typeName(type)}</strong>")} |
| 252 </h4> | 267 </h4> |
| 253 </div> | 268 </div> |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 285 | 300 |
| 286 writeFooter(); | 301 writeFooter(); |
| 287 endFile(); | 302 endFile(); |
| 288 } | 303 } |
| 289 | 304 |
| 290 void docMembers(Type type) { | 305 void docMembers(Type type) { |
| 291 // Collect the different kinds of members. | 306 // Collect the different kinds of members. |
| 292 final methods = []; | 307 final methods = []; |
| 293 final fields = []; | 308 final fields = []; |
| 294 | 309 |
| 295 for (final member in orderValuesByKeys(type.members)) { | 310 for (final member in orderByName(type.members)) { |
| 296 if (member.name.startsWith('_')) continue; | 311 if (member.name.startsWith('_')) continue; |
| 297 | 312 |
| 298 if (member.isProperty) { | 313 if (member.isProperty) { |
| 299 if (member.canGet) methods.add(member.getter); | 314 if (member.canGet) methods.add(member.getter); |
| 300 if (member.canSet) methods.add(member.setter); | 315 if (member.canSet) methods.add(member.setter); |
| 301 } else if (member.isMethod) { | 316 } else if (member.isMethod) { |
| 302 methods.add(member); | 317 methods.add(member); |
| 303 } else if (member.isField) { | 318 } else if (member.isField) { |
| 304 fields.add(member); | 319 fields.add(member); |
| 305 } | 320 } |
| (...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 728 } else if (line.startsWith('*')) { | 743 } else if (line.startsWith('*')) { |
| 729 line = line.substring(1, line.length); | 744 line = line.substring(1, line.length); |
| 730 } | 745 } |
| 731 | 746 |
| 732 buf.add(line); | 747 buf.add(line); |
| 733 buf.add('\n'); | 748 buf.add('\n'); |
| 734 } | 749 } |
| 735 | 750 |
| 736 return buf.toString(); | 751 return buf.toString(); |
| 737 } | 752 } |
| OLD | NEW |