From 9355522ea32d2e6a069b657680949fcb2533c9b9 Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <178714+mx1up@users.noreply.github.com> Date: Thu, 5 Jan 2023 18:44:08 +0100 Subject: [PATCH 01/38] initial code from pr !15 --- pkgs/mime/README.md | 19 ++++++++++++++ pkgs/mime/lib/mime.dart | 1 + pkgs/mime/lib/src/extension.dart | 33 ++++++++++++++++++++++++ pkgs/mime/test/extension_test.dart | 41 ++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+) create mode 100644 pkgs/mime/lib/src/extension.dart create mode 100644 pkgs/mime/test/extension_test.dart diff --git a/pkgs/mime/README.md b/pkgs/mime/README.md index 8a814150c..eb4ab2ce4 100644 --- a/pkgs/mime/README.md +++ b/pkgs/mime/README.md @@ -57,3 +57,22 @@ request .map((part) => part.fold(0, (p, d) => p + d)) .listen((length) => print('Part with length $length')); ``` + +## Determining file extension by MIME type + +The top level function `lookupExtension` can be used to determine the +file extension of a given MIME type. + +```dart +print(lookupExtension('text/html')); // Will print html +print(lookupExtension('image/jpeg')); // Will print jpg +print(lookupExtension('application/pdf')); // Will print pdf +``` + +You can override the default MIME type-extension mapping using +`addMimeType`: + +```dart +addMimeType('image/jpeg', 'jpeg'); +print(lookupExtension('image/jpeg')); // Will print jpeg +``` diff --git a/pkgs/mime/lib/mime.dart b/pkgs/mime/lib/mime.dart index f2c446403..cb450981f 100644 --- a/pkgs/mime/lib/mime.dart +++ b/pkgs/mime/lib/mime.dart @@ -9,6 +9,7 @@ /// [Internet media type](http://en.wikipedia.org/wiki/Internet_media_type). library; +export 'src/extension.dart'; export 'src/mime_multipart_transformer.dart'; export 'src/mime_shared.dart'; export 'src/mime_type.dart'; diff --git a/pkgs/mime/lib/src/extension.dart b/pkgs/mime/lib/src/extension.dart new file mode 100644 index 000000000..e27948dcf --- /dev/null +++ b/pkgs/mime/lib/src/extension.dart @@ -0,0 +1,33 @@ +// Copyright (c) 2023, 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 'default_extension_map.dart'; + +/// Add an override for common extensions since different extensions may map +/// to the same MIME type. +final Map _preferredExtensionsMap = { + 'application/vnd.ms-excel': 'xls', + 'image/jpeg': 'jpg', + 'text/x-c': 'c' +}; + +/// Lookup file extension by a given MIME type. +/// If no extension is found, `null` is returned. +String lookupExtension(String mimeType) { + if (_preferredExtensionsMap.containsKey(mimeType)) { + return _preferredExtensionsMap[mimeType]; + } + String extension; + defaultExtensionMap.forEach((String ext, String test) { + if (mimeType.toLowerCase() == test) { + extension = ext; + } + }); + return extension; +} + +/// Allow for a user-specified MIME type-extension map that overrides the default. +void addMimeType(String mimeType, String extension) { + _preferredExtensionsMap[mimeType] = extension; +} \ No newline at end of file diff --git a/pkgs/mime/test/extension_test.dart b/pkgs/mime/test/extension_test.dart new file mode 100644 index 000000000..c5e1b495e --- /dev/null +++ b/pkgs/mime/test/extension_test.dart @@ -0,0 +1,41 @@ +// Copyright (c) 2015, 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 'package:test/test.dart'; +import 'package:mime/mime.dart'; + +void main() { + group('lookup-mime-type', () { + test('valid-mime-type', () { + expect(lookupExtension('application/dart'), equals('dart')); + expect(lookupExtension('application/javascript'), equals('js')); + expect(lookupExtension('application/pdf'), equals('pdf')); + expect(lookupExtension('application/vnd.ms-excel'), equals('xls')); + expect(lookupExtension('application/xhtml+xml'), equals('xhtml')); + expect(lookupExtension('image/jpeg'), equals('jpg')); + expect(lookupExtension('image/png'), equals('png')); + expect(lookupExtension('text/css'), equals('css')); + expect(lookupExtension('text/html'), equals('html')); + expect(lookupExtension('text/plain'), equals('txt')); + expect(lookupExtension('text/x-c'), equals('c')); + }); + + test('invalid-mime-type', () { + expect(lookupExtension('invalid-content-type'), isNull); + expect(lookupExtension('invalid/content-type'), isNull); + }); + }); + + group('add-mime-type', () { + test('new-mime-type', () { + addMimeType('custom/type', 'ct'); + expect(lookupExtension('custom/type'), equals('ct')); + }); + + test('overridden-mime-type', () { + addMimeType('image/jpeg', 'jpeg'); + expect(lookupExtension('image/jpeg'), equals('jpeg')); + }); + }); +} \ No newline at end of file From e7f328eb09fecb47f6b4157c328b39cc8b64c504 Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <178714+mx1up@users.noreply.github.com> Date: Thu, 5 Jan 2023 18:47:40 +0100 Subject: [PATCH 02/38] update copyright year --- pkgs/mime/test/extension_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/mime/test/extension_test.dart b/pkgs/mime/test/extension_test.dart index c5e1b495e..51432e8e7 100644 --- a/pkgs/mime/test/extension_test.dart +++ b/pkgs/mime/test/extension_test.dart @@ -1,4 +1,4 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2023, 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. From 7eb72c38973812bc0ada281297080ac49a9fa470 Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <178714+mx1up@users.noreply.github.com> Date: Fri, 6 Jan 2023 17:13:06 +0100 Subject: [PATCH 03/38] improve lookup: case-insensitive and use firstWhereOrNull instead of for loop --- pkgs/mime/lib/src/extension.dart | 25 ++++++++++++------------- pkgs/mime/pubspec.yaml | 3 +++ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/pkgs/mime/lib/src/extension.dart b/pkgs/mime/lib/src/extension.dart index e27948dcf..70e37a5f5 100644 --- a/pkgs/mime/lib/src/extension.dart +++ b/pkgs/mime/lib/src/extension.dart @@ -2,6 +2,8 @@ // 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 'package:collection/collection.dart'; + import 'default_extension_map.dart'; /// Add an override for common extensions since different extensions may map @@ -14,20 +16,17 @@ final Map _preferredExtensionsMap = { /// Lookup file extension by a given MIME type. /// If no extension is found, `null` is returned. -String lookupExtension(String mimeType) { - if (_preferredExtensionsMap.containsKey(mimeType)) { - return _preferredExtensionsMap[mimeType]; +String? lookupExtension(String mimeType) { + final mimeTypeLC = mimeType.toLowerCase(); + if (_preferredExtensionsMap.containsKey(mimeTypeLC)) { + return _preferredExtensionsMap[mimeTypeLC]!; } - String extension; - defaultExtensionMap.forEach((String ext, String test) { - if (mimeType.toLowerCase() == test) { - extension = ext; - } - }); - return extension; + return defaultExtensionMap.entries + .firstWhereOrNull((entry) => entry.value == mimeTypeLC)?.key; } -/// Allow for a user-specified MIME type-extension map that overrides the default. +/// Allow for a user-specified MIME type-extension mapping that overrides the +/// default. void addMimeType(String mimeType, String extension) { - _preferredExtensionsMap[mimeType] = extension; -} \ No newline at end of file + _preferredExtensionsMap[mimeType.toLowerCase()] = extension.toLowerCase(); +} diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 8d3c49823..0dec004e1 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -13,6 +13,9 @@ topics: environment: sdk: ^3.2.0 +dependencies: + collection: ^1.17.0 + dev_dependencies: dart_flutter_team_lints: ^3.0.0 test: ^1.16.0 From 80079be5dc826cdc5ef1a902bb607a37e831c81c Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <178714+mx1up@users.noreply.github.com> Date: Fri, 6 Jan 2023 17:13:33 +0100 Subject: [PATCH 04/38] tests cleanup --- pkgs/mime/test/extension_test.dart | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/pkgs/mime/test/extension_test.dart b/pkgs/mime/test/extension_test.dart index 51432e8e7..f4ad5b347 100644 --- a/pkgs/mime/test/extension_test.dart +++ b/pkgs/mime/test/extension_test.dart @@ -2,28 +2,31 @@ // 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 'package:test/test.dart'; import 'package:mime/mime.dart'; +import 'package:test/test.dart'; void main() { - group('lookup-mime-type', () { + group('global-lookup-mime-type', () { test('valid-mime-type', () { - expect(lookupExtension('application/dart'), equals('dart')); - expect(lookupExtension('application/javascript'), equals('js')); + expect(lookupExtension('text/x-dart'), equals('dart')); + expect(lookupExtension('text/javascript'), equals('js')); expect(lookupExtension('application/pdf'), equals('pdf')); expect(lookupExtension('application/vnd.ms-excel'), equals('xls')); - expect(lookupExtension('application/xhtml+xml'), equals('xhtml')); + expect(lookupExtension('application/xhtml+xml'), equals('xht')); expect(lookupExtension('image/jpeg'), equals('jpg')); expect(lookupExtension('image/png'), equals('png')); expect(lookupExtension('text/css'), equals('css')); - expect(lookupExtension('text/html'), equals('html')); - expect(lookupExtension('text/plain'), equals('txt')); + expect(lookupExtension('text/html'), equals('htm')); + // expect(lookupExtension('text/plain'), equals('txt')); expect(lookupExtension('text/x-c'), equals('c')); }); test('invalid-mime-type', () { - expect(lookupExtension('invalid-content-type'), isNull); - expect(lookupExtension('invalid/content-type'), isNull); + expect(lookupExtension('invalid-mime-type'), isNull); + }); + + test('unknown-mime-type', () { + expect(lookupExtension('application/to-be-invented'), isNull); }); }); From d3ce7aea5ac116a5ea905d58d78bacb1904b5620 Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <178714+mx1up@users.noreply.github.com> Date: Fri, 6 Jan 2023 17:16:14 +0100 Subject: [PATCH 05/38] check baseline --- pkgs/mime/test/extension_test.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/mime/test/extension_test.dart b/pkgs/mime/test/extension_test.dart index f4ad5b347..f096f1b54 100644 --- a/pkgs/mime/test/extension_test.dart +++ b/pkgs/mime/test/extension_test.dart @@ -32,11 +32,13 @@ void main() { group('add-mime-type', () { test('new-mime-type', () { + expect(lookupExtension('custom/type'), isNull); addMimeType('custom/type', 'ct'); expect(lookupExtension('custom/type'), equals('ct')); }); test('overridden-mime-type', () { + expect(lookupExtension('image/jpeg'), equals('jpg')); addMimeType('image/jpeg', 'jpeg'); expect(lookupExtension('image/jpeg'), equals('jpeg')); }); From 29050ff8830e977cb4242b89e9fbddcaaf3986a5 Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <178714+mx1up@users.noreply.github.com> Date: Fri, 6 Jan 2023 17:47:59 +0100 Subject: [PATCH 06/38] test to check whether each mimetype with multiple extensions has a preferred extension defined --- pkgs/mime/lib/src/extension.dart | 3 +++ pkgs/mime/test/extension_test.dart | 22 +++++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/pkgs/mime/lib/src/extension.dart b/pkgs/mime/lib/src/extension.dart index 70e37a5f5..fdc34b2ec 100644 --- a/pkgs/mime/lib/src/extension.dart +++ b/pkgs/mime/lib/src/extension.dart @@ -30,3 +30,6 @@ String? lookupExtension(String mimeType) { void addMimeType(String mimeType, String extension) { _preferredExtensionsMap[mimeType.toLowerCase()] = extension.toLowerCase(); } + +bool hasPreferredExtension(String mimeType) => + _preferredExtensionsMap.containsKey(mimeType.toLowerCase()); diff --git a/pkgs/mime/test/extension_test.dart b/pkgs/mime/test/extension_test.dart index f096f1b54..06106d267 100644 --- a/pkgs/mime/test/extension_test.dart +++ b/pkgs/mime/test/extension_test.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:mime/mime.dart'; +import 'package:mime/src/default_extension_map.dart'; import 'package:test/test.dart'; void main() { @@ -42,5 +43,24 @@ void main() { addMimeType('image/jpeg', 'jpeg'); expect(lookupExtension('image/jpeg'), equals('jpeg')); }); + + test('check-preferred-present-for-non-unique', () { + final mimeTypeToExtMap = >{}; + for (var entry in defaultExtensionMap.entries) { + final extensions = mimeTypeToExtMap.putIfAbsent(entry.value, () => []); + extensions.add(entry.key); + } + final mimeTypesWithMultipleExtensions = Map.fromEntries(mimeTypeToExtMap + .entries + .where((element) => element.value.length > 1)); + for (var mimeType in mimeTypesWithMultipleExtensions.keys) { + expect( + hasPreferredExtension(mimeType), + isTrue, + reason: 'mimeType $mimeType with multiple extension, ' + 'does not have preferred extension defined', + ); + } + }); }); -} \ No newline at end of file +} From 84f3bd8f83636e79e7f11f47e7d96058b729ee78 Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <178714+mx1up@users.noreply.github.com> Date: Fri, 6 Jan 2023 17:48:08 +0100 Subject: [PATCH 07/38] reformat --- pkgs/mime/lib/src/extension.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgs/mime/lib/src/extension.dart b/pkgs/mime/lib/src/extension.dart index fdc34b2ec..765c61093 100644 --- a/pkgs/mime/lib/src/extension.dart +++ b/pkgs/mime/lib/src/extension.dart @@ -22,7 +22,8 @@ String? lookupExtension(String mimeType) { return _preferredExtensionsMap[mimeTypeLC]!; } return defaultExtensionMap.entries - .firstWhereOrNull((entry) => entry.value == mimeTypeLC)?.key; + .firstWhereOrNull((entry) => entry.value == mimeTypeLC) + ?.key; } /// Allow for a user-specified MIME type-extension mapping that overrides the From c27fa377aba51394578559cc435e31193cd705f3 Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <178714+mx1up@users.noreply.github.com> Date: Fri, 6 Jan 2023 19:05:56 +0100 Subject: [PATCH 08/38] apparently, the function already existed :roll-eyes: but the preferred extension not. for backwards compatibility: add `extensionFromMimeOrNull`, and add an `orElse` param for `extensionFromMime` as the standard behavior results in creating an invalid filename. --- pkgs/mime/lib/src/extension.dart | 10 +++++-- pkgs/mime/lib/src/mime_type.dart | 14 --------- pkgs/mime/test/extension_test.dart | 46 +++++++++++++++++++----------- 3 files changed, 37 insertions(+), 33 deletions(-) diff --git a/pkgs/mime/lib/src/extension.dart b/pkgs/mime/lib/src/extension.dart index 765c61093..4a356a17d 100644 --- a/pkgs/mime/lib/src/extension.dart +++ b/pkgs/mime/lib/src/extension.dart @@ -14,9 +14,12 @@ final Map _preferredExtensionsMap = { 'text/x-c': 'c' }; -/// Lookup file extension by a given MIME type. +/// Lookup file extension for a given MIME type. +/// +/// If there are multiple extensions for [mimeType], return preferred extension +/// if defined, or the first occurrence in the map. /// If no extension is found, `null` is returned. -String? lookupExtension(String mimeType) { +String? extensionFromMimeOrNull(String mimeType) { final mimeTypeLC = mimeType.toLowerCase(); if (_preferredExtensionsMap.containsKey(mimeTypeLC)) { return _preferredExtensionsMap[mimeTypeLC]!; @@ -26,6 +29,9 @@ String? lookupExtension(String mimeType) { ?.key; } +String extensionFromMime(String mimeType, {String? orElse}) => + extensionFromMimeOrNull(mimeType) ?? orElse ?? mimeType; + /// Allow for a user-specified MIME type-extension mapping that overrides the /// default. void addMimeType(String mimeType, String extension) { diff --git a/pkgs/mime/lib/src/mime_type.dart b/pkgs/mime/lib/src/mime_type.dart index 03121c97b..9cf9194a1 100644 --- a/pkgs/mime/lib/src/mime_type.dart +++ b/pkgs/mime/lib/src/mime_type.dart @@ -23,20 +23,6 @@ int get defaultMagicNumbersMaxLength => _globalResolver.magicNumbersMaxLength; String? lookupMimeType(String path, {List? headerBytes}) => _globalResolver.lookup(path, headerBytes: headerBytes); -/// Returns the extension for the given MIME type. -/// -/// If there are multiple extensions for [mime], return the first occurrence in -/// the map. If there are no extensions for [mime], return [mime]. -String extensionFromMime(String mime) { - mime = mime.toLowerCase(); - for (final entry in defaultExtensionMap.entries) { - if (defaultExtensionMap[entry.key] == mime) { - return entry.key; - } - } - return mime; -} - /// MIME-type resolver class, used to customize the lookup of mime-types. class MimeTypeResolver { final Map _extensionMap = {}; diff --git a/pkgs/mime/test/extension_test.dart b/pkgs/mime/test/extension_test.dart index 06106d267..62c084fc1 100644 --- a/pkgs/mime/test/extension_test.dart +++ b/pkgs/mime/test/extension_test.dart @@ -9,39 +9,51 @@ import 'package:test/test.dart'; void main() { group('global-lookup-mime-type', () { test('valid-mime-type', () { - expect(lookupExtension('text/x-dart'), equals('dart')); - expect(lookupExtension('text/javascript'), equals('js')); - expect(lookupExtension('application/pdf'), equals('pdf')); - expect(lookupExtension('application/vnd.ms-excel'), equals('xls')); - expect(lookupExtension('application/xhtml+xml'), equals('xht')); - expect(lookupExtension('image/jpeg'), equals('jpg')); - expect(lookupExtension('image/png'), equals('png')); - expect(lookupExtension('text/css'), equals('css')); - expect(lookupExtension('text/html'), equals('htm')); - // expect(lookupExtension('text/plain'), equals('txt')); - expect(lookupExtension('text/x-c'), equals('c')); + expect(extensionFromMime('text/x-dart'), equals('dart')); + expect(extensionFromMime('text/javascript'), equals('js')); + expect(extensionFromMime('application/pdf'), equals('pdf')); + expect(extensionFromMime('application/vnd.ms-excel'), equals('xls')); + expect(extensionFromMime('application/xhtml+xml'), equals('xht')); + expect(extensionFromMime('image/jpeg'), equals('jpg')); + expect(extensionFromMime('image/png'), equals('png')); + expect(extensionFromMime('text/css'), equals('css')); + expect(extensionFromMime('text/html'), equals('htm')); + // expect(extensionFromMime('text/plain'), equals('txt')); + expect(extensionFromMime('text/x-c'), equals('c')); }); test('invalid-mime-type', () { - expect(lookupExtension('invalid-mime-type'), isNull); + expect(extensionFromMime('invalid-mime-type'), 'invalid-mime-type'); + expect(extensionFromMime('invalid/mime/type'), 'invalid/mime/type'); + + expect( + extensionFromMime('invalid-mime-type', orElse: 'invalid'), 'invalid'); + expect( + extensionFromMime('invalid/mime/type', orElse: 'invalid'), 'invalid'); + + expect(extensionFromMimeOrNull('invalid-mime-type'), isNull); + expect(extensionFromMimeOrNull('invalid/mime/type'), isNull); }); test('unknown-mime-type', () { - expect(lookupExtension('application/to-be-invented'), isNull); + expect(extensionFromMime('application/to-be-invented'), + 'application/to-be-invented'); + + expect(extensionFromMimeOrNull('application/to-be-invented'), isNull); }); }); group('add-mime-type', () { test('new-mime-type', () { - expect(lookupExtension('custom/type'), isNull); + expect(extensionFromMimeOrNull('custom/type'), isNull); addMimeType('custom/type', 'ct'); - expect(lookupExtension('custom/type'), equals('ct')); + expect(extensionFromMime('custom/type'), equals('ct')); }); test('overridden-mime-type', () { - expect(lookupExtension('image/jpeg'), equals('jpg')); + expect(extensionFromMime('image/jpeg'), equals('jpg')); addMimeType('image/jpeg', 'jpeg'); - expect(lookupExtension('image/jpeg'), equals('jpeg')); + expect(extensionFromMime('image/jpeg'), equals('jpeg')); }); test('check-preferred-present-for-non-unique', () { From f2a62f7f57df1367728cd8b99f784a063685e672 Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <178714+mx1up@users.noreply.github.com> Date: Fri, 6 Jan 2023 19:07:59 +0100 Subject: [PATCH 09/38] probably better not to enforce a preferred extension for mime types with multiple extensions. There are quite some, but most of them are legacy, and new mimetypes tend to map to 1 extension (no 3 chars limit anymore), so less useful in the future --- pkgs/mime/CONTRIBUTING.md | 4 ++++ pkgs/mime/lib/src/extension.dart | 3 --- pkgs/mime/test/extension_test.dart | 20 -------------------- 3 files changed, 4 insertions(+), 23 deletions(-) diff --git a/pkgs/mime/CONTRIBUTING.md b/pkgs/mime/CONTRIBUTING.md index 6f5e0ea67..50a36a2d7 100644 --- a/pkgs/mime/CONTRIBUTING.md +++ b/pkgs/mime/CONTRIBUTING.md @@ -31,3 +31,7 @@ All files in the project must start with the following header. Contributions made by corporations are covered by a different agreement than the one above, the [Software Grant and Corporate Contributor License Agreement](https://developers.google.com/open-source/cla/corporate). + +### Adding an extension to an existing MIME type +If a MIME type ends up with multiple extensions, it is recommended to define a +preferred extension in `_preferredExtensionsMap` in `extension.dart` \ No newline at end of file diff --git a/pkgs/mime/lib/src/extension.dart b/pkgs/mime/lib/src/extension.dart index 4a356a17d..04a80718d 100644 --- a/pkgs/mime/lib/src/extension.dart +++ b/pkgs/mime/lib/src/extension.dart @@ -37,6 +37,3 @@ String extensionFromMime(String mimeType, {String? orElse}) => void addMimeType(String mimeType, String extension) { _preferredExtensionsMap[mimeType.toLowerCase()] = extension.toLowerCase(); } - -bool hasPreferredExtension(String mimeType) => - _preferredExtensionsMap.containsKey(mimeType.toLowerCase()); diff --git a/pkgs/mime/test/extension_test.dart b/pkgs/mime/test/extension_test.dart index 62c084fc1..0f6df2855 100644 --- a/pkgs/mime/test/extension_test.dart +++ b/pkgs/mime/test/extension_test.dart @@ -3,7 +3,6 @@ // BSD-style license that can be found in the LICENSE file. import 'package:mime/mime.dart'; -import 'package:mime/src/default_extension_map.dart'; import 'package:test/test.dart'; void main() { @@ -55,24 +54,5 @@ void main() { addMimeType('image/jpeg', 'jpeg'); expect(extensionFromMime('image/jpeg'), equals('jpeg')); }); - - test('check-preferred-present-for-non-unique', () { - final mimeTypeToExtMap = >{}; - for (var entry in defaultExtensionMap.entries) { - final extensions = mimeTypeToExtMap.putIfAbsent(entry.value, () => []); - extensions.add(entry.key); - } - final mimeTypesWithMultipleExtensions = Map.fromEntries(mimeTypeToExtMap - .entries - .where((element) => element.value.length > 1)); - for (var mimeType in mimeTypesWithMultipleExtensions.keys) { - expect( - hasPreferredExtension(mimeType), - isTrue, - reason: 'mimeType $mimeType with multiple extension, ' - 'does not have preferred extension defined', - ); - } - }); }); } From bdb76d3d52e5489df6d3e378ce8e038bad959a71 Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <178714+mx1up@users.noreply.github.com> Date: Fri, 6 Jan 2023 19:08:49 +0100 Subject: [PATCH 10/38] added some preferred extensions for common file formats --- pkgs/mime/lib/src/extension.dart | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/pkgs/mime/lib/src/extension.dart b/pkgs/mime/lib/src/extension.dart index 04a80718d..c70afb14b 100644 --- a/pkgs/mime/lib/src/extension.dart +++ b/pkgs/mime/lib/src/extension.dart @@ -10,8 +10,19 @@ import 'default_extension_map.dart'; /// to the same MIME type. final Map _preferredExtensionsMap = { 'application/vnd.ms-excel': 'xls', + 'application/vnd.ms-powerpoint': 'ppt', 'image/jpeg': 'jpg', - 'text/x-c': 'c' + 'image/tiff': 'tif', + 'image/svg+xml': 'svg', + 'text/calendar': 'ics', + 'text/javascript': 'js', + 'text/plain': 'txt', + 'text/sgml': 'sgml', + 'text/x-pascal': 'pas', + 'video/mp4': 'mp4', + 'video/mpeg': 'mpg', + 'video/quicktime': 'mov', + 'video/x-matroska': 'mkv', }; /// Lookup file extension for a given MIME type. From 16f54d571c72d5bc8d77a41f20c182a5ac9ac704 Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <178714+mx1up@users.noreply.github.com> Date: Fri, 6 Jan 2023 19:16:54 +0100 Subject: [PATCH 11/38] cleanup old tests --- pkgs/mime/test/extension_test.dart | 2 ++ pkgs/mime/test/mime_type_test.dart | 17 ----------------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/pkgs/mime/test/extension_test.dart b/pkgs/mime/test/extension_test.dart index 0f6df2855..a3d7f98f7 100644 --- a/pkgs/mime/test/extension_test.dart +++ b/pkgs/mime/test/extension_test.dart @@ -10,6 +10,8 @@ void main() { test('valid-mime-type', () { expect(extensionFromMime('text/x-dart'), equals('dart')); expect(extensionFromMime('text/javascript'), equals('js')); + expect(extensionFromMime('application/java-archive'), equals('jar')); + expect(extensionFromMime('application/json'), equals('json')); expect(extensionFromMime('application/pdf'), equals('pdf')); expect(extensionFromMime('application/vnd.ms-excel'), equals('xls')); expect(extensionFromMime('application/xhtml+xml'), equals('xht')); diff --git a/pkgs/mime/test/mime_type_test.dart b/pkgs/mime/test/mime_type_test.dart index f7388ff34..56efba88b 100644 --- a/pkgs/mime/test/mime_type_test.dart +++ b/pkgs/mime/test/mime_type_test.dart @@ -318,21 +318,4 @@ void main() { expect(initialMagicNumbersMaxLength, actualMaxBytes); }); - group('extensionFromMime', () { - test('returns match for mime with single extension', () { - expect(extensionFromMime('application/json'), equals('json')); - expect(extensionFromMime('application/java-archive'), equals('jar')); - }); - - test('returns first match for mime with multiple extensions', () { - expect(extensionFromMime('text/html'), equals('htm')); - expect(extensionFromMime('application/x-cbr'), equals('cb7')); - }); - - test('returns inputted string for unrecognized mime', () { - expect( - extensionFromMime('unrecognized_mime'), equals('unrecognized_mime')); - expect(extensionFromMime('i/am/not/a/mime'), equals('i/am/not/a/mime')); - }); - }); } From dccafc0ab26bc9d5a39f1db2aa67466fb87b179b Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <178714+mx1up@users.noreply.github.com> Date: Mon, 16 Jan 2023 15:16:02 +0100 Subject: [PATCH 12/38] test orElse param for unknown mime type --- pkgs/mime/test/extension_test.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkgs/mime/test/extension_test.dart b/pkgs/mime/test/extension_test.dart index a3d7f98f7..bed63b49a 100644 --- a/pkgs/mime/test/extension_test.dart +++ b/pkgs/mime/test/extension_test.dart @@ -40,6 +40,9 @@ void main() { expect(extensionFromMime('application/to-be-invented'), 'application/to-be-invented'); + expect(extensionFromMime('application/to-be-invented', orElse: 'unknown'), + 'unknown'); + expect(extensionFromMimeOrNull('application/to-be-invented'), isNull); }); }); From 59c6ec2891d85a04eb654960c0b3e952bd32eb33 Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <178714+mx1up@users.noreply.github.com> Date: Mon, 16 Jan 2023 15:22:24 +0100 Subject: [PATCH 13/38] link to file --- pkgs/mime/CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/mime/CONTRIBUTING.md b/pkgs/mime/CONTRIBUTING.md index 50a36a2d7..cd7d82f0c 100644 --- a/pkgs/mime/CONTRIBUTING.md +++ b/pkgs/mime/CONTRIBUTING.md @@ -34,4 +34,4 @@ one above, the ### Adding an extension to an existing MIME type If a MIME type ends up with multiple extensions, it is recommended to define a -preferred extension in `_preferredExtensionsMap` in `extension.dart` \ No newline at end of file +preferred extension in `_preferredExtensionsMap` in [extension.dart](lib/src/extension.dart). \ No newline at end of file From 9e4b9d0c1155a43243341106901c6b14bd89df2d Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <178714+mx1up@users.noreply.github.com> Date: Mon, 16 Jan 2023 15:26:38 +0100 Subject: [PATCH 14/38] fix title to be more accurate --- pkgs/mime/CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/mime/CONTRIBUTING.md b/pkgs/mime/CONTRIBUTING.md index cd7d82f0c..bd079dd62 100644 --- a/pkgs/mime/CONTRIBUTING.md +++ b/pkgs/mime/CONTRIBUTING.md @@ -32,6 +32,6 @@ Contributions made by corporations are covered by a different agreement than the one above, the [Software Grant and Corporate Contributor License Agreement](https://developers.google.com/open-source/cla/corporate). -### Adding an extension to an existing MIME type +### Adding an extension / MIME type mapping If a MIME type ends up with multiple extensions, it is recommended to define a preferred extension in `_preferredExtensionsMap` in [extension.dart](lib/src/extension.dart). \ No newline at end of file From bc90ebd838d54445c285b1b4957a1f74a98acab7 Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <178714+mx1up@users.noreply.github.com> Date: Mon, 16 Jan 2023 15:32:15 +0100 Subject: [PATCH 15/38] rename to existing function --- pkgs/mime/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/mime/README.md b/pkgs/mime/README.md index eb4ab2ce4..18ecbb622 100644 --- a/pkgs/mime/README.md +++ b/pkgs/mime/README.md @@ -64,9 +64,9 @@ The top level function `lookupExtension` can be used to determine the file extension of a given MIME type. ```dart -print(lookupExtension('text/html')); // Will print html -print(lookupExtension('image/jpeg')); // Will print jpg -print(lookupExtension('application/pdf')); // Will print pdf +print(extensionFromMime('text/html')); // Will print html +print(extensionFromMime('image/jpeg')); // Will print jpg +print(extensionFromMime('application/pdf')); // Will print pdf ``` You can override the default MIME type-extension mapping using @@ -74,5 +74,5 @@ You can override the default MIME type-extension mapping using ```dart addMimeType('image/jpeg', 'jpeg'); -print(lookupExtension('image/jpeg')); // Will print jpeg +print(extensionFromMime('image/jpeg')); // Will print jpeg ``` From cd5e5015aeaba8855208fd272044cf0f2236d3a5 Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <178714+mx1up@users.noreply.github.com> Date: Mon, 16 Jan 2023 15:32:41 +0100 Subject: [PATCH 16/38] add standard behavior to make example more clear --- pkgs/mime/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/mime/README.md b/pkgs/mime/README.md index 18ecbb622..1a1e44f55 100644 --- a/pkgs/mime/README.md +++ b/pkgs/mime/README.md @@ -73,6 +73,7 @@ You can override the default MIME type-extension mapping using `addMimeType`: ```dart +print(extensionFromMime('image/jpeg')); // Will print jpg addMimeType('image/jpeg', 'jpeg'); print(extensionFromMime('image/jpeg')); // Will print jpeg ``` From 557520ef0003002157d6e133051107a89311c777 Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <178714+mx1up@users.noreply.github.com> Date: Mon, 16 Jan 2023 15:34:31 +0100 Subject: [PATCH 17/38] include text/plain mapping again --- pkgs/mime/test/extension_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/mime/test/extension_test.dart b/pkgs/mime/test/extension_test.dart index bed63b49a..7a22f0203 100644 --- a/pkgs/mime/test/extension_test.dart +++ b/pkgs/mime/test/extension_test.dart @@ -19,7 +19,7 @@ void main() { expect(extensionFromMime('image/png'), equals('png')); expect(extensionFromMime('text/css'), equals('css')); expect(extensionFromMime('text/html'), equals('htm')); - // expect(extensionFromMime('text/plain'), equals('txt')); + expect(extensionFromMime('text/plain'), equals('txt')); expect(extensionFromMime('text/x-c'), equals('c')); }); From 8c1f0a05e8e9beaba12a44bbc0c64953bdad591c Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <178714+mx1up@users.noreply.github.com> Date: Tue, 17 Jan 2023 10:31:44 +0100 Subject: [PATCH 18/38] remove collection dependency --- pkgs/mime/lib/src/extension.dart | 12 ++++++++++-- pkgs/mime/pubspec.yaml | 3 --- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/pkgs/mime/lib/src/extension.dart b/pkgs/mime/lib/src/extension.dart index c70afb14b..94e3f7da5 100644 --- a/pkgs/mime/lib/src/extension.dart +++ b/pkgs/mime/lib/src/extension.dart @@ -2,8 +2,6 @@ // 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 'package:collection/collection.dart'; - import 'default_extension_map.dart'; /// Add an override for common extensions since different extensions may map @@ -48,3 +46,13 @@ String extensionFromMime(String mimeType, {String? orElse}) => void addMimeType(String mimeType, String extension) { _preferredExtensionsMap[mimeType.toLowerCase()] = extension.toLowerCase(); } + +extension _IterableExtension on Iterable { + /// The first element satisfying [test], or `null` if there are none. + T? firstWhereOrNull(bool Function(T element) test) { + for (var element in this) { + if (test(element)) return element; + } + return null; + } +} \ No newline at end of file diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 0dec004e1..8d3c49823 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -13,9 +13,6 @@ topics: environment: sdk: ^3.2.0 -dependencies: - collection: ^1.17.0 - dev_dependencies: dart_flutter_team_lints: ^3.0.0 test: ^1.16.0 From 07011650e1e22f7bfe3a6a8703b1511fbe351b15 Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <178714+mx1up@users.noreply.github.com> Date: Fri, 27 Jan 2023 14:08:23 +0100 Subject: [PATCH 19/38] lookupExtension has been renamed to existing extensionFromMime --- pkgs/mime/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/mime/README.md b/pkgs/mime/README.md index 1a1e44f55..3bd4a482a 100644 --- a/pkgs/mime/README.md +++ b/pkgs/mime/README.md @@ -60,7 +60,7 @@ request ## Determining file extension by MIME type -The top level function `lookupExtension` can be used to determine the +The top level function `extensionFromMime` can be used to determine the file extension of a given MIME type. ```dart From 7ad372340c6344cee3e865c4e4c7fe784f01e93a Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <121732-mx1up@users.noreply.gitlab.com> Date: Wed, 13 Dec 2023 19:13:13 +0100 Subject: [PATCH 20/38] drop non-nullable extensionFromMime variant per review suggestion --- pkgs/mime/lib/src/extension.dart | 5 +---- pkgs/mime/test/extension_test.dart | 22 ++++------------------ 2 files changed, 5 insertions(+), 22 deletions(-) diff --git a/pkgs/mime/lib/src/extension.dart b/pkgs/mime/lib/src/extension.dart index 94e3f7da5..69a1bdcc9 100644 --- a/pkgs/mime/lib/src/extension.dart +++ b/pkgs/mime/lib/src/extension.dart @@ -28,7 +28,7 @@ final Map _preferredExtensionsMap = { /// If there are multiple extensions for [mimeType], return preferred extension /// if defined, or the first occurrence in the map. /// If no extension is found, `null` is returned. -String? extensionFromMimeOrNull(String mimeType) { +String? extensionFromMime(String mimeType) { final mimeTypeLC = mimeType.toLowerCase(); if (_preferredExtensionsMap.containsKey(mimeTypeLC)) { return _preferredExtensionsMap[mimeTypeLC]!; @@ -38,9 +38,6 @@ String? extensionFromMimeOrNull(String mimeType) { ?.key; } -String extensionFromMime(String mimeType, {String? orElse}) => - extensionFromMimeOrNull(mimeType) ?? orElse ?? mimeType; - /// Allow for a user-specified MIME type-extension mapping that overrides the /// default. void addMimeType(String mimeType, String extension) { diff --git a/pkgs/mime/test/extension_test.dart b/pkgs/mime/test/extension_test.dart index 7a22f0203..a57e9c648 100644 --- a/pkgs/mime/test/extension_test.dart +++ b/pkgs/mime/test/extension_test.dart @@ -24,32 +24,18 @@ void main() { }); test('invalid-mime-type', () { - expect(extensionFromMime('invalid-mime-type'), 'invalid-mime-type'); - expect(extensionFromMime('invalid/mime/type'), 'invalid/mime/type'); - - expect( - extensionFromMime('invalid-mime-type', orElse: 'invalid'), 'invalid'); - expect( - extensionFromMime('invalid/mime/type', orElse: 'invalid'), 'invalid'); - - expect(extensionFromMimeOrNull('invalid-mime-type'), isNull); - expect(extensionFromMimeOrNull('invalid/mime/type'), isNull); + expect(extensionFromMime('invalid-mime-type'), isNull); + expect(extensionFromMime('invalid/mime/type'), isNull); }); test('unknown-mime-type', () { - expect(extensionFromMime('application/to-be-invented'), - 'application/to-be-invented'); - - expect(extensionFromMime('application/to-be-invented', orElse: 'unknown'), - 'unknown'); - - expect(extensionFromMimeOrNull('application/to-be-invented'), isNull); + expect(extensionFromMime('application/to-be-invented'), isNull); }); }); group('add-mime-type', () { test('new-mime-type', () { - expect(extensionFromMimeOrNull('custom/type'), isNull); + expect(extensionFromMime('custom/type'), isNull); addMimeType('custom/type', 'ct'); expect(extensionFromMime('custom/type'), equals('ct')); }); From 58ad484815dabc535275f19488873ea6d40da893 Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <121732-mx1up@users.noreply.gitlab.com> Date: Wed, 13 Dec 2023 19:34:09 +0100 Subject: [PATCH 21/38] doc update: try using noun phrase; don't refer to implementation details --- pkgs/mime/lib/src/extension.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/mime/lib/src/extension.dart b/pkgs/mime/lib/src/extension.dart index 69a1bdcc9..4344be9ae 100644 --- a/pkgs/mime/lib/src/extension.dart +++ b/pkgs/mime/lib/src/extension.dart @@ -23,10 +23,10 @@ final Map _preferredExtensionsMap = { 'video/x-matroska': 'mkv', }; -/// Lookup file extension for a given MIME type. +/// The extension for a given MIME type. /// /// If there are multiple extensions for [mimeType], return preferred extension -/// if defined, or the first occurrence in the map. +/// if defined, otherwise an extension chosen by the library. /// If no extension is found, `null` is returned. String? extensionFromMime(String mimeType) { final mimeTypeLC = mimeType.toLowerCase(); From eed2ba9b35abc9dee00e0c437b383fb6fccbc9b6 Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <121732-mx1up@users.noreply.gitlab.com> Date: Wed, 13 Dec 2023 19:37:19 +0100 Subject: [PATCH 22/38] don't use extension method --- pkgs/mime/lib/src/extension.dart | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/pkgs/mime/lib/src/extension.dart b/pkgs/mime/lib/src/extension.dart index 4344be9ae..b9160ed59 100644 --- a/pkgs/mime/lib/src/extension.dart +++ b/pkgs/mime/lib/src/extension.dart @@ -33,9 +33,11 @@ String? extensionFromMime(String mimeType) { if (_preferredExtensionsMap.containsKey(mimeTypeLC)) { return _preferredExtensionsMap[mimeTypeLC]!; } - return defaultExtensionMap.entries - .firstWhereOrNull((entry) => entry.value == mimeTypeLC) - ?.key; + + for (final entry in defaultExtensionMap.entries) { + if (entry.value == mimeTypeLC) return entry.key; + } + return null; } /// Allow for a user-specified MIME type-extension mapping that overrides the @@ -43,13 +45,3 @@ String? extensionFromMime(String mimeType) { void addMimeType(String mimeType, String extension) { _preferredExtensionsMap[mimeType.toLowerCase()] = extension.toLowerCase(); } - -extension _IterableExtension on Iterable { - /// The first element satisfying [test], or `null` if there are none. - T? firstWhereOrNull(bool Function(T element) test) { - for (var element in this) { - if (test(element)) return element; - } - return null; - } -} \ No newline at end of file From dc5db0bf23dd1a46cb8566087bfc18a5f4896167 Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <121732-mx1up@users.noreply.gitlab.com> Date: Wed, 13 Dec 2023 19:44:13 +0100 Subject: [PATCH 23/38] remove addMimeType and leave it for another time.. --- pkgs/mime/lib/src/extension.dart | 6 ------ pkgs/mime/test/extension_test.dart | 14 -------------- 2 files changed, 20 deletions(-) diff --git a/pkgs/mime/lib/src/extension.dart b/pkgs/mime/lib/src/extension.dart index b9160ed59..22b3e070a 100644 --- a/pkgs/mime/lib/src/extension.dart +++ b/pkgs/mime/lib/src/extension.dart @@ -39,9 +39,3 @@ String? extensionFromMime(String mimeType) { } return null; } - -/// Allow for a user-specified MIME type-extension mapping that overrides the -/// default. -void addMimeType(String mimeType, String extension) { - _preferredExtensionsMap[mimeType.toLowerCase()] = extension.toLowerCase(); -} diff --git a/pkgs/mime/test/extension_test.dart b/pkgs/mime/test/extension_test.dart index a57e9c648..0a3db0fad 100644 --- a/pkgs/mime/test/extension_test.dart +++ b/pkgs/mime/test/extension_test.dart @@ -32,18 +32,4 @@ void main() { expect(extensionFromMime('application/to-be-invented'), isNull); }); }); - - group('add-mime-type', () { - test('new-mime-type', () { - expect(extensionFromMime('custom/type'), isNull); - addMimeType('custom/type', 'ct'); - expect(extensionFromMime('custom/type'), equals('ct')); - }); - - test('overridden-mime-type', () { - expect(extensionFromMime('image/jpeg'), equals('jpg')); - addMimeType('image/jpeg', 'jpeg'); - expect(extensionFromMime('image/jpeg'), equals('jpeg')); - }); - }); } From d285aae83d5dc2e6f17718711a4b8da35873c093 Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <121732-mx1up@users.noreply.gitlab.com> Date: Wed, 13 Dec 2023 20:53:17 +0100 Subject: [PATCH 24/38] remove addMimeType documentation --- pkgs/mime/README.md | 9 --------- 1 file changed, 9 deletions(-) diff --git a/pkgs/mime/README.md b/pkgs/mime/README.md index 3bd4a482a..09675e899 100644 --- a/pkgs/mime/README.md +++ b/pkgs/mime/README.md @@ -68,12 +68,3 @@ print(extensionFromMime('text/html')); // Will print html print(extensionFromMime('image/jpeg')); // Will print jpg print(extensionFromMime('application/pdf')); // Will print pdf ``` - -You can override the default MIME type-extension mapping using -`addMimeType`: - -```dart -print(extensionFromMime('image/jpeg')); // Will print jpg -addMimeType('image/jpeg', 'jpeg'); -print(extensionFromMime('image/jpeg')); // Will print jpeg -``` From 342b63f57e4971cc002275b909e4a36ac083ae45 Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <121732-mx1up@users.noreply.gitlab.com> Date: Mon, 19 Feb 2024 19:00:11 +0100 Subject: [PATCH 25/38] be more specific about extension --- pkgs/mime/lib/src/extension.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/mime/lib/src/extension.dart b/pkgs/mime/lib/src/extension.dart index 22b3e070a..871ee55fb 100644 --- a/pkgs/mime/lib/src/extension.dart +++ b/pkgs/mime/lib/src/extension.dart @@ -23,7 +23,7 @@ final Map _preferredExtensionsMap = { 'video/x-matroska': 'mkv', }; -/// The extension for a given MIME type. +/// The file extension for a given MIME type. /// /// If there are multiple extensions for [mimeType], return preferred extension /// if defined, otherwise an extension chosen by the library. From 40cd80c5a9f511578f1f730362ad5f5b0cea9ca0 Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <121732-mx1up@users.noreply.gitlab.com> Date: Mon, 19 Feb 2024 19:07:41 +0100 Subject: [PATCH 26/38] review feedback: avoid abbreviations, just overwrite function param --- pkgs/mime/lib/src/extension.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/mime/lib/src/extension.dart b/pkgs/mime/lib/src/extension.dart index 871ee55fb..e77b038a4 100644 --- a/pkgs/mime/lib/src/extension.dart +++ b/pkgs/mime/lib/src/extension.dart @@ -29,13 +29,13 @@ final Map _preferredExtensionsMap = { /// if defined, otherwise an extension chosen by the library. /// If no extension is found, `null` is returned. String? extensionFromMime(String mimeType) { - final mimeTypeLC = mimeType.toLowerCase(); - if (_preferredExtensionsMap.containsKey(mimeTypeLC)) { - return _preferredExtensionsMap[mimeTypeLC]!; + mimeType = mimeType.toLowerCase(); + if (_preferredExtensionsMap.containsKey(mimeType)) { + return _preferredExtensionsMap[mimeType]!; } for (final entry in defaultExtensionMap.entries) { - if (entry.value == mimeTypeLC) return entry.key; + if (entry.value == mimeType) return entry.key; } return null; } From 60730a6dbc5842d8a0856e41f9f42a0548dcd5c4 Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <121732-mx1up@users.noreply.gitlab.com> Date: Mon, 19 Feb 2024 19:25:01 +0100 Subject: [PATCH 27/38] since extensions can no longer by added at runtime, we can optimize and avoid the linear search --- pkgs/mime/lib/src/extension.dart | 43 ++++++++++++++------------------ 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/pkgs/mime/lib/src/extension.dart b/pkgs/mime/lib/src/extension.dart index e77b038a4..5b223a37c 100644 --- a/pkgs/mime/lib/src/extension.dart +++ b/pkgs/mime/lib/src/extension.dart @@ -6,22 +6,24 @@ import 'default_extension_map.dart'; /// Add an override for common extensions since different extensions may map /// to the same MIME type. -final Map _preferredExtensionsMap = { - 'application/vnd.ms-excel': 'xls', - 'application/vnd.ms-powerpoint': 'ppt', - 'image/jpeg': 'jpg', - 'image/tiff': 'tif', - 'image/svg+xml': 'svg', - 'text/calendar': 'ics', - 'text/javascript': 'js', - 'text/plain': 'txt', - 'text/sgml': 'sgml', - 'text/x-pascal': 'pas', - 'video/mp4': 'mp4', - 'video/mpeg': 'mpg', - 'video/quicktime': 'mov', - 'video/x-matroska': 'mkv', -}; +final Map _defaultMimeTypeMap = { + for (var entry in defaultExtensionMap.entries) entry.value: entry.key, +}..addAll({ + 'application/vnd.ms-excel': 'xls', + 'application/vnd.ms-powerpoint': 'ppt', + 'image/jpeg': 'jpg', + 'image/tiff': 'tif', + 'image/svg+xml': 'svg', + 'text/calendar': 'ics', + 'text/javascript': 'js', + 'text/plain': 'txt', + 'text/sgml': 'sgml', + 'text/x-pascal': 'pas', + 'video/mp4': 'mp4', + 'video/mpeg': 'mpg', + 'video/quicktime': 'mov', + 'video/x-matroska': 'mkv', + }); /// The file extension for a given MIME type. /// @@ -30,12 +32,5 @@ final Map _preferredExtensionsMap = { /// If no extension is found, `null` is returned. String? extensionFromMime(String mimeType) { mimeType = mimeType.toLowerCase(); - if (_preferredExtensionsMap.containsKey(mimeType)) { - return _preferredExtensionsMap[mimeType]!; - } - - for (final entry in defaultExtensionMap.entries) { - if (entry.value == mimeType) return entry.key; - } - return null; + return _defaultMimeTypeMap[mimeType]; } From 04f81695acfdb1a8dc181db72c90b1e9e3c23c63 Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <121732-mx1up@users.noreply.gitlab.com> Date: Mon, 19 Feb 2024 19:27:23 +0100 Subject: [PATCH 28/38] local var no longer needed --- pkgs/mime/lib/src/extension.dart | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pkgs/mime/lib/src/extension.dart b/pkgs/mime/lib/src/extension.dart index 5b223a37c..1edaca2c4 100644 --- a/pkgs/mime/lib/src/extension.dart +++ b/pkgs/mime/lib/src/extension.dart @@ -30,7 +30,5 @@ final Map _defaultMimeTypeMap = { /// If there are multiple extensions for [mimeType], return preferred extension /// if defined, otherwise an extension chosen by the library. /// If no extension is found, `null` is returned. -String? extensionFromMime(String mimeType) { - mimeType = mimeType.toLowerCase(); - return _defaultMimeTypeMap[mimeType]; -} +String? extensionFromMime(String mimeType) => + _defaultMimeTypeMap[mimeType.toLowerCase()]; From 8ba5efba9f091316c27fb821fd30870c7db8c679 Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <121732-mx1up@users.noreply.gitlab.com> Date: Mon, 19 Feb 2024 19:34:51 +0100 Subject: [PATCH 29/38] update docs --- pkgs/mime/CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/mime/CONTRIBUTING.md b/pkgs/mime/CONTRIBUTING.md index bd079dd62..463063ae4 100644 --- a/pkgs/mime/CONTRIBUTING.md +++ b/pkgs/mime/CONTRIBUTING.md @@ -34,4 +34,4 @@ one above, the ### Adding an extension / MIME type mapping If a MIME type ends up with multiple extensions, it is recommended to define a -preferred extension in `_preferredExtensionsMap` in [extension.dart](lib/src/extension.dart). \ No newline at end of file +preferred extension in `_defaultMimeTypeMap` in [extension.dart](lib/src/extension.dart). \ No newline at end of file From c1d7b69657f2a698ff5200e5a3f93eed5cd38549 Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <121732-mx1up@users.noreply.gitlab.com> Date: Mon, 19 Feb 2024 19:38:56 +0100 Subject: [PATCH 30/38] update docs --- pkgs/mime/lib/src/extension.dart | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkgs/mime/lib/src/extension.dart b/pkgs/mime/lib/src/extension.dart index 1edaca2c4..35a860f88 100644 --- a/pkgs/mime/lib/src/extension.dart +++ b/pkgs/mime/lib/src/extension.dart @@ -4,8 +4,8 @@ import 'default_extension_map.dart'; -/// Add an override for common extensions since different extensions may map -/// to the same MIME type. +/// Reverse map of [defaultExtensionMap] with overrides for common extensions +/// since different extensions may map to the same MIME type. final Map _defaultMimeTypeMap = { for (var entry in defaultExtensionMap.entries) entry.value: entry.key, }..addAll({ @@ -28,7 +28,9 @@ final Map _defaultMimeTypeMap = { /// The file extension for a given MIME type. /// /// If there are multiple extensions for [mimeType], return preferred extension -/// if defined, otherwise an extension chosen by the library. +/// if defined in [_defaultMimeTypeMap], otherwise an extension chosen by the +/// library. +/// /// If no extension is found, `null` is returned. String? extensionFromMime(String mimeType) => _defaultMimeTypeMap[mimeType.toLowerCase()]; From e654a3275ddb3a63e76174d11ea77951d2daa871 Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <121732-mx1up@users.noreply.gitlab.com> Date: Tue, 27 Aug 2024 16:14:34 +0200 Subject: [PATCH 31/38] documentation updates --- pkgs/mime/README.md | 6 +++--- pkgs/mime/lib/src/extension.dart | 21 ++++++++++++++------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/pkgs/mime/README.md b/pkgs/mime/README.md index 09675e899..da06de62b 100644 --- a/pkgs/mime/README.md +++ b/pkgs/mime/README.md @@ -64,7 +64,7 @@ The top level function `extensionFromMime` can be used to determine the file extension of a given MIME type. ```dart -print(extensionFromMime('text/html')); // Will print html -print(extensionFromMime('image/jpeg')); // Will print jpg -print(extensionFromMime('application/pdf')); // Will print pdf +print(extensionFromMime('text/html')); // Prints "html". +print(extensionFromMime('image/jpeg')); // Prints "jpg". +print(extensionFromMime('application/pdf')); // Prints "pdf". ``` diff --git a/pkgs/mime/lib/src/extension.dart b/pkgs/mime/lib/src/extension.dart index 35a860f88..63234b6bf 100644 --- a/pkgs/mime/lib/src/extension.dart +++ b/pkgs/mime/lib/src/extension.dart @@ -4,8 +4,14 @@ import 'default_extension_map.dart'; -/// Reverse map of [defaultExtensionMap] with overrides for common extensions -/// since different extensions may map to the same MIME type. +/// Default extension for recognized MIME types. +/// +/// Is the inverse of [defaultExtensionMap], and where that +/// map has multiple extensions which map to the same +/// MIME type, this map maps that MIME type to a *default* +/// extension. +/// +/// Used by [extensionFromMime]. final Map _defaultMimeTypeMap = { for (var entry in defaultExtensionMap.entries) entry.value: entry.key, }..addAll({ @@ -25,12 +31,13 @@ final Map _defaultMimeTypeMap = { 'video/x-matroska': 'mkv', }); -/// The file extension for a given MIME type. +/// The default file extension for a given MIME type. /// -/// If there are multiple extensions for [mimeType], return preferred extension -/// if defined in [_defaultMimeTypeMap], otherwise an extension chosen by the -/// library. +/// If [mimeType] has multiple associated extensions, +/// the returned string is one of those, chosen as the default +/// extension for that MIME type. /// -/// If no extension is found, `null` is returned. +/// Returns `null` if [mimeType] is not a recognized and +/// supported MIME type. String? extensionFromMime(String mimeType) => _defaultMimeTypeMap[mimeType.toLowerCase()]; From c236bd85caa4a3991cf55478be263dd2430cb98f Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <121732-mx1up@users.noreply.gitlab.com> Date: Tue, 27 Aug 2024 16:15:04 +0200 Subject: [PATCH 32/38] remove unnecessary addAll --- pkgs/mime/lib/src/extension.dart | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/pkgs/mime/lib/src/extension.dart b/pkgs/mime/lib/src/extension.dart index 63234b6bf..db4bff482 100644 --- a/pkgs/mime/lib/src/extension.dart +++ b/pkgs/mime/lib/src/extension.dart @@ -14,22 +14,21 @@ import 'default_extension_map.dart'; /// Used by [extensionFromMime]. final Map _defaultMimeTypeMap = { for (var entry in defaultExtensionMap.entries) entry.value: entry.key, -}..addAll({ - 'application/vnd.ms-excel': 'xls', - 'application/vnd.ms-powerpoint': 'ppt', - 'image/jpeg': 'jpg', - 'image/tiff': 'tif', - 'image/svg+xml': 'svg', - 'text/calendar': 'ics', - 'text/javascript': 'js', - 'text/plain': 'txt', - 'text/sgml': 'sgml', - 'text/x-pascal': 'pas', - 'video/mp4': 'mp4', - 'video/mpeg': 'mpg', - 'video/quicktime': 'mov', - 'video/x-matroska': 'mkv', - }); + 'application/vnd.ms-excel': 'xls', + 'application/vnd.ms-powerpoint': 'ppt', + 'image/jpeg': 'jpg', + 'image/tiff': 'tif', + 'image/svg+xml': 'svg', + 'text/calendar': 'ics', + 'text/javascript': 'js', + 'text/plain': 'txt', + 'text/sgml': 'sgml', + 'text/x-pascal': 'pas', + 'video/mp4': 'mp4', + 'video/mpeg': 'mpg', + 'video/quicktime': 'mov', + 'video/x-matroska': 'mkv', +}; /// The default file extension for a given MIME type. /// From b11854c5e97645c043a7d96b8baf7ebf7cd5eddd Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <121732-mx1up@users.noreply.gitlab.com> Date: Tue, 27 Aug 2024 16:15:17 +0200 Subject: [PATCH 33/38] remove unnecessary group --- pkgs/mime/test/extension_test.dart | 44 ++++++++++++++---------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/pkgs/mime/test/extension_test.dart b/pkgs/mime/test/extension_test.dart index 0a3db0fad..cf8429e01 100644 --- a/pkgs/mime/test/extension_test.dart +++ b/pkgs/mime/test/extension_test.dart @@ -6,30 +6,28 @@ import 'package:mime/mime.dart'; import 'package:test/test.dart'; void main() { - group('global-lookup-mime-type', () { - test('valid-mime-type', () { - expect(extensionFromMime('text/x-dart'), equals('dart')); - expect(extensionFromMime('text/javascript'), equals('js')); - expect(extensionFromMime('application/java-archive'), equals('jar')); - expect(extensionFromMime('application/json'), equals('json')); - expect(extensionFromMime('application/pdf'), equals('pdf')); - expect(extensionFromMime('application/vnd.ms-excel'), equals('xls')); - expect(extensionFromMime('application/xhtml+xml'), equals('xht')); - expect(extensionFromMime('image/jpeg'), equals('jpg')); - expect(extensionFromMime('image/png'), equals('png')); - expect(extensionFromMime('text/css'), equals('css')); - expect(extensionFromMime('text/html'), equals('htm')); - expect(extensionFromMime('text/plain'), equals('txt')); - expect(extensionFromMime('text/x-c'), equals('c')); - }); + test('valid-mime-type', () { + expect(extensionFromMime('text/x-dart'), equals('dart')); + expect(extensionFromMime('text/javascript'), equals('js')); + expect(extensionFromMime('application/java-archive'), equals('jar')); + expect(extensionFromMime('application/json'), equals('json')); + expect(extensionFromMime('application/pdf'), equals('pdf')); + expect(extensionFromMime('application/vnd.ms-excel'), equals('xls')); + expect(extensionFromMime('application/xhtml+xml'), equals('xht')); + expect(extensionFromMime('image/jpeg'), equals('jpg')); + expect(extensionFromMime('image/png'), equals('png')); + expect(extensionFromMime('text/css'), equals('css')); + expect(extensionFromMime('text/html'), equals('htm')); + expect(extensionFromMime('text/plain'), equals('txt')); + expect(extensionFromMime('text/x-c'), equals('c')); + }); - test('invalid-mime-type', () { - expect(extensionFromMime('invalid-mime-type'), isNull); - expect(extensionFromMime('invalid/mime/type'), isNull); - }); + test('invalid-mime-type', () { + expect(extensionFromMime('invalid-mime-type'), isNull); + expect(extensionFromMime('invalid/mime/type'), isNull); + }); - test('unknown-mime-type', () { - expect(extensionFromMime('application/to-be-invented'), isNull); - }); + test('unknown-mime-type', () { + expect(extensionFromMime('application/to-be-invented'), isNull); }); } From 874f740028311418d6cd9f3655b38ed992aaa66d Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <121732-mx1up@users.noreply.gitlab.com> Date: Tue, 27 Aug 2024 16:22:59 +0200 Subject: [PATCH 34/38] bump version + add changelog --- pkgs/mime/CHANGELOG.md | 4 ++++ pkgs/mime/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index 50f243306..483c35f90 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.7-wip + +* Update `extensionFromMime` to return a default extension when a MIME type maps to multiple extensions. + ## 1.0.6 * Add `topics` section to `pubspec.yaml`. diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index 8d3c49823..f1208681e 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,5 +1,5 @@ name: mime -version: 1.0.6 +version: 1.0.7-wip description: >- Utilities for handling media (MIME) types, including determining a type from a file extension and file contents. From d5e3d4765f28cff191b811d67aa271bd6b779fa9 Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <121732-mx1up@users.noreply.gitlab.com> Date: Wed, 28 Aug 2024 18:25:34 +0200 Subject: [PATCH 35/38] remove superfluous line --- pkgs/mime/test/mime_type_test.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/mime/test/mime_type_test.dart b/pkgs/mime/test/mime_type_test.dart index 56efba88b..23cb34af3 100644 --- a/pkgs/mime/test/mime_type_test.dart +++ b/pkgs/mime/test/mime_type_test.dart @@ -317,5 +317,4 @@ void main() { expect(initialMagicNumbersMaxLength, actualMaxBytes); }); - } From 7b3193f26fd4c2267244d152386f457ef7a4cec4 Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <121732-mx1up@users.noreply.gitlab.com> Date: Thu, 29 Aug 2024 16:52:00 +0200 Subject: [PATCH 36/38] breaking release because of removed method --- pkgs/mime/CHANGELOG.md | 3 ++- pkgs/mime/pubspec.yaml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index 483c35f90..3f6dd9684 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,5 +1,6 @@ -## 1.0.7-wip +## 2.0.0-wip +* **[Breaking]** `extensionFromMime(String mimeType, {String? orElse})` has been removed. Use `extensionFromMime(String mimeType) ?? orElse` instead. * Update `extensionFromMime` to return a default extension when a MIME type maps to multiple extensions. ## 1.0.6 diff --git a/pkgs/mime/pubspec.yaml b/pkgs/mime/pubspec.yaml index f1208681e..2cfa75a33 100644 --- a/pkgs/mime/pubspec.yaml +++ b/pkgs/mime/pubspec.yaml @@ -1,5 +1,5 @@ name: mime -version: 1.0.7-wip +version: 2.0.0-wip description: >- Utilities for handling media (MIME) types, including determining a type from a file extension and file contents. From c33a7eaa3e20a797b9b4cde66585dd939d40eb4e Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <121732-mx1up@users.noreply.gitlab.com> Date: Thu, 29 Aug 2024 17:18:01 +0200 Subject: [PATCH 37/38] add some more default extensions --- pkgs/mime/lib/src/extension.dart | 13 +++++++++++++ pkgs/mime/test/extension_test.dart | 4 ++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/pkgs/mime/lib/src/extension.dart b/pkgs/mime/lib/src/extension.dart index db4bff482..293449a0e 100644 --- a/pkgs/mime/lib/src/extension.dart +++ b/pkgs/mime/lib/src/extension.dart @@ -14,15 +14,28 @@ import 'default_extension_map.dart'; /// Used by [extensionFromMime]. final Map _defaultMimeTypeMap = { for (var entry in defaultExtensionMap.entries) entry.value: entry.key, + 'application/msword': 'doc', 'application/vnd.ms-excel': 'xls', 'application/vnd.ms-powerpoint': 'ppt', + 'application/x-debian-package': 'deb', + 'application/xhtml+xml': 'xhtml', + 'application/xml': 'xml', + 'audio/x-aiff': 'aif', + 'audio/midi': 'mid', + 'audio/mp4': 'm4a', + 'audio/ogg': 'ogg', 'image/jpeg': 'jpg', 'image/tiff': 'tif', 'image/svg+xml': 'svg', + 'model/vrml': 'vrml', 'text/calendar': 'ics', + 'text/html': 'html', 'text/javascript': 'js', + 'text/markdown': 'md', 'text/plain': 'txt', 'text/sgml': 'sgml', + 'text/x-asm': 'asm', + 'text/x-c': 'c', 'text/x-pascal': 'pas', 'video/mp4': 'mp4', 'video/mpeg': 'mpg', diff --git a/pkgs/mime/test/extension_test.dart b/pkgs/mime/test/extension_test.dart index cf8429e01..40dae6df5 100644 --- a/pkgs/mime/test/extension_test.dart +++ b/pkgs/mime/test/extension_test.dart @@ -13,11 +13,11 @@ void main() { expect(extensionFromMime('application/json'), equals('json')); expect(extensionFromMime('application/pdf'), equals('pdf')); expect(extensionFromMime('application/vnd.ms-excel'), equals('xls')); - expect(extensionFromMime('application/xhtml+xml'), equals('xht')); + expect(extensionFromMime('application/xhtml+xml'), equals('xhtml')); expect(extensionFromMime('image/jpeg'), equals('jpg')); expect(extensionFromMime('image/png'), equals('png')); expect(extensionFromMime('text/css'), equals('css')); - expect(extensionFromMime('text/html'), equals('htm')); + expect(extensionFromMime('text/html'), equals('html')); expect(extensionFromMime('text/plain'), equals('txt')); expect(extensionFromMime('text/x-c'), equals('c')); }); From b5e69814d84ba23f8b5df9f158cf90be6d79c3e1 Mon Sep 17 00:00:00 2001 From: matthias sweertvaegher <121732-mx1up@users.noreply.gitlab.com> Date: Fri, 30 Aug 2024 12:23:10 +0200 Subject: [PATCH 38/38] document breaking change correctly --- pkgs/mime/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/mime/CHANGELOG.md b/pkgs/mime/CHANGELOG.md index 3f6dd9684..55332bac0 100644 --- a/pkgs/mime/CHANGELOG.md +++ b/pkgs/mime/CHANGELOG.md @@ -1,6 +1,6 @@ ## 2.0.0-wip -* **[Breaking]** `extensionFromMime(String mimeType, {String? orElse})` has been removed. Use `extensionFromMime(String mimeType) ?? orElse` instead. +* **[Breaking]** `extensionFromMime(String mimeType)` returns `null` instead of `mimeType` for an unknown mime type. * Update `extensionFromMime` to return a default extension when a MIME type maps to multiple extensions. ## 1.0.6