From 2bceedc0cafd83201fb3483db4ec017c7ef87ced Mon Sep 17 00:00:00 2001 From: M4rk9696 Date: Sun, 17 Nov 2019 02:23:16 +0530 Subject: [PATCH 01/24] Add support for fragment identifier --- index.d.ts | 16 ++++++++++++++++ index.js | 12 ++++++++---- index.test-d.ts | 3 +++ test/parse-url.js | 6 ++++++ 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/index.d.ts b/index.d.ts index d5012b44..f1c58c41 100644 --- a/index.d.ts +++ b/index.d.ts @@ -121,6 +121,21 @@ export interface ParseOptions { ``` */ readonly parseBooleans?: boolean; + + /** + Parse the fragment identifier from the URL. + + @default false + + @example + ``` + import queryString = require('query-string'); + + queryString.parseUrl('https://foo.bar?foo=bar#xyz'); + //=> {url: 'https://foo.bar', query: {foo: 'bar'}, fragment: 'xyz'} + ``` + */ + readonly parseFragment?: boolean; } export interface ParsedQuery { @@ -142,6 +157,7 @@ export function parse(query: string, options?: ParseOptions): ParsedQuery; export interface ParsedUrl { readonly url: string; readonly query: ParsedQuery; + readonly fragment?: string; } /** diff --git a/index.js b/index.js index 0b57b3ec..3f2f3138 100644 --- a/index.js +++ b/index.js @@ -338,10 +338,14 @@ exports.stringify = (object, options) => { }; exports.parseUrl = (input, options) => { - return { - url: removeHash(input).split('?')[0] || '', - query: parse(extract(input), options) - }; + const [url, hash] = splitOnFirst(input, '#'); + return Object.assign( + { + url: url.split('?')[0] || '', + query: parse(extract(input), options) + }, + options && options.parseFragment && hash ? {fragment: hash} : {} + ); }; exports.stringifyUrl = (input, options) => { diff --git a/index.test-d.ts b/index.test-d.ts index 19a6817c..e4488961 100644 --- a/index.test-d.ts +++ b/index.test-d.ts @@ -87,6 +87,9 @@ expectType( expectType( queryString.parseUrl('?foo=true', {parseBooleans: true}) ); +expectType( + queryString.parseUrl('?foo=true#bar', {parseFragment: true}) +); // Extract expectType(queryString.extract('http://foo.bar/?abc=def&hij=klm')); diff --git a/test/parse-url.js b/test/parse-url.js index a85e88e9..f172e57a 100644 --- a/test/parse-url.js +++ b/test/parse-url.js @@ -18,6 +18,12 @@ test('handles strings with query string that contain =', t => { t.deepEqual(queryString.parseUrl('https://foo.bar?foo=bar=&foo=baz='), {url: 'https://foo.bar', query: {foo: ['bar=', 'baz=']}}); }); +test('handles strings with fragment identifier', t => { + t.deepEqual(queryString.parseUrl('https://foo.bar?top=foo#bar', {parseFragment: true}), {url: 'https://foo.bar', query: {top: 'foo'}, fragment: 'bar'}); + t.deepEqual(queryString.parseUrl('https://foo.bar?foo=bar&foo=baz#top', {parseFragment: true}), {url: 'https://foo.bar', query: {foo: ['bar', 'baz']}, fragment: 'top'}); + t.deepEqual(queryString.parseUrl('https://foo.bar/#top', {parseFragment: true}), {url: 'https://foo.bar/', query: {}, fragment: 'top'}); +}); + test('throws for invalid values', t => { t.throws(() => { queryString.parseUrl(null); From eee9da2f4d85bd05c45485c4310e8808ae9e6152 Mon Sep 17 00:00:00 2001 From: M4rk9696 Date: Sun, 1 Dec 2019 22:52:05 +0530 Subject: [PATCH 02/24] Rename fragment to fragmentIdentifier --- index.d.ts | 8 ++++---- index.js | 2 +- index.test-d.ts | 2 +- test/parse-url.js | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/index.d.ts b/index.d.ts index f1c58c41..0ae21ebc 100644 --- a/index.d.ts +++ b/index.d.ts @@ -131,11 +131,11 @@ export interface ParseOptions { ``` import queryString = require('query-string'); - queryString.parseUrl('https://foo.bar?foo=bar#xyz'); - //=> {url: 'https://foo.bar', query: {foo: 'bar'}, fragment: 'xyz'} + queryString.parseUrl('https://foo.bar?foo=bar#xyz', {parseFragmentIdentifier: true}); + //=> {url: 'https://foo.bar', query: {foo: 'bar'}, fragmentIdentifier: 'xyz'} ``` */ - readonly parseFragment?: boolean; + readonly parseFragmentIdentifier?: boolean; } export interface ParsedQuery { @@ -157,7 +157,7 @@ export function parse(query: string, options?: ParseOptions): ParsedQuery; export interface ParsedUrl { readonly url: string; readonly query: ParsedQuery; - readonly fragment?: string; + readonly fragmentIdentifier?: string; } /** diff --git a/index.js b/index.js index 3f2f3138..956c18b4 100644 --- a/index.js +++ b/index.js @@ -344,7 +344,7 @@ exports.parseUrl = (input, options) => { url: url.split('?')[0] || '', query: parse(extract(input), options) }, - options && options.parseFragment && hash ? {fragment: hash} : {} + options && options.parseFragmentIdentifier && hash ? {fragmentIdentifier: hash} : {} ); }; diff --git a/index.test-d.ts b/index.test-d.ts index e4488961..a7563e8a 100644 --- a/index.test-d.ts +++ b/index.test-d.ts @@ -88,7 +88,7 @@ expectType( queryString.parseUrl('?foo=true', {parseBooleans: true}) ); expectType( - queryString.parseUrl('?foo=true#bar', {parseFragment: true}) + queryString.parseUrl('?foo=true#bar', {parseFragmentIdentifier: true}) ); // Extract diff --git a/test/parse-url.js b/test/parse-url.js index f172e57a..bb48b570 100644 --- a/test/parse-url.js +++ b/test/parse-url.js @@ -19,9 +19,9 @@ test('handles strings with query string that contain =', t => { }); test('handles strings with fragment identifier', t => { - t.deepEqual(queryString.parseUrl('https://foo.bar?top=foo#bar', {parseFragment: true}), {url: 'https://foo.bar', query: {top: 'foo'}, fragment: 'bar'}); - t.deepEqual(queryString.parseUrl('https://foo.bar?foo=bar&foo=baz#top', {parseFragment: true}), {url: 'https://foo.bar', query: {foo: ['bar', 'baz']}, fragment: 'top'}); - t.deepEqual(queryString.parseUrl('https://foo.bar/#top', {parseFragment: true}), {url: 'https://foo.bar/', query: {}, fragment: 'top'}); + t.deepEqual(queryString.parseUrl('https://foo.bar?top=foo#bar', {parseFragmentIdentifier: true}), {url: 'https://foo.bar', query: {top: 'foo'}, fragmentIdentifier: 'bar'}); + t.deepEqual(queryString.parseUrl('https://foo.bar?foo=bar&foo=baz#top', {parseFragmentIdentifier: true}), {url: 'https://foo.bar', query: {foo: ['bar', 'baz']}, fragmentIdentifier: 'top'}); + t.deepEqual(queryString.parseUrl('https://foo.bar/#top', {parseFragmentIdentifier: true}), {url: 'https://foo.bar/', query: {}, fragmentIdentifier: 'top'}); }); test('throws for invalid values', t => { From 1b788b24d9eca76eb50d63daab06e6231cbf7cd9 Mon Sep 17 00:00:00 2001 From: M4rk9696 Date: Sun, 1 Dec 2019 22:52:23 +0530 Subject: [PATCH 03/24] Update readme on fragmentIdentifier --- readme.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/readme.md b/readme.md index 75a1d3f8..b832c2cc 100644 --- a/readme.md +++ b/readme.md @@ -383,6 +383,19 @@ The URL to stringify. Type: `object` Query items to add to the URL. +#### parseFragmentIdentifier + +Extracts the fragment identifier from url + +Type: `boolean`\ +Default: `false` + +```js +import queryString = require('query-string'); + +queryString.parseUrl('https://foo.bar?foo=bar#xyz', {parseFragmentIdentifier: true}); +//=> {url: 'https://foo.bar', query: {foo: 'bar'}, fragmentIdentifier: 'xyz'} +``` ## Nesting From 13465083561b68d2951dee9eaef83d2534c8d46f Mon Sep 17 00:00:00 2001 From: M4rk9696 Date: Mon, 6 Apr 2020 13:51:27 +0530 Subject: [PATCH 04/24] Add support fer fragment identifier in stringifyUrl --- index.js | 6 +++++- test/stringify-url.js | 8 ++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 956c18b4..aa4918f5 100644 --- a/index.js +++ b/index.js @@ -352,12 +352,16 @@ exports.stringifyUrl = (input, options) => { const url = removeHash(input.url).split('?')[0] || ''; const queryFromUrl = exports.extract(input.url); const parsedQueryFromUrl = exports.parse(queryFromUrl); - const hash = getHash(input.url); + let hash = getHash(input.url); const query = Object.assign(parsedQueryFromUrl, input.query); let queryString = exports.stringify(query, options); if (queryString) { queryString = `?${queryString}`; } + if (options && options.parseFragmentIdentifier && input.fragmentIdentifier) { + hash = `#${input.fragmentIdentifier}`; + } + return `${url}${queryString}${hash}`; }; diff --git a/test/stringify-url.js b/test/stringify-url.js index 933af7a2..05dd7708 100644 --- a/test/stringify-url.js +++ b/test/stringify-url.js @@ -19,6 +19,14 @@ test('stringify URL with a query string', t => { t.deepEqual(queryString.stringifyUrl({url: 'https://foo.bar?foo=baz', query: {foo: 'bar'}}), 'https://foo.bar?foo=bar'); }); +test('stringify URL with fragment identifier', t => { + const config = {parseFragmentIdentifier: true}; + t.deepEqual(queryString.stringifyUrl({url: 'https://foo.bar', query: {top: 'foo'}, fragmentIdentifier: 'bar'}, config), 'https://foo.bar?top=foo#bar'); + t.deepEqual(queryString.stringifyUrl({url: 'https://foo.bar', query: {foo: ['bar', 'baz']}, fragmentIdentifier: 'top'}, config), 'https://foo.bar?foo=bar&foo=baz#top'); + t.deepEqual(queryString.stringifyUrl({url: 'https://foo.bar/', query: {}, fragmentIdentifier: 'top'}, config), 'https://foo.bar/#top'); + t.deepEqual(queryString.stringifyUrl({url: 'https://foo.bar/#abc', query: {}, fragmentIdentifier: 'top'}, config), 'https://foo.bar/#top'); +}); + test('skipEmptyString:: stringify URL with a query string', t => { const config = {skipEmptyString: true}; From 2de7f1c570e63b8a2f34f1f0df466c822069f173 Mon Sep 17 00:00:00 2001 From: M4rk9696 Date: Mon, 6 Apr 2020 13:52:01 +0530 Subject: [PATCH 05/24] Update README, review changes --- readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index b832c2cc..60e37e51 100644 --- a/readme.md +++ b/readme.md @@ -385,13 +385,13 @@ Type: `object` Query items to add to the URL. #### parseFragmentIdentifier -Extracts the fragment identifier from url +Parse the fragment identifier from the URL. Type: `boolean`\ Default: `false` ```js -import queryString = require('query-string'); +const queryString = require('query-string'); queryString.parseUrl('https://foo.bar?foo=bar#xyz', {parseFragmentIdentifier: true}); //=> {url: 'https://foo.bar', query: {foo: 'bar'}, fragmentIdentifier: 'xyz'} From 00be68d7dd09b3a8f5f219ba59740e97db5d86b6 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Mon, 6 Apr 2020 22:25:40 +0800 Subject: [PATCH 06/24] Update readme.md --- readme.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 60e37e51..ac99848b 100644 --- a/readme.md +++ b/readme.md @@ -383,7 +383,8 @@ The URL to stringify. Type: `object` Query items to add to the URL. -#### parseFragmentIdentifier + +##### parseFragmentIdentifier Parse the fragment identifier from the URL. From 05a4385148f53b868174ff8185b75bfbe0cd3a25 Mon Sep 17 00:00:00 2001 From: M4rk9696 Date: Mon, 6 Apr 2020 20:05:30 +0530 Subject: [PATCH 07/24] Update Readme section --- readme.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/readme.md b/readme.md index ac99848b..0ef9173e 100644 --- a/readme.md +++ b/readme.md @@ -350,6 +350,20 @@ queryString.parseUrl('https://foo.bar?foo=bar'); //=> {url: 'https://foo.bar', query: {foo: 'bar'}} ``` +##### parseFragmentIdentifier + +Parse the fragment identifier from the URL. + +Type: `boolean`\ +Default: `false` + +```js +const queryString = require('query-string'); + +queryString.parseUrl('https://foo.bar?foo=bar#xyz', {parseFragmentIdentifier: true}); +//=> {url: 'https://foo.bar', query: {foo: 'bar'}, fragmentIdentifier: 'xyz'} +``` + ### .stringifyUrl(object, options?) Stringify an object into a URL with a query string and sorting the keys. The inverse of [`.parseUrl()`](https://github.com/sindresorhus/query-string#parseurlstring-options) @@ -384,20 +398,6 @@ Type: `object` Query items to add to the URL. -##### parseFragmentIdentifier - -Parse the fragment identifier from the URL. - -Type: `boolean`\ -Default: `false` - -```js -const queryString = require('query-string'); - -queryString.parseUrl('https://foo.bar?foo=bar#xyz', {parseFragmentIdentifier: true}); -//=> {url: 'https://foo.bar', query: {foo: 'bar'}, fragmentIdentifier: 'xyz'} -``` - ## Nesting This module intentionally doesn't support nesting as it's not spec'd and varies between implementations, which causes a lot of [edge cases](https://github.com/visionmedia/node-querystring/issues). From 8813d6a09220d55a5c5376d7303b7567750ac691 Mon Sep 17 00:00:00 2001 From: Mark1626 Date: Mon, 18 May 2020 11:55:43 +0530 Subject: [PATCH 08/24] Update documentation Co-authored-by: Karuppiah --- index.d.ts | 24 ++++++++++++++++++++++++ readme.md | 30 +++++++++++++++++++++++++++--- test/stringify-url.js | 1 + 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/index.d.ts b/index.d.ts index 0ae21ebc..83d7715c 100644 --- a/index.d.ts +++ b/index.d.ts @@ -157,6 +157,9 @@ export function parse(query: string, options?: ParseOptions): ParsedQuery; export interface ParsedUrl { readonly url: string; readonly query: ParsedQuery; + /** + The fragment identifier of the URL. + */ readonly fragmentIdentifier?: string; } @@ -326,6 +329,27 @@ export interface StringifyOptions { ``` */ readonly skipEmptyString?: boolean; + + /** + Adds the fragment identifier to the URL. + + @default false + + @example + ``` + import queryString = require('query-string'); + + queryString.stringifyUrl({ + url: 'https://foo.bar', + query: {top: 'foo'}, + fragmentIdentifier: 'bar' + }, { + parseFragmentIdentifier: true + }); + //=> 'https://foo.bar?top=foo#bar' + ``` + */ + readonly parseFragmentIdentifier?: boolean; } /** diff --git a/readme.md b/readme.md index 0ef9173e..6ca93c52 100644 --- a/readme.md +++ b/readme.md @@ -339,8 +339,6 @@ Note: This behaviour can be changed with the `skipNull` option. Extract the URL and the query string as an object. -The `options` are the same as for `.parse()`. - Returns an object with a `url` and `query` property. ```js @@ -350,6 +348,14 @@ queryString.parseUrl('https://foo.bar?foo=bar'); //=> {url: 'https://foo.bar', query: {foo: 'bar'}} ``` +#### options + +Type: `object` + +The `options` are the same as for `.parse()`. + +Extra options are as below + ##### parseFragmentIdentifier Parse the fragment identifier from the URL. @@ -382,7 +388,7 @@ queryString.stringifyUrl({url: 'https://foo.bar?foo=baz', query: {foo: 'bar'}}); //=> 'https://foo.bar?foo=bar' ``` -#### object +#### options Type: `object` @@ -398,6 +404,24 @@ Type: `object` Query items to add to the URL. +##### parseFragmentIdentifier + +Adds the fragment identifier to the URL. + +Type: `boolean`\ +Default: `false` + +```js +queryString.stringifyUrl({ + url: 'https://foo.bar', + query: {top: 'foo'}, + fragmentIdentifier: 'bar' +}, { + parseFragmentIdentifier: true +}); +//=> 'https://foo.bar?top=foo#bar' +``` + ## Nesting This module intentionally doesn't support nesting as it's not spec'd and varies between implementations, which causes a lot of [edge cases](https://github.com/visionmedia/node-querystring/issues). diff --git a/test/stringify-url.js b/test/stringify-url.js index 05dd7708..bcb55afb 100644 --- a/test/stringify-url.js +++ b/test/stringify-url.js @@ -25,6 +25,7 @@ test('stringify URL with fragment identifier', t => { t.deepEqual(queryString.stringifyUrl({url: 'https://foo.bar', query: {foo: ['bar', 'baz']}, fragmentIdentifier: 'top'}, config), 'https://foo.bar?foo=bar&foo=baz#top'); t.deepEqual(queryString.stringifyUrl({url: 'https://foo.bar/', query: {}, fragmentIdentifier: 'top'}, config), 'https://foo.bar/#top'); t.deepEqual(queryString.stringifyUrl({url: 'https://foo.bar/#abc', query: {}, fragmentIdentifier: 'top'}, config), 'https://foo.bar/#top'); + t.deepEqual(queryString.stringifyUrl({url: 'https://foo.bar', query: {}}, config), 'https://foo.bar'); }); test('skipEmptyString:: stringify URL with a query string', t => { From 0441b0bab310924c293277fbf931d0af9b470ceb Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Sun, 24 May 2020 17:02:27 +0800 Subject: [PATCH 09/24] Update index.d.ts --- index.d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/index.d.ts b/index.d.ts index 83d7715c..e3ce4c7c 100644 --- a/index.d.ts +++ b/index.d.ts @@ -157,6 +157,7 @@ export function parse(query: string, options?: ParseOptions): ParsedQuery; export interface ParsedUrl { readonly url: string; readonly query: ParsedQuery; + /** The fragment identifier of the URL. */ From 2c85b165ec5e85663ad2d8e3d2dbe5564706ef7c Mon Sep 17 00:00:00 2001 From: Mark1626 Date: Sun, 24 May 2020 19:36:26 +0530 Subject: [PATCH 10/24] Review Changes Co-authored-by: Karuppiah --- index.d.ts | 30 ++++++++---------------------- index.js | 13 ++++++++++--- readme.md | 27 ++++++++------------------- test/parse-url.js | 1 + test/stringify-url.js | 12 ++++++------ 5 files changed, 33 insertions(+), 50 deletions(-) diff --git a/index.d.ts b/index.d.ts index e3ce4c7c..95e94c48 100644 --- a/index.d.ts +++ b/index.d.ts @@ -123,7 +123,7 @@ export interface ParseOptions { readonly parseBooleans?: boolean; /** - Parse the fragment identifier from the URL. + Parse the fragment identifier from the URL and add it to result object. @default false @@ -330,27 +330,6 @@ export interface StringifyOptions { ``` */ readonly skipEmptyString?: boolean; - - /** - Adds the fragment identifier to the URL. - - @default false - - @example - ``` - import queryString = require('query-string'); - - queryString.stringifyUrl({ - url: 'https://foo.bar', - query: {top: 'foo'}, - fragmentIdentifier: 'bar' - }, { - parseFragmentIdentifier: true - }); - //=> 'https://foo.bar?top=foo#bar' - ``` - */ - readonly parseFragmentIdentifier?: boolean; } /** @@ -380,6 +359,13 @@ queryString.stringifyUrl({url: 'https://foo.bar', query: {foo: 'bar'}}); queryString.stringifyUrl({url: 'https://foo.bar?foo=baz', query: {foo: 'bar'}}); //=> 'https://foo.bar?foo=bar' + +queryString.stringifyUrl({ + url: 'https://foo.bar', + query: {top: 'foo'}, + fragmentIdentifier: 'bar' +}); +//=> 'https://foo.bar?top=foo#bar' ``` */ export function stringifyUrl( diff --git a/index.js b/index.js index aa4918f5..3723743f 100644 --- a/index.js +++ b/index.js @@ -338,17 +338,24 @@ exports.stringify = (object, options) => { }; exports.parseUrl = (input, options) => { + options = Object.assign({ + decode: true + }, options); const [url, hash] = splitOnFirst(input, '#'); return Object.assign( { url: url.split('?')[0] || '', query: parse(extract(input), options) }, - options && options.parseFragmentIdentifier && hash ? {fragmentIdentifier: hash} : {} + options && options.parseFragmentIdentifier && hash ? {fragmentIdentifier: decode(hash, options)} : {} ); }; exports.stringifyUrl = (input, options) => { + options = Object.assign({ + encode: true, + strict: true + }, options); const url = removeHash(input.url).split('?')[0] || ''; const queryFromUrl = exports.extract(input.url); const parsedQueryFromUrl = exports.parse(queryFromUrl); @@ -359,8 +366,8 @@ exports.stringifyUrl = (input, options) => { queryString = `?${queryString}`; } - if (options && options.parseFragmentIdentifier && input.fragmentIdentifier) { - hash = `#${input.fragmentIdentifier}`; + if (input.fragmentIdentifier) { + hash = `#${encode(input.fragmentIdentifier, options)}`; } return `${url}${queryString}${hash}`; diff --git a/readme.md b/readme.md index 6ca93c52..0889fac5 100644 --- a/readme.md +++ b/readme.md @@ -354,7 +354,7 @@ Type: `object` The `options` are the same as for `.parse()`. -Extra options are as below +Extra options are as below. ##### parseFragmentIdentifier @@ -386,6 +386,13 @@ queryString.stringifyUrl({url: 'https://foo.bar', query: {foo: 'bar'}}); queryString.stringifyUrl({url: 'https://foo.bar?foo=baz', query: {foo: 'bar'}}); //=> 'https://foo.bar?foo=bar' + +queryString.stringifyUrl({ + url: 'https://foo.bar', + query: {top: 'foo'}, + fragmentIdentifier: 'bar' +}); +//=> 'https://foo.bar?top=foo#bar' ``` #### options @@ -404,24 +411,6 @@ Type: `object` Query items to add to the URL. -##### parseFragmentIdentifier - -Adds the fragment identifier to the URL. - -Type: `boolean`\ -Default: `false` - -```js -queryString.stringifyUrl({ - url: 'https://foo.bar', - query: {top: 'foo'}, - fragmentIdentifier: 'bar' -}, { - parseFragmentIdentifier: true -}); -//=> 'https://foo.bar?top=foo#bar' -``` - ## Nesting This module intentionally doesn't support nesting as it's not spec'd and varies between implementations, which causes a lot of [edge cases](https://github.com/visionmedia/node-querystring/issues). diff --git a/test/parse-url.js b/test/parse-url.js index bb48b570..720333c4 100644 --- a/test/parse-url.js +++ b/test/parse-url.js @@ -22,6 +22,7 @@ test('handles strings with fragment identifier', t => { t.deepEqual(queryString.parseUrl('https://foo.bar?top=foo#bar', {parseFragmentIdentifier: true}), {url: 'https://foo.bar', query: {top: 'foo'}, fragmentIdentifier: 'bar'}); t.deepEqual(queryString.parseUrl('https://foo.bar?foo=bar&foo=baz#top', {parseFragmentIdentifier: true}), {url: 'https://foo.bar', query: {foo: ['bar', 'baz']}, fragmentIdentifier: 'top'}); t.deepEqual(queryString.parseUrl('https://foo.bar/#top', {parseFragmentIdentifier: true}), {url: 'https://foo.bar/', query: {}, fragmentIdentifier: 'top'}); + t.deepEqual(queryString.parseUrl('https://foo.bar/#st%C3%A5le', {parseFragmentIdentifier: true}), {url: 'https://foo.bar/', query: {}, fragmentIdentifier: 'ståle'}); }); test('throws for invalid values', t => { diff --git a/test/stringify-url.js b/test/stringify-url.js index bcb55afb..98055cc1 100644 --- a/test/stringify-url.js +++ b/test/stringify-url.js @@ -20,12 +20,12 @@ test('stringify URL with a query string', t => { }); test('stringify URL with fragment identifier', t => { - const config = {parseFragmentIdentifier: true}; - t.deepEqual(queryString.stringifyUrl({url: 'https://foo.bar', query: {top: 'foo'}, fragmentIdentifier: 'bar'}, config), 'https://foo.bar?top=foo#bar'); - t.deepEqual(queryString.stringifyUrl({url: 'https://foo.bar', query: {foo: ['bar', 'baz']}, fragmentIdentifier: 'top'}, config), 'https://foo.bar?foo=bar&foo=baz#top'); - t.deepEqual(queryString.stringifyUrl({url: 'https://foo.bar/', query: {}, fragmentIdentifier: 'top'}, config), 'https://foo.bar/#top'); - t.deepEqual(queryString.stringifyUrl({url: 'https://foo.bar/#abc', query: {}, fragmentIdentifier: 'top'}, config), 'https://foo.bar/#top'); - t.deepEqual(queryString.stringifyUrl({url: 'https://foo.bar', query: {}}, config), 'https://foo.bar'); + t.deepEqual(queryString.stringifyUrl({url: 'https://foo.bar', query: {top: 'foo'}, fragmentIdentifier: 'bar'}), 'https://foo.bar?top=foo#bar'); + t.deepEqual(queryString.stringifyUrl({url: 'https://foo.bar', query: {foo: ['bar', 'baz']}, fragmentIdentifier: 'top'}), 'https://foo.bar?foo=bar&foo=baz#top'); + t.deepEqual(queryString.stringifyUrl({url: 'https://foo.bar/', query: {}, fragmentIdentifier: 'top'}), 'https://foo.bar/#top'); + t.deepEqual(queryString.stringifyUrl({url: 'https://foo.bar/#abc', query: {}, fragmentIdentifier: 'top'}), 'https://foo.bar/#top'); + t.deepEqual(queryString.stringifyUrl({url: 'https://foo.bar', query: {}}), 'https://foo.bar'); + t.deepEqual(queryString.stringifyUrl({url: 'https://foo.bar', query: {}, fragmentIdentifier: 'foo bar'}), 'https://foo.bar#foo%20bar'); }); test('skipEmptyString:: stringify URL with a query string', t => { From 26b72c812c7c9b157b2c295217d14485820e49bb Mon Sep 17 00:00:00 2001 From: Mark1626 Date: Sun, 24 May 2020 19:51:46 +0530 Subject: [PATCH 11/24] Update Documentation Co-authored-by: Karuppiah --- index.d.ts | 6 ++++++ readme.md | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/index.d.ts b/index.d.ts index 95e94c48..97d99d6a 100644 --- a/index.d.ts +++ b/index.d.ts @@ -166,6 +166,7 @@ export interface ParsedUrl { /** Extract the URL and the query string as an object. +Optionally object contains `fragmentIdentifier` if `parseFragmentIdentifier` is `true` in options. @param url - The URL to parse. @@ -175,6 +176,9 @@ import queryString = require('query-string'); queryString.parseUrl('https://foo.bar?foo=bar'); //=> {url: 'https://foo.bar', query: {foo: 'bar'}} + +queryString.parseUrl('https://foo.bar?foo=bar#xyz', {parseFragmentIdentifier: true}); +//=> {url: 'https://foo.bar', query: {foo: 'bar'}, fragmentIdentifier: 'xyz'} ``` */ export function parseUrl(url: string, options?: ParseOptions): ParsedUrl; @@ -352,6 +356,8 @@ Stringify an object into a URL with a query string and sorting the keys. The inv Query items in the `query` property overrides queries in the `url` property. +Fragment identifier in the `fragmentIdentifier` property overrides fragment identifier in the `url` property + @example ``` queryString.stringifyUrl({url: 'https://foo.bar', query: {foo: 'bar'}}); diff --git a/readme.md b/readme.md index 0889fac5..c96aad1b 100644 --- a/readme.md +++ b/readme.md @@ -340,12 +340,16 @@ Note: This behaviour can be changed with the `skipNull` option. Extract the URL and the query string as an object. Returns an object with a `url` and `query` property. +Optionally object contains `fragmentIdentifier` if `parseFragmentIdentifier` is `true` in options. ```js const queryString = require('query-string'); queryString.parseUrl('https://foo.bar?foo=bar'); //=> {url: 'https://foo.bar', query: {foo: 'bar'}} + +queryString.parseUrl('https://foo.bar?foo=bar#xyz', {parseFragmentIdentifier: true}); +//=> {url: 'https://foo.bar', query: {foo: 'bar'}, fragmentIdentifier: 'xyz'} ``` #### options @@ -380,6 +384,8 @@ Returns a string with the URL and a query string. Query items in the `query` property overrides queries in the `url` property. +Fragment identifier in the `fragmentIdentifier` property overrides fragment identifier in the `url` property + ```js queryString.stringifyUrl({url: 'https://foo.bar', query: {foo: 'bar'}}); //=> 'https://foo.bar?foo=bar' From 2e014d3f975ccbb4df3c4ae541ea498d70d7f260 Mon Sep 17 00:00:00 2001 From: Nimalan Date: Wed, 3 Jun 2020 20:03:26 +0530 Subject: [PATCH 12/24] Update index.d.ts Co-authored-by: Sindre Sorhus --- index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.d.ts b/index.d.ts index 97d99d6a..17d98fe8 100644 --- a/index.d.ts +++ b/index.d.ts @@ -166,7 +166,7 @@ export interface ParsedUrl { /** Extract the URL and the query string as an object. -Optionally object contains `fragmentIdentifier` if `parseFragmentIdentifier` is `true` in options. +If the `parseFragmentIdentifier` is `true`, the object will also contain a `fragmentIdentifier` property. @param url - The URL to parse. From cae1a5316e90ae5387425466e00b8f01c62a0854 Mon Sep 17 00:00:00 2001 From: Nimalan Date: Wed, 3 Jun 2020 20:03:34 +0530 Subject: [PATCH 13/24] Update index.d.ts Co-authored-by: Sindre Sorhus --- index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.d.ts b/index.d.ts index 17d98fe8..dcfcbfcb 100644 --- a/index.d.ts +++ b/index.d.ts @@ -356,7 +356,7 @@ Stringify an object into a URL with a query string and sorting the keys. The inv Query items in the `query` property overrides queries in the `url` property. -Fragment identifier in the `fragmentIdentifier` property overrides fragment identifier in the `url` property +The `fragmentIdentifier` property overrides the fragment identifier in the `url` property. @example ``` From a20482fd1100c5abf0577700359c8ccade5d0a2f Mon Sep 17 00:00:00 2001 From: Mark1626 Date: Wed, 3 Jun 2020 20:08:52 +0530 Subject: [PATCH 14/24] Add in readme --- readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index c96aad1b..0d18c207 100644 --- a/readme.md +++ b/readme.md @@ -340,7 +340,7 @@ Note: This behaviour can be changed with the `skipNull` option. Extract the URL and the query string as an object. Returns an object with a `url` and `query` property. -Optionally object contains `fragmentIdentifier` if `parseFragmentIdentifier` is `true` in options. +If the `parseFragmentIdentifier` is `true`, the object will also contain a `fragmentIdentifier` property. ```js const queryString = require('query-string'); @@ -384,7 +384,7 @@ Returns a string with the URL and a query string. Query items in the `query` property overrides queries in the `url` property. -Fragment identifier in the `fragmentIdentifier` property overrides fragment identifier in the `url` property +The `fragmentIdentifier` property overrides the fragment identifier in the `url` property. ```js queryString.stringifyUrl({url: 'https://foo.bar', query: {foo: 'bar'}}); From 10d00bb2c81d5d8fbee88a32005503d0fbe07715 Mon Sep 17 00:00:00 2001 From: Mark1626 Date: Wed, 3 Jun 2020 20:23:34 +0530 Subject: [PATCH 15/24] Update index.d.ts --- index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.d.ts b/index.d.ts index dcfcbfcb..73502013 100644 --- a/index.d.ts +++ b/index.d.ts @@ -159,7 +159,7 @@ export interface ParsedUrl { readonly query: ParsedQuery; /** - The fragment identifier of the URL. + If the `parseFragmentIdentifier` is `true`, the object will also contain a `fragmentIdentifier` property. */ readonly fragmentIdentifier?: string; } From 296334ebb2ef80c8bfda6baa5d5ab42b284da150 Mon Sep 17 00:00:00 2001 From: Mark1626 Date: Wed, 3 Jun 2020 20:46:57 +0530 Subject: [PATCH 16/24] Update index.d.ts --- index.d.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/index.d.ts b/index.d.ts index 73502013..dacfa240 100644 --- a/index.d.ts +++ b/index.d.ts @@ -159,7 +159,8 @@ export interface ParsedUrl { readonly query: ParsedQuery; /** - If the `parseFragmentIdentifier` is `true`, the object will also contain a `fragmentIdentifier` property. + The fragment identifier of the URL. + Present when `parseFragmentIdentifier` is `true`. */ readonly fragmentIdentifier?: string; } From bea843a4402b7ad05da87227f43259398d20de36 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Sat, 6 Jun 2020 14:20:11 +0800 Subject: [PATCH 17/24] Update index.d.ts --- index.d.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/index.d.ts b/index.d.ts index dacfa240..a7dc6d72 100644 --- a/index.d.ts +++ b/index.d.ts @@ -160,7 +160,8 @@ export interface ParsedUrl { /** The fragment identifier of the URL. - Present when `parseFragmentIdentifier` is `true`. + + Present when the `parseFragmentIdentifier` option is `true`. */ readonly fragmentIdentifier?: string; } From 6c47029ca8b723c8ce5256fa8a984908a6349e1a Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Sat, 6 Jun 2020 14:21:09 +0800 Subject: [PATCH 18/24] Update index.d.ts --- index.d.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/index.d.ts b/index.d.ts index a7dc6d72..dfa63a63 100644 --- a/index.d.ts +++ b/index.d.ts @@ -168,7 +168,8 @@ export interface ParsedUrl { /** Extract the URL and the query string as an object. -If the `parseFragmentIdentifier` is `true`, the object will also contain a `fragmentIdentifier` property. + +If the `parseFragmentIdentifier` option is `true`, the object will also contain a `fragmentIdentifier` property. @param url - The URL to parse. From ebf1fff1f9eb6ef335669eb0c93efa393713b714 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Sat, 6 Jun 2020 14:22:03 +0800 Subject: [PATCH 19/24] Update index.js --- index.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/index.js b/index.js index 3723743f..1d40de13 100644 --- a/index.js +++ b/index.js @@ -341,7 +341,9 @@ exports.parseUrl = (input, options) => { options = Object.assign({ decode: true }, options); + const [url, hash] = splitOnFirst(input, '#'); + return Object.assign( { url: url.split('?')[0] || '', @@ -356,6 +358,7 @@ exports.stringifyUrl = (input, options) => { encode: true, strict: true }, options); + const url = removeHash(input.url).split('?')[0] || ''; const queryFromUrl = exports.extract(input.url); const parsedQueryFromUrl = exports.parse(queryFromUrl); From 7d074d793de4f094810c3c211c8b831dbe889da1 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Sat, 6 Jun 2020 14:25:01 +0800 Subject: [PATCH 20/24] Update readme.md --- readme.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 0d18c207..cb4a9b2d 100644 --- a/readme.md +++ b/readme.md @@ -340,7 +340,8 @@ Note: This behaviour can be changed with the `skipNull` option. Extract the URL and the query string as an object. Returns an object with a `url` and `query` property. -If the `parseFragmentIdentifier` is `true`, the object will also contain a `fragmentIdentifier` property. + +If the `parseFragmentIdentifier` option is `true`, the object will also contain a `fragmentIdentifier` property. ```js const queryString = require('query-string'); From 085fc6c141f161e965cf5ead8e481b467f38f961 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Sat, 6 Jun 2020 14:25:53 +0800 Subject: [PATCH 21/24] Update readme.md --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index cb4a9b2d..37b07cd3 100644 --- a/readme.md +++ b/readme.md @@ -402,7 +402,7 @@ queryString.stringifyUrl({ //=> 'https://foo.bar?top=foo#bar' ``` -#### options +#### object Type: `object` From cd157b1acee02da7323c475aabdce79ea91f0371 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Sat, 6 Jun 2020 14:28:09 +0800 Subject: [PATCH 22/24] Update readme.md --- readme.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 37b07cd3..a8f92dec 100644 --- a/readme.md +++ b/readme.md @@ -357,7 +357,7 @@ queryString.parseUrl('https://foo.bar?foo=bar#xyz', {parseFragmentIdentifier: tr Type: `object` -The `options` are the same as for `.parse()`. +The options are the same as for `.parse()`. Extra options are as below. @@ -396,7 +396,9 @@ queryString.stringifyUrl({url: 'https://foo.bar?foo=baz', query: {foo: 'bar'}}); queryString.stringifyUrl({ url: 'https://foo.bar', - query: {top: 'foo'}, + query: { + top: 'foo' + }, fragmentIdentifier: 'bar' }); //=> 'https://foo.bar?top=foo#bar' From dba65ecad6ec2f3fb6e6f55073ca5af0e1a5fb29 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Sat, 6 Jun 2020 14:32:54 +0800 Subject: [PATCH 23/24] Update index.d.ts --- index.d.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/index.d.ts b/index.d.ts index dfa63a63..fecf1047 100644 --- a/index.d.ts +++ b/index.d.ts @@ -371,7 +371,9 @@ queryString.stringifyUrl({url: 'https://foo.bar?foo=baz', query: {foo: 'bar'}}); queryString.stringifyUrl({ url: 'https://foo.bar', - query: {top: 'foo'}, + query: { + top: 'foo' + }, fragmentIdentifier: 'bar' }); //=> 'https://foo.bar?top=foo#bar' From 3d171a3329b1c2c058c0b57cc37508d8d9a510f4 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Sat, 6 Jun 2020 14:33:52 +0800 Subject: [PATCH 24/24] Update index.js --- index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 1d40de13..f8ca0df7 100644 --- a/index.js +++ b/index.js @@ -362,13 +362,14 @@ exports.stringifyUrl = (input, options) => { const url = removeHash(input.url).split('?')[0] || ''; const queryFromUrl = exports.extract(input.url); const parsedQueryFromUrl = exports.parse(queryFromUrl); - let hash = getHash(input.url); + const query = Object.assign(parsedQueryFromUrl, input.query); let queryString = exports.stringify(query, options); if (queryString) { queryString = `?${queryString}`; } + let hash = getHash(input.url); if (input.fragmentIdentifier) { hash = `#${encode(input.fragmentIdentifier, options)}`; }