Repository: sindresorhus/normalize-url
Pull request #100 (2019-09-28 05:47:18)

Strip default MIME type and charset in data URLs
Strip default mime & charset in Data URL, simplify tests


Patch:
diff --git a/index.js b/index.js
index 4c99af1..4eea255 100644
--- a/index.js
+++ b/index.js
@@ -2,6 +2,10 @@
 // TODO: Use the `URL` global when targeting Node.js 10
 const URLParser = typeof URL === 'undefined' ? require('url').URL : URL;
 
+// https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs
+const DATA_URL_DEFAULT_MIME_TYPE = 'text/plain';
+const DATA_URL_DEFAULT_CHARSET = 'us-ascii';
+
 const testParameter = (name, filters) => {
 	return filters.some(filter => filter instanceof RegExp ? filter.test(name) : filter === name);
 };
@@ -27,17 +31,21 @@ const normalizeDataURL = (urlString, {stripHash}) => {
 	// Lowercase MIME type
 	const mimeType = (mediaType.shift() || '').toLowerCase();
 	const attributes = mediaType
-		.filter(Boolean)
 		.map(attribute => {
 			let [key, value = ''] = attribute.split('=').map(string => string.trim());
 
 			// Lowercase `charset`
 			if (key === 'charset') {
 				value = value.toLowerCase();
+
+				if (value === DATA_URL_DEFAULT_CHARSET) {
+					return '';
+				}
 			}
 
 			return `${key}${value ? `=${value}` : ''}`;
-		});
+		})
+		.filter(Boolean);
 
 	const normalizedMediaType = [
 		...attributes
@@ -47,7 +55,7 @@ const normalizeDataURL = (urlString, {stripHash}) => {
 		normalizedMediaType.push('base64');
 	}
 
-	if (normalizedMediaType.length !== 0 || mimeType) {
+	if (normalizedMediaType.length !== 0 || (mimeType && mimeType !== DATA_URL_DEFAULT_MIME_TYPE)) {
 		normalizedMediaType.unshift(mimeType);
 	}
 


Test patch:
diff --git a/test.js b/test.js
index efcda01..dba2e13 100644
--- a/test.js
+++ b/test.js
@@ -216,8 +216,14 @@ test('data URL', t => {
 	// Invalid URL.
 	t.throws(() => normalizeUrl('data:'), 'Invalid URL: data:');
 
+	// Strip default MIME type
+	t.is(normalizeUrl('data:text/plain,foo'), 'data:,foo');
+
+	// Strip default charset
+	t.is(normalizeUrl('data:;charset=us-ascii,foo'), 'data:,foo');
+
 	// Normalize away trailing semicolon.
-	t.is(normalizeUrl('data:text/plain;charset=UTF-8;,foo'), 'data:text/plain;charset=utf-8,foo');
+	t.is(normalizeUrl('data:;charset=UTF-8;,foo'), 'data:;charset=utf-8,foo');
 
 	// Empty MIME type.
 	t.is(normalizeUrl('data:,'), 'data:,');
@@ -226,23 +232,22 @@ test('data URL', t => {
 	t.is(normalizeUrl('data:;charset=utf-8,foo'), 'data:;charset=utf-8,foo');
 
 	// Lowercase the MIME type.
-	t.is(normalizeUrl('data:TEXT/plain,foo'), 'data:text/plain,foo');
+	t.is(normalizeUrl('data:TEXT/HTML,foo'), 'data:text/html,foo');
 
 	// Strip empty hash.
 	t.is(normalizeUrl('data:,foo# '), 'data:,foo');
 
 	// Key only mediaType attribute.
-	t.is(normalizeUrl('data:text/plain;foo=,'), 'data:text/plain;foo,');
-	t.is(normalizeUrl('data:text/plain; foo,'), 'data:text/plain;foo,');
+	t.is(normalizeUrl('data:;foo=;bar,'), 'data:;foo;bar,');
 
 	// Lowercase the charset.
-	t.is(normalizeUrl('data:text/plain;charset=UTF-8,foo'), 'data:text/plain;charset=utf-8,foo');
+	t.is(normalizeUrl('data:;charset=UTF-8,foo'), 'data:;charset=utf-8,foo');
 
 	// Remove spaces after the comma when it's base64.
-	t.is(normalizeUrl('data:image/gif;base64, R0lGODlhAQABAAAAACw= #foo #bar'), 'data:image/gif;base64,R0lGODlhAQABAAAAACw=#foo #bar');
+	t.is(normalizeUrl('data:;base64, Zm9v #foo #bar'), 'data:;base64,Zm9v#foo #bar');
 
 	// Keep spaces when it's not base64.
-	t.is(normalizeUrl('data:text/plain;charset=utf-8, foo #bar'), 'data:text/plain;charset=utf-8, foo #bar');
+	t.is(normalizeUrl('data:, foo #bar'), 'data:, foo #bar');
 
 	// Options.
 	const options = {