diff --git a/.gitignore b/.gitignore index 239ecff..748ccb6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules yarn.lock +.nyc_output diff --git a/.travis.yml b/.travis.yml index c89aee6..5e3bcf3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,5 @@ language: node_js node_js: - '10' - '8' - - '6' after_success: - './node_modules/.bin/nyc report --reporter=text-lcov | ./node_modules/.bin/coveralls' diff --git a/index.js b/index.js index ce70108..7e9e294 100644 --- a/index.js +++ b/index.js @@ -6,31 +6,33 @@ const testParameter = (name, filters) => { return filters.some(filter => filter instanceof RegExp ? filter.test(name) : filter === name); }; -module.exports = (urlString, opts) => { - opts = Object.assign({ +module.exports = (urlString, options) => { + options = { defaultProtocol: 'http:', normalizeProtocol: true, forceHttp: false, forceHttps: false, - stripHash: true, + stripAuthentication: true, + stripHash: false, stripWWW: true, removeQueryParameters: [/^utm_\w+/i], removeTrailingSlash: true, removeDirectoryIndex: false, - sortQueryParameters: true - }, opts); + sortQueryParameters: true, + ...options + }; - // Backwards compatibility - if (Reflect.has(opts, 'normalizeHttps')) { - opts.forceHttp = opts.normalizeHttps; + // TODO: Remove this at some point in the future + if (Reflect.has(options, 'normalizeHttps')) { + throw new Error('options.normalizeHttps is renamed to options.forceHttp'); } - if (Reflect.has(opts, 'normalizeHttp')) { - opts.forceHttps = opts.normalizeHttp; + if (Reflect.has(options, 'normalizeHttp')) { + throw new Error('options.normalizeHttp is renamed to options.forceHttps'); } - if (Reflect.has(opts, 'stripFragment')) { - opts.stripHash = opts.stripFragment; + if (Reflect.has(options, 'stripFragment')) { + throw new Error('options.stripFragment is renamed to options.stripHash'); } urlString = urlString.trim(); @@ -40,25 +42,31 @@ module.exports = (urlString, opts) => { // Prepend protocol if (!isRelativeUrl) { - urlString = urlString.replace(/^(?!(?:\w+:)?\/\/)|^\/\//, opts.defaultProtocol); + urlString = urlString.replace(/^(?!(?:\w+:)?\/\/)|^\/\//, options.defaultProtocol); } const urlObj = new URLParser(urlString); - if (opts.forceHttp && opts.forceHttps) { + if (options.forceHttp && options.forceHttps) { throw new Error('The `forceHttp` and `forceHttps` options cannot be used together'); } - if (opts.forceHttp && urlObj.protocol === 'https:') { + if (options.forceHttp && urlObj.protocol === 'https:') { urlObj.protocol = 'http:'; } - if (opts.forceHttps && urlObj.protocol === 'http:') { + if (options.forceHttps && urlObj.protocol === 'http:') { urlObj.protocol = 'https:'; } + // Remove auth + if (options.stripAuthentication) { + urlObj.username = ''; + urlObj.password = ''; + } + // Remove hash - if (opts.stripHash) { + if (options.stripHash) { urlObj.hash = ''; } @@ -80,15 +88,15 @@ module.exports = (urlString, opts) => { } // Remove directory index - if (opts.removeDirectoryIndex === true) { - opts.removeDirectoryIndex = [/^index\.[a-z]+$/]; + if (options.removeDirectoryIndex === true) { + options.removeDirectoryIndex = [/^index\.[a-z]+$/]; } - if (Array.isArray(opts.removeDirectoryIndex) && opts.removeDirectoryIndex.length > 0) { + if (Array.isArray(options.removeDirectoryIndex) && options.removeDirectoryIndex.length > 0) { let pathComponents = urlObj.pathname.split('/'); const lastComponent = pathComponents[pathComponents.length - 1]; - if (testParameter(lastComponent, opts.removeDirectoryIndex)) { + if (testParameter(lastComponent, options.removeDirectoryIndex)) { pathComponents = pathComponents.slice(0, pathComponents.length - 1); urlObj.pathname = pathComponents.slice(1).join('/') + '/'; } @@ -99,8 +107,7 @@ module.exports = (urlString, opts) => { urlObj.hostname = urlObj.hostname.replace(/\.$/, ''); // Remove `www.` - // eslint-disable-next-line no-useless-escape - if (opts.stripWWW && /^www\.([a-z\-\d]{2,63})\.([a-z\.]{2,5})$/.test(urlObj.hostname)) { + if (options.stripWWW && /^www\.([a-z\-\d]{2,63})\.([a-z.]{2,5})$/.test(urlObj.hostname)) { // Each label should be max 63 at length (min: 2). // The extension should be max 5 at length (min: 2). // Source: https://en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_host_names @@ -109,16 +116,16 @@ module.exports = (urlString, opts) => { } // Remove query unwanted parameters - if (Array.isArray(opts.removeQueryParameters)) { + if (Array.isArray(options.removeQueryParameters)) { for (const key of [...urlObj.searchParams.keys()]) { - if (testParameter(key, opts.removeQueryParameters)) { + if (testParameter(key, options.removeQueryParameters)) { urlObj.searchParams.delete(key); } } } // Sort query parameters - if (opts.sortQueryParameters) { + if (options.sortQueryParameters) { urlObj.searchParams.sort(); } @@ -126,14 +133,19 @@ module.exports = (urlString, opts) => { urlString = urlObj.toString(); // Remove ending `/` - if (opts.removeTrailingSlash || urlObj.pathname === '/') { + if (options.removeTrailingSlash || urlObj.pathname === '/') { urlString = urlString.replace(/\/$/, ''); } // Restore relative protocol, if applicable - if (hasRelativeProtocol && !opts.normalizeProtocol) { + if (hasRelativeProtocol && !options.normalizeProtocol) { urlString = urlString.replace(/^http:\/\//, '//'); } + // Remove http/https + if (options.stripProtocol) { + urlString = urlString.replace(/^(?:https?:)?\/\//, ''); + } + return urlString; }; diff --git a/package.json b/package.json index 0bbfb04..6c48e23 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "normalize-url", - "version": "3.3.0", + "version": "4.0.0", "description": "Normalize a URL", "license": "MIT", "repository": "sindresorhus/normalize-url", @@ -10,7 +10,7 @@ "url": "sindresorhus.com" }, "engines": { - "node": ">=6" + "node": ">=8" }, "scripts": { "test": "xo && nyc ava" @@ -34,9 +34,9 @@ "canonical" ], "devDependencies": { - "ava": "*", + "ava": "^0.25.0", "coveralls": "^3.0.0", - "nyc": "^12.0.2", - "xo": "*" + "nyc": "^13.1.0", + "xo": "^0.23.0" } } diff --git a/readme.md b/readme.md index d051aaf..f40153e 100644 --- a/readme.md +++ b/readme.md @@ -70,7 +70,7 @@ Normalizes `https:` URLs to `http:`. normalizeUrl('https://sindresorhus.com:80/'); //=> 'https://sindresorhus.com' -normalizeUrl('https://sindresorhus.com:80/', {normalizeHttps: true}); +normalizeUrl('https://sindresorhus.com:80/', {forceHttp: true}); //=> 'http://sindresorhus.com' ``` @@ -85,25 +85,55 @@ Normalizes `http:` URLs to `https:`. normalizeUrl('https://sindresorhus.com:80/'); //=> 'https://sindresorhus.com' -normalizeUrl('http://sindresorhus.com:80/', {normalizeHttp: true}); +normalizeUrl('http://sindresorhus.com:80/', {forceHttps: true}); //=> 'https://sindresorhus.com' ``` This option can't be used with the `forceHttp` option at the same time. -##### stripHash +##### stripAuthentication Type: `boolean`
Default: `true` +Strip the [authentication](https://en.wikipedia.org/wiki/Basic_access_authentication) part of a URL. + +```js +normalizeUrl('user:password@sindresorhus.com'); +//=> 'https://sindresorhus.com' + +normalizeUrl('user:password@sindresorhus.com', {stripAuthentication: false}); +//=> 'https://user:password@sindresorhus.com' +``` + +##### stripHash + +Type: `boolean`
+Default: `false` + Removes hash from the URL. ```js normalizeUrl('sindresorhus.com/about.html#contact'); +//=> 'http://sindresorhus.com/about.html#contact' + +normalizeUrl('sindresorhus.com/about.html#contact', {stripHash: true}); //=> 'http://sindresorhus.com/about.html' +``` -normalizeUrl('sindresorhus.com/about.html#contact', {stripHash: false}); -//=> 'http://sindresorhus.com/about.html#contact' +##### stripProtocol + +Type: `boolean`
+Default: `false` + +Removes HTTP(S) protocol from an URL `http://sindresorhus.com` → `sindresorhus.com`. + +```js +normalizeUrl('https://sindresorhus.com'); +//=> 'https://sindresorhus.com' + +normalizeUrl('sindresorhus.com', {stripProtocol: true}); +//=> 'sindresorhus.com' ``` ##### stripWWW @@ -114,11 +144,11 @@ Default: `true` Removes `www.` from the URL. ```js -normalizeUrl('http://www.sindresorhus.com/about.html#contact'); -//=> 'http://sindresorhus.com/about.html#contact' +normalizeUrl('http://www.sindresorhus.com'); +//=> 'http://sindresorhus.com' -normalizeUrl('http://www.sindresorhus.com/about.html#contact', {stripWWW: false}); -//=> 'http://www.sindresorhus.com/about.html#contact' +normalizeUrl('http://www.sindresorhus.com', {stripWWW: false}); +//=> 'http://www.sindresorhus.com' ``` ##### removeQueryParameters diff --git a/test.js b/test.js index 510ec27..9333d35 100644 --- a/test.js +++ b/test.js @@ -1,176 +1,193 @@ import test from 'ava'; -import m from '.'; +import normalizeUrl from '.'; test('main', t => { - t.is(m('sindresorhus.com'), 'http://sindresorhus.com'); - t.is(m('sindresorhus.com '), 'http://sindresorhus.com'); - t.is(m('sindresorhus.com.'), 'http://sindresorhus.com'); - t.is(m('sindresorhus.com', {defaultProtocol: 'https:'}), 'https://sindresorhus.com'); - t.is(m('HTTP://sindresorhus.com'), 'http://sindresorhus.com'); - t.is(m('//sindresorhus.com'), 'http://sindresorhus.com'); - t.is(m('http://sindresorhus.com'), 'http://sindresorhus.com'); - t.is(m('http://sindresorhus.com:80'), 'http://sindresorhus.com'); - t.is(m('https://sindresorhus.com:443'), 'https://sindresorhus.com'); - t.is(m('ftp://sindresorhus.com:21'), 'ftp://sindresorhus.com'); - t.is(m('http://www.sindresorhus.com'), 'http://sindresorhus.com'); - t.is(m('www.com'), 'http://www.com'); - t.is(m('http://www.www.sindresorhus.com'), 'http://www.www.sindresorhus.com'); - t.is(m('www.sindresorhus.com'), 'http://sindresorhus.com'); - t.is(m('http://sindresorhus.com/foo/'), 'http://sindresorhus.com/foo'); - t.is(m('sindresorhus.com/?foo=bar baz'), 'http://sindresorhus.com/?foo=bar+baz'); - t.is(m('https://foo.com/https://bar.com'), 'https://foo.com/https://bar.com'); - t.is(m('https://foo.com/https://bar.com/foo//bar'), 'https://foo.com/https://bar.com/foo/bar'); - t.is(m('https://foo.com/http://bar.com'), 'https://foo.com/http://bar.com'); - t.is(m('https://foo.com/http://bar.com/foo//bar'), 'https://foo.com/http://bar.com/foo/bar'); - t.is(m('http://sindresorhus.com/%7Efoo/'), 'http://sindresorhus.com/~foo', 'decode URI octets'); - t.is(m('http://sindresorhus.com/?'), 'http://sindresorhus.com'); - t.is(m('êxample.com'), 'http://xn--xample-hva.com'); - t.is(m('http://sindresorhus.com/?b=bar&a=foo'), 'http://sindresorhus.com/?a=foo&b=bar'); - t.is(m('http://sindresorhus.com/?foo=bar*|<>:"'), 'http://sindresorhus.com/?foo=bar*%7C%3C%3E%3A%22'); - t.is(m('http://sindresorhus.com:5000'), 'http://sindresorhus.com:5000'); - t.is(m('http://sindresorhus.com////foo/bar'), 'http://sindresorhus.com/foo/bar'); - t.is(m('http://sindresorhus.com////foo////bar'), 'http://sindresorhus.com/foo/bar'); - t.is(m('//sindresorhus.com/', {normalizeProtocol: false}), '//sindresorhus.com'); - t.is(m('//sindresorhus.com:80/', {normalizeProtocol: false}), '//sindresorhus.com'); - t.is(m('http://sindresorhus.com/foo#bar'), 'http://sindresorhus.com/foo'); - t.is(m('http://sindresorhus.com/foo#bar', {stripHash: false}), 'http://sindresorhus.com/foo#bar'); - t.is(m('http://sindresorhus.com/foo/bar/../baz'), 'http://sindresorhus.com/foo/baz'); - t.is(m('http://sindresorhus.com/foo/bar/./baz'), 'http://sindresorhus.com/foo/bar/baz'); - t.is(m('sindre://www.sorhus.com'), 'sindre://sorhus.com'); - t.is(m('sindre://www.sorhus.com/'), 'sindre://sorhus.com'); - t.is(m('sindre://www.sorhus.com/foo/bar'), 'sindre://sorhus.com/foo/bar'); - t.is(m('https://i.vimeocdn.com/filter/overlay?src0=https://i.vimeocdn.com/video/598160082_1280x720.jpg&src1=https://f.vimeocdn.com/images_v6/share/play_icon_overlay.png'), 'https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F598160082_1280x720.jpg&src1=https%3A%2F%2Ff.vimeocdn.com%2Fimages_v6%2Fshare%2Fplay_icon_overlay.png'); + t.is(normalizeUrl('sindresorhus.com'), 'http://sindresorhus.com'); + t.is(normalizeUrl('sindresorhus.com '), 'http://sindresorhus.com'); + t.is(normalizeUrl('sindresorhus.com.'), 'http://sindresorhus.com'); + t.is(normalizeUrl('sindresorhus.com', {defaultProtocol: 'https:'}), 'https://sindresorhus.com'); + t.is(normalizeUrl('HTTP://sindresorhus.com'), 'http://sindresorhus.com'); + t.is(normalizeUrl('//sindresorhus.com'), 'http://sindresorhus.com'); + t.is(normalizeUrl('http://sindresorhus.com'), 'http://sindresorhus.com'); + t.is(normalizeUrl('http://sindresorhus.com:80'), 'http://sindresorhus.com'); + t.is(normalizeUrl('https://sindresorhus.com:443'), 'https://sindresorhus.com'); + t.is(normalizeUrl('ftp://sindresorhus.com:21'), 'ftp://sindresorhus.com'); + t.is(normalizeUrl('http://www.sindresorhus.com'), 'http://sindresorhus.com'); + t.is(normalizeUrl('www.com'), 'http://www.com'); + t.is(normalizeUrl('http://www.www.sindresorhus.com'), 'http://www.www.sindresorhus.com'); + t.is(normalizeUrl('www.sindresorhus.com'), 'http://sindresorhus.com'); + t.is(normalizeUrl('http://sindresorhus.com/foo/'), 'http://sindresorhus.com/foo'); + t.is(normalizeUrl('sindresorhus.com/?foo=bar baz'), 'http://sindresorhus.com/?foo=bar+baz'); + t.is(normalizeUrl('https://foo.com/https://bar.com'), 'https://foo.com/https://bar.com'); + t.is(normalizeUrl('https://foo.com/https://bar.com/foo//bar'), 'https://foo.com/https://bar.com/foo/bar'); + t.is(normalizeUrl('https://foo.com/http://bar.com'), 'https://foo.com/http://bar.com'); + t.is(normalizeUrl('https://foo.com/http://bar.com/foo//bar'), 'https://foo.com/http://bar.com/foo/bar'); + t.is(normalizeUrl('http://sindresorhus.com/%7Efoo/'), 'http://sindresorhus.com/~foo', 'decode URI octets'); + t.is(normalizeUrl('http://sindresorhus.com/?'), 'http://sindresorhus.com'); + t.is(normalizeUrl('êxample.com'), 'http://xn--xample-hva.com'); + t.is(normalizeUrl('http://sindresorhus.com/?b=bar&a=foo'), 'http://sindresorhus.com/?a=foo&b=bar'); + t.is(normalizeUrl('http://sindresorhus.com/?foo=bar*|<>:"'), 'http://sindresorhus.com/?foo=bar*%7C%3C%3E%3A%22'); + t.is(normalizeUrl('http://sindresorhus.com:5000'), 'http://sindresorhus.com:5000'); + t.is(normalizeUrl('http://sindresorhus.com////foo/bar'), 'http://sindresorhus.com/foo/bar'); + t.is(normalizeUrl('http://sindresorhus.com////foo////bar'), 'http://sindresorhus.com/foo/bar'); + t.is(normalizeUrl('//sindresorhus.com/', {normalizeProtocol: false}), '//sindresorhus.com'); + t.is(normalizeUrl('//sindresorhus.com:80/', {normalizeProtocol: false}), '//sindresorhus.com'); + t.is(normalizeUrl('http://sindresorhus.com/foo#bar'), 'http://sindresorhus.com/foo#bar'); + t.is(normalizeUrl('http://sindresorhus.com/foo#bar', {stripHash: true}), 'http://sindresorhus.com/foo'); + t.is(normalizeUrl('http://sindresorhus.com/foo/bar/../baz'), 'http://sindresorhus.com/foo/baz'); + t.is(normalizeUrl('http://sindresorhus.com/foo/bar/./baz'), 'http://sindresorhus.com/foo/bar/baz'); + t.is(normalizeUrl('sindre://www.sorhus.com'), 'sindre://sorhus.com'); + t.is(normalizeUrl('sindre://www.sorhus.com/'), 'sindre://sorhus.com'); + t.is(normalizeUrl('sindre://www.sorhus.com/foo/bar'), 'sindre://sorhus.com/foo/bar'); + t.is(normalizeUrl('https://i.vimeocdn.com/filter/overlay?src0=https://i.vimeocdn.com/video/598160082_1280x720.jpg&src1=https://f.vimeocdn.com/images_v6/share/play_icon_overlay.png'), 'https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F598160082_1280x720.jpg&src1=https%3A%2F%2Ff.vimeocdn.com%2Fimages_v6%2Fshare%2Fplay_icon_overlay.png'); + t.is(normalizeUrl('http://user:password@www.sindresorhus.com'), 'http://sindresorhus.com'); + t.is(normalizeUrl('https://user:password@www.sindresorhus.com'), 'https://sindresorhus.com'); + t.is(normalizeUrl('https://user:password@www.sindresorhus.com/@user'), 'https://sindresorhus.com/@user'); + t.is(normalizeUrl('user:password@sindresorhus.com'), 'http://sindresorhus.com'); + t.is(normalizeUrl('http://user:password@www.êxample.com'), 'http://xn--xample-hva.com'); + t.is(normalizeUrl('sindre://user:password@www.sorhus.com'), 'sindre://sorhus.com'); }); -test('backwards compatibility', t => { - t.is(m('http://sindresorhus.com/foo#bar', {stripFragment: false}), 'http://sindresorhus.com/foo#bar'); - t.is(m('https://sindresorhus.com', {normalizeHttps: true}), 'http://sindresorhus.com'); - t.is(m('http://sindresorhus.com', {normalizeHttp: true}), 'https://sindresorhus.com'); +test('stripAuthentication option', t => { + const options = {stripAuthentication: false}; + t.is(normalizeUrl('http://user:password@www.sindresorhus.com', options), 'http://user:password@sindresorhus.com'); + t.is(normalizeUrl('https://user:password@www.sindresorhus.com', options), 'https://user:password@sindresorhus.com'); + t.is(normalizeUrl('https://user:password@www.sindresorhus.com/@user', options), 'https://user:password@sindresorhus.com/@user'); + t.is(normalizeUrl('user:password@sindresorhus.com', options), 'http://user:password@sindresorhus.com'); + t.is(normalizeUrl('http://user:password@www.êxample.com', options), 'http://user:password@xn--xample-hva.com'); + t.is(normalizeUrl('sindre://user:password@www.sorhus.com', options), 'sindre://user:password@sorhus.com'); +}); + +test('stripProtocol option', t => { + const options = {stripProtocol: true}; + t.is(normalizeUrl('http://www.sindresorhus.com', options), 'sindresorhus.com'); + t.is(normalizeUrl('http://sindresorhus.com', options), 'sindresorhus.com'); + t.is(normalizeUrl('https://www.sindresorhus.com', options), 'sindresorhus.com'); + t.is(normalizeUrl('//www.sindresorhus.com', options), 'sindresorhus.com'); + t.is(normalizeUrl('sindre://user:password@www.sorhus.com', options), 'sindre://sorhus.com'); + t.is(normalizeUrl('sindre://www.sorhus.com', options), 'sindre://sorhus.com'); }); test('stripWWW option', t => { - const opts = {stripWWW: false}; - t.is(m('http://www.sindresorhus.com', opts), 'http://www.sindresorhus.com'); - t.is(m('www.sindresorhus.com', opts), 'http://www.sindresorhus.com'); - t.is(m('http://www.êxample.com', opts), 'http://www.xn--xample-hva.com'); - t.is(m('sindre://www.sorhus.com', opts), 'sindre://www.sorhus.com'); + const options = {stripWWW: false}; + t.is(normalizeUrl('http://www.sindresorhus.com', options), 'http://www.sindresorhus.com'); + t.is(normalizeUrl('www.sindresorhus.com', options), 'http://www.sindresorhus.com'); + t.is(normalizeUrl('http://www.êxample.com', options), 'http://www.xn--xample-hva.com'); + t.is(normalizeUrl('sindre://www.sorhus.com', options), 'sindre://www.sorhus.com'); }); test('removeQueryParameters option', t => { - const opts = { + const options = { stripWWW: false, removeQueryParameters: [/^utm_\w+/i, 'ref'] }; - t.is(m('www.sindresorhus.com?foo=bar&utm_medium=test'), 'http://sindresorhus.com/?foo=bar'); - t.is(m('http://www.sindresorhus.com', opts), 'http://www.sindresorhus.com'); - t.is(m('www.sindresorhus.com?foo=bar', opts), 'http://www.sindresorhus.com/?foo=bar'); - t.is(m('www.sindresorhus.com?foo=bar&utm_medium=test&ref=test_ref', opts), 'http://www.sindresorhus.com/?foo=bar'); + t.is(normalizeUrl('www.sindresorhus.com?foo=bar&utm_medium=test'), 'http://sindresorhus.com/?foo=bar'); + t.is(normalizeUrl('http://www.sindresorhus.com', options), 'http://www.sindresorhus.com'); + t.is(normalizeUrl('www.sindresorhus.com?foo=bar', options), 'http://www.sindresorhus.com/?foo=bar'); + t.is(normalizeUrl('www.sindresorhus.com?foo=bar&utm_medium=test&ref=test_ref', options), 'http://www.sindresorhus.com/?foo=bar'); }); test('forceHttp option', t => { - const opts = {forceHttp: true}; - - t.is(m('https://sindresorhus.com'), 'https://sindresorhus.com'); - t.is(m('http://sindresorhus.com', opts), 'http://sindresorhus.com'); - t.is(m('https://www.sindresorhus.com', opts), 'http://sindresorhus.com'); - t.is(m('//sindresorhus.com', opts), 'http://sindresorhus.com'); + const options = {forceHttp: true}; + t.is(normalizeUrl('https://sindresorhus.com'), 'https://sindresorhus.com'); + t.is(normalizeUrl('http://sindresorhus.com', options), 'http://sindresorhus.com'); + t.is(normalizeUrl('https://www.sindresorhus.com', options), 'http://sindresorhus.com'); + t.is(normalizeUrl('//sindresorhus.com', options), 'http://sindresorhus.com'); }); test('forceHttp option with forceHttps', t => { t.throws(() => { - m('https://www.sindresorhus.com', {forceHttp: true, forceHttps: true}); + normalizeUrl('https://www.sindresorhus.com', {forceHttp: true, forceHttps: true}); }, 'The `forceHttp` and `forceHttps` options cannot be used together'); }); test('forceHttps option', t => { - const opts = {forceHttps: true}; - - t.is(m('https://sindresorhus.com'), 'https://sindresorhus.com'); - t.is(m('http://sindresorhus.com', opts), 'https://sindresorhus.com'); - t.is(m('https://www.sindresorhus.com', opts), 'https://sindresorhus.com'); - t.is(m('//sindresorhus.com', opts), 'https://sindresorhus.com'); + const options = {forceHttps: true}; + t.is(normalizeUrl('https://sindresorhus.com'), 'https://sindresorhus.com'); + t.is(normalizeUrl('http://sindresorhus.com', options), 'https://sindresorhus.com'); + t.is(normalizeUrl('https://www.sindresorhus.com', options), 'https://sindresorhus.com'); + t.is(normalizeUrl('//sindresorhus.com', options), 'https://sindresorhus.com'); }); test('removeTrailingSlash option', t => { - const opts = {removeTrailingSlash: false}; - t.is(m('http://sindresorhus.com/'), 'http://sindresorhus.com'); - t.is(m('http://sindresorhus.com/', opts), 'http://sindresorhus.com'); - t.is(m('http://sindresorhus.com/redirect/'), 'http://sindresorhus.com/redirect'); - t.is(m('http://sindresorhus.com/redirect/', opts), 'http://sindresorhus.com/redirect/'); + const options = {removeTrailingSlash: false}; + t.is(normalizeUrl('http://sindresorhus.com/'), 'http://sindresorhus.com'); + t.is(normalizeUrl('http://sindresorhus.com/', options), 'http://sindresorhus.com'); + t.is(normalizeUrl('http://sindresorhus.com/redirect/'), 'http://sindresorhus.com/redirect'); + t.is(normalizeUrl('http://sindresorhus.com/redirect/', options), 'http://sindresorhus.com/redirect/'); }); test('removeDirectoryIndex option', t => { - const opts1 = {removeDirectoryIndex: ['index.html', 'index.php']}; - t.is(m('http://sindresorhus.com/index.html'), 'http://sindresorhus.com/index.html'); - t.is(m('http://sindresorhus.com/index.html', opts1), 'http://sindresorhus.com'); - t.is(m('http://sindresorhus.com/index.htm', opts1), 'http://sindresorhus.com/index.htm'); - t.is(m('http://sindresorhus.com/index.php', opts1), 'http://sindresorhus.com'); - t.is(m('http://sindresorhus.com/path/index.html'), 'http://sindresorhus.com/path/index.html'); - t.is(m('http://sindresorhus.com/path/index.html', opts1), 'http://sindresorhus.com/path'); - t.is(m('http://sindresorhus.com/path/index.htm', opts1), 'http://sindresorhus.com/path/index.htm'); - t.is(m('http://sindresorhus.com/path/index.php', opts1), 'http://sindresorhus.com/path'); - t.is(m('http://sindresorhus.com/foo/bar/index.html', opts1), 'http://sindresorhus.com/foo/bar'); - - const opts2 = {removeDirectoryIndex: [/^index\.[a-z]+$/, 'remove.html']}; - t.is(m('http://sindresorhus.com/index.html'), 'http://sindresorhus.com/index.html'); - t.is(m('http://sindresorhus.com/index.html', opts2), 'http://sindresorhus.com'); - t.is(m('http://sindresorhus.com/index/index.html', opts2), 'http://sindresorhus.com/index'); - t.is(m('http://sindresorhus.com/remove.html', opts2), 'http://sindresorhus.com'); - t.is(m('http://sindresorhus.com/default.htm', opts2), 'http://sindresorhus.com/default.htm'); - t.is(m('http://sindresorhus.com/index.php', opts2), 'http://sindresorhus.com'); - - const opts3 = {removeDirectoryIndex: true}; - t.is(m('http://sindresorhus.com/index.html'), 'http://sindresorhus.com/index.html'); - t.is(m('http://sindresorhus.com/index.html', opts3), 'http://sindresorhus.com'); - t.is(m('http://sindresorhus.com/index.htm', opts3), 'http://sindresorhus.com'); - t.is(m('http://sindresorhus.com/index.php', opts3), 'http://sindresorhus.com'); + const options1 = {removeDirectoryIndex: ['index.html', 'index.php']}; + t.is(normalizeUrl('http://sindresorhus.com/index.html'), 'http://sindresorhus.com/index.html'); + t.is(normalizeUrl('http://sindresorhus.com/index.html', options1), 'http://sindresorhus.com'); + t.is(normalizeUrl('http://sindresorhus.com/index.htm', options1), 'http://sindresorhus.com/index.htm'); + t.is(normalizeUrl('http://sindresorhus.com/index.php', options1), 'http://sindresorhus.com'); + t.is(normalizeUrl('http://sindresorhus.com/path/index.html'), 'http://sindresorhus.com/path/index.html'); + t.is(normalizeUrl('http://sindresorhus.com/path/index.html', options1), 'http://sindresorhus.com/path'); + t.is(normalizeUrl('http://sindresorhus.com/path/index.htm', options1), 'http://sindresorhus.com/path/index.htm'); + t.is(normalizeUrl('http://sindresorhus.com/path/index.php', options1), 'http://sindresorhus.com/path'); + t.is(normalizeUrl('http://sindresorhus.com/foo/bar/index.html', options1), 'http://sindresorhus.com/foo/bar'); + + const options2 = {removeDirectoryIndex: [/^index\.[a-z]+$/, 'remove.html']}; + t.is(normalizeUrl('http://sindresorhus.com/index.html'), 'http://sindresorhus.com/index.html'); + t.is(normalizeUrl('http://sindresorhus.com/index.html', options2), 'http://sindresorhus.com'); + t.is(normalizeUrl('http://sindresorhus.com/index/index.html', options2), 'http://sindresorhus.com/index'); + t.is(normalizeUrl('http://sindresorhus.com/remove.html', options2), 'http://sindresorhus.com'); + t.is(normalizeUrl('http://sindresorhus.com/default.htm', options2), 'http://sindresorhus.com/default.htm'); + t.is(normalizeUrl('http://sindresorhus.com/index.php', options2), 'http://sindresorhus.com'); + + const options3 = {removeDirectoryIndex: true}; + t.is(normalizeUrl('http://sindresorhus.com/index.html'), 'http://sindresorhus.com/index.html'); + t.is(normalizeUrl('http://sindresorhus.com/index.html', options3), 'http://sindresorhus.com'); + t.is(normalizeUrl('http://sindresorhus.com/index.htm', options3), 'http://sindresorhus.com'); + t.is(normalizeUrl('http://sindresorhus.com/index.php', options3), 'http://sindresorhus.com'); }); test('removeTrailingSlash and removeDirectoryIndex options)', t => { - const opts1 = { + const options1 = { removeTrailingSlash: true, removeDirectoryIndex: true }; - t.is(m('http://sindresorhus.com/path/', opts1), 'http://sindresorhus.com/path'); - t.is(m('http://sindresorhus.com/path/index.html', opts1), 'http://sindresorhus.com/path'); + t.is(normalizeUrl('http://sindresorhus.com/path/', options1), 'http://sindresorhus.com/path'); + t.is(normalizeUrl('http://sindresorhus.com/path/index.html', options1), 'http://sindresorhus.com/path'); - const opts2 = { + const options2 = { removeTrailingSlash: false, removeDirectoryIndex: true }; - t.is(m('http://sindresorhus.com/path/', opts2), 'http://sindresorhus.com/path/'); - t.is(m('http://sindresorhus.com/path/index.html', opts2), 'http://sindresorhus.com/path/'); + t.is(normalizeUrl('http://sindresorhus.com/path/', options2), 'http://sindresorhus.com/path/'); + t.is(normalizeUrl('http://sindresorhus.com/path/index.html', options2), 'http://sindresorhus.com/path/'); }); test('sortQueryParameters option', t => { - let opts = { + const options1 = { sortQueryParameters: true }; - t.is(m('http://sindresorhus.com/?a=Z&b=Y&c=X&d=W', opts), 'http://sindresorhus.com/?a=Z&b=Y&c=X&d=W'); - t.is(m('http://sindresorhus.com/?b=Y&c=X&a=Z&d=W', opts), 'http://sindresorhus.com/?a=Z&b=Y&c=X&d=W'); - t.is(m('http://sindresorhus.com/?a=Z&d=W&b=Y&c=X', opts), 'http://sindresorhus.com/?a=Z&b=Y&c=X&d=W'); - t.is(m('http://sindresorhus.com/', opts), 'http://sindresorhus.com'); + t.is(normalizeUrl('http://sindresorhus.com/?a=Z&b=Y&c=X&d=W', options1), 'http://sindresorhus.com/?a=Z&b=Y&c=X&d=W'); + t.is(normalizeUrl('http://sindresorhus.com/?b=Y&c=X&a=Z&d=W', options1), 'http://sindresorhus.com/?a=Z&b=Y&c=X&d=W'); + t.is(normalizeUrl('http://sindresorhus.com/?a=Z&d=W&b=Y&c=X', options1), 'http://sindresorhus.com/?a=Z&b=Y&c=X&d=W'); + t.is(normalizeUrl('http://sindresorhus.com/', options1), 'http://sindresorhus.com'); - opts = { + const options2 = { sortQueryParameters: false }; - - t.is(m('http://sindresorhus.com/?a=Z&b=Y&c=X&d=W', opts), 'http://sindresorhus.com/?a=Z&b=Y&c=X&d=W'); - t.is(m('http://sindresorhus.com/?b=Y&c=X&a=Z&d=W', opts), 'http://sindresorhus.com/?b=Y&c=X&a=Z&d=W'); - t.is(m('http://sindresorhus.com/?a=Z&d=W&b=Y&c=X', opts), 'http://sindresorhus.com/?a=Z&d=W&b=Y&c=X'); - t.is(m('http://sindresorhus.com/', opts), 'http://sindresorhus.com'); + t.is(normalizeUrl('http://sindresorhus.com/?a=Z&b=Y&c=X&d=W', options2), 'http://sindresorhus.com/?a=Z&b=Y&c=X&d=W'); + t.is(normalizeUrl('http://sindresorhus.com/?b=Y&c=X&a=Z&d=W', options2), 'http://sindresorhus.com/?b=Y&c=X&a=Z&d=W'); + t.is(normalizeUrl('http://sindresorhus.com/?a=Z&d=W&b=Y&c=X', options2), 'http://sindresorhus.com/?a=Z&d=W&b=Y&c=X'); + t.is(normalizeUrl('http://sindresorhus.com/', options2), 'http://sindresorhus.com'); }); test('invalid urls', t => { t.throws(() => { - m('http://'); + normalizeUrl('http://'); }, 'Invalid URL: http://'); t.throws(() => { - m('/'); + normalizeUrl('/'); }, 'Invalid URL: /'); t.throws(() => { - m('/relative/path/'); + normalizeUrl('/relative/path/'); }, 'Invalid URL: /relative/path/'); });