1656 lines
36 KiB
JavaScript
Raw Normal View History

2020-02-20 14:38:25 -08:00
/**
2021-08-25 08:53:42 -07:00
*
2020-02-20 14:38:25 -08:00
* handlebar-kit
2021-08-25 08:53:42 -07:00
*
2020-02-20 14:38:25 -08:00
* Copyright (c) 2020, Jocelyn Badgley
2021-08-25 08:53:42 -07:00
*
2020-02-20 14:38:25 -08:00
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
2021-08-25 08:53:42 -07:00
*
2020-02-20 14:38:25 -08:00
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
2021-08-25 08:53:42 -07:00
*
2020-02-20 14:38:25 -08:00
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2021-08-25 08:53:42 -07:00
*
2020-02-20 14:38:25 -08:00
* Portions of the MIT licensed date-fns library are bundled with this
* software. https://github.com/date-fns/date-fns#readme
*/
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
2020-02-27 18:57:39 -08:00
function equals (value) {
2021-08-25 08:53:42 -07:00
value = uc(value);
return (tok) => uc(tok) === value;
2020-02-27 18:57:39 -08:00
}
function re (pattern) {
2021-08-25 08:53:42 -07:00
if (isString(pattern)) pattern = new RegExp(pattern);
return (tok) => !!String(tok).match(pattern);
2020-02-27 18:57:39 -08:00
}
function anyOf (...args) {
2021-08-25 08:53:42 -07:00
args = args.flat().map(uc);
if (!anyBy(args, isFunction)) {
// arguments do not contain a function, so we can optimize
if (args.length === 1) return (tok) => uc(tok) === args[0];
return (tok) => args.includes(uc(tok));
}
args = args.map((a) => isFunction(a) && a || equals(a));
if (args.length === 1) return (tok) => args[0](tok);
return (tok) => anyBy(args, (check) => check(tok));
2020-02-27 18:57:39 -08:00
}
function allOf (...args) {
2021-08-25 08:53:42 -07:00
args = args.flat().map((a) => isFunction(a) && a || equals(a));
if (args.length === 1) return (tok) => args[0](tok);
return (tok) => allBy(args, (check) => check(tok));
2020-02-27 18:57:39 -08:00
}
2020-02-20 14:38:25 -08:00
function isNumber (input) { return typeof input === 'number' && !isNaN(input); }
function isString (input) { return typeof input === 'string'; }
function isBoolean (input) { return typeof input === 'boolean'; }
function isFunction (input) { return typeof input === 'function'; }
function isUndefined (input) { return typeof input === 'undefined'; }
function isMap (input) { return input instanceof Map; }
function isSet (input) { return input instanceof Set; }
2020-02-27 18:57:39 -08:00
function isDate (input) { return input instanceof Date; }
function isRegExp (input) { return input instanceof RegExp; }
function isTruthy (input) { return !!input; }
function isFalsey (input) { return !input; }
function isNull (input) { return input === null; }
const isArray = Array.isArray;
2020-02-20 14:38:25 -08:00
function isPrimitive (input) {
2021-08-25 08:53:42 -07:00
switch (typeof input) {
case 'string':
case 'number':
case 'boolean':
return true;
default:
return false;
}
2020-02-20 14:38:25 -08:00
}
function isObject (input) {
2021-08-25 08:53:42 -07:00
if (!input) return false;
if (typeof input !== 'object') return false;
if (isArray(input)) return false;
if (!(input instanceof Object)) return false;
if (input.constructor !== Object.prototype.constructor) return false;
return true;
2020-02-20 14:38:25 -08:00
}
2020-02-27 18:57:39 -08:00
const IS_LOOKUP = new Map([
2021-08-25 08:53:42 -07:00
[ Array, isArray ],
[ Number, isNumber ],
[ String, isString ],
[ Boolean, isBoolean ],
[ Map, isMap ],
[ Set, isSet ],
[ Function, isFunction ],
[ Date, isDate ],
[ undefined, isUndefined ],
[ true, isTruthy ],
[ false, isFalsey ],
2020-02-27 18:57:39 -08:00
]);
function is (...args) {
2021-08-25 08:53:42 -07:00
args = args.flat().map((a) =>
IS_LOOKUP.get(a)
2020-02-27 18:57:39 -08:00
|| (isFunction(a) && a)
|| (isRegExp(a) && re(a))
|| equals(a)
2021-08-25 08:53:42 -07:00
);
if (args.length === 1) return (tok) => args[0](tok);
return (tok) => anyBy(args, (check) => check(tok));
2020-02-27 18:57:39 -08:00
}
function isAll (...args) {
2021-08-25 08:53:42 -07:00
args = args.flat().map((a) =>
IS_LOOKUP.get(a)
2020-02-27 18:57:39 -08:00
|| (isFunction(a) && a)
|| (isRegExp(a) && re(a))
|| equals(a)
2021-08-25 08:53:42 -07:00
);
if (args.length === 1) return (tok) => args[0](tok);
return (tok) => allBy(args, (check) => check(tok));
2020-02-27 18:57:39 -08:00
}
function isArrayOf (...args) {
2021-08-25 08:53:42 -07:00
const predicate = is(...args);
return (tok) => (isArray(tok) ? allBy(tok, predicate) : predicate(tok));
2020-02-27 18:57:39 -08:00
}
2020-02-20 14:38:25 -08:00
function isArrayOfStrings (input) { return allBy(input, isString); }
function isArrayOfNumbers (input) { return allBy(input, isNumber); }
function isArrayOfBooleans (input) { return allBy(input, isBoolean); }
function isArrayOfObjects (input) { return allBy(input, isObject); }
function isArrayOfMappables (input) { return allBy(input, isMappable); }
function isArrayOfPrimatives (input) { return allBy(input, isPrimitive); }
2020-02-27 18:57:39 -08:00
function isArrayOfFunctions (input) { return allBy(input, isFunction); }
function isArrayOfRegEx (input) { return allBy(input, isRegExp); }
function isArrayOfTruthy (input) { return allBy(input, isTruthy); }
function isArrayOfFalsey (input) { return allBy(input, isFalsey); }
function contains (...args) {
2021-08-25 08:53:42 -07:00
const predicate = is(...args);
return (tok) => (isArray(tok) ? anyBy(tok, predicate) : predicate(tok));
2020-02-27 18:57:39 -08:00
}
function containsStrings (input) { return anyBy(input, isString); }
function containsNumbers (input) { return anyBy(input, isNumber); }
function containsBooleans (input) { return anyBy(input, isBoolean); }
function containsObjects (input) { return anyBy(input, isObject); }
function containsMappables (input) { return anyBy(input, isMappable); }
function containsPrimatives (input) { return anyBy(input, isPrimitive); }
function containsFunctions (input) { return anyBy(input, isFunction); }
function containsRegEx (input) { return anyBy(input, isRegExp); }
function containsTruthy (input) { return anyBy(input, isTruthy); }
function containsFalsey (input) { return anyBy(input, isFalsey); }
2020-02-20 14:38:25 -08:00
function truthy (value) {
2021-08-25 08:53:42 -07:00
if (isMappable(value)) return !!sizeOf(value);
return !!value;
2020-02-20 14:38:25 -08:00
}
function hasOwn (obj, key) {
2021-08-25 08:53:42 -07:00
return Object.prototype.hasOwnProperty.call(obj, key);
2020-02-20 14:38:25 -08:00
}
2020-02-27 18:57:39 -08:00
function lc (str) {
2021-08-25 08:53:42 -07:00
return isString(uc) ? str.toLowerCase() : str;
2020-02-27 18:57:39 -08:00
}
function uc (str) {
2021-08-25 08:53:42 -07:00
return isString(str) ? str.toUpperCase() : str;
2020-02-27 18:57:39 -08:00
}
2020-02-20 14:38:25 -08:00
function ucfirst (input) {
2021-08-25 08:53:42 -07:00
input = String(input);
return input.charAt(0).toUpperCase() + input.slice(1);
2020-02-20 14:38:25 -08:00
}
function ucsentence (input) {
2021-08-25 08:53:42 -07:00
return input.replace(/((?:\S[^.?!]*)[.?!]*)/g, (txt) =>
txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()
2021-08-25 08:53:42 -07:00
);
2020-02-20 14:38:25 -08:00
}
function ucwords (input) {
2021-08-25 08:53:42 -07:00
return input.replace(/\w\S*/g, (word) => word.charAt(0).toUpperCase() + word.substr(1));
2020-02-20 14:38:25 -08:00
}
function merge (...sources) {
2021-08-25 08:53:42 -07:00
const result = {};
for (const source of sources) {
if (!source) continue;
for (const [ key, value ] of Object.entries(source)) {
if (isObject(value)) {
if (isObject(result[key])) {
result[key] = merge(result[key], value);
} else {
result[key] = merge(value);
}
} else {
result[key] = value;
}
}
}
return result;
2020-02-20 14:38:25 -08:00
}
function set (obj, path, value) {
2021-08-25 08:53:42 -07:00
if (path === null && path === undefined && path === '') return false;
if (isNumber(path)) path = [ String(path) ];
else if (isString(path)) {
if (hasOwn(obj, path)) {
obj[path] = value;
return obj;
}
path = path.split(/[,[\].]+?/);
}
const c = path.length - 1;
path
.filter((s) => s || s === 0)
.reduce((res, key, i) => {
if (i === c) {
res[key] = value;
return true;
}
if (isObject(res[key]) || isFunction(res[key])) return res[key];
return (res[key] = {});
}, obj);
return obj;
2020-02-20 14:38:25 -08:00
}
function get (obj, path, defaultValue) {
2021-08-25 08:53:42 -07:00
if (path === null && path === undefined && path === '') return defaultValue;
if (isNumber(path)) path = [ String(path) ];
else if (isString(path)) {
if (hasOwn(obj, path)) return obj[path];
path = path.split(/[,[\].]+?/);
}
const result = path
.filter((s) => s !== null && s !== undefined && s !== '')
.reduce((res, key) =>
((res !== null && res !== undefined) ? res[key] : res)
, obj);
return (result === undefined || result === obj) ? defaultValue : result;
2020-02-20 14:38:25 -08:00
}
function has (obj, path) {
2021-08-25 08:53:42 -07:00
if (isNumber(path)) path = [ String(path) ];
else if (isString(path)) path = String.prototype.split.call(path, /[,[\].]+?/);
let res = obj;
for (const key of path) {
if (res === null || res === undefined) return false;
if (typeof res !== 'object' && typeof res !== 'function') return false;
if (!hasOwn(res, key)) return false;
res = res[key];
}
return true;
2020-02-20 14:38:25 -08:00
}
function isMappable (collection, arrays = true) {
2021-08-25 08:53:42 -07:00
return (
(arrays && isArray(collection)) ||
2020-02-20 14:38:25 -08:00
(arrays && isSet(collection)) ||
isMap(collection) ||
collection && (typeof collection === 'object' || typeof collection === 'function')
2021-08-25 08:53:42 -07:00
);
2020-02-20 14:38:25 -08:00
}
function sizeOf (collection) {
2021-08-25 08:53:42 -07:00
if (isArray(collection) || isString(collection)) return collection.length;
if (isSet(collection) || isMap(collection)) return collection.size;
if (isObject(collection)) return Object.keys(collection).length;
return !!collection;
2020-02-20 14:38:25 -08:00
}
function keys (input) {
2021-08-25 08:53:42 -07:00
if (isArray(input)) return [ ...input.keys() ];
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
if (isSet(input)) return Array.from(input.entries(), ([ k ]) => k);
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
if (isMap(input)) return Array.from(input.keys());
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
if (isObject(input)) return Object.keys(input);
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
return [];
2020-02-20 14:38:25 -08:00
}
function values (input) {
2021-08-25 08:53:42 -07:00
if (isArray(input)) return [ ...input ];
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
if (isSet(input) || isMap(input)) return Array.from(input.values());
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
if (isObject(input)) return Object.values(input);
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
return [];
2020-02-20 14:38:25 -08:00
}
function arrayify (input) {
2021-08-25 08:53:42 -07:00
if (isArray(input)) return input;
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
if (isSet(input) || isMap(input)) return Array.from(input.values());
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
if (isObject(input)) return Object.values(input);
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
return [ input ];
2020-02-20 14:38:25 -08:00
}
2020-02-27 18:57:39 -08:00
function first (input, count = 1) {
2021-08-25 08:53:42 -07:00
if (count === 1) {
if (isArray(input) || isString(input)) return input[0];
if (isSet(input) || isObject(input)) for (const v of input) return v;
if (isMap(input)) for (const [ , v ] of input) return v;
return;
}
if (isArray(input) || isString(input)) return input.slice(0, count);
if (isSet(input)) return Array.from(input).slice(0, count);
if (isObject(input)) return Object.values(input).slice(0, count);
if (isMap(input)) return Array.from(input.values()).slice(0, count);
2020-02-27 18:57:39 -08:00
}
function last (input, count = 1) {
2021-08-25 08:53:42 -07:00
if (count === 1) {
if (isArray(input) || isString(input)) return input[input.length - 1];
}
if (isArray(input) || isString(input)) return input.slice(-count);
if (isSet(input)) return Array.from(input).slice(-count);
if (isObject(input)) return Object.values(input).slice(-count);
if (isMap(input)) return Array.from(input.values()).slice(-count);
2020-02-27 18:57:39 -08:00
}
2020-02-20 14:38:25 -08:00
function all (...args) {
2021-08-25 08:53:42 -07:00
let input;
if (args.length > 1) {
input = args;
} else {
input = arrayify(args[0]);
}
let result = input.shift();
for (const value of input) {
if (!truthy(result)) {
return false;
}
result = value;
}
return result;
2020-02-20 14:38:25 -08:00
}
function allBy (collection, predicate = null) {
2021-08-25 08:53:42 -07:00
if (!collection) return false;
if (predicate === null) {
predicate = (v) => v;
} else if (!isFunction(predicate)) {
predicate = iteratee(predicate);
}
if (isArray(collection)) {
let i = 0;
for (const value of collection) {
if (!predicate(value, i, i++)) return false;
}
return true;
}
if (isSet(collection)) {
let i = 0;
for (const item of collection) {
if (!predicate(item, i, i++)) return false;
}
return true;
}
// received a Map
if (isMap(collection)) {
let i = 0;
for (const [ key, value ] of collection.entries()) {
if (!predicate(value, key, i++)) return false;
}
return true;
}
// received an object hash
if (isObject(collection)) {
let i = 0;
for (const [ key, value ] of Object.entries(collection)) {
if (!predicate(value, key, i++)) return false;
}
return true;
}
return !!collection;
2020-02-20 14:38:25 -08:00
}
function any (...args) {
2021-08-25 08:53:42 -07:00
let input;
if (args.length > 1) {
input = args;
} else {
input = arrayify(args[0]);
}
for (const value of input) {
if (truthy(value)) {
return value;
}
}
return input[input.length - 1];
2020-02-20 14:38:25 -08:00
}
function anyBy (collection, predicate = null) {
2021-08-25 08:53:42 -07:00
if (!collection) return false;
if (predicate === null) {
predicate = (v) => v;
} else if (!isFunction(iteratee)) {
predicate = iteratee(predicate);
}
if (isArray(collection)) {
let i = 0;
for (const value of collection) {
if (predicate(value, i, i++)) return true;
}
return false;
}
if (isSet(collection)) {
let i = 0;
for (const item of collection) {
if (predicate(item, i, i++)) return true;
}
return false;
}
// received a Map
if (isMap(collection)) {
let i = 0;
for (const [ key, value ] of collection.entries()) {
if (predicate(value, key, i++)) return true;
}
return false;
}
// received an object hash
if (isObject(collection)) {
let i = 0;
for (const [ key, value ] of Object.entries(collection)) {
if (predicate(value, key, i++)) return true;
}
return false;
}
return !!collection;
2020-02-20 14:38:25 -08:00
}
function iteratee (match) {
2021-08-25 08:53:42 -07:00
if (isUndefined(match) || match === null) return Boolean;
if (isFunction(match)) return match;
if (isString(match)) {
return (o) => {
if (isArray(o)) return o.includes(match);
if (isObject(o)) return o[match];
if (isMap(o)) return o.get(match);
if (isSet(o)) return o.has(match);
if (isPrimitive(o)) return o[match];
return o === match;
};
}
if (isNumber(match)) {
return (o) => {
if (isObject(o) || isArray(o)) return o[match];
if (isMap(o)) return o.get(match);
if (isSet(o)) return o.has(match);
if (isNumber(o)) return o === match;
if (isString(o)) return Number(o) === match;
return o === match;
};
}
if (isArray(match)) {
const [ key, value ] = match;
return (o) => o[key] === value;
}
if (isObject(match)) {
// create an array of key/value iteratees
const tests = Object.entries(match).map(iteratee);
// evaluate the object against the array
return (o) => {
for (const t of tests) {
if (!t(o)) return false;
}
return true;
};
}
2020-02-20 14:38:25 -08:00
}
function sorter (match) {
2021-08-25 08:53:42 -07:00
if (isFunction(match)) return match;
function qs (a, b) {
if (a > b) return 1;
else if (b > a) return -1;
return 0;
}
if (isString(match)) {
return (a, b) => {
if (!isObject(a) && !isObject(b)) return qs(a, b);
if (!isObject(a)) return -1;
if (!isObject(b)) return 1;
return qs(a[match], b[match]);
};
}
if (isArray(match)) {
return (a, b) => {
if (!isObject(a) && !isObject(b)) return qs(a, b);
if (!isObject(a)) return -1;
if (!isObject(b)) return 1;
for (const k of match) {
const v = qs(a[k], b[k]);
if (v) return v;
}
return 0;
};
}
if (isObject(match)) {
return (a, b) => {
if (!isObject(a) && !isObject(b)) return qs(a, b);
if (!isObject(a)) return -1;
if (!isObject(b)) return 1;
for (const [ k, d ] of Object.entries(match)) {
const v = qs(a[k], b[k]) * (d < 0 ? -1 : 1);
if (v) return v;
}
return 0;
};
}
return (a, b) => {
if (!isObject(a) && !isObject(b)) return qs(a, b);
if (!isObject(a)) return -1;
if (!isObject(b)) return 1;
return 0;
};
2020-02-20 14:38:25 -08:00
}
function toPairs (object) {
2021-08-25 08:53:42 -07:00
return Object.entries(object);
2020-02-20 14:38:25 -08:00
}
function fromPairs (entries) {
2021-08-25 08:53:42 -07:00
return mapReduce(entries, ([ v, k ]) => [ v, k ]);
2020-02-20 14:38:25 -08:00
}
function slice (collection, begin, end) {
2021-08-25 08:53:42 -07:00
if (isString(collection) || isArray(collection)) return collection.slice(begin, end);
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
if (isSet(collection)) {
return new Set(Array.from(collection.values()).slice(begin, end));
}
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
if (isMap(collection)) {
return new Map(Array.from(collection.entries()).slice(begin, end));
}
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
if (isObject(collection)) {
return fromPairs(toPairs(collection).slice(begin, end));
}
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
return collection;
2020-02-20 14:38:25 -08:00
}
function sort (collection, predicate) {
2021-08-25 08:53:42 -07:00
predicate = sorter(predicate);
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
if (isArray(collection)) return [ ...collection ].sort(predicate);
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
if (isSet(collection)) {
return new Set(Array.from(collection.values()).sort(predicate));
}
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
// sort by key for maps and objects
const hashpredicate = (a, b) => predicate(a[0], b[0]);
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
if (isMap(collection)) {
return new Map(Array.from(collection.entries()).sort(hashpredicate));
}
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
if (isObject(collection)) {
return fromPairs(toPairs(collection).sort(hashpredicate));
}
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
return collection;
2020-02-20 14:38:25 -08:00
}
function map (collection, predicate) {
2021-08-25 08:53:42 -07:00
predicate = iteratee(predicate);
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
if (isArray(collection)) {
return collection.map((value, i) => predicate(value, i, i));
}
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
if (isSet(collection)) {
return Array.from(collection, (value, i) => predicate(value, i, i));
}
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
return mapReduce(collection, (value, key, index) => [ key, predicate(value, key, index) ]);
2020-02-20 14:38:25 -08:00
}
function uniq (collection, predicate = null) {
2021-08-25 08:53:42 -07:00
if (predicate === null) {
predicate = (v) => v;
} else {
predicate = iteratee(predicate);
}
const exists = new Set();
if (isArray(collection)) {
const result = [];
collection.forEach((v) => {
const match = predicate(v);
if (exists.has(match)) return;
exists.add(match);
result.push(v);
});
return result;
}
if (isSet(collection)) return new Set(collection); // really?
if (isMap(collection)) {
return new Map(Array.from(collection.entries(), ([ k, v ]) => {
const match = predicate(v);
if (exists.has(match)) return false;
exists.add(match);
return [ k, v ];
}).filter(Boolean));
}
if (isObject(collection)) {
return mapReduce(collection, ([ v, k ]) => {
const match = predicate(v);
if (exists.has(match)) return null;
exists.add(match);
return [ k, v ];
});
}
return collection;
2020-02-20 14:38:25 -08:00
}
2020-02-27 18:57:39 -08:00
function keyBy (collection, predicate) {
2021-08-25 08:53:42 -07:00
predicate = iteratee(predicate);
return mapReduce(collection, (value, key, index) =>
[ predicate(value, key, index), value ]
2021-08-25 08:53:42 -07:00
);
2020-02-27 18:57:39 -08:00
}
function groupBy (collection, predicate) {
2021-08-25 08:53:42 -07:00
predicate = iteratee(predicate);
return reduce(collection, (result, value, key, index) => {
const k = predicate(value, key, index);
(result[k] || (result[k] = [])).push(value);
return result;
}, {});
2020-02-27 18:57:39 -08:00
}
2020-02-20 14:38:25 -08:00
function filter (collection, predicate) {
2021-08-25 08:53:42 -07:00
predicate = iteratee(predicate);
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
if (isArray(collection)) {
return collection.filter((value, i) => predicate(value, i, i));
}
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
if (isSet(collection)) {
return Array.from(collection).filter((value, i) => predicate(value, i, i));
}
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
throw new Error('filter can not be applied to objects or maps, perhaps you meant to use omit?');
2020-02-20 14:38:25 -08:00
}
function omit (collection, predicate) {
2021-08-25 08:53:42 -07:00
if (isFunction(predicate)) {
return mapReduce(collection, (value, key, index) =>
(predicate(value, key, index)
? [ undefined, undefined ]
: [ key, value ])
2021-08-25 08:53:42 -07:00
);
}
if (isString(predicate)) {
predicate = [ predicate ];
}
if (!isArray(predicate)) throw new Error('omit requires a string or array of strings');
return mapReduce(collection, (value, key) =>
(predicate.includes(key)
? [ undefined, undefined ]
: [ key, value ])
2021-08-25 08:53:42 -07:00
);
2020-02-20 14:38:25 -08:00
}
function pick (collection, predicate) {
2021-08-25 08:53:42 -07:00
if (!collection) return {};
if (isFunction(predicate)) {
return mapReduce(collection, (value, key, index) =>
(predicate(value, key, index)
? [ key, value ]
: [ undefined, undefined ])
2021-08-25 08:53:42 -07:00
);
}
if (isString(predicate)) {
predicate = [ predicate ];
}
if (!isArray(predicate)) throw new Error('pick requires a string or array of strings');
return predicate.reduce((obj, key) => {
const value = get(collection, key);
if (isUndefined(value)) return obj;
return set(obj, key, value);
}, {});
2020-02-20 14:38:25 -08:00
}
function deepPick (collection, schema) {
2021-08-25 08:53:42 -07:00
if (isPrimitive(schema) && isPrimitive(collection)) return collection;
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
if (isArray(schema) && schema.length > 0) {
// collection does not match this schema tier, abort
if (!isArray(collection)) return;
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
schema = schema[0];
return collection.map((branch) => deepPick(branch, schema));
}
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
// if the schema at this tier is not an object,
// return the value at this tier only if schema is truthy
if (!isObject(schema)) return schema ? collection : undefined;
if (isPrimitive(collection)) return;
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
// if the collection isn't something we can pull data from, skip it
if (!isObject(collection) && !isFunction(collection)) return;
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
const result = {};
for (const [ key, subschema ] of Object.entries(schema)) {
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
const target = collection[key];
if (isUndefined(target)) continue;
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
const child = deepPick(target, subschema);
if (isUndefined(child)) continue;
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
result[key] = child;
}
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
return result;
2020-02-20 14:38:25 -08:00
}
function pathinate (object, delimiter = '.') {
2021-08-25 08:53:42 -07:00
const paths = [];
function descend (branch, ancest) {
if (!isObject(branch)) {
paths.push(ancest.join(delimiter));
return;
}
for (const [ k, v ] of Object.entries(branch)) {
descend(v, ancest.concat([ k ]));
}
return;
}
descend(object, []);
return uniq(paths);
2020-02-20 14:38:25 -08:00
}
/**
* Iterates over a collection and generates an object based on tuple returned from the iteratee.
*
2020-02-20 14:38:25 -08:00
* @param {Object|Array|Map|Set} collection
* @param {Function} iteratee Callback invoked for each item, receives `value, key, index`, returns `[key, value]`;
* @param cb
* @returns {Object}
2020-02-20 14:38:25 -08:00
*/
function mapReduce (collection, cb) {
2021-08-25 08:53:42 -07:00
if (!collection) return {};
const result = {};
function iterate (v, k, i) {
// return true to continue looping
const res = cb(v, k, i) || [];
if (res === false) return false;
if (!res || !isArray(res)) return true;
const [ key, value ] = res;
if (key === undefined || key === null || value === undefined) return true;
result[key] = value;
return true;
}
if (isArray(collection)) {
let i = 0;
for (const value of collection) {
if (!iterate(value, i, i++)) break;
}
return result;
}
if (isSet(collection)) {
let i = 0;
for (const item of collection) {
if (!iterate(item, i, i++)) break;
}
return result;
}
// received a Map
if (isMap(collection)) {
let i = 0;
for (const [ key, value ] of collection.entries()) {
if (!iterate(value, key, i++)) break;
}
return result;
}
// received an object hash
if (isObject(collection)) {
let i = 0;
for (const [ key, value ] of Object.entries(collection)) {
if (!iterate(value, key, i++)) break;
}
return result;
}
return result;
2020-02-20 14:38:25 -08:00
}
2020-02-27 18:57:39 -08:00
function reduce (collection, predicate, init) {
2021-08-25 08:53:42 -07:00
if (!isFunction(predicate)) throw new TypeError('Predicate must be a function');
2020-02-27 18:57:39 -08:00
2021-08-25 08:53:42 -07:00
if (isArray(collection)) return collection.reduce((r, v, i) => predicate(r, v, i, i), init);
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
if (isSet(collection)) {
return Array.from(collection).reduce((r, v, i) => predicate(r, v, i, i), init);
}
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
if (isMap(collection)) {
return Array.from(collection.entries()).reduce((prev, [ key, value ], i) => predicate(prev, value, key, i), init);
}
2020-02-20 14:38:25 -08:00
2021-08-25 08:53:42 -07:00
if (isObject(collection)) {
return Object.entries(collection).reduce((prev, [ key, value ], i) => predicate(prev, value, key, i), init);
}
2020-02-20 14:38:25 -08:00
}
function flatten (collection, depth = Infinity) {
2021-08-25 08:53:42 -07:00
if (depth <= 0) return slice(collection);
return reduce(collection,
(acc, val) => acc.concat(...(
isMappable(val)
? flatten(val, depth - 1)
: [ val ]
)),
[]
2021-08-25 08:53:42 -07:00
);
2020-02-20 14:38:25 -08:00
}
function slugify (input, delimiter = '-', separators = false) {
2021-08-25 08:53:42 -07:00
var i = separators && separators.length;
var slug = input;
var regexEscape = new RegExp(/[[/\\^$*+?.()|{}\]]/g);
var regexDelimiter = delimiter.replace(regexEscape, '\\$&');
var prohibited = new RegExp('([^a-z0-9' + regexDelimiter + '])', 'g');
var consecutive = new RegExp('(' + regexDelimiter + '+)', 'g');
var trim = new RegExp('^' + regexDelimiter + '*(.*?)' + regexDelimiter + '*$');
var sanitizer = {
// common latin
'á': 'a',
'à': 'a',
'â': 'a',
'ä': 'a',
'ã': 'a',
'æ': 'ae',
'ç': 'c',
'é': 'e',
'è': 'e',
'ê': 'e',
'ë': 'e',
'ẽ': 'e',
'í': 'i',
'ì': 'i',
'î': 'i',
'ï': 'i',
'ĩ': 'i',
'ó': 'o',
'ò': 'o',
'ô': 'o',
'ö': 'o',
'õ': 'o',
'œ': 'oe',
'ß': 'ss',
'ú': 'u',
'ù': 'u',
'û': 'u',
'ü': 'u',
'ũ': 'u',
// other diacritics
'ă': 'a',
'ắ': 'a',
'ằ': 'a',
'ẵ': 'a',
'ẳ': 'a',
'ấ': 'a',
'ầ': 'a',
'ẫ': 'a',
'ẩ': 'a',
'ǎ': 'a',
'å': 'a',
'ǻ': 'a',
'ǟ': 'a',
'ȧ': 'a',
'ǡ': 'a',
'ą': 'a',
'ā': 'a',
'ả': 'a',
'ȁ': 'a',
'ȃ': 'a',
'ạ': 'a',
'ặ': 'a',
'ậ': 'a',
'ḁ': 'a',
'ⱥ': 'a',
'ᶏ': 'a',
'ɐ': 'a',
'ɑ': 'a',
'ḃ': 'b',
'ḅ': 'b',
'ḇ': 'b',
'ƀ': 'b',
'ɓ': 'b',
'ƃ': 'b',
'ᵬ': 'b',
'ᶀ': 'b',
'þ': 'b',
'ć': 'c',
'ĉ': 'c',
'č': 'c',
'ċ': 'c',
'ḉ': 'c',
'ȼ': 'c',
'ƈ': 'c',
'ɕ': 'c',
'ď': 'd',
'ḋ': 'd',
'ḑ': 'd',
'ḍ': 'd',
'ḓ': 'd',
'ḏ': 'd',
'đ': 'd',
'ɖ': 'd',
'ɗ': 'd',
'ƌ': 'd',
'ᵭ': 'd',
'ᶁ': 'd',
'ᶑ': 'd',
'ȡ': 'd',
'∂': 'd',
'ĕ': 'e',
'ế': 'e',
'ề': 'e',
'ễ': 'e',
'ể': 'e',
'ě': 'e',
'ė': 'e',
'ȩ': 'e',
'ḝ': 'e',
'ę': 'e',
'ē': 'e',
'ḗ': 'e',
'ḕ': 'e',
'ẻ': 'e',
'ȅ': 'e',
'ȇ': 'e',
'ẹ': 'e',
'ệ': 'e',
'ḙ': 'e',
'ḛ': 'e',
'ɇ': 'e',
'ᶒ': 'e',
'ḟ': 'f',
'ƒ': 'f',
'ᵮ': 'f',
'ᶂ': 'f',
'ǵ': 'g',
'ğ': 'g',
'ĝ': 'g',
'ǧ': 'g',
'ġ': 'g',
'ģ': 'g',
'ḡ': 'g',
'ǥ': 'g',
'ɠ': 'g',
'': 'g',
'ĥ': 'h',
'ȟ': 'h',
'ḧ': 'h',
'ḣ': 'h',
'ḩ': 'h',
'ḥ': 'h',
'ḫ': 'h',
'ẖ': 'h',
'ħ': 'h',
'ⱨ': 'h',
'ĭ': 'i',
'ǐ': 'i',
'ḯ': 'i',
'į': 'i',
'ī': 'i',
'ỉ': 'i',
'ȉ': 'i',
'ȋ': 'i',
'ị': 'i',
'ḭ': 'i',
'ɨ': 'i',
'ᵻ': 'i',
'ᶖ': 'i',
'i': 'i',
'ı': 'i',
'ĵ': 'j',
'ɉ': 'j',
'ǰ': 'j',
'ȷ': 'j',
'ʝ': 'j',
'ɟ': 'j',
'ʄ': 'j',
'ḱ': 'k',
'ǩ': 'k',
'ķ': 'k',
'ḳ': 'k',
'ḵ': 'k',
'ƙ': 'k',
'ⱪ': 'k',
'ᶄ': 'k',
'ĺ': 'l',
'ľ': 'l',
'ļ': 'l',
'ḷ': 'l',
'ḹ': 'l',
'ḽ': 'l',
'ḻ': 'l',
'ł': 'l',
'ŀ': 'l',
'ƚ': 'l',
'ⱡ': 'l',
'ɫ': 'l',
'ɬ': 'l',
'ᶅ': 'l',
'ɭ': 'l',
'ȴ': 'l',
'ḿ': 'm',
'ṁ': 'm',
'ṃ': 'm',
'ᵯ': 'm',
'ᶆ': 'm',
'ɱ': 'm',
'ń': 'n',
'ǹ': 'n',
'ň': 'n',
'ñ': 'n',
'ṅ': 'n',
'ņ': 'n',
'ṇ': 'n',
'ṋ': 'n',
'ṉ': 'n',
'n̈': 'n',
'ɲ': 'n',
'ƞ': 'n',
'ŋ': 'n',
'ᵰ': 'n',
'ᶇ': 'n',
'ɳ': 'n',
'ȵ': 'n',
'ŏ': 'o',
'ố': 'o',
'ồ': 'o',
'ỗ': 'o',
'ổ': 'o',
'ǒ': 'o',
'ȫ': 'o',
'ő': 'o',
'ṍ': 'o',
'ṏ': 'o',
'ȭ': 'o',
'ȯ': 'o',
'͘o͘': 'o',
'ȱ': 'o',
'ø': 'o',
'ǿ': 'o',
'ǫ': 'o',
'ǭ': 'o',
'ō': 'o',
'ṓ': 'o',
'ṑ': 'o',
'ỏ': 'o',
'ȍ': 'o',
'ȏ': 'o',
'ơ': 'o',
'ớ': 'o',
'ờ': 'o',
'ỡ': 'o',
'ở': 'o',
'ợ': 'o',
'ọ': 'o',
'ộ': 'o',
'ɵ': 'o',
'ɔ': 'o',
'ṕ': 'p',
'ṗ': 'p',
'ᵽ': 'p',
'ƥ': 'p',
'p̃': 'p',
'ᵱ': 'p',
'ᶈ': 'p',
'ɋ': 'q',
'ƣ': 'q',
'ʠ': 'q',
'ŕ': 'r',
'ř': 'r',
'ṙ': 'r',
'ŗ': 'r',
'ȑ': 'r',
'ȓ': 'r',
'ṛ': 'r',
'ṝ': 'r',
'ṟ': 'r',
'ɍ': 'r',
'ɽ': 'r',
'ᵲ': 'r',
'ᶉ': 'r',
'ɼ': 'r',
'ɾ': 'r',
'ᵳ': 'r',
'ś': 's',
'ṥ': 's',
'ŝ': 's',
'š': 's',
'ṧ': 's',
'ṡẛ': 's',
'ş': 's',
'ṣ': 's',
'ṩ': 's',
'ș': 's',
's̩': 's',
'ᵴ': 's',
'ᶊ': 's',
'ʂ': 's',
'ȿ': 's',
'ť': 't',
'ṫ': 't',
'ţ': 't',
'ṭ': 't',
'ț': 't',
'ṱ': 't',
'ṯ': 't',
'ŧ': 't',
'ⱦ': 't',
'ƭ': 't',
'ʈ': 't',
'̈ẗ': 't',
'ᵵ': 't',
'ƫ': 't',
'ȶ': 't',
'ŭ': 'u',
'ǔ': 'u',
'ů': 'u',
'ǘ': 'u',
'ǜ': 'u',
'ǚ': 'u',
'ǖ': 'u',
'ű': 'u',
'ṹ': 'u',
'ų': 'u',
'ū': 'u',
'ṻ': 'u',
'ủ': 'u',
'ȕ': 'u',
'ȗ': 'u',
'ư': 'u',
'ứ': 'u',
'ừ': 'u',
'ữ': 'u',
'ử': 'u',
'ự': 'u',
'ụ': 'u',
'ṳ': 'u',
'ṷ': 'u',
'ṵ': 'u',
'ʉ': 'u',
'ᵾ': 'u',
'ᶙ': 'u',
'ṽ': 'v',
'ṿ': 'v',
'ʋ': 'v',
'': 'v',
'ⱴ': 'v',
'ẃ': 'w',
'ẁ': 'w',
'ŵ': 'w',
'ẅ': 'w',
'ẇ': 'w',
'ẉ': 'w',
'ẘ': 'w',
'ẍ': 'x',
'ẋ': 'x',
'ᶍ': 'x',
'ý': 'y',
'ỳ': 'y',
'ŷ': 'y',
'ẙ': 'y',
'ÿ': 'y',
'ỹ': 'y',
'ẏ': 'y',
'ȳ': 'y',
'ỷ': 'y',
'ỵ': 'y',
'ɏ': 'y',
'ƴ': 'y',
'ʏ': 'y',
'ź': 'z',
'ẑ': 'z',
'ž': 'z',
'ż': 'z',
'ẓ': 'z',
'ẕ': 'z',
'ƶ': 'z',
'ȥ': 'z',
'ⱬ': 'z',
'ᵶ': 'z',
'ᶎ': 'z',
'ʐ': 'z',
'ʑ': 'z',
'ɀ': 'z',
// greek
'α': 'a',
'β': 'b',
'γ': 'g',
'ɣ': 'g',
'δ': 'd',
'ð': 'd',
'ε': 'e',
'ζ': 'z',
'η': 'i',
'θ': 'th',
'ι': 'i',
'κ': 'k',
'λ': 'l',
'μ': 'm',
'µ': 'm',
'ν': 'n',
'ξ': 'x',
'ο': 'o',
'π': 'p',
'ρ': 'r',
'σ': 's',
'ς': 's',
'τ': 't',
'υ': 'u', // official rule: if preceeded by 'α' OR 'ε' => 'v', by 'ο' => 'u', else => 'i'
'φ': 'f',
'χ': 'ch',
'ψ': 'ps',
'ω': 'o',
// greek diacritics
'ᾳ': 'a',
'ά': 'a',
'ὰ': 'a',
'ᾴ': 'a',
'ᾲ': 'a',
'ᾶ': 'a',
'ᾷ': 'a',
'ἀ': 'a',
'ᾀ': 'a',
'ἄ': 'a',
'ᾄ': 'a',
'ἂ': 'a',
'ᾂ': 'a',
'ἆ': 'a',
'ᾆ': 'a',
'ἁ': 'a',
'ᾁ': 'a',
'ἅ': 'a',
'ᾅ': 'a',
'ἃ': 'a',
'ᾃ': 'a',
'ἇ': 'a',
'ᾇ': 'a',
'ᾱ': 'a',
'ᾰ': 'a',
'έ': 'e',
'ὲ': 'e',
'ἐ': 'e',
'ἔ': 'e',
'ἒ': 'e',
'ἑ': 'e',
'ἕ': 'e',
'ἓ': 'e',
'ῃ': 'i',
'ή': 'i',
'ὴ': 'i',
'ῄ': 'i',
'ῂ': 'i',
'ῆ': 'i',
'ῇ': 'i',
'ἠ': 'i',
'ᾐ': 'i',
'ἤ': 'i',
'ᾔ': 'i',
'ἢ': 'i',
'ᾒ': 'i',
'ἦ': 'i',
'ᾖ': 'i',
'ἡ': 'i',
'ᾑ': 'i',
'ἥ': 'i',
'ᾕ': 'i',
'ἣ': 'i',
'ᾓ': 'i',
'ἧ': 'i',
'ᾗ': 'i',
'ί': 'i',
'ὶ': 'i',
'ῖ': 'i',
'ἰ': 'i',
'ἴ': 'i',
'ἲ': 'i',
'ἶ': 'i',
'ἱ': 'i',
'ἵ': 'i',
'ἳ': 'i',
'ἷ': 'i',
'ϊ': 'i',
'ΐ': 'i',
'ῒ': 'i',
'ῗ': 'i',
'ῑ': 'i',
'ῐ': 'i',
'ό': 'o',
'ὸ': 'o',
'ὀ': 'o',
'ὄ': 'o',
'ὂ': 'o',
'ὁ': 'o',
'ὅ': 'o',
'ὃ': 'o',
'ύ': 'u',
'ὺ': 'u',
'ῦ': 'u',
'ὐ': 'u',
'ὔ': 'u',
'ὒ': 'u',
'ὖ': 'u',
'ὑ': 'u',
'ὕ': 'u',
'ὓ': 'u',
'ὗ': 'u',
'ϋ': 'u',
'ΰ': 'u',
'ῢ': 'u',
'ῧ': 'u',
'ῡ': 'u',
'ῠ': 'u',
'ῳ': 'o',
'ώ': 'o',
'ῴ': 'o',
'ὼ': 'o',
'ῲ': 'o',
'ῶ': 'o',
'ῷ': 'o',
'ὠ': 'o',
'ᾠ': 'o',
'ὤ': 'o',
'ᾤ': 'o',
'ὢ': 'o',
'ᾢ': 'o',
'ὦ': 'o',
'ᾦ': 'o',
'ὡ': 'o',
'ᾡ': 'o',
'ὥ': 'o',
'ᾥ': 'o',
'ὣ': 'o',
'ᾣ': 'o',
'ὧ': 'o',
'ᾧ': 'o',
'ῤ': 'r',
'ῥ': 'r',
// cyrillic (russian)
'а': 'a',
'б': 'b',
'в': 'v',
'г': 'g',
'д': 'd',
'е': 'e',
'ё': 'e',
'ж': 'zh',
'з': 'z',
'и': 'i',
'й': 'j',
'к': 'k',
'л': 'l',
'м': 'm',
'н': 'n',
'о': 'o',
'п': 'p',
'р': 'r',
'с': 's',
'т': 't',
'у': 'u',
'ф': 'f',
'х': 'h',
'ц': 'ts',
'ч': 'ch',
'ш': 'sh',
'щ': 'sh',
'ъ': '',
'ы': 'i',
'ь': '',
'э': 'e',
'ю': 'yu',
'я': 'ya',
// ---
'і': 'j',
'ѳ': 'f',
'ѣ': 'e',
'ѵ': 'i',
'ѕ': 'z',
'ѯ': 'ks',
'ѱ': 'ps',
'ѡ': 'o',
'ѫ': 'yu',
'ѧ': 'ya',
'ѭ': 'yu',
'ѩ': 'ya',
// currency
'₳': 'ARA',
'฿': 'THB',
'₵': 'GHS',
'¢': 'c',
'₡': 'CRC',
'₢': 'Cr',
'₠': 'XEU',
'$': 'USD',
'₫': 'VND',
'৳': 'BDT',
'₯': 'GRD',
'€': 'EUR',
'₣': 'FRF',
'₲': 'PYG',
'₴': 'HRN',
'₭': 'LAK',
'₦': 'NGN',
'₧': 'ESP',
'₱': 'PhP',
'£': 'GBP',
'₤': 'GBP',
'₨': 'Rs',
'₪': 'NS',
'₮': 'MNT',
'₩': 'WON',
'¥': 'YEN',
'៛': 'KHR',
// separators
'': delimiter,
'—': delimiter,
'―': delimiter,
'~': delimiter,
'/': delimiter,
'\\': delimiter,
'|': delimiter,
'+': delimiter,
'': delimiter,
'': delimiter,
'\'': delimiter,
' ': delimiter,
// permitted by default but can be overridden
'-': '-',
'_': '_',
};
// add any user-defined separator elements
if (separators) {
for (i; i >= 0; --i) {
sanitizer[separators[i]] = delimiter;
}
}
// do all the replacements
slug = slug.toLowerCase(); // if we don't do this, add the uppercase versions to the sanitizer plus inlcude A-Z in the prohibited filter
slug = slug.replace(prohibited, (match) => sanitizer[match] || '');
slug = slug.replace(consecutive, delimiter);
slug = slug.replace(trim, '$1');
return slug;
2020-02-20 14:38:25 -08:00
}
exports.all = all;
exports.allBy = allBy;
2020-02-27 18:57:39 -08:00
exports.allOf = allOf;
2020-02-20 14:38:25 -08:00
exports.any = any;
exports.anyBy = anyBy;
2020-02-27 18:57:39 -08:00
exports.anyOf = anyOf;
2020-02-20 14:38:25 -08:00
exports.arrayify = arrayify;
2020-02-27 18:57:39 -08:00
exports.contains = contains;
exports.containsBooleans = containsBooleans;
exports.containsFalsey = containsFalsey;
exports.containsFunctions = containsFunctions;
exports.containsMappables = containsMappables;
exports.containsNumbers = containsNumbers;
exports.containsObjects = containsObjects;
exports.containsPrimatives = containsPrimatives;
exports.containsRegEx = containsRegEx;
exports.containsStrings = containsStrings;
exports.containsTruthy = containsTruthy;
2020-02-20 14:38:25 -08:00
exports.deepPick = deepPick;
2020-02-27 18:57:39 -08:00
exports.equals = equals;
2020-02-20 14:38:25 -08:00
exports.filter = filter;
2020-02-27 18:57:39 -08:00
exports.first = first;
2020-02-20 14:38:25 -08:00
exports.flatten = flatten;
exports.fromPairs = fromPairs;
exports.get = get;
2020-02-27 18:57:39 -08:00
exports.groupBy = groupBy;
2020-02-20 14:38:25 -08:00
exports.has = has;
exports.hasOwn = hasOwn;
2020-02-27 18:57:39 -08:00
exports.is = is;
exports.isAll = isAll;
2020-02-20 14:38:25 -08:00
exports.isArray = isArray;
2020-02-27 18:57:39 -08:00
exports.isArrayOf = isArrayOf;
2020-02-20 14:38:25 -08:00
exports.isArrayOfBooleans = isArrayOfBooleans;
2020-02-27 18:57:39 -08:00
exports.isArrayOfFalsey = isArrayOfFalsey;
exports.isArrayOfFunctions = isArrayOfFunctions;
2020-02-20 14:38:25 -08:00
exports.isArrayOfMappables = isArrayOfMappables;
exports.isArrayOfNumbers = isArrayOfNumbers;
exports.isArrayOfObjects = isArrayOfObjects;
exports.isArrayOfPrimatives = isArrayOfPrimatives;
2020-02-27 18:57:39 -08:00
exports.isArrayOfRegEx = isArrayOfRegEx;
2020-02-20 14:38:25 -08:00
exports.isArrayOfStrings = isArrayOfStrings;
2020-02-27 18:57:39 -08:00
exports.isArrayOfTruthy = isArrayOfTruthy;
2020-02-20 14:38:25 -08:00
exports.isBoolean = isBoolean;
2020-02-27 18:57:39 -08:00
exports.isDate = isDate;
exports.isFalsey = isFalsey;
2020-02-20 14:38:25 -08:00
exports.isFunction = isFunction;
exports.isMap = isMap;
exports.isMappable = isMappable;
exports.isNull = isNull;
exports.isNumber = isNumber;
exports.isObject = isObject;
exports.isPrimitive = isPrimitive;
2020-02-27 18:57:39 -08:00
exports.isRegExp = isRegExp;
2020-02-20 14:38:25 -08:00
exports.isSet = isSet;
exports.isString = isString;
2020-02-27 18:57:39 -08:00
exports.isTruthy = isTruthy;
2020-02-20 14:38:25 -08:00
exports.isUndefined = isUndefined;
exports.iteratee = iteratee;
2020-02-27 18:57:39 -08:00
exports.keyBy = keyBy;
2020-02-20 14:38:25 -08:00
exports.keys = keys;
2020-02-27 18:57:39 -08:00
exports.last = last;
exports.lc = lc;
2020-02-20 14:38:25 -08:00
exports.map = map;
exports.mapReduce = mapReduce;
exports.merge = merge;
exports.omit = omit;
exports.pathinate = pathinate;
exports.pick = pick;
2020-02-27 18:57:39 -08:00
exports.re = re;
2020-02-20 14:38:25 -08:00
exports.reduce = reduce;
exports.set = set;
exports.sizeOf = sizeOf;
exports.slice = slice;
exports.slugify = slugify;
exports.sort = sort;
exports.sorter = sorter;
exports.toPairs = toPairs;
exports.truthy = truthy;
2020-02-27 18:57:39 -08:00
exports.uc = uc;
2020-02-20 14:38:25 -08:00
exports.ucfirst = ucfirst;
exports.ucsentence = ucsentence;
exports.ucwords = ucwords;
exports.uniq = uniq;
exports.values = values;