| 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 * |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 // TODO(3914): Hack to avoid 'file already exists' exception thrown | 83 // TODO(3914): Hack to avoid 'file already exists' exception thrown |
| 84 // due to invalid result from dir.existsSync() (probably due to race | 84 // due to invalid result from dir.existsSync() (probably due to race |
| 85 // conditions). | 85 // conditions). |
| 86 outputDir.createSync(); | 86 outputDir.createSync(); |
| 87 } on DirectoryIOException catch (e) { | 87 } on DirectoryIOException catch (e) { |
| 88 // Ignore. | 88 // Ignore. |
| 89 } | 89 } |
| 90 } | 90 } |
| 91 | 91 |
| 92 /** | 92 /** |
| 93 * Returns the display name of the library. This is necessary to account for |
| 94 * dart: libraries. |
| 95 */ |
| 96 String displayName(LibraryMirror library) { |
| 97 var uri = library.uri.toString(); |
| 98 return uri.startsWith('dart:') ? uri.toString() : library.simpleName; |
| 99 } |
| 100 |
| 101 /** |
| 93 * Copies all of the files in the directory [from] to [to]. Does *not* | 102 * Copies all of the files in the directory [from] to [to]. Does *not* |
| 94 * recursively copy subdirectories. | 103 * recursively copy subdirectories. |
| 95 * | 104 * |
| 96 * Note: runs asynchronously, so you won't see any files copied until after the | 105 * Note: runs asynchronously, so you won't see any files copied until after the |
| 97 * event loop has had a chance to pump (i.e. after `main()` has returned). | 106 * event loop has had a chance to pump (i.e. after `main()` has returned). |
| 98 */ | 107 */ |
| 99 Future copyDirectory(Path from, Path to) { | 108 Future copyDirectory(Path from, Path to) { |
| 100 final completer = new Completer(); | 109 final completer = new Completer(); |
| 101 final fromDir = new Directory.fromPath(from); | 110 final fromDir = new Directory.fromPath(from); |
| 102 final lister = fromDir.list(recursive: false); | 111 final lister = fromDir.list(recursive: false); |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 } | 259 } |
| 251 | 260 |
| 252 /** | 261 /** |
| 253 * Returns `true` if [library] is included in the generated documentation. | 262 * Returns `true` if [library] is included in the generated documentation. |
| 254 */ | 263 */ |
| 255 bool shouldIncludeLibrary(LibraryMirror library) { | 264 bool shouldIncludeLibrary(LibraryMirror library) { |
| 256 if (shouldLinkToPublicApi(library)) { | 265 if (shouldLinkToPublicApi(library)) { |
| 257 return false; | 266 return false; |
| 258 } | 267 } |
| 259 var includeByDefault = true; | 268 var includeByDefault = true; |
| 260 String libraryName = library.simpleName; | 269 String libraryName = displayName(library); |
| 261 if (!includedLibraries.isEmpty) { | 270 if (!includedLibraries.isEmpty) { |
| 262 includeByDefault = false; | 271 includeByDefault = false; |
| 263 if (includedLibraries.indexOf(libraryName) != -1) { | 272 if (includedLibraries.indexOf(libraryName) != -1) { |
| 264 return true; | 273 return true; |
| 265 } | 274 } |
| 266 } | 275 } |
| 267 if (excludedLibraries.indexOf(libraryName) != -1) { | 276 if (excludedLibraries.indexOf(libraryName) != -1) { |
| 268 return false; | 277 return false; |
| 269 } | 278 } |
| 270 if (libraryName.startsWith('dart:')) { | 279 if (libraryName.startsWith('dart:')) { |
| 271 String suffix = libraryName.substring('dart:'.length); | 280 String suffix = libraryName.substring('dart:'.length); |
| 272 LibraryInfo info = LIBRARIES[suffix]; | 281 LibraryInfo info = LIBRARIES[suffix]; |
| 273 if (info != null) { | 282 if (info != null) { |
| 274 return info.documented && includeApi; | 283 return info.documented && includeApi; |
| 275 } | 284 } |
| 276 } | 285 } |
| 277 return includeByDefault; | 286 return includeByDefault; |
| 278 } | 287 } |
| 279 | 288 |
| 280 /** | 289 /** |
| 281 * Returns `true` if links to the public API should be generated for | 290 * Returns `true` if links to the public API should be generated for |
| 282 * [library]. | 291 * [library]. |
| 283 */ | 292 */ |
| 284 bool shouldLinkToPublicApi(LibraryMirror library) { | 293 bool shouldLinkToPublicApi(LibraryMirror library) { |
| 285 if (linkToApi) { | 294 if (linkToApi) { |
| 286 String libraryName = library.simpleName; | 295 String libraryName = displayName(library); |
| 287 if (libraryName.startsWith('dart:')) { | 296 if (libraryName.startsWith('dart:')) { |
| 288 String suffix = libraryName.substring('dart:'.length); | 297 String suffix = libraryName.substring('dart:'.length); |
| 289 LibraryInfo info = LIBRARIES[suffix]; | 298 LibraryInfo info = LIBRARIES[suffix]; |
| 290 if (info != null) { | 299 if (info != null) { |
| 291 return info.documented; | 300 return info.documented; |
| 292 } | 301 } |
| 293 } | 302 } |
| 294 } | 303 } |
| 295 return false; | 304 return false; |
| 296 } | 305 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 322 final compilation = new Compilation.library(libraryList, libPath, pkgPath); | 331 final compilation = new Compilation.library(libraryList, libPath, pkgPath); |
| 323 _document(compilation); | 332 _document(compilation); |
| 324 } | 333 } |
| 325 | 334 |
| 326 void _document(Compilation compilation) { | 335 void _document(Compilation compilation) { |
| 327 // Sort the libraries by name (not key). | 336 // Sort the libraries by name (not key). |
| 328 _sortedLibraries = new List<LibraryMirror>.from( | 337 _sortedLibraries = new List<LibraryMirror>.from( |
| 329 compilation.mirrors.libraries.getValues().filter( | 338 compilation.mirrors.libraries.getValues().filter( |
| 330 shouldIncludeLibrary)); | 339 shouldIncludeLibrary)); |
| 331 _sortedLibraries.sort((x, y) { | 340 _sortedLibraries.sort((x, y) { |
| 332 return x.simpleName.toUpperCase().compareTo( | 341 return displayName(x).toUpperCase().compareTo( |
| 333 y.simpleName.toUpperCase()); | 342 displayName(y).toUpperCase()); |
| 334 }); | 343 }); |
| 335 | 344 |
| 336 // Generate the docs. | 345 // Generate the docs. |
| 337 if (mode == MODE_LIVE_NAV) { | 346 if (mode == MODE_LIVE_NAV) { |
| 338 docNavigationJson(); | 347 docNavigationJson(); |
| 339 } else { | 348 } else { |
| 340 docNavigationDart(); | 349 docNavigationDart(); |
| 341 } | 350 } |
| 342 | 351 |
| 343 docIndex(); | 352 docIndex(); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 403 <!DOCTYPE html> | 412 <!DOCTYPE html> |
| 404 <html${htmlAttributes == '' ? '' : ' $htmlAttributes'}> | 413 <html${htmlAttributes == '' ? '' : ' $htmlAttributes'}> |
| 405 <head> | 414 <head> |
| 406 '''); | 415 '''); |
| 407 writeHeadContents(title); | 416 writeHeadContents(title); |
| 408 | 417 |
| 409 // Add data attributes describing what the page documents. | 418 // Add data attributes describing what the page documents. |
| 410 var data = ''; | 419 var data = ''; |
| 411 if (_currentLibrary != null) { | 420 if (_currentLibrary != null) { |
| 412 data = '$data data-library=' | 421 data = '$data data-library=' |
| 413 '"${md.escapeHtml(_currentLibrary.simpleName)}"'; | 422 '"${md.escapeHtml(displayName(_currentLibrary))}"'; |
| 414 } | 423 } |
| 415 | 424 |
| 416 if (_currentType != null) { | 425 if (_currentType != null) { |
| 417 data = '$data data-type="${md.escapeHtml(typeName(_currentType))}"'; | 426 data = '$data data-type="${md.escapeHtml(typeName(_currentType))}"'; |
| 418 } | 427 } |
| 419 | 428 |
| 420 write( | 429 write( |
| 421 ''' | 430 ''' |
| 422 </head> | 431 </head> |
| 423 <body$data> | 432 <body$data> |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 512 | 521 |
| 513 for (final library in _sortedLibraries) { | 522 for (final library in _sortedLibraries) { |
| 514 docIndexLibrary(library); | 523 docIndexLibrary(library); |
| 515 } | 524 } |
| 516 | 525 |
| 517 writeFooter(); | 526 writeFooter(); |
| 518 endFile(); | 527 endFile(); |
| 519 } | 528 } |
| 520 | 529 |
| 521 void docIndexLibrary(LibraryMirror library) { | 530 void docIndexLibrary(LibraryMirror library) { |
| 522 writeln('<h4>${a(libraryUrl(library), library.simpleName)}</h4>'); | 531 writeln('<h4>${a(libraryUrl(library), displayName(library))}</h4>'); |
| 523 } | 532 } |
| 524 | 533 |
| 525 /** | 534 /** |
| 526 * Walks the libraries and creates a JSON object containing the data needed | 535 * Walks the libraries and creates a JSON object containing the data needed |
| 527 * to generate navigation for them. | 536 * to generate navigation for them. |
| 528 */ | 537 */ |
| 529 void docNavigationJson() { | 538 void docNavigationJson() { |
| 530 startFile('nav.json'); | 539 startFile('nav.json'); |
| 531 writeln(JSON.stringify(createNavigationInfo())); | 540 writeln(JSON.stringify(createNavigationInfo())); |
| 532 endFile(); | 541 endFile(); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 563 List createNavigationInfo() { | 572 List createNavigationInfo() { |
| 564 final libraryList = []; | 573 final libraryList = []; |
| 565 for (final library in _sortedLibraries) { | 574 for (final library in _sortedLibraries) { |
| 566 docLibraryNavigationJson(library, libraryList); | 575 docLibraryNavigationJson(library, libraryList); |
| 567 } | 576 } |
| 568 return libraryList; | 577 return libraryList; |
| 569 } | 578 } |
| 570 | 579 |
| 571 void docLibraryNavigationJson(LibraryMirror library, List libraryList) { | 580 void docLibraryNavigationJson(LibraryMirror library, List libraryList) { |
| 572 var libraryInfo = {}; | 581 var libraryInfo = {}; |
| 573 libraryInfo[NAME] = library.simpleName; | 582 libraryInfo[NAME] = displayName(library); |
| 574 final List members = docMembersJson(library.declaredMembers); | 583 final List members = docMembersJson(library.declaredMembers); |
| 575 if (!members.isEmpty) { | 584 if (!members.isEmpty) { |
| 576 libraryInfo[MEMBERS] = members; | 585 libraryInfo[MEMBERS] = members; |
| 577 } | 586 } |
| 578 | 587 |
| 579 final types = []; | 588 final types = []; |
| 580 for (InterfaceMirror type in orderByName(library.types.getValues())) { | 589 for (InterfaceMirror type in orderByName(library.types.getValues())) { |
| 581 if (!showPrivate && type.isPrivate) continue; | 590 if (!showPrivate && type.isPrivate) continue; |
| 582 | 591 |
| 583 var typeInfo = {}; | 592 var typeInfo = {}; |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 648 writeln( | 657 writeln( |
| 649 ''' | 658 ''' |
| 650 <div class="nav"> | 659 <div class="nav"> |
| 651 '''); | 660 '''); |
| 652 | 661 |
| 653 if (mode == MODE_STATIC) { | 662 if (mode == MODE_STATIC) { |
| 654 for (final library in _sortedLibraries) { | 663 for (final library in _sortedLibraries) { |
| 655 write('<h2><div class="icon-library"></div>'); | 664 write('<h2><div class="icon-library"></div>'); |
| 656 | 665 |
| 657 if ((_currentLibrary == library) && (_currentType == null)) { | 666 if ((_currentLibrary == library) && (_currentType == null)) { |
| 658 write('<strong>${library.simpleName}</strong>'); | 667 write('<strong>${displayName(library)}</strong>'); |
| 659 } else { | 668 } else { |
| 660 write('${a(libraryUrl(library), library.simpleName)}'); | 669 write('${a(libraryUrl(library), displayName(library))}'); |
| 661 } | 670 } |
| 662 write('</h2>'); | 671 write('</h2>'); |
| 663 | 672 |
| 664 // Only expand classes in navigation for current library. | 673 // Only expand classes in navigation for current library. |
| 665 if (_currentLibrary == library) docLibraryNavigation(library); | 674 if (_currentLibrary == library) docLibraryNavigation(library); |
| 666 } | 675 } |
| 667 } | 676 } |
| 668 | 677 |
| 669 writeln('</div>'); | 678 writeln('</div>'); |
| 670 } | 679 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 708 '<div class="icon-$icon"></div><strong>${typeName(type)}</strong>'); | 717 '<div class="icon-$icon"></div><strong>${typeName(type)}</strong>'); |
| 709 } else { | 718 } else { |
| 710 write(a(typeUrl(type), | 719 write(a(typeUrl(type), |
| 711 '<div class="icon-$icon"></div>${typeName(type)}')); | 720 '<div class="icon-$icon"></div>${typeName(type)}')); |
| 712 } | 721 } |
| 713 writeln('</li>'); | 722 writeln('</li>'); |
| 714 } | 723 } |
| 715 | 724 |
| 716 void docLibrary(LibraryMirror library) { | 725 void docLibrary(LibraryMirror library) { |
| 717 if (verbose) { | 726 if (verbose) { |
| 718 print('Library \'${library.simpleName}\':'); | 727 print('Library \'${displayName(library)}\':'); |
| 719 } | 728 } |
| 720 _totalLibraries++; | 729 _totalLibraries++; |
| 721 _currentLibrary = library; | 730 _currentLibrary = library; |
| 722 _currentType = null; | 731 _currentType = null; |
| 723 | 732 |
| 724 startFile(libraryUrl(library)); | 733 startFile(libraryUrl(library)); |
| 725 writeHeader('${library.simpleName} Library', | 734 writeHeader('${displayName(library)} Library', |
| 726 [library.simpleName, libraryUrl(library)]); | 735 [displayName(library), libraryUrl(library)]); |
| 727 writeln('<h2><strong>${library.simpleName}</strong> library</h2>'); | 736 writeln('<h2><strong>${displayName(library)}</strong> library</h2>'); |
| 728 | 737 |
| 729 // Look for a comment for the entire library. | 738 // Look for a comment for the entire library. |
| 730 final comment = getLibraryComment(library); | 739 final comment = getLibraryComment(library); |
| 731 if (comment != null) { | 740 if (comment != null) { |
| 732 writeln('<div class="doc">${comment.html}</div>'); | 741 writeln('<div class="doc">${comment.html}</div>'); |
| 733 } | 742 } |
| 734 | 743 |
| 735 // Document the top-level members. | 744 // Document the top-level members. |
| 736 docMembers(library); | 745 docMembers(library); |
| 737 | 746 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 806 } else if (type.isClass) { | 815 } else if (type.isClass) { |
| 807 if (type.isAbstract) { | 816 if (type.isAbstract) { |
| 808 kind = 'abstract class'; | 817 kind = 'abstract class'; |
| 809 } else { | 818 } else { |
| 810 kind = 'class'; | 819 kind = 'class'; |
| 811 } | 820 } |
| 812 } | 821 } |
| 813 | 822 |
| 814 final typeTitle = | 823 final typeTitle = |
| 815 '${typeName(type)} ${kind}'; | 824 '${typeName(type)} ${kind}'; |
| 816 writeHeader('$typeTitle / ${type.library.simpleName} Library', | 825 writeHeader('$typeTitle / ${displayName(type.library)} Library', |
| 817 [type.library.simpleName, libraryUrl(type.library), | 826 [displayName(type.library), libraryUrl(type.library), |
| 818 typeName(type), typeUrl(type)]); | 827 typeName(type), typeUrl(type)]); |
| 819 writeln( | 828 writeln( |
| 820 ''' | 829 ''' |
| 821 <h2><strong>${typeName(type, showBounds: true)}</strong> | 830 <h2><strong>${typeName(type, showBounds: true)}</strong> |
| 822 $kind | 831 $kind |
| 823 </h2> | 832 </h2> |
| 824 '''); | 833 '''); |
| 825 writeln('<button id="show-inherited" class="show-inherited">' | 834 writeln('<button id="show-inherited" class="show-inherited">' |
| 826 'Hide inherited</button>'); | 835 'Hide inherited</button>'); |
| 827 | 836 |
| (...skipping 677 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1505 /** Gets whether or not the given URL is absolute or relative. */ | 1514 /** Gets whether or not the given URL is absolute or relative. */ |
| 1506 bool isAbsolute(String url) { | 1515 bool isAbsolute(String url) { |
| 1507 // TODO(rnystrom): Why don't we have a nice type in the platform for this? | 1516 // TODO(rnystrom): Why don't we have a nice type in the platform for this? |
| 1508 // TODO(rnystrom): This is a bit hackish. We consider any URL that lacks | 1517 // TODO(rnystrom): This is a bit hackish. We consider any URL that lacks |
| 1509 // a scheme to be relative. | 1518 // a scheme to be relative. |
| 1510 return const RegExp(r'^\w+:').hasMatch(url); | 1519 return const RegExp(r'^\w+:').hasMatch(url); |
| 1511 } | 1520 } |
| 1512 | 1521 |
| 1513 /** Gets the URL to the documentation for [library]. */ | 1522 /** Gets the URL to the documentation for [library]. */ |
| 1514 String libraryUrl(LibraryMirror library) { | 1523 String libraryUrl(LibraryMirror library) { |
| 1515 return '${sanitize(library.simpleName)}.html'; | 1524 return '${sanitize(displayName(library))}.html'; |
| 1516 } | 1525 } |
| 1517 | 1526 |
| 1518 /** Gets the URL for the documentation for [type]. */ | 1527 /** Gets the URL for the documentation for [type]. */ |
| 1519 String typeUrl(ObjectMirror type) { | 1528 String typeUrl(ObjectMirror type) { |
| 1520 if (type is LibraryMirror) { | 1529 if (type is LibraryMirror) { |
| 1521 return '${sanitize(type.simpleName)}.html'; | 1530 return '${sanitize(type.simpleName)}.html'; |
| 1522 } | 1531 } |
| 1523 assert (type is TypeMirror); | 1532 assert (type is TypeMirror); |
| 1524 // Always get the generic type to strip off any type parameters or | 1533 // Always get the generic type to strip off any type parameters or |
| 1525 // arguments. If the type isn't generic, genericType returns `this`, so it | 1534 // arguments. If the type isn't generic, genericType returns `this`, so it |
| 1526 // works for non-generic types too. | 1535 // works for non-generic types too. |
| 1527 return '${sanitize(type.library.simpleName)}/' | 1536 return '${sanitize(displayName(type.library))}/' |
| 1528 '${type.declaration.simpleName}.html'; | 1537 '${type.declaration.simpleName}.html'; |
| 1529 } | 1538 } |
| 1530 | 1539 |
| 1531 /** Gets the URL for the documentation for [member]. */ | 1540 /** Gets the URL for the documentation for [member]. */ |
| 1532 String memberUrl(MemberMirror member) { | 1541 String memberUrl(MemberMirror member) { |
| 1533 String url = typeUrl(member.surroundingDeclaration); | 1542 String url = typeUrl(member.surroundingDeclaration); |
| 1534 return '$url#${memberAnchor(member)}'; | 1543 return '$url#${memberAnchor(member)}'; |
| 1535 } | 1544 } |
| 1536 | 1545 |
| 1537 /** Gets the anchor id for the document for [member]. */ | 1546 /** Gets the anchor id for the document for [member]. */ |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1848 final InterfaceMirror inheritedFrom; | 1857 final InterfaceMirror inheritedFrom; |
| 1849 | 1858 |
| 1850 DocComment(this.text, [this.inheritedFrom = null]) { | 1859 DocComment(this.text, [this.inheritedFrom = null]) { |
| 1851 assert(text != null && !text.trim().isEmpty); | 1860 assert(text != null && !text.trim().isEmpty); |
| 1852 } | 1861 } |
| 1853 | 1862 |
| 1854 String get html => md.markdownToHtml(text); | 1863 String get html => md.markdownToHtml(text); |
| 1855 | 1864 |
| 1856 String toString() => text; | 1865 String toString() => text; |
| 1857 } | 1866 } |
| OLD | NEW |