blob: 41b32f7f9cb8ffcc16fe682850afa9a4420adfca [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.bin;
import 'dart:io';
import 'package:args/args.dart';
import 'package:cli_util/cli_util.dart' as cli_util;
import 'package:dartdoc/dartdoc.dart';
import 'package:dartdoc/src/package_meta.dart';
import 'package:path/path.dart' as path;
/// Analyzes Dart files and generates a representation of included libraries,
/// classes, and members. Uses the current directory to look for libraries.
main(List<String> arguments) async {
var parser = _createArgsParser();
var args = parser.parse(arguments);
if (args['help']) {
_printHelp(parser);
}
if (args['version']) {
print('$name version: $version');
exit(0);
}
Directory sdkDir = cli_util.getSdkDir(arguments);
if (sdkDir == null) {
print("Error: unable to locate the Dart SDK. Please use the --dart-sdk "
"command line option or set the DART_SDK environment variable.");
exit(1);
}
bool sdkDocs = false;
if (args['sdk-docs']) {
sdkDocs = true;
}
var readme = args['sdk-readme'];
if (readme != null && !(new File(readme).existsSync())) {
print("Error: unable to locate the SDK description file at $readme.");
exit(1);
}
Directory inputDir = new Directory(args['input']);
if (!inputDir.existsSync()) {
print("Error: unable to locate the input directory at ${inputDir.path}.");
exit(1);
}
List<String> excludeLibraries =
args['exclude'] == null ? [] : args['exclude'].split(',');
List<String> includeLibraries =
args['include'] == null ? [] : args['include'].split(',');
String url = args['hosted-url'];
String footerFilePath = _resolveTildePath(args['footer']);
if (footerFilePath != null && !new File(footerFilePath).existsSync()) {
print("Error: unable to locate the file with footer at ${footerFilePath}.");
exit(1);
}
String headerFilePath = _resolveTildePath(args['header']);
if (headerFilePath != null && !new File(headerFilePath).existsSync()) {
print("Error: unable to locate the file with header at ${headerFilePath}.");
exit(1);
}
Directory outputDir =
new Directory(path.join(Directory.current.path, defaultOutDir));
if (args['output'] != null) {
outputDir = new Directory(_resolveTildePath(args['output']));
}
Directory packageRootDir;
if (args['package-root'] != null) {
packageRootDir = new Directory(_resolveTildePath(args['package-root']));
}
Map<String, String> urlMappings;
if (args['url-mapping'] != null) {
urlMappings = new Map<String, String>();
for (String mapping in args['url-mapping']) {
int commaIndex = mapping.indexOf(',');
if (commaIndex == -1) {
print('Error: URL mapping "$mapping" does not contain a comma.');
exit(1);
}
String url = mapping.substring(0, commaIndex);
String path = mapping.substring(commaIndex + 1);
urlMappings[url] = path;
}
}
if (args.rest.isNotEmpty) {
var unknownArgs = args.rest.join(' ');
print('Error: detected unknown command-line argument(s): $unknownArgs');
_printUsageAndExit(parser, exitCode: 1);
}
PackageMeta packageMeta = sdkDocs
? new PackageMeta.fromSdk(sdkDir, sdkReadmePath: readme)
: new PackageMeta.fromDir(inputDir);
if (!packageMeta.isValid) {
print('Unable to generate documentation.');
packageMeta.getInvalidReasons().map((r) => '* $r').forEach(print);
exit(1);
}
print("Generating documentation for '${packageMeta}' into "
"${outputDir.absolute.path}${Platform.pathSeparator}");
print('');
var generators = initGenerators(url, headerFilePath, footerFilePath);
var dartdoc = new DartDoc(inputDir, excludeLibraries, sdkDir, generators,
outputDir, packageRootDir, packageMeta, urlMappings, includeLibraries);
try {
DartDocResults results = await dartdoc.generateDocs();
print('\nSuccess! Open file://${results.outDir.absolute.path}/index.html');
} catch (e, st) {
if (e is DartDocFailure) {
stderr.writeln('Generation failed: ${e}.');
exit(1);
} else {
stderr.writeln('Generation failed: ${e}\n${st}');
exit(255);
}
}
}
/// Print help if we are passed the help option.
void _printHelp(ArgParser parser, {int exitCode: 0}) {
print('Generate HTML documentation for Dart libraries.\n');
_printUsageAndExit(parser, exitCode: exitCode);
}
void _printUsageAndExit(ArgParser parser, {int exitCode: 0}) {
print('Usage: dartdoc [OPTIONS]\n');
print(parser.usage);
exit(exitCode);
}
ArgParser _createArgsParser() {
var parser = new ArgParser();
parser.addFlag('help',
abbr: 'h', negatable: false, help: 'Show command help.');
parser.addFlag('version',
help: 'Display the version for $name.', negatable: false);
parser.addOption('dart-sdk',
help: "Location of the Dart SDK. Use if SDK isn't automatically located.");
parser.addFlag('sdk-docs',
help: 'Generate ONLY the docs for the Dart SDK.', negatable: false);
parser.addOption('sdk-readme',
help: 'Path to the SDK description file. Use if generating Dart SDK docs.');
parser.addOption('input',
help: 'Path to source directory', defaultsTo: Directory.current.path);
parser.addOption('output',
help: 'Path to output directory.', defaultsTo: defaultOutDir);
parser.addOption('header',
help: 'path to file containing HTML text, inserted into the header of every page.');
parser.addOption('footer',
help: 'path to file containing HTML text, inserted into the footer of every page.');
parser.addOption('package-root', help: 'The path to the package root.');
parser.addOption('url-mapping',
help: '--url-mapping=libraryUri,/path/to/library.dart directs dartdoc to '
'use "library.dart" as the source for an import of "libraryUri"',
allowMultiple: true,
splitCommas: false);
parser.addOption('exclude',
help: 'Comma-separated list of library names to ignore.');
parser.addOption('include',
help: 'Comma-separated list of library names to generate docs for.');
parser.addOption('hosted-url',
help: 'URL where the docs will be hosted (used to generate the sitemap).');
return parser;
}
String _resolveTildePath(String originalPath) {
if (originalPath == null || !originalPath.startsWith('~/')) {
return originalPath;
}
String homeDir;
if (Platform.isWindows) {
homeDir = path.absolute(Platform.environment['USERPROFILE']);
} else {
homeDir = path.absolute(Platform.environment['HOME']);
}
return path.join(homeDir, originalPath.substring(2));
}