2016-05-01 22:52:51 +00:00
|
|
|
// Copyright 2016 The Chromium Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
|
|
|
import 'dart:async';
|
|
|
|
import 'dart:convert';
|
|
|
|
import 'dart:io';
|
|
|
|
|
2017-02-10 17:55:58 +00:00
|
|
|
import 'package:intl/intl.dart';
|
2016-05-01 22:52:51 +00:00
|
|
|
import 'package:path/path.dart' as path;
|
2017-06-20 18:27:37 +00:00
|
|
|
import 'update_versions.dart';
|
2016-05-01 22:52:51 +00:00
|
|
|
|
2016-05-16 15:28:58 +00:00
|
|
|
const String kDocRoot = 'dev/docs/doc';
|
|
|
|
|
2016-05-01 22:52:51 +00:00
|
|
|
/// This script expects to run with the cwd as the root of the flutter repo. It
|
|
|
|
/// will generate documentation for the packages in `//packages/` and write the
|
|
|
|
/// documentation to `//dev/docs/doc/api/`.
|
2016-08-29 23:20:18 +00:00
|
|
|
///
|
2016-05-16 15:28:58 +00:00
|
|
|
/// This script also updates the index.html file so that it can be placed
|
|
|
|
/// at the root of docs.flutter.io. We are keeping the files inside of
|
|
|
|
/// docs.flutter.io/flutter for now, so we need to manipulate paths
|
|
|
|
/// a bit. See https://github.com/flutter/flutter/issues/3900 for more info.
|
2017-05-11 16:42:08 +00:00
|
|
|
///
|
|
|
|
/// This will only work on UNIX systems, not Windows. It requires that 'git' be
|
|
|
|
/// in your path. It requires that 'flutter' has been run previously. It uses
|
|
|
|
/// the version of Dart downloaded by the 'flutter' tool in this repository and
|
|
|
|
/// will crash if that is absent.
|
2016-05-04 18:43:01 +00:00
|
|
|
Future<Null> main(List<String> args) async {
|
2016-05-01 22:52:51 +00:00
|
|
|
// If we're run from the `tools` dir, set the cwd to the repo root.
|
|
|
|
if (path.basename(Directory.current.path) == 'tools')
|
|
|
|
Directory.current = Directory.current.parent.parent;
|
|
|
|
|
2017-06-20 18:27:37 +00:00
|
|
|
final RawVersion version = new RawVersion('VERSION');
|
|
|
|
|
2016-05-01 22:52:51 +00:00
|
|
|
// Create the pubspec.yaml file.
|
2017-03-04 02:06:08 +00:00
|
|
|
final StringBuffer buf = new StringBuffer('''
|
2016-05-01 22:52:51 +00:00
|
|
|
name: Flutter
|
2017-06-21 15:01:26 +00:00
|
|
|
homepage: https://flutter.io
|
2017-06-20 18:27:37 +00:00
|
|
|
version: $version
|
2016-05-01 22:52:51 +00:00
|
|
|
dependencies:
|
|
|
|
''');
|
2016-05-16 15:28:58 +00:00
|
|
|
for (String package in findPackageNames()) {
|
2016-05-01 22:52:51 +00:00
|
|
|
buf.writeln(' $package:');
|
2016-09-23 03:39:35 +00:00
|
|
|
buf.writeln(' sdk: flutter');
|
2016-05-01 22:52:51 +00:00
|
|
|
}
|
2017-02-10 00:12:09 +00:00
|
|
|
buf.writeln(' platform_integration: 0.0.1');
|
|
|
|
buf.writeln('dependency_overrides:');
|
|
|
|
buf.writeln(' platform_integration:');
|
|
|
|
buf.writeln(' path: platform_integration');
|
2016-05-01 22:52:51 +00:00
|
|
|
new File('dev/docs/pubspec.yaml').writeAsStringSync(buf.toString());
|
|
|
|
|
|
|
|
// Create the library file.
|
2017-03-04 02:06:08 +00:00
|
|
|
final Directory libDir = new Directory('dev/docs/lib');
|
2016-05-01 22:52:51 +00:00
|
|
|
libDir.createSync();
|
|
|
|
|
2017-03-04 02:06:08 +00:00
|
|
|
final StringBuffer contents = new StringBuffer('library temp_doc;\n\n');
|
2016-05-16 15:28:58 +00:00
|
|
|
for (String libraryRef in libraryRefs()) {
|
2016-05-01 22:52:51 +00:00
|
|
|
contents.writeln('import \'package:$libraryRef\';');
|
|
|
|
}
|
|
|
|
new File('dev/docs/lib/temp_doc.dart').writeAsStringSync(contents.toString());
|
|
|
|
|
|
|
|
// Run pub.
|
2017-05-11 16:42:08 +00:00
|
|
|
Process process = await Process.start(
|
|
|
|
'../../bin/cache/dart-sdk/bin/pub',
|
|
|
|
<String>['get'],
|
2016-09-23 03:39:35 +00:00
|
|
|
workingDirectory: 'dev/docs',
|
|
|
|
environment: <String, String>{
|
2017-05-11 16:42:08 +00:00
|
|
|
'FLUTTER_ROOT': Directory.current.path,
|
|
|
|
},
|
2016-09-23 03:39:35 +00:00
|
|
|
);
|
2016-05-16 15:28:58 +00:00
|
|
|
printStream(process.stdout);
|
|
|
|
printStream(process.stderr);
|
2017-03-04 02:06:08 +00:00
|
|
|
final int code = await process.exitCode;
|
2016-05-01 22:52:51 +00:00
|
|
|
if (code != 0)
|
|
|
|
exit(code);
|
|
|
|
|
2017-02-10 17:55:58 +00:00
|
|
|
createFooter('dev/docs/lib/footer.html');
|
|
|
|
|
2017-04-19 17:00:18 +00:00
|
|
|
// Verify which version of dartdoc we're using.
|
2017-05-11 16:42:08 +00:00
|
|
|
final ProcessResult result = Process.runSync(
|
|
|
|
'../../bin/cache/dart-sdk/bin/pub',
|
|
|
|
<String>['global', 'run', 'dartdoc', '--version'],
|
|
|
|
workingDirectory: 'dev/docs',
|
|
|
|
);
|
2017-04-19 17:00:18 +00:00
|
|
|
print('\n${result.stdout}');
|
|
|
|
|
2016-08-29 23:20:18 +00:00
|
|
|
// Generate the documentation.
|
2017-03-04 02:06:08 +00:00
|
|
|
final List<String> args = <String>[
|
2016-05-01 22:52:51 +00:00
|
|
|
'global', 'run', 'dartdoc',
|
|
|
|
'--header', 'styles.html',
|
|
|
|
'--header', 'analytics.html',
|
2017-05-25 16:42:55 +00:00
|
|
|
'--footer-text', 'lib/footer.html',
|
2016-05-01 22:52:51 +00:00
|
|
|
'--exclude', 'temp_doc',
|
|
|
|
'--favicon=favicon.ico',
|
2017-05-04 20:28:07 +00:00
|
|
|
'--use-categories',
|
2017-05-19 15:47:14 +00:00
|
|
|
'--category-order', 'flutter,Dart Core,flutter_test,flutter_driver',
|
2016-05-01 22:52:51 +00:00
|
|
|
];
|
|
|
|
|
2017-01-11 17:00:10 +00:00
|
|
|
for (String libraryRef in libraryRefs(diskPath: true)) {
|
2016-05-01 22:52:51 +00:00
|
|
|
args.add('--include-external');
|
2017-01-11 17:00:10 +00:00
|
|
|
args.add(libraryRef);
|
2016-05-01 22:52:51 +00:00
|
|
|
}
|
|
|
|
|
2017-05-11 16:42:08 +00:00
|
|
|
process = await Process.start(
|
|
|
|
'../../bin/cache/dart-sdk/bin/pub',
|
|
|
|
args,
|
|
|
|
workingDirectory: 'dev/docs',
|
|
|
|
);
|
2016-05-16 15:28:58 +00:00
|
|
|
printStream(process.stdout);
|
|
|
|
printStream(process.stderr);
|
2017-03-04 02:06:08 +00:00
|
|
|
final int exitCode = await process.exitCode;
|
2016-05-16 15:28:58 +00:00
|
|
|
|
|
|
|
if (exitCode != 0)
|
|
|
|
exit(exitCode);
|
|
|
|
|
2016-11-09 23:16:13 +00:00
|
|
|
sanityCheckDocs();
|
|
|
|
|
2016-05-16 15:28:58 +00:00
|
|
|
createIndexAndCleanup();
|
|
|
|
}
|
|
|
|
|
2017-02-10 17:55:58 +00:00
|
|
|
void createFooter(String footerPath) {
|
2017-03-04 02:06:08 +00:00
|
|
|
final ProcessResult gitResult = Process.runSync('git', <String>['rev-parse', 'HEAD']);
|
|
|
|
final String gitHead = (gitResult.exitCode == 0) ? gitResult.stdout.trim() : 'unknown';
|
2017-02-10 17:55:58 +00:00
|
|
|
|
2017-03-04 02:06:08 +00:00
|
|
|
final String timestamp = new DateFormat('yyyy-MM-dd HH:mm').format(new DateTime.now());
|
2017-02-10 17:55:58 +00:00
|
|
|
|
|
|
|
new File(footerPath).writeAsStringSync(
|
2017-05-25 16:42:55 +00:00
|
|
|
'• </span class="no-break">$timestamp<span> '
|
|
|
|
'• </span class="no-break">$gitHead</span>'
|
2017-02-10 17:55:58 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2016-11-09 23:16:13 +00:00
|
|
|
void sanityCheckDocs() {
|
2017-04-21 15:11:33 +00:00
|
|
|
// TODO(jcollins-g): remove old_sdk_canaries for dartdoc >= 0.10.0
|
|
|
|
final List<String> oldSdkCanaries = <String>[
|
2017-04-12 20:33:02 +00:00
|
|
|
'$kDocRoot/api/dart.io/File-class.html',
|
2017-04-19 22:42:02 +00:00
|
|
|
'$kDocRoot/api/dart.ui/Canvas-class.html',
|
|
|
|
'$kDocRoot/api/dart.ui/Canvas/drawRect.html',
|
2017-04-21 15:11:33 +00:00
|
|
|
];
|
|
|
|
final List<String> newSdkCanaries = <String>[
|
|
|
|
'$kDocRoot/api/dart-io/File-class.html',
|
|
|
|
'$kDocRoot/api/dart-ui/Canvas-class.html',
|
|
|
|
'$kDocRoot/api/dart-ui/Canvas/drawRect.html',
|
|
|
|
];
|
|
|
|
final List<String> canaries = <String>[
|
2017-01-12 17:47:50 +00:00
|
|
|
'$kDocRoot/api/flutter_test/WidgetTester/pumpWidget.html',
|
2016-11-09 23:16:13 +00:00
|
|
|
'$kDocRoot/api/material/Material-class.html',
|
|
|
|
'$kDocRoot/api/material/Tooltip-class.html',
|
|
|
|
'$kDocRoot/api/widgets/Widget-class.html',
|
|
|
|
];
|
2017-04-21 15:11:33 +00:00
|
|
|
bool oldMissing = false;
|
|
|
|
for (String canary in oldSdkCanaries) {
|
|
|
|
if (!new File(canary).existsSync()) {
|
|
|
|
oldMissing = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (oldMissing)
|
|
|
|
canaries.addAll(newSdkCanaries);
|
2016-11-09 23:16:13 +00:00
|
|
|
for (String canary in canaries) {
|
|
|
|
if (!new File(canary).existsSync())
|
|
|
|
throw new Exception('Missing "$canary", which probably means the documentation failed to build correctly.');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-16 15:28:58 +00:00
|
|
|
/// Creates a custom index.html because we try to maintain old
|
|
|
|
/// paths. Cleanup unused index.html files no longer needed.
|
|
|
|
void createIndexAndCleanup() {
|
|
|
|
print('\nCreating a custom index.html in $kDocRoot/index.html');
|
2016-05-16 20:05:13 +00:00
|
|
|
removeOldFlutterDocsDir();
|
2016-05-16 15:28:58 +00:00
|
|
|
renameApiDir();
|
|
|
|
copyIndexToRootOfDocs();
|
|
|
|
addHtmlBaseToIndex();
|
|
|
|
putRedirectInOldIndexLocation();
|
|
|
|
print('\nDocs ready to go!');
|
|
|
|
}
|
|
|
|
|
2016-05-16 20:05:13 +00:00
|
|
|
void removeOldFlutterDocsDir() {
|
|
|
|
try {
|
|
|
|
new Directory('$kDocRoot/flutter').deleteSync(recursive: true);
|
2016-07-23 05:21:04 +00:00
|
|
|
} catch (e) {
|
2016-05-16 20:05:13 +00:00
|
|
|
// If the directory does not exist, that's OK.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-16 15:28:58 +00:00
|
|
|
void renameApiDir() {
|
|
|
|
new Directory('$kDocRoot/api').renameSync('$kDocRoot/flutter');
|
|
|
|
}
|
|
|
|
|
2016-07-23 05:21:04 +00:00
|
|
|
void copyIndexToRootOfDocs() {
|
|
|
|
new File('$kDocRoot/flutter/index.html').copySync('$kDocRoot/index.html');
|
2016-05-16 15:28:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void addHtmlBaseToIndex() {
|
2017-03-04 02:06:08 +00:00
|
|
|
final File indexFile = new File('$kDocRoot/index.html');
|
2016-05-16 15:28:58 +00:00
|
|
|
String indexContents = indexFile.readAsStringSync();
|
|
|
|
indexContents = indexContents.replaceFirst('</title>\n',
|
|
|
|
'</title>\n <base href="./flutter/">\n');
|
2017-02-10 00:12:09 +00:00
|
|
|
indexContents = indexContents.replaceAll(
|
|
|
|
'href="Android/Android-library.html"',
|
|
|
|
'href="https://docs.flutter.io/javadoc/"'
|
|
|
|
);
|
2016-05-16 15:28:58 +00:00
|
|
|
indexFile.writeAsStringSync(indexContents);
|
|
|
|
}
|
|
|
|
|
|
|
|
void putRedirectInOldIndexLocation() {
|
2017-03-04 02:06:08 +00:00
|
|
|
final String metaTag = '<meta http-equiv="refresh" content="0;URL=../index.html">';
|
2016-05-16 15:28:58 +00:00
|
|
|
new File('$kDocRoot/flutter/index.html').writeAsStringSync(metaTag);
|
2016-05-01 22:52:51 +00:00
|
|
|
}
|
|
|
|
|
2016-05-16 15:28:58 +00:00
|
|
|
List<String> findPackageNames() {
|
|
|
|
return findPackages().map((Directory dir) => path.basename(dir.path)).toList();
|
2016-05-01 22:52:51 +00:00
|
|
|
}
|
|
|
|
|
2017-01-11 17:00:10 +00:00
|
|
|
/// Finds all packages in the Flutter SDK
|
2016-05-16 15:28:58 +00:00
|
|
|
List<Directory> findPackages() {
|
2016-05-01 22:52:51 +00:00
|
|
|
return new Directory('packages')
|
|
|
|
.listSync()
|
2016-11-15 20:35:50 +00:00
|
|
|
.where((FileSystemEntity entity) {
|
|
|
|
if (entity is! Directory)
|
|
|
|
return false;
|
2017-03-04 02:06:08 +00:00
|
|
|
final File pubspec = new File('${entity.path}/pubspec.yaml');
|
2016-11-15 20:35:50 +00:00
|
|
|
// TODO(ianh): Use a real YAML parser here
|
|
|
|
return !pubspec.readAsStringSync().contains('nodoc: true');
|
2016-05-01 22:52:51 +00:00
|
|
|
})
|
|
|
|
.toList();
|
|
|
|
}
|
|
|
|
|
2017-01-11 17:00:10 +00:00
|
|
|
/// Returns import or on-disk paths for all libraries in the Flutter SDK.
|
|
|
|
///
|
|
|
|
/// diskPath toggles between import paths vs. disk paths.
|
|
|
|
Iterable<String> libraryRefs({ bool diskPath: false }) sync* {
|
2016-05-16 15:28:58 +00:00
|
|
|
for (Directory dir in findPackages()) {
|
2017-03-04 02:06:08 +00:00
|
|
|
final String dirName = path.basename(dir.path);
|
2016-05-01 22:52:51 +00:00
|
|
|
for (FileSystemEntity file in new Directory('${dir.path}/lib').listSync()) {
|
2017-01-11 17:00:10 +00:00
|
|
|
if (file is File && file.path.endsWith('.dart')) {
|
|
|
|
if (diskPath)
|
|
|
|
yield '$dirName/lib/${path.basename(file.path)}';
|
|
|
|
else
|
|
|
|
yield '$dirName/${path.basename(file.path)}';
|
|
|
|
}
|
2016-05-01 22:52:51 +00:00
|
|
|
}
|
|
|
|
}
|
2017-02-10 00:12:09 +00:00
|
|
|
|
|
|
|
// Add a fake package for platform integration APIs.
|
|
|
|
if (diskPath)
|
|
|
|
yield 'platform_integration/lib/android.dart';
|
|
|
|
else
|
|
|
|
yield 'platform_integration/android.dart';
|
2016-05-01 22:52:51 +00:00
|
|
|
}
|
|
|
|
|
2016-05-16 15:28:58 +00:00
|
|
|
void printStream(Stream<List<int>> stream) {
|
2016-05-01 22:52:51 +00:00
|
|
|
stream
|
|
|
|
.transform(UTF8.decoder)
|
|
|
|
.transform(const LineSplitter())
|
|
|
|
.listen(print);
|
|
|
|
}
|