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(),
|
|
|
|
|
);
|
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 ],
|
|
|
|
|
);
|
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 ]),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 ]),
|
|
|
|
|
);
|
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 ]),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
* @param {Object|Array|Map|Set} collection
|
|
|
|
|
* @param {Function} iteratee Callback invoked for each item, receives `value, key, index`, returns `[key, value]`;
|
|
|
|
|
* @return {Object}
|
|
|
|
|
*/
|
|
|
|
|
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 ]
|
|
|
|
|
)),
|
|
|
|
|
[],
|
|
|
|
|
);
|
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;
|