mirror of
https://github.com/GenderDysphoria/GenderDysphoria.fyi.git
synced 2025-01-31 15:26:17 +00:00
1655 lines
34 KiB
JavaScript
1655 lines
34 KiB
JavaScript
/**
|
||
*
|
||
* handlebar-kit
|
||
*
|
||
* Copyright (c) 2020, Jocelyn Badgley
|
||
*
|
||
* 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:
|
||
*
|
||
* The above copyright notice and this permission notice shall be
|
||
* included in all copies or substantial portions of the Software.
|
||
*
|
||
* 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.
|
||
*
|
||
* 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 });
|
||
|
||
function equals (value) {
|
||
value = uc(value);
|
||
return (tok) => uc(tok) === value;
|
||
}
|
||
|
||
function re (pattern) {
|
||
if (isString(pattern)) pattern = new RegExp(pattern);
|
||
return (tok) => !!String(tok).match(pattern);
|
||
}
|
||
|
||
function anyOf (...args) {
|
||
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));
|
||
}
|
||
|
||
function allOf (...args) {
|
||
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));
|
||
}
|
||
|
||
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; }
|
||
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;
|
||
|
||
function isPrimitive (input) {
|
||
switch (typeof input) {
|
||
case 'string':
|
||
case 'number':
|
||
case 'boolean':
|
||
return true;
|
||
default:
|
||
return false;
|
||
}
|
||
}
|
||
|
||
function isObject (input) {
|
||
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;
|
||
}
|
||
|
||
|
||
const IS_LOOKUP = new Map([
|
||
[ Array, isArray ],
|
||
[ Number, isNumber ],
|
||
[ String, isString ],
|
||
[ Boolean, isBoolean ],
|
||
[ Map, isMap ],
|
||
[ Set, isSet ],
|
||
[ Function, isFunction ],
|
||
[ Date, isDate ],
|
||
[ undefined, isUndefined ],
|
||
[ true, isTruthy ],
|
||
[ false, isFalsey ],
|
||
]);
|
||
|
||
function is (...args) {
|
||
args = args.flat().map((a) =>
|
||
IS_LOOKUP.get(a)
|
||
|| (isFunction(a) && a)
|
||
|| (isRegExp(a) && re(a))
|
||
|| equals(a),
|
||
);
|
||
if (args.length === 1) return (tok) => args[0](tok);
|
||
return (tok) => anyBy(args, (check) => check(tok));
|
||
}
|
||
|
||
function isAll (...args) {
|
||
args = args.flat().map((a) =>
|
||
IS_LOOKUP.get(a)
|
||
|| (isFunction(a) && a)
|
||
|| (isRegExp(a) && re(a))
|
||
|| equals(a),
|
||
);
|
||
if (args.length === 1) return (tok) => args[0](tok);
|
||
return (tok) => allBy(args, (check) => check(tok));
|
||
}
|
||
|
||
function isArrayOf (...args) {
|
||
const predicate = is(...args);
|
||
return (tok) => (isArray(tok) ? allBy(tok, predicate) : predicate(tok));
|
||
}
|
||
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); }
|
||
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) {
|
||
const predicate = is(...args);
|
||
return (tok) => (isArray(tok) ? anyBy(tok, predicate) : predicate(tok));
|
||
}
|
||
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); }
|
||
|
||
function truthy (value) {
|
||
if (isMappable(value)) return !!sizeOf(value);
|
||
return !!value;
|
||
}
|
||
|
||
function hasOwn (obj, key) {
|
||
return Object.prototype.hasOwnProperty.call(obj, key);
|
||
}
|
||
|
||
function lc (str) {
|
||
return isString(uc) ? str.toLowerCase() : str;
|
||
}
|
||
|
||
function uc (str) {
|
||
return isString(str) ? str.toUpperCase() : str;
|
||
}
|
||
|
||
function ucfirst (input) {
|
||
input = String(input);
|
||
return input.charAt(0).toUpperCase() + input.slice(1);
|
||
}
|
||
|
||
function ucsentence (input) {
|
||
return input.replace(/((?:\S[^.?!]*)[.?!]*)/g, (txt) =>
|
||
txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(),
|
||
);
|
||
}
|
||
|
||
function ucwords (input) {
|
||
return input.replace(/\w\S*/g, (word) => word.charAt(0).toUpperCase() + word.substr(1));
|
||
}
|
||
|
||
function merge (...sources) {
|
||
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;
|
||
}
|
||
|
||
function set (obj, path, value) {
|
||
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;
|
||
}
|
||
|
||
function get (obj, path, defaultValue) {
|
||
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;
|
||
}
|
||
|
||
function has (obj, path) {
|
||
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;
|
||
}
|
||
|
||
function isMappable (collection, arrays = true) {
|
||
return (
|
||
(arrays && isArray(collection)) ||
|
||
(arrays && isSet(collection)) ||
|
||
isMap(collection) ||
|
||
collection && (typeof collection === 'object' || typeof collection === 'function')
|
||
);
|
||
}
|
||
|
||
function sizeOf (collection) {
|
||
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;
|
||
}
|
||
|
||
function keys (input) {
|
||
if (isArray(input)) return [ ...input.keys() ];
|
||
|
||
if (isSet(input)) return Array.from(input.entries(), ([ k ]) => k);
|
||
|
||
if (isMap(input)) return Array.from(input.keys());
|
||
|
||
if (isObject(input)) return Object.keys(input);
|
||
|
||
return [];
|
||
}
|
||
|
||
function values (input) {
|
||
if (isArray(input)) return [ ...input ];
|
||
|
||
if (isSet(input) || isMap(input)) return Array.from(input.values());
|
||
|
||
if (isObject(input)) return Object.values(input);
|
||
|
||
return [];
|
||
}
|
||
|
||
function arrayify (input) {
|
||
if (isArray(input)) return input;
|
||
|
||
if (isSet(input) || isMap(input)) return Array.from(input.values());
|
||
|
||
if (isObject(input)) return Object.values(input);
|
||
|
||
return [ input ];
|
||
}
|
||
|
||
function first (input, count = 1) {
|
||
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);
|
||
}
|
||
|
||
function last (input, count = 1) {
|
||
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);
|
||
}
|
||
|
||
function all (...args) {
|
||
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;
|
||
}
|
||
|
||
function allBy (collection, predicate = null) {
|
||
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;
|
||
}
|
||
|
||
function any (...args) {
|
||
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];
|
||
}
|
||
|
||
function anyBy (collection, predicate = null) {
|
||
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;
|
||
}
|
||
|
||
function iteratee (match) {
|
||
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;
|
||
};
|
||
}
|
||
}
|
||
|
||
function sorter (match) {
|
||
|
||
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;
|
||
};
|
||
}
|
||
|
||
function toPairs (object) {
|
||
return Object.entries(object);
|
||
}
|
||
|
||
function fromPairs (entries) {
|
||
return mapReduce(entries, ([ v, k ]) => [ v, k ]);
|
||
}
|
||
|
||
function slice (collection, begin, end) {
|
||
if (isString(collection) || isArray(collection)) return collection.slice(begin, end);
|
||
|
||
if (isSet(collection)) {
|
||
return new Set(Array.from(collection.values()).slice(begin, end));
|
||
}
|
||
|
||
if (isMap(collection)) {
|
||
return new Map(Array.from(collection.entries()).slice(begin, end));
|
||
}
|
||
|
||
if (isObject(collection)) {
|
||
return fromPairs(toPairs(collection).slice(begin, end));
|
||
}
|
||
|
||
return collection;
|
||
}
|
||
|
||
function sort (collection, predicate) {
|
||
|
||
predicate = sorter(predicate);
|
||
|
||
if (isArray(collection)) return [ ...collection ].sort(predicate);
|
||
|
||
if (isSet(collection)) {
|
||
return new Set(Array.from(collection.values()).sort(predicate));
|
||
}
|
||
|
||
// sort by key for maps and objects
|
||
const hashpredicate = (a, b) => predicate(a[0], b[0]);
|
||
|
||
if (isMap(collection)) {
|
||
return new Map(Array.from(collection.entries()).sort(hashpredicate));
|
||
}
|
||
|
||
if (isObject(collection)) {
|
||
return fromPairs(toPairs(collection).sort(hashpredicate));
|
||
}
|
||
|
||
return collection;
|
||
}
|
||
|
||
function map (collection, predicate) {
|
||
predicate = iteratee(predicate);
|
||
|
||
if (isArray(collection)) {
|
||
return collection.map((value, i) => predicate(value, i, i));
|
||
}
|
||
|
||
if (isSet(collection)) {
|
||
return Array.from(collection, (value, i) => predicate(value, i, i));
|
||
}
|
||
|
||
return mapReduce(collection, (value, key, index) => [ key, predicate(value, key, index) ]);
|
||
}
|
||
|
||
function uniq (collection, predicate = null) {
|
||
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;
|
||
}
|
||
|
||
function keyBy (collection, predicate) {
|
||
predicate = iteratee(predicate);
|
||
return mapReduce(collection, (value, key, index) =>
|
||
[ predicate(value, key, index), value ],
|
||
);
|
||
}
|
||
|
||
function groupBy (collection, predicate) {
|
||
predicate = iteratee(predicate);
|
||
return reduce(collection, (result, value, key, index) => {
|
||
const k = predicate(value, key, index);
|
||
(result[k] || (result[k] = [])).push(value);
|
||
return result;
|
||
}, {});
|
||
}
|
||
|
||
function filter (collection, predicate) {
|
||
predicate = iteratee(predicate);
|
||
|
||
if (isArray(collection)) {
|
||
return collection.filter((value, i) => predicate(value, i, i));
|
||
}
|
||
|
||
if (isSet(collection)) {
|
||
return Array.from(collection).filter((value, i) => predicate(value, i, i));
|
||
}
|
||
|
||
throw new Error('filter can not be applied to objects or maps, perhaps you meant to use omit?');
|
||
}
|
||
|
||
function omit (collection, predicate) {
|
||
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 ]),
|
||
);
|
||
}
|
||
|
||
function pick (collection, predicate) {
|
||
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);
|
||
}, {});
|
||
}
|
||
|
||
|
||
function deepPick (collection, schema) {
|
||
if (isPrimitive(schema) && isPrimitive(collection)) return collection;
|
||
|
||
if (isArray(schema) && schema.length > 0) {
|
||
// collection does not match this schema tier, abort
|
||
if (!isArray(collection)) return;
|
||
|
||
schema = schema[0];
|
||
return collection.map((branch) => deepPick(branch, schema));
|
||
}
|
||
|
||
// 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;
|
||
|
||
// if the collection isn't something we can pull data from, skip it
|
||
if (!isObject(collection) && !isFunction(collection)) return;
|
||
|
||
const result = {};
|
||
for (const [ key, subschema ] of Object.entries(schema)) {
|
||
|
||
const target = collection[key];
|
||
if (isUndefined(target)) continue;
|
||
|
||
const child = deepPick(target, subschema);
|
||
if (isUndefined(child)) continue;
|
||
|
||
result[key] = child;
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
|
||
|
||
function pathinate (object, delimiter = '.') {
|
||
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);
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* 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) {
|
||
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;
|
||
}
|
||
|
||
function reduce (collection, predicate, init) {
|
||
if (!isFunction(predicate)) throw new TypeError('Predicate must be a function');
|
||
|
||
if (isArray(collection)) return collection.reduce((r, v, i) => predicate(r, v, i, i), init);
|
||
|
||
if (isSet(collection)) {
|
||
return Array.from(collection).reduce((r, v, i) => predicate(r, v, i, i), init);
|
||
}
|
||
|
||
if (isMap(collection)) {
|
||
return Array.from(collection.entries()).reduce((prev, [ key, value ], i) => predicate(prev, value, key, i), init);
|
||
}
|
||
|
||
if (isObject(collection)) {
|
||
return Object.entries(collection).reduce((prev, [ key, value ], i) => predicate(prev, value, key, i), init);
|
||
}
|
||
}
|
||
|
||
function flatten (collection, depth = Infinity) {
|
||
if (depth <= 0) return slice(collection);
|
||
return reduce(collection,
|
||
(acc, val) => acc.concat(...(
|
||
isMappable(val)
|
||
? flatten(val, depth - 1)
|
||
: [ val ]
|
||
)),
|
||
[],
|
||
);
|
||
}
|
||
|
||
function slugify (input, delimiter = '-', separators = false) {
|
||
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;
|
||
}
|
||
|
||
exports.all = all;
|
||
exports.allBy = allBy;
|
||
exports.allOf = allOf;
|
||
exports.any = any;
|
||
exports.anyBy = anyBy;
|
||
exports.anyOf = anyOf;
|
||
exports.arrayify = arrayify;
|
||
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;
|
||
exports.deepPick = deepPick;
|
||
exports.equals = equals;
|
||
exports.filter = filter;
|
||
exports.first = first;
|
||
exports.flatten = flatten;
|
||
exports.fromPairs = fromPairs;
|
||
exports.get = get;
|
||
exports.groupBy = groupBy;
|
||
exports.has = has;
|
||
exports.hasOwn = hasOwn;
|
||
exports.is = is;
|
||
exports.isAll = isAll;
|
||
exports.isArray = isArray;
|
||
exports.isArrayOf = isArrayOf;
|
||
exports.isArrayOfBooleans = isArrayOfBooleans;
|
||
exports.isArrayOfFalsey = isArrayOfFalsey;
|
||
exports.isArrayOfFunctions = isArrayOfFunctions;
|
||
exports.isArrayOfMappables = isArrayOfMappables;
|
||
exports.isArrayOfNumbers = isArrayOfNumbers;
|
||
exports.isArrayOfObjects = isArrayOfObjects;
|
||
exports.isArrayOfPrimatives = isArrayOfPrimatives;
|
||
exports.isArrayOfRegEx = isArrayOfRegEx;
|
||
exports.isArrayOfStrings = isArrayOfStrings;
|
||
exports.isArrayOfTruthy = isArrayOfTruthy;
|
||
exports.isBoolean = isBoolean;
|
||
exports.isDate = isDate;
|
||
exports.isFalsey = isFalsey;
|
||
exports.isFunction = isFunction;
|
||
exports.isMap = isMap;
|
||
exports.isMappable = isMappable;
|
||
exports.isNull = isNull;
|
||
exports.isNumber = isNumber;
|
||
exports.isObject = isObject;
|
||
exports.isPrimitive = isPrimitive;
|
||
exports.isRegExp = isRegExp;
|
||
exports.isSet = isSet;
|
||
exports.isString = isString;
|
||
exports.isTruthy = isTruthy;
|
||
exports.isUndefined = isUndefined;
|
||
exports.iteratee = iteratee;
|
||
exports.keyBy = keyBy;
|
||
exports.keys = keys;
|
||
exports.last = last;
|
||
exports.lc = lc;
|
||
exports.map = map;
|
||
exports.mapReduce = mapReduce;
|
||
exports.merge = merge;
|
||
exports.omit = omit;
|
||
exports.pathinate = pathinate;
|
||
exports.pick = pick;
|
||
exports.re = re;
|
||
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;
|
||
exports.uc = uc;
|
||
exports.ucfirst = ucfirst;
|
||
exports.ucsentence = ucsentence;
|
||
exports.ucwords = ucwords;
|
||
exports.uniq = uniq;
|
||
exports.values = values;
|