Add generator file.
Expects a file to be placed in /third_party/preferred_extension.mime.types.
(Or pointed to on command line).
diff --git a/pkgs/mime/tool/generate_defaults.dart b/pkgs/mime/tool/generate_defaults.dart
new file mode 100644
index 0000000..4124432
--- /dev/null
+++ b/pkgs/mime/tool/generate_defaults.dart
@@ -0,0 +1,112 @@
+// Copyright (c) 2024, 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.
+
+import 'dart:io';
+
+const startMarker = '\n // GENERATED by tool/generate_defaults.dart\n';
+const endMarker = '\n // END GENERATED\n';
+const androidMimeTypesPath = '../third_party/preferred_extension.mime.types';
+const extensionLibraryPath = '../lib/src/extension.dart';
+
+void main(List<String> args) {
+ var dryRun = false;
+ var printUsage = false;
+ var hadInvalidArgument = false;
+ Uri? mimeTypesOverride;
+ for (var arg in args) {
+ if (arg == '-h' || arg == '--help') {
+ printUsage = true;
+ } else if (arg == '-n' || arg == '--dryrun' || arg == '--dry-run') {
+ dryRun = true;
+ } else if (!arg.startsWith('-') && mimeTypesOverride == null) {
+ mimeTypesOverride = Directory.current.uri.resolve(arg);
+ } else {
+ hadInvalidArgument = true;
+ stderr.writeln('Unexpected command-line argument: $arg');
+ }
+ }
+ if (hadInvalidArgument) {
+ stderr.writeln(usage);
+ exit(1);
+ } else if (printUsage) {
+ stdout.writeln(usage);
+ exit(0);
+ }
+ final script = Platform.script;
+ final library = script.resolve(extensionLibraryPath);
+ final libraryFile = File.fromUri(library);
+ final librarySource = libraryFile.readAsStringSync();
+ final int startTagOffset, endTagOffset;
+ if (librarySource.indexOf(startMarker) case >= 0 && final start) {
+ startTagOffset = start;
+ if (librarySource.indexOf(endMarker, start + startMarker.length)
+ case >= 0 && final end) {
+ endTagOffset = end;
+ } else {
+ stderr.writeln('Library file (${libraryFile.path})\n'
+ ' does not contain end marker: $endMarker');
+ exit(1);
+ }
+ } else {
+ stderr.writeln('Library file (${libraryFile.path})\n'
+ ' does not contain start marker: $startMarker');
+ exit(1);
+ }
+
+ final androidDefaults =
+ mimeTypesOverride ?? script.resolve(androidMimeTypesPath);
+ final defaultsFile = File.fromUri(androidDefaults);
+ if (!defaultsFile.existsSync()) {
+ stderr.writeln('Cannot find file: ${androidDefaults.toFilePath()}');
+ if (mimeTypesOverride == null) {
+ stderr.writeln('Download file from rx: \n'
+ // ignore: missing_whitespace_between_adjacent_strings
+ ' https://android.googlesource.com/platform/frameworks/'
+ 'base/+/main/mime/java-res/android.mime.types');
+ }
+ exit(1);
+ }
+ final defaults = defaultsFile.readAsLinesSync();
+ final mapping = <String, String>{};
+ for (var line in defaults) {
+ if (line.startsWith('#')) continue;
+ final parts = line.split(' ');
+ var mediaType = parts[0];
+ var defaultExtension = parts[1];
+ if (defaultExtension.startsWith('?')) {
+ defaultExtension = defaultExtension.substring(1);
+ }
+ if (mediaType.startsWith('?')) {
+ mediaType = mediaType.substring(1);
+ mapping[mediaType] ??= defaultExtension;
+ } else {
+ mapping[mediaType] = defaultExtension;
+ }
+ }
+ final sortedKeys = mapping.keys.toList()..sort();
+ final newMapping =
+ [for (var key in sortedKeys) " '$key': '${mapping[key]}',"].join('\n');
+ final newLibrarySource = librarySource.replaceRange(
+ startTagOffset + startMarker.length, endTagOffset, newMapping);
+ if (newLibrarySource != librarySource) {
+ if (!dryRun) {
+ libraryFile.writeAsStringSync(newLibrarySource);
+ stdout.writeln('Changes to mapping written to file.');
+ } else {
+ stdout.writeln('Changes to mapping. (Not written as dry-run.)');
+ }
+ } else {
+ stdout.writeln('No change to mapping');
+ }
+}
+
+const String usage = '''
+Usage: dart tool/generate_defaults.dart [-h|-n] [MIMETYPES]
+
+--help or -h : Print this usage information
+--dry-run or -n : Don't write changes back to library
+MIMETYPES : Path to file in the `mime.types` format
+ where the first extension for each media type
+ is the preferred extension.
+''';