diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 0000000..349e87e --- /dev/null +++ b/index.d.ts @@ -0,0 +1,183 @@ +export interface Options { + /** + * @default 'http:' + */ + defaultProtocol?: string; + + /** + * Prepends `defaultProtocol` to the URL if it's protocol-relative. + * + * @default true + * + * @example + * + * normalizeUrl('//sindresorhus.com:80/'); + * //=> 'http://sindresorhus.com' + * + * normalizeUrl('//sindresorhus.com:80/', {normalizeProtocol: false}); + * //=> '//sindresorhus.com' + */ + normalizeProtocol?: boolean; + + /** + * Normalizes `https:` URLs to `http:`. + * + * @default false + * + * @example + * + * normalizeUrl('https://sindresorhus.com:80/'); + * //=> 'https://sindresorhus.com' + * + * normalizeUrl('https://sindresorhus.com:80/', {forceHttp: true}); + * //=> 'http://sindresorhus.com' + */ + forceHttp?: boolean; + + /** + * Normalizes `http:` URLs to `https:`. + * + * This option can't be used with the `forceHttp` option at the same time. + * + * @default false + * + * @example + * + * normalizeUrl('https://sindresorhus.com:80/'); + * //=> 'https://sindresorhus.com' + * + * normalizeUrl('http://sindresorhus.com:80/', {forceHttps: true}); + * //=> 'https://sindresorhus.com' + */ + forceHttps?: boolean; + + /** + * Strip the [authentication](https://en.wikipedia.org/wiki/Basic_access_authentication) part of a URL. + * + * @default true + * + * @example + * + * normalizeUrl('user:password@sindresorhus.com'); + * //=> 'https://sindresorhus.com' + * + * normalizeUrl('user:password@sindresorhus.com', {stripAuthentication: false}); + * //=> 'https://user:password@sindresorhus.com' + */ + stripAuthentication?: boolean; + + /** + * Removes hash from the URL. + * + * @default false + * + * @example + * + * 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' + */ + stripHash?: boolean; + + /** + * Removes HTTP(S) protocol from an URL `http://sindresorhus.com` → `sindresorhus.com`. + * + * @default false + * + * @example + * + * normalizeUrl('https://sindresorhus.com'); + * //=> 'https://sindresorhus.com' + * + * normalizeUrl('sindresorhus.com', {stripProtocol: true}); + * //=> 'sindresorhus.com' + */ + stripProtocol?: boolean; + + /** + * Removes `www.` from the URL. + * + * @default true + * + * @example + * + * normalizeUrl('http://www.sindresorhus.com'); + * //=> 'http://sindresorhus.com' + * + * normalizeUrl('http://www.sindresorhus.com', {stripWWW: false}); + * //=> 'http://www.sindresorhus.com' + */ + stripWWW?: boolean; + + /** + * Removes query parameters that matches any of the provided strings or regexes. + * + * @default [/^utm_\w+/i] + * + * @example + * + * normalizeUrl('www.sindresorhus.com?foo=bar&ref=test_ref', { + * removeQueryParameters: ['ref'] + * }); + * //=> 'http://sindresorhus.com/?foo=bar' + */ + removeQueryParameters?: (RegExp | string)[]; + + /** + * Removes trailing slash. + * + * **Note**: Trailing slash is always removed if the URL doesn't have a pathname. + * + * @default true + * + * @example + * + * normalizeUrl('http://sindresorhus.com/redirect/'); + * //=> 'http://sindresorhus.com/redirect' + * + * normalizeUrl('http://sindresorhus.com/redirect/', {removeTrailingSlash: false}); + * //=> 'http://sindresorhus.com/redirect/' + * + * normalizeUrl('http://sindresorhus.com/', {removeTrailingSlash: false}); + * //=> 'http://sindresorhus.com' + */ + removeTrailingSlash?: boolean; + + /** + * Removes the default directory index file from path that matches any of the provided strings or regexes. + * When `true`, the regex `/^index\.[a-z]+$/` is used. + * + * @default false + * + * @example + * + * normalizeUrl('www.sindresorhus.com/foo/default.php', { + * removeDirectoryIndex: [/^default\.[a-z]+$/] + * }); + * //=> 'http://sindresorhus.com/foo' + */ + removeDirectoryIndex?: (RegExp | string)[]; + + /** + * Sorts the query parameters alphabetically by key. + * + * @default true + * + * @example + * + * normalizeUrl('www.sindresorhus.com?b=two&a=one&c=three', { + * sortQueryParameters: false + * }); + * //=> 'http://sindresorhus.com/?b=two&a=one&c=three' + */ + sortQueryParameters?: boolean; +} + +/** + * [Normalize](https://en.wikipedia.org/wiki/URL_normalization) a URL. + * + * @param url - URL to normalize. + */ +export default function normalizeUrl(url: string, options?: Options): string; diff --git a/index.js b/index.js index f0c868b..d11ffb3 100644 --- a/index.js +++ b/index.js @@ -6,7 +6,7 @@ const testParameter = (name, filters) => { return filters.some(filter => filter instanceof RegExp ? filter.test(name) : filter === name); }; -module.exports = (urlString, options) => { +const normalizeUrl = (urlString, options) => { options = { defaultProtocol: 'http:', normalizeProtocol: true, @@ -78,6 +78,7 @@ module.exports = (urlString, options) => { if (/^(?!\/)/g.test(p1)) { return `${p1}/`; } + return '/'; }); } @@ -153,3 +154,6 @@ module.exports = (urlString, options) => { return urlString; }; + +module.exports = normalizeUrl; +module.exports.default = normalizeUrl; diff --git a/index.test-d.ts b/index.test-d.ts new file mode 100644 index 0000000..dad80be --- /dev/null +++ b/index.test-d.ts @@ -0,0 +1,24 @@ +import {expectType} from 'tsd-check'; +import normalizeUrl from '.'; + +expectType(normalizeUrl('sindresorhus.com')); +expectType(normalizeUrl('HTTP://xn--xample-hva.com:80/?b=bar&a=foo')); + +normalizeUrl('//sindresorhus.com:80/', {defaultProtocol: 'https:'}); +normalizeUrl('//sindresorhus.com:80/', {normalizeProtocol: false}); +normalizeUrl('https://sindresorhus.com:80/', {forceHttp: true}); +normalizeUrl('http://sindresorhus.com:80/', {forceHttps: true}); +normalizeUrl('user:password@sindresorhus.com', {stripAuthentication: false}); +normalizeUrl('sindresorhus.com/about.html#contact', {stripHash: true}); +normalizeUrl('https://sindresorhus.com', {stripProtocol: true}); +normalizeUrl('http://www.sindresorhus.com', {stripWWW: false}); +normalizeUrl('www.sindresorhus.com?foo=bar&ref=test_ref', { + removeQueryParameters: ['ref', /test/] +}); +normalizeUrl('http://sindresorhus.com/', {removeTrailingSlash: false}); +normalizeUrl('www.sindresorhus.com/foo/default.php', { + removeDirectoryIndex: [/^default\.[a-z]+$/, 'foo'] +}); +normalizeUrl('www.sindresorhus.com?b=two&a=one&c=three', { + sortQueryParameters: false +}); diff --git a/package.json b/package.json index c952f02..1770c77 100644 --- a/package.json +++ b/package.json @@ -13,10 +13,11 @@ "node": ">=8" }, "scripts": { - "test": "xo && nyc ava" + "test": "xo && nyc ava && tsd-check" }, "files": [ - "index.js" + "index.js", + "index.d.ts" ], "keywords": [ "normalize", @@ -34,9 +35,10 @@ "canonical" ], "devDependencies": { - "ava": "^0.25.0", + "ava": "^1.2.1", "coveralls": "^3.0.0", "nyc": "^13.1.0", - "xo": "^0.23.0" + "tsd-check": "^0.3.0", + "xo": "^0.24.0" } }