blob: 32a0db6bffc8cf9cff46b84570014aec1bdb93fb [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:analyzer/file_system/file_system.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';
/// Creates a [Generator] with an [HtmlGeneratorBackend] backend.
///
/// [forceRuntimeTemplates] should only be given [true] during tests.
Future<Generator> initHtmlGenerator(DartdocGeneratorOptionContext context,
{bool forceRuntimeTemplates = false}) async {
var templates = await Templates.fromContext(context,
forceRuntimeTemplates: forceRuntimeTemplates);
var options = DartdocGeneratorBackendOptions.fromContext(context);
var backend =
HtmlGeneratorBackend(options, templates, context.resourceProvider);
return GeneratorFrontEnd(backend);
}
/// Generator backend for html output.
class HtmlGeneratorBackend extends DartdocGeneratorBackend {
HtmlGeneratorBackend(DartdocGeneratorBackendOptions options,
Templates templates, ResourceProvider resourceProvider)
: super(options, templates, resourceProvider);
@override
void generatePackage(FileWriter writer, PackageGraph graph, Package package) {
super.generatePackage(writer, graph, package);
// We have to construct the data again. This only happens once per package.
TemplateData data = PackageTemplateData(options, graph, package);
var content = templates.renderError(data);
write(writer, '__404error.html', data, content);
}
@override
Future<void> generateAdditionalFiles(FileWriter writer) async {
await _copyResources(writer);
if (options.favicon != null) {
// Allow overwrite of favicon.
var bytes = resourceProvider.getFile(options.favicon).readAsBytesSync();
writer.writeBytes(
resourceProvider.pathContext.join('static-assets', 'favicon.png'),
bytes,
allowOverwrite: true,
);
}
}
Future<void> _copyResources(FileWriter writer) async {
for (var resourcePath in resources.resourceNames) {
if (!resourcePath.startsWith(_dartdocResourcePrefix)) {
throw StateError('Resource paths must start with '
'$_dartdocResourcePrefix, encountered $resourcePath');
}
var destFileName = resourcePath.substring(_dartdocResourcePrefix.length);
var destFilePath =
resourceProvider.pathContext.join('static-assets', destFileName);
writer.writeBytes(destFilePath,
await resourceProvider.loadResourceAsBytes(resourcePath));
}
}
static const _dartdocResourcePrefix = 'package:dartdoc/resources/';
}