Skip to content

Commit 8ab57b6

Browse files
committed
implement a --use-categories option
1 parent f2874b0 commit 8ab57b6

19 files changed

+237
-105
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
## unreleased
22
* [enhancement] added a `--favicon` option to specify a favicon to use for the
33
generated docs
4+
* [enhancement] added a `--use-categories` flag to groups libraries into source
5+
packages in the overview page and the left-hand side navigation panel
46

57
## 0.9.3+1
68
* [bug] fix an issue with including duplicated libraries

bin/dartdoc.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ main(List<String> arguments) async {
116116

117117
var generators = await initGenerators(
118118
url, headerFilePaths, footerFilePaths, args['rel-canonical-prefix'],
119-
faviconPath: args['favicon']);
119+
faviconPath: args['favicon'], useCategories: args['use-categories']);
120120

121121
for (var generator in generators) {
122122
generator.onFileCreated.listen(_onProgress);
@@ -207,6 +207,10 @@ ArgParser _createArgsParser() {
207207
help: 'Show source code blocks', negatable: true, defaultsTo: true);
208208
parser.addOption('favicon',
209209
help: 'A path to a favicon for the generated docs');
210+
parser.addFlag('use-categories',
211+
help: 'Group libraries from the same package into categories',
212+
negatable: false,
213+
defaultsTo: false);
210214
return parser;
211215
}
212216

lib/dartdoc.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,16 @@ final String defaultOutDir = p.join('doc', 'api');
4646
/// Initialize and setup the generators.
4747
Future<List<Generator>> initGenerators(String url, List<String> headerFilePaths,
4848
List<String> footerFilePaths, String relCanonicalPrefix,
49-
{String faviconPath}) async {
49+
{String faviconPath, bool useCategories: false}) async {
5050
return [
5151
await HtmlGenerator.create(
5252
url: url,
5353
headers: headerFilePaths,
5454
footers: footerFilePaths,
5555
relCanonicalPrefix: relCanonicalPrefix,
5656
toolVersion: version,
57-
faviconPath: faviconPath)
57+
faviconPath: faviconPath,
58+
useCategories: useCategories)
5859
];
5960
}
6061

lib/src/html/html_generator.dart

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class HtmlGenerator extends Generator {
4040
final Templates _templates;
4141
final String _toolVersion;
4242
final String faviconPath;
43+
final bool useCategories;
4344

4445
final StreamController<File> _onFileCreated =
4546
new StreamController(sync: true);
@@ -53,7 +54,8 @@ class HtmlGenerator extends Generator {
5354
List<String> footers,
5455
String relCanonicalPrefix,
5556
String toolVersion,
56-
String faviconPath}) async {
57+
String faviconPath,
58+
bool useCategories: false}) async {
5759
var templates =
5860
await Templates.create(headerPaths: headers, footerPaths: footers);
5961

@@ -62,17 +64,17 @@ class HtmlGenerator extends Generator {
6264
}
6365

6466
return new HtmlGenerator._(url, relCanonicalPrefix, templates, toolVersion,
65-
faviconPath: faviconPath);
67+
faviconPath: faviconPath, useCategories: useCategories);
6668
}
6769

6870
HtmlGenerator._(
6971
this._url, this._relCanonicalPrefix, this._templates, this._toolVersion,
70-
{this.faviconPath});
72+
{this.faviconPath, this.useCategories});
7173

7274
Future generate(Package package, Directory out) {
7375
return new HtmlGeneratorInstance(_toolVersion, _url, _templates, package,
7476
out, _onFileCreated, _relCanonicalPrefix,
75-
faviconPath: faviconPath)
77+
faviconPath: faviconPath, useCategories: useCategories)
7678
.generate();
7779
}
7880
}

lib/src/html/html_generator_instance.dart

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,11 @@ class HtmlGeneratorInstance implements HtmlOptions {
2525
final String relCanonicalPrefix;
2626
final String toolVersion;
2727
final String faviconPath;
28+
final bool useCategories;
2829

2930
HtmlGeneratorInstance(this.toolVersion, this.url, this._templates,
3031
this.package, this.out, this._onFileCreated, this.relCanonicalPrefix,
31-
{this.faviconPath});
32+
{this.faviconPath, this.useCategories});
3233

3334
Future generate() async {
3435
if (!out.existsSync()) out.createSync();
@@ -134,7 +135,7 @@ class HtmlGeneratorInstance implements HtmlOptions {
134135
void generatePackage() {
135136
stdout.write('documenting ${package.name}');
136137

137-
TemplateData data = new PackageTemplateData(this, package);
138+
TemplateData data = new PackageTemplateData(this, package, useCategories);
138139

139140
_build('index.html', _templates.indexTemplate, data);
140141
}
@@ -148,7 +149,8 @@ class HtmlGeneratorInstance implements HtmlOptions {
148149
"documentation comments");
149150
}
150151

151-
TemplateData data = new LibraryTemplateData(this, package, lib);
152+
TemplateData data =
153+
new LibraryTemplateData(this, package, lib, useCategories);
152154

153155
_build(path.join(lib.dirName, '${lib.fileName}'),
154156
_templates.libraryTemplate, data);

lib/src/html/template_data.dart

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,12 @@ abstract class TemplateData<T extends Documentable> {
6868
}
6969

7070
class PackageTemplateData extends TemplateData<Package> {
71-
PackageTemplateData(HtmlOptions htmlOptions, Package package)
71+
PackageTemplateData(
72+
HtmlOptions htmlOptions, Package package, this.useCategories)
7273
: super(htmlOptions, package);
7374

7475
bool get includeVersion => true;
76+
final bool useCategories;
7577
List get navLinks => [];
7678
String get title => '${package.name} - Dart API docs';
7779
Package get self => package;
@@ -90,11 +92,13 @@ class PackageTemplateData extends TemplateData<Package> {
9092
class LibraryTemplateData extends TemplateData<Library> {
9193
final Library library;
9294

93-
LibraryTemplateData(HtmlOptions htmlOptions, Package package, this.library)
95+
LibraryTemplateData(HtmlOptions htmlOptions, Package package, this.library,
96+
this.useCategories)
9497
: super(htmlOptions, package);
9598

9699
String get title => '${library.name} library - Dart API';
97100
String get documentation => library.documentation;
101+
final bool useCategories;
98102
String get htmlBase => '..';
99103
String get metaDescription =>
100104
'${library.name} library API docs, for the Dart programming language.';

lib/src/model.dart

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
library dartdoc.models;
77

88
import 'dart:convert';
9+
import 'dart:io';
910

1011
import 'package:analyzer/dart/ast/ast.dart'
1112
show AnnotatedNode, Annotation, Declaration;
@@ -16,6 +17,7 @@ import 'package:analyzer/src/generated/resolver.dart'
1617
import 'package:analyzer/src/generated/source_io.dart';
1718
import 'package:analyzer/src/generated/utilities_dart.dart' show ParameterKind;
1819
import 'package:collection/collection.dart';
20+
import 'package:path/path.dart' as p;
1921
import 'package:quiver/core.dart' show hash3;
2022

2123
import 'config.dart';
@@ -921,6 +923,7 @@ class Library extends ModelElement {
921923
List<TopLevelVariable> _variables;
922924
Namespace _exportedNamespace;
923925
String _name;
926+
String _packageName;
924927

925928
factory Library(LibraryElement element, Package package) {
926929
String key = element == null ? 'null' : element.name;
@@ -1020,6 +1023,21 @@ class Library extends ModelElement {
10201023
@override
10211024
String get href => '$dirName/$fileName';
10221025

1026+
String get packageName {
1027+
if (_packageName == null) {
1028+
String sourcePath = _library.source.fullName;
1029+
File file = new File(sourcePath);
1030+
if (file.existsSync()) {
1031+
_packageName = _getPackageName(file.parent);
1032+
if (_packageName == null) _packageName = '';
1033+
} else {
1034+
_packageName = '';
1035+
}
1036+
}
1037+
1038+
return _packageName;
1039+
}
1040+
10231041
bool get isAnonymous => element.name == null || element.name.isEmpty;
10241042

10251043
bool get isDocumented => oneLineDoc.isNotEmpty;
@@ -1143,6 +1161,20 @@ class Library extends ModelElement {
11431161

11441162
return _variables;
11451163
}
1164+
1165+
static String _getPackageName(Directory dir) {
1166+
if (!dir.existsSync() || !dir.path.contains(Platform.pathSeparator)) {
1167+
return null;
1168+
}
1169+
1170+
File pubspec = new File(p.join(dir.path, 'pubspec.yaml'));
1171+
if (pubspec.existsSync()) {
1172+
PackageMeta meta = new PackageMeta.fromDir(dir);
1173+
return meta.name;
1174+
} else {
1175+
return _getPackageName(dir.parent);
1176+
}
1177+
}
11461178
}
11471179

11481180
class Method extends ModelElement
@@ -1718,6 +1750,25 @@ class Package implements Nameable, Documentable {
17181750

17191751
List<Library> get libraries => _libraries;
17201752

1753+
List<PackageCategory> get categories {
1754+
Map<String, PackageCategory> result = {};
1755+
1756+
for (Library library in _libraries) {
1757+
String name = '';
1758+
1759+
if (library.name.startsWith('dart:')) {
1760+
name = 'Dart Core';
1761+
} else {
1762+
name = library.packageName;
1763+
}
1764+
1765+
if (!result.containsKey(name)) result[name] = new PackageCategory(name);
1766+
result[name]._libraries.add(library);
1767+
}
1768+
1769+
return result.values.toList()..sort();
1770+
}
1771+
17211772
String get name => packageMeta.name;
17221773

17231774
String get oneLineDoc => '';
@@ -1780,6 +1831,17 @@ class Package implements Nameable, Documentable {
17801831
}
17811832
}
17821833

1834+
class PackageCategory implements Comparable {
1835+
final String name;
1836+
final List<Library> _libraries = [];
1837+
1838+
PackageCategory(this.name);
1839+
1840+
List<Library> get libraries => _libraries;
1841+
1842+
int compareTo(PackageCategory other) => name.compareTo(other.name);
1843+
}
1844+
17831845
class Parameter extends ModelElement implements EnclosedElement {
17841846
Parameter(ParameterElement element, Library library)
17851847
: super(element, library) {

lib/templates/index.html

Lines changed: 48 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,38 +3,67 @@
33
<div class="col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left">
44
<h5>{{self.name}}</h5>
55

6+
{{#useCategories}}
7+
<ol>
8+
{{#package.categories}}
9+
<li class="section-title">{{name}}</li>
10+
{{#libraries}}
11+
<li>{{{linkedName}}}</li>
12+
{{/libraries}}
13+
{{/package.categories}}
14+
15+
</ol>
16+
{{/useCategories}}
17+
18+
{{^useCategories}}
619
<ol>
720
<li class="section-title"><a href="{{package.href}}#libraries">Libraries</a></li>
821
{{#package.libraries}}
922
<li>{{{linkedName}}}</li>
1023
{{/package.libraries}}
1124
</ol>
25+
{{/useCategories}}
1226
</div>
1327

1428
<div class="col-xs-12 col-sm-9 col-md-8 main-content">
15-
1629
{{#package}}
1730
{{>documentation}}
1831
{{/package}}
1932

20-
<section class="summary" id="libraries">
21-
<h2>Libraries</h2>
22-
<dl>
23-
{{#package.libraries}}
24-
<dt id="{{htmlId}}">
25-
<span class="name">{{{ linkedName }}}</span>
26-
</dt>
27-
<dd>
28-
{{#isDocumented}}
29-
<p>
30-
{{{ oneLineDoc }}}
31-
{{>has_more_docs}}
32-
</p>
33-
{{/isDocumented}}
34-
</dd>
35-
{{/package.libraries}}
36-
</dl>
37-
</section>
33+
{{#useCategories}}
34+
{{#package.categories}}
35+
<section class="summary">
36+
<h2>{{name}}</h2>
37+
<dl>
38+
{{#libraries}}
39+
<dt id="{{htmlId}}">
40+
<span class="name">{{{ linkedName }}}</span>
41+
</dt>
42+
<dd>
43+
{{#isDocumented}}<p>{{{ oneLineDoc }}}</p>{{/isDocumented}}
44+
</dd>
45+
{{/libraries}}
46+
</dl>
47+
</section>
48+
{{/package.categories}}
49+
50+
{{/useCategories}}
51+
52+
{{^useCategories}}
53+
<section class="summary" id="libraries">
54+
<h2>Libraries</h2>
55+
<dl>
56+
{{#package.libraries}}
57+
<dt id="{{htmlId}}">
58+
<span class="name">{{{ linkedName }}}</span>
59+
</dt>
60+
<dd>
61+
{{#isDocumented}}<p>{{{ oneLineDoc }}}</p>{{/isDocumented}}
62+
</dd>
63+
{{/package.libraries}}
64+
</dl>
65+
</section>
66+
{{/useCategories}}
3867

3968
</div> <!-- /.main-content -->
4069

lib/templates/library.html

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,26 @@
55
<h5><a href="{{href}}">{{name}}</a></h5>
66
{{/navLinks}}
77

8+
{{#useCategories}}
89
<ol>
9-
<li class="section-title"><a href="index.html">Libraries</a></li>
10+
{{#package.categories}}
11+
<li class="section-title">{{name}}</li>
12+
{{#libraries}}
13+
<li>{{{linkedName}}}</li>
14+
{{/libraries}}
15+
{{/package.categories}}
16+
17+
</ol>
18+
{{/useCategories}}
19+
20+
{{^useCategories}}
21+
<ol>
22+
<li class="section-title"><a href="{{package.href}}#libraries">Libraries</a></li>
1023
{{#package.libraries}}
1124
<li>{{{linkedName}}}</li>
1225
{{/package.libraries}}
1326
</ol>
27+
{{/useCategories}}
1428
</div>
1529

1630
<div class="col-xs-12 col-sm-9 col-md-8 main-content">

test/model_test.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ void main() {
4747
expect(package.libraries, hasLength(6));
4848
});
4949

50+
test('categories', () {
51+
expect(package.categories, hasLength(1));
52+
53+
PackageCategory category = package.categories.first;
54+
expect(category.name, 'test_package');
55+
expect(category.libraries, hasLength(6));
56+
});
57+
5058
test('is documented in library', () {
5159
expect(package.isDocumented(exLibrary.element), isTrue);
5260
});
@@ -121,6 +129,10 @@ void main() {
121129
expect(exLibrary.name, 'ex');
122130
});
123131

132+
test('packageName', () {
133+
expect(exLibrary.packageName, 'test_package');
134+
});
135+
124136
test('has a fully qualified name', () {
125137
expect(exLibrary.fullyQualifiedName, 'ex');
126138
});

0 commit comments

Comments
 (0)