blob: a8516025f5818fb6995929cdc36659121890b05b [file] [log] [blame]
// Copyright (c) 2014, 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.
library dartdoc.html_generator;
import 'package:dartdoc/options.dart';
import 'package:dartdoc/src/generator/generator.dart';
import 'package:dartdoc/src/generator/generator_backend.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/model.dart';
import 'package:dartdoc/src/runtime_stats.dart';
import 'package:meta/meta.dart';
/// Creates a [Generator] with an [HtmlGeneratorBackend] backend.
///
/// [forceRuntimeTemplates] should only be given [true] during tests.
Future<Generator> initHtmlGenerator(
DartdocGeneratorOptionContext context, {
required FileWriter writer,
@visibleForTesting bool forceRuntimeTemplates = false,
}) async {
var templates = await Templates.fromContext(context,
forceRuntimeTemplates: forceRuntimeTemplates);
var options = DartdocGeneratorBackendOptions.fromContext(context);
var backend = HtmlGeneratorBackend(
options, templates, writer, context.resourceProvider);
return GeneratorFrontEnd(backend);
}
/// Generator backend for HTML output.
class HtmlGeneratorBackend extends GeneratorBackendBase {
HtmlGeneratorBackend(
super.options, super.templates, super.writer, super.resourceProvider);
@override
void generateClass(PackageGraph packageGraph, Library library, Class clazz) {
super.generateClass(packageGraph, library, clazz);
var data = ClassTemplateData(options, packageGraph, library, clazz);
var sidebarContent = templates.renderSidebarForContainer(data);
write(writer, clazz.sidebarPath, data, sidebarContent);
runtimeStats.incrementAccumulator('writtenSidebarFileCount');
}
@override
void generateEnum(PackageGraph packageGraph, Library library, Enum eNum) {
super.generateEnum(packageGraph, library, eNum);
var data = EnumTemplateData(options, packageGraph, library, eNum);
var sidebarContent = templates.renderSidebarForContainer(data);
write(writer, eNum.sidebarPath, data, sidebarContent);
runtimeStats.incrementAccumulator('writtenSidebarFileCount');
}
@override
void generateExtension(
PackageGraph packageGraph, Library library, Extension extension) {
super.generateExtension(packageGraph, library, extension);
var data = ExtensionTemplateData(options, packageGraph, library, extension);
var sidebarContent = templates.renderSidebarForContainer(data);
write(writer, extension.sidebarPath, data, sidebarContent);
runtimeStats.incrementAccumulator('writtenSidebarFileCount');
}
@override
void generateLibrary(PackageGraph packageGraph, Library library) {
super.generateLibrary(packageGraph, library);
var data = LibraryTemplateData(options, packageGraph, library);
var sidebarContent = templates.renderSidebarForLibrary(data);
write(writer, library.sidebarPath, data, sidebarContent);
runtimeStats.incrementAccumulator('writtenSidebarFileCount');
}
@override
void generateMixin(PackageGraph packageGraph, Library library, Mixin mixin) {
super.generateMixin(packageGraph, library, mixin);
var data = MixinTemplateData(options, packageGraph, library, mixin);
var sidebarContent = templates.renderSidebarForContainer(data);
write(writer, mixin.sidebarPath, data, sidebarContent);
runtimeStats.incrementAccumulator('writtenSidebarFileCount');
}
@override
void generatePackage(PackageGraph packageGraph, Package package) {
super.generatePackage(packageGraph, package);
// We have to construct the data again. This only happens once per package.
var data = PackageTemplateData(options, packageGraph, package);
var dataForSearch =
PackageTemplateDataForSearch(options, packageGraph, package);
var content = templates.renderError(data);
write(writer, '__404error.html', data, content);
var searchContent = templates.renderSearchPage(dataForSearch);
write(writer, 'search.html', data, searchContent);
}
@override
Future<void> generateAdditionalFiles() async {
await _copyResources(writer);
var favicon = options.favicon;
if (favicon != null) {
// Allow overwrite of favicon.
var bytes = resourceProvider.getFile(favicon).readAsBytesSync();
writer.writeBytes(
_pathJoin('static-assets', 'favicon.png'),
bytes,
allowOverwrite: true,
);
}
}
Future<void> _copyResources(FileWriter writer) async {
var resourcesDir = options.resourcesDir ??
(await resourceProvider.getResourceFolder(_dartdocResourcePrefix)).path;
for (var resourceFileName in resources.resourceNames) {
var destinationPath = _pathJoin('static-assets', resourceFileName);
var sourcePath = _pathJoin(resourcesDir, resourceFileName);
writer.writeBytes(
destinationPath,
resourceProvider.getFile(sourcePath).readAsBytesSync(),
);
}
}
String _pathJoin(String a, String b) =>
resourceProvider.pathContext.join(a, b);
static const _dartdocResourcePrefix = 'package:dartdoc/resources';
}