diff --git a/README.md b/README.md index 9f6224722d..21d0a8aeda 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Run `pub global activate dartdoc` to install `dartdoc`. ## Running dartdoc Run `dartdoc` from the root directory of package. By default, the documentation -is geterated to the `doc/api/` directory. +is generated to the `doc/api/` directory. ## FAQ @@ -31,16 +31,16 @@ the issue tracker, start by opening an issue. Thanks! #### What does the output look like? -You can see the latest API of `dartdoc`, generated by `dartdoc`, +You can see the latest API of `dartdoc` - generated by `dartdoc` - [here](https://dartdoc.firebaseapp.com). #### Generating documentation for Dart SDK -If you want to generatr documentation for the SDK, run `dartdoc` with the +If you want to generate documentation for the SDK, run `dartdoc` with the following command line arguments: -- `--dart-sdk /pathTo/dart-sdk` (optional) - `--sdk-docs` +- `--dart-sdk /pathTo/dart-sdk` (optional) ## Issues and bugs diff --git a/bin/dartdoc.dart b/bin/dartdoc.dart index e509ea6966..50511cf845 100644 --- a/bin/dartdoc.dart +++ b/bin/dartdoc.dart @@ -87,7 +87,7 @@ main(List arguments) async { : new PackageMeta.fromDir(inputDir); print("Generating documentation for '${packageMeta}' into " - "${outputDir.absolute.path}${Platform.pathSeparator}."); + "${outputDir.absolute.path}${Platform.pathSeparator}"); print(''); var generators = initGenerators(url, headerFilePath, footerFilePath); diff --git a/lib/dartdoc.dart b/lib/dartdoc.dart index 430be19c8e..a5e7d5118b 100644 --- a/lib/dartdoc.dart +++ b/lib/dartdoc.dart @@ -2,6 +2,7 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +/// A documentation generator for Dart. library dartdoc; import 'dart:async'; @@ -23,6 +24,9 @@ import 'src/model.dart'; import 'src/model_utils.dart'; import 'src/package_meta.dart'; +export 'src/model.dart'; +export 'src/package_meta.dart'; + const String name = 'dartdoc'; // Update when pubspec version changes. const String version = '0.0.2+3'; @@ -55,10 +59,12 @@ class DartDoc { DartDoc(this.rootDir, this.excludes, this.sdkDir, this.generators, this.outputDir, this.packageRootDir, this.packageMeta); - /// Generate the documentation. [DartDocResults] is returned if dartdoc - /// succeeds. [DartDocFailure] is thrown if dartdoc fails in an expected way, - /// for instance if there is an anaysis error in the code. Any other exception - /// can be throw if there is an unexpected failure. + /// Generate DartDoc documentation. + /// + /// [DartDocResults] is returned if dartdoc succeeds. [DartDocFailure] is + /// thrown if dartdoc fails in an expected way, for example if there is an + /// anaysis error in the code. Any other exception can be throw if there is an + /// unexpected failure. Future generateDocs() async { _stopwatch = new Stopwatch()..start(); @@ -168,6 +174,7 @@ class DartDoc { } } +/// The results of a [DartDoc.generateDocs] call. class DartDocResults { final PackageMeta packageMeta; final Package package; diff --git a/lib/generator.dart b/lib/generator.dart index efa063fa34..1859d023cb 100644 --- a/lib/generator.dart +++ b/lib/generator.dart @@ -11,7 +11,9 @@ import 'dart:io'; import 'src/model.dart' show Package; /// An abstract class that defines a generator that generates documentation for -/// a given package. Generators can generate documentation in different formats: +/// a given package. +/// +/// Generators can generate documentation in different formats: /// html, json etc. abstract class Generator { /// Generate the documentation for the given package in the specified diff --git a/lib/markdown_processor.dart b/lib/markdown_processor.dart index a82e9769af..2fafea2f15 100644 --- a/lib/markdown_processor.dart +++ b/lib/markdown_processor.dart @@ -2,7 +2,8 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -library markdown_processor; +/// Utility code to convert markdown comments to html. +library dartdoc.markdown_processor; import 'package:analyzer/src/generated/ast.dart'; import 'package:analyzer/src/generated/element.dart' @@ -95,10 +96,6 @@ String oneLinerWithoutReferences(String text) { if (blocks.isEmpty) return ''; String firstPara = new PlainTextRenderer().render([blocks.first]); - if (firstPara.length > 200) { - firstPara = firstPara.substring(0, 200) + '...'; - } - return firstPara.trim(); } diff --git a/lib/resource_loader.dart b/lib/resource_loader.dart index ccd6c889ec..db3bfbb079 100644 --- a/lib/resource_loader.dart +++ b/lib/resource_loader.dart @@ -2,11 +2,15 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -/// Attempts to make it possible to load resources, independent of how the Dart -/// app is run. +// TODO: Consider making this a stand-alone package, if useful. + +/// Make it possible to load resources, independent of how the Dart app is run. +/// +/// Future getTemplateFile(String templatePath) { +/// return loadAsString('package:dartdoc/templates/$templatePath'); +/// } /// -/// TODO: consider making this a stand-alone package, if useful -library resource_loader; +library dartdoc.resource_loader; import 'dart:async' show Future; import 'dart:io' show Platform, File, Directory; diff --git a/lib/resources/styles.css b/lib/resources/styles.css index d1f6ea582c..6f46867696 100644 --- a/lib/resources/styles.css +++ b/lib/resources/styles.css @@ -1,32 +1,41 @@ -/* - -Colors -Palette generated by Material Palette - materialpalette.com/cyan/teal +/* Palette generated by Material Palette - materialpalette.com/blue-grey/light-blue */ -.dark-primary-color { background: #0097A7; } -.default-primary-color { background: #00BCD4; } -.light-primary-color { background: #B2EBF2; } +.dark-primary-color { background: #455A64; } +.default-primary-color { background: #607D8B; } +.light-primary-color { background: #CFD8DC; } .text-primary-color { color: #FFFFFF; } -.accent-color { background: #009688; } +.accent-color { background: #03A9F4; } .primary-text-color { color: #212121; } .secondary-text-color { color: #727272; } .divider-color { border-color: #B6B6B6; } +/* + Palette generated by Material Palette - materialpalette.com/cyan/teal + + .dark-primary-color { background: #0097A7; } + .default-primary-color { background: #00BCD4; } + .light-primary-color { background: #B2EBF2; } + .text-primary-color { color: #FFFFFF; } + .accent-color { background: #009688; } + .primary-text-color { color: #212121; } + .secondary-text-color { color: #727272; } + .divider-color { border-color: #B6B6B6; } */ html { - position:relative; - min-height:100%; + position: relative; + min-height: 100%; } body { font-family: 'Roboto', sans-serif; - font-size: 14px; + font-size: 15px; padding-top: 50px; margin-bottom: 60px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: 100%; + overflow-x: hidden; } /* some of this is to reset bootstrap */ @@ -42,17 +51,14 @@ nav.navbar { -webkit-justify-content: center; } -@media(max-width: 768px) -{ - nav .container { - width: 100% - } -} - header { - background-color: #00BCD4; - height: 200px; + background-color: #607D8B; color: white; + box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.37); +} + +header.header-fixed nav.navbar-fixed-top { + box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.37); } header.container-fluid { @@ -63,31 +69,60 @@ dl { margin: 0; } -h1, h2, h3, h4, h5, h6 { - font-weight: 300; +h1, +h2, +h3, +h4, +h5, +h6 { + font-weight: normal; margin: 0; } +h1.title { + overflow: hidden; + text-overflow: ellipsis; +} + h2 { font-size: 32px; } +.subtitle { + font-size: 17px; + min-height: 1.4em; +} + +.title-description .subtitle { + white-space: nowrap; + overflow-x: hidden; + text-overflow: ellipsis; +} + p { - margin-bottom: 8px; + margin-bottom: 1em; +} + +p, +ul, +li { + color: #727272; } a { - color: #0097A7; + color: #455A64; } pre { font-family: 'Source Code Pro', monospace; color: black; - border-radius: 0; - font-size: 12px; - width: 80ch; + border-radius: 4px; + font-size: 14px; word-wrap: normal; line-height: 1.4; + border: 1px solid #f0f0f0; + margin: 16px; + padding: 8px; } pre code { @@ -101,31 +136,57 @@ pre code { code { font-family: 'Source Code Pro', monospace; /* overriding bootstrap */ - font-size: inherit; + font-size: 14px; color: inherit; border-radius: 0; padding: 0; background-color: inherit; } -@media (min-width:970px) and (max-width: 2500px) { +@media (min-width: 970px) and (max-width: 2500px) { .container { - width:768px; + width: 768px; + } +} + +@media(max-width: 768px) { + nav .container { + width: 100% + } + + h1 { + font-size: 24px; + } + + pre { + margin: 16px 0; + } +} + +@media (min-width: 768px) { + .dl-horizontal dd { + margin-left: 128px; + } + + .dl-horizontal dt { + width: 128px; } } header h1 { - margin-top: 80px; + margin-top: 64px; font-weight: 400; } -header a { +header a, +header p, +header li { color: white; } -header h1 .kind { +/*header h1 .kind { font-weight: 300; -} +}*/ dt { font-weight: normal; @@ -138,7 +199,19 @@ dd { section.summary h2 { color: hsl(0, 0%, 46%); - margin-bottom: 32px; + margin-bottom: 16px; + border-bottom: 1px solid #B6B6B6; +} + +section.summary dd { + white-space: nowrap; + overflow-x: hidden; + text-overflow: ellipsis; +} + +section.summary dt { + margin-left: 24px; + text-indent: -24px; } dl.dl-horizontal dt { @@ -147,17 +220,7 @@ dl.dl-horizontal dt { } dt .name { - font-size: 16px; -} - -@media (min-width: 768px) { - .dl-horizontal dd { - margin-left: 320px; - } - - .dl-horizontal dt { - width: 320px; - } + font-size: 17px; } dl dt.callable .name { @@ -165,6 +228,10 @@ dl dt.callable .name { width: auto; } +.parameter { + white-space: nowrap; +} + .signature a { color: rgb(51, 51, 51); } @@ -173,6 +240,10 @@ dl dt.callable .name { font-style: italic; } +.undocumented { + font-style: italic; +} + .deprecated { text-decoration: line-through; } @@ -182,18 +253,31 @@ p.firstline { } footer { - background-color: #B6B6B6; padding: 20px; - position:absolute; - bottom:0; - width:100%; - height:60px; + position: absolute; + bottom: 0; + width: 100%; + height: 60px; } footer p { margin: 0; } +footer .no-break { + white-space: nowrap; +} + +footer .container, +footer .container-fluid { + padding-left: 0; + padding-right: 0; +} + +.copyright a { + color: #727272; +} + .markdown h1 { font-size: 24px; margin-bottom: 8px; @@ -201,6 +285,7 @@ footer p { .markdown h2 { font-size: 20px; + margin-top: 24px; margin-bottom: 8px; } @@ -211,7 +296,11 @@ footer p { .markdown h4 { font-size: 16px; - margin-bottom: 8px; + margin-bottom: 0; +} + +.markdown li p { + margin: 0; } .gt-separated { @@ -225,7 +314,7 @@ footer p { } .gt-separated li:after { - content: " > "; + content: " → "; } .gt-separated li:last-child:after { @@ -237,26 +326,41 @@ footer p { } .multi-line-signature { - font-size: 18px; + font-size: 17px; } .breadcrumbs { - padding: 0; - margin: 8px 0 8px 0; + padding: 0; + margin: 8px 0 8px 0; + font-size: 17px; +} + +.annotation-list { + list-style: none; + padding: 0; + display: inline; +} + +.annotation-list li { + display: inline; +} + +.annotation-list li:before { + content: "@"; } .comma-separated { - list-style: none; - padding: 0; - display: inline; + list-style: none; + padding: 0; + display: inline; } .comma-separated li { - display: inline; + display: inline; } .comma-separated li:after { - content: ", "; + content: ", "; } .comma-separated li:last-child:after { @@ -264,14 +368,11 @@ footer p { } .end-with-period li:last-child:after { - content: "."; + content: "."; } - section { - margin-bottom: 64px; - padding-top: 64px; - border-top: 1px solid #eeeeee; + padding-top: 32px; } .container > section:first-child { @@ -287,5 +388,5 @@ section { } section.multi-line-signature div.parameters { - margin-left: 16px; + margin-left: 24px; } diff --git a/lib/src/html_generator.dart b/lib/src/html_generator.dart index fad8d808d7..e66b925688 100644 --- a/lib/src/html_generator.dart +++ b/lib/src/html_generator.dart @@ -15,7 +15,7 @@ import 'model.dart'; import 'package_meta.dart'; import '../generator.dart'; import '../markdown_processor.dart'; -import '../resources.g.dart' show resource_names; +import 'resources.g.dart' as resources; import '../resource_loader.dart' as loader; typedef String TemplateRenderer(context, @@ -203,7 +203,6 @@ class HtmlGeneratorInstance { Map data = { 'package': package, 'documentation': package.documentation, - 'oneLineDoc': package.oneLineDoc, 'title': '${package.name} - Dart API docs', 'layoutTitle': _layoutTitle(package.name, package.isSdk ? '' : 'package'), 'metaDescription': @@ -478,7 +477,7 @@ class HtmlGeneratorInstance { // TODO: change this to use resource_loader Future _copyResources() async { final prefix = 'package:dartdoc/resources/'; - for (var resourcePath in resource_names) { + for (var resourcePath in resources.resource_names) { if (!resourcePath.startsWith(prefix)) { throw new StateError( 'Resource paths must start with $prefix, encountered $resourcePath'); diff --git a/lib/src/model.dart b/lib/src/model.dart index dc2e0ed75f..357e5c8bdc 100644 --- a/lib/src/model.dart +++ b/lib/src/model.dart @@ -45,7 +45,7 @@ void _addToImplementors(Class c) { } } -abstract class ModelElement { +abstract class ModelElement implements Comparable { final Element element; final Library library; @@ -98,6 +98,14 @@ abstract class ModelElement { throw "Unknown type ${e.runtimeType}"; } + int compareTo(dynamic other) { + if (other is ModelElement) { + return name.toLowerCase().compareTo(other.name.toLowerCase()); + } else { + return 0; + } + } + String get documentation { if (_documentation != null) { return _documentation; @@ -383,9 +391,13 @@ class Package { Library._libraryMap.putIfAbsent(lib.name, () => lib); _libraries.add(lib); }); + _libraries.forEach((library) { library._allClasses.forEach(_addToImplementors); }); + + _libraries.sort(); + _implementors.values.forEach((l) => l.sort()); } /// Does this package represent the SDK? @@ -499,6 +511,8 @@ class Library extends ModelElement { bool get isInSdk => _library.isInSdk; + bool get isNotDocumented => oneLineDoc.isEmpty; + List _getVariables() { if (_variables != null) return _variables; @@ -738,6 +752,8 @@ class Class extends ModelElement { return typeChain; } + List get superChainReversed => superChain.reversed.toList(); + List get mixins => _mixins; bool get hasMixins => mixins.isNotEmpty; @@ -748,7 +764,7 @@ class Class extends ModelElement { /// Returns all the implementors of the class specified. List get implementors => - _implementors[this] != null ? _implementors[this] : new List(0); + _implementors[this] != null ? _implementors[this] : []; bool get hasImplementors => implementors.isNotEmpty; diff --git a/lib/resources.g.dart b/lib/src/resources.g.dart similarity index 100% rename from lib/resources.g.dart rename to lib/src/resources.g.dart diff --git a/lib/templates/_callable.html b/lib/templates/_callable.html index 8beec23e6f..93ce7be23b 100644 --- a/lib/templates/_callable.html +++ b/lib/templates/_callable.html @@ -1,11 +1,10 @@
- {{>name_summary}} - {{#isInherited}}Inherited{{/isInherited}} - ( {{{ linkedParamsNoMetadata }}} ) + {{>name_summary}}({{{ linkedParamsNoMetadata }}}) → {{{ linkedReturnType }}} + {{#isInherited}}Inherited{{/isInherited}}
{{{ oneLineDoc }}} -
\ No newline at end of file + diff --git a/lib/templates/_footer.html b/lib/templates/_footer.html index fcbe63f8aa..82e0658a0f 100644 --- a/lib/templates/_footer.html +++ b/lib/templates/_footer.html @@ -3,11 +3,13 @@