Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 1 addition & 8 deletions lib/dartdoc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import 'dart:convert';
import 'dart:io' show exitCode, stderr;

import 'package:analyzer/file_system/file_system.dart';
import 'package:dartdoc/options.dart';
import 'package:dartdoc/src/dartdoc_options.dart';
import 'package:dartdoc/src/generator/empty_generator.dart';
import 'package:dartdoc/src/generator/generator.dart';
Expand Down Expand Up @@ -40,14 +41,6 @@ const String programName = 'dartdoc';
// Update when pubspec version changes by running `pub run build_runner build`
const String dartdocVersion = packageVersion;

/// Helper class that consolidates option contexts for instantiating generators.
class DartdocGeneratorOptionContext extends DartdocOptionContext
with GeneratorContext {
DartdocGeneratorOptionContext(
DartdocOptionSet optionSet, Folder dir, ResourceProvider resourceProvider)
: super(optionSet, dir, resourceProvider);
}

class DartdocFileWriter implements FileWriter {
final String outputDir;
@override
Expand Down
46 changes: 46 additions & 0 deletions lib/options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,52 @@ import 'package:args/args.dart';
import 'package:dartdoc/dartdoc.dart';
import 'package:dartdoc/src/logging.dart';

/// Helper class that consolidates option contexts for instantiating generators.
class DartdocGeneratorOptionContext extends DartdocOptionContext {
DartdocGeneratorOptionContext(
DartdocOptionSet optionSet, Folder dir, ResourceProvider resourceProvider)
: super(optionSet, dir, resourceProvider);

// TODO(migration): Make late final with initializer when Null Safe.
String _header;

/// Returns the joined contents of any 'header' files specified in options.
String get header =>
_header ??= _joinCustomTextFiles(optionSet['header'].valueAt(context));

// TODO(migration): Make late final with initializer when Null Safe.
String _footer;

/// Returns the joined contents of any 'footer' files specified in options.
String get footer =>
_footer ??= _joinCustomTextFiles(optionSet['footer'].valueAt(context));

// TODO(migration): Make late final with initializer when Null Safe.
String _footerText;

/// Returns the joined contents of any 'footer-text' files specified in
/// options.
String get footerText => _footerText ??=
_joinCustomTextFiles(optionSet['footerText'].valueAt(context));

String _joinCustomTextFiles(Iterable<String> paths) => paths
.map((p) => resourceProvider.getFile(p).readAsStringSync())
.join('\n');

bool get prettyIndexJson => optionSet['prettyIndexJson'].valueAt(context);

String get favicon => optionSet['favicon'].valueAt(context);

String get relCanonicalPrefix =>
optionSet['relCanonicalPrefix'].valueAt(context);

String get templatesDir => optionSet['templatesDir'].valueAt(context);

// TODO(jdkoren): duplicated temporarily so that GeneratorContext is enough for configuration.
@override
bool get useBaseHref => optionSet['useBaseHref'].valueAt(context);
}

class DartdocProgramOptionContext extends DartdocGeneratorOptionContext
with LoggingContext {
DartdocProgramOptionContext(
Expand Down
35 changes: 26 additions & 9 deletions lib/src/generator/dartdoc_generator_backend.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.

import 'package:dartdoc/dartdoc.dart';
import 'package:dartdoc/options.dart';
import 'package:dartdoc/src/generator/generator_frontend.dart';
import 'package:dartdoc/src/generator/generator_utils.dart' as generator_util;
import 'package:dartdoc/src/generator/template_data.dart';
Expand All @@ -18,6 +19,7 @@ import 'package:path/path.dart' as path show Context;
class DartdocGeneratorBackendOptions implements TemplateOptions {
@override
final String relCanonicalPrefix;

@override
final String toolVersion;

Expand All @@ -28,20 +30,35 @@ class DartdocGeneratorBackendOptions implements TemplateOptions {
@override
final bool useBaseHref;

@override
final String customHeaderContent;

@override
final String customFooterContent;

@override
final String customInnerFooterText;

DartdocGeneratorBackendOptions.fromContext(
DartdocGeneratorOptionContext context)
: relCanonicalPrefix = context.relCanonicalPrefix,
toolVersion = dartdocVersion,
favicon = context.favicon,
prettyIndexJson = context.prettyIndexJson,
useBaseHref = context.useBaseHref;

DartdocGeneratorBackendOptions(
{this.relCanonicalPrefix,
this.toolVersion,
this.favicon,
this.prettyIndexJson = false,
this.useBaseHref = false});
useBaseHref = context.useBaseHref,
customHeaderContent = context.header,
customFooterContent = context.footer,
customInnerFooterText = context.footerText;

DartdocGeneratorBackendOptions._defaults()
: relCanonicalPrefix = null,
toolVersion = null,
favicon = null,
prettyIndexJson = false,
useBaseHref = false,
customHeaderContent = '',
customFooterContent = '',
customInnerFooterText = '';
}

class SidebarGenerator<T extends Documentable> {
Expand All @@ -67,7 +84,7 @@ abstract class DartdocGeneratorBackend implements GeneratorBackend {

DartdocGeneratorBackend(
DartdocGeneratorBackendOptions options, this.templates, this._pathContext)
: options = options ?? DartdocGeneratorBackendOptions(),
: options = options ?? DartdocGeneratorBackendOptions._defaults(),
sidebarForContainer =
SidebarGenerator(templates.sidebarContainerTemplate),
sidebarForLibrary = SidebarGenerator(templates.sidebarLibraryTemplate);
Expand Down
21 changes: 0 additions & 21 deletions lib/src/generator/generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,27 +32,6 @@ abstract class Generator {
Future<void> generate(PackageGraph packageGraph, FileWriter writer);
}

/// Dartdoc options related to generators generally.
mixin GeneratorContext on DartdocOptionContextBase {
List<String> get footer => optionSet['footer'].valueAt(context);

List<String> get footerText => optionSet['footerText'].valueAt(context);

List<String> get header => optionSet['header'].valueAt(context);

bool get prettyIndexJson => optionSet['prettyIndexJson'].valueAt(context);

String get favicon => optionSet['favicon'].valueAt(context);

String get relCanonicalPrefix =>
optionSet['relCanonicalPrefix'].valueAt(context);

String get templatesDir => optionSet['templatesDir'].valueAt(context);

// TODO(jdkoren): duplicated temporarily so that GeneratorContext is enough for configuration.
bool get useBaseHref => optionSet['useBaseHref'].valueAt(context);
}

Future<List<DartdocOption<Object>>> createGeneratorOptions(
PackageMetaProvider packageMetaProvider) async {
var resourceProvider = packageMetaProvider.resourceProvider;
Expand Down
4 changes: 3 additions & 1 deletion lib/src/generator/html_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@

library dartdoc.html_generator;

import 'package:dartdoc/dartdoc.dart';
import 'package:dartdoc/options.dart';
import 'package:dartdoc/src/generator/dartdoc_generator_backend.dart';
import 'package:dartdoc/src/generator/generator.dart';
import 'package:dartdoc/src/generator/generator_frontend.dart';
import 'package:dartdoc/src/generator/html_resources.g.dart' as resources;
import 'package:dartdoc/src/generator/resource_loader.dart';
import 'package:dartdoc/src/generator/template_data.dart';
import 'package:dartdoc/src/generator/templates.dart';
import 'package:dartdoc/src/model/package.dart';
import 'package:dartdoc/src/model/package_graph.dart';
import 'package:path/path.dart' as path show Context;

Future<Generator> initHtmlGenerator(
Expand Down
2 changes: 1 addition & 1 deletion lib/src/generator/markdown_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +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.

import 'package:dartdoc/dartdoc.dart';
import 'package:dartdoc/options.dart';
import 'package:dartdoc/src/generator/dartdoc_generator_backend.dart';
import 'package:dartdoc/src/generator/generator.dart';
import 'package:dartdoc/src/generator/generator_frontend.dart';
Expand Down
9 changes: 9 additions & 0 deletions lib/src/generator/template_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ abstract class TemplateOptions {
String get relCanonicalPrefix;
String get toolVersion;
bool get useBaseHref;
String get customHeaderContent;
String get customFooterContent;
String get customInnerFooterText;
}

abstract class TemplateData<T extends Documentable> {
Expand Down Expand Up @@ -61,6 +64,12 @@ abstract class TemplateData<T extends Documentable> {
String _layoutTitle(String name, String kind, bool isDeprecated) =>
_packageGraph.rendererFactory.templateRenderer
.composeLayoutTitle(name, kind, isDeprecated);

String get customHeader => htmlOptions.customHeaderContent;

String get customFooter => htmlOptions.customFooterContent;

String get customInnerFooter => htmlOptions.customInnerFooterText;
}

/// A [TemplateData] which contains a library, for rendering the
Expand Down
71 changes: 9 additions & 62 deletions lib/src/generator/templates.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ library dartdoc.templates;

import 'package:analyzer/file_system/file_system.dart';
import 'package:dartdoc/dartdoc.dart';
import 'package:dartdoc/options.dart';
import 'package:dartdoc/src/generator/resource_loader.dart';
import 'package:dartdoc/src/generator/template_data.dart';
import 'package:dartdoc/src/mustachio/annotations.dart';
Expand Down Expand Up @@ -67,36 +68,6 @@ const _partials_md = <String>[
'source_link',
];

const String _headerPlaceholder = '{{! header placeholder }}';
const String _footerPlaceholder = '{{! footer placeholder }}';
const String _footerTextPlaceholder = '{{! footer-text placeholder }}';

Future<Map<String, String>> _loadPartials(
_TemplatesLoader templatesLoader,
List<String> headerPaths,
List<String> footerPaths,
List<String> footerTextPaths) async {
var partials = await templatesLoader.loadPartials();

void replacePlaceholder(String key, String placeholder, List<String> paths) {
var template = partials[key];
if (template != null && paths != null && paths.isNotEmpty) {
var replacement = paths
.map((p) =>
templatesLoader.resourceProvider.getFile(p).readAsStringSync())
.join('\n');
template = template.replaceAll(placeholder, replacement);
partials[key] = template;
}
}

replacePlaceholder('head', _headerPlaceholder, headerPaths);
replacePlaceholder('footer', _footerPlaceholder, footerPaths);
replacePlaceholder('footer', _footerTextPlaceholder, footerTextPaths);

return partials;
}

abstract class _TemplatesLoader {
ResourceProvider get resourceProvider;

Expand Down Expand Up @@ -207,53 +178,29 @@ class Templates {
DartdocGeneratorOptionContext context) async {
var templatesDir = context.templatesDir;
var format = context.format;
var footerTextPaths = context.footerText;

if (templatesDir != null) {
return _fromDirectory(
context.resourceProvider.getFolder(templatesDir), format,
resourceProvider: context.resourceProvider,
headerPaths: context.header,
footerPaths: context.footer,
footerTextPaths: footerTextPaths);
resourceProvider: context.resourceProvider);
} else {
return createDefault(format,
resourceProvider: context.resourceProvider,
headerPaths: context.header,
footerPaths: context.footer,
footerTextPaths: footerTextPaths);
return createDefault(format, resourceProvider: context.resourceProvider);
}
}

@visibleForTesting
static Future<Templates> createDefault(String format,
{@required ResourceProvider resourceProvider,
List<String> headerPaths = const <String>[],
List<String> footerPaths = const <String>[],
List<String> footerTextPaths = const <String>[]}) async {
return _create(_DefaultTemplatesLoader.create(format, resourceProvider),
headerPaths: headerPaths,
footerPaths: footerPaths,
footerTextPaths: footerTextPaths);
{@required ResourceProvider resourceProvider}) async {
return _create(_DefaultTemplatesLoader.create(format, resourceProvider));
}

static Future<Templates> _fromDirectory(Folder dir, String format,
{@required ResourceProvider resourceProvider,
@required List<String> headerPaths,
@required List<String> footerPaths,
@required List<String> footerTextPaths}) async {
return _create(_DirectoryTemplatesLoader(dir, format, resourceProvider),
headerPaths: headerPaths,
footerPaths: footerPaths,
footerTextPaths: footerTextPaths);
{@required ResourceProvider resourceProvider}) async {
return _create(_DirectoryTemplatesLoader(dir, format, resourceProvider));
}

static Future<Templates> _create(_TemplatesLoader templatesLoader,
{@required List<String> headerPaths,
@required List<String> footerPaths,
@required List<String> footerTextPaths}) async {
var partials = await _loadPartials(
templatesLoader, headerPaths, footerPaths, footerTextPaths);
static Future<Templates> _create(_TemplatesLoader templatesLoader) async {
var partials = await templatesLoader.loadPartials();

Template _partial(String name) {
var partial = partials[name];
Expand Down
36 changes: 36 additions & 0 deletions lib/src/generator/templates.renderers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1283,6 +1283,42 @@ class _Renderer_TemplateData<T extends Documentable>
return renderSimple(c.bareHref, ast, r.template, parent: r);
},
),
'customFooter': Property(
getValue: (CT_ c) => c.customFooter,
renderVariable: (CT_ c, Property<CT_> self,
List<String> remainingNames) =>
self.renderSimpleVariable(c, remainingNames, 'String'),
isNullValue: (CT_ c) => c.customFooter == null,
renderValue:
(CT_ c, RendererBase<CT_> r, List<MustachioNode> ast) {
return renderSimple(c.customFooter, ast, r.template,
parent: r);
},
),
'customHeader': Property(
getValue: (CT_ c) => c.customHeader,
renderVariable: (CT_ c, Property<CT_> self,
List<String> remainingNames) =>
self.renderSimpleVariable(c, remainingNames, 'String'),
isNullValue: (CT_ c) => c.customHeader == null,
renderValue:
(CT_ c, RendererBase<CT_> r, List<MustachioNode> ast) {
return renderSimple(c.customHeader, ast, r.template,
parent: r);
},
),
'customInnerFooter': Property(
getValue: (CT_ c) => c.customInnerFooter,
renderVariable: (CT_ c, Property<CT_> self,
List<String> remainingNames) =>
self.renderSimpleVariable(c, remainingNames, 'String'),
isNullValue: (CT_ c) => c.customInnerFooter == null,
renderValue:
(CT_ c, RendererBase<CT_> r, List<MustachioNode> ast) {
return renderSimple(c.customInnerFooter, ast, r.template,
parent: r);
},
),
'defaultPackage': Property(
getValue: (CT_ c) => c.defaultPackage,
renderVariable:
Expand Down
4 changes: 2 additions & 2 deletions lib/templates/html/_footer.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
{{/hasFooterVersion}}
</span>

{{! footer-text placeholder }}
{{{ customInnerFooter }}}
</footer>

{{! TODO(jdkoren): unwrap ^useBaseHref sections when the option is removed.}}
<script src="{{^useBaseHref}}%%__HTMLBASE_dartdoc_internal__%%{{/useBaseHref}}static-assets/highlight.pack.js"></script>
<script src="{{^useBaseHref}}%%__HTMLBASE_dartdoc_internal__%%{{/useBaseHref}}static-assets/script.js"></script>

{{! footer placeholder }}
{{{ customFooter }}}

</body>

Expand Down
2 changes: 1 addition & 1 deletion lib/templates/html/_head.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
<link rel="stylesheet" href="{{^useBaseHref}}%%__HTMLBASE_dartdoc_internal__%%{{/useBaseHref}}static-assets/styles.css">
<link rel="icon" href="{{^useBaseHref}}%%__HTMLBASE_dartdoc_internal__%%{{/useBaseHref}}static-assets/favicon.png">

{{! header placeholder }}
{{{ customHeader }}}
</head>

{{! We don't use <base href>, but we do lookup the htmlBase from javascript. }}
Expand Down
Loading