normalize-url 2.0.1 → 3.2.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.
- package/index.js +35 -77
- package/package.json +38 -44
- package/readme.md +17 -0
package/index.js
CHANGED
|
@@ -1,38 +1,16 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
const queryString = require('query-string');
|
|
5
|
-
const prependHttp = require('prepend-http');
|
|
6
|
-
const sortKeys = require('sort-keys');
|
|
7
|
-
|
|
8
|
-
const DEFAULT_PORTS = {
|
|
9
|
-
'http:': 80,
|
|
10
|
-
'https:': 443,
|
|
11
|
-
'ftp:': 21
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
// Protocols that always contain a `//`` bit
|
|
15
|
-
const slashedProtocol = {
|
|
16
|
-
http: true,
|
|
17
|
-
https: true,
|
|
18
|
-
ftp: true,
|
|
19
|
-
gopher: true,
|
|
20
|
-
file: true,
|
|
21
|
-
'http:': true,
|
|
22
|
-
'https:': true,
|
|
23
|
-
'ftp:': true,
|
|
24
|
-
'gopher:': true,
|
|
25
|
-
'file:': true
|
|
26
|
-
};
|
|
2
|
+
// TODO: Use the `URL` global when targeting Node.js 10
|
|
3
|
+
const URLParser = typeof URL === 'undefined' ? require('url').URL : URL;
|
|
27
4
|
|
|
28
5
|
function testParameter(name, filters) {
|
|
29
6
|
return filters.some(filter => filter instanceof RegExp ? filter.test(name) : filter === name);
|
|
30
7
|
}
|
|
31
8
|
|
|
32
|
-
module.exports = (
|
|
9
|
+
module.exports = (urlString, opts) => {
|
|
33
10
|
opts = Object.assign({
|
|
34
11
|
normalizeProtocol: true,
|
|
35
12
|
normalizeHttps: false,
|
|
13
|
+
normalizeHttp: false,
|
|
36
14
|
stripFragment: true,
|
|
37
15
|
stripWWW: true,
|
|
38
16
|
removeQueryParameters: [/^utm_\w+/i],
|
|
@@ -41,43 +19,45 @@ module.exports = (str, opts) => {
|
|
|
41
19
|
sortQueryParameters: true
|
|
42
20
|
}, opts);
|
|
43
21
|
|
|
44
|
-
|
|
45
|
-
throw new TypeError('Expected a string');
|
|
46
|
-
}
|
|
22
|
+
urlString = urlString.trim();
|
|
47
23
|
|
|
48
|
-
const hasRelativeProtocol =
|
|
24
|
+
const hasRelativeProtocol = urlString.startsWith('//');
|
|
25
|
+
const isRelativeUrl = !hasRelativeProtocol && /^\.*\//.test(urlString);
|
|
49
26
|
|
|
50
27
|
// Prepend protocol
|
|
51
|
-
|
|
28
|
+
if (!isRelativeUrl) {
|
|
29
|
+
urlString = urlString.replace(/^(?!(?:\w+:)?\/\/)|^\/\//, 'http://');
|
|
30
|
+
}
|
|
52
31
|
|
|
53
|
-
const urlObj =
|
|
32
|
+
const urlObj = new URLParser(urlString);
|
|
54
33
|
|
|
55
|
-
if (opts.normalizeHttps &&
|
|
56
|
-
|
|
34
|
+
if (opts.normalizeHttps && opts.normalizeHttp) {
|
|
35
|
+
throw new Error('The `normalizeHttp` and `normalizeHttps` options cannot be used together');
|
|
57
36
|
}
|
|
58
37
|
|
|
59
|
-
if (
|
|
60
|
-
|
|
38
|
+
if (opts.normalizeHttp && urlObj.protocol === 'http:') {
|
|
39
|
+
urlObj.protocol = 'https:';
|
|
61
40
|
}
|
|
62
41
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
42
|
+
if (opts.normalizeHttps && urlObj.protocol === 'https:') {
|
|
43
|
+
urlObj.protocol = 'http:';
|
|
44
|
+
}
|
|
66
45
|
|
|
67
46
|
// Remove fragment
|
|
68
47
|
if (opts.stripFragment) {
|
|
69
|
-
|
|
48
|
+
urlObj.hash = '';
|
|
70
49
|
}
|
|
71
50
|
|
|
72
|
-
// Remove
|
|
73
|
-
const port = DEFAULT_PORTS[urlObj.protocol];
|
|
74
|
-
if (Number(urlObj.port) === port) {
|
|
75
|
-
delete urlObj.port;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Remove duplicate slashes
|
|
51
|
+
// Remove duplicate slashes if not preceded by a protocol
|
|
79
52
|
if (urlObj.pathname) {
|
|
80
|
-
|
|
53
|
+
// TODO: Use the following instead when targeting Node.js 10
|
|
54
|
+
// `urlObj.pathname = urlObj.pathname.replace(/(?<!https?:)\/{2,}/g, '/');`
|
|
55
|
+
urlObj.pathname = urlObj.pathname.replace(/((?![https?:]).)\/{2,}/g, (_, p1) => {
|
|
56
|
+
if (/^(?!\/)/g.test(p1)) {
|
|
57
|
+
return `${p1}/`;
|
|
58
|
+
}
|
|
59
|
+
return '/';
|
|
60
|
+
});
|
|
81
61
|
}
|
|
82
62
|
|
|
83
63
|
// Decode URI octets
|
|
@@ -100,17 +80,7 @@ module.exports = (str, opts) => {
|
|
|
100
80
|
}
|
|
101
81
|
}
|
|
102
82
|
|
|
103
|
-
// Resolve relative paths, but only for slashed protocols
|
|
104
|
-
if (slashedProtocol[urlObj.protocol]) {
|
|
105
|
-
const domain = urlObj.protocol + '//' + urlObj.hostname;
|
|
106
|
-
const relative = url.resolve(domain, urlObj.pathname);
|
|
107
|
-
urlObj.pathname = relative.replace(domain, '');
|
|
108
|
-
}
|
|
109
|
-
|
|
110
83
|
if (urlObj.hostname) {
|
|
111
|
-
// IDN to Unicode
|
|
112
|
-
urlObj.hostname = punycode.toUnicode(urlObj.hostname).toLowerCase();
|
|
113
|
-
|
|
114
84
|
// Remove trailing dot
|
|
115
85
|
urlObj.hostname = urlObj.hostname.replace(/\.$/, '');
|
|
116
86
|
|
|
@@ -120,44 +90,32 @@ module.exports = (str, opts) => {
|
|
|
120
90
|
}
|
|
121
91
|
}
|
|
122
92
|
|
|
123
|
-
// Remove URL with empty query string
|
|
124
|
-
if (urlObj.search === '?') {
|
|
125
|
-
delete urlObj.search;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const queryParameters = queryString.parse(urlObj.search);
|
|
129
|
-
|
|
130
93
|
// Remove query unwanted parameters
|
|
131
94
|
if (Array.isArray(opts.removeQueryParameters)) {
|
|
132
|
-
for (const key
|
|
95
|
+
for (const key of [...urlObj.searchParams.keys()]) {
|
|
133
96
|
if (testParameter(key, opts.removeQueryParameters)) {
|
|
134
|
-
delete
|
|
97
|
+
urlObj.searchParams.delete(key);
|
|
135
98
|
}
|
|
136
99
|
}
|
|
137
100
|
}
|
|
138
101
|
|
|
139
102
|
// Sort query parameters
|
|
140
103
|
if (opts.sortQueryParameters) {
|
|
141
|
-
urlObj.
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// Decode query parameters
|
|
145
|
-
if (urlObj.search !== null) {
|
|
146
|
-
urlObj.search = decodeURIComponent(urlObj.search);
|
|
104
|
+
urlObj.searchParams.sort();
|
|
147
105
|
}
|
|
148
106
|
|
|
149
107
|
// Take advantage of many of the Node `url` normalizations
|
|
150
|
-
|
|
108
|
+
urlString = urlObj.toString();
|
|
151
109
|
|
|
152
110
|
// Remove ending `/`
|
|
153
111
|
if (opts.removeTrailingSlash || urlObj.pathname === '/') {
|
|
154
|
-
|
|
112
|
+
urlString = urlString.replace(/\/$/, '');
|
|
155
113
|
}
|
|
156
114
|
|
|
157
115
|
// Restore relative protocol, if applicable
|
|
158
116
|
if (hasRelativeProtocol && !opts.normalizeProtocol) {
|
|
159
|
-
|
|
117
|
+
urlString = urlString.replace(/^http:\/\//, '//');
|
|
160
118
|
}
|
|
161
119
|
|
|
162
|
-
return
|
|
120
|
+
return urlString;
|
|
163
121
|
};
|
package/package.json
CHANGED
|
@@ -1,46 +1,40 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
"sort-keys": "^2.0.0"
|
|
41
|
-
},
|
|
42
|
-
"devDependencies": {
|
|
43
|
-
"ava": "*",
|
|
44
|
-
"xo": "*"
|
|
45
|
-
}
|
|
2
|
+
"name": "normalize-url",
|
|
3
|
+
"version": "3.2.0",
|
|
4
|
+
"description": "Normalize a URL",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": "sindresorhus/normalize-url",
|
|
7
|
+
"author": {
|
|
8
|
+
"name": "Sindre Sorhus",
|
|
9
|
+
"email": "sindresorhus@gmail.com",
|
|
10
|
+
"url": "sindresorhus.com"
|
|
11
|
+
},
|
|
12
|
+
"engines": {
|
|
13
|
+
"node": ">=6"
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"test": "xo && ava"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"index.js"
|
|
20
|
+
],
|
|
21
|
+
"keywords": [
|
|
22
|
+
"normalize",
|
|
23
|
+
"url",
|
|
24
|
+
"uri",
|
|
25
|
+
"address",
|
|
26
|
+
"string",
|
|
27
|
+
"normalization",
|
|
28
|
+
"normalisation",
|
|
29
|
+
"query",
|
|
30
|
+
"querystring",
|
|
31
|
+
"simplify",
|
|
32
|
+
"strip",
|
|
33
|
+
"trim",
|
|
34
|
+
"canonical"
|
|
35
|
+
],
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"ava": "*",
|
|
38
|
+
"xo": "*"
|
|
39
|
+
}
|
|
46
40
|
}
|
package/readme.md
CHANGED
|
@@ -69,6 +69,23 @@ normalizeUrl('https://sindresorhus.com:80/', {normalizeHttps: true});
|
|
|
69
69
|
//=> 'http://sindresorhus.com'
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
+
##### normalizeHttp
|
|
73
|
+
|
|
74
|
+
Type: `boolean`<br>
|
|
75
|
+
Default: `false`
|
|
76
|
+
|
|
77
|
+
Normalize `http:` URLs to `https:`.
|
|
78
|
+
|
|
79
|
+
```js
|
|
80
|
+
normalizeUrl('https://sindresorhus.com:80/');
|
|
81
|
+
//=> 'https://sindresorhus.com'
|
|
82
|
+
|
|
83
|
+
normalizeUrl('http://sindresorhus.com:80/', {normalizeHttp: true});
|
|
84
|
+
//=> 'https://sindresorhus.com'
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
This option is mutually exclusive with the `normalizeHttps` option.
|
|
88
|
+
|
|
72
89
|
##### stripFragment
|
|
73
90
|
|
|
74
91
|
Type: `boolean`<br>
|