normalize-url 6.0.1 → 7.0.2

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 (5) hide show
  1. package/index.d.ts +213 -199
  2. package/index.js +68 -40
  3. package/license +1 -1
  4. package/package.json +11 -8
  5. package/readme.md +22 -3
package/index.d.ts CHANGED
@@ -1,231 +1,247 @@
1
- declare namespace normalizeUrl {
2
- interface Options {
3
- /**
4
- @default 'http:'
5
- */
6
- readonly defaultProtocol?: string;
1
+ export interface Options {
2
+ /**
3
+ @default 'http:'
4
+ */
5
+ readonly defaultProtocol?: string;
7
6
 
8
- /**
9
- Prepends `defaultProtocol` to the URL if it's protocol-relative.
7
+ /**
8
+ Prepends `defaultProtocol` to the URL if it's protocol-relative.
10
9
 
11
- @default true
10
+ @default true
12
11
 
13
- @example
14
- ```
15
- normalizeUrl('//sindresorhus.com:80/');
16
- //=> 'http://sindresorhus.com'
12
+ @example
13
+ ```
14
+ normalizeUrl('//sindresorhus.com:80/');
15
+ //=> 'http://sindresorhus.com'
17
16
 
18
- normalizeUrl('//sindresorhus.com:80/', {normalizeProtocol: false});
19
- //=> '//sindresorhus.com'
20
- ```
21
- */
22
- readonly normalizeProtocol?: boolean;
17
+ normalizeUrl('//sindresorhus.com:80/', {normalizeProtocol: false});
18
+ //=> '//sindresorhus.com'
19
+ ```
20
+ */
21
+ readonly normalizeProtocol?: boolean;
23
22
 
24
- /**
25
- Normalizes `https:` URLs to `http:`.
23
+ /**
24
+ Normalizes `https:` URLs to `http:`.
26
25
 
27
- @default false
26
+ @default false
28
27
 
29
- @example
30
- ```
31
- normalizeUrl('https://sindresorhus.com:80/');
32
- //=> 'https://sindresorhus.com'
28
+ @example
29
+ ```
30
+ normalizeUrl('https://sindresorhus.com:80/');
31
+ //=> 'https://sindresorhus.com'
33
32
 
34
- normalizeUrl('https://sindresorhus.com:80/', {forceHttp: true});
35
- //=> 'http://sindresorhus.com'
36
- ```
37
- */
38
- readonly forceHttp?: boolean;
33
+ normalizeUrl('https://sindresorhus.com:80/', {forceHttp: true});
34
+ //=> 'http://sindresorhus.com'
35
+ ```
36
+ */
37
+ readonly forceHttp?: boolean;
39
38
 
40
- /**
41
- Normalizes `http:` URLs to `https:`.
39
+ /**
40
+ Normalizes `http:` URLs to `https:`.
42
41
 
43
- This option can't be used with the `forceHttp` option at the same time.
42
+ This option can't be used with the `forceHttp` option at the same time.
44
43
 
45
- @default false
44
+ @default false
46
45
 
47
- @example
48
- ```
49
- normalizeUrl('https://sindresorhus.com:80/');
50
- //=> 'https://sindresorhus.com'
46
+ @example
47
+ ```
48
+ normalizeUrl('https://sindresorhus.com:80/');
49
+ //=> 'https://sindresorhus.com'
51
50
 
52
- normalizeUrl('http://sindresorhus.com:80/', {forceHttps: true});
53
- //=> 'https://sindresorhus.com'
54
- ```
55
- */
56
- readonly forceHttps?: boolean;
51
+ normalizeUrl('http://sindresorhus.com:80/', {forceHttps: true});
52
+ //=> 'https://sindresorhus.com'
53
+ ```
54
+ */
55
+ readonly forceHttps?: boolean;
57
56
 
58
- /**
59
- Strip the [authentication](https://en.wikipedia.org/wiki/Basic_access_authentication) part of a URL.
57
+ /**
58
+ Strip the [authentication](https://en.wikipedia.org/wiki/Basic_access_authentication) part of a URL.
60
59
 
61
- @default true
60
+ @default true
62
61
 
63
- @example
64
- ```
65
- normalizeUrl('user:password@sindresorhus.com');
66
- //=> 'https://sindresorhus.com'
62
+ @example
63
+ ```
64
+ normalizeUrl('user:password@sindresorhus.com');
65
+ //=> 'https://sindresorhus.com'
67
66
 
68
- normalizeUrl('user:password@sindresorhus.com', {stripAuthentication: false});
69
- //=> 'https://user:password@sindresorhus.com'
70
- ```
71
- */
72
- readonly stripAuthentication?: boolean;
67
+ normalizeUrl('user:password@sindresorhus.com', {stripAuthentication: false});
68
+ //=> 'https://user:password@sindresorhus.com'
69
+ ```
70
+ */
71
+ readonly stripAuthentication?: boolean;
73
72
 
74
- /**
75
- Removes hash from the URL.
73
+ /**
74
+ Removes hash from the URL.
76
75
 
77
- @default false
76
+ @default false
78
77
 
79
- @example
80
- ```
81
- normalizeUrl('sindresorhus.com/about.html#contact');
82
- //=> 'http://sindresorhus.com/about.html#contact'
78
+ @example
79
+ ```
80
+ normalizeUrl('sindresorhus.com/about.html#contact');
81
+ //=> 'http://sindresorhus.com/about.html#contact'
83
82
 
84
- normalizeUrl('sindresorhus.com/about.html#contact', {stripHash: true});
85
- //=> 'http://sindresorhus.com/about.html'
86
- ```
87
- */
88
- readonly stripHash?: boolean;
83
+ normalizeUrl('sindresorhus.com/about.html#contact', {stripHash: true});
84
+ //=> 'http://sindresorhus.com/about.html'
85
+ ```
86
+ */
87
+ readonly stripHash?: boolean;
89
88
 
90
- /**
91
- Removes HTTP(S) protocol from an URL `http://sindresorhus.com` → `sindresorhus.com`.
89
+ /**
90
+ Removes HTTP(S) protocol from an URL `http://sindresorhus.com` → `sindresorhus.com`.
92
91
 
93
- @default false
92
+ @default false
94
93
 
95
- @example
96
- ```
97
- normalizeUrl('https://sindresorhus.com');
98
- //=> 'https://sindresorhus.com'
94
+ @example
95
+ ```
96
+ normalizeUrl('https://sindresorhus.com');
97
+ //=> 'https://sindresorhus.com'
99
98
 
100
- normalizeUrl('sindresorhus.com', {stripProtocol: true});
101
- //=> 'sindresorhus.com'
102
- ```
103
- */
104
- readonly stripProtocol?: boolean;
99
+ normalizeUrl('sindresorhus.com', {stripProtocol: true});
100
+ //=> 'sindresorhus.com'
101
+ ```
102
+ */
103
+ readonly stripProtocol?: boolean;
105
104
 
106
- /**
107
- Strip the [text fragment](https://web.dev/text-fragments/) part of the URL
105
+ /**
106
+ Strip the [text fragment](https://web.dev/text-fragments/) part of the URL
108
107
 
109
- __Note:__ The text fragment will always be removed if the `stripHash` option is set to `true`, as the hash contains the text fragment.
108
+ __Note:__ The text fragment will always be removed if the `stripHash` option is set to `true`, as the hash contains the text fragment.
110
109
 
111
- @default true
110
+ @default true
112
111
 
113
- @example
114
- ```
115
- normalizeUrl('http://sindresorhus.com/about.html#:~:text=hello');
116
- //=> 'http://sindresorhus.com/about.html#'
112
+ @example
113
+ ```
114
+ normalizeUrl('http://sindresorhus.com/about.html#:~:text=hello');
115
+ //=> 'http://sindresorhus.com/about.html#'
117
116
 
118
- normalizeUrl('http://sindresorhus.com/about.html#section:~:text=hello');
119
- //=> 'http://sindresorhus.com/about.html#section'
117
+ normalizeUrl('http://sindresorhus.com/about.html#section:~:text=hello');
118
+ //=> 'http://sindresorhus.com/about.html#section'
120
119
 
121
- normalizeUrl('http://sindresorhus.com/about.html#:~:text=hello', {stripTextFragment: false});
122
- //=> 'http://sindresorhus.com/about.html#:~:text=hello'
120
+ normalizeUrl('http://sindresorhus.com/about.html#:~:text=hello', {stripTextFragment: false});
121
+ //=> 'http://sindresorhus.com/about.html#:~:text=hello'
123
122
 
124
- normalizeUrl('http://sindresorhus.com/about.html#section:~:text=hello', {stripTextFragment: false});
125
- //=> 'http://sindresorhus.com/about.html#section:~:text=hello'
126
- ```
127
- */
128
- readonly stripTextFragment?: boolean;
129
-
130
- /**
131
- Removes `www.` from the URL.
132
-
133
- @default true
134
-
135
- @example
136
- ```
137
- normalizeUrl('http://www.sindresorhus.com');
138
- //=> 'http://sindresorhus.com'
123
+ normalizeUrl('http://sindresorhus.com/about.html#section:~:text=hello', {stripTextFragment: false});
124
+ //=> 'http://sindresorhus.com/about.html#section:~:text=hello'
125
+ ```
126
+ */
127
+ readonly stripTextFragment?: boolean;
128
+
129
+ /**
130
+ Removes `www.` from the URL.
139
131
 
140
- normalizeUrl('http://www.sindresorhus.com', {stripWWW: false});
141
- //=> 'http://www.sindresorhus.com'
142
- ```
143
- */
144
- readonly stripWWW?: boolean;
145
-
146
- /**
147
- Removes query parameters that matches any of the provided strings or regexes.
148
-
149
- @default [/^utm_\w+/i]
150
-
151
- @example
152
- ```
153
- normalizeUrl('www.sindresorhus.com?foo=bar&ref=test_ref', {
154
- removeQueryParameters: ['ref']
155
- });
156
- //=> 'http://sindresorhus.com/?foo=bar'
157
- ```
158
- */
159
- readonly removeQueryParameters?: ReadonlyArray<RegExp | string>;
160
-
161
- /**
162
- Removes trailing slash.
163
-
164
- __Note__: Trailing slash is always removed if the URL doesn't have a pathname unless the `removeSingleSlash` option is set to `false`.
165
-
166
- @default true
167
-
168
- @example
169
- ```
170
- normalizeUrl('http://sindresorhus.com/redirect/');
171
- //=> 'http://sindresorhus.com/redirect'
172
-
173
- normalizeUrl('http://sindresorhus.com/redirect/', {removeTrailingSlash: false});
174
- //=> 'http://sindresorhus.com/redirect/'
175
-
176
- normalizeUrl('http://sindresorhus.com/', {removeTrailingSlash: false});
177
- //=> 'http://sindresorhus.com'
178
- ```
179
- */
180
- readonly removeTrailingSlash?: boolean;
181
-
182
- /**
183
- Remove a sole `/` pathname in the output. This option is independant of `removeTrailingSlash`.
184
-
185
- @default true
186
-
187
- @example
188
- ```
189
- normalizeUrl('https://sindresorhus.com/');
190
- //=> 'https://sindresorhus.com'
191
-
192
- normalizeUrl('https://sindresorhus.com/', {removeSingleSlash: false});
193
- //=> 'https://sindresorhus.com/'
194
- ```
195
- */
196
- readonly removeSingleSlash?: boolean;
197
-
198
- /**
199
- Removes the default directory index file from path that matches any of the provided strings or regexes.
200
- When `true`, the regex `/^index\.[a-z]+$/` is used.
201
-
202
- @default false
203
-
204
- @example
205
- ```
206
- normalizeUrl('www.sindresorhus.com/foo/default.php', {
207
- removeDirectoryIndex: [/^default\.[a-z]+$/]
208
- });
209
- //=> 'http://sindresorhus.com/foo'
210
- ```
211
- */
212
- readonly removeDirectoryIndex?: ReadonlyArray<RegExp | string>;
213
-
214
- /**
215
- Sorts the query parameters alphabetically by key.
216
-
217
- @default true
218
-
219
- @example
220
- ```
221
- normalizeUrl('www.sindresorhus.com?b=two&a=one&c=three', {
222
- sortQueryParameters: false
223
- });
224
- //=> 'http://sindresorhus.com/?b=two&a=one&c=three'
225
- ```
226
- */
227
- readonly sortQueryParameters?: boolean;
228
- }
132
+ @default true
133
+
134
+ @example
135
+ ```
136
+ normalizeUrl('http://www.sindresorhus.com');
137
+ //=> 'http://sindresorhus.com'
138
+
139
+ normalizeUrl('http://www.sindresorhus.com', {stripWWW: false});
140
+ //=> 'http://www.sindresorhus.com'
141
+ ```
142
+ */
143
+ readonly stripWWW?: boolean;
144
+
145
+ /**
146
+ Removes query parameters that matches any of the provided strings or regexes.
147
+
148
+ @default [/^utm_\w+/i]
149
+
150
+ @example
151
+ ```
152
+ normalizeUrl('www.sindresorhus.com?foo=bar&ref=test_ref', {
153
+ removeQueryParameters: ['ref']
154
+ });
155
+ //=> 'http://sindresorhus.com/?foo=bar'
156
+ ```
157
+
158
+ If a boolean is provided, `true` will remove all the query parameters.
159
+
160
+ ```
161
+ normalizeUrl('www.sindresorhus.com?foo=bar', {
162
+ removeQueryParameters: true
163
+ });
164
+ //=> 'http://sindresorhus.com'
165
+ ```
166
+
167
+ `false` will not remove any query parameter.
168
+
169
+ ```
170
+ normalizeUrl('www.sindresorhus.com?foo=bar&utm_medium=test&ref=test_ref', {
171
+ removeQueryParameters: false
172
+ });
173
+ //=> 'http://www.sindresorhus.com/?foo=bar&ref=test_ref&utm_medium=test'
174
+ ```
175
+ */
176
+ readonly removeQueryParameters?: ReadonlyArray<RegExp | string> | boolean;
177
+
178
+ /**
179
+ Removes trailing slash.
180
+
181
+ __Note__: Trailing slash is always removed if the URL doesn't have a pathname unless the `removeSingleSlash` option is set to `false`.
182
+
183
+ @default true
184
+
185
+ @example
186
+ ```
187
+ normalizeUrl('http://sindresorhus.com/redirect/');
188
+ //=> 'http://sindresorhus.com/redirect'
189
+
190
+ normalizeUrl('http://sindresorhus.com/redirect/', {removeTrailingSlash: false});
191
+ //=> 'http://sindresorhus.com/redirect/'
192
+
193
+ normalizeUrl('http://sindresorhus.com/', {removeTrailingSlash: false});
194
+ //=> 'http://sindresorhus.com'
195
+ ```
196
+ */
197
+ readonly removeTrailingSlash?: boolean;
198
+
199
+ /**
200
+ Remove a sole `/` pathname in the output. This option is independant of `removeTrailingSlash`.
201
+
202
+ @default true
203
+
204
+ @example
205
+ ```
206
+ normalizeUrl('https://sindresorhus.com/');
207
+ //=> 'https://sindresorhus.com'
208
+
209
+ normalizeUrl('https://sindresorhus.com/', {removeSingleSlash: false});
210
+ //=> 'https://sindresorhus.com/'
211
+ ```
212
+ */
213
+ readonly removeSingleSlash?: boolean;
214
+
215
+ /**
216
+ Removes the default directory index file from path that matches any of the provided strings or regexes.
217
+ When `true`, the regex `/^index\.[a-z]+$/` is used.
218
+
219
+ @default false
220
+
221
+ @example
222
+ ```
223
+ normalizeUrl('www.sindresorhus.com/foo/default.php', {
224
+ removeDirectoryIndex: [/^default\.[a-z]+$/]
225
+ });
226
+ //=> 'http://sindresorhus.com/foo'
227
+ ```
228
+ */
229
+ readonly removeDirectoryIndex?: boolean | ReadonlyArray<RegExp | string>;
230
+
231
+ /**
232
+ Sorts the query parameters alphabetically by key.
233
+
234
+ @default true
235
+
236
+ @example
237
+ ```
238
+ normalizeUrl('www.sindresorhus.com?b=two&a=one&c=three', {
239
+ sortQueryParameters: false
240
+ });
241
+ //=> 'http://sindresorhus.com/?b=two&a=one&c=three'
242
+ ```
243
+ */
244
+ readonly sortQueryParameters?: boolean;
229
245
  }
230
246
 
231
247
  /**
@@ -235,7 +251,7 @@ declare namespace normalizeUrl {
235
251
 
236
252
  @example
237
253
  ```
238
- import normalizeUrl = require('normalize-url');
254
+ import normalizeUrl from 'normalize-url';
239
255
 
240
256
  normalizeUrl('sindresorhus.com');
241
257
  //=> 'http://sindresorhus.com'
@@ -244,6 +260,4 @@ normalizeUrl('//www.sindresorhus.com:80/../baz?b=bar&a=foo');
244
260
  //=> 'http://sindresorhus.com/baz?a=foo&b=bar'
245
261
  ```
246
262
  */
247
- declare function normalizeUrl(url: string, options?: normalizeUrl.Options): string;
248
-
249
- export = normalizeUrl;
263
+ export default function normalizeUrl(url: string, options?: Options): string;
package/index.js CHANGED
@@ -1,12 +1,8 @@
1
- 'use strict';
2
-
3
1
  // https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs
4
2
  const DATA_URL_DEFAULT_MIME_TYPE = 'text/plain';
5
3
  const DATA_URL_DEFAULT_CHARSET = 'us-ascii';
6
4
 
7
- const testParameter = (name, filters) => {
8
- return filters.some(filter => filter instanceof RegExp ? filter.test(name) : filter === name);
9
- };
5
+ const testParameter = (name, filters) => filters.some(filter => filter instanceof RegExp ? filter.test(name) : filter === name);
10
6
 
11
7
  const normalizeDataURL = (urlString, {stripHash}) => {
12
8
  const match = /^data:(?<type>[^,]*?),(?<data>[^#]*?)(?:#(?<hash>.*))?$/.exec(urlString);
@@ -45,21 +41,21 @@ const normalizeDataURL = (urlString, {stripHash}) => {
45
41
  .filter(Boolean);
46
42
 
47
43
  const normalizedMediaType = [
48
- ...attributes
44
+ ...attributes,
49
45
  ];
50
46
 
51
47
  if (isBase64) {
52
48
  normalizedMediaType.push('base64');
53
49
  }
54
50
 
55
- if (normalizedMediaType.length !== 0 || (mimeType && mimeType !== DATA_URL_DEFAULT_MIME_TYPE)) {
51
+ if (normalizedMediaType.length > 0 || (mimeType && mimeType !== DATA_URL_DEFAULT_MIME_TYPE)) {
56
52
  normalizedMediaType.unshift(mimeType);
57
53
  }
58
54
 
59
55
  return `data:${normalizedMediaType.join(';')},${isBase64 ? data.trim() : data}${hash ? `#${hash}` : ''}`;
60
56
  };
61
57
 
62
- const normalizeUrl = (urlString, options) => {
58
+ export default function normalizeUrl(urlString, options) {
63
59
  options = {
64
60
  defaultProtocol: 'http:',
65
61
  normalizeProtocol: true,
@@ -74,7 +70,7 @@ const normalizeUrl = (urlString, options) => {
74
70
  removeSingleSlash: true,
75
71
  removeDirectoryIndex: false,
76
72
  sortQueryParameters: true,
77
- ...options
73
+ ...options,
78
74
  };
79
75
 
80
76
  urlString = urlString.trim();
@@ -96,43 +92,73 @@ const normalizeUrl = (urlString, options) => {
96
92
  urlString = urlString.replace(/^(?!(?:\w+:)?\/\/)|^\/\//, options.defaultProtocol);
97
93
  }
98
94
 
99
- const urlObj = new URL(urlString);
95
+ const urlObject = new URL(urlString);
100
96
 
101
97
  if (options.forceHttp && options.forceHttps) {
102
98
  throw new Error('The `forceHttp` and `forceHttps` options cannot be used together');
103
99
  }
104
100
 
105
- if (options.forceHttp && urlObj.protocol === 'https:') {
106
- urlObj.protocol = 'http:';
101
+ if (options.forceHttp && urlObject.protocol === 'https:') {
102
+ urlObject.protocol = 'http:';
107
103
  }
108
104
 
109
- if (options.forceHttps && urlObj.protocol === 'http:') {
110
- urlObj.protocol = 'https:';
105
+ if (options.forceHttps && urlObject.protocol === 'http:') {
106
+ urlObject.protocol = 'https:';
111
107
  }
112
108
 
113
109
  // Remove auth
114
110
  if (options.stripAuthentication) {
115
- urlObj.username = '';
116
- urlObj.password = '';
111
+ urlObject.username = '';
112
+ urlObject.password = '';
117
113
  }
118
114
 
119
115
  // Remove hash
120
116
  if (options.stripHash) {
121
- urlObj.hash = '';
117
+ urlObject.hash = '';
122
118
  } else if (options.stripTextFragment) {
123
- urlObj.hash = urlObj.hash.replace(/#?:~:text.*?$/i, '');
119
+ urlObject.hash = urlObject.hash.replace(/#?:~:text.*?$/i, '');
124
120
  }
125
121
 
126
122
  // Remove duplicate slashes if not preceded by a protocol
127
- if (urlObj.pathname) {
128
- urlObj.pathname = urlObj.pathname.replace(/(?<!\b(?:[a-z][a-z\d+\-.]{1,50}:))\/{2,}/g, '/');
123
+ // NOTE: This could be implemented using a single negative lookbehind
124
+ // regex, but we avoid that to maintain compatibility with older js engines
125
+ // which do not have support for that feature.
126
+ if (urlObject.pathname) {
127
+ // TODO: Replace everything below with `urlObject.pathname = urlObject.pathname.replace(/(?<!\b[a-z][a-z\d+\-.]{1,50}:)\/{2,}/g, '/');` when Safari supports negative lookbehind.
128
+
129
+ // Split the string by occurrences of this protocol regex, and perform
130
+ // duplicate-slash replacement on the strings between those occurrences
131
+ // (if any).
132
+ const protocolRegex = /\b[a-z][a-z\d+\-.]{1,50}:\/\//g;
133
+
134
+ let lastIndex = 0;
135
+ let result = '';
136
+ for (;;) {
137
+ const match = protocolRegex.exec(urlObject.pathname);
138
+ if (!match) {
139
+ break;
140
+ }
141
+
142
+ const protocol = match[0];
143
+ const protocolAtIndex = match.index;
144
+ const intermediate = urlObject.pathname.slice(lastIndex, protocolAtIndex);
145
+
146
+ result += intermediate.replace(/\/{2,}/g, '/');
147
+ result += protocol;
148
+ lastIndex = protocolAtIndex + protocol.length;
149
+ }
150
+
151
+ const remnant = urlObject.pathname.slice(lastIndex, urlObject.pathname.length);
152
+ result += remnant.replace(/\/{2,}/g, '/');
153
+
154
+ urlObject.pathname = result;
129
155
  }
130
156
 
131
157
  // Decode URI octets
132
- if (urlObj.pathname) {
158
+ if (urlObject.pathname) {
133
159
  try {
134
- urlObj.pathname = decodeURI(urlObj.pathname);
135
- } catch (_) {}
160
+ urlObject.pathname = decodeURI(urlObject.pathname);
161
+ } catch {}
136
162
  }
137
163
 
138
164
  // Remove directory index
@@ -141,58 +167,62 @@ const normalizeUrl = (urlString, options) => {
141
167
  }
142
168
 
143
169
  if (Array.isArray(options.removeDirectoryIndex) && options.removeDirectoryIndex.length > 0) {
144
- let pathComponents = urlObj.pathname.split('/');
170
+ let pathComponents = urlObject.pathname.split('/');
145
171
  const lastComponent = pathComponents[pathComponents.length - 1];
146
172
 
147
173
  if (testParameter(lastComponent, options.removeDirectoryIndex)) {
148
- pathComponents = pathComponents.slice(0, pathComponents.length - 1);
149
- urlObj.pathname = pathComponents.slice(1).join('/') + '/';
174
+ pathComponents = pathComponents.slice(0, -1);
175
+ urlObject.pathname = pathComponents.slice(1).join('/') + '/';
150
176
  }
151
177
  }
152
178
 
153
- if (urlObj.hostname) {
179
+ if (urlObject.hostname) {
154
180
  // Remove trailing dot
155
- urlObj.hostname = urlObj.hostname.replace(/\.$/, '');
181
+ urlObject.hostname = urlObject.hostname.replace(/\.$/, '');
156
182
 
157
183
  // Remove `www.`
158
- if (options.stripWWW && /^www\.(?!www\.)(?:[a-z\-\d]{1,63})\.(?:[a-z.\-\d]{2,63})$/.test(urlObj.hostname)) {
184
+ if (options.stripWWW && /^www\.(?!www\.)[a-z\-\d]{1,63}\.[a-z.\-\d]{2,63}$/.test(urlObject.hostname)) {
159
185
  // Each label should be max 63 at length (min: 1).
160
186
  // Source: https://en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_host_names
161
187
  // Each TLD should be up to 63 characters long (min: 2).
162
188
  // It is technically possible to have a single character TLD, but none currently exist.
163
- urlObj.hostname = urlObj.hostname.replace(/^www\./, '');
189
+ urlObject.hostname = urlObject.hostname.replace(/^www\./, '');
164
190
  }
165
191
  }
166
192
 
167
193
  // Remove query unwanted parameters
168
194
  if (Array.isArray(options.removeQueryParameters)) {
169
- for (const key of [...urlObj.searchParams.keys()]) {
195
+ for (const key of [...urlObject.searchParams.keys()]) {
170
196
  if (testParameter(key, options.removeQueryParameters)) {
171
- urlObj.searchParams.delete(key);
197
+ urlObject.searchParams.delete(key);
172
198
  }
173
199
  }
174
200
  }
175
201
 
202
+ if (options.removeQueryParameters === true) {
203
+ urlObject.search = '';
204
+ }
205
+
176
206
  // Sort query parameters
177
207
  if (options.sortQueryParameters) {
178
- urlObj.searchParams.sort();
208
+ urlObject.searchParams.sort();
179
209
  }
180
210
 
181
211
  if (options.removeTrailingSlash) {
182
- urlObj.pathname = urlObj.pathname.replace(/\/$/, '');
212
+ urlObject.pathname = urlObject.pathname.replace(/\/$/, '');
183
213
  }
184
214
 
185
215
  const oldUrlString = urlString;
186
216
 
187
217
  // Take advantage of many of the Node `url` normalizations
188
- urlString = urlObj.toString();
218
+ urlString = urlObject.toString();
189
219
 
190
- if (!options.removeSingleSlash && urlObj.pathname === '/' && !oldUrlString.endsWith('/') && urlObj.hash === '') {
220
+ if (!options.removeSingleSlash && urlObject.pathname === '/' && !oldUrlString.endsWith('/') && urlObject.hash === '') {
191
221
  urlString = urlString.replace(/\/$/, '');
192
222
  }
193
223
 
194
224
  // Remove ending `/` unless removeSingleSlash is false
195
- if ((options.removeTrailingSlash || urlObj.pathname === '/') && urlObj.hash === '' && options.removeSingleSlash) {
225
+ if ((options.removeTrailingSlash || urlObject.pathname === '/') && urlObject.hash === '' && options.removeSingleSlash) {
196
226
  urlString = urlString.replace(/\/$/, '');
197
227
  }
198
228
 
@@ -207,6 +237,4 @@ const normalizeUrl = (urlString, options) => {
207
237
  }
208
238
 
209
239
  return urlString;
210
- };
211
-
212
- module.exports = normalizeUrl;
240
+ }
package/license CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
3
+ Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
6
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "normalize-url",
3
- "version": "6.0.1",
3
+ "version": "7.0.2",
4
4
  "description": "Normalize a URL",
5
5
  "license": "MIT",
6
6
  "repository": "sindresorhus/normalize-url",
@@ -10,11 +10,13 @@
10
10
  "email": "sindresorhus@gmail.com",
11
11
  "url": "https://sindresorhus.com"
12
12
  },
13
+ "type": "module",
14
+ "exports": "./index.js",
13
15
  "engines": {
14
- "node": ">=10"
16
+ "node": ">=12.20"
15
17
  },
16
18
  "scripts": {
17
- "test": "xo && nyc ava && tsd"
19
+ "test": "xo && c8 ava && tsd"
18
20
  },
19
21
  "files": [
20
22
  "index.js",
@@ -36,12 +38,13 @@
36
38
  "canonical"
37
39
  ],
38
40
  "devDependencies": {
39
- "ava": "^2.4.0",
40
- "nyc": "^15.0.0",
41
- "tsd": "^0.11.0",
42
- "xo": "^0.25.3"
41
+ "ava": "^3.15.0",
42
+ "c8": "^7.7.3",
43
+ "tsd": "^0.17.0",
44
+ "typescript": "^4.3.5",
45
+ "xo": "^0.41.0"
43
46
  },
44
- "nyc": {
47
+ "c8": {
45
48
  "reporter": [
46
49
  "text",
47
50
  "lcov"
package/readme.md CHANGED
@@ -4,6 +4,8 @@
4
4
 
5
5
  Useful when you need to display, store, deduplicate, sort, compare, etc, URLs.
6
6
 
7
+ **Note:** This package does **not** do URL sanitization. [Garbage in, garbage out.](https://en.wikipedia.org/wiki/Garbage_in,_garbage_out) If you use this in a server context and accept URLs as user input, it's up to you to protect against invalid URLs, [path traversal attacks](https://owasp.org/www-community/attacks/Path_Traversal), etc.
8
+
7
9
  ## Install
8
10
 
9
11
  ```
@@ -15,7 +17,7 @@ $ npm install normalize-url
15
17
  ## Usage
16
18
 
17
19
  ```js
18
- const normalizeUrl = require('normalize-url');
20
+ import normalizeUrl from 'normalize-url';
19
21
 
20
22
  normalizeUrl('sindresorhus.com');
21
23
  //=> 'http://sindresorhus.com'
@@ -175,7 +177,7 @@ normalizeUrl('http://www.sindresorhus.com', {stripWWW: false});
175
177
 
176
178
  ##### removeQueryParameters
177
179
 
178
- Type: `Array<RegExp | string>`\
180
+ Type: `Array<RegExp | string> | boolean`\
179
181
  Default: `[/^utm_\w+/i]`
180
182
 
181
183
  Remove query parameters that matches any of the provided strings or regexes.
@@ -187,6 +189,24 @@ normalizeUrl('www.sindresorhus.com?foo=bar&ref=test_ref', {
187
189
  //=> 'http://sindresorhus.com/?foo=bar'
188
190
  ```
189
191
 
192
+ If a boolean is provided, `true` will remove all the query parameters.
193
+
194
+ ```js
195
+ normalizeUrl('www.sindresorhus.com?foo=bar', {
196
+ removeQueryParameters: true
197
+ });
198
+ //=> 'http://sindresorhus.com'
199
+ ```
200
+
201
+ `false` will not remove any query parameter.
202
+
203
+ ```js
204
+ normalizeUrl('www.sindresorhus.com?foo=bar&utm_medium=test&ref=test_ref', {
205
+ removeQueryParameters: false
206
+ });
207
+ //=> 'http://www.sindresorhus.com/?foo=bar&ref=test_ref&utm_medium=test'
208
+ ```
209
+
190
210
  ##### removeTrailingSlash
191
211
 
192
212
  Type: `boolean`\
@@ -222,7 +242,6 @@ normalizeUrl('https://sindresorhus.com/', {removeSingleSlash: false});
222
242
  //=> 'https://sindresorhus.com/'
223
243
  ```
224
244
 
225
-
226
245
  ##### removeDirectoryIndex
227
246
 
228
247
  Type: `boolean | Array<RegExp | string>`\