blob: b26c17d0cb54947bc5c03d26f6bad72d8c9aac02 [file] [log] [blame]
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// 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.
import 'package:collection/collection.dart';
import 'package:dartdoc/src/model/model.dart';
final RegExp _categoryRegExp = RegExp(
r'[ ]*{@(api|category|subCategory|image|samples) (.+?)}[ ]*\n?',
multiLine: true);
/// Mixin parsing the `@category` directive for ModelElements.
mixin Categorization on DocumentationComment implements Indexable {
@override
String buildDocumentationAddition(String rawDocs) =>
_stripAndSetDartdocCategories(super.buildDocumentationAddition(rawDocs));
/// Parse `{@category ...}` and related information in API comments, stripping
/// out that information from the given comments and returning the stripped
/// version.
String _stripAndSetDartdocCategories(String rawDocs) {
var categorySet = <String>{};
var subCategorySet = <String>{};
_hasCategorization = false;
rawDocs = rawDocs.replaceAllMapped(_categoryRegExp, (match) {
_hasCategorization = true;
switch (match[1]) {
case 'category':
case 'api':
categorySet.add(match[2]!.trim());
break;
case 'subCategory':
subCategorySet.add(match[2]!.trim());
break;
case 'image':
_image = match[2]!.trim();
break;
case 'samples':
_samples = match[2]!.trim();
break;
}
return '';
});
_categoryNames = categorySet.toList(growable: false)..sort();
_subCategoryNames = subCategorySet.toList(growable: false)..sort();
_image ??= '';
_samples ??= '';
return rawDocs;
}
bool get hasSubCategoryNames => subCategoryNames?.isNotEmpty ?? false;
List<String>? _subCategoryNames;
/// Either a set of strings containing all declared subcategories for this symbol,
/// or 'null' if none were declared.
List<String>? get subCategoryNames {
// TODO(jcollins-g): avoid side-effect dependency
if (_subCategoryNames == null) documentationLocal;
return _subCategoryNames;
}
bool get hasCategoryNames => categoryNames?.isNotEmpty ?? false;
List<String>? _categoryNames;
/// Either a set of strings containing all declared categories for this symbol,
/// or 'null' if none were declared.
List<String>? get categoryNames {
// TODO(jcollins-g): avoid side-effect dependency
if (_categoryNames == null) documentationLocal;
return _categoryNames;
}
bool get hasImage => image!.isNotEmpty;
String? _image;
/// Either a URI to a defined image,
/// or 'null' if one was not declared.
String? get image {
// TODO(jcollins-g): avoid side-effect dependency
if (_image == null) documentationLocal;
return _image;
}
bool get hasSamples => samples?.isNotEmpty ?? false;
String? _samples;
/// Either a URI to documentation with samples,
/// or 'null' if one was not declared.
String? get samples {
// TODO(jcollins-g): avoid side-effect dependency
if (_samples == null) documentationLocal;
return _samples;
}
late final Iterable<Category> categories = [
...?categoryNames?.map((n) => package.nameToCategory[n]).whereNotNull()
]..sort();
Iterable<Category> get displayedCategories {
if (config.showUndocumentedCategories) return categories;
return categories.where((c) => c.isDocumented);
}
bool? _hasCategorization;
/// True if categories, subcategories, a documentation icon, or samples were
/// declared.
late final bool hasCategorization = () {
if (_hasCategorization == null) documentationLocal;
return _hasCategorization ?? false;
}();
}