From be04d7042d6fd531b61e2fd7d53a1cd14509e390 Mon Sep 17 00:00:00 2001 From: silverwind Date: Mon, 28 Sep 2020 19:38:15 +0200 Subject: [PATCH] Add `keepSingleSlash` option Decided it's better to have a separate option than to overload a boolean type with non-boolean values. Fixes: https://github.com/sindresorhus/normalize-url/issues/119 --- index.d.ts | 16 ++++++++++++++++ index.js | 5 +++-- readme.md | 18 +++++++++++++++++- test.js | 18 ++++++++++++++++++ 4 files changed, 54 insertions(+), 3 deletions(-) diff --git a/index.d.ts b/index.d.ts index 2b73768..49bbd2e 100644 --- a/index.d.ts +++ b/index.d.ts @@ -155,6 +155,22 @@ declare namespace normalizeUrl { */ readonly removeTrailingSlash?: boolean; + /** + Remove a sole `/` pathname in the output. This option is independant of `removeTrailingSlash`. + + @default false + + @example + ``` + normalizeUrl('http://sindresorhus.com/'); + //=> 'http://sindresorhus.com' + + normalizeUrl('http://sindresorhus.com/', {removeSingleSlash: false}); + //=> 'http://sindresorhus.com/' + ``` + */ + readonly removeSingleSlash?: 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. diff --git a/index.js b/index.js index e615cf8..8d4f989 100644 --- a/index.js +++ b/index.js @@ -70,6 +70,7 @@ const normalizeUrl = (urlString, options) => { stripWWW: true, removeQueryParameters: [/^utm_\w+/i], removeTrailingSlash: true, + removeSingleSlash: true, removeDirectoryIndex: false, sortQueryParameters: true, ...options @@ -177,8 +178,8 @@ const normalizeUrl = (urlString, options) => { // Take advantage of many of the Node `url` normalizations urlString = urlObj.toString(); - // Remove ending `/` - if ((options.removeTrailingSlash || urlObj.pathname === '/') && urlObj.hash === '') { + // Remove ending `/` unless removeSingleSlash is false + if ((options.removeTrailingSlash || urlObj.pathname === '/') && urlObj.hash === '' && options.removeSingleSlash) { urlString = urlString.replace(/\/$/, ''); } diff --git a/readme.md b/readme.md index d09d3f6..21733cc 100644 --- a/readme.md +++ b/readme.md @@ -171,7 +171,7 @@ Default: `true` Remove trailing slash. -**Note:** Trailing slash is always removed if the URL doesn't have a pathname. +**Note:** Trailing slash is always removed if the URL doesn't have a pathname unless the `removeSingleSlash` option is set to `false`. ```js normalizeUrl('http://sindresorhus.com/redirect/'); @@ -184,6 +184,22 @@ normalizeUrl('http://sindresorhus.com/', {removeTrailingSlash: false}); //=> 'http://sindresorhus.com' ``` +##### removeSingleSlash + +Type: `boolean`\ +Default: `true` + +Remove a sole `/` pathname in the output. This option is independant of `removeTrailingSlash`. + +```js +normalizeUrl('http://sindresorhus.com/'); +//=> 'http://sindresorhus.com' + +normalizeUrl('http://sindresorhus.com/', {removeSingleSlash: false}); +//=> 'http://sindresorhus.com/' +``` + + ##### removeDirectoryIndex Type: `boolean | Array`\ diff --git a/test.js b/test.js index fc5b5c2..c2479b9 100644 --- a/test.js +++ b/test.js @@ -124,6 +124,24 @@ test('removeTrailingSlash option', t => { t.is(normalizeUrl('http://sindresorhus.com/redirect/'), 'http://sindresorhus.com/redirect'); t.is(normalizeUrl('http://sindresorhus.com/redirect/', options), 'http://sindresorhus.com/redirect/'); t.is(normalizeUrl('http://sindresorhus.com/#/', options), 'http://sindresorhus.com/#/'); + t.is(normalizeUrl('http://sindresorhus.com/?unicorns=true'), 'http://sindresorhus.com/?unicorns=true'); + t.is(normalizeUrl('http://sindresorhus.com/?unicorns=true', options), 'http://sindresorhus.com/?unicorns=true'); +}); + +test('removeSingleSlash option', t => { + const options = {removeSingleSlash: false}; + t.is(normalizeUrl('http://sindresorhus.com/', options), 'http://sindresorhus.com/'); + t.is(normalizeUrl('http://sindresorhus.com/redirect/', options), 'http://sindresorhus.com/redirect'); + t.is(normalizeUrl('http://sindresorhus.com/#/', options), 'http://sindresorhus.com/#/'); + t.is(normalizeUrl('http://sindresorhus.com/?unicorns=true', options), 'http://sindresorhus.com/?unicorns=true'); +}); + +test('removeSingleSlash option combined with removeTrailingSlash option', t => { + const options = {removeTrailingSlash: true, removeSingleSlash: false}; + t.is(normalizeUrl('http://sindresorhus.com/', options), 'http://sindresorhus.com/'); + t.is(normalizeUrl('http://sindresorhus.com/redirect/', options), 'http://sindresorhus.com/redirect'); + t.is(normalizeUrl('http://sindresorhus.com/#/', options), 'http://sindresorhus.com/#/'); + t.is(normalizeUrl('http://sindresorhus.com/?unicorns=true', options), 'http://sindresorhus.com/?unicorns=true'); }); test('removeDirectoryIndex option', t => {