Commit e466e836 authored by Robert Knight's avatar Robert Knight

Replace query-string dependency with wrapper around `URLSearchParams`

For the client's very simple query string generating and parsing needs
we can avoid this dependency by using a very simple wrapper around
`URLSearchParams`. This also improves type checking since this
dependency didn't provide types and we weren't using the
@types/query-string package.

The `stringify` function sorts parameters in the returned string for
consistency with query-string's behavior.
parent d17a3c22
...@@ -77,7 +77,6 @@ ...@@ -77,7 +77,6 @@
"preact": "^10.4.0", "preact": "^10.4.0",
"prettier": "2.3.2", "prettier": "2.3.2",
"puppeteer": "^10.0.0", "puppeteer": "^10.0.0",
"query-string": "^3.0.1",
"redux": "^4.0.1", "redux": "^4.0.1",
"redux-thunk": "^2.1.0", "redux-thunk": "^2.1.0",
"reselect": "^4.0.0", "reselect": "^4.0.0",
......
...@@ -64,7 +64,7 @@ module.exports = function createBundle(config, buildOpts) { ...@@ -64,7 +64,7 @@ module.exports = function createBundle(config, buildOpts) {
// //
// See node_modules/browserify/lib/builtins.js to find out which // See node_modules/browserify/lib/builtins.js to find out which
// modules provide the implementations of these. // modules provide the implementations of these.
builtins: ['console', '_process', 'querystring'], builtins: ['console', '_process'],
externalRequireName, externalRequireName,
// Map of global variable names to functions returning _source code_ for // Map of global variable names to functions returning _source code_ for
......
import * as queryString from 'query-string'; import * as queryString from '../util/query-string';
import { import {
toBoolean, toBoolean,
toInteger, toInteger,
......
import * as queryString from 'query-string'; import * as queryString from './util/query-string';
/** /**
* Return an HTML5 audio player with the given src URL. * Return an HTML5 audio player with the given src URL.
...@@ -110,6 +110,7 @@ function youTubeQueryParams(link) { ...@@ -110,6 +110,7 @@ function youTubeQueryParams(link) {
't', // will be translated to `start` 't', // will be translated to `start`
]; ];
const linkParams = queryString.parse(link.search); const linkParams = queryString.parse(link.search);
/** @type {Record<string, string>} */
const filteredQuery = {}; const filteredQuery = {};
// Filter linkParams for allowed keys and build those entries // Filter linkParams for allowed keys and build those entries
// into the filteredQuery object // into the filteredQuery object
......
import * as queryString from 'query-string'; import * as queryString from '../util/query-string';
import { replaceURLParams } from '../util/url'; import { replaceURLParams } from '../util/url';
/** /**
......
import * as queryString from 'query-string'; import * as queryString from '../util/query-string';
/** /**
* @typedef {'annotation'|'notebook'|'stream'|'sidebar'} RouteName * @typedef {'annotation'|'notebook'|'stream'|'sidebar'} RouteName
......
import * as queryString from 'query-string';
import warnOnce from '../../shared/warn-once'; import warnOnce from '../../shared/warn-once';
import { generateHexString } from '../util/random'; import { generateHexString } from '../util/random';
import { Socket } from '../websocket'; import { Socket } from '../websocket';
import * as queryString from '../util/query-string';
import { watch } from '../util/watch'; import { watch } from '../util/watch';
/** /**
......
import * as queryString from 'query-string'; import * as queryString from './query-string';
import * as random from './random'; import * as random from './random';
/** /**
...@@ -248,10 +247,10 @@ export default class OAuthClient { ...@@ -248,10 +247,10 @@ export default class OAuthClient {
// key=value format. // key=value format.
const authWindowSettings = queryString const authWindowSettings = queryString
.stringify({ .stringify({
left, left: left.toString(),
top, top: top.toString(),
width, width: width.toString(),
height, height: height.toString(),
}) })
.replace(/&/g, ','); .replace(/&/g, ',');
......
/**
* Generate a query string from a record of query parameters.
*
* The returned string does not have a leading "?" and the parameters are
* sorted by name.
*
* @param {Record<string, string>} params
* @return {string}
*/
export function stringify(params) {
const searchParams = new URLSearchParams();
Object.entries(params).forEach(([key, value]) =>
searchParams.append(key, value)
);
searchParams.sort();
return searchParams.toString();
}
/**
* Parse a query string into a record of parameters.
*
* @param {string} query - Query string which may have a leading "?"
* @return {Record<string, string>}
*/
export function parse(query) {
const params = new URLSearchParams(query);
/** @type {Record<string, string>} */
const result = {};
// @ts-expect-error - `URLSearchParams.entries` is missing.
for (let [key, value] of params.entries()) {
result[key] = value;
}
return result;
}
import fetchMock from 'fetch-mock'; import fetchMock from 'fetch-mock';
import { stringify } from 'query-string'; import { stringify } from '../query-string';
import sinon from 'sinon'; import sinon from 'sinon';
import OAuthClient from '../oauth-client'; import OAuthClient from '../oauth-client';
......
import { parse, stringify } from '../query-string';
describe('sidebar/util/query-string', () => {
describe('parse', () => {
it('returns parsed record', () => {
const query = '?foo=bar+baz%2Fboop&baz=meep';
const parsed = parse(query);
assert.deepEqual(parsed, { foo: 'bar baz/boop', baz: 'meep' });
});
});
describe('stringify', () => {
it('returns formatted query with sorted params', () => {
const params = { foo: 'bar baz/boop', baz: 'meep' };
const formatted = stringify(params);
assert.equal(formatted, 'baz=meep&foo=bar+baz%2Fboop');
});
});
});
...@@ -6604,13 +6604,6 @@ qs@6.7.0: ...@@ -6604,13 +6604,6 @@ qs@6.7.0:
resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==
query-string@^3.0.1:
version "3.0.3"
resolved "https://registry.yarnpkg.com/query-string/-/query-string-3.0.3.tgz#ae2e14b4d05071d4e9b9eb4873c35b0dcd42e638"
integrity sha1-ri4UtNBQcdTpuetIc8NbDc1C5jg=
dependencies:
strict-uri-encode "^1.0.0"
querystring-es3@~0.2.0: querystring-es3@~0.2.0:
version "0.2.1" version "0.2.1"
resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
...@@ -7476,11 +7469,6 @@ streamroller@^2.2.4: ...@@ -7476,11 +7469,6 @@ streamroller@^2.2.4:
debug "^4.1.1" debug "^4.1.1"
fs-extra "^8.1.0" fs-extra "^8.1.0"
strict-uri-encode@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=
string-width@^1.0.1, string-width@^1.0.2: string-width@^1.0.1, string-width@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment