diff --git a/lib/src/element_type.dart b/lib/src/element_type.dart index e9f713932b..fc0d5ef3f4 100644 --- a/lib/src/element_type.dart +++ b/lib/src/element_type.dart @@ -132,8 +132,7 @@ class FunctionTypeElementType extends UndefinedElementType { @override String get linkedName { if (_linkedName == null) { - _linkedName = - FunctionTypeElementTypeRendererHtml().renderLinkedName(this); + _linkedName = _renderer.renderLinkedName(this); } return _linkedName; } @@ -146,8 +145,7 @@ class FunctionTypeElementType extends UndefinedElementType { @override String get nameWithGenerics { if (_nameWithGenerics == null) { - _nameWithGenerics = - FunctionTypeElementTypeRendererHtml().renderNameWithGenerics(this); + _nameWithGenerics = _renderer.renderNameWithGenerics(this); } return _nameWithGenerics; } @@ -162,6 +160,9 @@ class FunctionTypeElementType extends UndefinedElementType { @override String get name => 'Function'; + + ElementTypeRenderer get _renderer => + packageGraph.rendererFactory.functionTypeElementTypeRenderer; } class ParameterizedElementType extends DefinedElementType { @@ -173,8 +174,7 @@ class ParameterizedElementType extends DefinedElementType { @override String get linkedName { if (_linkedName == null) { - _linkedName = - ParameterizedElementTypeRendererHtml().renderLinkedName(this); + _linkedName = _renderer.renderLinkedName(this); } return _linkedName; } @@ -183,11 +183,13 @@ class ParameterizedElementType extends DefinedElementType { @override String get nameWithGenerics { if (_nameWithGenerics == null) { - _nameWithGenerics = - ParameterizedElementTypeRendererHtml().renderNameWithGenerics(this); + _nameWithGenerics = _renderer.renderNameWithGenerics(this); } return _nameWithGenerics; } + + ElementTypeRenderer get _renderer => + packageGraph.rendererFactory.parameterizedElementTypeRenderer; } class TypeParameterElementType extends DefinedElementType { @@ -362,12 +364,16 @@ class CallableElementType extends ParameterizedElementType @override String get linkedName { if (_linkedName == null) { - _linkedName = CallableElementTypeRendererHtml().renderLinkedName(this); + _linkedName = _renderer.renderLinkedName(this); } return _linkedName; } String get superLinkedName => super.linkedName; + + @override + ElementTypeRenderer get _renderer => + packageGraph.rendererFactory.callableElementTypeRenderer; } /// Types backed by a [GenericTypeAliasElement] that may or may not be callable. diff --git a/lib/src/model/category.dart b/lib/src/model/category.dart index 8464d50a15..6c611626a9 100644 --- a/lib/src/model/category.dart +++ b/lib/src/model/category.dart @@ -124,13 +124,9 @@ class Category extends Nameable String get href => isCanonical ? '${package.baseHref}topics/${name}-topic.html' : null; - String get categorization { - return CategoryRendererHtml().renderCategoryLabel(this); - } + String get categorization => _renderer.renderCategoryLabel(this); - String get linkedName { - return CategoryRendererHtml().renderLinkedName(this); - } + String get linkedName => _renderer.renderLinkedName(this); int _categoryIndex; @@ -201,4 +197,7 @@ class Category extends Nameable @override Iterable get typedefs => _typedefs; + + CategoryRenderer get _renderer => + packageGraph.rendererFactory.categoryRenderer; } diff --git a/lib/src/model/documentation.dart b/lib/src/model/documentation.dart index b22fa09315..8344fddd52 100644 --- a/lib/src/model/documentation.dart +++ b/lib/src/model/documentation.dart @@ -53,7 +53,7 @@ class Documentation { _hasExtendedDocs = parseResult.item2; Tuple2 renderResult = - DocumentationRendererHtml().render(parseResult.item1, processAllDocs); + _renderer.render(parseResult.item1, processAllDocs); if (processAllDocs) { _asHtml = renderResult.item1; @@ -71,4 +71,7 @@ class Documentation { MarkdownDocument.withElementLinkResolver(_element, commentRefs); return document.parseMarkdownText(text, processFullDocs); } + + DocumentationRenderer get _renderer => + _element.packageGraph.rendererFactory.documentationRenderer; } diff --git a/lib/src/model/enum.dart b/lib/src/model/enum.dart index a534a3676d..017aca1ec0 100644 --- a/lib/src/model/enum.dart +++ b/lib/src/model/enum.dart @@ -44,7 +44,7 @@ class EnumField extends Field { : super(element, library, packageGraph, getter, null); @override - String get constantValueBase => EnumFieldRendererHtml().renderValue(this); + String get constantValueBase => _fieldRenderer.renderValue(this); @override List get documentationFrom { @@ -104,4 +104,7 @@ class EnumField extends Field { @override Inheritable get overriddenElement => null; + + EnumFieldRenderer get _fieldRenderer => + packageGraph.rendererFactory.enumFieldRenderer; } diff --git a/lib/src/model/model_element.dart b/lib/src/model/model_element.dart index 8bc6918bce..8d33b8614f 100644 --- a/lib/src/model/model_element.dart +++ b/lib/src/model/model_element.dart @@ -25,8 +25,8 @@ import 'package:dartdoc/src/element_type.dart'; import 'package:dartdoc/src/logging.dart'; import 'package:dartdoc/src/model/model.dart'; import 'package:dartdoc/src/model_utils.dart' as utils; -import 'package:dartdoc/src/render/parameter_renderer.dart'; import 'package:dartdoc/src/render/model_element_renderer.dart'; +import 'package:dartdoc/src/render/parameter_renderer.dart'; import 'package:dartdoc/src/source_linker.dart'; import 'package:dartdoc/src/tuple.dart'; import 'package:dartdoc/src/utils.dart'; @@ -784,7 +784,7 @@ abstract class ModelElement extends Canonicalization /// does not exist. String get extendedDocLink { if (hasExtendedDocumentation) { - return ModelElementRendererHtml().renderExtendedDocLink(this); + return _modelElementRenderer.renderExtendedDocLink(this); } return ''; } @@ -916,18 +916,25 @@ abstract class ModelElement extends Canonicalization return _linkedName; } - String get linkedParams => - ParameterRendererHtml().renderLinkedParams(parameters); + ModelElementRenderer get _modelElementRenderer => + packageGraph.rendererFactory.modelElementRenderer; + + ParameterRenderer get _parameterRenderer => + packageGraph.rendererFactory.parameterRenderer; + + ParameterRenderer get _parameterRendererDetailed => + packageGraph.rendererFactory.parameterRendererDetailed; + + String get linkedParams => _parameterRenderer.renderLinkedParams(parameters); String get linkedParamsLines => - ParameterRendererHtmlList().renderLinkedParams(parameters).trim(); + _parameterRendererDetailed.renderLinkedParams(parameters).trim(); String get linkedParamsNoMetadata => - ParameterRendererHtml(showMetadata: false).renderLinkedParams(parameters); + _parameterRenderer.renderLinkedParams(parameters, showMetadata: false); - String get linkedParamsNoMetadataOrNames => - ParameterRendererHtml(showMetadata: false, showNames: false) - .renderLinkedParams(parameters); + String get linkedParamsNoMetadataOrNames => _parameterRenderer + .renderLinkedParams(parameters, showMetadata: false, showNames: false); ElementType get modelType { if (_modelType == null) { @@ -1120,7 +1127,7 @@ abstract class ModelElement extends Canonicalization return htmlEscape.convert(name); } - return ModelElementRendererHtml().renderLinkedName(this); + return _modelElementRenderer.renderLinkedName(this); } /// Replace {@example ...} in API comments with the content of named file. @@ -1351,8 +1358,7 @@ abstract class ModelElement extends Canonicalization final String youTubeId = url.group(url.groupCount); final String aspectRatio = (height / width * 100).toStringAsFixed(2); - return ModelElementRendererHtml() - .renderYoutubeUrl(youTubeId, aspectRatio); + return _modelElementRenderer.renderYoutubeUrl(youTubeId, aspectRatio); }); } @@ -1483,8 +1489,8 @@ abstract class ModelElement extends Canonicalization 'parameter)'); } - return ModelElementRendererHtml() - .renderAnimation(uniqueId, width, height, movieUrl, overlayId); + return _modelElementRenderer.renderAnimation( + uniqueId, width, height, movieUrl, overlayId); }); } diff --git a/lib/src/model/package_builder.dart b/lib/src/model/package_builder.dart index 8d82ca138f..ea728b69e9 100644 --- a/lib/src/model/package_builder.dart +++ b/lib/src/model/package_builder.dart @@ -27,6 +27,7 @@ import 'package:dartdoc/src/io_utils.dart'; import 'package:dartdoc/src/logging.dart'; import 'package:dartdoc/src/model/model.dart'; import 'package:dartdoc/src/package_meta.dart' show PackageMeta; +import 'package:dartdoc/src/render/renderer_factory.dart'; import 'package:dartdoc/src/special_elements.dart'; import 'package:package_config/discovery.dart' as package_config; import 'package:path/path.dart' as path; @@ -42,13 +43,16 @@ class PackageBuilder { if (config.topLevelPackageMeta.needsPubGet) { config.topLevelPackageMeta.runPubGet(); } + // TODO(jdkoren): change factory for other formats based on config options + RendererFactory rendererFactory = HtmlRenderFactory(); PackageGraph newGraph = PackageGraph.UninitializedPackageGraph( config, driver, await driver.currentSession.typeSystem, sdk, - hasEmbedderSdkFiles); + hasEmbedderSdkFiles, + rendererFactory); await getLibraries(newGraph); await newGraph.initializePackageGraph(); return newGraph; diff --git a/lib/src/model/package_graph.dart b/lib/src/model/package_graph.dart index 864ea31981..30d680818a 100644 --- a/lib/src/model/package_graph.dart +++ b/lib/src/model/package_graph.dart @@ -19,13 +19,14 @@ import 'package:dartdoc/src/dartdoc_options.dart'; import 'package:dartdoc/src/model/model.dart'; import 'package:dartdoc/src/model_utils.dart' as utils; import 'package:dartdoc/src/package_meta.dart' show PackageMeta; +import 'package:dartdoc/src/render/renderer_factory.dart'; import 'package:dartdoc/src/special_elements.dart'; import 'package:dartdoc/src/tuple.dart'; import 'package:dartdoc/src/warnings.dart'; class PackageGraph { - PackageGraph.UninitializedPackageGraph( - this.config, this.driver, this.typeSystem, this.sdk, this.hasEmbedderSdk) + PackageGraph.UninitializedPackageGraph(this.config, this.driver, + this.typeSystem, this.sdk, this.hasEmbedderSdk, this.rendererFactory) : packageMeta = config.topLevelPackageMeta, session = driver.currentSession { _packageWarningCounter = PackageWarningCounter(this); @@ -207,6 +208,9 @@ class PackageGraph { /// Dartdoc's configuration flags. final DartdocOptionContext config; + /// Factory for renderers + final RendererFactory rendererFactory; + Package _defaultPackage; Package get defaultPackage { diff --git a/lib/src/model/type_parameter.dart b/lib/src/model/type_parameter.dart index 158095ddaa..550c20bc5b 100644 --- a/lib/src/model/type_parameter.dart +++ b/lib/src/model/type_parameter.dart @@ -76,16 +76,17 @@ abstract class TypeParameters implements ModelElement { bool get hasGenericParameters => typeParameters.isNotEmpty; - String get genericParameters { - return TypeParametersRendererHtml().renderGenericParameters(this); - } + String get genericParameters => + _typeParametersRenderer.renderGenericParameters(this); - String get linkedGenericParameters { - return TypeParametersRendererHtml().renderLinkedGenericParameters(this); - } + String get linkedGenericParameters => + _typeParametersRenderer.renderLinkedGenericParameters(this); @override DefinedElementType get modelType; List get typeParameters; + + TypeParametersRenderer get _typeParametersRenderer => + packageGraph.rendererFactory.typeParametersRenderer; } diff --git a/lib/src/model/typedef.dart b/lib/src/model/typedef.dart index 3a134474fd..b7e7424e6d 100644 --- a/lib/src/model/typedef.dart +++ b/lib/src/model/typedef.dart @@ -21,8 +21,7 @@ class Typedef extends ModelElement String get nameWithGenerics => '$name${super.genericParameters}'; @override - String get genericParameters => - TypedefRendererHtml().renderGenericParameters(this); + String get genericParameters => _renderer.renderGenericParameters(this); List get genericTypeParameters { if (element is GenericTypeAliasElement) { @@ -59,4 +58,6 @@ class Typedef extends ModelElement List get typeParameters => _typedef.typeParameters.map((f) { return ModelElement.from(f, library, packageGraph) as TypeParameter; }).toList(); + + TypedefRenderer get _renderer => packageGraph.rendererFactory.typedefRenderer; } diff --git a/lib/src/render/element_type_renderer.dart b/lib/src/render/element_type_renderer.dart index eb62710856..cc4be7a4fb 100644 --- a/lib/src/render/element_type_renderer.dart +++ b/lib/src/render/element_type_renderer.dart @@ -85,8 +85,8 @@ class CallableElementTypeRendererHtml StringBuffer buf = StringBuffer(); buf.write(elementType.nameWithGenerics); buf.write('('); - buf.write(ParameterRendererHtml(showNames: false) - .renderLinkedParams(elementType.element.parameters) + buf.write(ParameterRendererHtml() + .renderLinkedParams(elementType.element.parameters, showNames: false) .trim()); buf.write(') → '); buf.write(elementType.returnType.linkedName); diff --git a/lib/src/render/parameter_renderer.dart b/lib/src/render/parameter_renderer.dart index 4cf6bcd355..3e7a895c3a 100644 --- a/lib/src/render/parameter_renderer.dart +++ b/lib/src/render/parameter_renderer.dart @@ -8,8 +8,6 @@ import 'package:dartdoc/src/model/parameter.dart'; /// Render HTML in an extended vertical format using
    tag. class ParameterRendererHtmlList extends ParameterRendererHtml { - ParameterRendererHtmlList({bool showMetadata = true, bool showNames = true}) - : super(showMetadata: showMetadata, showNames: showNames); @override String listItem(String listItem) => '
  1. $listItem
  2. \n'; @override @@ -20,12 +18,6 @@ class ParameterRendererHtmlList extends ParameterRendererHtml { /// Render HTML suitable for a single, wrapped line. class ParameterRendererHtml extends ParameterRenderer { - @override - final bool showMetadata; - @override - final bool showNames; - ParameterRendererHtml({this.showMetadata = true, this.showNames = true}); - @override String listItem(String listItem) => '${listItem}'; @override @@ -51,9 +43,6 @@ class ParameterRendererHtml extends ParameterRenderer { } abstract class ParameterRenderer { - bool get showMetadata; - bool get showNames; - String listItem(String item); String orderedList(String listItems); String annotation(String annotation); @@ -64,28 +53,8 @@ abstract class ParameterRenderer { String typeName(String typeName); String required(String required); - String _linkedParameterSublist(List parameters, bool trailingComma, - {String thisOpenBracket = '', String thisCloseBracket = ''}) { - StringBuffer builder = StringBuffer(); - parameters.forEach((p) { - String prefix = ''; - String suffix = ''; - if (identical(p, parameters.first)) { - prefix = thisOpenBracket; - } - if (identical(p, parameters.last)) { - suffix += thisCloseBracket; - if (trailingComma) suffix += ', '; - } else { - suffix += ', '; - } - builder.write( - listItem(parameter(prefix + renderParam(p) + suffix, p.htmlId))); - }); - return builder.toString(); - } - - String renderLinkedParams(List parameters) { + String renderLinkedParams(List parameters, + {showMetadata = true, showNames = true}) { List positionalParams = parameters.where((Parameter p) => p.isRequiredPositional).toList(); List optionalPositionalParams = @@ -96,21 +65,55 @@ abstract class ParameterRenderer { String positional = '', optional = '', named = ''; if (positionalParams.isNotEmpty) { positional = _linkedParameterSublist(positionalParams, - optionalPositionalParams.isNotEmpty || namedParams.isNotEmpty); + optionalPositionalParams.isNotEmpty || namedParams.isNotEmpty, + showMetadata: showMetadata, showNames: showNames); } if (optionalPositionalParams.isNotEmpty) { optional = _linkedParameterSublist( optionalPositionalParams, namedParams.isNotEmpty, - thisOpenBracket: '[', thisCloseBracket: ']'); + openBracket: '[', + closeBracket: ']', + showMetadata: showMetadata, + showNames: showNames); } if (namedParams.isNotEmpty) { named = _linkedParameterSublist(namedParams, false, - thisOpenBracket: '{', thisCloseBracket: '}'); + openBracket: '{', + closeBracket: '}', + showMetadata: showMetadata, + showNames: showNames); } return (orderedList(positional + optional + named)); } - String renderParam(Parameter param) { + String _linkedParameterSublist(List parameters, bool trailingComma, + {String openBracket = '', + String closeBracket = '', + showMetadata = true, + showNames = true}) { + StringBuffer builder = StringBuffer(); + parameters.forEach((p) { + String prefix = ''; + String suffix = ''; + if (identical(p, parameters.first)) { + prefix = openBracket; + } + if (identical(p, parameters.last)) { + suffix += closeBracket; + if (trailingComma) suffix += ', '; + } else { + suffix += ', '; + } + String renderedParam = + _renderParam(p, showMetadata: showMetadata, showNames: showNames); + builder.write( + listItem(parameter(prefix + renderedParam + suffix, p.htmlId))); + }); + return builder.toString(); + } + + String _renderParam(Parameter param, + {showMetadata = true, showNames = true}) { StringBuffer buf = StringBuffer(); ElementType paramModelType = param.modelType; @@ -140,13 +143,16 @@ abstract class ParameterRenderer { } if (!paramModelType.isTypedef && paramModelType is DefinedElementType) { buf.write('('); - buf.write(renderLinkedParams(paramModelType.element.parameters)); + buf.write(renderLinkedParams(paramModelType.element.parameters, + showMetadata: showMetadata, showNames: showNames)); buf.write(')'); } if (!paramModelType.isTypedef && paramModelType.type is FunctionType) { buf.write('('); buf.write(renderLinkedParams( - (paramModelType as UndefinedElementType).parameters)); + (paramModelType as UndefinedElementType).parameters, + showMetadata: showMetadata, + showNames: showNames)); buf.write(')'); } } else if (param.modelType != null) { diff --git a/lib/src/render/renderer_factory.dart b/lib/src/render/renderer_factory.dart new file mode 100644 index 0000000000..7144c3f1a5 --- /dev/null +++ b/lib/src/render/renderer_factory.dart @@ -0,0 +1,82 @@ +// 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:dartdoc/dartdoc.dart'; +import 'package:dartdoc/src/render/category_renderer.dart'; +import 'package:dartdoc/src/render/documentation_renderer.dart'; +import 'package:dartdoc/src/render/element_type_renderer.dart'; +import 'package:dartdoc/src/render/enum_field_renderer.dart'; +import 'package:dartdoc/src/render/model_element_renderer.dart'; +import 'package:dartdoc/src/render/parameter_renderer.dart'; +import 'package:dartdoc/src/render/type_parameters_renderer.dart'; +import 'package:dartdoc/src/render/typedef_renderer.dart'; + +abstract class RendererFactory { + CategoryRenderer get categoryRenderer; + + DocumentationRenderer get documentationRenderer; + + ElementTypeRenderer + get functionTypeElementTypeRenderer; + + ElementTypeRenderer + get parameterizedElementTypeRenderer; + + ElementTypeRenderer get callableElementTypeRenderer; + + EnumFieldRenderer get enumFieldRenderer; + + ModelElementRenderer get modelElementRenderer; + + ParameterRenderer get parameterRenderer; + + ParameterRenderer get parameterRendererDetailed; + + TypeParametersRenderer get typeParametersRenderer; + + TypedefRenderer get typedefRenderer; +} + +class HtmlRenderFactory extends RendererFactory { + @override + CategoryRenderer get categoryRenderer => CategoryRendererHtml(); + + @override + DocumentationRenderer get documentationRenderer => + DocumentationRendererHtml(); + + @override + ElementTypeRenderer get callableElementTypeRenderer => + CallableElementTypeRendererHtml(); + + @override + ElementTypeRenderer + get functionTypeElementTypeRenderer => + FunctionTypeElementTypeRendererHtml(); + + @override + ElementTypeRenderer + get parameterizedElementTypeRenderer => + ParameterizedElementTypeRendererHtml(); + + @override + EnumFieldRenderer get enumFieldRenderer => EnumFieldRendererHtml(); + + @override + ModelElementRenderer get modelElementRenderer => ModelElementRendererHtml(); + + @override + ParameterRenderer get parameterRenderer => ParameterRendererHtml(); + + @override + ParameterRenderer get parameterRendererDetailed => + ParameterRendererHtmlList(); + + @override + TypeParametersRenderer get typeParametersRenderer => + TypeParametersRendererHtml(); + + @override + TypedefRenderer get typedefRenderer => TypedefRendererHtml(); +} diff --git a/test/model_test.dart b/test/model_test.dart index 5f52a1081a..edae9ae3bc 100644 --- a/test/model_test.dart +++ b/test/model_test.dart @@ -3270,8 +3270,8 @@ String topLevelFunction(int param1, bool param2, Cool coolBeans, test('a function requiring a Future parameter', () { expect( - ParameterRendererHtml(showMetadata: true, showNames: true) - .renderLinkedParams(aVoidParameter.parameters), + ParameterRendererHtml().renderLinkedParams(aVoidParameter.parameters, + showMetadata: true, showNames: true), equals( 'Future<void> p1')); });