normalize-url 7.1.0 → 8.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/index.d.ts +33 -16
  2. package/index.js +30 -4
  3. package/package.json +10 -7
  4. package/readme.md +30 -12
package/index.d.ts CHANGED
@@ -1,10 +1,8 @@
1
- export interface Options {
1
+ export type Options = {
2
2
  /**
3
- @default 'http:'
4
-
5
- Values: `'https:' | 'http:'`
3
+ @default 'http'
6
4
  */
7
- readonly defaultProtocol?: string; // TODO: Make this `'https:' | 'http:'` in the next major version.
5
+ readonly defaultProtocol?: 'https' | 'http';
8
6
 
9
7
  /**
10
8
  Prepends `defaultProtocol` to the URL if it's protocol-relative.
@@ -13,44 +11,44 @@ export interface Options {
13
11
 
14
12
  @example
15
13
  ```
16
- normalizeUrl('//sindresorhus.com:80/');
14
+ normalizeUrl('//sindresorhus.com');
17
15
  //=> 'http://sindresorhus.com'
18
16
 
19
- normalizeUrl('//sindresorhus.com:80/', {normalizeProtocol: false});
17
+ normalizeUrl('//sindresorhus.com', {normalizeProtocol: false});
20
18
  //=> '//sindresorhus.com'
21
19
  ```
22
20
  */
23
21
  readonly normalizeProtocol?: boolean;
24
22
 
25
23
  /**
26
- Normalizes `https:` URLs to `http:`.
24
+ Normalizes HTTPS URLs to HTTP.
27
25
 
28
26
  @default false
29
27
 
30
28
  @example
31
29
  ```
32
- normalizeUrl('https://sindresorhus.com:80/');
30
+ normalizeUrl('https://sindresorhus.com');
33
31
  //=> 'https://sindresorhus.com'
34
32
 
35
- normalizeUrl('https://sindresorhus.com:80/', {forceHttp: true});
33
+ normalizeUrl('https://sindresorhus.com', {forceHttp: true});
36
34
  //=> 'http://sindresorhus.com'
37
35
  ```
38
36
  */
39
37
  readonly forceHttp?: boolean;
40
38
 
41
39
  /**
42
- Normalizes `http:` URLs to `https:`.
40
+ Normalizes HTTP URLs to HTTPS.
43
41
 
44
- This option can't be used with the `forceHttp` option at the same time.
42
+ This option cannot be used with the `forceHttp` option at the same time.
45
43
 
46
44
  @default false
47
45
 
48
46
  @example
49
47
  ```
50
- normalizeUrl('https://sindresorhus.com:80/');
51
- //=> 'https://sindresorhus.com'
48
+ normalizeUrl('http://sindresorhus.com');
49
+ //=> 'http://sindresorhus.com'
52
50
 
53
- normalizeUrl('http://sindresorhus.com:80/', {forceHttps: true});
51
+ normalizeUrl('http://sindresorhus.com', {forceHttps: true});
54
52
  //=> 'https://sindresorhus.com'
55
53
  ```
56
54
  */
@@ -249,6 +247,23 @@ export interface Options {
249
247
  */
250
248
  readonly removeDirectoryIndex?: boolean | ReadonlyArray<RegExp | string>;
251
249
 
250
+ /**
251
+ Removes an explicit port number from the URL.
252
+
253
+ Port 443 is always removed from HTTPS URLs and 80 is always removed from HTTP URLs regardless of this option.
254
+
255
+ @default false
256
+
257
+ @example
258
+ ```
259
+ normalizeUrl('sindresorhus.com:123', {
260
+ removeExplicitPort: true
261
+ });
262
+ //=> 'http://sindresorhus.com'
263
+ ```
264
+ */
265
+ readonly removeExplicitPort?: boolean;
266
+
252
267
  /**
253
268
  Sorts the query parameters alphabetically by key.
254
269
 
@@ -263,11 +278,13 @@ export interface Options {
263
278
  ```
264
279
  */
265
280
  readonly sortQueryParameters?: boolean;
266
- }
281
+ };
267
282
 
268
283
  /**
269
284
  [Normalize](https://en.wikipedia.org/wiki/URL_normalization) a URL.
270
285
 
286
+ URLs with custom protocols are not normalized and just passed through by default. Supported protocols are: `https`, `http`, `file`, and `data`.
287
+
271
288
  @param url - URL to normalize, including [data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs).
272
289
 
273
290
  @example
package/index.js CHANGED
@@ -4,6 +4,21 @@ const DATA_URL_DEFAULT_CHARSET = 'us-ascii';
4
4
 
5
5
  const testParameter = (name, filters) => filters.some(filter => filter instanceof RegExp ? filter.test(name) : filter === name);
6
6
 
7
+ const supportedProtocols = new Set([
8
+ 'https:',
9
+ 'http:',
10
+ 'file:',
11
+ ]);
12
+
13
+ const hasCustomProtocol = urlString => {
14
+ try {
15
+ const {protocol} = new URL(urlString);
16
+ return protocol.endsWith(':') && !supportedProtocols.has(protocol);
17
+ } catch {
18
+ return false;
19
+ }
20
+ };
21
+
7
22
  const normalizeDataURL = (urlString, {stripHash}) => {
8
23
  const match = /^data:(?<type>[^,]*?),(?<data>[^#]*?)(?:#(?<hash>.*))?$/.exec(urlString);
9
24
 
@@ -22,7 +37,7 @@ const normalizeDataURL = (urlString, {stripHash}) => {
22
37
  }
23
38
 
24
39
  // Lowercase MIME type
25
- const mimeType = (mediaType.shift() || '').toLowerCase();
40
+ const mimeType = mediaType.shift()?.toLowerCase() ?? '';
26
41
  const attributes = mediaType
27
42
  .map(attribute => {
28
43
  let [key, value = ''] = attribute.split('=').map(string => string.trim());
@@ -57,7 +72,7 @@ const normalizeDataURL = (urlString, {stripHash}) => {
57
72
 
58
73
  export default function normalizeUrl(urlString, options) {
59
74
  options = {
60
- defaultProtocol: 'http:',
75
+ defaultProtocol: 'http',
61
76
  normalizeProtocol: true,
62
77
  forceHttp: false,
63
78
  forceHttps: false,
@@ -69,10 +84,16 @@ export default function normalizeUrl(urlString, options) {
69
84
  removeTrailingSlash: true,
70
85
  removeSingleSlash: true,
71
86
  removeDirectoryIndex: false,
87
+ removeExplicitPort: false,
72
88
  sortQueryParameters: true,
73
89
  ...options,
74
90
  };
75
91
 
92
+ // Legacy: Append `:` to the protocol if missing.
93
+ if (typeof options.defaultProtocol === 'string' && !options.defaultProtocol.endsWith(':')) {
94
+ options.defaultProtocol = `${options.defaultProtocol}:`;
95
+ }
96
+
76
97
  urlString = urlString.trim();
77
98
 
78
99
  // Data URL
@@ -80,8 +101,8 @@ export default function normalizeUrl(urlString, options) {
80
101
  return normalizeDataURL(urlString, options);
81
102
  }
82
103
 
83
- if (/^view-source:/i.test(urlString)) {
84
- throw new Error('`view-source:` is not supported as it is a non-standard protocol');
104
+ if (hasCustomProtocol(urlString)) {
105
+ return urlString;
85
106
  }
86
107
 
87
108
  const hasRelativeProtocol = urlString.startsWith('//');
@@ -228,6 +249,11 @@ export default function normalizeUrl(urlString, options) {
228
249
  urlObject.pathname = urlObject.pathname.replace(/\/$/, '');
229
250
  }
230
251
 
252
+ // Remove an explicit port number, excluding a default port number, if applicable
253
+ if (options.removeExplicitPort && urlObject.port) {
254
+ urlObject.port = '';
255
+ }
256
+
231
257
  const oldUrlString = urlString;
232
258
 
233
259
  // Take advantage of many of the Node `url` normalizations
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "normalize-url",
3
- "version": "7.1.0",
3
+ "version": "8.0.0",
4
4
  "description": "Normalize a URL",
5
5
  "license": "MIT",
6
6
  "repository": "sindresorhus/normalize-url",
@@ -11,9 +11,12 @@
11
11
  "url": "https://sindresorhus.com"
12
12
  },
13
13
  "type": "module",
14
- "exports": "./index.js",
14
+ "exports": {
15
+ "types": "./index.d.ts",
16
+ "default": "./index.js"
17
+ },
15
18
  "engines": {
16
- "node": ">=12.20"
19
+ "node": ">=14.16"
17
20
  },
18
21
  "scripts": {
19
22
  "test": "xo && c8 ava && tsd"
@@ -38,10 +41,10 @@
38
41
  "canonical"
39
42
  ],
40
43
  "devDependencies": {
41
- "ava": "^4.0.1",
42
- "c8": "^7.11.0",
43
- "tsd": "^0.19.1",
44
- "xo": "^0.47.0"
44
+ "ava": "^5.0.1",
45
+ "c8": "^7.12.0",
46
+ "tsd": "^0.24.1",
47
+ "xo": "^0.52.4"
45
48
  },
46
49
  "c8": {
47
50
  "reporter": [
package/readme.md CHANGED
@@ -30,6 +30,8 @@ normalizeUrl('//www.sindresorhus.com:80/../baz?b=bar&a=foo');
30
30
 
31
31
  ### normalizeUrl(url, options?)
32
32
 
33
+ URLs with custom protocols are not normalized and just passed through by default. Supported protocols are: `https`, `http`, `file`, and `data`.
34
+
33
35
  #### url
34
36
 
35
37
  Type: `string`
@@ -43,8 +45,8 @@ Type: `object`
43
45
  ##### defaultProtocol
44
46
 
45
47
  Type: `string`\
46
- Default: `http:`\
47
- Values: `'https:' | 'http:'`
48
+ Default: `'http'`\
49
+ Values: `'https' | 'http'`
48
50
 
49
51
  ##### normalizeProtocol
50
52
 
@@ -54,10 +56,10 @@ Default: `true`
54
56
  Prepend `defaultProtocol` to the URL if it's protocol-relative.
55
57
 
56
58
  ```js
57
- normalizeUrl('//sindresorhus.com:80/');
59
+ normalizeUrl('//sindresorhus.com');
58
60
  //=> 'http://sindresorhus.com'
59
61
 
60
- normalizeUrl('//sindresorhus.com:80/', {normalizeProtocol: false});
62
+ normalizeUrl('//sindresorhus.com', {normalizeProtocol: false});
61
63
  //=> '//sindresorhus.com'
62
64
  ```
63
65
 
@@ -66,13 +68,13 @@ normalizeUrl('//sindresorhus.com:80/', {normalizeProtocol: false});
66
68
  Type: `boolean`\
67
69
  Default: `false`
68
70
 
69
- Normalize `https:` to `http:`.
71
+ Normalize HTTPS to HTTP.
70
72
 
71
73
  ```js
72
- normalizeUrl('https://sindresorhus.com:80/');
74
+ normalizeUrl('https://sindresorhus.com');
73
75
  //=> 'https://sindresorhus.com'
74
76
 
75
- normalizeUrl('https://sindresorhus.com:80/', {forceHttp: true});
77
+ normalizeUrl('https://sindresorhus.com', {forceHttp: true});
76
78
  //=> 'http://sindresorhus.com'
77
79
  ```
78
80
 
@@ -81,17 +83,17 @@ normalizeUrl('https://sindresorhus.com:80/', {forceHttp: true});
81
83
  Type: `boolean`\
82
84
  Default: `false`
83
85
 
84
- Normalize `http:` to `https:`.
86
+ Normalize HTTP to HTTPS.
85
87
 
86
88
  ```js
87
- normalizeUrl('https://sindresorhus.com:80/');
88
- //=> 'https://sindresorhus.com'
89
+ normalizeUrl('http://sindresorhus.com');
90
+ //=> 'http://sindresorhus.com'
89
91
 
90
- normalizeUrl('http://sindresorhus.com:80/', {forceHttps: true});
92
+ normalizeUrl('http://sindresorhus.com', {forceHttps: true});
91
93
  //=> 'https://sindresorhus.com'
92
94
  ```
93
95
 
94
- This option can't be used with the `forceHttp` option at the same time.
96
+ This option cannot be used with the `forceHttp` option at the same time.
95
97
 
96
98
  ##### stripAuthentication
97
99
 
@@ -275,6 +277,22 @@ normalizeUrl('www.sindresorhus.com/foo/default.php', {
275
277
  //=> 'http://sindresorhus.com/foo'
276
278
  ```
277
279
 
280
+ ##### removeExplicitPort
281
+
282
+ Type: `boolean`\
283
+ Default: `false`
284
+
285
+ Removes an explicit port number from the URL.
286
+
287
+ Port 443 is always removed from HTTPS URLs and 80 is always removed from HTTP URLs regardless of this option.
288
+
289
+ ```js
290
+ normalizeUrl('sindresorhus.com:123', {
291
+ removeExplicitPort: true
292
+ });
293
+ //=> 'http://sindresorhus.com'
294
+ ```
295
+
278
296
  ##### sortQueryParameters
279
297
 
280
298
  Type: `boolean`\