Last active
January 10, 2017 17:37
-
-
Save james-jlo-long/2397294cb34dff205629be2103442bf8 to your computer and use it in GitHub Desktop.
A manager for URL query strings
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
TODO: Allow Query#parseString to correctly parse square brackets. | |
TODO: Handle nested objects correctly. | |
*/ | |
var Query = (function () { | |
"use strict"; | |
var hasOwn = Object.prototype.hasOwnProperty; | |
// Checks to see if the given object is an object. Will return true for | |
// arrays as well. | |
var isObject = function (object) { | |
return object !== null && typeof object === "object"; | |
}; | |
// Converts any element into a string, an empty string for empty values. | |
var interpretString = function (string) { | |
return (string === null || string === undefined) | |
? "" | |
: String(string); | |
}; | |
/** | |
* class Query | |
* | |
* Parses query strings and allows them to be manipulated. It does not set | |
* any query string (so if the current URL is used, any changes will still | |
* need to be set) but it allows the data to be managed. | |
* | |
* [[Query#has]], [[Query#set]], [[Query#get]], [[Query#add]] and | |
* [[Query.unset]] will allow [[Query#data]] to be manipulated. | |
* [[Query#parseString]] can be used to load a query string and parse it. | |
* [[Query#toString]] will convert [[Query#data]] into a query string. | |
**/ | |
var Query = function () { | |
return this.init.apply(this, arguments); | |
}; | |
Query.prototype = { | |
/** | |
* new Query([data]) | |
* - data (String|Object): Optional initial data. | |
* | |
* `data` can be provided as either an object or a string. In either | |
* case it will be used to populate [[Query#data]]. | |
* | |
* var q1 = new Query(); | |
* q1.data; // -> {} | |
* var q2 = new Query({foo: 1, bar: 2}); | |
* q2.data; // -> {foo: 1, bar: 2} | |
* var q3 = new Query("foo=1&bar=2"); | |
* q3.data; // -> {foo: 1, bar: 2} | |
* | |
* In the examples gives, `q2` is a short-cut for calling [[Query#set]] | |
* and `q3` is a short-cut for calling [[Query#parseString]]. See those | |
* function descriptions for full details. | |
**/ | |
init: function (data) { | |
/** | |
* Query#data -> Object | |
* | |
* The data for the query string. Try not to manipulate this | |
* directly. Instead, use the helper methods [[Query#set]], | |
* [[Query#get]], [[Query#add]] and [[Query.unset]]. The data can | |
* be checked using either [[Query#has]] or [[Query#keys]] and | |
* [[Query#each]] will iterate over the data. | |
* | |
* In a future version of this object, [[Query#data]] may become | |
* hidden. | |
**/ | |
this.data = {}; | |
this.setArrayType(Query.ARRAY_KEYS_REPEAT); | |
if (typeof data === "string") { | |
this.parseString(data); | |
} else if (isObject(data)) { | |
this.set(data); | |
} | |
}, | |
/** chainable | |
* Query#setArrayType(type) -> Query | |
* - type (Number): Array type. | |
* | |
* Sets the array handling type, changing the way that arrays are | |
* handled when converting the query into a string. There are currently | |
* 3 possibilities: | |
* | |
* **[[Query.ARRAY_KEYS_REPEAT]] (default)** | |
* | |
* This setting causes the array keys to simply repeat. | |
* | |
* new Query("foo=1&foo=2") | |
* .setArrayType(Query.ARRAY_KEYS_REPEAT) | |
* .toString(); | |
* // -> "foo=1&foo=2" | |
* | |
* **[[Query.ARRAY_KEYS_BRACKET]]** | |
* | |
* This setting causes the array keys to include empty square brackets | |
* after them. | |
* | |
* new Query("foo=1&foo=2") | |
* .setArrayType(Query.ARRAY_KEYS_BRACKET) | |
* .toString(); | |
* // -> "foo[]=1&foo[]=2" | |
* | |
* **[[Query.ARRAY_KEYS_INDEX]]** | |
* | |
* This setting causes the array keys to include square brackets | |
* containing the index after them. | |
* | |
* new Query("foo=1&foo=2") | |
* .setArrayType(Query.ARRAY_KEYS_BRACKET) | |
* .toString(); | |
* // -> "foo[0]=1&foo[1]=2" | |
* | |
* If a value of `type` is given and not recognised, | |
* [[Query.ARRAY_KEYS_REPEAT]] will be assumed. | |
**/ | |
setArrayType: function (type) { | |
/** | |
* Query#arrayType -> Number | |
* | |
* A flag detailing how to handle array keys when converting the | |
* query into a string. See [[Query#setArrayType]] for full | |
* details. | |
**/ | |
this.arrayType = type; | |
return this; | |
}, | |
/** | |
* Query#has(key) -> Boolean | |
* - key (String): Key to check. | |
* | |
* Checks to see if the given key exists in [[Query#data]]. | |
* | |
* var q = new Query(); | |
* q.set("foo", "alpha"); | |
* q.has("foo"); // -> true | |
* q.has("bar"); // -> false | |
* | |
* Be aware that data is decoded from the URL component so a raw key | |
* should be checked instead of the original query value. | |
* | |
* q.parseString("foo%20bar=bravo"); | |
* q.has("foo bar"); // -> true | |
* q.has("foo%20bar"); // -> false | |
* | |
**/ | |
has: function (key) { | |
return hasOwn.call(this.data, key); | |
}, | |
/** chainable | |
* Query#set(data) -> Query | |
* Query#set(key[, value]) -> Query | |
* - data (Object): Key/Value pairs for setting. | |
* - key (String): Key to set. | |
* - value (?): Optional value for the `key`. | |
* | |
* Sets information in [[Query#data]]. The instance is returned to | |
* allow for chaining. | |
* | |
* var q = new Query(); | |
* q.set("foo", "alpha"); | |
* q.has("foo"); // -> true | |
* | |
* q.set("bar", "bravo").set("baz", "charlie"); | |
* q.has("bar"); // -> true | |
* q.has("baz"); // -> true | |
* | |
* Data can be passed as an object to speed up adding information. | |
* | |
* q.set({ | |
* blip: "delta", | |
* blop: ["echo", "foxtrot"] | |
* }); | |
* q.has("blip"); // -> true | |
* q.has("blop"); // -> true | |
* | |
* If the same data is set again, the value is overridden. | |
* | |
* q.get("foo"); // -> "alpha" | |
* q.set("foo", "golf"); | |
* q.get("foo"); // -> "golf" | |
* q.set({ | |
* foo: "hotel" | |
* }); | |
* q.get("foo"); // -> "hotel" | |
* | |
**/ | |
set: function (key, value) { | |
if (isObject(key)) { | |
Object.keys(key).forEach(function (part) { | |
this.set(part, key[part]); | |
}, this); | |
} else { | |
this.data[key] = value; | |
} | |
return this; | |
}, | |
/** | |
* Query#get(keys) -> Object | |
* Query#get(key) -> ? | |
* - keys (Array): Array of keys to access. | |
* - key (String): Key to access. | |
* | |
* Gets the value from [[Query#data]]. If the data cannot be found, | |
* `undefined` is returned. | |
* | |
* var q = new Query(); | |
* q.set("foo", "alpha"); | |
* q.get("foo"); // -> "alpha" | |
* q.get("bar"); // -> undefined | |
* | |
* If [[Query#get]] is passed an array, the entries are returned as an | |
* object. | |
* | |
* q.get(["foo", "bar"]); // -> {foo: "alpha", bar: undefined} | |
* | |
* This means that a shallow clone of [[Query#data]] can be returned | |
* by combining [[Query#get]] and [[Query#keys]]. | |
* | |
* q.get(q.keys()); // -> {foo: "alpha"} | |
* | |
* Be aware that it is possible for a query string to have a key but | |
* not a value. In that situation, `undefined` would also be returned. | |
* Use [[Query#has]] to ensure that the key exists but is empty. | |
* | |
* q.parseString("baz=&blip=something"); | |
* q.get("blip"); // -> "something" | |
* q.get("baz"); // -> undefined | |
* q.has("baz"); // -> true | |
* q.has("bar"); // -> false | |
* | |
**/ | |
get: function (key) { | |
var result = this.data[key]; | |
if (Array.isArray(key)) { | |
result = {}; | |
key.forEach(function (k) { | |
result[k] = this.get(k); | |
}, this); | |
} | |
return result; | |
}, | |
/** chainable | |
* Query#add(data) -> Query | |
* Query#add(key, value) -> Query | |
* - data (Object): Key/Value pairs for setting. | |
* - key (String): Key to add. | |
* - value (?): Value for the `key`. | |
* | |
* Adds a value to [[Query#data]]. Unlike [[Query#set]] which will | |
* replace an existing value, [[Query#add]] will add the value and | |
* preserve existing data. Since it will also create data if the data | |
* does not exist, it can be more useful than [[Query#set]]. The data | |
* created by [[Query#add]] will always be an array even if there is | |
* only one value. This is normalised when converted into a string | |
* using [[Query#toString]]. | |
* | |
* var q = new Query(); | |
* | |
* q.set("foo", "alpha"); | |
* q.get("foo"); // -> "alpha" | |
* q.set("foo", "bravo"); | |
* q.get("foo"); // -> "bravo" | |
* | |
* q.add("bar", "alpha"); | |
* q.get("bar"); // -> ["alpha"] | |
* q.add("bar", "bravo"); | |
* q.get("bar"); // -> ["alpha", "bravo"] | |
* | |
* The instance is returned to allow for chaining. | |
**/ | |
add: function (key, value) { | |
if (isObject(key)) { | |
Object.keys(key).forEach(function (part) { | |
this.add(part, key[part]); | |
}, this); | |
} else { | |
if (!this.has(key)) { | |
this.set(key, []); | |
} else if (!this.isArray(key)) { | |
this.set(key, [this.get(key)]); | |
} | |
this.data[key].push(value); | |
} | |
return this; | |
}, | |
/** | |
* Query#unset(key[, index]) -> Boolean | |
* - key (String): Key to unset. | |
* - index (Number): Optional index for `key`. | |
* | |
* Unsets data from [[Query#data]]. Unsetting data that does not exist | |
* will not cause any errors. | |
* | |
* var q = new Query(); | |
* q.parseString("foo=alpha&bar=bravo&bar=charlie"); | |
* q.get("foo"); // -> "alpha" | |
* q.get("bar"); // -> ["bravo", "charlie"] | |
* q.unset("foo"); // -> true | |
* q.has("foo"); // -> false | |
* q.unset("foo"); // -> false | |
* q.has("foo"); // -> false | |
* | |
* If `index` is provided, is a number and `key` refers to an array | |
* then that entry in the array is removed instead of the entire value. | |
* Attempting to remove an entry in an array that does not exist will | |
* not cause any errors. | |
* | |
* q.get("bar"); // -> ["bravo", "charlie"] | |
* q.unset("bar", 1); // -> true | |
* q.get("bar"); // -> ["bravo"] | |
* q.unset("bar", 10); // -> false | |
* q.get("bar"); // -> ["bravo"] | |
* | |
* A boolean is returned that is `true` if data was successfully | |
* removed and `false` otherwise. | |
**/ | |
unset: function (key, index) { | |
var existed = this.has(key); | |
if (this.isArray(key) && (/^\d+$/).test(index)) { | |
existed = hasOwn.call(this.data[key], index); | |
this.data[key].splice(index, 1); | |
} else { | |
delete this.data[key]; | |
} | |
return existed; | |
}, | |
/** | |
* Query#isArray(key) -> Boolean | |
* - key (String): Key to check. | |
* | |
* Checks to see if the `key` refers to an array in [[Query#data]]. | |
* | |
* var q = new Query(); | |
* q.parseString("foo=alpha&bar=bravo&bar=charlie"); | |
* q.isArray("foo"); // -> false | |
* q.isArray("bar"); // -> true | |
* q.set("baz", "delta"); | |
* q.add("blip", "echo"); | |
* q.isArray("baz"); // -> false | |
* q.isArray("blip"); // -> true | |
* | |
**/ | |
isArray: function (key) { | |
return this.has(key) && Array.isArray(this.get(key)); | |
}, | |
/** | |
* Query#keys() -> Array | |
* | |
* Returns all the keys from [[Query#data]]. | |
* | |
* var q = new Query(); | |
* q.parseString("foo=alpha&bar=bravo&bar=charlie"); | |
* q.keys(); // -> ["foo", "bar"] | |
* | |
**/ | |
keys: function () { | |
return Object.keys(this.data); | |
}, | |
/** | |
* Query#each(handler[, context]) | |
* - handler (Function): Function to execute. | |
* - context (?): Optional context for `handler`. | |
* | |
* Executes a function on all entries in [[Query#data]]. The `handler` | |
* function is passed the `key` and the `value` for each entry. Be | |
* aware that the order of execution is not guarenteed. | |
* | |
* var q = new Query(); | |
* q.parseString("foo=alpha&bar=bravo&bar=charlie"); | |
* q.each(function (key, value) { | |
* console.log("Query#data[%s] = %o", key, value); | |
* }); | |
* // Logs: "Query#data[foo] = "alpha" | |
* // Logs: "Query#data[bar] = ["bravo", "charlie"] | |
* | |
**/ | |
each: function (handler, context) { | |
this.keys().forEach(function (key) { | |
handler.call(context, key, this.data[key]); | |
}, this); | |
}, | |
/** | |
* Query#parseString(string[, isOverride = false]) | |
* - string (String): Query string to parse. | |
* - isOverride (Boolean): Whether a match should be added to (`false`) | |
* or replaced (`true`). | |
* | |
* Parses the given query string and adds all information to | |
* [[Query#data]]. Care is taken so that single entries in the `string` | |
* are not converted into arrays in [[Query#data]]. The keys and values | |
* are URL decoded. Ampersands are normalised from HTML entities thus | |
* `&` and `&` are considered the same. | |
* | |
* var q = new Query(); | |
* q.parseString("foo=a&bar=b&bar=c&baz%20blip=d"); | |
* q.keys(); // -> ["foo", "bar", "baz blip"] | |
* q.get("foo"); // -> "a" | |
* q.get("bar"); // -> ["b", "c"] | |
* q.get("baz blip"); // -> "d" | |
* | |
* When parsing a string, if a similar value is found, the value is | |
* converted into an array (if it is not already) and the second value | |
* is added to that array. You can see that happening with the `"bar"` | |
* key in the example above. To change that behaviour so that a second | |
* key replaces the value of the first, set `isOverride` to `true`. | |
* | |
* var q1 = new Query(); | |
* q1.parseString("bar=1&bar=2"); | |
* q1.get("bar"); // -> ["1", "2"] | |
* var q2 = new Query(); | |
* q2.parseString("bar=1&bar=2", true); | |
* q1.get("bar"); // -> "2" | |
* | |
**/ | |
parseString: function (string, isOverride) { | |
var str = interpretString(string).trim(); | |
if (str) { | |
str.split(/&(?:amp;)?/).forEach(function (parameter) { | |
var param = parameter.trim(); | |
var parts = parameter.split("="); | |
var key = window.decodeURIComponent(parts[0]); | |
var value = parts.length > 1 | |
? window.decodeURIComponent( | |
parts[1].replace(/\+/g, " ") | |
) | |
: undefined; | |
this[ | |
(this.has(key) && !isOverride) | |
? "add" | |
: "set" | |
](key, value); | |
}, this); | |
} | |
}, | |
/** | |
* Query#stringifyKey(key[, index]) -> String | |
* - key (String): Key to be stringified. | |
* - index (Number): Optional index for the key. | |
* | |
* Converts the given `key` into a URL-friendly key. | |
* | |
* var q = new Query(); | |
* q.stringifyKey("foo"); // -> "foo" | |
* q.stringifyKey("bar baz"); // -> "bar%20baz" | |
* | |
* Keys are not checked against [[Query#data]] so an associated value | |
* does not need to exist for the key to be converted. | |
* | |
* If `index` is included, the key is assumed to be part of an array | |
* and handled according to the [[Query#arrayType]] that has been set | |
* (see [[Query#setArrayType]] for full details). | |
* | |
* var q = new Query(); | |
* q.setArrayType(Query.ARRAY_KEYS_INDEX); | |
* q.stringifyKey("foo", 0); // -> "foo[0]" | |
* q.stringifyKey("bar baz", 1); // -> "bar%20baz[1]" | |
* | |
* This function is mainly used in [[Query.stringify]]. | |
**/ | |
stringifyKey: function (key, index) { | |
var string = window.encodeURIComponent(key); | |
if (index !== undefined) { | |
if (this.arrayType === Query.ARRAY_KEYS_INDEX) { | |
string += "[" + window.encodeURIComponent(index) + "]"; | |
} else if (this.arrayType === Query.ARRAY_KEYS_BRACKET) { | |
string += "[]"; | |
} | |
} | |
return string; | |
}, | |
/** | |
* Query#stringifyValue(value) -> String | |
* - value (String): Value to convert. | |
* | |
* Converts the value into a URL-friendly string and prefixes it with | |
* `"="` so it can be included in a query string. | |
* | |
* var q = new Query(); | |
* q.stringifyValue("foo"); // -> "=foo" | |
* q.stringifyValue("bar baz"); // -> "=bar+baz" | |
* | |
* Since there is no key provided, the value does not need to be | |
* associated with any data. | |
* | |
* This function is mainly used in [[Query#stringify]]. | |
**/ | |
stringifyValue: function (value) { | |
var string = ""; | |
if (value !== undefined) { | |
value = window | |
.encodeURIComponent( | |
// Normalize newlines as \r\n because the HTML spec | |
// says newlines should be encoded as CRLFs. | |
interpretString(value).replace(/(\r)?\n/g, "\r\n") | |
) | |
// Likewise, according to the spec, spaces should be "+" | |
// rather than "%20". | |
.replace(/%20/g, "+"); | |
string += "=" + value; | |
} | |
return string; | |
}, | |
/** | |
* Query#stringify(key[, value]) -> String | |
* - key (String): Key to convert. | |
* - value (?): Optional value to convert. | |
* | |
* Converts the given `key`/`value` pair into a URL-ready query string | |
* component. According to the HTML spec, spaces in the values should | |
* be converted into `+` rather than `%20` but the same is not true of | |
* keys. | |
* | |
* var q = new Query(); | |
* q.stringify("foo", "alpha"); // -> "foo=alpha" | |
* q.stringify("bar", ["bravo", "charlie"]); | |
* // -> "bar=bravo&bar=charlie | |
* q.stringify("baz blip", "delta echo"); | |
* // -> "bar%20blip=delta+echo" | |
* q.stringify("blop"); // -> "blop" | |
* | |
* Whenever `value` is an array, the `key` is modified according to the | |
* current [[Query#arrayType]] - see [[Query#setArrayType]] for full | |
* details. | |
* | |
* This function may not be especially useful on its own but it is a | |
* key component of [[Query#toString]]. | |
**/ | |
stringify: function (key, value) { | |
return Array.isArray(value) | |
? value | |
.map(function (val, i) { | |
return this.stringifyKey(key, i) | |
+ this.stringifyValue(val); | |
}, this) | |
.join("&") | |
: (this.stringifyKey(key) + this.stringifyValue(value)); | |
}, | |
/** | |
* Query#toString() -> String | |
* | |
* Converts [[Query#data]] to a URL-encoded query string, joined with | |
* ampersands. Due to the way that query strings are handled, there | |
* will be no difference between a string value and an array value with | |
* a single entry. | |
* | |
* Be warned that the order of the query string parameters cannot be | |
* guarenteed. If the order is important, use [[Query#keys()]] to get | |
* an array of [[Query#data]] keys, `.sort()` to handle the sorting, | |
* [[Query#get]] to get the values of [[Query#data]] and | |
* [[Query#stringify]] to convert the results. You will have to | |
* manually concatenate the results. | |
* | |
* var q = new Query(); | |
* q.set({ | |
* foo: "a", | |
* bar: ["b", "c"], | |
* baz: ["d"], | |
* "blip blop": "d e", | |
* }).set("blap"); | |
* q.toString(); | |
* // -> "foo=a&bar=b&bar=c&baz=d&blip%20blop=d+e&blap" | |
* | |
* When converting an array value into a string, the key is converted | |
* according to the current [[Query#arrayType]] - see | |
* [[Query#setArrayType]] for full details and examples. | |
* | |
* Because the method name is `toString`, JavaScript will automatically | |
* execute it if the instance is treated as a string. | |
* | |
* "?" + q; // -> "?foo=a&bar=b&bar=c&baz=d&blip%20blop=d+e&blap" | |
* | |
**/ | |
toString: function () { | |
var string = []; | |
this.each(function (key, value) { | |
string.push(this.stringify(key, value)); | |
}, this); | |
return string.join("&"); | |
} | |
}; | |
/** | |
* Query.parseUrl() -> Query | |
* | |
* Creates an instance of [[Query]] with the current URL query string | |
* parsed. | |
* | |
* // Assume URL is http://example.com?foo=alpha&bar=bravo&bar=charlie | |
* var q = Query.parseUrl(); | |
* q.get("foo"); // -> "alpha" | |
* q.get("bar"); // -> ["bravo", "charlie"] | |
* | |
**/ | |
Query.parseUrl = function () { | |
return new Query(window.location.search.slice(1)); | |
}; | |
Object.defineProperties(Query, { | |
/** | |
* Query.ARRAY_KEYS_REPEAT = 0 | |
* | |
* A setting used for [[Query#setArrayType]]. Causes the keys to | |
* repeat. | |
* | |
* new Query("foo=1&foo=2") | |
* .setArrayType(Query.ARRAY_KEYS_REPEAT) | |
* .toString(); | |
* // -> "foo=1&foo=2" | |
* | |
**/ | |
ARRAY_KEYS_REPEAT: { | |
configurable: false, | |
enumerable: true, | |
value: 0, | |
writable: false | |
}, | |
/** | |
* Query.ARRAY_KEYS_BRACKET = 1 | |
* | |
* A setting used for [[Query#setArrayType]]. Causes the keys to | |
* include empty square brackets. | |
* | |
* new Query("foo=1&foo=2") | |
* .setArrayType(Query.ARRAY_KEYS_BRACKET) | |
* .toString(); | |
* // -> "foo[]=1&foo[]=2" | |
* | |
**/ | |
ARRAY_KEYS_BRACKET: { | |
configurable: false, | |
enumerable: true, | |
value: 1, | |
writable: false | |
}, | |
/** | |
* Query.ARRAY_KEYS_INDEX = 1 | |
* | |
* A setting used for [[Query#setArrayType]]. Causes the keys to | |
* include square brackets containing the index. | |
* | |
* new Query("foo=1&foo=2") | |
* .setArrayType(Query.ARRAY_KEYS_INDEX) | |
* .toString(); | |
* // -> "foo[0]=1&foo[1]=2" | |
* | |
**/ | |
ARRAY_KEYS_INDEX: { | |
configurable: false, | |
enumerable: true, | |
value: 2, | |
writable: false | |
} | |
}); | |
return Query; | |
}()); |
More notes:
var Query = (function () {
var Query = function () {
return this.init.apply(this, arguments);
};
Query.prototype = {
init: function (data, settings) {
var config = Object.assign({
arrayType: Query.defaultArrayType,
joiner: Query.defaultJoiner
}, settings);
this.data = {};
return this;
},
get: function (path) {
var result = {};
if (typeof path === "string") {
result = _.get(this.data, path);
} else if (Array.isArray(path)) {
path.forEach(function (key) {
_.set(result, key, this.get(key));
}, this);
} else if (path === undefined) {
result = this.get(this.keys());
}
return result;
},
has: function (path) {
return Array.isArray(path)
? path.map(this.has, this)
: _.has(this.data, path);
},
set: function (key, value) {
if (_.isPlainObject(key)) {
Object.keys(key).forEach(function (k) {
this.set(k, key[k]);
}, this);
} else {
_.set(this.data, key, value);
}
return this;
},
unset: function (path) {
return Array.isArray(path)
? path.map(this.unset, this)
: _.unset(this.data, path);
},
add: function (key, value) {
var result;
if (_.isPlainObject(key)) {
Object.keys(key).forEach(function (k) {
this.add(k, key[k]);
}, this);
} else {
if (this.has(key)) {
result = this.get(key);
if (Array.isArray(result)) {
result.push(value);
} else if (_.isPlainObject(result)) {
result[
Object.keys(result).filter(function (key) {
return _.isInteger(+key);
}).length
] = value;
} else {
result = [result, value];
}
this.set(key, result);
} else {
this.set(key, value);
}
}
return this;
},
keys: function () {
return _.keys(this.data);
},
values: function () {
return _.values(this.data)
},
each: function (handler, context) {
this.keys().forEach(function (key) {
handler.call(context, key, this.get(key));
}, this);
},
parseString: function (string, arrayType) {
var parser = Query.parsers[
arrayType === undefined
? this.arrayType
: arrayType
];
if (typeof parser === "function") {
parser.call(this, interpretString(string).replace(/^\??/, ""));
}
}
};
}());
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Extremely rough notes about a possible couple of enhancements: