diff --git a/packages/url/CHANGELOG.md b/packages/url/CHANGELOG.md index e0f2f033c4af94..0b1dfb761ff72b 100644 --- a/packages/url/CHANGELOG.md +++ b/packages/url/CHANGELOG.md @@ -1,3 +1,11 @@ +## 2.2.0 (Unreleased) + +### Features + +- Added `getQueryArg`. +- Added `hasQueryArg`. +- Added `removeQueryArgs`. + ## 2.1.0 (2018-10-16) ### Features diff --git a/packages/url/README.md b/packages/url/README.md index 6c156612327551..26f54fbaff57f7 100644 --- a/packages/url/README.md +++ b/packages/url/README.md @@ -25,6 +25,15 @@ const newURL = addQueryArgs( 'https://google.com', { q: 'test' } ); // https:// // Prepends 'http://' to URLs that are probably mean to have them const actualURL = prependHTTP( 'wordpress.org' ); // http://wordpress.org + +// Gets a single query arg from the given URL. +const foo = getQueryArg( 'https://wordpress.org?foo=bar&bar=baz', 'foo' ); // bar + +// Checks whether a URL contains a given query arg. +const hasBar = hasQueryArg( 'https://wordpress.org?foo=bar&bar=baz', 'bar' ); // true + +// Removes one or more query args from the given URL. +const newUrl = removeQueryArgs( 'https://wordpress.org?foo=bar&bar=baz&baz=foobar', 'foo', 'bar' ); // https://wordpress.org?baz=foobar ```

Code is Poetry.

diff --git a/packages/url/src/index.js b/packages/url/src/index.js index 4538ee2040bbc6..98cd123cfc666d 100644 --- a/packages/url/src/index.js +++ b/packages/url/src/index.js @@ -21,10 +21,10 @@ export function isURL( url ) { /** * Appends arguments to the query string of the url * - * @param {string} url URL - * @param {Object} args Query Args + * @param {string} url URL + * @param {Object} args Query Args * - * @return {string} Updated URL + * @return {string} Updated URL */ export function addQueryArgs( url, args ) { const queryStringIndex = url.indexOf( '?' ); @@ -34,6 +34,51 @@ export function addQueryArgs( url, args ) { return baseUrl + '?' + stringify( { ...query, ...args } ); } +/** + * Returns a single query argument of the url + * + * @param {string} url URL + * @param {string} arg Query arg name + * + * @return {Array|string} Query arg value. + */ +export function getQueryArg( url, arg ) { + const queryStringIndex = url.indexOf( '?' ); + const query = queryStringIndex !== -1 ? parse( url.substr( queryStringIndex + 1 ) ) : {}; + + return query[ arg ]; +} + +/** + * Determines whether the URL contains a given query arg. + * + * @param {string} url URL + * @param {string} arg Query arg name + * + * @return {boolean} Whether or not the URL contains the query aeg. + */ +export function hasQueryArg( url, arg ) { + return getQueryArg( url, arg ) !== undefined; +} + +/** + * Removes arguments from the query string of the url + * + * @param {string} url URL + * @param {...string} args Query Args + * + * @return {string} Updated URL + */ +export function removeQueryArgs( url, ...args ) { + const queryStringIndex = url.indexOf( '?' ); + const query = queryStringIndex !== -1 ? parse( url.substr( queryStringIndex + 1 ) ) : {}; + const baseUrl = queryStringIndex !== -1 ? url.substr( 0, queryStringIndex ) : url; + + args.forEach( ( arg ) => delete query[ arg ] ); + + return baseUrl + '?' + stringify( query ); +} + /** * Prepends "http://" to a url, if it looks like something that is meant to be a TLD. * diff --git a/packages/url/src/test/index.test.js b/packages/url/src/test/index.test.js index 7815a1cae68ed6..46548528f3bc10 100644 --- a/packages/url/src/test/index.test.js +++ b/packages/url/src/test/index.test.js @@ -9,6 +9,9 @@ import { every } from 'lodash'; import { isURL, addQueryArgs, + getQueryArg, + hasQueryArg, + removeQueryArgs, prependHTTP, safeDecodeURI, } from '../'; @@ -69,6 +72,66 @@ describe( 'addQueryArgs', () => { } ); } ); +describe( 'getQueryArg', () => { + it( 'should get the value of an existing query arg', () => { + const url = 'https://andalouses.example/beach?foo=bar&bar=baz'; + + expect( getQueryArg( url, 'foo' ) ).toBe( 'bar' ); + } ); + + it( 'should not return a value of an unknown query arg', () => { + const url = 'https://andalouses.example/beach?foo=bar&bar=baz'; + + expect( getQueryArg( url, 'baz' ) ).toBeUndefined(); + } ); + + it( 'should get the value of an arry query arg', () => { + const url = 'https://andalouses.example/beach?foo[]=bar&foo[]=baz'; + + expect( getQueryArg( url, 'foo' ) ).toEqual( [ 'bar', 'baz' ] ); + } ); +} ); + +describe( 'hasQueryArg', () => { + it( 'should return true for an existing query arg', () => { + const url = 'https://andalouses.example/beach?foo=bar&bar=baz'; + + expect( hasQueryArg( url, 'foo' ) ).toBeTruthy(); + } ); + + it( 'should return false for an unknown query arg', () => { + const url = 'https://andalouses.example/beach?foo=bar&bar=baz'; + + expect( hasQueryArg( url, 'baz' ) ).toBeFalsy(); + } ); + + it( 'should return true for an arry query arg', () => { + const url = 'https://andalouses.example/beach?foo[]=bar&foo[]=baz'; + + expect( hasQueryArg( url, 'foo' ) ).toBeTruthy(); + } ); +} ); + +describe( 'removeQueryArgs', () => { + it( 'should not change URL not containing query args', () => { + const url = 'https://andalouses.example/beach?foo=bar&bar=baz'; + + expect( removeQueryArgs( url, 'baz', 'test' ) ).toEqual( url ); + } ); + + it( 'should remove existing query args', () => { + const url = 'https://andalouses.example/beach?foo=bar&baz=foo&bar=baz'; + + expect( removeQueryArgs( url, 'foo', 'bar' ) ).toEqual( 'https://andalouses.example/beach?baz=foo' ); + } ); + + it( 'should remove array query arg', () => { + const url = 'https://andalouses.example/beach?foo[]=bar&foo[]=baz&bar=foobar'; + + expect( removeQueryArgs( url, 'foo' ) ).toEqual( 'https://andalouses.example/beach?bar=foobar' ); + } ); +} ); + describe( 'prependHTTP', () => { it( 'should prepend http to a domain', () => { const url = 'wordpress.org';