diff --git a/dist/_30s.es5.js b/dist/_30s.es5.js index cbcbf9aa0..e58fa4e25 100644 --- a/dist/_30s.es5.js +++ b/dist/_30s.es5.js @@ -114,9 +114,65 @@ throw new TypeError("Invalid attempt to destructure non-iterable instance"); } + var fs = typeof require !== "undefined" && require('fs'); + var crypto = typeof require !== "undefined" && require('crypto'); - var fs = typeof require !== "undefined" && require('fs'); + var CSVToArray = function CSVToArray(data) { + var delimiter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ','; + var omitFirstRow = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + return data.slice(omitFirstRow ? data.indexOf('\n') + 1 : 0).split('\n').map(function (v) { + return v.split(delimiter); + }); + }; + + var CSVToJSON = function CSVToJSON(data) { + var delimiter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ','; + var titles = data.slice(0, data.indexOf('\n')).split(delimiter); + return data.slice(data.indexOf('\n') + 1).split('\n').map(function (v) { + var values = v.split(delimiter); + return titles.reduce(function (obj, title, index) { + return obj[title] = values[index], obj; + }, {}); + }); + }; + + var JSONToFile = function JSONToFile(obj, filename) { + return fs.writeFile("".concat(filename, ".json"), JSON.stringify(obj, null, 2)); + }; + + var JSONtoCSV = function JSONtoCSV(arr, columns) { + var delimiter = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ','; + return [columns.join(delimiter)].concat(_toConsumableArray(arr.map(function (obj) { + return columns.reduce(function (acc, key) { + return "".concat(acc).concat(!acc.length ? '' : delimiter, "\"").concat(!obj[key] ? '' : obj[key], "\""); + }, ''); + }))).join('\n'); + }; + + var RGBToHex = function RGBToHex(r, g, b) { + return ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0'); + }; + + var URLJoin = function URLJoin() { + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + return args.join('/').replace(/[\/]+/g, '/').replace(/^(.+):\//, '$1://').replace(/^file:/, 'file:/').replace(/\/(\?|&|#[^!])/g, '$1').replace(/\?/g, '&').replace('&', '?'); + }; + + var UUIDGeneratorBrowser = function UUIDGeneratorBrowser() { + return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, function (c) { + return (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16); + }); + }; + + var UUIDGeneratorNode = function UUIDGeneratorNode() { + return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, function (c) { + return (c ^ crypto.randomBytes(1)[0] & 15 >> c / 4).toString(16); + }); + }; var all = function all(arr) { var fn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Boolean; @@ -158,8 +214,8 @@ var ary = function ary(fn, n) { return function () { - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; + for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + args[_key2] = arguments[_key2]; } return fn.apply(void 0, _toConsumableArray(args.slice(0, n))); @@ -172,8 +228,8 @@ var attempt = function attempt(fn) { try { - for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { - args[_key2 - 1] = arguments[_key2]; + for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { + args[_key3 - 1] = arguments[_key3]; } return fn.apply(void 0, args); @@ -183,8 +239,8 @@ }; var average = function average() { - for (var _len3 = arguments.length, nums = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { - nums[_key3] = arguments[_key3]; + for (var _len4 = arguments.length, nums = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { + nums[_key4] = arguments[_key4]; } return nums.reduce(function (acc, val) { @@ -213,13 +269,13 @@ }; var bind = function bind(fn, context) { - for (var _len4 = arguments.length, boundArgs = new Array(_len4 > 2 ? _len4 - 2 : 0), _key4 = 2; _key4 < _len4; _key4++) { - boundArgs[_key4 - 2] = arguments[_key4]; + for (var _len5 = arguments.length, boundArgs = new Array(_len5 > 2 ? _len5 - 2 : 0), _key5 = 2; _key5 < _len5; _key5++) { + boundArgs[_key5 - 2] = arguments[_key5]; } return function () { - for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) { - args[_key5] = arguments[_key5]; + for (var _len6 = arguments.length, args = new Array(_len6), _key6 = 0; _key6 < _len6; _key6++) { + args[_key6] = arguments[_key6]; } return fn.apply(context, boundArgs.concat(args)); @@ -227,8 +283,8 @@ }; var bindAll = function bindAll(obj) { - for (var _len6 = arguments.length, fns = new Array(_len6 > 1 ? _len6 - 1 : 0), _key6 = 1; _key6 < _len6; _key6++) { - fns[_key6 - 1] = arguments[_key6]; + for (var _len7 = arguments.length, fns = new Array(_len7 > 1 ? _len7 - 1 : 0), _key7 = 1; _key7 < _len7; _key7++) { + fns[_key7 - 1] = arguments[_key7]; } return fns.forEach(function (fn) { @@ -239,13 +295,13 @@ }; var bindKey = function bindKey(context, fn) { - for (var _len7 = arguments.length, boundArgs = new Array(_len7 > 2 ? _len7 - 2 : 0), _key7 = 2; _key7 < _len7; _key7++) { - boundArgs[_key7 - 2] = arguments[_key7]; + for (var _len8 = arguments.length, boundArgs = new Array(_len8 > 2 ? _len8 - 2 : 0), _key8 = 2; _key8 < _len8; _key8++) { + boundArgs[_key8 - 2] = arguments[_key8]; } return function () { - for (var _len8 = arguments.length, args = new Array(_len8), _key8 = 0; _key8 < _len8; _key8++) { - args[_key8] = arguments[_key8]; + for (var _len9 = arguments.length, args = new Array(_len9), _key9 = 0; _key9 < _len9; _key9++) { + args[_key9] = arguments[_key9]; } return context[fn].apply(context, boundArgs.concat(args)); @@ -280,8 +336,8 @@ }; var call = function call(key) { - for (var _len9 = arguments.length, args = new Array(_len9 > 1 ? _len9 - 1 : 0), _key9 = 1; _key9 < _len9; _key9++) { - args[_key9 - 1] = arguments[_key9]; + for (var _len10 = arguments.length, args = new Array(_len10 > 1 ? _len10 - 1 : 0), _key10 = 1; _key10 < _len10; _key10++) { + args[_key10 - 1] = arguments[_key10]; } return function (context) { @@ -335,8 +391,8 @@ }; var coalesce = function coalesce() { - for (var _len10 = arguments.length, args = new Array(_len10), _key10 = 0; _key10 < _len10; _key10++) { - args[_key10] = arguments[_key10]; + for (var _len11 = arguments.length, args = new Array(_len11), _key11 = 0; _key11 < _len11; _key11++) { + args[_key11] = arguments[_key11]; } return args.find(function (_) { @@ -346,8 +402,8 @@ var coalesceFactory = function coalesceFactory(valid) { return function () { - for (var _len11 = arguments.length, args = new Array(_len11), _key11 = 0; _key11 < _len11; _key11++) { - args[_key11] = arguments[_key11]; + for (var _len12 = arguments.length, args = new Array(_len12), _key12 = 0; _key12 < _len12; _key12++) { + args[_key12] = arguments[_key12]; } return args.find(valid); @@ -356,8 +412,8 @@ var collectInto = function collectInto(fn) { return function () { - for (var _len12 = arguments.length, args = new Array(_len12), _key12 = 0; _key12 < _len12; _key12++) { - args[_key12] = arguments[_key12]; + for (var _len13 = arguments.length, args = new Array(_len13), _key13 = 0; _key13 < _len13; _key13++) { + args[_key13] = arguments[_key13]; } return fn(args); @@ -365,8 +421,8 @@ }; var colorize = function colorize() { - for (var _len13 = arguments.length, args = new Array(_len13), _key13 = 0; _key13 < _len13; _key13++) { - args[_key13] = arguments[_key13]; + for (var _len14 = arguments.length, args = new Array(_len14), _key14 = 0; _key14 < _len14; _key14++) { + args[_key14] = arguments[_key14]; } return { @@ -394,8 +450,8 @@ }; var compose = function compose() { - for (var _len14 = arguments.length, fns = new Array(_len14), _key14 = 0; _key14 < _len14; _key14++) { - fns[_key14] = arguments[_key14]; + for (var _len15 = arguments.length, fns = new Array(_len15), _key15 = 0; _key15 < _len15; _key15++) { + fns[_key15] = arguments[_key15]; } return fns.reduce(function (f, g) { @@ -406,8 +462,8 @@ }; var composeRight = function composeRight() { - for (var _len15 = arguments.length, fns = new Array(_len15), _key15 = 0; _key15 < _len15; _key15++) { - fns[_key15] = arguments[_key15]; + for (var _len16 = arguments.length, fns = new Array(_len16), _key16 = 0; _key16 < _len16; _key16++) { + fns[_key16] = arguments[_key16]; } return fns.reduce(function (f, g) { @@ -419,8 +475,8 @@ var converge = function converge(converger, fns) { return function () { - for (var _len16 = arguments.length, args = new Array(_len16), _key16 = 0; _key16 < _len16; _key16++) { - args[_key16] = arguments[_key16]; + for (var _len17 = arguments.length, args = new Array(_len17), _key17 = 0; _key17 < _len17; _key17++) { + args[_key17] = arguments[_key17]; } return converger.apply(void 0, _toConsumableArray(fns.map(function (fn) { @@ -456,6 +512,12 @@ }, {}); }; + var countOccurrences = function countOccurrences(arr, val) { + return arr.reduce(function (a, v) { + return v === val ? a + 1 : a; + }, 0); + }; + var counter = function counter(selector, start, end) { var step = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1; var duration = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 2000; @@ -472,12 +534,6 @@ return timer; }; - var countOccurrences = function countOccurrences(arr, val) { - return arr.reduce(function (a, v) { - return v === val ? a + 1 : a; - }, 0); - }; - var createElement = function createElement(str) { var el = document.createElement('div'); el.innerHTML = str; @@ -505,25 +561,6 @@ }; }; - var CSVToArray = function CSVToArray(data) { - var delimiter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ','; - var omitFirstRow = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; - return data.slice(omitFirstRow ? data.indexOf('\n') + 1 : 0).split('\n').map(function (v) { - return v.split(delimiter); - }); - }; - - var CSVToJSON = function CSVToJSON(data) { - var delimiter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ','; - var titles = data.slice(0, data.indexOf('\n')).split(delimiter); - return data.slice(data.indexOf('\n') + 1).split('\n').map(function (v) { - var values = v.split(delimiter); - return titles.reduce(function (obj, title, index) { - return obj[title] = values[index], obj; - }, {}); - }); - }; - var currentURL = function currentURL() { return window.location.href; }; @@ -531,8 +568,8 @@ var curry = function curry(fn) { var arity = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : fn.length; - for (var _len17 = arguments.length, args = new Array(_len17 > 2 ? _len17 - 2 : 0), _key17 = 2; _key17 < _len17; _key17++) { - args[_key17 - 2] = arguments[_key17]; + for (var _len18 = arguments.length, args = new Array(_len18 > 2 ? _len18 - 2 : 0), _key18 = 2; _key18 < _len18; _key18++) { + args[_key18 - 2] = arguments[_key18]; } return arity <= args.length ? fn.apply(void 0, args) : curry.bind.apply(curry, [null, fn, arity].concat(args)); @@ -548,8 +585,8 @@ return function () { var _this = this; - for (var _len18 = arguments.length, args = new Array(_len18), _key18 = 0; _key18 < _len18; _key18++) { - args[_key18] = arguments[_key18]; + for (var _len19 = arguments.length, args = new Array(_len19), _key19 = 0; _key19 < _len19; _key19++) { + args[_key19] = arguments[_key19]; } clearTimeout(timeoutId); @@ -591,16 +628,16 @@ }; var defaults = function defaults(obj) { - for (var _len19 = arguments.length, defs = new Array(_len19 > 1 ? _len19 - 1 : 0), _key19 = 1; _key19 < _len19; _key19++) { - defs[_key19 - 1] = arguments[_key19]; + for (var _len20 = arguments.length, defs = new Array(_len20 > 1 ? _len20 - 1 : 0), _key20 = 1; _key20 < _len20; _key20++) { + defs[_key20 - 1] = arguments[_key20]; } return Object.assign.apply(Object, [{}, obj].concat(_toConsumableArray(defs.reverse()), [obj])); }; var defer = function defer(fn) { - for (var _len20 = arguments.length, args = new Array(_len20 > 1 ? _len20 - 1 : 0), _key20 = 1; _key20 < _len20; _key20++) { - args[_key20 - 1] = arguments[_key20]; + for (var _len21 = arguments.length, args = new Array(_len21 > 1 ? _len21 - 1 : 0), _key21 = 1; _key21 < _len21; _key21++) { + args[_key21 - 1] = arguments[_key21]; } return setTimeout.apply(void 0, [fn, 1].concat(args)); @@ -611,8 +648,8 @@ }; var delay = function delay(fn, wait) { - for (var _len21 = arguments.length, args = new Array(_len21 > 2 ? _len21 - 2 : 0), _key21 = 2; _key21 < _len21; _key21++) { - args[_key21 - 2] = arguments[_key21]; + for (var _len22 = arguments.length, args = new Array(_len22 > 2 ? _len22 - 2 : 0), _key22 = 2; _key22 < _len22; _key22++) { + args[_key22 - 2] = arguments[_key22]; } return setTimeout.apply(void 0, [fn, wait].concat(args)); @@ -860,8 +897,8 @@ var flip = function flip(fn) { return function (first) { - for (var _len22 = arguments.length, rest = new Array(_len22 > 1 ? _len22 - 1 : 0), _key22 = 1; _key22 < _len22; _key22++) { - rest[_key22 - 1] = arguments[_key22]; + for (var _len23 = arguments.length, rest = new Array(_len23 > 1 ? _len23 - 1 : 0), _key23 = 1; _key23 < _len23; _key23++) { + rest[_key23 - 1] = arguments[_key23]; } return fn.apply(void 0, rest.concat([first])); @@ -872,6 +909,18 @@ return arr.slice(0).reverse().forEach(callback); }; + var forOwn = function forOwn(obj, fn) { + return Object.keys(obj).forEach(function (key) { + return fn(obj[key], key, obj); + }); + }; + + var forOwnRight = function forOwnRight(obj, fn) { + return Object.keys(obj).reverse().forEach(function (key) { + return fn(obj[key], key, obj); + }); + }; + var formatDuration = function formatDuration(ms) { if (ms < 0) ms = -ms; var time = { @@ -892,18 +941,6 @@ }).join(', '); }; - var forOwn = function forOwn(obj, fn) { - return Object.keys(obj).forEach(function (key) { - return fn(obj[key], key, obj); - }); - }; - - var forOwnRight = function forOwnRight(obj, fn) { - return Object.keys(obj).reverse().forEach(function (key) { - return fn(obj[key], key, obj); - }); - }; - var fromCamelCase = function fromCamelCase(str) { var separator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '_'; return str.replace(/([a-z\d])([A-Z])/g, '$1' + separator + '$2').replace(/([A-Z]+)([A-Z][a-z\d]+)/g, '$1' + separator + '$2').toLowerCase(); @@ -925,8 +962,8 @@ return !y ? x : gcd(y, x % y); }; - for (var _len23 = arguments.length, arr = new Array(_len23), _key23 = 0; _key23 < _len23; _key23++) { - arr[_key23] = arguments[_key23]; + for (var _len24 = arguments.length, arr = new Array(_len24), _key24 = 0; _key24 < _len24; _key24++) { + arr[_key24] = arguments[_key24]; } return arr.concat().reduce(function (a, b) { @@ -945,8 +982,8 @@ }; var get = function get(from) { - for (var _len24 = arguments.length, selectors = new Array(_len24 > 1 ? _len24 - 1 : 0), _key24 = 1; _key24 < _len24; _key24++) { - selectors[_key24 - 1] = arguments[_key24]; + for (var _len25 = arguments.length, selectors = new Array(_len25 > 1 ? _len25 - 1 : 0), _key25 = 1; _key25 < _len25; _key25++) { + selectors[_key25 - 1] = arguments[_key25]; } return selectors.concat().map(function (s) { @@ -1020,8 +1057,8 @@ }; var hasFlags = function hasFlags() { - for (var _len25 = arguments.length, flags = new Array(_len25), _key25 = 0; _key25 < _len25; _key25++) { - flags[_key25] = arguments[_key25]; + for (var _len26 = arguments.length, flags = new Array(_len26), _key26 = 0; _key26 < _len26; _key26++) { + flags[_key26] = arguments[_key26]; } return flags.every(function (flag) { @@ -1118,6 +1155,18 @@ return 1000 * iterations / (performance.now() - before); }; + var inRange = function inRange(n, start) { + var end = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; + + if (end && start > end) { + var _ref12 = [start, end]; + end = _ref12[0]; + start = _ref12[1]; + } + + return end == null ? n >= 0 && n < start : n >= start && n < end; + }; + var indentString = function indentString(str, count) { var indent = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ' '; return str.replace(/^/gm, indent.repeat(count)); @@ -1170,8 +1219,8 @@ }; var initializeNDArray = function initializeNDArray(val) { - for (var _len26 = arguments.length, args = new Array(_len26 > 1 ? _len26 - 1 : 0), _key26 = 1; _key26 < _len26; _key26++) { - args[_key26 - 1] = arguments[_key26]; + for (var _len27 = arguments.length, args = new Array(_len27 > 1 ? _len27 - 1 : 0), _key27 = 1; _key27 < _len27; _key27++) { + args[_key27 - 1] = arguments[_key27]; } return args.length === 0 ? val : Array.from({ @@ -1181,18 +1230,6 @@ }); }; - var inRange = function inRange(n, start) { - var end = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; - - if (end && start > end) { - var _ref12 = [start, end]; - end = _ref12[0]; - start = _ref12[1]; - } - - return end == null ? n >= 0 && n < start : n >= start && n < end; - }; - var insertAfter = function insertAfter(el, htmlString) { return el.insertAdjacentHTML('afterend', htmlString); }; @@ -1422,19 +1459,6 @@ }, ''); }; - var JSONtoCSV = function JSONtoCSV(arr, columns) { - var delimiter = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ','; - return [columns.join(delimiter)].concat(_toConsumableArray(arr.map(function (obj) { - return columns.reduce(function (acc, key) { - return "".concat(acc).concat(!acc.length ? '' : delimiter, "\"").concat(!obj[key] ? '' : obj[key], "\""); - }, ''); - }))).join('\n'); - }; - - var JSONToFile = function JSONToFile(obj, filename) { - return fs.writeFile("".concat(filename, ".json"), JSON.stringify(obj, null, 2)); - }; - var last = function last(arr) { return arr[arr.length - 1]; }; @@ -1448,8 +1472,8 @@ return x * y / gcd(x, y); }; - for (var _len27 = arguments.length, arr = new Array(_len27), _key27 = 0; _key27 < _len27; _key27++) { - arr[_key27] = arguments[_key27]; + for (var _len28 = arguments.length, arr = new Array(_len28), _key28 = 0; _key28 < _len28; _key28++) { + arr[_key28] = arguments[_key28]; } return arr.concat().reduce(function (a, b) { @@ -1458,8 +1482,8 @@ }; var longestItem = function longestItem(val) { - for (var _len28 = arguments.length, vals = new Array(_len28 > 1 ? _len28 - 1 : 0), _key28 = 1; _key28 < _len28; _key28++) { - vals[_key28 - 1] = arguments[_key28]; + for (var _len29 = arguments.length, vals = new Array(_len29 > 1 ? _len29 - 1 : 0), _key29 = 1; _key29 < _len29; _key29++) { + vals[_key29 - 1] = arguments[_key29]; } return [val].concat(vals).reduce(function (a, x) { @@ -1541,8 +1565,8 @@ var maxDate = function maxDate() { var _Math$max; - for (var _len29 = arguments.length, dates = new Array(_len29), _key29 = 0; _key29 < _len29; _key29++) { - dates[_key29] = arguments[_key29]; + for (var _len30 = arguments.length, dates = new Array(_len30), _key30 = 0; _key30 < _len30; _key30++) { + dates[_key30] = arguments[_key30]; } return new Date((_Math$max = Math.max).apply.apply(_Math$max, [null].concat(dates))); @@ -1576,8 +1600,8 @@ }; var merge = function merge() { - for (var _len30 = arguments.length, objs = new Array(_len30), _key30 = 0; _key30 < _len30; _key30++) { - objs[_key30] = arguments[_key30]; + for (var _len31 = arguments.length, objs = new Array(_len31), _key31 = 0; _key31 < _len31; _key31++) { + objs[_key31] = arguments[_key31]; } return objs.concat().reduce(function (acc, obj) { @@ -1597,8 +1621,8 @@ var minDate = function minDate() { var _Math$min; - for (var _len31 = arguments.length, dates = new Array(_len31), _key31 = 0; _key31 < _len31; _key31++) { - dates[_key31] = arguments[_key31]; + for (var _len32 = arguments.length, dates = new Array(_len32), _key32 = 0; _key32 < _len32; _key32++) { + dates[_key32] = arguments[_key32]; } return new Date((_Math$min = Math.min).apply.apply(_Math$min, [null].concat(dates))); @@ -1654,8 +1678,8 @@ var nthArg = function nthArg(n) { return function () { - for (var _len32 = arguments.length, args = new Array(_len32), _key32 = 0; _key32 < _len32; _key32++) { - args[_key32] = arguments[_key32]; + for (var _len33 = arguments.length, args = new Array(_len33), _key33 = 0; _key33 < _len33; _key33++) { + args[_key33] = arguments[_key33]; } return args.slice(n)[0]; @@ -1736,20 +1760,6 @@ if (opts.target) return delegatorFn; }; - var once = function once(fn) { - var called = false; - return function () { - if (called) return; - called = true; - - for (var _len33 = arguments.length, args = new Array(_len33), _key33 = 0; _key33 < _len33; _key33++) { - args[_key33] = arguments[_key33]; - } - - return fn.apply(this, args); - }; - }; - var onUserInputChange = function onUserInputChange(callback) { var type = 'mouse', lastTime = 0; @@ -1766,6 +1776,20 @@ }); }; + var once = function once(fn) { + var called = false; + return function () { + if (called) return; + called = true; + + for (var _len34 = arguments.length, args = new Array(_len34), _key34 = 0; _key34 < _len34; _key34++) { + args[_key34] = arguments[_key34]; + } + + return fn.apply(this, args); + }; + }; + var orderBy = function orderBy(arr, props, orders) { return _toConsumableArray(arr).sort(function (a, b) { return props.reduce(function (acc, prop, i) { @@ -1784,13 +1808,13 @@ }; var over = function over() { - for (var _len34 = arguments.length, fns = new Array(_len34), _key34 = 0; _key34 < _len34; _key34++) { - fns[_key34] = arguments[_key34]; + for (var _len35 = arguments.length, fns = new Array(_len35), _key35 = 0; _key35 < _len35; _key35++) { + fns[_key35] = arguments[_key35]; } return function () { - for (var _len35 = arguments.length, args = new Array(_len35), _key35 = 0; _key35 < _len35; _key35++) { - args[_key35] = arguments[_key35]; + for (var _len36 = arguments.length, args = new Array(_len36), _key36 = 0; _key36 < _len36; _key36++) { + args[_key36] = arguments[_key36]; } return fns.map(function (fn) { @@ -1801,8 +1825,8 @@ var overArgs = function overArgs(fn, transforms) { return function () { - for (var _len36 = arguments.length, args = new Array(_len36), _key36 = 0; _key36 < _len36; _key36++) { - args[_key36] = arguments[_key36]; + for (var _len37 = arguments.length, args = new Array(_len37), _key37 = 0; _key37 < _len37; _key37++) { + args[_key37] = arguments[_key37]; } return fn.apply(void 0, _toConsumableArray(args.map(function (val, i) { @@ -1831,13 +1855,13 @@ }; var partial = function partial(fn) { - for (var _len37 = arguments.length, partials = new Array(_len37 > 1 ? _len37 - 1 : 0), _key37 = 1; _key37 < _len37; _key37++) { - partials[_key37 - 1] = arguments[_key37]; + for (var _len38 = arguments.length, partials = new Array(_len38 > 1 ? _len38 - 1 : 0), _key38 = 1; _key38 < _len38; _key38++) { + partials[_key38 - 1] = arguments[_key38]; } return function () { - for (var _len38 = arguments.length, args = new Array(_len38), _key38 = 0; _key38 < _len38; _key38++) { - args[_key38] = arguments[_key38]; + for (var _len39 = arguments.length, args = new Array(_len39), _key39 = 0; _key39 < _len39; _key39++) { + args[_key39] = arguments[_key39]; } return fn.apply(void 0, partials.concat(args)); @@ -1845,13 +1869,13 @@ }; var partialRight = function partialRight(fn) { - for (var _len39 = arguments.length, partials = new Array(_len39 > 1 ? _len39 - 1 : 0), _key39 = 1; _key39 < _len39; _key39++) { - partials[_key39 - 1] = arguments[_key39]; + for (var _len40 = arguments.length, partials = new Array(_len40 > 1 ? _len40 - 1 : 0), _key40 = 1; _key40 < _len40; _key40++) { + partials[_key40 - 1] = arguments[_key40]; } return function () { - for (var _len40 = arguments.length, args = new Array(_len40), _key40 = 0; _key40 < _len40; _key40++) { - args[_key40] = arguments[_key40]; + for (var _len41 = arguments.length, args = new Array(_len41), _key41 = 0; _key41 < _len41; _key41++) { + args[_key41] = arguments[_key41]; } return fn.apply(void 0, args.concat(partials)); @@ -1895,8 +1919,8 @@ }; var pipeAsyncFunctions = function pipeAsyncFunctions() { - for (var _len41 = arguments.length, fns = new Array(_len41), _key41 = 0; _key41 < _len41; _key41++) { - fns[_key41] = arguments[_key41]; + for (var _len42 = arguments.length, fns = new Array(_len42), _key42 = 0; _key42 < _len42; _key42++) { + fns[_key42] = arguments[_key42]; } return function (arg) { @@ -1907,8 +1931,8 @@ }; var pipeFunctions = function pipeFunctions() { - for (var _len42 = arguments.length, fns = new Array(_len42), _key42 = 0; _key42 < _len42; _key42++) { - fns[_key42] = arguments[_key42]; + for (var _len43 = arguments.length, fns = new Array(_len43), _key43 = 0; _key43 < _len43; _key43++) { + fns[_key43] = arguments[_key43]; } return fns.reduce(function (f, g) { @@ -1981,8 +2005,8 @@ var promisify = function promisify(func) { return function () { - for (var _len43 = arguments.length, args = new Array(_len43), _key43 = 0; _key43 < _len43; _key43++) { - args[_key43] = arguments[_key43]; + for (var _len44 = arguments.length, args = new Array(_len44), _key44 = 0; _key44 < _len44; _key44++) { + args[_key44] = arguments[_key44]; } return new Promise(function (resolve, reject) { @@ -1994,8 +2018,8 @@ }; var pull = function pull(arr) { - for (var _len44 = arguments.length, args = new Array(_len44 > 1 ? _len44 - 1 : 0), _key44 = 1; _key44 < _len44; _key44++) { - args[_key44 - 1] = arguments[_key44]; + for (var _len45 = arguments.length, args = new Array(_len45 > 1 ? _len45 - 1 : 0), _key45 = 1; _key45 < _len45; _key45++) { + args[_key45 - 1] = arguments[_key45]; } var argState = Array.isArray(args[0]) ? args[0] : args; @@ -2038,8 +2062,8 @@ }; var pullBy = function pullBy(arr) { - for (var _len45 = arguments.length, args = new Array(_len45 > 1 ? _len45 - 1 : 0), _key45 = 1; _key45 < _len45; _key45++) { - args[_key45 - 1] = arguments[_key45]; + for (var _len46 = arguments.length, args = new Array(_len46 > 1 ? _len46 - 1 : 0), _key46 = 1; _key46 < _len46; _key46++) { + args[_key46 - 1] = arguments[_key46]; } var length = args.length; @@ -2089,8 +2113,8 @@ var rearg = function rearg(fn, indexes) { return function () { - for (var _len46 = arguments.length, args = new Array(_len46), _key46 = 0; _key46 < _len46; _key46++) { - args[_key46] = arguments[_key46]; + for (var _len47 = arguments.length, args = new Array(_len47), _key47 = 0; _key47 < _len47; _key47++) { + args[_key47] = arguments[_key47]; } return fn.apply(void 0, _toConsumableArray(indexes.map(function (i) { @@ -2133,15 +2157,6 @@ return asLink ? window.location.href = url : window.location.replace(url); }; - var reducedFilter = function reducedFilter(data, keys, fn) { - return data.filter(fn).map(function (el) { - return keys.reduce(function (acc, key) { - acc[key] = el[key]; - return acc; - }, {}); - }); - }; - var reduceSuccessive = function reduceSuccessive(arr, fn, acc) { return arr.reduce(function (res, val, i, arr) { return res.push(fn(res.slice(-1)[0], val, i, arr)), res; @@ -2157,6 +2172,15 @@ }); }; + var reducedFilter = function reducedFilter(data, keys, fn) { + return data.filter(fn).map(function (el) { + return keys.reduce(function (acc, key) { + acc[key] = el[key]; + return acc; + }, {}); + }); + }; + var reject = function reject(pred, array) { return array.filter(function () { return !pred.apply(void 0, arguments); @@ -2184,10 +2208,6 @@ return _toConsumableArray(str).reverse().join(''); }; - var RGBToHex = function RGBToHex(r, g, b) { - return ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0'); - }; - var round = function round(n) { var decimals = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; return Number("".concat(Math.round("".concat(n, "e").concat(decimals)), "e-").concat(decimals)); @@ -2268,16 +2288,16 @@ var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; var delCount = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; - for (var _len47 = arguments.length, elements = new Array(_len47 > 3 ? _len47 - 3 : 0), _key47 = 3; _key47 < _len47; _key47++) { - elements[_key47 - 3] = arguments[_key47]; + for (var _len48 = arguments.length, elements = new Array(_len48 > 3 ? _len48 - 3 : 0), _key48 = 3; _key48 < _len48; _key48++) { + elements[_key48 - 3] = arguments[_key48]; } return arr.slice(0, index).concat(elements).concat(arr.slice(index + delCount)); }; var show = function show() { - for (var _len48 = arguments.length, el = new Array(_len48), _key48 = 0; _key48 < _len48; _key48++) { - el[_key48] = arguments[_key48]; + for (var _len49 = arguments.length, el = new Array(_len49), _key49 = 0; _key49 < _len49; _key49++) { + el[_key49] = arguments[_key49]; } return el.concat().forEach(function (e) { @@ -2413,8 +2433,8 @@ }; var sum = function sum() { - for (var _len49 = arguments.length, arr = new Array(_len49), _key49 = 0; _key49 < _len49; _key49++) { - arr[_key49] = arguments[_key49]; + for (var _len50 = arguments.length, arr = new Array(_len50), _key50 = 0; _key50 < _len50; _key50++) { + arr[_key50] = arguments[_key50]; } return arr.concat().reduce(function (acc, val) { @@ -2549,13 +2569,6 @@ }; }; - var times = function times(n, fn) { - var context = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined; - var i = 0; - - while (fn.call(context, i) !== false && ++i < n) {} - }; - var timeTaken = function timeTaken(callback) { console.time('timeTaken'); var r = callback(); @@ -2563,6 +2576,13 @@ return r; }; + var times = function times(n, fn) { + var context = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined; + var i = 0; + + while (fn.call(context, i) !== false && ++i < n) {} + }; + var toCamelCase = function toCamelCase(str) { var s = str && str.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g).map(function (x) { return x.slice(0, 1).toUpperCase() + x.slice(1).toLowerCase(); @@ -2582,10 +2602,6 @@ return num.toLocaleString('en-US'); }; - var toggleClass = function toggleClass(el, className) { - return el.classList.toggle(className); - }; - var toHash = function toHash(object, key) { return Array.prototype.reduce.call(object, function (acc, data, index) { return acc[!key ? index : data[key]] = data, acc; @@ -2598,14 +2614,6 @@ }).join('-'); }; - var tomorrow = function tomorrow() { - var long = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; - var t = new Date(); - t.setDate(t.getDate() + 1); - var ret = "".concat(t.getFullYear(), "-").concat(String(t.getMonth() + 1).padStart(2, '0'), "-").concat(String(t.getDate()).padStart(2, '0')); - return !long ? ret : "".concat(ret, "T00:00:00"); - }; - var toOrdinalSuffix = function toOrdinalSuffix(num) { var int = parseInt(num), digits = [int % 10, int % 100], @@ -2625,6 +2633,18 @@ }).join('_'); }; + var toggleClass = function toggleClass(el, className) { + return el.classList.toggle(className); + }; + + var tomorrow = function tomorrow() { + var long = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + var t = new Date(); + t.setDate(t.getDate() + 1); + var ret = "".concat(t.getFullYear(), "-").concat(String(t.getMonth() + 1).padStart(2, '0'), "-").concat(String(t.getDate()).padStart(2, '0')); + return !long ? ret : "".concat(ret, "T00:00:00"); + }; + var transform = function transform(obj, fn, acc) { return Object.keys(obj).reduce(function (a, k) { return fn(a, obj[k], k, obj); @@ -2664,8 +2684,8 @@ }; }; - for (var _len50 = arguments.length, args = new Array(_len50), _key50 = 0; _key50 < _len50; _key50++) { - args[_key50] = arguments[_key50]; + for (var _len51 = arguments.length, args = new Array(_len51), _key51 = 0; _key51 < _len51; _key51++) { + args[_key51] = arguments[_key51]; } if (n > args.length) throw new RangeError('Arguments too few!'); @@ -2792,26 +2812,6 @@ }); }; - var URLJoin = function URLJoin() { - for (var _len51 = arguments.length, args = new Array(_len51), _key51 = 0; _key51 < _len51; _key51++) { - args[_key51] = arguments[_key51]; - } - - return args.join('/').replace(/[\/]+/g, '/').replace(/^(.+):\//, '$1://').replace(/^file:/, 'file:/').replace(/\/(\?|&|#[^!])/g, '$1').replace(/\?/g, '&').replace('&', '?'); - }; - - var UUIDGeneratorBrowser = function UUIDGeneratorBrowser() { - return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, function (c) { - return (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16); - }); - }; - - var UUIDGeneratorNode = function UUIDGeneratorNode() { - return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, function (c) { - return (c ^ crypto.randomBytes(1)[0] & 15 >> c / 4).toString(16); - }); - }; - var validateNumber = function validateNumber(n) { return !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n; }; @@ -2895,6 +2895,14 @@ }; module.exports = { + CSVToArray: CSVToArray, + CSVToJSON: CSVToJSON, + JSONToFile: JSONToFile, + JSONtoCSV: JSONtoCSV, + RGBToHex: RGBToHex, + URLJoin: URLJoin, + UUIDGeneratorBrowser: UUIDGeneratorBrowser, + UUIDGeneratorNode: UUIDGeneratorNode, all: all, allEqual: allEqual, any: any, @@ -2933,12 +2941,10 @@ converge: converge, copyToClipboard: copyToClipboard, countBy: countBy, - counter: counter, countOccurrences: countOccurrences, + counter: counter, createElement: createElement, createEventHub: createEventHub, - CSVToArray: CSVToArray, - CSVToJSON: CSVToJSON, currentURL: currentURL, curry: curry, dayOfYear: dayOfYear, @@ -2982,9 +2988,9 @@ flattenObject: flattenObject, flip: flip, forEachRight: forEachRight, - formatDuration: formatDuration, forOwn: forOwn, forOwnRight: forOwnRight, + formatDuration: formatDuration, fromCamelCase: fromCamelCase, functionName: functionName, functions: functions, @@ -3012,6 +3018,7 @@ httpPost: httpPost, httpsRedirect: httpsRedirect, hz: hz, + inRange: inRange, indentString: indentString, indexOfAll: indexOfAll, initial: initial, @@ -3020,7 +3027,6 @@ initializeArrayWithRangeRight: initializeArrayWithRangeRight, initializeArrayWithValues: initializeArrayWithValues, initializeNDArray: initializeNDArray, - inRange: inRange, insertAfter: insertAfter, insertBefore: insertBefore, intersection: intersection, @@ -3063,8 +3069,6 @@ isValidJSON: isValidJSON, isWritableStream: isWritableStream, join: join, - JSONtoCSV: JSONtoCSV, - JSONToFile: JSONToFile, last: last, lcm: lcm, longestItem: longestItem, @@ -3101,8 +3105,8 @@ omit: omit, omitBy: omitBy, on: on, - once: once, onUserInputChange: onUserInputChange, + once: once, orderBy: orderBy, over: over, overArgs: overArgs, @@ -3137,15 +3141,14 @@ rearg: rearg, recordAnimationFrames: recordAnimationFrames, redirect: redirect, - reducedFilter: reducedFilter, reduceSuccessive: reduceSuccessive, reduceWhich: reduceWhich, + reducedFilter: reducedFilter, reject: reject, remove: remove, removeNonASCII: removeNonASCII, renameKeys: renameKeys, reverseString: reverseString, - RGBToHex: RGBToHex, round: round, runAsync: runAsync, runPromisesInSeries: runPromisesInSeries, @@ -3186,18 +3189,18 @@ takeRightWhile: takeRightWhile, takeWhile: takeWhile, throttle: throttle, - times: times, timeTaken: timeTaken, + times: times, toCamelCase: toCamelCase, toCurrency: toCurrency, toDecimalMark: toDecimalMark, - toggleClass: toggleClass, toHash: toHash, toKebabCase: toKebabCase, - tomorrow: tomorrow, toOrdinalSuffix: toOrdinalSuffix, toSafeInteger: toSafeInteger, toSnakeCase: toSnakeCase, + toggleClass: toggleClass, + tomorrow: tomorrow, transform: transform, triggerEvent: triggerEvent, truncateString: truncateString, @@ -3217,9 +3220,6 @@ untildify: untildify, unzip: unzip, unzipWith: unzipWith, - URLJoin: URLJoin, - UUIDGeneratorBrowser: UUIDGeneratorBrowser, - UUIDGeneratorNode: UUIDGeneratorNode, validateNumber: validateNumber, when: when, without: without, diff --git a/dist/_30s.es5.min.js b/dist/_30s.es5.min.js index 8b18cc1f8..55ad3bfaf 100644 --- a/dist/_30s.es5.min.js +++ b/dist/_30s.es5.min.js @@ -1 +1 @@ -(function(e,t){'object'==typeof exports&&'undefined'!=typeof module?t():'function'==typeof define&&define.amd?define(t):t()})(this,function(){'use strict';function e(t){return e='function'==typeof Symbol&&'symbol'==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&'function'==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?'symbol':typeof e},e(t)}function t(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function n(e){for(var n=1;n'.concat(e,'')}).join('')}()},ary:function(e,t){return function(){for(var n=arguments.length,i=Array(n),r=0;rt||t>e)return 0;if(0===t||t===e)return 1;if(1===t||t===e-1)return e;e-t=(document.documentElement.scrollHeight||document.documentElement.clientHeight)},btoa:function(e){return Buffer.from(e,'binary').toString('base64')},byteSize:function(e){return new Blob([e]).size},call:function(e){for(var t=arguments.length,n=Array(1(n-t)*i?-i:i,o=setInterval(function(){a+=l,document.querySelector(e).innerHTML=a,a>=n&&(document.querySelector(e).innerHTML=n),a>=n&&clearInterval(o)},v(y(r/(n-t))));return o},countOccurrences:function(e,t){return e.reduce(function(e,n){return n===t?e+1:e},0)},createElement:function(e){var t=document.createElement('div');return t.innerHTML=e,t.firstElementChild},createEventHub:function(){return{hub:Object.create(null),emit:function(e,t){(this.hub[e]||[]).forEach(function(e){return e(t)})},on:function(e,t){this.hub[e]||(this.hub[e]=[]),this.hub[e].push(t)},off:function(e,t){var n=(this.hub[e]||[]).findIndex(function(e){return e===t});-1'"]/g,function(e){return{"&":'&',"<":'<',">":'>',"'":''','"':'"'}[e]||e})},escapeRegExp:function(e){return e.replace(/[.*+?^${}()|[\]\\]/g,'\\$&')},everyNth:function(e,t){return e.filter(function(n,e){return e%t==t-1})},extendHex:function(e){return'#'+e.slice(e.startsWith('#')?1:0).split('').map(function(e){return e+e}).join('')},factorial:function e(t){return 0>t?function(){throw new TypeError('Negative numbers are not allowed!')}():1>=t?1:t*e(t-1)},fibonacci:function(e){return Array.from({length:e}).reduce(function(e,t,n){return e.concat(1e&&(e=-e);var t={day:y(e/864e5),hour:y(e/36e5)%24,minute:y(e/6e4)%60,second:y(e/1e3)%60,millisecond:y(e)%1e3};return Object.entries(t).filter(function(e){return 0!==e[1]}).map(function(e){var t=r(e,2),n=t[0],i=t[1];return''.concat(i,' ').concat(n).concat(1===i?'':'s')}).join(', ')},forOwn:function(e,t){return Object.keys(e).forEach(function(n){return t(e[n],n,e)})},forOwnRight:function(e,t){return Object.keys(e).reverse().forEach(function(n){return t(e[n],n,e)})},fromCamelCase:function(e){var t=1e?e%12+'am':e%12+'pm'},getScrollPosition:function(){var e=0>>(t?24:16))+', '+((n&(t?16711680:65280))>>>(t?16:8))+', '+((n&(t?65280:255))>>>(t?8:0))+(t?', '.concat(255&n):'')+')'},hide:function(e){return e.forEach(function(t){return t.style.display='none'})},httpGet:function(e,t){var n=2n){var i=[t,n];n=i[0],t=i[1]}return null==n?0<=e&&e=t&&et},isAnagram:function(e,t){var n=function(e){return e.toLowerCase().replace(/[^a-z0-9]/gi,'').split('').sort().join('')};return n(e)===n(t)},isArrayLike:function(e){return null!=e&&'function'==typeof e[Symbol.iterator]},isBeforeDate:function(e,t){return ee.length?t:e})},lowercaseKeys:function(e){return Object.keys(e).reduce(function(t,n){return t[n.toLowerCase()]=e[n],t},{})},luhnCheck:function(e){var t=(e+'').split('').reverse().map(function(e){return parseInt(e)}),n=t.splice(0,1)[0],i=t.reduce(function(e,t,n){return 0==n%2?e+2*t%9||9:e+t},0);return i+=n,0==i%10},mapKeys:function(e,t){return Object.keys(e).reduce(function(n,i){return n[t(e[i],i,e)]=e[i],n},{})},mapObject:function(e,t){return function(n){return n=[e,e.map(t)],n[0].reduce(function(e,t,i){return e[t]=n[1][i],e},{})}()},mapString:function(e,t){return e.split('').map(function(n,r){return t(n,r,e)}).join('')},mapValues:function(e,t){return Object.keys(e).reduce(function(n,i){return n[i]=t(e[i],i,e),n},{})},mask:function(e){var t=1r-n&&(t='mouse',e(t),document.removeEventListener('mousemove',i)),n=r};document.addEventListener('touchstart',function(){'touch'==t||(t='touch',e(t),document.addEventListener('mousemove',i))})},orderBy:function(e,t,n){return o(e).sort(function(e,a){return t.reduce(function(t,l,o){if(0===t){var i=n&&'desc'===n[o]?[a[l],e[l]]:[e[l],a[l]],c=r(i,2),s=c[0],d=c[1];t=s>d?1:sv(e))return e+(i?' ':'')+r[0];var a=m(y(Math.log10(0>e?-e:e)/3),r.length-1),l=+((0>e?-e:e)/g(1e3,a)).toPrecision(t);return(0>e?'-':'')+l+(i?' ':'')+r[a]},primes:function(e){var t=Array.from({length:e-1}).map(function(e,t){return t+2}),n=y(h(e)),i=Array.from({length:n-1}).map(function(e,t){return t+2});return i.forEach(function(e){return t=t.filter(function(t){return 0!=t%e||t===e})}),t},promisify:function(e){return function(){for(var t=arguments.length,n=Array(t),i=0;ie[e.length-1],i=e.findIndex(function(e){return n?t>=e:t<=e});return-1===i?e.length:i},sortedIndexBy:function(e,t,n){var i=n(e[0])>n(e[e.length-1]),r=n(t),a=e.findIndex(function(e){return i?r>=n(e):r<=n(e)});return-1===a?e.length:a},sortedLastIndex:function(e,t){var n=e[0]>e[e.length-1],i=e.reverse().findIndex(function(e){return n?t<=e:t>=e});return-1===i?0:e.length-i},sortedLastIndexBy:function(e,t,n){var i=n(e[0])>n(e[e.length-1]),r=n(t),a=e.map(n).reverse().findIndex(function(e){return i?r<=e:r>=e});return-1===a?0:e.length-a},splitLines:function(e){return e.split(/\r?\n/)},spreadOver:function(e){return function(t){return e.apply(void 0,o(t))}},stableSort:function(e,t){return e.map(function(e,t){return{item:e,index:t}}).sort(function(e,n){return t(e.item,n.item)||e.index-n.index}).map(function(e){var t=e.item;return t})},standardDeviation:function(e){var t=!!(1=t.length?2===t.length?[t,t[1]+t[0]]:[t]:t.split('').reduce(function(n,r,a){return n.concat(e(t.slice(0,a)+t.slice(a+1)).map(function(e){return r+e}))},[])},stripHTMLTags:function(e){return e.replace(/<[^>]*>/g,'')},sum:function(){for(var e=arguments.length,t=Array(e),n=0;n=t&&(e.apply(a,l),r=Date.now())},k(t-(Date.now()-r),0))):(e.apply(a,l),r=Date.now(),n=!0)}},times:function(e,t){for(var n=2t?e.slice(0,3r.length)throw new RangeError('Arguments too few!');return n(e)(r.slice(0,t))}},unescapeHTML:function(e){return e.replace(/&|<|>|'|"/g,function(e){return{"&":'&',"<":'<',">":'>',"'":'\'',""":'"'}[e]||e})},unflattenObject:function(e){return Object.keys(e).reduce(function(t,n){if(-1!==n.indexOf('.')){var r=n.split('.');Object.assign(t,JSON.parse('{'+r.map(function(e,t){return t===r.length-1?'"'.concat(e,'":'):'"'.concat(e,'":{')}).join('')+e[n]+'}'.repeat(r.length)))}else t[n]=e[n];return t},{})},unfold:function(e,t){for(var n=[],i=[null,t];i=e(i[1]);)n.push(i[0]);return n},union:function(e,t){return Array.from(new Set(o(e).concat(o(t))))},unionBy:function(e,t,n){var i=new Set(e.map(n));return Array.from(new Set(o(e).concat(o(t.filter(function(e){return!i.has(n(e))})))))},unionWith:function(e,t,n){return Array.from(new Set(o(e).concat(o(t.filter(function(t){return-1===e.findIndex(function(e){return n(t,e)})})))))},uniqueElements:function(e){return o(new Set(e))},uniqueElementsBy:function(e,t){return e.reduce(function(e,n){return e.some(function(e){return t(n,e)})||e.push(n),e},[])},uniqueElementsByRight:function(e,t){return e.reduceRight(function(e,n){return e.some(function(e){return t(n,e)})||e.push(n),e},[])},uniqueSymmetricDifference:function(e,t){return o(new Set(o(e.filter(function(e){return!t.includes(e)})).concat(o(t.filter(function(t){return!e.includes(t)})))))},untildify:function(e){return e.replace(/^~($|\/|\\)/,''.concat(require('os').homedir(),'$1'))},unzip:function(e){return e.reduce(function(e,t){return t.forEach(function(t,n){return e[n].push(t)}),e},Array.from({length:k.apply(Math,o(e.map(function(e){return e.length})))}).map(function(){return[]}))},unzipWith:function(e,t){return e.reduce(function(e,t){return t.forEach(function(t,n){return e[n].push(t)}),e},Array.from({length:k.apply(Math,o(e.map(function(e){return e.length})))}).map(function(){return[]})).map(function(e){return t.apply(void 0,o(e))})},URLJoin:function(){for(var e=arguments.length,t=Array(e),n=0;n>e/4).toString(16)})},UUIDGeneratorNode:function(){return'10000000-1000-4000-8000-100000000000'.replace(/[018]/g,function(e){return(e^S.randomBytes(1)[0]&15>>e/4).toString(16)})},validateNumber:function(e){return!isNaN(parseFloat(e))&&isFinite(e)&&+e==e},when:function(e,t){return function(n){return e(n)?t(n):n}},without:function(e){for(var t=arguments.length,n=Array(1>e/4).toString(16)})},UUIDGeneratorNode:function(){return'10000000-1000-4000-8000-100000000000'.replace(/[018]/g,function(e){return(e^j.randomBytes(1)[0]&15>>e/4).toString(16)})},all:function(e){var t=1'.concat(e,'')}).join('')}()},ary:function(e,t){return function(){for(var n=arguments.length,i=Array(n),r=0;rt||t>e)return 0;if(0===t||t===e)return 1;if(1===t||t===e-1)return e;e-t=(document.documentElement.scrollHeight||document.documentElement.clientHeight)},btoa:function(e){return Buffer.from(e,'binary').toString('base64')},byteSize:function(e){return new Blob([e]).size},call:function(e){for(var t=arguments.length,n=Array(1(n-t)*i?-i:i,o=setInterval(function(){a+=l,document.querySelector(e).innerHTML=a,a>=n&&(document.querySelector(e).innerHTML=n),a>=n&&clearInterval(o)},v(y(r/(n-t))));return o},createElement:function(e){var t=document.createElement('div');return t.innerHTML=e,t.firstElementChild},createEventHub:function(){return{hub:Object.create(null),emit:function(e,t){(this.hub[e]||[]).forEach(function(e){return e(t)})},on:function(e,t){this.hub[e]||(this.hub[e]=[]),this.hub[e].push(t)},off:function(e,t){var n=(this.hub[e]||[]).findIndex(function(e){return e===t});-1'"]/g,function(e){return{"&":'&',"<":'<',">":'>',"'":''','"':'"'}[e]||e})},escapeRegExp:function(e){return e.replace(/[.*+?^${}()|[\]\\]/g,'\\$&')},everyNth:function(e,t){return e.filter(function(n,e){return e%t==t-1})},extendHex:function(e){return'#'+e.slice(e.startsWith('#')?1:0).split('').map(function(e){return e+e}).join('')},factorial:function e(t){return 0>t?function(){throw new TypeError('Negative numbers are not allowed!')}():1>=t?1:t*e(t-1)},fibonacci:function(e){return Array.from({length:e}).reduce(function(e,t,n){return e.concat(1e&&(e=-e);var t={day:y(e/864e5),hour:y(e/36e5)%24,minute:y(e/6e4)%60,second:y(e/1e3)%60,millisecond:y(e)%1e3};return Object.entries(t).filter(function(e){return 0!==e[1]}).map(function(e){var t=r(e,2),n=t[0],i=t[1];return''.concat(i,' ').concat(n).concat(1===i?'':'s')}).join(', ')},fromCamelCase:function(e){var t=1e?e%12+'am':e%12+'pm'},getScrollPosition:function(){var e=0>>(t?24:16))+', '+((n&(t?16711680:65280))>>>(t?16:8))+', '+((n&(t?65280:255))>>>(t?8:0))+(t?', '.concat(255&n):'')+')'},hide:function(e){return e.forEach(function(t){return t.style.display='none'})},httpGet:function(e,t){var n=2n){var i=[t,n];n=i[0],t=i[1]}return null==n?0<=e&&e=t&&et},isAnagram:function(e,t){var n=function(e){return e.toLowerCase().replace(/[^a-z0-9]/gi,'').split('').sort().join('')};return n(e)===n(t)},isArrayLike:function(e){return null!=e&&'function'==typeof e[Symbol.iterator]},isBeforeDate:function(e,t){return ee.length?t:e})},lowercaseKeys:function(e){return Object.keys(e).reduce(function(t,n){return t[n.toLowerCase()]=e[n],t},{})},luhnCheck:function(e){var t=(e+'').split('').reverse().map(function(e){return parseInt(e)}),n=t.splice(0,1)[0],i=t.reduce(function(e,t,n){return 0==n%2?e+2*t%9||9:e+t},0);return i+=n,0==i%10},mapKeys:function(e,t){return Object.keys(e).reduce(function(n,i){return n[t(e[i],i,e)]=e[i],n},{})},mapObject:function(e,t){return function(n){return n=[e,e.map(t)],n[0].reduce(function(e,t,i){return e[t]=n[1][i],e},{})}()},mapString:function(e,t){return e.split('').map(function(n,r){return t(n,r,e)}).join('')},mapValues:function(e,t){return Object.keys(e).reduce(function(n,i){return n[i]=t(e[i],i,e),n},{})},mask:function(e){var t=1r-n&&(t='mouse',e(t),document.removeEventListener('mousemove',i)),n=r};document.addEventListener('touchstart',function(){'touch'==t||(t='touch',e(t),document.addEventListener('mousemove',i))})},once:function(e){var t=!1;return function(){if(!t){t=!0;for(var n=arguments.length,i=Array(n),r=0;rd?1:sv(e))return e+(i?' ':'')+r[0];var a=m(y(Math.log10(0>e?-e:e)/3),r.length-1),l=+((0>e?-e:e)/g(1e3,a)).toPrecision(t);return(0>e?'-':'')+l+(i?' ':'')+r[a]},primes:function(e){var t=Array.from({length:e-1}).map(function(e,t){return t+2}),n=y(h(e)),i=Array.from({length:n-1}).map(function(e,t){return t+2});return i.forEach(function(e){return t=t.filter(function(t){return 0!=t%e||t===e})}),t},promisify:function(e){return function(){for(var t=arguments.length,n=Array(t),i=0;ie[e.length-1],i=e.findIndex(function(e){return n?t>=e:t<=e});return-1===i?e.length:i},sortedIndexBy:function(e,t,n){var i=n(e[0])>n(e[e.length-1]),r=n(t),a=e.findIndex(function(e){return i?r>=n(e):r<=n(e)});return-1===a?e.length:a},sortedLastIndex:function(e,t){var n=e[0]>e[e.length-1],i=e.reverse().findIndex(function(e){return n?t<=e:t>=e});return-1===i?0:e.length-i},sortedLastIndexBy:function(e,t,n){var i=n(e[0])>n(e[e.length-1]),r=n(t),a=e.map(n).reverse().findIndex(function(e){return i?r<=e:r>=e});return-1===a?0:e.length-a},splitLines:function(e){return e.split(/\r?\n/)},spreadOver:function(e){return function(t){return e.apply(void 0,o(t))}},stableSort:function(e,t){return e.map(function(e,t){return{item:e,index:t}}).sort(function(e,n){return t(e.item,n.item)||e.index-n.index}).map(function(e){var t=e.item;return t})},standardDeviation:function(e){var t=!!(1=t.length?2===t.length?[t,t[1]+t[0]]:[t]:t.split('').reduce(function(n,r,a){return n.concat(e(t.slice(0,a)+t.slice(a+1)).map(function(e){return r+e}))},[])},stripHTMLTags:function(e){return e.replace(/<[^>]*>/g,'')},sum:function(){for(var e=arguments.length,t=Array(e),n=0;n=t&&(e.apply(a,l),r=Date.now())},k(t-(Date.now()-r),0))):(e.apply(a,l),r=Date.now(),n=!0)}},timeTaken:function(e){console.time('timeTaken');var t=e();return console.timeEnd('timeTaken'),t},times:function(e,t){for(var n=2t?e.slice(0,3r.length)throw new RangeError('Arguments too few!');return n(e)(r.slice(0,t))}},unescapeHTML:function(e){return e.replace(/&|<|>|'|"/g,function(e){return{"&":'&',"<":'<',">":'>',"'":'\'',""":'"'}[e]||e})},unflattenObject:function(e){return Object.keys(e).reduce(function(t,n){if(-1!==n.indexOf('.')){var r=n.split('.');Object.assign(t,JSON.parse('{'+r.map(function(e,t){return t===r.length-1?'"'.concat(e,'":'):'"'.concat(e,'":{')}).join('')+e[n]+'}'.repeat(r.length)))}else t[n]=e[n];return t},{})},unfold:function(e,t){for(var n=[],i=[null,t];i=e(i[1]);)n.push(i[0]);return n},union:function(e,t){return Array.from(new Set(o(e).concat(o(t))))},unionBy:function(e,t,n){var i=new Set(e.map(n));return Array.from(new Set(o(e).concat(o(t.filter(function(e){return!i.has(n(e))})))))},unionWith:function(e,t,n){return Array.from(new Set(o(e).concat(o(t.filter(function(t){return-1===e.findIndex(function(e){return n(t,e)})})))))},uniqueElements:function(e){return o(new Set(e))},uniqueElementsBy:function(e,t){return e.reduce(function(e,n){return e.some(function(e){return t(n,e)})||e.push(n),e},[])},uniqueElementsByRight:function(e,t){return e.reduceRight(function(e,n){return e.some(function(e){return t(n,e)})||e.push(n),e},[])},uniqueSymmetricDifference:function(e,t){return o(new Set(o(e.filter(function(e){return!t.includes(e)})).concat(o(t.filter(function(t){return!e.includes(t)})))))},untildify:function(e){return e.replace(/^~($|\/|\\)/,''.concat(require('os').homedir(),'$1'))},unzip:function(e){return e.reduce(function(e,t){return t.forEach(function(t,n){return e[n].push(t)}),e},Array.from({length:k.apply(Math,o(e.map(function(e){return e.length})))}).map(function(){return[]}))},unzipWith:function(e,t){return e.reduce(function(e,t){return t.forEach(function(t,n){return e[n].push(t)}),e},Array.from({length:k.apply(Math,o(e.map(function(e){return e.length})))}).map(function(){return[]})).map(function(e){return t.apply(void 0,o(e))})},validateNumber:function(e){return!isNaN(parseFloat(e))&&isFinite(e)&&+e==e},when:function(e,t){return function(n){return e(n)?t(n):n}},without:function(e){for(var t=arguments.length,n=Array(1 arr.every(fn); - const allEqual = arr => arr.every(val => val === arr[0]); - const any = (arr, fn = Boolean) => arr.some(fn); - const approximatelyEqual = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) < epsilon; - const arrayToCSV = (arr, delimiter = ',') => - arr.map(v => v.map(x => `"${x}"`).join(delimiter)).join('\n'); - const arrayToHtmlList = (arr, listID) => - (el => ( - (el = document.querySelector('#' + listID)), - (el.innerHTML += arr.map(item => `
  • ${item}
  • `).join('')) - ))(); - const ary = (fn, n) => (...args) => fn(...args.slice(0, n)); - const atob = str => Buffer.from(str, 'base64').toString('binary'); - const attempt = (fn, ...args) => { - try { - return fn(...args); - } catch (e) { - return e instanceof Error ? e : new Error(e); - } -}; - const average = (...nums) => nums.reduce((acc, val) => acc + val, 0) / nums.length; - const averageBy = (arr, fn) => - arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0) / - arr.length; - const bifurcate = (arr, filter) => - arr.reduce((acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc), [[], []]); - const bifurcateBy = (arr, fn) => - arr.reduce((acc, val, i) => (acc[fn(val, i) ? 0 : 1].push(val), acc), [[], []]); - const bind = (fn, context, ...boundArgs) => (...args) => fn.apply(context, [...boundArgs, ...args]); - const bindAll = (obj, ...fns) => - fns.forEach( - fn => ( - (f = obj[fn]), - (obj[fn] = function() { - return f.apply(obj); - }) - ) - ); - const bindKey = (context, fn, ...boundArgs) => (...args) => - context[fn].apply(context, [...boundArgs, ...args]); - const binomialCoefficient = (n, k) => { - if (Number.isNaN(n) || Number.isNaN(k)) return NaN; - if (k < 0 || k > n) return 0; - if (k === 0 || k === n) return 1; - if (k === 1 || k === n - 1) return n; - if (n - k < k) k = n - k; - let res = n; - for (let j = 2; j <= k; j++) res *= (n - j + 1) / j; - return Math.round(res); -}; - const bottomVisible = () => - document.documentElement.clientHeight + window.scrollY >= - (document.documentElement.scrollHeight || document.documentElement.clientHeight); - const btoa = str => Buffer.from(str, 'binary').toString('base64'); - const byteSize = str => new Blob([str]).size; +const CSVToArray = (data, delimiter = ',', omitFirstRow = false) => + data + .slice(omitFirstRow ? data.indexOf('\n') + 1 : 0) + .split('\n') + .map(v => v.split(delimiter)); +const CSVToJSON = (data, delimiter = ',') => { + const titles = data.slice(0, data.indexOf('\n')).split(delimiter); + return data + .slice(data.indexOf('\n') + 1) + .split('\n') + .map(v => { + const values = v.split(delimiter); + return titles.reduce((obj, title, index) => ((obj[title] = values[index]), obj), {}); + }); +}; + +const JSONToFile = (obj, filename) => + fs.writeFile(`${filename}.json`, JSON.stringify(obj, null, 2)); +const JSONtoCSV = (arr, columns, delimiter = ',') => + [ + columns.join(delimiter), + ...arr.map(obj => + columns.reduce( + (acc, key) => `${acc}${!acc.length ? '' : delimiter}"${!obj[key] ? '' : obj[key]}"`, + '' + ) + ) + ].join('\n'); +const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0'); +const URLJoin = (...args) => + args + .join('/') + .replace(/[\/]+/g, '/') + .replace(/^(.+):\//, '$1://') + .replace(/^file:/, 'file:/') + .replace(/\/(\?|&|#[^!])/g, '$1') + .replace(/\?/g, '&') + .replace('&', '?'); +const UUIDGeneratorBrowser = () => + ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => + (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16) + ); + +const UUIDGeneratorNode = () => + ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => + (c ^ (crypto.randomBytes(1)[0] & (15 >> (c / 4)))).toString(16) + ); +const all = (arr, fn = Boolean) => arr.every(fn); +const allEqual = arr => arr.every(val => val === arr[0]); +const any = (arr, fn = Boolean) => arr.some(fn); +const approximatelyEqual = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) < epsilon; +const arrayToCSV = (arr, delimiter = ',') => + arr.map(v => v.map(x => `"${x}"`).join(delimiter)).join('\n'); +const arrayToHtmlList = (arr, listID) => + (el => ( + (el = document.querySelector('#' + listID)), + (el.innerHTML += arr.map(item => `
  • ${item}
  • `).join('')) + ))(); +const ary = (fn, n) => (...args) => fn(...args.slice(0, n)); +const atob = str => Buffer.from(str, 'base64').toString('binary'); +const attempt = (fn, ...args) => { + try { + return fn(...args); + } catch (e) { + return e instanceof Error ? e : new Error(e); + } +}; +const average = (...nums) => nums.reduce((acc, val) => acc + val, 0) / nums.length; +const averageBy = (arr, fn) => + arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0) / + arr.length; +const bifurcate = (arr, filter) => + arr.reduce((acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc), [[], []]); +const bifurcateBy = (arr, fn) => + arr.reduce((acc, val, i) => (acc[fn(val, i) ? 0 : 1].push(val), acc), [[], []]); +const bind = (fn, context, ...boundArgs) => (...args) => fn.apply(context, [...boundArgs, ...args]); +const bindAll = (obj, ...fns) => + fns.forEach( + fn => ( + (f = obj[fn]), + (obj[fn] = function() { + return f.apply(obj); + }) + ) + ); +const bindKey = (context, fn, ...boundArgs) => (...args) => + context[fn].apply(context, [...boundArgs, ...args]); +const binomialCoefficient = (n, k) => { + if (Number.isNaN(n) || Number.isNaN(k)) return NaN; + if (k < 0 || k > n) return 0; + if (k === 0 || k === n) return 1; + if (k === 1 || k === n - 1) return n; + if (n - k < k) k = n - k; + let res = n; + for (let j = 2; j <= k; j++) res *= (n - j + 1) / j; + return Math.round(res); +}; +const bottomVisible = () => + document.documentElement.clientHeight + window.scrollY >= + (document.documentElement.scrollHeight || document.documentElement.clientHeight); +const btoa = str => Buffer.from(str, 'binary').toString('base64'); +const byteSize = str => new Blob([str]).size; const call = (key, ...args) => context => context[key](...args); - const capitalize = ([first, ...rest], lowerRest = false) => - first.toUpperCase() + (lowerRest ? rest.join('').toLowerCase() : rest.join('')); - const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase()); - const castArray = val => (Array.isArray(val) ? val : [val]); - const chainAsync = fns => { - let curr = 0; - const next = () => fns[curr++](next); - next(); -}; - const chunk = (arr, size) => - Array.from({ length: Math.ceil(arr.length / size) }, (v, i) => - arr.slice(i * size, i * size + size) - ); - const clampNumber = (num, a, b) => Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b)); - const cloneRegExp = regExp => new RegExp(regExp.source, regExp.flags); - const coalesce = (...args) => args.find(_ => ![undefined, null].includes(_)); - const coalesceFactory = valid => (...args) => args.find(valid); +const capitalize = ([first, ...rest], lowerRest = false) => + first.toUpperCase() + (lowerRest ? rest.join('').toLowerCase() : rest.join('')); +const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase()); +const castArray = val => (Array.isArray(val) ? val : [val]); +const chainAsync = fns => { + let curr = 0; + const next = () => fns[curr++](next); + next(); +}; +const chunk = (arr, size) => + Array.from({ length: Math.ceil(arr.length / size) }, (v, i) => + arr.slice(i * size, i * size + size) + ); +const clampNumber = (num, a, b) => Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b)); +const cloneRegExp = regExp => new RegExp(regExp.source, regExp.flags); +const coalesce = (...args) => args.find(_ => ![undefined, null].includes(_)); +const coalesceFactory = valid => (...args) => args.find(valid); const collectInto = fn => (...args) => fn(args); - const colorize = (...args) => ({ - black: `\x1b[30m${args.join(' ')}`, - red: `\x1b[31m${args.join(' ')}`, - green: `\x1b[32m${args.join(' ')}`, - yellow: `\x1b[33m${args.join(' ')}`, - blue: `\x1b[34m${args.join(' ')}`, - magenta: `\x1b[35m${args.join(' ')}`, - cyan: `\x1b[36m${args.join(' ')}`, - white: `\x1b[37m${args.join(' ')}`, - bgBlack: `\x1b[40m${args.join(' ')}\x1b[0m`, - bgRed: `\x1b[41m${args.join(' ')}\x1b[0m`, - bgGreen: `\x1b[42m${args.join(' ')}\x1b[0m`, - bgYellow: `\x1b[43m${args.join(' ')}\x1b[0m`, - bgBlue: `\x1b[44m${args.join(' ')}\x1b[0m`, - bgMagenta: `\x1b[45m${args.join(' ')}\x1b[0m`, - bgCyan: `\x1b[46m${args.join(' ')}\x1b[0m`, - bgWhite: `\x1b[47m${args.join(' ')}\x1b[0m` -}); - const compact = arr => arr.filter(Boolean); - const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args))); - const composeRight = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args))); - const converge = (converger, fns) => (...args) => converger(...fns.map(fn => fn.apply(null, args))); - const copyToClipboard = str => { - const el = document.createElement('textarea'); - el.value = str; - el.setAttribute('readonly', ''); - el.style.position = 'absolute'; - el.style.left = '-9999px'; - document.body.appendChild(el); - const selected = - document.getSelection().rangeCount > 0 ? document.getSelection().getRangeAt(0) : false; - el.select(); - document.execCommand('copy'); - document.body.removeChild(el); - if (selected) { - document.getSelection().removeAllRanges(); - document.getSelection().addRange(selected); - } -}; - const countBy = (arr, fn) => - arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => { - acc[val] = (acc[val] || 0) + 1; - return acc; - }, {}); - const counter = (selector, start, end, step = 1, duration = 2000) => { - let current = start, - _step = (end - start) * step < 0 ? -step : step, - timer = setInterval(() => { - current += _step; - document.querySelector(selector).innerHTML = current; - if (current >= end) document.querySelector(selector).innerHTML = end; - if (current >= end) clearInterval(timer); - }, Math.abs(Math.floor(duration / (end - start)))); - return timer; -}; - const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0); - const createElement = str => { - const el = document.createElement('div'); - el.innerHTML = str; - return el.firstElementChild; -}; - const createEventHub = () => ({ - hub: Object.create(null), - emit(event, data) { - (this.hub[event] || []).forEach(handler => handler(data)); - }, - on(event, handler) { - if (!this.hub[event]) this.hub[event] = []; - this.hub[event].push(handler); - }, - off(event, handler) { - const i = (this.hub[event] || []).findIndex(h => h === handler); - if (i > -1) this.hub[event].splice(i, 1); - } -}); - const CSVToArray = (data, delimiter = ',', omitFirstRow = false) => - data - .slice(omitFirstRow ? data.indexOf('\n') + 1 : 0) - .split('\n') - .map(v => v.split(delimiter)); - const CSVToJSON = (data, delimiter = ',') => { - const titles = data.slice(0, data.indexOf('\n')).split(delimiter); - return data - .slice(data.indexOf('\n') + 1) - .split('\n') - .map(v => { - const values = v.split(delimiter); - return titles.reduce((obj, title, index) => ((obj[title] = values[index]), obj), {}); - }); -}; - const currentURL = () => window.location.href; - const curry = (fn, arity = fn.length, ...args) => - arity <= args.length ? fn(...args) : curry.bind(null, fn, arity, ...args); - const dayOfYear = date => - Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24); - const debounce = (fn, ms = 0) => { - let timeoutId; - return function(...args) { - clearTimeout(timeoutId); - timeoutId = setTimeout(() => fn.apply(this, args), ms); - }; -}; - const decapitalize = ([first, ...rest], upperRest = false) => - first.toLowerCase() + (upperRest ? rest.join('').toUpperCase() : rest.join('')); - const deepClone = obj => { - let clone = Object.assign({}, obj); - Object.keys(clone).forEach( - key => (clone[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key]) - ); - return Array.isArray(obj) ? (clone.length = obj.length) && Array.from(clone) : clone; -}; - const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v))); - const deepFreeze = obj => - Object.keys(obj).forEach( - prop => - !(obj[prop] instanceof Object) || Object.isFrozen(obj[prop]) ? null : deepFreeze(obj[prop]) - ) || Object.freeze(obj); - const defaults = (obj, ...defs) => Object.assign({}, obj, ...defs.reverse(), obj); - const defer = (fn, ...args) => setTimeout(fn, 1, ...args); - const degreesToRads = deg => (deg * Math.PI) / 180.0; - const delay = (fn, wait, ...args) => setTimeout(fn, wait, ...args); - const detectDeviceType = () => - /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) - ? 'Mobile' - : 'Desktop'; - const difference = (a, b) => { - const s = new Set(b); - return a.filter(x => !s.has(x)); -}; - const differenceBy = (a, b, fn) => { - const s = new Set(b.map(fn)); - return a.filter(x => !s.has(fn(x))); -}; - const differenceWith = (arr, val, comp) => arr.filter(a => val.findIndex(b => comp(a, b)) === -1); - const dig = (obj, target) => - target in obj - ? obj[target] - : Object.values(obj).reduce((acc, val) => { - if (acc !== undefined) return acc; - if (typeof val === 'object') return dig(val, target); - }, undefined); - const digitize = n => [...`${n}`].map(i => parseInt(i)); - const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0); - const drop = (arr, n = 1) => arr.slice(n); - const dropRight = (arr, n = 1) => arr.slice(0, -n); - const dropRightWhile = (arr, func) => { - while (arr.length > 0 && !func(arr[arr.length - 1])) arr = arr.slice(0, -1); - return arr; -}; - const dropWhile = (arr, func) => { - while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1); - return arr; -}; - const elementContains = (parent, child) => parent !== child && parent.contains(child); - const elementIsVisibleInViewport = (el, partiallyVisible = false) => { - const { top, left, bottom, right } = el.getBoundingClientRect(); - const { innerHeight, innerWidth } = window; - return partiallyVisible - ? ((top > 0 && top < innerHeight) || (bottom > 0 && bottom < innerHeight)) && - ((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth)) - : top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth; -}; - const elo = ([...ratings], kFactor = 32, selfRating) => { - const [a, b] = ratings; - const expectedScore = (self, opponent) => 1 / (1 + 10 ** ((opponent - self) / 400)); - const newRating = (rating, i) => - (selfRating || rating) + kFactor * (i - expectedScore(i ? a : b, i ? b : a)); - if (ratings.length === 2) return [newRating(a, 1), newRating(b, 0)]; - - for (let i = 0, len = ratings.length; i < len; i++) { - let j = i; - while (j < len - 1) { - j++; - [ratings[i], ratings[j]] = elo([ratings[i], ratings[j]], kFactor); - } - } - return ratings; -}; - const equals = (a, b) => { - if (a === b) return true; - if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime(); - if (!a || !b || (typeof a !== 'object' && typeof b !== 'object')) return a === b; - if (a === null || a === undefined || b === null || b === undefined) return false; - if (a.prototype !== b.prototype) return false; - let keys = Object.keys(a); - if (keys.length !== Object.keys(b).length) return false; - return keys.every(k => equals(a[k], b[k])); -}; - const escapeHTML = str => - str.replace( - /[&<>'"]/g, - tag => - ({ - '&': '&', - '<': '<', - '>': '>', - "'": ''', - '"': '"' - }[tag] || tag) - ); - const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); - const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === nth - 1); - const extendHex = shortHex => - '#' + - shortHex - .slice(shortHex.startsWith('#') ? 1 : 0) - .split('') - .map(x => x + x) - .join(''); - const factorial = n => - n < 0 - ? (() => { - throw new TypeError('Negative numbers are not allowed!'); - })() - : n <= 1 - ? 1 - : n * factorial(n - 1); - const fibonacci = n => - Array.from({ length: n }).reduce( - (acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), - [] - ); - const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i)); - const filterNonUniqueBy = (arr, fn) => - arr.filter((v, i) => arr.every((x, j) => (i === j) === fn(v, x, i, j))); - const findKey = (obj, fn) => Object.keys(obj).find(key => fn(obj[key], key, obj)); - const findLast = (arr, fn) => arr.filter(fn).pop(); - const findLastIndex = (arr, fn) => - arr - .map((val, i) => [i, val]) - .filter(([i, val]) => fn(val, i, arr)) - .pop()[0]; - const findLastKey = (obj, fn) => - Object.keys(obj) - .reverse() - .find(key => fn(obj[key], key, obj)); - const flatten = (arr, depth = 1) => - arr.reduce((a, v) => a.concat(depth > 1 && Array.isArray(v) ? flatten(v, depth - 1) : v), []); - const flattenObject = (obj, prefix = '') => - Object.keys(obj).reduce((acc, k) => { - const pre = prefix.length ? prefix + '.' : ''; - if (typeof obj[k] === 'object') Object.assign(acc, flattenObject(obj[k], pre + k)); - else acc[pre + k] = obj[k]; - return acc; - }, {}); +const colorize = (...args) => ({ + black: `\x1b[30m${args.join(' ')}`, + red: `\x1b[31m${args.join(' ')}`, + green: `\x1b[32m${args.join(' ')}`, + yellow: `\x1b[33m${args.join(' ')}`, + blue: `\x1b[34m${args.join(' ')}`, + magenta: `\x1b[35m${args.join(' ')}`, + cyan: `\x1b[36m${args.join(' ')}`, + white: `\x1b[37m${args.join(' ')}`, + bgBlack: `\x1b[40m${args.join(' ')}\x1b[0m`, + bgRed: `\x1b[41m${args.join(' ')}\x1b[0m`, + bgGreen: `\x1b[42m${args.join(' ')}\x1b[0m`, + bgYellow: `\x1b[43m${args.join(' ')}\x1b[0m`, + bgBlue: `\x1b[44m${args.join(' ')}\x1b[0m`, + bgMagenta: `\x1b[45m${args.join(' ')}\x1b[0m`, + bgCyan: `\x1b[46m${args.join(' ')}\x1b[0m`, + bgWhite: `\x1b[47m${args.join(' ')}\x1b[0m` +}); +const compact = arr => arr.filter(Boolean); +const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args))); +const composeRight = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args))); +const converge = (converger, fns) => (...args) => converger(...fns.map(fn => fn.apply(null, args))); +const copyToClipboard = str => { + const el = document.createElement('textarea'); + el.value = str; + el.setAttribute('readonly', ''); + el.style.position = 'absolute'; + el.style.left = '-9999px'; + document.body.appendChild(el); + const selected = + document.getSelection().rangeCount > 0 ? document.getSelection().getRangeAt(0) : false; + el.select(); + document.execCommand('copy'); + document.body.removeChild(el); + if (selected) { + document.getSelection().removeAllRanges(); + document.getSelection().addRange(selected); + } +}; +const countBy = (arr, fn) => + arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => { + acc[val] = (acc[val] || 0) + 1; + return acc; + }, {}); +const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0); +const counter = (selector, start, end, step = 1, duration = 2000) => { + let current = start, + _step = (end - start) * step < 0 ? -step : step, + timer = setInterval(() => { + current += _step; + document.querySelector(selector).innerHTML = current; + if (current >= end) document.querySelector(selector).innerHTML = end; + if (current >= end) clearInterval(timer); + }, Math.abs(Math.floor(duration / (end - start)))); + return timer; +}; +const createElement = str => { + const el = document.createElement('div'); + el.innerHTML = str; + return el.firstElementChild; +}; +const createEventHub = () => ({ + hub: Object.create(null), + emit(event, data) { + (this.hub[event] || []).forEach(handler => handler(data)); + }, + on(event, handler) { + if (!this.hub[event]) this.hub[event] = []; + this.hub[event].push(handler); + }, + off(event, handler) { + const i = (this.hub[event] || []).findIndex(h => h === handler); + if (i > -1) this.hub[event].splice(i, 1); + } +}); +const currentURL = () => window.location.href; +const curry = (fn, arity = fn.length, ...args) => + arity <= args.length ? fn(...args) : curry.bind(null, fn, arity, ...args); +const dayOfYear = date => + Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24); +const debounce = (fn, ms = 0) => { + let timeoutId; + return function(...args) { + clearTimeout(timeoutId); + timeoutId = setTimeout(() => fn.apply(this, args), ms); + }; +}; +const decapitalize = ([first, ...rest], upperRest = false) => + first.toLowerCase() + (upperRest ? rest.join('').toUpperCase() : rest.join('')); +const deepClone = obj => { + let clone = Object.assign({}, obj); + Object.keys(clone).forEach( + key => (clone[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key]) + ); + return Array.isArray(obj) ? (clone.length = obj.length) && Array.from(clone) : clone; +}; +const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v))); +const deepFreeze = obj => + Object.keys(obj).forEach( + prop => + !(obj[prop] instanceof Object) || Object.isFrozen(obj[prop]) ? null : deepFreeze(obj[prop]) + ) || Object.freeze(obj); +const defaults = (obj, ...defs) => Object.assign({}, obj, ...defs.reverse(), obj); +const defer = (fn, ...args) => setTimeout(fn, 1, ...args); +const degreesToRads = deg => (deg * Math.PI) / 180.0; +const delay = (fn, wait, ...args) => setTimeout(fn, wait, ...args); +const detectDeviceType = () => + /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) + ? 'Mobile' + : 'Desktop'; +const difference = (a, b) => { + const s = new Set(b); + return a.filter(x => !s.has(x)); +}; +const differenceBy = (a, b, fn) => { + const s = new Set(b.map(fn)); + return a.filter(x => !s.has(fn(x))); +}; +const differenceWith = (arr, val, comp) => arr.filter(a => val.findIndex(b => comp(a, b)) === -1); +const dig = (obj, target) => + target in obj + ? obj[target] + : Object.values(obj).reduce((acc, val) => { + if (acc !== undefined) return acc; + if (typeof val === 'object') return dig(val, target); + }, undefined); +const digitize = n => [...`${n}`].map(i => parseInt(i)); +const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0); +const drop = (arr, n = 1) => arr.slice(n); +const dropRight = (arr, n = 1) => arr.slice(0, -n); +const dropRightWhile = (arr, func) => { + while (arr.length > 0 && !func(arr[arr.length - 1])) arr = arr.slice(0, -1); + return arr; +}; +const dropWhile = (arr, func) => { + while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1); + return arr; +}; +const elementContains = (parent, child) => parent !== child && parent.contains(child); +const elementIsVisibleInViewport = (el, partiallyVisible = false) => { + const { top, left, bottom, right } = el.getBoundingClientRect(); + const { innerHeight, innerWidth } = window; + return partiallyVisible + ? ((top > 0 && top < innerHeight) || (bottom > 0 && bottom < innerHeight)) && + ((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth)) + : top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth; +}; +const elo = ([...ratings], kFactor = 32, selfRating) => { + const [a, b] = ratings; + const expectedScore = (self, opponent) => 1 / (1 + 10 ** ((opponent - self) / 400)); + const newRating = (rating, i) => + (selfRating || rating) + kFactor * (i - expectedScore(i ? a : b, i ? b : a)); + if (ratings.length === 2) return [newRating(a, 1), newRating(b, 0)]; + + for (let i = 0, len = ratings.length; i < len; i++) { + let j = i; + while (j < len - 1) { + j++; + [ratings[i], ratings[j]] = elo([ratings[i], ratings[j]], kFactor); + } + } + return ratings; +}; +const equals = (a, b) => { + if (a === b) return true; + if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime(); + if (!a || !b || (typeof a !== 'object' && typeof b !== 'object')) return a === b; + if (a === null || a === undefined || b === null || b === undefined) return false; + if (a.prototype !== b.prototype) return false; + let keys = Object.keys(a); + if (keys.length !== Object.keys(b).length) return false; + return keys.every(k => equals(a[k], b[k])); +}; +const escapeHTML = str => + str.replace( + /[&<>'"]/g, + tag => + ({ + '&': '&', + '<': '<', + '>': '>', + "'": ''', + '"': '"' + }[tag] || tag) + ); +const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); +const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === nth - 1); +const extendHex = shortHex => + '#' + + shortHex + .slice(shortHex.startsWith('#') ? 1 : 0) + .split('') + .map(x => x + x) + .join(''); +const factorial = n => + n < 0 + ? (() => { + throw new TypeError('Negative numbers are not allowed!'); + })() + : n <= 1 + ? 1 + : n * factorial(n - 1); +const fibonacci = n => + Array.from({ length: n }).reduce( + (acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), + [] + ); +const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i)); +const filterNonUniqueBy = (arr, fn) => + arr.filter((v, i) => arr.every((x, j) => (i === j) === fn(v, x, i, j))); +const findKey = (obj, fn) => Object.keys(obj).find(key => fn(obj[key], key, obj)); +const findLast = (arr, fn) => arr.filter(fn).pop(); +const findLastIndex = (arr, fn) => + arr + .map((val, i) => [i, val]) + .filter(([i, val]) => fn(val, i, arr)) + .pop()[0]; +const findLastKey = (obj, fn) => + Object.keys(obj) + .reverse() + .find(key => fn(obj[key], key, obj)); +const flatten = (arr, depth = 1) => + arr.reduce((a, v) => a.concat(depth > 1 && Array.isArray(v) ? flatten(v, depth - 1) : v), []); +const flattenObject = (obj, prefix = '') => + Object.keys(obj).reduce((acc, k) => { + const pre = prefix.length ? prefix + '.' : ''; + if (typeof obj[k] === 'object') Object.assign(acc, flattenObject(obj[k], pre + k)); + else acc[pre + k] = obj[k]; + return acc; + }, {}); const flip = fn => (first, ...rest) => fn(...rest, first); - const forEachRight = (arr, callback) => - arr - .slice(0) - .reverse() - .forEach(callback); - const formatDuration = ms => { - if (ms < 0) ms = -ms; - const time = { - day: Math.floor(ms / 86400000), - hour: Math.floor(ms / 3600000) % 24, - minute: Math.floor(ms / 60000) % 60, - second: Math.floor(ms / 1000) % 60, - millisecond: Math.floor(ms) % 1000 - }; - return Object.entries(time) - .filter(val => val[1] !== 0) - .map(([key, val]) => `${val} ${key}${val !== 1 ? 's' : ''}`) - .join(', '); -}; - const forOwn = (obj, fn) => Object.keys(obj).forEach(key => fn(obj[key], key, obj)); - const forOwnRight = (obj, fn) => - Object.keys(obj) - .reverse() - .forEach(key => fn(obj[key], key, obj)); - const fromCamelCase = (str, separator = '_') => - str - .replace(/([a-z\d])([A-Z])/g, '$1' + separator + '$2') - .replace(/([A-Z]+)([A-Z][a-z\d]+)/g, '$1' + separator + '$2') - .toLowerCase(); - const functionName = fn => (console.debug(fn.name), fn); - const functions = (obj, inherited = false) => - (inherited - ? [...Object.keys(obj), ...Object.keys(Object.getPrototypeOf(obj))] - : Object.keys(obj) - ).filter(key => typeof obj[key] === 'function'); - const gcd = (...arr) => { - const _gcd = (x, y) => (!y ? x : gcd(y, x % y)); - return [...arr].reduce((a, b) => _gcd(a, b)); -}; - const geometricProgression = (end, start = 1, step = 2) => - Array.from({ length: Math.floor(Math.log(end / start) / Math.log(step)) + 1 }).map( - (v, i) => start * step ** i - ); - const get = (from, ...selectors) => - [...selectors].map(s => - s - .replace(/\[([^\[\]]*)\]/g, '.$1.') - .split('.') - .filter(t => t !== '') - .reduce((prev, cur) => prev && prev[cur], from) - ); - const getColonTimeFromDate = date => date.toTimeString().slice(0, 8); - const getDaysDiffBetweenDates = (dateInitial, dateFinal) => - (dateFinal - dateInitial) / (1000 * 3600 * 24); - const getImages = (el, includeDuplicates = false) => { - const images = [...el.getElementsByTagName('img')].map(img => img.getAttribute('src')); - return includeDuplicates ? images : [...new Set(images)]; -}; - const getMeridiemSuffixOfInteger = num => - num === 0 || num === 24 - ? 12 + 'am' - : num === 12 - ? 12 + 'pm' - : num < 12 - ? (num % 12) + 'am' - : (num % 12) + 'pm'; - const getScrollPosition = (el = window) => ({ - x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft, - y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop -}); - const getStyle = (el, ruleName) => getComputedStyle(el)[ruleName]; - const getType = v => - v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name.toLowerCase(); - const getURLParameters = url => - (url.match(/([^?=&]+)(=([^&]*))/g) || []).reduce( - (a, v) => ((a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1)), a), - {} - ); - const groupBy = (arr, fn) => - arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val, i) => { - acc[val] = (acc[val] || []).concat(arr[i]); - return acc; - }, {}); - const hammingDistance = (num1, num2) => ((num1 ^ num2).toString(2).match(/1/g) || '').length; - const hasClass = (el, className) => el.classList.contains(className); - const hasFlags = (...flags) => - flags.every(flag => process.argv.includes(/^-{1,2}/.test(flag) ? flag : '--' + flag)); - const hashBrowser = val => - crypto.subtle.digest('SHA-256', new TextEncoder('utf-8').encode(val)).then(h => { - let hexes = [], - view = new DataView(h); - for (let i = 0; i < view.byteLength; i += 4) - hexes.push(('00000000' + view.getUint32(i).toString(16)).slice(-8)); - return hexes.join(''); - }); - -const hashNode = val => - new Promise(resolve => - setTimeout( - () => - resolve( - crypto - .createHash('sha256') - .update(val) - .digest('hex') - ), - 0 - ) - ); - const head = arr => arr[0]; - const hexToRGB = hex => { - let alpha = false, - h = hex.slice(hex.startsWith('#') ? 1 : 0); - if (h.length === 3) h = [...h].map(x => x + x).join(''); - else if (h.length === 8) alpha = true; - h = parseInt(h, 16); - return ( - 'rgb' + - (alpha ? 'a' : '') + - '(' + - (h >>> (alpha ? 24 : 16)) + - ', ' + - ((h & (alpha ? 0x00ff0000 : 0x00ff00)) >>> (alpha ? 16 : 8)) + - ', ' + - ((h & (alpha ? 0x0000ff00 : 0x0000ff)) >>> (alpha ? 8 : 0)) + - (alpha ? `, ${h & 0x000000ff}` : '') + - ')' - ); -}; - const hide = els => els.forEach(e => (e.style.display = 'none')); - const httpGet = (url, callback, err = console.error) => { - const request = new XMLHttpRequest(); - request.open('GET', url, true); - request.onload = () => callback(request.responseText); - request.onerror = () => err(request); - request.send(); -}; - const httpPost = (url, data, callback, err = console.error) => { - const request = new XMLHttpRequest(); - request.open('POST', url, true); - request.setRequestHeader('Content-type', 'application/json; charset=utf-8'); - request.onload = () => callback(request.responseText); - request.onerror = () => err(request); - request.send(data); -}; - const httpsRedirect = () => { - if (location.protocol !== 'https:') location.replace('https://' + location.href.split('//')[1]); -}; - const hz = (fn, iterations = 100) => { - const before = performance.now(); - for (let i = 0; i < iterations; i++) fn(); - return (1000 * iterations) / (performance.now() - before); -}; - const indentString = (str, count, indent = ' ') => str.replace(/^/gm, indent.repeat(count)); - const indexOfAll = (arr, val) => arr.reduce((acc, el, i) => (el === val ? [...acc, i] : acc), []); - const initial = arr => arr.slice(0, -1); - const initialize2DArray = (w, h, val = null) => - Array.from({ length: h }).map(() => Array.from({ length: w }).fill(val)); - const initializeArrayWithRange = (end, start = 0, step = 1) => - Array.from({ length: Math.ceil((end - start + 1) / step) }, (v, i) => i * step + start); - const initializeArrayWithRangeRight = (end, start = 0, step = 1) => - Array.from({ length: Math.ceil((end + 1 - start) / step) }).map( - (v, i, arr) => (arr.length - i - 1) * step + start - ); - const initializeArrayWithValues = (n, val = 0) => Array(n).fill(val); - const initializeNDArray = (val, ...args) => - args.length === 0 - ? val - : Array.from({ length: args[0] }).map(() => initializeNDArray(val, ...args.slice(1))); - const inRange = (n, start, end = null) => { - if (end && start > end) [end, start] = [start, end]; - return end == null ? n >= 0 && n < start : n >= start && n < end; -}; - const insertAfter = (el, htmlString) => el.insertAdjacentHTML('afterend', htmlString); - const insertBefore = (el, htmlString) => el.insertAdjacentHTML('beforebegin', htmlString); - const intersection = (a, b) => { - const s = new Set(b); - return a.filter(x => s.has(x)); -}; - const intersectionBy = (a, b, fn) => { - const s = new Set(b.map(fn)); - return a.filter(x => s.has(fn(x))); -}; - const intersectionWith = (a, b, comp) => a.filter(x => b.findIndex(y => comp(x, y)) !== -1); - const invertKeyValues = (obj, fn) => - Object.keys(obj).reduce((acc, key) => { - const val = fn ? fn(obj[key]) : obj[key]; - acc[val] = acc[val] || []; - acc[val].push(key); - return acc; - }, {}); - const is = (type, val) => ![, null].includes(val) && val.constructor === type; - const isAbsoluteURL = str => /^[a-z][a-z0-9+.-]*:/.test(str); - const isAfterDate = (dateA, dateB) => dateA > dateB; - const isAnagram = (str1, str2) => { - const normalize = str => - str - .toLowerCase() - .replace(/[^a-z0-9]/gi, '') - .split('') - .sort() - .join(''); - return normalize(str1) === normalize(str2); -}; - const isArrayLike = obj => obj != null && typeof obj[Symbol.iterator] === 'function'; - const isBeforeDate = (dateA, dateB) => dateA < dateB; - const isBoolean = val => typeof val === 'boolean'; - const isBrowser = () => ![typeof window, typeof document].includes('undefined'); - const isBrowserTabFocused = () => !document.hidden; - const isDivisible = (dividend, divisor) => dividend % divisor === 0; - const isDuplexStream = val => - val !== null && - typeof val === 'object' && - typeof val.pipe === 'function' && - typeof val._read === 'function' && - typeof val._readableState === 'object' && - typeof val._write === 'function' && - typeof val._writableState === 'object'; - const isEmpty = val => val == null || !(Object.keys(val) || val).length; - const isEven = num => num % 2 === 0; - const isFunction = val => typeof val === 'function'; - const isLowerCase = str => str === str.toLowerCase(); - const isNil = val => val === undefined || val === null; - const isNull = val => val === null; - const isNumber = val => typeof val === 'number'; - const isObject = obj => obj === Object(obj); - const isObjectLike = val => val !== null && typeof val === 'object'; - const isPlainObject = val => !!val && typeof val === 'object' && val.constructor === Object; - const isPrime = num => { - const boundary = Math.floor(Math.sqrt(num)); - for (var i = 2; i <= boundary; i++) if (num % i === 0) return false; - return num >= 2; -}; - const isPrimitive = val => Object(val) !== val; - const isPromiseLike = obj => - obj !== null && - (typeof obj === 'object' || typeof obj === 'function') && - typeof obj.then === 'function'; - const isReadableStream = val => - val !== null && - typeof val === 'object' && - typeof val.pipe === 'function' && - typeof val._read === 'function' && - typeof val._readableState === 'object'; - const isSameDate = (dateA, dateB) => dateA.toISOString() === dateB.toISOString(); - const isSorted = arr => { - let direction = -(arr[0] - arr[1]); - for (let [i, val] of arr.entries()) { - direction = !direction ? -(arr[i - 1] - arr[i]) : direction; - if (i === arr.length - 1) return !direction ? 0 : direction; - else if ((val - arr[i + 1]) * direction > 0) return 0; - } -}; - const isStream = val => val !== null && typeof val === 'object' && typeof val.pipe === 'function'; - const isString = val => typeof val === 'string'; - const isSymbol = val => typeof val === 'symbol'; - const isTravisCI = () => 'TRAVIS' in process.env && 'CI' in process.env; - const isUndefined = val => val === undefined; - const isUpperCase = str => str === str.toUpperCase(); - const isValidJSON = obj => { - try { - JSON.parse(obj); - return true; - } catch (e) { - return false; - } -}; - const isWritableStream = val => - val !== null && - typeof val === 'object' && - typeof val.pipe === 'function' && - typeof val._write === 'function' && - typeof val._writableState === 'object'; - const join = (arr, separator = ',', end = separator) => - arr.reduce( - (acc, val, i) => - i === arr.length - 2 - ? acc + val + end - : i === arr.length - 1 - ? acc + val - : acc + val + separator, - '' - ); - const JSONtoCSV = (arr, columns, delimiter = ',') => - [ - columns.join(delimiter), - ...arr.map(obj => - columns.reduce( - (acc, key) => `${acc}${!acc.length ? '' : delimiter}"${!obj[key] ? '' : obj[key]}"`, - '' - ) - ) - ].join('\n'); - -const JSONToFile = (obj, filename) => - fs.writeFile(`${filename}.json`, JSON.stringify(obj, null, 2)); - const last = arr => arr[arr.length - 1]; - const lcm = (...arr) => { - const gcd = (x, y) => (!y ? x : gcd(y, x % y)); - const _lcm = (x, y) => (x * y) / gcd(x, y); - return [...arr].reduce((a, b) => _lcm(a, b)); -}; - const longestItem = (val, ...vals) => - [val, ...vals].reduce((a, x) => (x.length > a.length ? x : a)); - const lowercaseKeys = obj => - Object.keys(obj).reduce((acc, key) => { - acc[key.toLowerCase()] = obj[key]; - return acc; - }, {}); - const luhnCheck = num => { - let arr = (num + '') - .split('') - .reverse() - .map(x => parseInt(x)); - let lastDigit = arr.splice(0, 1)[0]; - let sum = arr.reduce((acc, val, i) => (i % 2 !== 0 ? acc + val : acc + ((val * 2) % 9) || 9), 0); - sum += lastDigit; - return sum % 10 === 0; -}; - const mapKeys = (obj, fn) => - Object.keys(obj).reduce((acc, k) => { - acc[fn(obj[k], k, obj)] = obj[k]; - return acc; - }, {}); - const mapObject = (arr, fn) => - (a => ( - (a = [arr, arr.map(fn)]), a[0].reduce((acc, val, ind) => ((acc[val] = a[1][ind]), acc), {}) - ))(); - const mapString = (str, fn) => - str - .split('') - .map((c, i) => fn(c, i, str)) - .join(''); - const mapValues = (obj, fn) => - Object.keys(obj).reduce((acc, k) => { - acc[k] = fn(obj[k], k, obj); - return acc; - }, {}); - const mask = (cc, num = 4, mask = '*') => `${cc}`.slice(-num).padStart(`${cc}`.length, mask); - const matches = (obj, source) => - Object.keys(source).every(key => obj.hasOwnProperty(key) && obj[key] === source[key]); - const matchesWith = (obj, source, fn) => - Object.keys(source).every( - key => - obj.hasOwnProperty(key) && fn - ? fn(obj[key], source[key], key, obj, source) - : obj[key] == source[key] - ); - const maxBy = (arr, fn) => Math.max(...arr.map(typeof fn === 'function' ? fn : val => val[fn])); - const maxDate = (...dates) => new Date(Math.max.apply(null, ...dates)); - const maxN = (arr, n = 1) => [...arr].sort((a, b) => b - a).slice(0, n); - const median = arr => { - const mid = Math.floor(arr.length / 2), - nums = [...arr].sort((a, b) => a - b); - return arr.length % 2 !== 0 ? nums[mid] : (nums[mid - 1] + nums[mid]) / 2; -}; - const memoize = fn => { - const cache = new Map(); - const cached = function(val) { - return cache.has(val) ? cache.get(val) : cache.set(val, fn.call(this, val)) && cache.get(val); - }; - cached.cache = cache; - return cached; -}; - const merge = (...objs) => - [...objs].reduce( - (acc, obj) => - Object.keys(obj).reduce((a, k) => { - acc[k] = acc.hasOwnProperty(k) ? [].concat(acc[k]).concat(obj[k]) : obj[k]; - return acc; - }, {}), - {} - ); - const minBy = (arr, fn) => Math.min(...arr.map(typeof fn === 'function' ? fn : val => val[fn])); - const minDate = (...dates) => new Date(Math.min.apply(null, ...dates)); - const minN = (arr, n = 1) => [...arr].sort((a, b) => a - b).slice(0, n); - const mostPerformant = (fns, iterations = 10000) => { - const times = fns.map(fn => { - const before = performance.now(); - for (let i = 0; i < iterations; i++) fn(); - return performance.now() - before; - }); - return times.indexOf(Math.min(...times)); -}; - const negate = func => (...args) => !func(...args); - const nest = (items, id = null, link = 'parent_id') => - items - .filter(item => item[link] === id) - .map(item => ({ ...item, children: nest(items, item.id) })); - const nodeListToArray = nodeList => [...nodeList]; - const none = (arr, fn = Boolean) => !arr.some(fn); - const nthArg = n => (...args) => args.slice(n)[0]; - const nthElement = (arr, n = 0) => (n === -1 ? arr.slice(n) : arr.slice(n, n + 1))[0]; - const objectFromPairs = arr => arr.reduce((a, [key, val]) => ((a[key] = val), a), {}); - const objectToPairs = obj => Object.keys(obj).map(k => [k, obj[k]]); - const observeMutations = (element, callback, options) => { - const observer = new MutationObserver(mutations => mutations.forEach(m => callback(m))); - observer.observe( - element, - Object.assign( - { - childList: true, - attributes: true, - attributeOldValue: true, - characterData: true, - characterDataOldValue: true, - subtree: true - }, - options - ) - ); - return observer; -}; - const off = (el, evt, fn, opts = false) => el.removeEventListener(evt, fn, opts); - const offset = (arr, offset) => [...arr.slice(offset), ...arr.slice(0, offset)]; - const omit = (obj, arr) => - Object.keys(obj) - .filter(k => !arr.includes(k)) - .reduce((acc, key) => ((acc[key] = obj[key]), acc), {}); - const omitBy = (obj, fn) => - Object.keys(obj) - .filter(k => !fn(obj[k], k)) - .reduce((acc, key) => ((acc[key] = obj[key]), acc), {}); - const on = (el, evt, fn, opts = {}) => { - const delegatorFn = e => e.target.matches(opts.target) && fn.call(e.target, e); - el.addEventListener(evt, opts.target ? delegatorFn : fn, opts.options || false); - if (opts.target) return delegatorFn; -}; - const once = fn => { - let called = false; - return function(...args) { - if (called) return; - called = true; - return fn.apply(this, args); - }; -}; - const onUserInputChange = callback => { - let type = 'mouse', - lastTime = 0; - const mousemoveHandler = () => { - const now = performance.now(); - if (now - lastTime < 20) - (type = 'mouse'), callback(type), document.removeEventListener('mousemove', mousemoveHandler); - lastTime = now; - }; - document.addEventListener('touchstart', () => { - if (type === 'touch') return; - (type = 'touch'), callback(type), document.addEventListener('mousemove', mousemoveHandler); - }); -}; - const orderBy = (arr, props, orders) => - [...arr].sort((a, b) => - props.reduce((acc, prop, i) => { - if (acc === 0) { - const [p1, p2] = orders && orders[i] === 'desc' ? [b[prop], a[prop]] : [a[prop], b[prop]]; - acc = p1 > p2 ? 1 : p1 < p2 ? -1 : 0; - } - return acc; - }, 0) - ); - const over = (...fns) => (...args) => fns.map(fn => fn.apply(null, args)); - const overArgs = (fn, transforms) => (...args) => fn(...args.map((val, i) => transforms[i](val))); - const pad = (str, length, char = ' ') => - str.padStart((str.length + length) / 2, char).padEnd(length, char); - const palindrome = str => { - const s = str.toLowerCase().replace(/[\W_]/g, ''); - return s === [...s].reverse().join(''); -}; - const parseCookie = str => - str - .split(';') - .map(v => v.split('=')) - .reduce((acc, v) => { - acc[decodeURIComponent(v[0].trim())] = decodeURIComponent(v[1].trim()); - return acc; - }, {}); - const partial = (fn, ...partials) => (...args) => fn(...partials, ...args); - const partialRight = (fn, ...partials) => (...args) => fn(...args, ...partials); - const partition = (arr, fn) => - arr.reduce( - (acc, val, i, arr) => { - acc[fn(val, i, arr) ? 0 : 1].push(val); - return acc; - }, - [[], []] - ); - const percentile = (arr, val) => - (100 * arr.reduce((acc, v) => acc + (v < val ? 1 : 0) + (v === val ? 0.5 : 0), 0)) / arr.length; - const permutations = arr => { - if (arr.length <= 2) return arr.length === 2 ? [arr, [arr[1], arr[0]]] : arr; - return arr.reduce( - (acc, item, i) => - acc.concat( - permutations([...arr.slice(0, i), ...arr.slice(i + 1)]).map(val => [item, ...val]) - ), - [] - ); -}; - const pick = (obj, arr) => - arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {}); - const pickBy = (obj, fn) => - Object.keys(obj) - .filter(k => fn(obj[k], k)) - .reduce((acc, key) => ((acc[key] = obj[key]), acc), {}); - const pipeAsyncFunctions = (...fns) => arg => fns.reduce((p, f) => p.then(f), Promise.resolve(arg)); - const pipeFunctions = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args))); - const pluralize = (val, word, plural = word + 's') => { - const _pluralize = (num, word, plural = word + 's') => - [1, -1].includes(Number(num)) ? word : plural; - if (typeof val === 'object') return (num, word) => _pluralize(num, word, val[word]); - return _pluralize(val, word, plural); -}; - const powerset = arr => arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]); - const prefix = prop => { - const capitalizedProp = prop.charAt(0).toUpperCase() + prop.slice(1); - const prefixes = ['', 'webkit', 'moz', 'ms', 'o']; - const i = prefixes.findIndex( - prefix => typeof document.body.style[prefix ? prefix + capitalizedProp : prop] !== 'undefined' - ); - return i !== -1 ? (i === 0 ? prop : prefixes[i] + capitalizedProp) : null; -}; - const prettyBytes = (num, precision = 3, addSpace = true) => { - const UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; - if (Math.abs(num) < 1) return num + (addSpace ? ' ' : '') + UNITS[0]; - const exponent = Math.min(Math.floor(Math.log10(num < 0 ? -num : num) / 3), UNITS.length - 1); - const n = Number(((num < 0 ? -num : num) / 1000 ** exponent).toPrecision(precision)); - return (num < 0 ? '-' : '') + n + (addSpace ? ' ' : '') + UNITS[exponent]; -}; - const primes = num => { - let arr = Array.from({ length: num - 1 }).map((x, i) => i + 2), - sqroot = Math.floor(Math.sqrt(num)), - numsTillSqroot = Array.from({ length: sqroot - 1 }).map((x, i) => i + 2); - numsTillSqroot.forEach(x => (arr = arr.filter(y => y % x !== 0 || y === x))); - return arr; -}; - const promisify = func => (...args) => - new Promise((resolve, reject) => - func(...args, (err, result) => (err ? reject(err) : resolve(result))) - ); - const pull = (arr, ...args) => { - let argState = Array.isArray(args[0]) ? args[0] : args; - let pulled = arr.filter((v, i) => !argState.includes(v)); - arr.length = 0; - pulled.forEach(v => arr.push(v)); -}; - const pullAtIndex = (arr, pullArr) => { - let removed = []; - let pulled = arr - .map((v, i) => (pullArr.includes(i) ? removed.push(v) : v)) - .filter((v, i) => !pullArr.includes(i)); - arr.length = 0; - pulled.forEach(v => arr.push(v)); - return removed; -}; - const pullAtValue = (arr, pullArr) => { - let removed = [], - pushToRemove = arr.forEach((v, i) => (pullArr.includes(v) ? removed.push(v) : v)), - mutateTo = arr.filter((v, i) => !pullArr.includes(v)); - arr.length = 0; - mutateTo.forEach(v => arr.push(v)); - return removed; -}; - const pullBy = (arr, ...args) => { - const length = args.length; - let fn = length > 1 ? args[length - 1] : undefined; - fn = typeof fn == 'function' ? (args.pop(), fn) : undefined; - let argState = (Array.isArray(args[0]) ? args[0] : args).map(val => fn(val)); - let pulled = arr.filter((v, i) => !argState.includes(fn(v))); - arr.length = 0; - pulled.forEach(v => arr.push(v)); -}; - const radsToDegrees = rad => (rad * 180.0) / Math.PI; - const randomHexColorCode = () => { - let n = (Math.random() * 0xfffff * 1000000).toString(16); - return '#' + n.slice(0, 6); -}; - const randomIntArrayInRange = (min, max, n = 1) => - Array.from({ length: n }, () => Math.floor(Math.random() * (max - min + 1)) + min); - const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min; - const randomNumberInRange = (min, max) => Math.random() * (max - min) + min; - -const readFileLines = filename => - fs - .readFileSync(filename) - .toString('UTF8') - .split('\n'); - const rearg = (fn, indexes) => (...args) => fn(...indexes.map(i => args[i])); - const recordAnimationFrames = (callback, autoStart = true) => { - let running = true, - raf; - const stop = () => { - running = false; - cancelAnimationFrame(raf); - }; - const start = () => { - running = true; - run(); - }; - const run = () => { - raf = requestAnimationFrame(() => { - callback(); - if (running) run(); - }); - }; - if (autoStart) start(); - return { start, stop }; -}; - const redirect = (url, asLink = true) => - asLink ? (window.location.href = url) : window.location.replace(url); - const reducedFilter = (data, keys, fn) => - data.filter(fn).map(el => - keys.reduce((acc, key) => { - acc[key] = el[key]; - return acc; - }, {}) - ); - const reduceSuccessive = (arr, fn, acc) => - arr.reduce((res, val, i, arr) => (res.push(fn(res.slice(-1)[0], val, i, arr)), res), [acc]); - const reduceWhich = (arr, comparator = (a, b) => a - b) => - arr.reduce((a, b) => (comparator(a, b) >= 0 ? b : a)); - const reject = (pred, array) => array.filter((...args) => !pred(...args)); - const remove = (arr, func) => - Array.isArray(arr) - ? arr.filter(func).reduce((acc, val) => { - arr.splice(arr.indexOf(val), 1); - return acc.concat(val); - }, []) - : []; - const removeNonASCII = str => str.replace(/[^\x20-\x7E]/g, ''); - const renameKeys = (keysMap, obj) => - Object.keys(obj).reduce( - (acc, key) => ({ - ...acc, - ...{ [keysMap[key] || key]: obj[key] } - }), - {} - ); - const reverseString = str => [...str].reverse().join(''); - const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0'); - const round = (n, decimals = 0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`); - const runAsync = fn => { - const worker = new Worker( - URL.createObjectURL(new Blob([`postMessage((${fn})());`]), { - type: 'application/javascript; charset=utf-8' - }) - ); - return new Promise((res, rej) => { - worker.onmessage = ({ data }) => { - res(data), worker.terminate(); - }; - worker.onerror = err => { - rej(err), worker.terminate(); - }; - }); -}; - const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve()); - const sample = arr => arr[Math.floor(Math.random() * arr.length)]; - const sampleSize = ([...arr], n = 1) => { - let m = arr.length; - while (m) { - const i = Math.floor(Math.random() * m--); - [arr[m], arr[i]] = [arr[i], arr[m]]; - } - return arr.slice(0, n); -}; - const scrollToTop = () => { - const c = document.documentElement.scrollTop || document.body.scrollTop; - if (c > 0) { - window.requestAnimationFrame(scrollToTop); - window.scrollTo(0, c - c / 8); - } -}; - const sdbm = str => { - let arr = str.split(''); - return arr.reduce( - (hashCode, currentVal) => - (hashCode = currentVal.charCodeAt(0) + (hashCode << 6) + (hashCode << 16) - hashCode), - 0 - ); -}; - const serializeCookie = (name, val) => `${encodeURIComponent(name)}=${encodeURIComponent(val)}`; - const setStyle = (el, ruleName, val) => (el.style[ruleName] = val); - const shallowClone = obj => Object.assign({}, obj); - const shank = (arr, index = 0, delCount = 0, ...elements) => - arr - .slice(0, index) - .concat(elements) - .concat(arr.slice(index + delCount)); - const show = (...el) => [...el].forEach(e => (e.style.display = '')); - const shuffle = ([...arr]) => { - let m = arr.length; - while (m) { - const i = Math.floor(Math.random() * m--); - [arr[m], arr[i]] = [arr[i], arr[m]]; - } - return arr; -}; - const similarity = (arr, values) => arr.filter(v => values.includes(v)); - const size = val => - Array.isArray(val) - ? val.length - : val && typeof val === 'object' - ? val.size || val.length || Object.keys(val).length - : typeof val === 'string' - ? new Blob([val]).size - : 0; - const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); - const smoothScroll = element => - document.querySelector(element).scrollIntoView({ - behavior: 'smooth' - }); - const sortCharactersInString = str => [...str].sort((a, b) => a.localeCompare(b)).join(''); - const sortedIndex = (arr, n) => { - const isDescending = arr[0] > arr[arr.length - 1]; - const index = arr.findIndex(el => (isDescending ? n >= el : n <= el)); - return index === -1 ? arr.length : index; -}; - const sortedIndexBy = (arr, n, fn) => { - const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]); - const val = fn(n); - const index = arr.findIndex(el => (isDescending ? val >= fn(el) : val <= fn(el))); - return index === -1 ? arr.length : index; -}; - const sortedLastIndex = (arr, n) => { - const isDescending = arr[0] > arr[arr.length - 1]; - const index = arr.reverse().findIndex(el => (isDescending ? n <= el : n >= el)); - return index === -1 ? 0 : arr.length - index; -}; - const sortedLastIndexBy = (arr, n, fn) => { - const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]); - const val = fn(n); - const index = arr - .map(fn) - .reverse() - .findIndex(el => (isDescending ? val <= el : val >= el)); - return index === -1 ? 0 : arr.length - index; -}; - const splitLines = str => str.split(/\r?\n/); +const forEachRight = (arr, callback) => + arr + .slice(0) + .reverse() + .forEach(callback); +const forOwn = (obj, fn) => Object.keys(obj).forEach(key => fn(obj[key], key, obj)); +const forOwnRight = (obj, fn) => + Object.keys(obj) + .reverse() + .forEach(key => fn(obj[key], key, obj)); +const formatDuration = ms => { + if (ms < 0) ms = -ms; + const time = { + day: Math.floor(ms / 86400000), + hour: Math.floor(ms / 3600000) % 24, + minute: Math.floor(ms / 60000) % 60, + second: Math.floor(ms / 1000) % 60, + millisecond: Math.floor(ms) % 1000 + }; + return Object.entries(time) + .filter(val => val[1] !== 0) + .map(([key, val]) => `${val} ${key}${val !== 1 ? 's' : ''}`) + .join(', '); +}; +const fromCamelCase = (str, separator = '_') => + str + .replace(/([a-z\d])([A-Z])/g, '$1' + separator + '$2') + .replace(/([A-Z]+)([A-Z][a-z\d]+)/g, '$1' + separator + '$2') + .toLowerCase(); +const functionName = fn => (console.debug(fn.name), fn); +const functions = (obj, inherited = false) => + (inherited + ? [...Object.keys(obj), ...Object.keys(Object.getPrototypeOf(obj))] + : Object.keys(obj) + ).filter(key => typeof obj[key] === 'function'); +const gcd = (...arr) => { + const _gcd = (x, y) => (!y ? x : gcd(y, x % y)); + return [...arr].reduce((a, b) => _gcd(a, b)); +}; +const geometricProgression = (end, start = 1, step = 2) => + Array.from({ length: Math.floor(Math.log(end / start) / Math.log(step)) + 1 }).map( + (v, i) => start * step ** i + ); +const get = (from, ...selectors) => + [...selectors].map(s => + s + .replace(/\[([^\[\]]*)\]/g, '.$1.') + .split('.') + .filter(t => t !== '') + .reduce((prev, cur) => prev && prev[cur], from) + ); +const getColonTimeFromDate = date => date.toTimeString().slice(0, 8); +const getDaysDiffBetweenDates = (dateInitial, dateFinal) => + (dateFinal - dateInitial) / (1000 * 3600 * 24); +const getImages = (el, includeDuplicates = false) => { + const images = [...el.getElementsByTagName('img')].map(img => img.getAttribute('src')); + return includeDuplicates ? images : [...new Set(images)]; +}; +const getMeridiemSuffixOfInteger = num => + num === 0 || num === 24 + ? 12 + 'am' + : num === 12 + ? 12 + 'pm' + : num < 12 + ? (num % 12) + 'am' + : (num % 12) + 'pm'; +const getScrollPosition = (el = window) => ({ + x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft, + y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop +}); +const getStyle = (el, ruleName) => getComputedStyle(el)[ruleName]; +const getType = v => + v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name.toLowerCase(); +const getURLParameters = url => + (url.match(/([^?=&]+)(=([^&]*))/g) || []).reduce( + (a, v) => ((a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1)), a), + {} + ); +const groupBy = (arr, fn) => + arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val, i) => { + acc[val] = (acc[val] || []).concat(arr[i]); + return acc; + }, {}); +const hammingDistance = (num1, num2) => ((num1 ^ num2).toString(2).match(/1/g) || '').length; +const hasClass = (el, className) => el.classList.contains(className); +const hasFlags = (...flags) => + flags.every(flag => process.argv.includes(/^-{1,2}/.test(flag) ? flag : '--' + flag)); +const hashBrowser = val => + crypto.subtle.digest('SHA-256', new TextEncoder('utf-8').encode(val)).then(h => { + let hexes = [], + view = new DataView(h); + for (let i = 0; i < view.byteLength; i += 4) + hexes.push(('00000000' + view.getUint32(i).toString(16)).slice(-8)); + return hexes.join(''); + }); + +const hashNode = val => + new Promise(resolve => + setTimeout( + () => + resolve( + crypto + .createHash('sha256') + .update(val) + .digest('hex') + ), + 0 + ) + ); +const head = arr => arr[0]; +const hexToRGB = hex => { + let alpha = false, + h = hex.slice(hex.startsWith('#') ? 1 : 0); + if (h.length === 3) h = [...h].map(x => x + x).join(''); + else if (h.length === 8) alpha = true; + h = parseInt(h, 16); + return ( + 'rgb' + + (alpha ? 'a' : '') + + '(' + + (h >>> (alpha ? 24 : 16)) + + ', ' + + ((h & (alpha ? 0x00ff0000 : 0x00ff00)) >>> (alpha ? 16 : 8)) + + ', ' + + ((h & (alpha ? 0x0000ff00 : 0x0000ff)) >>> (alpha ? 8 : 0)) + + (alpha ? `, ${h & 0x000000ff}` : '') + + ')' + ); +}; +const hide = els => els.forEach(e => (e.style.display = 'none')); +const httpGet = (url, callback, err = console.error) => { + const request = new XMLHttpRequest(); + request.open('GET', url, true); + request.onload = () => callback(request.responseText); + request.onerror = () => err(request); + request.send(); +}; +const httpPost = (url, data, callback, err = console.error) => { + const request = new XMLHttpRequest(); + request.open('POST', url, true); + request.setRequestHeader('Content-type', 'application/json; charset=utf-8'); + request.onload = () => callback(request.responseText); + request.onerror = () => err(request); + request.send(data); +}; +const httpsRedirect = () => { + if (location.protocol !== 'https:') location.replace('https://' + location.href.split('//')[1]); +}; +const hz = (fn, iterations = 100) => { + const before = performance.now(); + for (let i = 0; i < iterations; i++) fn(); + return (1000 * iterations) / (performance.now() - before); +}; +const inRange = (n, start, end = null) => { + if (end && start > end) [end, start] = [start, end]; + return end == null ? n >= 0 && n < start : n >= start && n < end; +}; +const indentString = (str, count, indent = ' ') => str.replace(/^/gm, indent.repeat(count)); +const indexOfAll = (arr, val) => arr.reduce((acc, el, i) => (el === val ? [...acc, i] : acc), []); +const initial = arr => arr.slice(0, -1); +const initialize2DArray = (w, h, val = null) => + Array.from({ length: h }).map(() => Array.from({ length: w }).fill(val)); +const initializeArrayWithRange = (end, start = 0, step = 1) => + Array.from({ length: Math.ceil((end - start + 1) / step) }, (v, i) => i * step + start); +const initializeArrayWithRangeRight = (end, start = 0, step = 1) => + Array.from({ length: Math.ceil((end + 1 - start) / step) }).map( + (v, i, arr) => (arr.length - i - 1) * step + start + ); +const initializeArrayWithValues = (n, val = 0) => Array(n).fill(val); +const initializeNDArray = (val, ...args) => + args.length === 0 + ? val + : Array.from({ length: args[0] }).map(() => initializeNDArray(val, ...args.slice(1))); +const insertAfter = (el, htmlString) => el.insertAdjacentHTML('afterend', htmlString); +const insertBefore = (el, htmlString) => el.insertAdjacentHTML('beforebegin', htmlString); +const intersection = (a, b) => { + const s = new Set(b); + return a.filter(x => s.has(x)); +}; +const intersectionBy = (a, b, fn) => { + const s = new Set(b.map(fn)); + return a.filter(x => s.has(fn(x))); +}; +const intersectionWith = (a, b, comp) => a.filter(x => b.findIndex(y => comp(x, y)) !== -1); +const invertKeyValues = (obj, fn) => + Object.keys(obj).reduce((acc, key) => { + const val = fn ? fn(obj[key]) : obj[key]; + acc[val] = acc[val] || []; + acc[val].push(key); + return acc; + }, {}); +const is = (type, val) => ![, null].includes(val) && val.constructor === type; +const isAbsoluteURL = str => /^[a-z][a-z0-9+.-]*:/.test(str); +const isAfterDate = (dateA, dateB) => dateA > dateB; +const isAnagram = (str1, str2) => { + const normalize = str => + str + .toLowerCase() + .replace(/[^a-z0-9]/gi, '') + .split('') + .sort() + .join(''); + return normalize(str1) === normalize(str2); +}; +const isArrayLike = obj => obj != null && typeof obj[Symbol.iterator] === 'function'; +const isBeforeDate = (dateA, dateB) => dateA < dateB; +const isBoolean = val => typeof val === 'boolean'; +const isBrowser = () => ![typeof window, typeof document].includes('undefined'); +const isBrowserTabFocused = () => !document.hidden; +const isDivisible = (dividend, divisor) => dividend % divisor === 0; +const isDuplexStream = val => + val !== null && + typeof val === 'object' && + typeof val.pipe === 'function' && + typeof val._read === 'function' && + typeof val._readableState === 'object' && + typeof val._write === 'function' && + typeof val._writableState === 'object'; +const isEmpty = val => val == null || !(Object.keys(val) || val).length; +const isEven = num => num % 2 === 0; +const isFunction = val => typeof val === 'function'; +const isLowerCase = str => str === str.toLowerCase(); +const isNil = val => val === undefined || val === null; +const isNull = val => val === null; +const isNumber = val => typeof val === 'number'; +const isObject = obj => obj === Object(obj); +const isObjectLike = val => val !== null && typeof val === 'object'; +const isPlainObject = val => !!val && typeof val === 'object' && val.constructor === Object; +const isPrime = num => { + const boundary = Math.floor(Math.sqrt(num)); + for (var i = 2; i <= boundary; i++) if (num % i === 0) return false; + return num >= 2; +}; +const isPrimitive = val => Object(val) !== val; +const isPromiseLike = obj => + obj !== null && + (typeof obj === 'object' || typeof obj === 'function') && + typeof obj.then === 'function'; +const isReadableStream = val => + val !== null && + typeof val === 'object' && + typeof val.pipe === 'function' && + typeof val._read === 'function' && + typeof val._readableState === 'object'; +const isSameDate = (dateA, dateB) => dateA.toISOString() === dateB.toISOString(); +const isSorted = arr => { + let direction = -(arr[0] - arr[1]); + for (let [i, val] of arr.entries()) { + direction = !direction ? -(arr[i - 1] - arr[i]) : direction; + if (i === arr.length - 1) return !direction ? 0 : direction; + else if ((val - arr[i + 1]) * direction > 0) return 0; + } +}; +const isStream = val => val !== null && typeof val === 'object' && typeof val.pipe === 'function'; +const isString = val => typeof val === 'string'; +const isSymbol = val => typeof val === 'symbol'; +const isTravisCI = () => 'TRAVIS' in process.env && 'CI' in process.env; +const isUndefined = val => val === undefined; +const isUpperCase = str => str === str.toUpperCase(); +const isValidJSON = obj => { + try { + JSON.parse(obj); + return true; + } catch (e) { + return false; + } +}; +const isWritableStream = val => + val !== null && + typeof val === 'object' && + typeof val.pipe === 'function' && + typeof val._write === 'function' && + typeof val._writableState === 'object'; +const join = (arr, separator = ',', end = separator) => + arr.reduce( + (acc, val, i) => + i === arr.length - 2 + ? acc + val + end + : i === arr.length - 1 + ? acc + val + : acc + val + separator, + '' + ); +const last = arr => arr[arr.length - 1]; +const lcm = (...arr) => { + const gcd = (x, y) => (!y ? x : gcd(y, x % y)); + const _lcm = (x, y) => (x * y) / gcd(x, y); + return [...arr].reduce((a, b) => _lcm(a, b)); +}; +const longestItem = (val, ...vals) => + [val, ...vals].reduce((a, x) => (x.length > a.length ? x : a)); +const lowercaseKeys = obj => + Object.keys(obj).reduce((acc, key) => { + acc[key.toLowerCase()] = obj[key]; + return acc; + }, {}); +const luhnCheck = num => { + let arr = (num + '') + .split('') + .reverse() + .map(x => parseInt(x)); + let lastDigit = arr.splice(0, 1)[0]; + let sum = arr.reduce((acc, val, i) => (i % 2 !== 0 ? acc + val : acc + ((val * 2) % 9) || 9), 0); + sum += lastDigit; + return sum % 10 === 0; +}; +const mapKeys = (obj, fn) => + Object.keys(obj).reduce((acc, k) => { + acc[fn(obj[k], k, obj)] = obj[k]; + return acc; + }, {}); +const mapObject = (arr, fn) => + (a => ( + (a = [arr, arr.map(fn)]), a[0].reduce((acc, val, ind) => ((acc[val] = a[1][ind]), acc), {}) + ))(); +const mapString = (str, fn) => + str + .split('') + .map((c, i) => fn(c, i, str)) + .join(''); +const mapValues = (obj, fn) => + Object.keys(obj).reduce((acc, k) => { + acc[k] = fn(obj[k], k, obj); + return acc; + }, {}); +const mask = (cc, num = 4, mask = '*') => `${cc}`.slice(-num).padStart(`${cc}`.length, mask); +const matches = (obj, source) => + Object.keys(source).every(key => obj.hasOwnProperty(key) && obj[key] === source[key]); +const matchesWith = (obj, source, fn) => + Object.keys(source).every( + key => + obj.hasOwnProperty(key) && fn + ? fn(obj[key], source[key], key, obj, source) + : obj[key] == source[key] + ); +const maxBy = (arr, fn) => Math.max(...arr.map(typeof fn === 'function' ? fn : val => val[fn])); +const maxDate = (...dates) => new Date(Math.max.apply(null, ...dates)); +const maxN = (arr, n = 1) => [...arr].sort((a, b) => b - a).slice(0, n); +const median = arr => { + const mid = Math.floor(arr.length / 2), + nums = [...arr].sort((a, b) => a - b); + return arr.length % 2 !== 0 ? nums[mid] : (nums[mid - 1] + nums[mid]) / 2; +}; +const memoize = fn => { + const cache = new Map(); + const cached = function(val) { + return cache.has(val) ? cache.get(val) : cache.set(val, fn.call(this, val)) && cache.get(val); + }; + cached.cache = cache; + return cached; +}; +const merge = (...objs) => + [...objs].reduce( + (acc, obj) => + Object.keys(obj).reduce((a, k) => { + acc[k] = acc.hasOwnProperty(k) ? [].concat(acc[k]).concat(obj[k]) : obj[k]; + return acc; + }, {}), + {} + ); +const minBy = (arr, fn) => Math.min(...arr.map(typeof fn === 'function' ? fn : val => val[fn])); +const minDate = (...dates) => new Date(Math.min.apply(null, ...dates)); +const minN = (arr, n = 1) => [...arr].sort((a, b) => a - b).slice(0, n); +const mostPerformant = (fns, iterations = 10000) => { + const times = fns.map(fn => { + const before = performance.now(); + for (let i = 0; i < iterations; i++) fn(); + return performance.now() - before; + }); + return times.indexOf(Math.min(...times)); +}; +const negate = func => (...args) => !func(...args); +const nest = (items, id = null, link = 'parent_id') => + items + .filter(item => item[link] === id) + .map(item => ({ ...item, children: nest(items, item.id) })); +const nodeListToArray = nodeList => [...nodeList]; +const none = (arr, fn = Boolean) => !arr.some(fn); +const nthArg = n => (...args) => args.slice(n)[0]; +const nthElement = (arr, n = 0) => (n === -1 ? arr.slice(n) : arr.slice(n, n + 1))[0]; +const objectFromPairs = arr => arr.reduce((a, [key, val]) => ((a[key] = val), a), {}); +const objectToPairs = obj => Object.keys(obj).map(k => [k, obj[k]]); +const observeMutations = (element, callback, options) => { + const observer = new MutationObserver(mutations => mutations.forEach(m => callback(m))); + observer.observe( + element, + Object.assign( + { + childList: true, + attributes: true, + attributeOldValue: true, + characterData: true, + characterDataOldValue: true, + subtree: true + }, + options + ) + ); + return observer; +}; +const off = (el, evt, fn, opts = false) => el.removeEventListener(evt, fn, opts); +const offset = (arr, offset) => [...arr.slice(offset), ...arr.slice(0, offset)]; +const omit = (obj, arr) => + Object.keys(obj) + .filter(k => !arr.includes(k)) + .reduce((acc, key) => ((acc[key] = obj[key]), acc), {}); +const omitBy = (obj, fn) => + Object.keys(obj) + .filter(k => !fn(obj[k], k)) + .reduce((acc, key) => ((acc[key] = obj[key]), acc), {}); +const on = (el, evt, fn, opts = {}) => { + const delegatorFn = e => e.target.matches(opts.target) && fn.call(e.target, e); + el.addEventListener(evt, opts.target ? delegatorFn : fn, opts.options || false); + if (opts.target) return delegatorFn; +}; +const onUserInputChange = callback => { + let type = 'mouse', + lastTime = 0; + const mousemoveHandler = () => { + const now = performance.now(); + if (now - lastTime < 20) + (type = 'mouse'), callback(type), document.removeEventListener('mousemove', mousemoveHandler); + lastTime = now; + }; + document.addEventListener('touchstart', () => { + if (type === 'touch') return; + (type = 'touch'), callback(type), document.addEventListener('mousemove', mousemoveHandler); + }); +}; +const once = fn => { + let called = false; + return function(...args) { + if (called) return; + called = true; + return fn.apply(this, args); + }; +}; +const orderBy = (arr, props, orders) => + [...arr].sort((a, b) => + props.reduce((acc, prop, i) => { + if (acc === 0) { + const [p1, p2] = orders && orders[i] === 'desc' ? [b[prop], a[prop]] : [a[prop], b[prop]]; + acc = p1 > p2 ? 1 : p1 < p2 ? -1 : 0; + } + return acc; + }, 0) + ); +const over = (...fns) => (...args) => fns.map(fn => fn.apply(null, args)); +const overArgs = (fn, transforms) => (...args) => fn(...args.map((val, i) => transforms[i](val))); +const pad = (str, length, char = ' ') => + str.padStart((str.length + length) / 2, char).padEnd(length, char); +const palindrome = str => { + const s = str.toLowerCase().replace(/[\W_]/g, ''); + return s === [...s].reverse().join(''); +}; +const parseCookie = str => + str + .split(';') + .map(v => v.split('=')) + .reduce((acc, v) => { + acc[decodeURIComponent(v[0].trim())] = decodeURIComponent(v[1].trim()); + return acc; + }, {}); +const partial = (fn, ...partials) => (...args) => fn(...partials, ...args); +const partialRight = (fn, ...partials) => (...args) => fn(...args, ...partials); +const partition = (arr, fn) => + arr.reduce( + (acc, val, i, arr) => { + acc[fn(val, i, arr) ? 0 : 1].push(val); + return acc; + }, + [[], []] + ); +const percentile = (arr, val) => + (100 * arr.reduce((acc, v) => acc + (v < val ? 1 : 0) + (v === val ? 0.5 : 0), 0)) / arr.length; +const permutations = arr => { + if (arr.length <= 2) return arr.length === 2 ? [arr, [arr[1], arr[0]]] : arr; + return arr.reduce( + (acc, item, i) => + acc.concat( + permutations([...arr.slice(0, i), ...arr.slice(i + 1)]).map(val => [item, ...val]) + ), + [] + ); +}; +const pick = (obj, arr) => + arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {}); +const pickBy = (obj, fn) => + Object.keys(obj) + .filter(k => fn(obj[k], k)) + .reduce((acc, key) => ((acc[key] = obj[key]), acc), {}); +const pipeAsyncFunctions = (...fns) => arg => fns.reduce((p, f) => p.then(f), Promise.resolve(arg)); +const pipeFunctions = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args))); +const pluralize = (val, word, plural = word + 's') => { + const _pluralize = (num, word, plural = word + 's') => + [1, -1].includes(Number(num)) ? word : plural; + if (typeof val === 'object') return (num, word) => _pluralize(num, word, val[word]); + return _pluralize(val, word, plural); +}; +const powerset = arr => arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]); +const prefix = prop => { + const capitalizedProp = prop.charAt(0).toUpperCase() + prop.slice(1); + const prefixes = ['', 'webkit', 'moz', 'ms', 'o']; + const i = prefixes.findIndex( + prefix => typeof document.body.style[prefix ? prefix + capitalizedProp : prop] !== 'undefined' + ); + return i !== -1 ? (i === 0 ? prop : prefixes[i] + capitalizedProp) : null; +}; +const prettyBytes = (num, precision = 3, addSpace = true) => { + const UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; + if (Math.abs(num) < 1) return num + (addSpace ? ' ' : '') + UNITS[0]; + const exponent = Math.min(Math.floor(Math.log10(num < 0 ? -num : num) / 3), UNITS.length - 1); + const n = Number(((num < 0 ? -num : num) / 1000 ** exponent).toPrecision(precision)); + return (num < 0 ? '-' : '') + n + (addSpace ? ' ' : '') + UNITS[exponent]; +}; +const primes = num => { + let arr = Array.from({ length: num - 1 }).map((x, i) => i + 2), + sqroot = Math.floor(Math.sqrt(num)), + numsTillSqroot = Array.from({ length: sqroot - 1 }).map((x, i) => i + 2); + numsTillSqroot.forEach(x => (arr = arr.filter(y => y % x !== 0 || y === x))); + return arr; +}; +const promisify = func => (...args) => + new Promise((resolve, reject) => + func(...args, (err, result) => (err ? reject(err) : resolve(result))) + ); +const pull = (arr, ...args) => { + let argState = Array.isArray(args[0]) ? args[0] : args; + let pulled = arr.filter((v, i) => !argState.includes(v)); + arr.length = 0; + pulled.forEach(v => arr.push(v)); +}; +const pullAtIndex = (arr, pullArr) => { + let removed = []; + let pulled = arr + .map((v, i) => (pullArr.includes(i) ? removed.push(v) : v)) + .filter((v, i) => !pullArr.includes(i)); + arr.length = 0; + pulled.forEach(v => arr.push(v)); + return removed; +}; +const pullAtValue = (arr, pullArr) => { + let removed = [], + pushToRemove = arr.forEach((v, i) => (pullArr.includes(v) ? removed.push(v) : v)), + mutateTo = arr.filter((v, i) => !pullArr.includes(v)); + arr.length = 0; + mutateTo.forEach(v => arr.push(v)); + return removed; +}; +const pullBy = (arr, ...args) => { + const length = args.length; + let fn = length > 1 ? args[length - 1] : undefined; + fn = typeof fn == 'function' ? (args.pop(), fn) : undefined; + let argState = (Array.isArray(args[0]) ? args[0] : args).map(val => fn(val)); + let pulled = arr.filter((v, i) => !argState.includes(fn(v))); + arr.length = 0; + pulled.forEach(v => arr.push(v)); +}; +const radsToDegrees = rad => (rad * 180.0) / Math.PI; +const randomHexColorCode = () => { + let n = (Math.random() * 0xfffff * 1000000).toString(16); + return '#' + n.slice(0, 6); +}; +const randomIntArrayInRange = (min, max, n = 1) => + Array.from({ length: n }, () => Math.floor(Math.random() * (max - min + 1)) + min); +const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min; +const randomNumberInRange = (min, max) => Math.random() * (max - min) + min; + +const readFileLines = filename => + fs + .readFileSync(filename) + .toString('UTF8') + .split('\n'); +const rearg = (fn, indexes) => (...args) => fn(...indexes.map(i => args[i])); +const recordAnimationFrames = (callback, autoStart = true) => { + let running = true, + raf; + const stop = () => { + running = false; + cancelAnimationFrame(raf); + }; + const start = () => { + running = true; + run(); + }; + const run = () => { + raf = requestAnimationFrame(() => { + callback(); + if (running) run(); + }); + }; + if (autoStart) start(); + return { start, stop }; +}; +const redirect = (url, asLink = true) => + asLink ? (window.location.href = url) : window.location.replace(url); +const reduceSuccessive = (arr, fn, acc) => + arr.reduce((res, val, i, arr) => (res.push(fn(res.slice(-1)[0], val, i, arr)), res), [acc]); +const reduceWhich = (arr, comparator = (a, b) => a - b) => + arr.reduce((a, b) => (comparator(a, b) >= 0 ? b : a)); +const reducedFilter = (data, keys, fn) => + data.filter(fn).map(el => + keys.reduce((acc, key) => { + acc[key] = el[key]; + return acc; + }, {}) + ); +const reject = (pred, array) => array.filter((...args) => !pred(...args)); +const remove = (arr, func) => + Array.isArray(arr) + ? arr.filter(func).reduce((acc, val) => { + arr.splice(arr.indexOf(val), 1); + return acc.concat(val); + }, []) + : []; +const removeNonASCII = str => str.replace(/[^\x20-\x7E]/g, ''); +const renameKeys = (keysMap, obj) => + Object.keys(obj).reduce( + (acc, key) => ({ + ...acc, + ...{ [keysMap[key] || key]: obj[key] } + }), + {} + ); +const reverseString = str => [...str].reverse().join(''); +const round = (n, decimals = 0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`); +const runAsync = fn => { + const worker = new Worker( + URL.createObjectURL(new Blob([`postMessage((${fn})());`]), { + type: 'application/javascript; charset=utf-8' + }) + ); + return new Promise((res, rej) => { + worker.onmessage = ({ data }) => { + res(data), worker.terminate(); + }; + worker.onerror = err => { + rej(err), worker.terminate(); + }; + }); +}; +const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve()); +const sample = arr => arr[Math.floor(Math.random() * arr.length)]; +const sampleSize = ([...arr], n = 1) => { + let m = arr.length; + while (m) { + const i = Math.floor(Math.random() * m--); + [arr[m], arr[i]] = [arr[i], arr[m]]; + } + return arr.slice(0, n); +}; +const scrollToTop = () => { + const c = document.documentElement.scrollTop || document.body.scrollTop; + if (c > 0) { + window.requestAnimationFrame(scrollToTop); + window.scrollTo(0, c - c / 8); + } +}; +const sdbm = str => { + let arr = str.split(''); + return arr.reduce( + (hashCode, currentVal) => + (hashCode = currentVal.charCodeAt(0) + (hashCode << 6) + (hashCode << 16) - hashCode), + 0 + ); +}; +const serializeCookie = (name, val) => `${encodeURIComponent(name)}=${encodeURIComponent(val)}`; +const setStyle = (el, ruleName, val) => (el.style[ruleName] = val); +const shallowClone = obj => Object.assign({}, obj); +const shank = (arr, index = 0, delCount = 0, ...elements) => + arr + .slice(0, index) + .concat(elements) + .concat(arr.slice(index + delCount)); +const show = (...el) => [...el].forEach(e => (e.style.display = '')); +const shuffle = ([...arr]) => { + let m = arr.length; + while (m) { + const i = Math.floor(Math.random() * m--); + [arr[m], arr[i]] = [arr[i], arr[m]]; + } + return arr; +}; +const similarity = (arr, values) => arr.filter(v => values.includes(v)); +const size = val => + Array.isArray(val) + ? val.length + : val && typeof val === 'object' + ? val.size || val.length || Object.keys(val).length + : typeof val === 'string' + ? new Blob([val]).size + : 0; +const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); +const smoothScroll = element => + document.querySelector(element).scrollIntoView({ + behavior: 'smooth' + }); +const sortCharactersInString = str => [...str].sort((a, b) => a.localeCompare(b)).join(''); +const sortedIndex = (arr, n) => { + const isDescending = arr[0] > arr[arr.length - 1]; + const index = arr.findIndex(el => (isDescending ? n >= el : n <= el)); + return index === -1 ? arr.length : index; +}; +const sortedIndexBy = (arr, n, fn) => { + const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]); + const val = fn(n); + const index = arr.findIndex(el => (isDescending ? val >= fn(el) : val <= fn(el))); + return index === -1 ? arr.length : index; +}; +const sortedLastIndex = (arr, n) => { + const isDescending = arr[0] > arr[arr.length - 1]; + const index = arr.reverse().findIndex(el => (isDescending ? n <= el : n >= el)); + return index === -1 ? 0 : arr.length - index; +}; +const sortedLastIndexBy = (arr, n, fn) => { + const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]); + const val = fn(n); + const index = arr + .map(fn) + .reverse() + .findIndex(el => (isDescending ? val <= el : val >= el)); + return index === -1 ? 0 : arr.length - index; +}; +const splitLines = str => str.split(/\r?\n/); const spreadOver = fn => argsArr => fn(...argsArr); - const stableSort = (arr, compare) => - arr - .map((item, index) => ({ item, index })) - .sort((a, b) => compare(a.item, b.item) || a.index - b.index) - .map(({ item }) => item); - const standardDeviation = (arr, usePopulation = false) => { - const mean = arr.reduce((acc, val) => acc + val, 0) / arr.length; - return Math.sqrt( - arr.reduce((acc, val) => acc.concat((val - mean) ** 2), []).reduce((acc, val) => acc + val, 0) / - (arr.length - (usePopulation ? 0 : 1)) - ); -}; - const stringPermutations = str => { - if (str.length <= 2) return str.length === 2 ? [str, str[1] + str[0]] : [str]; - return str - .split('') - .reduce( - (acc, letter, i) => - acc.concat(stringPermutations(str.slice(0, i) + str.slice(i + 1)).map(val => letter + val)), - [] - ); -}; - const stripHTMLTags = str => str.replace(/<[^>]*>/g, ''); - const sum = (...arr) => [...arr].reduce((acc, val) => acc + val, 0); - const sumBy = (arr, fn) => - arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0); - const sumPower = (end, power = 2, start = 1) => - Array(end + 1 - start) - .fill(0) - .map((x, i) => (i + start) ** power) - .reduce((a, b) => a + b, 0); - const symmetricDifference = (a, b) => { - const sA = new Set(a), - sB = new Set(b); - return [...a.filter(x => !sB.has(x)), ...b.filter(x => !sA.has(x))]; -}; - const symmetricDifferenceBy = (a, b, fn) => { - const sA = new Set(a.map(v => fn(v))), - sB = new Set(b.map(v => fn(v))); - return [...a.filter(x => !sB.has(fn(x))), ...b.filter(x => !sA.has(fn(x)))]; -}; - const symmetricDifferenceWith = (arr, val, comp) => [ - ...arr.filter(a => val.findIndex(b => comp(a, b)) === -1), - ...val.filter(a => arr.findIndex(b => comp(a, b)) === -1) -]; - const tail = arr => (arr.length > 1 ? arr.slice(1) : arr); - const take = (arr, n = 1) => arr.slice(0, n); - const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length); - const takeRightWhile = (arr, func) => - arr.reduceRight((acc, el) => (func(el) ? acc : [el, ...acc]), []); - const takeWhile = (arr, func) => { - for (const [i, val] of arr.entries()) if (func(val)) return arr.slice(0, i); - return arr; -}; - const throttle = (fn, wait) => { - let inThrottle, lastFn, lastTime; - return function() { - const context = this, - args = arguments; - if (!inThrottle) { - fn.apply(context, args); - lastTime = Date.now(); - inThrottle = true; - } else { - clearTimeout(lastFn); - lastFn = setTimeout(function() { - if (Date.now() - lastTime >= wait) { - fn.apply(context, args); - lastTime = Date.now(); - } - }, Math.max(wait - (Date.now() - lastTime), 0)); - } - }; -}; - const times = (n, fn, context = undefined) => { - let i = 0; - while (fn.call(context, i) !== false && ++i < n) {} -}; - const timeTaken = callback => { - console.time('timeTaken'); - const r = callback(); - console.timeEnd('timeTaken'); - return r; -}; - const toCamelCase = str => { - let s = - str && - str - .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) - .map(x => x.slice(0, 1).toUpperCase() + x.slice(1).toLowerCase()) - .join(''); - return s.slice(0, 1).toLowerCase() + s.slice(1); -}; - const toCurrency = (n, curr, LanguageFormat = undefined) => - Intl.NumberFormat(LanguageFormat, { style: 'currency', currency: curr }).format(n); - const toDecimalMark = num => num.toLocaleString('en-US'); - const toggleClass = (el, className) => el.classList.toggle(className); - const toHash = (object, key) => - Array.prototype.reduce.call( - object, - (acc, data, index) => ((acc[!key ? index : data[key]] = data), acc), - {} - ); - const toKebabCase = str => - str && - str - .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) - .map(x => x.toLowerCase()) - .join('-'); - const tomorrow = (long = false) => { - let t = new Date(); - t.setDate(t.getDate() + 1); - const ret = `${t.getFullYear()}-${String(t.getMonth() + 1).padStart(2, '0')}-${String( - t.getDate() - ).padStart(2, '0')}`; - return !long ? ret : `${ret}T00:00:00`; -}; - const toOrdinalSuffix = num => { - const int = parseInt(num), - digits = [int % 10, int % 100], - ordinals = ['st', 'nd', 'rd', 'th'], - oPattern = [1, 2, 3, 4], - tPattern = [11, 12, 13, 14, 15, 16, 17, 18, 19]; - return oPattern.includes(digits[0]) && !tPattern.includes(digits[1]) - ? int + ordinals[digits[0] - 1] - : int + ordinals[3]; -}; - const toSafeInteger = num => - Math.round(Math.max(Math.min(num, Number.MAX_SAFE_INTEGER), Number.MIN_SAFE_INTEGER)); - const toSnakeCase = str => - str && - str - .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) - .map(x => x.toLowerCase()) - .join('_'); - const transform = (obj, fn, acc) => Object.keys(obj).reduce((a, k) => fn(a, obj[k], k, obj), acc); - const triggerEvent = (el, eventType, detail) => - el.dispatchEvent(new CustomEvent(eventType, { detail })); - const truncateString = (str, num) => - str.length > num ? str.slice(0, num > 3 ? num - 3 : num) + '...' : str; - const truthCheckCollection = (collection, pre) => collection.every(obj => obj[pre]); - const unary = fn => val => fn(val); - const uncurry = (fn, n = 1) => (...args) => { - const next = acc => args => args.reduce((x, y) => x(y), acc); - if (n > args.length) throw new RangeError('Arguments too few!'); - return next(fn)(args.slice(0, n)); -}; - const unescapeHTML = str => - str.replace( - /&|<|>|'|"/g, - tag => - ({ - '&': '&', - '<': '<', - '>': '>', - ''': "'", - '"': '"' - }[tag] || tag) - ); - const unflattenObject = obj => - Object.keys(obj).reduce((acc, k) => { - if (k.indexOf('.') !== -1) { - const keys = k.split('.'); - Object.assign( - acc, - JSON.parse( - '{' + - keys.map((v, i) => (i !== keys.length - 1 ? `"${v}":{` : `"${v}":`)).join('') + - obj[k] + - '}'.repeat(keys.length) - ) - ); - } else acc[k] = obj[k]; - return acc; - }, {}); - const unfold = (fn, seed) => { - let result = [], - val = [null, seed]; - while ((val = fn(val[1]))) result.push(val[0]); - return result; -}; - const union = (a, b) => Array.from(new Set([...a, ...b])); - const unionBy = (a, b, fn) => { - const s = new Set(a.map(fn)); - return Array.from(new Set([...a, ...b.filter(x => !s.has(fn(x)))])); -}; - const unionWith = (a, b, comp) => - Array.from(new Set([...a, ...b.filter(x => a.findIndex(y => comp(x, y)) === -1)])); - const uniqueElements = arr => [...new Set(arr)]; - const uniqueElementsBy = (arr, fn) => - arr.reduce((acc, v) => { - if (!acc.some(x => fn(v, x))) acc.push(v); - return acc; - }, []); - const uniqueElementsByRight = (arr, fn) => - arr.reduceRight((acc, v) => { - if (!acc.some(x => fn(v, x))) acc.push(v); - return acc; - }, []); - const uniqueSymmetricDifference = (a, b) => [ - ...new Set([...a.filter(v => !b.includes(v)), ...b.filter(v => !a.includes(v))]) -]; - const untildify = str => str.replace(/^~($|\/|\\)/, `${require('os').homedir()}$1`); - const unzip = arr => - arr.reduce( - (acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc), - Array.from({ - length: Math.max(...arr.map(x => x.length)) - }).map(x => []) - ); - const unzipWith = (arr, fn) => - arr - .reduce( - (acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc), - Array.from({ - length: Math.max(...arr.map(x => x.length)) - }).map(x => []) - ) - .map(val => fn(...val)); - const URLJoin = (...args) => - args - .join('/') - .replace(/[\/]+/g, '/') - .replace(/^(.+):\//, '$1://') - .replace(/^file:/, 'file:/') - .replace(/\/(\?|&|#[^!])/g, '$1') - .replace(/\?/g, '&') - .replace('&', '?'); - const UUIDGeneratorBrowser = () => - ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => - (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16) - ); - -const UUIDGeneratorNode = () => - ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => - (c ^ (crypto.randomBytes(1)[0] & (15 >> (c / 4)))).toString(16) - ); - const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n; - const when = (pred, whenTrue) => x => (pred(x) ? whenTrue(x) : x); - const without = (arr, ...args) => arr.filter(v => !args.includes(v)); - const words = (str, pattern = /[^a-zA-Z-]+/) => str.split(pattern).filter(Boolean); - const xProd = (a, b) => a.reduce((acc, x) => acc.concat(b.map(y => [x, y])), []); - const yesNo = (val, def = false) => - /^(y|yes)$/i.test(val) ? true : /^(n|no)$/i.test(val) ? false : def; - const zip = (...arrays) => { - const maxLength = Math.max(...arrays.map(x => x.length)); - return Array.from({ length: maxLength }).map((_, i) => { - return Array.from({ length: arrays.length }, (_, k) => arrays[k][i]); - }); -}; - const zipObject = (props, values) => - props.reduce((obj, prop, index) => ((obj[prop] = values[index]), obj), {}); - const zipWith = (...array) => { - const fn = typeof array[array.length - 1] === 'function' ? array.pop() : undefined; - return Array.from( - { length: Math.max(...array.map(a => a.length)) }, - (_, i) => (fn ? fn(...array.map(a => a[i])) : array.map(a => a[i])) - ); -}; +const stableSort = (arr, compare) => + arr + .map((item, index) => ({ item, index })) + .sort((a, b) => compare(a.item, b.item) || a.index - b.index) + .map(({ item }) => item); +const standardDeviation = (arr, usePopulation = false) => { + const mean = arr.reduce((acc, val) => acc + val, 0) / arr.length; + return Math.sqrt( + arr.reduce((acc, val) => acc.concat((val - mean) ** 2), []).reduce((acc, val) => acc + val, 0) / + (arr.length - (usePopulation ? 0 : 1)) + ); +}; +const stringPermutations = str => { + if (str.length <= 2) return str.length === 2 ? [str, str[1] + str[0]] : [str]; + return str + .split('') + .reduce( + (acc, letter, i) => + acc.concat(stringPermutations(str.slice(0, i) + str.slice(i + 1)).map(val => letter + val)), + [] + ); +}; +const stripHTMLTags = str => str.replace(/<[^>]*>/g, ''); +const sum = (...arr) => [...arr].reduce((acc, val) => acc + val, 0); +const sumBy = (arr, fn) => + arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0); +const sumPower = (end, power = 2, start = 1) => + Array(end + 1 - start) + .fill(0) + .map((x, i) => (i + start) ** power) + .reduce((a, b) => a + b, 0); +const symmetricDifference = (a, b) => { + const sA = new Set(a), + sB = new Set(b); + return [...a.filter(x => !sB.has(x)), ...b.filter(x => !sA.has(x))]; +}; +const symmetricDifferenceBy = (a, b, fn) => { + const sA = new Set(a.map(v => fn(v))), + sB = new Set(b.map(v => fn(v))); + return [...a.filter(x => !sB.has(fn(x))), ...b.filter(x => !sA.has(fn(x)))]; +}; +const symmetricDifferenceWith = (arr, val, comp) => [ + ...arr.filter(a => val.findIndex(b => comp(a, b)) === -1), + ...val.filter(a => arr.findIndex(b => comp(a, b)) === -1) +]; +const tail = arr => (arr.length > 1 ? arr.slice(1) : arr); +const take = (arr, n = 1) => arr.slice(0, n); +const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length); +const takeRightWhile = (arr, func) => + arr.reduceRight((acc, el) => (func(el) ? acc : [el, ...acc]), []); +const takeWhile = (arr, func) => { + for (const [i, val] of arr.entries()) if (func(val)) return arr.slice(0, i); + return arr; +}; +const throttle = (fn, wait) => { + let inThrottle, lastFn, lastTime; + return function() { + const context = this, + args = arguments; + if (!inThrottle) { + fn.apply(context, args); + lastTime = Date.now(); + inThrottle = true; + } else { + clearTimeout(lastFn); + lastFn = setTimeout(function() { + if (Date.now() - lastTime >= wait) { + fn.apply(context, args); + lastTime = Date.now(); + } + }, Math.max(wait - (Date.now() - lastTime), 0)); + } + }; +}; +const timeTaken = callback => { + console.time('timeTaken'); + const r = callback(); + console.timeEnd('timeTaken'); + return r; +}; +const times = (n, fn, context = undefined) => { + let i = 0; + while (fn.call(context, i) !== false && ++i < n) {} +}; +const toCamelCase = str => { + let s = + str && + str + .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) + .map(x => x.slice(0, 1).toUpperCase() + x.slice(1).toLowerCase()) + .join(''); + return s.slice(0, 1).toLowerCase() + s.slice(1); +}; +const toCurrency = (n, curr, LanguageFormat = undefined) => + Intl.NumberFormat(LanguageFormat, { style: 'currency', currency: curr }).format(n); +const toDecimalMark = num => num.toLocaleString('en-US'); +const toHash = (object, key) => + Array.prototype.reduce.call( + object, + (acc, data, index) => ((acc[!key ? index : data[key]] = data), acc), + {} + ); +const toKebabCase = str => + str && + str + .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) + .map(x => x.toLowerCase()) + .join('-'); +const toOrdinalSuffix = num => { + const int = parseInt(num), + digits = [int % 10, int % 100], + ordinals = ['st', 'nd', 'rd', 'th'], + oPattern = [1, 2, 3, 4], + tPattern = [11, 12, 13, 14, 15, 16, 17, 18, 19]; + return oPattern.includes(digits[0]) && !tPattern.includes(digits[1]) + ? int + ordinals[digits[0] - 1] + : int + ordinals[3]; +}; +const toSafeInteger = num => + Math.round(Math.max(Math.min(num, Number.MAX_SAFE_INTEGER), Number.MIN_SAFE_INTEGER)); +const toSnakeCase = str => + str && + str + .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) + .map(x => x.toLowerCase()) + .join('_'); +const toggleClass = (el, className) => el.classList.toggle(className); +const tomorrow = (long = false) => { + let t = new Date(); + t.setDate(t.getDate() + 1); + const ret = `${t.getFullYear()}-${String(t.getMonth() + 1).padStart(2, '0')}-${String( + t.getDate() + ).padStart(2, '0')}`; + return !long ? ret : `${ret}T00:00:00`; +}; +const transform = (obj, fn, acc) => Object.keys(obj).reduce((a, k) => fn(a, obj[k], k, obj), acc); +const triggerEvent = (el, eventType, detail) => + el.dispatchEvent(new CustomEvent(eventType, { detail })); +const truncateString = (str, num) => + str.length > num ? str.slice(0, num > 3 ? num - 3 : num) + '...' : str; +const truthCheckCollection = (collection, pre) => collection.every(obj => obj[pre]); +const unary = fn => val => fn(val); +const uncurry = (fn, n = 1) => (...args) => { + const next = acc => args => args.reduce((x, y) => x(y), acc); + if (n > args.length) throw new RangeError('Arguments too few!'); + return next(fn)(args.slice(0, n)); +}; +const unescapeHTML = str => + str.replace( + /&|<|>|'|"/g, + tag => + ({ + '&': '&', + '<': '<', + '>': '>', + ''': "'", + '"': '"' + }[tag] || tag) + ); +const unflattenObject = obj => + Object.keys(obj).reduce((acc, k) => { + if (k.indexOf('.') !== -1) { + const keys = k.split('.'); + Object.assign( + acc, + JSON.parse( + '{' + + keys.map((v, i) => (i !== keys.length - 1 ? `"${v}":{` : `"${v}":`)).join('') + + obj[k] + + '}'.repeat(keys.length) + ) + ); + } else acc[k] = obj[k]; + return acc; + }, {}); +const unfold = (fn, seed) => { + let result = [], + val = [null, seed]; + while ((val = fn(val[1]))) result.push(val[0]); + return result; +}; +const union = (a, b) => Array.from(new Set([...a, ...b])); +const unionBy = (a, b, fn) => { + const s = new Set(a.map(fn)); + return Array.from(new Set([...a, ...b.filter(x => !s.has(fn(x)))])); +}; +const unionWith = (a, b, comp) => + Array.from(new Set([...a, ...b.filter(x => a.findIndex(y => comp(x, y)) === -1)])); +const uniqueElements = arr => [...new Set(arr)]; +const uniqueElementsBy = (arr, fn) => + arr.reduce((acc, v) => { + if (!acc.some(x => fn(v, x))) acc.push(v); + return acc; + }, []); +const uniqueElementsByRight = (arr, fn) => + arr.reduceRight((acc, v) => { + if (!acc.some(x => fn(v, x))) acc.push(v); + return acc; + }, []); +const uniqueSymmetricDifference = (a, b) => [ + ...new Set([...a.filter(v => !b.includes(v)), ...b.filter(v => !a.includes(v))]) +]; +const untildify = str => str.replace(/^~($|\/|\\)/, `${require('os').homedir()}$1`); +const unzip = arr => + arr.reduce( + (acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc), + Array.from({ + length: Math.max(...arr.map(x => x.length)) + }).map(x => []) + ); +const unzipWith = (arr, fn) => + arr + .reduce( + (acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc), + Array.from({ + length: Math.max(...arr.map(x => x.length)) + }).map(x => []) + ) + .map(val => fn(...val)); +const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n; +const when = (pred, whenTrue) => x => (pred(x) ? whenTrue(x) : x); +const without = (arr, ...args) => arr.filter(v => !args.includes(v)); +const words = (str, pattern = /[^a-zA-Z-]+/) => str.split(pattern).filter(Boolean); +const xProd = (a, b) => a.reduce((acc, x) => acc.concat(b.map(y => [x, y])), []); +const yesNo = (val, def = false) => + /^(y|yes)$/i.test(val) ? true : /^(n|no)$/i.test(val) ? false : def; +const zip = (...arrays) => { + const maxLength = Math.max(...arrays.map(x => x.length)); + return Array.from({ length: maxLength }).map((_, i) => { + return Array.from({ length: arrays.length }, (_, k) => arrays[k][i]); + }); +}; +const zipObject = (props, values) => + props.reduce((obj, prop, index) => ((obj[prop] = values[index]), obj), {}); +const zipWith = (...array) => { + const fn = typeof array[array.length - 1] === 'function' ? array.pop() : undefined; + return Array.from( + { length: Math.max(...array.map(a => a.length)) }, + (_, i) => (fn ? fn(...array.map(a => a[i])) : array.map(a => a[i])) + ); +}; -module.exports = {all,allEqual,any,approximatelyEqual,arrayToCSV,arrayToHtmlList,ary,atob,attempt,average,averageBy,bifurcate,bifurcateBy,bind,bindAll,bindKey,binomialCoefficient,bottomVisible,btoa,byteSize,call,capitalize,capitalizeEveryWord,castArray,chainAsync,chunk,clampNumber,cloneRegExp,coalesce,coalesceFactory,collectInto,colorize,compact,compose,composeRight,converge,copyToClipboard,countBy,counter,countOccurrences,createElement,createEventHub,CSVToArray,CSVToJSON,currentURL,curry,dayOfYear,debounce,decapitalize,deepClone,deepFlatten,deepFreeze,defaults,defer,degreesToRads,delay,detectDeviceType,difference,differenceBy,differenceWith,dig,digitize,distance,drop,dropRight,dropRightWhile,dropWhile,elementContains,elementIsVisibleInViewport,elo,equals,escapeHTML,escapeRegExp,everyNth,extendHex,factorial,fibonacci,filterNonUnique,filterNonUniqueBy,findKey,findLast,findLastIndex,findLastKey,flatten,flattenObject,flip,forEachRight,formatDuration,forOwn,forOwnRight,fromCamelCase,functionName,functions,gcd,geometricProgression,get,getColonTimeFromDate,getDaysDiffBetweenDates,getImages,getMeridiemSuffixOfInteger,getScrollPosition,getStyle,getType,getURLParameters,groupBy,hammingDistance,hasClass,hasFlags,hashBrowser,hashNode,head,hexToRGB,hide,httpGet,httpPost,httpsRedirect,hz,indentString,indexOfAll,initial,initialize2DArray,initializeArrayWithRange,initializeArrayWithRangeRight,initializeArrayWithValues,initializeNDArray,inRange,insertAfter,insertBefore,intersection,intersectionBy,intersectionWith,invertKeyValues,is,isAbsoluteURL,isAfterDate,isAnagram,isArrayLike,isBeforeDate,isBoolean,isBrowser,isBrowserTabFocused,isDivisible,isDuplexStream,isEmpty,isEven,isFunction,isLowerCase,isNil,isNull,isNumber,isObject,isObjectLike,isPlainObject,isPrime,isPrimitive,isPromiseLike,isReadableStream,isSameDate,isSorted,isStream,isString,isSymbol,isTravisCI,isUndefined,isUpperCase,isValidJSON,isWritableStream,join,JSONtoCSV,JSONToFile,last,lcm,longestItem,lowercaseKeys,luhnCheck,mapKeys,mapObject,mapString,mapValues,mask,matches,matchesWith,maxBy,maxDate,maxN,median,memoize,merge,minBy,minDate,minN,mostPerformant,negate,nest,nodeListToArray,none,nthArg,nthElement,objectFromPairs,objectToPairs,observeMutations,off,offset,omit,omitBy,on,once,onUserInputChange,orderBy,over,overArgs,pad,palindrome,parseCookie,partial,partialRight,partition,percentile,permutations,pick,pickBy,pipeAsyncFunctions,pipeFunctions,pluralize,powerset,prefix,prettyBytes,primes,promisify,pull,pullAtIndex,pullAtValue,pullBy,radsToDegrees,randomHexColorCode,randomIntArrayInRange,randomIntegerInRange,randomNumberInRange,readFileLines,rearg,recordAnimationFrames,redirect,reducedFilter,reduceSuccessive,reduceWhich,reject,remove,removeNonASCII,renameKeys,reverseString,RGBToHex,round,runAsync,runPromisesInSeries,sample,sampleSize,scrollToTop,sdbm,serializeCookie,setStyle,shallowClone,shank,show,shuffle,similarity,size,sleep,smoothScroll,sortCharactersInString,sortedIndex,sortedIndexBy,sortedLastIndex,sortedLastIndexBy,splitLines,spreadOver,stableSort,standardDeviation,stringPermutations,stripHTMLTags,sum,sumBy,sumPower,symmetricDifference,symmetricDifferenceBy,symmetricDifferenceWith,tail,take,takeRight,takeRightWhile,takeWhile,throttle,times,timeTaken,toCamelCase,toCurrency,toDecimalMark,toggleClass,toHash,toKebabCase,tomorrow,toOrdinalSuffix,toSafeInteger,toSnakeCase,transform,triggerEvent,truncateString,truthCheckCollection,unary,uncurry,unescapeHTML,unflattenObject,unfold,union,unionBy,unionWith,uniqueElements,uniqueElementsBy,uniqueElementsByRight,uniqueSymmetricDifference,untildify,unzip,unzipWith,URLJoin,UUIDGeneratorBrowser,UUIDGeneratorNode,validateNumber,when,without,words,xProd,yesNo,zip,zipObject,zipWith}; +module.exports = {CSVToArray,CSVToJSON,JSONToFile,JSONtoCSV,RGBToHex,URLJoin,UUIDGeneratorBrowser,UUIDGeneratorNode,all,allEqual,any,approximatelyEqual,arrayToCSV,arrayToHtmlList,ary,atob,attempt,average,averageBy,bifurcate,bifurcateBy,bind,bindAll,bindKey,binomialCoefficient,bottomVisible,btoa,byteSize,call,capitalize,capitalizeEveryWord,castArray,chainAsync,chunk,clampNumber,cloneRegExp,coalesce,coalesceFactory,collectInto,colorize,compact,compose,composeRight,converge,copyToClipboard,countBy,countOccurrences,counter,createElement,createEventHub,currentURL,curry,dayOfYear,debounce,decapitalize,deepClone,deepFlatten,deepFreeze,defaults,defer,degreesToRads,delay,detectDeviceType,difference,differenceBy,differenceWith,dig,digitize,distance,drop,dropRight,dropRightWhile,dropWhile,elementContains,elementIsVisibleInViewport,elo,equals,escapeHTML,escapeRegExp,everyNth,extendHex,factorial,fibonacci,filterNonUnique,filterNonUniqueBy,findKey,findLast,findLastIndex,findLastKey,flatten,flattenObject,flip,forEachRight,forOwn,forOwnRight,formatDuration,fromCamelCase,functionName,functions,gcd,geometricProgression,get,getColonTimeFromDate,getDaysDiffBetweenDates,getImages,getMeridiemSuffixOfInteger,getScrollPosition,getStyle,getType,getURLParameters,groupBy,hammingDistance,hasClass,hasFlags,hashBrowser,hashNode,head,hexToRGB,hide,httpGet,httpPost,httpsRedirect,hz,inRange,indentString,indexOfAll,initial,initialize2DArray,initializeArrayWithRange,initializeArrayWithRangeRight,initializeArrayWithValues,initializeNDArray,insertAfter,insertBefore,intersection,intersectionBy,intersectionWith,invertKeyValues,is,isAbsoluteURL,isAfterDate,isAnagram,isArrayLike,isBeforeDate,isBoolean,isBrowser,isBrowserTabFocused,isDivisible,isDuplexStream,isEmpty,isEven,isFunction,isLowerCase,isNil,isNull,isNumber,isObject,isObjectLike,isPlainObject,isPrime,isPrimitive,isPromiseLike,isReadableStream,isSameDate,isSorted,isStream,isString,isSymbol,isTravisCI,isUndefined,isUpperCase,isValidJSON,isWritableStream,join,last,lcm,longestItem,lowercaseKeys,luhnCheck,mapKeys,mapObject,mapString,mapValues,mask,matches,matchesWith,maxBy,maxDate,maxN,median,memoize,merge,minBy,minDate,minN,mostPerformant,negate,nest,nodeListToArray,none,nthArg,nthElement,objectFromPairs,objectToPairs,observeMutations,off,offset,omit,omitBy,on,onUserInputChange,once,orderBy,over,overArgs,pad,palindrome,parseCookie,partial,partialRight,partition,percentile,permutations,pick,pickBy,pipeAsyncFunctions,pipeFunctions,pluralize,powerset,prefix,prettyBytes,primes,promisify,pull,pullAtIndex,pullAtValue,pullBy,radsToDegrees,randomHexColorCode,randomIntArrayInRange,randomIntegerInRange,randomNumberInRange,readFileLines,rearg,recordAnimationFrames,redirect,reduceSuccessive,reduceWhich,reducedFilter,reject,remove,removeNonASCII,renameKeys,reverseString,round,runAsync,runPromisesInSeries,sample,sampleSize,scrollToTop,sdbm,serializeCookie,setStyle,shallowClone,shank,show,shuffle,similarity,size,sleep,smoothScroll,sortCharactersInString,sortedIndex,sortedIndexBy,sortedLastIndex,sortedLastIndexBy,splitLines,spreadOver,stableSort,standardDeviation,stringPermutations,stripHTMLTags,sum,sumBy,sumPower,symmetricDifference,symmetricDifferenceBy,symmetricDifferenceWith,tail,take,takeRight,takeRightWhile,takeWhile,throttle,timeTaken,times,toCamelCase,toCurrency,toDecimalMark,toHash,toKebabCase,toOrdinalSuffix,toSafeInteger,toSnakeCase,toggleClass,tomorrow,transform,triggerEvent,truncateString,truthCheckCollection,unary,uncurry,unescapeHTML,unflattenObject,unfold,union,unionBy,unionWith,uniqueElements,uniqueElementsBy,uniqueElementsByRight,uniqueSymmetricDifference,untildify,unzip,unzipWith,validateNumber,when,without,words,xProd,yesNo,zip,zipObject,zipWith}; diff --git a/dist/_30s.js b/dist/_30s.js index 3af22678f..7e060f1c0 100644 --- a/dist/_30s.js +++ b/dist/_30s.js @@ -4,1329 +4,1329 @@ (factory()); }(this, (function () { 'use strict'; - const crypto = typeof require !== "undefined" && require('crypto'); const fs = typeof require !== "undefined" && require('fs'); + const crypto = typeof require !== "undefined" && require('crypto'); - const all = (arr, fn = Boolean) => arr.every(fn); - const allEqual = arr => arr.every(val => val === arr[0]); - const any = (arr, fn = Boolean) => arr.some(fn); - const approximatelyEqual = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) < epsilon; - const arrayToCSV = (arr, delimiter = ',') => - arr.map(v => v.map(x => `"${x}"`).join(delimiter)).join('\n'); - const arrayToHtmlList = (arr, listID) => - (el => ( - (el = document.querySelector('#' + listID)), - (el.innerHTML += arr.map(item => `
  • ${item}
  • `).join('')) - ))(); - const ary = (fn, n) => (...args) => fn(...args.slice(0, n)); - const atob = str => Buffer.from(str, 'base64').toString('binary'); - const attempt = (fn, ...args) => { - try { - return fn(...args); - } catch (e) { - return e instanceof Error ? e : new Error(e); - } - }; - const average = (...nums) => nums.reduce((acc, val) => acc + val, 0) / nums.length; - const averageBy = (arr, fn) => - arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0) / - arr.length; - const bifurcate = (arr, filter) => - arr.reduce((acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc), [[], []]); - const bifurcateBy = (arr, fn) => - arr.reduce((acc, val, i) => (acc[fn(val, i) ? 0 : 1].push(val), acc), [[], []]); - const bind = (fn, context, ...boundArgs) => (...args) => fn.apply(context, [...boundArgs, ...args]); - const bindAll = (obj, ...fns) => - fns.forEach( - fn => ( - (f = obj[fn]), - (obj[fn] = function() { - return f.apply(obj); - }) - ) - ); - const bindKey = (context, fn, ...boundArgs) => (...args) => - context[fn].apply(context, [...boundArgs, ...args]); - const binomialCoefficient = (n, k) => { - if (Number.isNaN(n) || Number.isNaN(k)) return NaN; - if (k < 0 || k > n) return 0; - if (k === 0 || k === n) return 1; - if (k === 1 || k === n - 1) return n; - if (n - k < k) k = n - k; - let res = n; - for (let j = 2; j <= k; j++) res *= (n - j + 1) / j; - return Math.round(res); - }; - const bottomVisible = () => - document.documentElement.clientHeight + window.scrollY >= - (document.documentElement.scrollHeight || document.documentElement.clientHeight); - const btoa = str => Buffer.from(str, 'binary').toString('base64'); - const byteSize = str => new Blob([str]).size; + const CSVToArray = (data, delimiter = ',', omitFirstRow = false) => + data + .slice(omitFirstRow ? data.indexOf('\n') + 1 : 0) + .split('\n') + .map(v => v.split(delimiter)); + const CSVToJSON = (data, delimiter = ',') => { + const titles = data.slice(0, data.indexOf('\n')).split(delimiter); + return data + .slice(data.indexOf('\n') + 1) + .split('\n') + .map(v => { + const values = v.split(delimiter); + return titles.reduce((obj, title, index) => ((obj[title] = values[index]), obj), {}); + }); + }; + + const JSONToFile = (obj, filename) => + fs.writeFile(`${filename}.json`, JSON.stringify(obj, null, 2)); + const JSONtoCSV = (arr, columns, delimiter = ',') => + [ + columns.join(delimiter), + ...arr.map(obj => + columns.reduce( + (acc, key) => `${acc}${!acc.length ? '' : delimiter}"${!obj[key] ? '' : obj[key]}"`, + '' + ) + ) + ].join('\n'); + const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0'); + const URLJoin = (...args) => + args + .join('/') + .replace(/[\/]+/g, '/') + .replace(/^(.+):\//, '$1://') + .replace(/^file:/, 'file:/') + .replace(/\/(\?|&|#[^!])/g, '$1') + .replace(/\?/g, '&') + .replace('&', '?'); + const UUIDGeneratorBrowser = () => + ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => + (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16) + ); + + const UUIDGeneratorNode = () => + ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => + (c ^ (crypto.randomBytes(1)[0] & (15 >> (c / 4)))).toString(16) + ); + const all = (arr, fn = Boolean) => arr.every(fn); + const allEqual = arr => arr.every(val => val === arr[0]); + const any = (arr, fn = Boolean) => arr.some(fn); + const approximatelyEqual = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) < epsilon; + const arrayToCSV = (arr, delimiter = ',') => + arr.map(v => v.map(x => `"${x}"`).join(delimiter)).join('\n'); + const arrayToHtmlList = (arr, listID) => + (el => ( + (el = document.querySelector('#' + listID)), + (el.innerHTML += arr.map(item => `
  • ${item}
  • `).join('')) + ))(); + const ary = (fn, n) => (...args) => fn(...args.slice(0, n)); + const atob = str => Buffer.from(str, 'base64').toString('binary'); + const attempt = (fn, ...args) => { + try { + return fn(...args); + } catch (e) { + return e instanceof Error ? e : new Error(e); + } + }; + const average = (...nums) => nums.reduce((acc, val) => acc + val, 0) / nums.length; + const averageBy = (arr, fn) => + arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0) / + arr.length; + const bifurcate = (arr, filter) => + arr.reduce((acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc), [[], []]); + const bifurcateBy = (arr, fn) => + arr.reduce((acc, val, i) => (acc[fn(val, i) ? 0 : 1].push(val), acc), [[], []]); + const bind = (fn, context, ...boundArgs) => (...args) => fn.apply(context, [...boundArgs, ...args]); + const bindAll = (obj, ...fns) => + fns.forEach( + fn => ( + (f = obj[fn]), + (obj[fn] = function() { + return f.apply(obj); + }) + ) + ); + const bindKey = (context, fn, ...boundArgs) => (...args) => + context[fn].apply(context, [...boundArgs, ...args]); + const binomialCoefficient = (n, k) => { + if (Number.isNaN(n) || Number.isNaN(k)) return NaN; + if (k < 0 || k > n) return 0; + if (k === 0 || k === n) return 1; + if (k === 1 || k === n - 1) return n; + if (n - k < k) k = n - k; + let res = n; + for (let j = 2; j <= k; j++) res *= (n - j + 1) / j; + return Math.round(res); + }; + const bottomVisible = () => + document.documentElement.clientHeight + window.scrollY >= + (document.documentElement.scrollHeight || document.documentElement.clientHeight); + const btoa = str => Buffer.from(str, 'binary').toString('base64'); + const byteSize = str => new Blob([str]).size; const call = (key, ...args) => context => context[key](...args); - const capitalize = ([first, ...rest], lowerRest = false) => - first.toUpperCase() + (lowerRest ? rest.join('').toLowerCase() : rest.join('')); - const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase()); - const castArray = val => (Array.isArray(val) ? val : [val]); - const chainAsync = fns => { - let curr = 0; - const next = () => fns[curr++](next); - next(); - }; - const chunk = (arr, size) => - Array.from({ length: Math.ceil(arr.length / size) }, (v, i) => - arr.slice(i * size, i * size + size) - ); - const clampNumber = (num, a, b) => Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b)); - const cloneRegExp = regExp => new RegExp(regExp.source, regExp.flags); - const coalesce = (...args) => args.find(_ => ![undefined, null].includes(_)); - const coalesceFactory = valid => (...args) => args.find(valid); + const capitalize = ([first, ...rest], lowerRest = false) => + first.toUpperCase() + (lowerRest ? rest.join('').toLowerCase() : rest.join('')); + const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase()); + const castArray = val => (Array.isArray(val) ? val : [val]); + const chainAsync = fns => { + let curr = 0; + const next = () => fns[curr++](next); + next(); + }; + const chunk = (arr, size) => + Array.from({ length: Math.ceil(arr.length / size) }, (v, i) => + arr.slice(i * size, i * size + size) + ); + const clampNumber = (num, a, b) => Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b)); + const cloneRegExp = regExp => new RegExp(regExp.source, regExp.flags); + const coalesce = (...args) => args.find(_ => ![undefined, null].includes(_)); + const coalesceFactory = valid => (...args) => args.find(valid); const collectInto = fn => (...args) => fn(args); - const colorize = (...args) => ({ - black: `\x1b[30m${args.join(' ')}`, - red: `\x1b[31m${args.join(' ')}`, - green: `\x1b[32m${args.join(' ')}`, - yellow: `\x1b[33m${args.join(' ')}`, - blue: `\x1b[34m${args.join(' ')}`, - magenta: `\x1b[35m${args.join(' ')}`, - cyan: `\x1b[36m${args.join(' ')}`, - white: `\x1b[37m${args.join(' ')}`, - bgBlack: `\x1b[40m${args.join(' ')}\x1b[0m`, - bgRed: `\x1b[41m${args.join(' ')}\x1b[0m`, - bgGreen: `\x1b[42m${args.join(' ')}\x1b[0m`, - bgYellow: `\x1b[43m${args.join(' ')}\x1b[0m`, - bgBlue: `\x1b[44m${args.join(' ')}\x1b[0m`, - bgMagenta: `\x1b[45m${args.join(' ')}\x1b[0m`, - bgCyan: `\x1b[46m${args.join(' ')}\x1b[0m`, - bgWhite: `\x1b[47m${args.join(' ')}\x1b[0m` - }); - const compact = arr => arr.filter(Boolean); - const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args))); - const composeRight = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args))); - const converge = (converger, fns) => (...args) => converger(...fns.map(fn => fn.apply(null, args))); - const copyToClipboard = str => { - const el = document.createElement('textarea'); - el.value = str; - el.setAttribute('readonly', ''); - el.style.position = 'absolute'; - el.style.left = '-9999px'; - document.body.appendChild(el); - const selected = - document.getSelection().rangeCount > 0 ? document.getSelection().getRangeAt(0) : false; - el.select(); - document.execCommand('copy'); - document.body.removeChild(el); - if (selected) { - document.getSelection().removeAllRanges(); - document.getSelection().addRange(selected); - } - }; - const countBy = (arr, fn) => - arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => { - acc[val] = (acc[val] || 0) + 1; - return acc; - }, {}); - const counter = (selector, start, end, step = 1, duration = 2000) => { - let current = start, - _step = (end - start) * step < 0 ? -step : step, - timer = setInterval(() => { - current += _step; - document.querySelector(selector).innerHTML = current; - if (current >= end) document.querySelector(selector).innerHTML = end; - if (current >= end) clearInterval(timer); - }, Math.abs(Math.floor(duration / (end - start)))); - return timer; - }; - const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0); - const createElement = str => { - const el = document.createElement('div'); - el.innerHTML = str; - return el.firstElementChild; - }; - const createEventHub = () => ({ - hub: Object.create(null), - emit(event, data) { - (this.hub[event] || []).forEach(handler => handler(data)); - }, - on(event, handler) { - if (!this.hub[event]) this.hub[event] = []; - this.hub[event].push(handler); - }, - off(event, handler) { - const i = (this.hub[event] || []).findIndex(h => h === handler); - if (i > -1) this.hub[event].splice(i, 1); - } - }); - const CSVToArray = (data, delimiter = ',', omitFirstRow = false) => - data - .slice(omitFirstRow ? data.indexOf('\n') + 1 : 0) - .split('\n') - .map(v => v.split(delimiter)); - const CSVToJSON = (data, delimiter = ',') => { - const titles = data.slice(0, data.indexOf('\n')).split(delimiter); - return data - .slice(data.indexOf('\n') + 1) - .split('\n') - .map(v => { - const values = v.split(delimiter); - return titles.reduce((obj, title, index) => ((obj[title] = values[index]), obj), {}); - }); - }; - const currentURL = () => window.location.href; - const curry = (fn, arity = fn.length, ...args) => - arity <= args.length ? fn(...args) : curry.bind(null, fn, arity, ...args); - const dayOfYear = date => - Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24); - const debounce = (fn, ms = 0) => { - let timeoutId; - return function(...args) { - clearTimeout(timeoutId); - timeoutId = setTimeout(() => fn.apply(this, args), ms); - }; - }; - const decapitalize = ([first, ...rest], upperRest = false) => - first.toLowerCase() + (upperRest ? rest.join('').toUpperCase() : rest.join('')); - const deepClone = obj => { - let clone = Object.assign({}, obj); - Object.keys(clone).forEach( - key => (clone[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key]) - ); - return Array.isArray(obj) ? (clone.length = obj.length) && Array.from(clone) : clone; - }; - const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v))); - const deepFreeze = obj => - Object.keys(obj).forEach( - prop => - !(obj[prop] instanceof Object) || Object.isFrozen(obj[prop]) ? null : deepFreeze(obj[prop]) - ) || Object.freeze(obj); - const defaults = (obj, ...defs) => Object.assign({}, obj, ...defs.reverse(), obj); - const defer = (fn, ...args) => setTimeout(fn, 1, ...args); - const degreesToRads = deg => (deg * Math.PI) / 180.0; - const delay = (fn, wait, ...args) => setTimeout(fn, wait, ...args); - const detectDeviceType = () => - /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) - ? 'Mobile' - : 'Desktop'; - const difference = (a, b) => { - const s = new Set(b); - return a.filter(x => !s.has(x)); - }; - const differenceBy = (a, b, fn) => { - const s = new Set(b.map(fn)); - return a.filter(x => !s.has(fn(x))); - }; - const differenceWith = (arr, val, comp) => arr.filter(a => val.findIndex(b => comp(a, b)) === -1); - const dig = (obj, target) => - target in obj - ? obj[target] - : Object.values(obj).reduce((acc, val) => { - if (acc !== undefined) return acc; - if (typeof val === 'object') return dig(val, target); - }, undefined); - const digitize = n => [...`${n}`].map(i => parseInt(i)); - const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0); - const drop = (arr, n = 1) => arr.slice(n); - const dropRight = (arr, n = 1) => arr.slice(0, -n); - const dropRightWhile = (arr, func) => { - while (arr.length > 0 && !func(arr[arr.length - 1])) arr = arr.slice(0, -1); - return arr; - }; - const dropWhile = (arr, func) => { - while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1); - return arr; - }; - const elementContains = (parent, child) => parent !== child && parent.contains(child); - const elementIsVisibleInViewport = (el, partiallyVisible = false) => { - const { top, left, bottom, right } = el.getBoundingClientRect(); - const { innerHeight, innerWidth } = window; - return partiallyVisible - ? ((top > 0 && top < innerHeight) || (bottom > 0 && bottom < innerHeight)) && - ((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth)) - : top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth; - }; - const elo = ([...ratings], kFactor = 32, selfRating) => { - const [a, b] = ratings; - const expectedScore = (self, opponent) => 1 / (1 + 10 ** ((opponent - self) / 400)); - const newRating = (rating, i) => - (selfRating || rating) + kFactor * (i - expectedScore(i ? a : b, i ? b : a)); - if (ratings.length === 2) return [newRating(a, 1), newRating(b, 0)]; - - for (let i = 0, len = ratings.length; i < len; i++) { - let j = i; - while (j < len - 1) { - j++; - [ratings[i], ratings[j]] = elo([ratings[i], ratings[j]], kFactor); - } - } - return ratings; - }; - const equals = (a, b) => { - if (a === b) return true; - if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime(); - if (!a || !b || (typeof a !== 'object' && typeof b !== 'object')) return a === b; - if (a === null || a === undefined || b === null || b === undefined) return false; - if (a.prototype !== b.prototype) return false; - let keys = Object.keys(a); - if (keys.length !== Object.keys(b).length) return false; - return keys.every(k => equals(a[k], b[k])); - }; - const escapeHTML = str => - str.replace( - /[&<>'"]/g, - tag => - ({ - '&': '&', - '<': '<', - '>': '>', - "'": ''', - '"': '"' - }[tag] || tag) - ); - const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); - const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === nth - 1); - const extendHex = shortHex => - '#' + - shortHex - .slice(shortHex.startsWith('#') ? 1 : 0) - .split('') - .map(x => x + x) - .join(''); - const factorial = n => - n < 0 - ? (() => { - throw new TypeError('Negative numbers are not allowed!'); - })() - : n <= 1 - ? 1 - : n * factorial(n - 1); - const fibonacci = n => - Array.from({ length: n }).reduce( - (acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), - [] - ); - const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i)); - const filterNonUniqueBy = (arr, fn) => - arr.filter((v, i) => arr.every((x, j) => (i === j) === fn(v, x, i, j))); - const findKey = (obj, fn) => Object.keys(obj).find(key => fn(obj[key], key, obj)); - const findLast = (arr, fn) => arr.filter(fn).pop(); - const findLastIndex = (arr, fn) => - arr - .map((val, i) => [i, val]) - .filter(([i, val]) => fn(val, i, arr)) - .pop()[0]; - const findLastKey = (obj, fn) => - Object.keys(obj) - .reverse() - .find(key => fn(obj[key], key, obj)); - const flatten = (arr, depth = 1) => - arr.reduce((a, v) => a.concat(depth > 1 && Array.isArray(v) ? flatten(v, depth - 1) : v), []); - const flattenObject = (obj, prefix = '') => - Object.keys(obj).reduce((acc, k) => { - const pre = prefix.length ? prefix + '.' : ''; - if (typeof obj[k] === 'object') Object.assign(acc, flattenObject(obj[k], pre + k)); - else acc[pre + k] = obj[k]; - return acc; - }, {}); + const colorize = (...args) => ({ + black: `\x1b[30m${args.join(' ')}`, + red: `\x1b[31m${args.join(' ')}`, + green: `\x1b[32m${args.join(' ')}`, + yellow: `\x1b[33m${args.join(' ')}`, + blue: `\x1b[34m${args.join(' ')}`, + magenta: `\x1b[35m${args.join(' ')}`, + cyan: `\x1b[36m${args.join(' ')}`, + white: `\x1b[37m${args.join(' ')}`, + bgBlack: `\x1b[40m${args.join(' ')}\x1b[0m`, + bgRed: `\x1b[41m${args.join(' ')}\x1b[0m`, + bgGreen: `\x1b[42m${args.join(' ')}\x1b[0m`, + bgYellow: `\x1b[43m${args.join(' ')}\x1b[0m`, + bgBlue: `\x1b[44m${args.join(' ')}\x1b[0m`, + bgMagenta: `\x1b[45m${args.join(' ')}\x1b[0m`, + bgCyan: `\x1b[46m${args.join(' ')}\x1b[0m`, + bgWhite: `\x1b[47m${args.join(' ')}\x1b[0m` + }); + const compact = arr => arr.filter(Boolean); + const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args))); + const composeRight = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args))); + const converge = (converger, fns) => (...args) => converger(...fns.map(fn => fn.apply(null, args))); + const copyToClipboard = str => { + const el = document.createElement('textarea'); + el.value = str; + el.setAttribute('readonly', ''); + el.style.position = 'absolute'; + el.style.left = '-9999px'; + document.body.appendChild(el); + const selected = + document.getSelection().rangeCount > 0 ? document.getSelection().getRangeAt(0) : false; + el.select(); + document.execCommand('copy'); + document.body.removeChild(el); + if (selected) { + document.getSelection().removeAllRanges(); + document.getSelection().addRange(selected); + } + }; + const countBy = (arr, fn) => + arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => { + acc[val] = (acc[val] || 0) + 1; + return acc; + }, {}); + const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0); + const counter = (selector, start, end, step = 1, duration = 2000) => { + let current = start, + _step = (end - start) * step < 0 ? -step : step, + timer = setInterval(() => { + current += _step; + document.querySelector(selector).innerHTML = current; + if (current >= end) document.querySelector(selector).innerHTML = end; + if (current >= end) clearInterval(timer); + }, Math.abs(Math.floor(duration / (end - start)))); + return timer; + }; + const createElement = str => { + const el = document.createElement('div'); + el.innerHTML = str; + return el.firstElementChild; + }; + const createEventHub = () => ({ + hub: Object.create(null), + emit(event, data) { + (this.hub[event] || []).forEach(handler => handler(data)); + }, + on(event, handler) { + if (!this.hub[event]) this.hub[event] = []; + this.hub[event].push(handler); + }, + off(event, handler) { + const i = (this.hub[event] || []).findIndex(h => h === handler); + if (i > -1) this.hub[event].splice(i, 1); + } + }); + const currentURL = () => window.location.href; + const curry = (fn, arity = fn.length, ...args) => + arity <= args.length ? fn(...args) : curry.bind(null, fn, arity, ...args); + const dayOfYear = date => + Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24); + const debounce = (fn, ms = 0) => { + let timeoutId; + return function(...args) { + clearTimeout(timeoutId); + timeoutId = setTimeout(() => fn.apply(this, args), ms); + }; + }; + const decapitalize = ([first, ...rest], upperRest = false) => + first.toLowerCase() + (upperRest ? rest.join('').toUpperCase() : rest.join('')); + const deepClone = obj => { + let clone = Object.assign({}, obj); + Object.keys(clone).forEach( + key => (clone[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key]) + ); + return Array.isArray(obj) ? (clone.length = obj.length) && Array.from(clone) : clone; + }; + const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v))); + const deepFreeze = obj => + Object.keys(obj).forEach( + prop => + !(obj[prop] instanceof Object) || Object.isFrozen(obj[prop]) ? null : deepFreeze(obj[prop]) + ) || Object.freeze(obj); + const defaults = (obj, ...defs) => Object.assign({}, obj, ...defs.reverse(), obj); + const defer = (fn, ...args) => setTimeout(fn, 1, ...args); + const degreesToRads = deg => (deg * Math.PI) / 180.0; + const delay = (fn, wait, ...args) => setTimeout(fn, wait, ...args); + const detectDeviceType = () => + /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) + ? 'Mobile' + : 'Desktop'; + const difference = (a, b) => { + const s = new Set(b); + return a.filter(x => !s.has(x)); + }; + const differenceBy = (a, b, fn) => { + const s = new Set(b.map(fn)); + return a.filter(x => !s.has(fn(x))); + }; + const differenceWith = (arr, val, comp) => arr.filter(a => val.findIndex(b => comp(a, b)) === -1); + const dig = (obj, target) => + target in obj + ? obj[target] + : Object.values(obj).reduce((acc, val) => { + if (acc !== undefined) return acc; + if (typeof val === 'object') return dig(val, target); + }, undefined); + const digitize = n => [...`${n}`].map(i => parseInt(i)); + const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0); + const drop = (arr, n = 1) => arr.slice(n); + const dropRight = (arr, n = 1) => arr.slice(0, -n); + const dropRightWhile = (arr, func) => { + while (arr.length > 0 && !func(arr[arr.length - 1])) arr = arr.slice(0, -1); + return arr; + }; + const dropWhile = (arr, func) => { + while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1); + return arr; + }; + const elementContains = (parent, child) => parent !== child && parent.contains(child); + const elementIsVisibleInViewport = (el, partiallyVisible = false) => { + const { top, left, bottom, right } = el.getBoundingClientRect(); + const { innerHeight, innerWidth } = window; + return partiallyVisible + ? ((top > 0 && top < innerHeight) || (bottom > 0 && bottom < innerHeight)) && + ((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth)) + : top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth; + }; + const elo = ([...ratings], kFactor = 32, selfRating) => { + const [a, b] = ratings; + const expectedScore = (self, opponent) => 1 / (1 + 10 ** ((opponent - self) / 400)); + const newRating = (rating, i) => + (selfRating || rating) + kFactor * (i - expectedScore(i ? a : b, i ? b : a)); + if (ratings.length === 2) return [newRating(a, 1), newRating(b, 0)]; + + for (let i = 0, len = ratings.length; i < len; i++) { + let j = i; + while (j < len - 1) { + j++; + [ratings[i], ratings[j]] = elo([ratings[i], ratings[j]], kFactor); + } + } + return ratings; + }; + const equals = (a, b) => { + if (a === b) return true; + if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime(); + if (!a || !b || (typeof a !== 'object' && typeof b !== 'object')) return a === b; + if (a === null || a === undefined || b === null || b === undefined) return false; + if (a.prototype !== b.prototype) return false; + let keys = Object.keys(a); + if (keys.length !== Object.keys(b).length) return false; + return keys.every(k => equals(a[k], b[k])); + }; + const escapeHTML = str => + str.replace( + /[&<>'"]/g, + tag => + ({ + '&': '&', + '<': '<', + '>': '>', + "'": ''', + '"': '"' + }[tag] || tag) + ); + const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === nth - 1); + const extendHex = shortHex => + '#' + + shortHex + .slice(shortHex.startsWith('#') ? 1 : 0) + .split('') + .map(x => x + x) + .join(''); + const factorial = n => + n < 0 + ? (() => { + throw new TypeError('Negative numbers are not allowed!'); + })() + : n <= 1 + ? 1 + : n * factorial(n - 1); + const fibonacci = n => + Array.from({ length: n }).reduce( + (acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), + [] + ); + const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i)); + const filterNonUniqueBy = (arr, fn) => + arr.filter((v, i) => arr.every((x, j) => (i === j) === fn(v, x, i, j))); + const findKey = (obj, fn) => Object.keys(obj).find(key => fn(obj[key], key, obj)); + const findLast = (arr, fn) => arr.filter(fn).pop(); + const findLastIndex = (arr, fn) => + arr + .map((val, i) => [i, val]) + .filter(([i, val]) => fn(val, i, arr)) + .pop()[0]; + const findLastKey = (obj, fn) => + Object.keys(obj) + .reverse() + .find(key => fn(obj[key], key, obj)); + const flatten = (arr, depth = 1) => + arr.reduce((a, v) => a.concat(depth > 1 && Array.isArray(v) ? flatten(v, depth - 1) : v), []); + const flattenObject = (obj, prefix = '') => + Object.keys(obj).reduce((acc, k) => { + const pre = prefix.length ? prefix + '.' : ''; + if (typeof obj[k] === 'object') Object.assign(acc, flattenObject(obj[k], pre + k)); + else acc[pre + k] = obj[k]; + return acc; + }, {}); const flip = fn => (first, ...rest) => fn(...rest, first); - const forEachRight = (arr, callback) => - arr - .slice(0) - .reverse() - .forEach(callback); - const formatDuration = ms => { - if (ms < 0) ms = -ms; - const time = { - day: Math.floor(ms / 86400000), - hour: Math.floor(ms / 3600000) % 24, - minute: Math.floor(ms / 60000) % 60, - second: Math.floor(ms / 1000) % 60, - millisecond: Math.floor(ms) % 1000 - }; - return Object.entries(time) - .filter(val => val[1] !== 0) - .map(([key, val]) => `${val} ${key}${val !== 1 ? 's' : ''}`) - .join(', '); - }; - const forOwn = (obj, fn) => Object.keys(obj).forEach(key => fn(obj[key], key, obj)); - const forOwnRight = (obj, fn) => - Object.keys(obj) - .reverse() - .forEach(key => fn(obj[key], key, obj)); - const fromCamelCase = (str, separator = '_') => - str - .replace(/([a-z\d])([A-Z])/g, '$1' + separator + '$2') - .replace(/([A-Z]+)([A-Z][a-z\d]+)/g, '$1' + separator + '$2') - .toLowerCase(); - const functionName = fn => (console.debug(fn.name), fn); - const functions = (obj, inherited = false) => - (inherited - ? [...Object.keys(obj), ...Object.keys(Object.getPrototypeOf(obj))] - : Object.keys(obj) - ).filter(key => typeof obj[key] === 'function'); - const gcd = (...arr) => { - const _gcd = (x, y) => (!y ? x : gcd(y, x % y)); - return [...arr].reduce((a, b) => _gcd(a, b)); - }; - const geometricProgression = (end, start = 1, step = 2) => - Array.from({ length: Math.floor(Math.log(end / start) / Math.log(step)) + 1 }).map( - (v, i) => start * step ** i - ); - const get = (from, ...selectors) => - [...selectors].map(s => - s - .replace(/\[([^\[\]]*)\]/g, '.$1.') - .split('.') - .filter(t => t !== '') - .reduce((prev, cur) => prev && prev[cur], from) - ); - const getColonTimeFromDate = date => date.toTimeString().slice(0, 8); - const getDaysDiffBetweenDates = (dateInitial, dateFinal) => - (dateFinal - dateInitial) / (1000 * 3600 * 24); - const getImages = (el, includeDuplicates = false) => { - const images = [...el.getElementsByTagName('img')].map(img => img.getAttribute('src')); - return includeDuplicates ? images : [...new Set(images)]; - }; - const getMeridiemSuffixOfInteger = num => - num === 0 || num === 24 - ? 12 + 'am' - : num === 12 - ? 12 + 'pm' - : num < 12 - ? (num % 12) + 'am' - : (num % 12) + 'pm'; - const getScrollPosition = (el = window) => ({ - x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft, - y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop - }); - const getStyle = (el, ruleName) => getComputedStyle(el)[ruleName]; - const getType = v => - v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name.toLowerCase(); - const getURLParameters = url => - (url.match(/([^?=&]+)(=([^&]*))/g) || []).reduce( - (a, v) => ((a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1)), a), - {} - ); - const groupBy = (arr, fn) => - arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val, i) => { - acc[val] = (acc[val] || []).concat(arr[i]); - return acc; - }, {}); - const hammingDistance = (num1, num2) => ((num1 ^ num2).toString(2).match(/1/g) || '').length; - const hasClass = (el, className) => el.classList.contains(className); - const hasFlags = (...flags) => - flags.every(flag => process.argv.includes(/^-{1,2}/.test(flag) ? flag : '--' + flag)); - const hashBrowser = val => - crypto.subtle.digest('SHA-256', new TextEncoder('utf-8').encode(val)).then(h => { - let hexes = [], - view = new DataView(h); - for (let i = 0; i < view.byteLength; i += 4) - hexes.push(('00000000' + view.getUint32(i).toString(16)).slice(-8)); - return hexes.join(''); - }); - - const hashNode = val => - new Promise(resolve => - setTimeout( - () => - resolve( - crypto - .createHash('sha256') - .update(val) - .digest('hex') - ), - 0 - ) - ); - const head = arr => arr[0]; - const hexToRGB = hex => { - let alpha = false, - h = hex.slice(hex.startsWith('#') ? 1 : 0); - if (h.length === 3) h = [...h].map(x => x + x).join(''); - else if (h.length === 8) alpha = true; - h = parseInt(h, 16); - return ( - 'rgb' + - (alpha ? 'a' : '') + - '(' + - (h >>> (alpha ? 24 : 16)) + - ', ' + - ((h & (alpha ? 0x00ff0000 : 0x00ff00)) >>> (alpha ? 16 : 8)) + - ', ' + - ((h & (alpha ? 0x0000ff00 : 0x0000ff)) >>> (alpha ? 8 : 0)) + - (alpha ? `, ${h & 0x000000ff}` : '') + - ')' - ); - }; - const hide = els => els.forEach(e => (e.style.display = 'none')); - const httpGet = (url, callback, err = console.error) => { - const request = new XMLHttpRequest(); - request.open('GET', url, true); - request.onload = () => callback(request.responseText); - request.onerror = () => err(request); - request.send(); - }; - const httpPost = (url, data, callback, err = console.error) => { - const request = new XMLHttpRequest(); - request.open('POST', url, true); - request.setRequestHeader('Content-type', 'application/json; charset=utf-8'); - request.onload = () => callback(request.responseText); - request.onerror = () => err(request); - request.send(data); - }; - const httpsRedirect = () => { - if (location.protocol !== 'https:') location.replace('https://' + location.href.split('//')[1]); - }; - const hz = (fn, iterations = 100) => { - const before = performance.now(); - for (let i = 0; i < iterations; i++) fn(); - return (1000 * iterations) / (performance.now() - before); - }; - const indentString = (str, count, indent = ' ') => str.replace(/^/gm, indent.repeat(count)); - const indexOfAll = (arr, val) => arr.reduce((acc, el, i) => (el === val ? [...acc, i] : acc), []); - const initial = arr => arr.slice(0, -1); - const initialize2DArray = (w, h, val = null) => - Array.from({ length: h }).map(() => Array.from({ length: w }).fill(val)); - const initializeArrayWithRange = (end, start = 0, step = 1) => - Array.from({ length: Math.ceil((end - start + 1) / step) }, (v, i) => i * step + start); - const initializeArrayWithRangeRight = (end, start = 0, step = 1) => - Array.from({ length: Math.ceil((end + 1 - start) / step) }).map( - (v, i, arr) => (arr.length - i - 1) * step + start - ); - const initializeArrayWithValues = (n, val = 0) => Array(n).fill(val); - const initializeNDArray = (val, ...args) => - args.length === 0 - ? val - : Array.from({ length: args[0] }).map(() => initializeNDArray(val, ...args.slice(1))); - const inRange = (n, start, end = null) => { - if (end && start > end) [end, start] = [start, end]; - return end == null ? n >= 0 && n < start : n >= start && n < end; - }; - const insertAfter = (el, htmlString) => el.insertAdjacentHTML('afterend', htmlString); - const insertBefore = (el, htmlString) => el.insertAdjacentHTML('beforebegin', htmlString); - const intersection = (a, b) => { - const s = new Set(b); - return a.filter(x => s.has(x)); - }; - const intersectionBy = (a, b, fn) => { - const s = new Set(b.map(fn)); - return a.filter(x => s.has(fn(x))); - }; - const intersectionWith = (a, b, comp) => a.filter(x => b.findIndex(y => comp(x, y)) !== -1); - const invertKeyValues = (obj, fn) => - Object.keys(obj).reduce((acc, key) => { - const val = fn ? fn(obj[key]) : obj[key]; - acc[val] = acc[val] || []; - acc[val].push(key); - return acc; - }, {}); - const is = (type, val) => ![, null].includes(val) && val.constructor === type; - const isAbsoluteURL = str => /^[a-z][a-z0-9+.-]*:/.test(str); - const isAfterDate = (dateA, dateB) => dateA > dateB; - const isAnagram = (str1, str2) => { - const normalize = str => - str - .toLowerCase() - .replace(/[^a-z0-9]/gi, '') - .split('') - .sort() - .join(''); - return normalize(str1) === normalize(str2); - }; - const isArrayLike = obj => obj != null && typeof obj[Symbol.iterator] === 'function'; - const isBeforeDate = (dateA, dateB) => dateA < dateB; - const isBoolean = val => typeof val === 'boolean'; - const isBrowser = () => ![typeof window, typeof document].includes('undefined'); - const isBrowserTabFocused = () => !document.hidden; - const isDivisible = (dividend, divisor) => dividend % divisor === 0; - const isDuplexStream = val => - val !== null && - typeof val === 'object' && - typeof val.pipe === 'function' && - typeof val._read === 'function' && - typeof val._readableState === 'object' && - typeof val._write === 'function' && - typeof val._writableState === 'object'; - const isEmpty = val => val == null || !(Object.keys(val) || val).length; - const isEven = num => num % 2 === 0; - const isFunction = val => typeof val === 'function'; - const isLowerCase = str => str === str.toLowerCase(); - const isNil = val => val === undefined || val === null; - const isNull = val => val === null; - const isNumber = val => typeof val === 'number'; - const isObject = obj => obj === Object(obj); - const isObjectLike = val => val !== null && typeof val === 'object'; - const isPlainObject = val => !!val && typeof val === 'object' && val.constructor === Object; - const isPrime = num => { - const boundary = Math.floor(Math.sqrt(num)); - for (var i = 2; i <= boundary; i++) if (num % i === 0) return false; - return num >= 2; - }; - const isPrimitive = val => Object(val) !== val; - const isPromiseLike = obj => - obj !== null && - (typeof obj === 'object' || typeof obj === 'function') && - typeof obj.then === 'function'; - const isReadableStream = val => - val !== null && - typeof val === 'object' && - typeof val.pipe === 'function' && - typeof val._read === 'function' && - typeof val._readableState === 'object'; - const isSameDate = (dateA, dateB) => dateA.toISOString() === dateB.toISOString(); - const isSorted = arr => { - let direction = -(arr[0] - arr[1]); - for (let [i, val] of arr.entries()) { - direction = !direction ? -(arr[i - 1] - arr[i]) : direction; - if (i === arr.length - 1) return !direction ? 0 : direction; - else if ((val - arr[i + 1]) * direction > 0) return 0; - } - }; - const isStream = val => val !== null && typeof val === 'object' && typeof val.pipe === 'function'; - const isString = val => typeof val === 'string'; - const isSymbol = val => typeof val === 'symbol'; - const isTravisCI = () => 'TRAVIS' in process.env && 'CI' in process.env; - const isUndefined = val => val === undefined; - const isUpperCase = str => str === str.toUpperCase(); - const isValidJSON = obj => { - try { - JSON.parse(obj); - return true; - } catch (e) { - return false; - } - }; - const isWritableStream = val => - val !== null && - typeof val === 'object' && - typeof val.pipe === 'function' && - typeof val._write === 'function' && - typeof val._writableState === 'object'; - const join = (arr, separator = ',', end = separator) => - arr.reduce( - (acc, val, i) => - i === arr.length - 2 - ? acc + val + end - : i === arr.length - 1 - ? acc + val - : acc + val + separator, - '' - ); - const JSONtoCSV = (arr, columns, delimiter = ',') => - [ - columns.join(delimiter), - ...arr.map(obj => - columns.reduce( - (acc, key) => `${acc}${!acc.length ? '' : delimiter}"${!obj[key] ? '' : obj[key]}"`, - '' - ) - ) - ].join('\n'); - - const JSONToFile = (obj, filename) => - fs.writeFile(`${filename}.json`, JSON.stringify(obj, null, 2)); - const last = arr => arr[arr.length - 1]; - const lcm = (...arr) => { - const gcd = (x, y) => (!y ? x : gcd(y, x % y)); - const _lcm = (x, y) => (x * y) / gcd(x, y); - return [...arr].reduce((a, b) => _lcm(a, b)); - }; - const longestItem = (val, ...vals) => - [val, ...vals].reduce((a, x) => (x.length > a.length ? x : a)); - const lowercaseKeys = obj => - Object.keys(obj).reduce((acc, key) => { - acc[key.toLowerCase()] = obj[key]; - return acc; - }, {}); - const luhnCheck = num => { - let arr = (num + '') - .split('') - .reverse() - .map(x => parseInt(x)); - let lastDigit = arr.splice(0, 1)[0]; - let sum = arr.reduce((acc, val, i) => (i % 2 !== 0 ? acc + val : acc + ((val * 2) % 9) || 9), 0); - sum += lastDigit; - return sum % 10 === 0; - }; - const mapKeys = (obj, fn) => - Object.keys(obj).reduce((acc, k) => { - acc[fn(obj[k], k, obj)] = obj[k]; - return acc; - }, {}); - const mapObject = (arr, fn) => - (a => ( - (a = [arr, arr.map(fn)]), a[0].reduce((acc, val, ind) => ((acc[val] = a[1][ind]), acc), {}) - ))(); - const mapString = (str, fn) => - str - .split('') - .map((c, i) => fn(c, i, str)) - .join(''); - const mapValues = (obj, fn) => - Object.keys(obj).reduce((acc, k) => { - acc[k] = fn(obj[k], k, obj); - return acc; - }, {}); - const mask = (cc, num = 4, mask = '*') => `${cc}`.slice(-num).padStart(`${cc}`.length, mask); - const matches = (obj, source) => - Object.keys(source).every(key => obj.hasOwnProperty(key) && obj[key] === source[key]); - const matchesWith = (obj, source, fn) => - Object.keys(source).every( - key => - obj.hasOwnProperty(key) && fn - ? fn(obj[key], source[key], key, obj, source) - : obj[key] == source[key] - ); - const maxBy = (arr, fn) => Math.max(...arr.map(typeof fn === 'function' ? fn : val => val[fn])); - const maxDate = (...dates) => new Date(Math.max.apply(null, ...dates)); - const maxN = (arr, n = 1) => [...arr].sort((a, b) => b - a).slice(0, n); - const median = arr => { - const mid = Math.floor(arr.length / 2), - nums = [...arr].sort((a, b) => a - b); - return arr.length % 2 !== 0 ? nums[mid] : (nums[mid - 1] + nums[mid]) / 2; - }; - const memoize = fn => { - const cache = new Map(); - const cached = function(val) { - return cache.has(val) ? cache.get(val) : cache.set(val, fn.call(this, val)) && cache.get(val); - }; - cached.cache = cache; - return cached; - }; - const merge = (...objs) => - [...objs].reduce( - (acc, obj) => - Object.keys(obj).reduce((a, k) => { - acc[k] = acc.hasOwnProperty(k) ? [].concat(acc[k]).concat(obj[k]) : obj[k]; - return acc; - }, {}), - {} - ); - const minBy = (arr, fn) => Math.min(...arr.map(typeof fn === 'function' ? fn : val => val[fn])); - const minDate = (...dates) => new Date(Math.min.apply(null, ...dates)); - const minN = (arr, n = 1) => [...arr].sort((a, b) => a - b).slice(0, n); - const mostPerformant = (fns, iterations = 10000) => { - const times = fns.map(fn => { - const before = performance.now(); - for (let i = 0; i < iterations; i++) fn(); - return performance.now() - before; - }); - return times.indexOf(Math.min(...times)); - }; - const negate = func => (...args) => !func(...args); - const nest = (items, id = null, link = 'parent_id') => - items - .filter(item => item[link] === id) - .map(item => ({ ...item, children: nest(items, item.id) })); - const nodeListToArray = nodeList => [...nodeList]; - const none = (arr, fn = Boolean) => !arr.some(fn); - const nthArg = n => (...args) => args.slice(n)[0]; - const nthElement = (arr, n = 0) => (n === -1 ? arr.slice(n) : arr.slice(n, n + 1))[0]; - const objectFromPairs = arr => arr.reduce((a, [key, val]) => ((a[key] = val), a), {}); - const objectToPairs = obj => Object.keys(obj).map(k => [k, obj[k]]); - const observeMutations = (element, callback, options) => { - const observer = new MutationObserver(mutations => mutations.forEach(m => callback(m))); - observer.observe( - element, - Object.assign( - { - childList: true, - attributes: true, - attributeOldValue: true, - characterData: true, - characterDataOldValue: true, - subtree: true - }, - options - ) - ); - return observer; - }; - const off = (el, evt, fn, opts = false) => el.removeEventListener(evt, fn, opts); - const offset = (arr, offset) => [...arr.slice(offset), ...arr.slice(0, offset)]; - const omit = (obj, arr) => - Object.keys(obj) - .filter(k => !arr.includes(k)) - .reduce((acc, key) => ((acc[key] = obj[key]), acc), {}); - const omitBy = (obj, fn) => - Object.keys(obj) - .filter(k => !fn(obj[k], k)) - .reduce((acc, key) => ((acc[key] = obj[key]), acc), {}); - const on = (el, evt, fn, opts = {}) => { - const delegatorFn = e => e.target.matches(opts.target) && fn.call(e.target, e); - el.addEventListener(evt, opts.target ? delegatorFn : fn, opts.options || false); - if (opts.target) return delegatorFn; - }; - const once = fn => { - let called = false; - return function(...args) { - if (called) return; - called = true; - return fn.apply(this, args); - }; - }; - const onUserInputChange = callback => { - let type = 'mouse', - lastTime = 0; - const mousemoveHandler = () => { - const now = performance.now(); - if (now - lastTime < 20) - (type = 'mouse'), callback(type), document.removeEventListener('mousemove', mousemoveHandler); - lastTime = now; - }; - document.addEventListener('touchstart', () => { - if (type === 'touch') return; - (type = 'touch'), callback(type), document.addEventListener('mousemove', mousemoveHandler); - }); - }; - const orderBy = (arr, props, orders) => - [...arr].sort((a, b) => - props.reduce((acc, prop, i) => { - if (acc === 0) { - const [p1, p2] = orders && orders[i] === 'desc' ? [b[prop], a[prop]] : [a[prop], b[prop]]; - acc = p1 > p2 ? 1 : p1 < p2 ? -1 : 0; - } - return acc; - }, 0) - ); - const over = (...fns) => (...args) => fns.map(fn => fn.apply(null, args)); - const overArgs = (fn, transforms) => (...args) => fn(...args.map((val, i) => transforms[i](val))); - const pad = (str, length, char = ' ') => - str.padStart((str.length + length) / 2, char).padEnd(length, char); - const palindrome = str => { - const s = str.toLowerCase().replace(/[\W_]/g, ''); - return s === [...s].reverse().join(''); - }; - const parseCookie = str => - str - .split(';') - .map(v => v.split('=')) - .reduce((acc, v) => { - acc[decodeURIComponent(v[0].trim())] = decodeURIComponent(v[1].trim()); - return acc; - }, {}); - const partial = (fn, ...partials) => (...args) => fn(...partials, ...args); - const partialRight = (fn, ...partials) => (...args) => fn(...args, ...partials); - const partition = (arr, fn) => - arr.reduce( - (acc, val, i, arr) => { - acc[fn(val, i, arr) ? 0 : 1].push(val); - return acc; - }, - [[], []] - ); - const percentile = (arr, val) => - (100 * arr.reduce((acc, v) => acc + (v < val ? 1 : 0) + (v === val ? 0.5 : 0), 0)) / arr.length; - const permutations = arr => { - if (arr.length <= 2) return arr.length === 2 ? [arr, [arr[1], arr[0]]] : arr; - return arr.reduce( - (acc, item, i) => - acc.concat( - permutations([...arr.slice(0, i), ...arr.slice(i + 1)]).map(val => [item, ...val]) - ), - [] - ); - }; - const pick = (obj, arr) => - arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {}); - const pickBy = (obj, fn) => - Object.keys(obj) - .filter(k => fn(obj[k], k)) - .reduce((acc, key) => ((acc[key] = obj[key]), acc), {}); - const pipeAsyncFunctions = (...fns) => arg => fns.reduce((p, f) => p.then(f), Promise.resolve(arg)); - const pipeFunctions = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args))); - const pluralize = (val, word, plural = word + 's') => { - const _pluralize = (num, word, plural = word + 's') => - [1, -1].includes(Number(num)) ? word : plural; - if (typeof val === 'object') return (num, word) => _pluralize(num, word, val[word]); - return _pluralize(val, word, plural); - }; - const powerset = arr => arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]); - const prefix = prop => { - const capitalizedProp = prop.charAt(0).toUpperCase() + prop.slice(1); - const prefixes = ['', 'webkit', 'moz', 'ms', 'o']; - const i = prefixes.findIndex( - prefix => typeof document.body.style[prefix ? prefix + capitalizedProp : prop] !== 'undefined' - ); - return i !== -1 ? (i === 0 ? prop : prefixes[i] + capitalizedProp) : null; - }; - const prettyBytes = (num, precision = 3, addSpace = true) => { - const UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; - if (Math.abs(num) < 1) return num + (addSpace ? ' ' : '') + UNITS[0]; - const exponent = Math.min(Math.floor(Math.log10(num < 0 ? -num : num) / 3), UNITS.length - 1); - const n = Number(((num < 0 ? -num : num) / 1000 ** exponent).toPrecision(precision)); - return (num < 0 ? '-' : '') + n + (addSpace ? ' ' : '') + UNITS[exponent]; - }; - const primes = num => { - let arr = Array.from({ length: num - 1 }).map((x, i) => i + 2), - sqroot = Math.floor(Math.sqrt(num)), - numsTillSqroot = Array.from({ length: sqroot - 1 }).map((x, i) => i + 2); - numsTillSqroot.forEach(x => (arr = arr.filter(y => y % x !== 0 || y === x))); - return arr; - }; - const promisify = func => (...args) => - new Promise((resolve, reject) => - func(...args, (err, result) => (err ? reject(err) : resolve(result))) - ); - const pull = (arr, ...args) => { - let argState = Array.isArray(args[0]) ? args[0] : args; - let pulled = arr.filter((v, i) => !argState.includes(v)); - arr.length = 0; - pulled.forEach(v => arr.push(v)); - }; - const pullAtIndex = (arr, pullArr) => { - let removed = []; - let pulled = arr - .map((v, i) => (pullArr.includes(i) ? removed.push(v) : v)) - .filter((v, i) => !pullArr.includes(i)); - arr.length = 0; - pulled.forEach(v => arr.push(v)); - return removed; - }; - const pullAtValue = (arr, pullArr) => { - let removed = [], - pushToRemove = arr.forEach((v, i) => (pullArr.includes(v) ? removed.push(v) : v)), - mutateTo = arr.filter((v, i) => !pullArr.includes(v)); - arr.length = 0; - mutateTo.forEach(v => arr.push(v)); - return removed; - }; - const pullBy = (arr, ...args) => { - const length = args.length; - let fn = length > 1 ? args[length - 1] : undefined; - fn = typeof fn == 'function' ? (args.pop(), fn) : undefined; - let argState = (Array.isArray(args[0]) ? args[0] : args).map(val => fn(val)); - let pulled = arr.filter((v, i) => !argState.includes(fn(v))); - arr.length = 0; - pulled.forEach(v => arr.push(v)); - }; - const radsToDegrees = rad => (rad * 180.0) / Math.PI; - const randomHexColorCode = () => { - let n = (Math.random() * 0xfffff * 1000000).toString(16); - return '#' + n.slice(0, 6); - }; - const randomIntArrayInRange = (min, max, n = 1) => - Array.from({ length: n }, () => Math.floor(Math.random() * (max - min + 1)) + min); - const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min; - const randomNumberInRange = (min, max) => Math.random() * (max - min) + min; - - const readFileLines = filename => - fs - .readFileSync(filename) - .toString('UTF8') - .split('\n'); - const rearg = (fn, indexes) => (...args) => fn(...indexes.map(i => args[i])); - const recordAnimationFrames = (callback, autoStart = true) => { - let running = true, - raf; - const stop = () => { - running = false; - cancelAnimationFrame(raf); - }; - const start = () => { - running = true; - run(); - }; - const run = () => { - raf = requestAnimationFrame(() => { - callback(); - if (running) run(); - }); - }; - if (autoStart) start(); - return { start, stop }; - }; - const redirect = (url, asLink = true) => - asLink ? (window.location.href = url) : window.location.replace(url); - const reducedFilter = (data, keys, fn) => - data.filter(fn).map(el => - keys.reduce((acc, key) => { - acc[key] = el[key]; - return acc; - }, {}) - ); - const reduceSuccessive = (arr, fn, acc) => - arr.reduce((res, val, i, arr) => (res.push(fn(res.slice(-1)[0], val, i, arr)), res), [acc]); - const reduceWhich = (arr, comparator = (a, b) => a - b) => - arr.reduce((a, b) => (comparator(a, b) >= 0 ? b : a)); - const reject = (pred, array) => array.filter((...args) => !pred(...args)); - const remove = (arr, func) => - Array.isArray(arr) - ? arr.filter(func).reduce((acc, val) => { - arr.splice(arr.indexOf(val), 1); - return acc.concat(val); - }, []) - : []; - const removeNonASCII = str => str.replace(/[^\x20-\x7E]/g, ''); - const renameKeys = (keysMap, obj) => - Object.keys(obj).reduce( - (acc, key) => ({ - ...acc, - ...{ [keysMap[key] || key]: obj[key] } - }), - {} - ); - const reverseString = str => [...str].reverse().join(''); - const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0'); - const round = (n, decimals = 0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`); - const runAsync = fn => { - const worker = new Worker( - URL.createObjectURL(new Blob([`postMessage((${fn})());`]), { - type: 'application/javascript; charset=utf-8' - }) - ); - return new Promise((res, rej) => { - worker.onmessage = ({ data }) => { - res(data), worker.terminate(); - }; - worker.onerror = err => { - rej(err), worker.terminate(); - }; - }); - }; - const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve()); - const sample = arr => arr[Math.floor(Math.random() * arr.length)]; - const sampleSize = ([...arr], n = 1) => { - let m = arr.length; - while (m) { - const i = Math.floor(Math.random() * m--); - [arr[m], arr[i]] = [arr[i], arr[m]]; - } - return arr.slice(0, n); - }; - const scrollToTop = () => { - const c = document.documentElement.scrollTop || document.body.scrollTop; - if (c > 0) { - window.requestAnimationFrame(scrollToTop); - window.scrollTo(0, c - c / 8); - } - }; - const sdbm = str => { - let arr = str.split(''); - return arr.reduce( - (hashCode, currentVal) => - (hashCode = currentVal.charCodeAt(0) + (hashCode << 6) + (hashCode << 16) - hashCode), - 0 - ); - }; - const serializeCookie = (name, val) => `${encodeURIComponent(name)}=${encodeURIComponent(val)}`; - const setStyle = (el, ruleName, val) => (el.style[ruleName] = val); - const shallowClone = obj => Object.assign({}, obj); - const shank = (arr, index = 0, delCount = 0, ...elements) => - arr - .slice(0, index) - .concat(elements) - .concat(arr.slice(index + delCount)); - const show = (...el) => [...el].forEach(e => (e.style.display = '')); - const shuffle = ([...arr]) => { - let m = arr.length; - while (m) { - const i = Math.floor(Math.random() * m--); - [arr[m], arr[i]] = [arr[i], arr[m]]; - } - return arr; - }; - const similarity = (arr, values) => arr.filter(v => values.includes(v)); - const size = val => - Array.isArray(val) - ? val.length - : val && typeof val === 'object' - ? val.size || val.length || Object.keys(val).length - : typeof val === 'string' - ? new Blob([val]).size - : 0; - const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); - const smoothScroll = element => - document.querySelector(element).scrollIntoView({ - behavior: 'smooth' - }); - const sortCharactersInString = str => [...str].sort((a, b) => a.localeCompare(b)).join(''); - const sortedIndex = (arr, n) => { - const isDescending = arr[0] > arr[arr.length - 1]; - const index = arr.findIndex(el => (isDescending ? n >= el : n <= el)); - return index === -1 ? arr.length : index; - }; - const sortedIndexBy = (arr, n, fn) => { - const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]); - const val = fn(n); - const index = arr.findIndex(el => (isDescending ? val >= fn(el) : val <= fn(el))); - return index === -1 ? arr.length : index; - }; - const sortedLastIndex = (arr, n) => { - const isDescending = arr[0] > arr[arr.length - 1]; - const index = arr.reverse().findIndex(el => (isDescending ? n <= el : n >= el)); - return index === -1 ? 0 : arr.length - index; - }; - const sortedLastIndexBy = (arr, n, fn) => { - const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]); - const val = fn(n); - const index = arr - .map(fn) - .reverse() - .findIndex(el => (isDescending ? val <= el : val >= el)); - return index === -1 ? 0 : arr.length - index; - }; - const splitLines = str => str.split(/\r?\n/); + const forEachRight = (arr, callback) => + arr + .slice(0) + .reverse() + .forEach(callback); + const forOwn = (obj, fn) => Object.keys(obj).forEach(key => fn(obj[key], key, obj)); + const forOwnRight = (obj, fn) => + Object.keys(obj) + .reverse() + .forEach(key => fn(obj[key], key, obj)); + const formatDuration = ms => { + if (ms < 0) ms = -ms; + const time = { + day: Math.floor(ms / 86400000), + hour: Math.floor(ms / 3600000) % 24, + minute: Math.floor(ms / 60000) % 60, + second: Math.floor(ms / 1000) % 60, + millisecond: Math.floor(ms) % 1000 + }; + return Object.entries(time) + .filter(val => val[1] !== 0) + .map(([key, val]) => `${val} ${key}${val !== 1 ? 's' : ''}`) + .join(', '); + }; + const fromCamelCase = (str, separator = '_') => + str + .replace(/([a-z\d])([A-Z])/g, '$1' + separator + '$2') + .replace(/([A-Z]+)([A-Z][a-z\d]+)/g, '$1' + separator + '$2') + .toLowerCase(); + const functionName = fn => (console.debug(fn.name), fn); + const functions = (obj, inherited = false) => + (inherited + ? [...Object.keys(obj), ...Object.keys(Object.getPrototypeOf(obj))] + : Object.keys(obj) + ).filter(key => typeof obj[key] === 'function'); + const gcd = (...arr) => { + const _gcd = (x, y) => (!y ? x : gcd(y, x % y)); + return [...arr].reduce((a, b) => _gcd(a, b)); + }; + const geometricProgression = (end, start = 1, step = 2) => + Array.from({ length: Math.floor(Math.log(end / start) / Math.log(step)) + 1 }).map( + (v, i) => start * step ** i + ); + const get = (from, ...selectors) => + [...selectors].map(s => + s + .replace(/\[([^\[\]]*)\]/g, '.$1.') + .split('.') + .filter(t => t !== '') + .reduce((prev, cur) => prev && prev[cur], from) + ); + const getColonTimeFromDate = date => date.toTimeString().slice(0, 8); + const getDaysDiffBetweenDates = (dateInitial, dateFinal) => + (dateFinal - dateInitial) / (1000 * 3600 * 24); + const getImages = (el, includeDuplicates = false) => { + const images = [...el.getElementsByTagName('img')].map(img => img.getAttribute('src')); + return includeDuplicates ? images : [...new Set(images)]; + }; + const getMeridiemSuffixOfInteger = num => + num === 0 || num === 24 + ? 12 + 'am' + : num === 12 + ? 12 + 'pm' + : num < 12 + ? (num % 12) + 'am' + : (num % 12) + 'pm'; + const getScrollPosition = (el = window) => ({ + x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft, + y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop + }); + const getStyle = (el, ruleName) => getComputedStyle(el)[ruleName]; + const getType = v => + v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name.toLowerCase(); + const getURLParameters = url => + (url.match(/([^?=&]+)(=([^&]*))/g) || []).reduce( + (a, v) => ((a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1)), a), + {} + ); + const groupBy = (arr, fn) => + arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val, i) => { + acc[val] = (acc[val] || []).concat(arr[i]); + return acc; + }, {}); + const hammingDistance = (num1, num2) => ((num1 ^ num2).toString(2).match(/1/g) || '').length; + const hasClass = (el, className) => el.classList.contains(className); + const hasFlags = (...flags) => + flags.every(flag => process.argv.includes(/^-{1,2}/.test(flag) ? flag : '--' + flag)); + const hashBrowser = val => + crypto.subtle.digest('SHA-256', new TextEncoder('utf-8').encode(val)).then(h => { + let hexes = [], + view = new DataView(h); + for (let i = 0; i < view.byteLength; i += 4) + hexes.push(('00000000' + view.getUint32(i).toString(16)).slice(-8)); + return hexes.join(''); + }); + + const hashNode = val => + new Promise(resolve => + setTimeout( + () => + resolve( + crypto + .createHash('sha256') + .update(val) + .digest('hex') + ), + 0 + ) + ); + const head = arr => arr[0]; + const hexToRGB = hex => { + let alpha = false, + h = hex.slice(hex.startsWith('#') ? 1 : 0); + if (h.length === 3) h = [...h].map(x => x + x).join(''); + else if (h.length === 8) alpha = true; + h = parseInt(h, 16); + return ( + 'rgb' + + (alpha ? 'a' : '') + + '(' + + (h >>> (alpha ? 24 : 16)) + + ', ' + + ((h & (alpha ? 0x00ff0000 : 0x00ff00)) >>> (alpha ? 16 : 8)) + + ', ' + + ((h & (alpha ? 0x0000ff00 : 0x0000ff)) >>> (alpha ? 8 : 0)) + + (alpha ? `, ${h & 0x000000ff}` : '') + + ')' + ); + }; + const hide = els => els.forEach(e => (e.style.display = 'none')); + const httpGet = (url, callback, err = console.error) => { + const request = new XMLHttpRequest(); + request.open('GET', url, true); + request.onload = () => callback(request.responseText); + request.onerror = () => err(request); + request.send(); + }; + const httpPost = (url, data, callback, err = console.error) => { + const request = new XMLHttpRequest(); + request.open('POST', url, true); + request.setRequestHeader('Content-type', 'application/json; charset=utf-8'); + request.onload = () => callback(request.responseText); + request.onerror = () => err(request); + request.send(data); + }; + const httpsRedirect = () => { + if (location.protocol !== 'https:') location.replace('https://' + location.href.split('//')[1]); + }; + const hz = (fn, iterations = 100) => { + const before = performance.now(); + for (let i = 0; i < iterations; i++) fn(); + return (1000 * iterations) / (performance.now() - before); + }; + const inRange = (n, start, end = null) => { + if (end && start > end) [end, start] = [start, end]; + return end == null ? n >= 0 && n < start : n >= start && n < end; + }; + const indentString = (str, count, indent = ' ') => str.replace(/^/gm, indent.repeat(count)); + const indexOfAll = (arr, val) => arr.reduce((acc, el, i) => (el === val ? [...acc, i] : acc), []); + const initial = arr => arr.slice(0, -1); + const initialize2DArray = (w, h, val = null) => + Array.from({ length: h }).map(() => Array.from({ length: w }).fill(val)); + const initializeArrayWithRange = (end, start = 0, step = 1) => + Array.from({ length: Math.ceil((end - start + 1) / step) }, (v, i) => i * step + start); + const initializeArrayWithRangeRight = (end, start = 0, step = 1) => + Array.from({ length: Math.ceil((end + 1 - start) / step) }).map( + (v, i, arr) => (arr.length - i - 1) * step + start + ); + const initializeArrayWithValues = (n, val = 0) => Array(n).fill(val); + const initializeNDArray = (val, ...args) => + args.length === 0 + ? val + : Array.from({ length: args[0] }).map(() => initializeNDArray(val, ...args.slice(1))); + const insertAfter = (el, htmlString) => el.insertAdjacentHTML('afterend', htmlString); + const insertBefore = (el, htmlString) => el.insertAdjacentHTML('beforebegin', htmlString); + const intersection = (a, b) => { + const s = new Set(b); + return a.filter(x => s.has(x)); + }; + const intersectionBy = (a, b, fn) => { + const s = new Set(b.map(fn)); + return a.filter(x => s.has(fn(x))); + }; + const intersectionWith = (a, b, comp) => a.filter(x => b.findIndex(y => comp(x, y)) !== -1); + const invertKeyValues = (obj, fn) => + Object.keys(obj).reduce((acc, key) => { + const val = fn ? fn(obj[key]) : obj[key]; + acc[val] = acc[val] || []; + acc[val].push(key); + return acc; + }, {}); + const is = (type, val) => ![, null].includes(val) && val.constructor === type; + const isAbsoluteURL = str => /^[a-z][a-z0-9+.-]*:/.test(str); + const isAfterDate = (dateA, dateB) => dateA > dateB; + const isAnagram = (str1, str2) => { + const normalize = str => + str + .toLowerCase() + .replace(/[^a-z0-9]/gi, '') + .split('') + .sort() + .join(''); + return normalize(str1) === normalize(str2); + }; + const isArrayLike = obj => obj != null && typeof obj[Symbol.iterator] === 'function'; + const isBeforeDate = (dateA, dateB) => dateA < dateB; + const isBoolean = val => typeof val === 'boolean'; + const isBrowser = () => ![typeof window, typeof document].includes('undefined'); + const isBrowserTabFocused = () => !document.hidden; + const isDivisible = (dividend, divisor) => dividend % divisor === 0; + const isDuplexStream = val => + val !== null && + typeof val === 'object' && + typeof val.pipe === 'function' && + typeof val._read === 'function' && + typeof val._readableState === 'object' && + typeof val._write === 'function' && + typeof val._writableState === 'object'; + const isEmpty = val => val == null || !(Object.keys(val) || val).length; + const isEven = num => num % 2 === 0; + const isFunction = val => typeof val === 'function'; + const isLowerCase = str => str === str.toLowerCase(); + const isNil = val => val === undefined || val === null; + const isNull = val => val === null; + const isNumber = val => typeof val === 'number'; + const isObject = obj => obj === Object(obj); + const isObjectLike = val => val !== null && typeof val === 'object'; + const isPlainObject = val => !!val && typeof val === 'object' && val.constructor === Object; + const isPrime = num => { + const boundary = Math.floor(Math.sqrt(num)); + for (var i = 2; i <= boundary; i++) if (num % i === 0) return false; + return num >= 2; + }; + const isPrimitive = val => Object(val) !== val; + const isPromiseLike = obj => + obj !== null && + (typeof obj === 'object' || typeof obj === 'function') && + typeof obj.then === 'function'; + const isReadableStream = val => + val !== null && + typeof val === 'object' && + typeof val.pipe === 'function' && + typeof val._read === 'function' && + typeof val._readableState === 'object'; + const isSameDate = (dateA, dateB) => dateA.toISOString() === dateB.toISOString(); + const isSorted = arr => { + let direction = -(arr[0] - arr[1]); + for (let [i, val] of arr.entries()) { + direction = !direction ? -(arr[i - 1] - arr[i]) : direction; + if (i === arr.length - 1) return !direction ? 0 : direction; + else if ((val - arr[i + 1]) * direction > 0) return 0; + } + }; + const isStream = val => val !== null && typeof val === 'object' && typeof val.pipe === 'function'; + const isString = val => typeof val === 'string'; + const isSymbol = val => typeof val === 'symbol'; + const isTravisCI = () => 'TRAVIS' in process.env && 'CI' in process.env; + const isUndefined = val => val === undefined; + const isUpperCase = str => str === str.toUpperCase(); + const isValidJSON = obj => { + try { + JSON.parse(obj); + return true; + } catch (e) { + return false; + } + }; + const isWritableStream = val => + val !== null && + typeof val === 'object' && + typeof val.pipe === 'function' && + typeof val._write === 'function' && + typeof val._writableState === 'object'; + const join = (arr, separator = ',', end = separator) => + arr.reduce( + (acc, val, i) => + i === arr.length - 2 + ? acc + val + end + : i === arr.length - 1 + ? acc + val + : acc + val + separator, + '' + ); + const last = arr => arr[arr.length - 1]; + const lcm = (...arr) => { + const gcd = (x, y) => (!y ? x : gcd(y, x % y)); + const _lcm = (x, y) => (x * y) / gcd(x, y); + return [...arr].reduce((a, b) => _lcm(a, b)); + }; + const longestItem = (val, ...vals) => + [val, ...vals].reduce((a, x) => (x.length > a.length ? x : a)); + const lowercaseKeys = obj => + Object.keys(obj).reduce((acc, key) => { + acc[key.toLowerCase()] = obj[key]; + return acc; + }, {}); + const luhnCheck = num => { + let arr = (num + '') + .split('') + .reverse() + .map(x => parseInt(x)); + let lastDigit = arr.splice(0, 1)[0]; + let sum = arr.reduce((acc, val, i) => (i % 2 !== 0 ? acc + val : acc + ((val * 2) % 9) || 9), 0); + sum += lastDigit; + return sum % 10 === 0; + }; + const mapKeys = (obj, fn) => + Object.keys(obj).reduce((acc, k) => { + acc[fn(obj[k], k, obj)] = obj[k]; + return acc; + }, {}); + const mapObject = (arr, fn) => + (a => ( + (a = [arr, arr.map(fn)]), a[0].reduce((acc, val, ind) => ((acc[val] = a[1][ind]), acc), {}) + ))(); + const mapString = (str, fn) => + str + .split('') + .map((c, i) => fn(c, i, str)) + .join(''); + const mapValues = (obj, fn) => + Object.keys(obj).reduce((acc, k) => { + acc[k] = fn(obj[k], k, obj); + return acc; + }, {}); + const mask = (cc, num = 4, mask = '*') => `${cc}`.slice(-num).padStart(`${cc}`.length, mask); + const matches = (obj, source) => + Object.keys(source).every(key => obj.hasOwnProperty(key) && obj[key] === source[key]); + const matchesWith = (obj, source, fn) => + Object.keys(source).every( + key => + obj.hasOwnProperty(key) && fn + ? fn(obj[key], source[key], key, obj, source) + : obj[key] == source[key] + ); + const maxBy = (arr, fn) => Math.max(...arr.map(typeof fn === 'function' ? fn : val => val[fn])); + const maxDate = (...dates) => new Date(Math.max.apply(null, ...dates)); + const maxN = (arr, n = 1) => [...arr].sort((a, b) => b - a).slice(0, n); + const median = arr => { + const mid = Math.floor(arr.length / 2), + nums = [...arr].sort((a, b) => a - b); + return arr.length % 2 !== 0 ? nums[mid] : (nums[mid - 1] + nums[mid]) / 2; + }; + const memoize = fn => { + const cache = new Map(); + const cached = function(val) { + return cache.has(val) ? cache.get(val) : cache.set(val, fn.call(this, val)) && cache.get(val); + }; + cached.cache = cache; + return cached; + }; + const merge = (...objs) => + [...objs].reduce( + (acc, obj) => + Object.keys(obj).reduce((a, k) => { + acc[k] = acc.hasOwnProperty(k) ? [].concat(acc[k]).concat(obj[k]) : obj[k]; + return acc; + }, {}), + {} + ); + const minBy = (arr, fn) => Math.min(...arr.map(typeof fn === 'function' ? fn : val => val[fn])); + const minDate = (...dates) => new Date(Math.min.apply(null, ...dates)); + const minN = (arr, n = 1) => [...arr].sort((a, b) => a - b).slice(0, n); + const mostPerformant = (fns, iterations = 10000) => { + const times = fns.map(fn => { + const before = performance.now(); + for (let i = 0; i < iterations; i++) fn(); + return performance.now() - before; + }); + return times.indexOf(Math.min(...times)); + }; + const negate = func => (...args) => !func(...args); + const nest = (items, id = null, link = 'parent_id') => + items + .filter(item => item[link] === id) + .map(item => ({ ...item, children: nest(items, item.id) })); + const nodeListToArray = nodeList => [...nodeList]; + const none = (arr, fn = Boolean) => !arr.some(fn); + const nthArg = n => (...args) => args.slice(n)[0]; + const nthElement = (arr, n = 0) => (n === -1 ? arr.slice(n) : arr.slice(n, n + 1))[0]; + const objectFromPairs = arr => arr.reduce((a, [key, val]) => ((a[key] = val), a), {}); + const objectToPairs = obj => Object.keys(obj).map(k => [k, obj[k]]); + const observeMutations = (element, callback, options) => { + const observer = new MutationObserver(mutations => mutations.forEach(m => callback(m))); + observer.observe( + element, + Object.assign( + { + childList: true, + attributes: true, + attributeOldValue: true, + characterData: true, + characterDataOldValue: true, + subtree: true + }, + options + ) + ); + return observer; + }; + const off = (el, evt, fn, opts = false) => el.removeEventListener(evt, fn, opts); + const offset = (arr, offset) => [...arr.slice(offset), ...arr.slice(0, offset)]; + const omit = (obj, arr) => + Object.keys(obj) + .filter(k => !arr.includes(k)) + .reduce((acc, key) => ((acc[key] = obj[key]), acc), {}); + const omitBy = (obj, fn) => + Object.keys(obj) + .filter(k => !fn(obj[k], k)) + .reduce((acc, key) => ((acc[key] = obj[key]), acc), {}); + const on = (el, evt, fn, opts = {}) => { + const delegatorFn = e => e.target.matches(opts.target) && fn.call(e.target, e); + el.addEventListener(evt, opts.target ? delegatorFn : fn, opts.options || false); + if (opts.target) return delegatorFn; + }; + const onUserInputChange = callback => { + let type = 'mouse', + lastTime = 0; + const mousemoveHandler = () => { + const now = performance.now(); + if (now - lastTime < 20) + (type = 'mouse'), callback(type), document.removeEventListener('mousemove', mousemoveHandler); + lastTime = now; + }; + document.addEventListener('touchstart', () => { + if (type === 'touch') return; + (type = 'touch'), callback(type), document.addEventListener('mousemove', mousemoveHandler); + }); + }; + const once = fn => { + let called = false; + return function(...args) { + if (called) return; + called = true; + return fn.apply(this, args); + }; + }; + const orderBy = (arr, props, orders) => + [...arr].sort((a, b) => + props.reduce((acc, prop, i) => { + if (acc === 0) { + const [p1, p2] = orders && orders[i] === 'desc' ? [b[prop], a[prop]] : [a[prop], b[prop]]; + acc = p1 > p2 ? 1 : p1 < p2 ? -1 : 0; + } + return acc; + }, 0) + ); + const over = (...fns) => (...args) => fns.map(fn => fn.apply(null, args)); + const overArgs = (fn, transforms) => (...args) => fn(...args.map((val, i) => transforms[i](val))); + const pad = (str, length, char = ' ') => + str.padStart((str.length + length) / 2, char).padEnd(length, char); + const palindrome = str => { + const s = str.toLowerCase().replace(/[\W_]/g, ''); + return s === [...s].reverse().join(''); + }; + const parseCookie = str => + str + .split(';') + .map(v => v.split('=')) + .reduce((acc, v) => { + acc[decodeURIComponent(v[0].trim())] = decodeURIComponent(v[1].trim()); + return acc; + }, {}); + const partial = (fn, ...partials) => (...args) => fn(...partials, ...args); + const partialRight = (fn, ...partials) => (...args) => fn(...args, ...partials); + const partition = (arr, fn) => + arr.reduce( + (acc, val, i, arr) => { + acc[fn(val, i, arr) ? 0 : 1].push(val); + return acc; + }, + [[], []] + ); + const percentile = (arr, val) => + (100 * arr.reduce((acc, v) => acc + (v < val ? 1 : 0) + (v === val ? 0.5 : 0), 0)) / arr.length; + const permutations = arr => { + if (arr.length <= 2) return arr.length === 2 ? [arr, [arr[1], arr[0]]] : arr; + return arr.reduce( + (acc, item, i) => + acc.concat( + permutations([...arr.slice(0, i), ...arr.slice(i + 1)]).map(val => [item, ...val]) + ), + [] + ); + }; + const pick = (obj, arr) => + arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {}); + const pickBy = (obj, fn) => + Object.keys(obj) + .filter(k => fn(obj[k], k)) + .reduce((acc, key) => ((acc[key] = obj[key]), acc), {}); + const pipeAsyncFunctions = (...fns) => arg => fns.reduce((p, f) => p.then(f), Promise.resolve(arg)); + const pipeFunctions = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args))); + const pluralize = (val, word, plural = word + 's') => { + const _pluralize = (num, word, plural = word + 's') => + [1, -1].includes(Number(num)) ? word : plural; + if (typeof val === 'object') return (num, word) => _pluralize(num, word, val[word]); + return _pluralize(val, word, plural); + }; + const powerset = arr => arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]); + const prefix = prop => { + const capitalizedProp = prop.charAt(0).toUpperCase() + prop.slice(1); + const prefixes = ['', 'webkit', 'moz', 'ms', 'o']; + const i = prefixes.findIndex( + prefix => typeof document.body.style[prefix ? prefix + capitalizedProp : prop] !== 'undefined' + ); + return i !== -1 ? (i === 0 ? prop : prefixes[i] + capitalizedProp) : null; + }; + const prettyBytes = (num, precision = 3, addSpace = true) => { + const UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; + if (Math.abs(num) < 1) return num + (addSpace ? ' ' : '') + UNITS[0]; + const exponent = Math.min(Math.floor(Math.log10(num < 0 ? -num : num) / 3), UNITS.length - 1); + const n = Number(((num < 0 ? -num : num) / 1000 ** exponent).toPrecision(precision)); + return (num < 0 ? '-' : '') + n + (addSpace ? ' ' : '') + UNITS[exponent]; + }; + const primes = num => { + let arr = Array.from({ length: num - 1 }).map((x, i) => i + 2), + sqroot = Math.floor(Math.sqrt(num)), + numsTillSqroot = Array.from({ length: sqroot - 1 }).map((x, i) => i + 2); + numsTillSqroot.forEach(x => (arr = arr.filter(y => y % x !== 0 || y === x))); + return arr; + }; + const promisify = func => (...args) => + new Promise((resolve, reject) => + func(...args, (err, result) => (err ? reject(err) : resolve(result))) + ); + const pull = (arr, ...args) => { + let argState = Array.isArray(args[0]) ? args[0] : args; + let pulled = arr.filter((v, i) => !argState.includes(v)); + arr.length = 0; + pulled.forEach(v => arr.push(v)); + }; + const pullAtIndex = (arr, pullArr) => { + let removed = []; + let pulled = arr + .map((v, i) => (pullArr.includes(i) ? removed.push(v) : v)) + .filter((v, i) => !pullArr.includes(i)); + arr.length = 0; + pulled.forEach(v => arr.push(v)); + return removed; + }; + const pullAtValue = (arr, pullArr) => { + let removed = [], + pushToRemove = arr.forEach((v, i) => (pullArr.includes(v) ? removed.push(v) : v)), + mutateTo = arr.filter((v, i) => !pullArr.includes(v)); + arr.length = 0; + mutateTo.forEach(v => arr.push(v)); + return removed; + }; + const pullBy = (arr, ...args) => { + const length = args.length; + let fn = length > 1 ? args[length - 1] : undefined; + fn = typeof fn == 'function' ? (args.pop(), fn) : undefined; + let argState = (Array.isArray(args[0]) ? args[0] : args).map(val => fn(val)); + let pulled = arr.filter((v, i) => !argState.includes(fn(v))); + arr.length = 0; + pulled.forEach(v => arr.push(v)); + }; + const radsToDegrees = rad => (rad * 180.0) / Math.PI; + const randomHexColorCode = () => { + let n = (Math.random() * 0xfffff * 1000000).toString(16); + return '#' + n.slice(0, 6); + }; + const randomIntArrayInRange = (min, max, n = 1) => + Array.from({ length: n }, () => Math.floor(Math.random() * (max - min + 1)) + min); + const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min; + const randomNumberInRange = (min, max) => Math.random() * (max - min) + min; + + const readFileLines = filename => + fs + .readFileSync(filename) + .toString('UTF8') + .split('\n'); + const rearg = (fn, indexes) => (...args) => fn(...indexes.map(i => args[i])); + const recordAnimationFrames = (callback, autoStart = true) => { + let running = true, + raf; + const stop = () => { + running = false; + cancelAnimationFrame(raf); + }; + const start = () => { + running = true; + run(); + }; + const run = () => { + raf = requestAnimationFrame(() => { + callback(); + if (running) run(); + }); + }; + if (autoStart) start(); + return { start, stop }; + }; + const redirect = (url, asLink = true) => + asLink ? (window.location.href = url) : window.location.replace(url); + const reduceSuccessive = (arr, fn, acc) => + arr.reduce((res, val, i, arr) => (res.push(fn(res.slice(-1)[0], val, i, arr)), res), [acc]); + const reduceWhich = (arr, comparator = (a, b) => a - b) => + arr.reduce((a, b) => (comparator(a, b) >= 0 ? b : a)); + const reducedFilter = (data, keys, fn) => + data.filter(fn).map(el => + keys.reduce((acc, key) => { + acc[key] = el[key]; + return acc; + }, {}) + ); + const reject = (pred, array) => array.filter((...args) => !pred(...args)); + const remove = (arr, func) => + Array.isArray(arr) + ? arr.filter(func).reduce((acc, val) => { + arr.splice(arr.indexOf(val), 1); + return acc.concat(val); + }, []) + : []; + const removeNonASCII = str => str.replace(/[^\x20-\x7E]/g, ''); + const renameKeys = (keysMap, obj) => + Object.keys(obj).reduce( + (acc, key) => ({ + ...acc, + ...{ [keysMap[key] || key]: obj[key] } + }), + {} + ); + const reverseString = str => [...str].reverse().join(''); + const round = (n, decimals = 0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`); + const runAsync = fn => { + const worker = new Worker( + URL.createObjectURL(new Blob([`postMessage((${fn})());`]), { + type: 'application/javascript; charset=utf-8' + }) + ); + return new Promise((res, rej) => { + worker.onmessage = ({ data }) => { + res(data), worker.terminate(); + }; + worker.onerror = err => { + rej(err), worker.terminate(); + }; + }); + }; + const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve()); + const sample = arr => arr[Math.floor(Math.random() * arr.length)]; + const sampleSize = ([...arr], n = 1) => { + let m = arr.length; + while (m) { + const i = Math.floor(Math.random() * m--); + [arr[m], arr[i]] = [arr[i], arr[m]]; + } + return arr.slice(0, n); + }; + const scrollToTop = () => { + const c = document.documentElement.scrollTop || document.body.scrollTop; + if (c > 0) { + window.requestAnimationFrame(scrollToTop); + window.scrollTo(0, c - c / 8); + } + }; + const sdbm = str => { + let arr = str.split(''); + return arr.reduce( + (hashCode, currentVal) => + (hashCode = currentVal.charCodeAt(0) + (hashCode << 6) + (hashCode << 16) - hashCode), + 0 + ); + }; + const serializeCookie = (name, val) => `${encodeURIComponent(name)}=${encodeURIComponent(val)}`; + const setStyle = (el, ruleName, val) => (el.style[ruleName] = val); + const shallowClone = obj => Object.assign({}, obj); + const shank = (arr, index = 0, delCount = 0, ...elements) => + arr + .slice(0, index) + .concat(elements) + .concat(arr.slice(index + delCount)); + const show = (...el) => [...el].forEach(e => (e.style.display = '')); + const shuffle = ([...arr]) => { + let m = arr.length; + while (m) { + const i = Math.floor(Math.random() * m--); + [arr[m], arr[i]] = [arr[i], arr[m]]; + } + return arr; + }; + const similarity = (arr, values) => arr.filter(v => values.includes(v)); + const size = val => + Array.isArray(val) + ? val.length + : val && typeof val === 'object' + ? val.size || val.length || Object.keys(val).length + : typeof val === 'string' + ? new Blob([val]).size + : 0; + const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); + const smoothScroll = element => + document.querySelector(element).scrollIntoView({ + behavior: 'smooth' + }); + const sortCharactersInString = str => [...str].sort((a, b) => a.localeCompare(b)).join(''); + const sortedIndex = (arr, n) => { + const isDescending = arr[0] > arr[arr.length - 1]; + const index = arr.findIndex(el => (isDescending ? n >= el : n <= el)); + return index === -1 ? arr.length : index; + }; + const sortedIndexBy = (arr, n, fn) => { + const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]); + const val = fn(n); + const index = arr.findIndex(el => (isDescending ? val >= fn(el) : val <= fn(el))); + return index === -1 ? arr.length : index; + }; + const sortedLastIndex = (arr, n) => { + const isDescending = arr[0] > arr[arr.length - 1]; + const index = arr.reverse().findIndex(el => (isDescending ? n <= el : n >= el)); + return index === -1 ? 0 : arr.length - index; + }; + const sortedLastIndexBy = (arr, n, fn) => { + const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]); + const val = fn(n); + const index = arr + .map(fn) + .reverse() + .findIndex(el => (isDescending ? val <= el : val >= el)); + return index === -1 ? 0 : arr.length - index; + }; + const splitLines = str => str.split(/\r?\n/); const spreadOver = fn => argsArr => fn(...argsArr); - const stableSort = (arr, compare) => - arr - .map((item, index) => ({ item, index })) - .sort((a, b) => compare(a.item, b.item) || a.index - b.index) - .map(({ item }) => item); - const standardDeviation = (arr, usePopulation = false) => { - const mean = arr.reduce((acc, val) => acc + val, 0) / arr.length; - return Math.sqrt( - arr.reduce((acc, val) => acc.concat((val - mean) ** 2), []).reduce((acc, val) => acc + val, 0) / - (arr.length - (usePopulation ? 0 : 1)) - ); - }; - const stringPermutations = str => { - if (str.length <= 2) return str.length === 2 ? [str, str[1] + str[0]] : [str]; - return str - .split('') - .reduce( - (acc, letter, i) => - acc.concat(stringPermutations(str.slice(0, i) + str.slice(i + 1)).map(val => letter + val)), - [] - ); - }; - const stripHTMLTags = str => str.replace(/<[^>]*>/g, ''); - const sum = (...arr) => [...arr].reduce((acc, val) => acc + val, 0); - const sumBy = (arr, fn) => - arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0); - const sumPower = (end, power = 2, start = 1) => - Array(end + 1 - start) - .fill(0) - .map((x, i) => (i + start) ** power) - .reduce((a, b) => a + b, 0); - const symmetricDifference = (a, b) => { - const sA = new Set(a), - sB = new Set(b); - return [...a.filter(x => !sB.has(x)), ...b.filter(x => !sA.has(x))]; - }; - const symmetricDifferenceBy = (a, b, fn) => { - const sA = new Set(a.map(v => fn(v))), - sB = new Set(b.map(v => fn(v))); - return [...a.filter(x => !sB.has(fn(x))), ...b.filter(x => !sA.has(fn(x)))]; - }; - const symmetricDifferenceWith = (arr, val, comp) => [ - ...arr.filter(a => val.findIndex(b => comp(a, b)) === -1), - ...val.filter(a => arr.findIndex(b => comp(a, b)) === -1) - ]; - const tail = arr => (arr.length > 1 ? arr.slice(1) : arr); - const take = (arr, n = 1) => arr.slice(0, n); - const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length); - const takeRightWhile = (arr, func) => - arr.reduceRight((acc, el) => (func(el) ? acc : [el, ...acc]), []); - const takeWhile = (arr, func) => { - for (const [i, val] of arr.entries()) if (func(val)) return arr.slice(0, i); - return arr; - }; - const throttle = (fn, wait) => { - let inThrottle, lastFn, lastTime; - return function() { - const context = this, - args = arguments; - if (!inThrottle) { - fn.apply(context, args); - lastTime = Date.now(); - inThrottle = true; - } else { - clearTimeout(lastFn); - lastFn = setTimeout(function() { - if (Date.now() - lastTime >= wait) { - fn.apply(context, args); - lastTime = Date.now(); - } - }, Math.max(wait - (Date.now() - lastTime), 0)); - } - }; - }; - const times = (n, fn, context = undefined) => { - let i = 0; - while (fn.call(context, i) !== false && ++i < n) {} - }; - const timeTaken = callback => { - console.time('timeTaken'); - const r = callback(); - console.timeEnd('timeTaken'); - return r; - }; - const toCamelCase = str => { - let s = - str && - str - .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) - .map(x => x.slice(0, 1).toUpperCase() + x.slice(1).toLowerCase()) - .join(''); - return s.slice(0, 1).toLowerCase() + s.slice(1); - }; - const toCurrency = (n, curr, LanguageFormat = undefined) => - Intl.NumberFormat(LanguageFormat, { style: 'currency', currency: curr }).format(n); - const toDecimalMark = num => num.toLocaleString('en-US'); - const toggleClass = (el, className) => el.classList.toggle(className); - const toHash = (object, key) => - Array.prototype.reduce.call( - object, - (acc, data, index) => ((acc[!key ? index : data[key]] = data), acc), - {} - ); - const toKebabCase = str => - str && - str - .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) - .map(x => x.toLowerCase()) - .join('-'); - const tomorrow = (long = false) => { - let t = new Date(); - t.setDate(t.getDate() + 1); - const ret = `${t.getFullYear()}-${String(t.getMonth() + 1).padStart(2, '0')}-${String( - t.getDate() - ).padStart(2, '0')}`; - return !long ? ret : `${ret}T00:00:00`; - }; - const toOrdinalSuffix = num => { - const int = parseInt(num), - digits = [int % 10, int % 100], - ordinals = ['st', 'nd', 'rd', 'th'], - oPattern = [1, 2, 3, 4], - tPattern = [11, 12, 13, 14, 15, 16, 17, 18, 19]; - return oPattern.includes(digits[0]) && !tPattern.includes(digits[1]) - ? int + ordinals[digits[0] - 1] - : int + ordinals[3]; - }; - const toSafeInteger = num => - Math.round(Math.max(Math.min(num, Number.MAX_SAFE_INTEGER), Number.MIN_SAFE_INTEGER)); - const toSnakeCase = str => - str && - str - .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) - .map(x => x.toLowerCase()) - .join('_'); - const transform = (obj, fn, acc) => Object.keys(obj).reduce((a, k) => fn(a, obj[k], k, obj), acc); - const triggerEvent = (el, eventType, detail) => - el.dispatchEvent(new CustomEvent(eventType, { detail })); - const truncateString = (str, num) => - str.length > num ? str.slice(0, num > 3 ? num - 3 : num) + '...' : str; - const truthCheckCollection = (collection, pre) => collection.every(obj => obj[pre]); - const unary = fn => val => fn(val); - const uncurry = (fn, n = 1) => (...args) => { - const next = acc => args => args.reduce((x, y) => x(y), acc); - if (n > args.length) throw new RangeError('Arguments too few!'); - return next(fn)(args.slice(0, n)); - }; - const unescapeHTML = str => - str.replace( - /&|<|>|'|"/g, - tag => - ({ - '&': '&', - '<': '<', - '>': '>', - ''': "'", - '"': '"' - }[tag] || tag) - ); - const unflattenObject = obj => - Object.keys(obj).reduce((acc, k) => { - if (k.indexOf('.') !== -1) { - const keys = k.split('.'); - Object.assign( - acc, - JSON.parse( - '{' + - keys.map((v, i) => (i !== keys.length - 1 ? `"${v}":{` : `"${v}":`)).join('') + - obj[k] + - '}'.repeat(keys.length) - ) - ); - } else acc[k] = obj[k]; - return acc; - }, {}); - const unfold = (fn, seed) => { - let result = [], - val = [null, seed]; - while ((val = fn(val[1]))) result.push(val[0]); - return result; - }; - const union = (a, b) => Array.from(new Set([...a, ...b])); - const unionBy = (a, b, fn) => { - const s = new Set(a.map(fn)); - return Array.from(new Set([...a, ...b.filter(x => !s.has(fn(x)))])); - }; - const unionWith = (a, b, comp) => - Array.from(new Set([...a, ...b.filter(x => a.findIndex(y => comp(x, y)) === -1)])); - const uniqueElements = arr => [...new Set(arr)]; - const uniqueElementsBy = (arr, fn) => - arr.reduce((acc, v) => { - if (!acc.some(x => fn(v, x))) acc.push(v); - return acc; - }, []); - const uniqueElementsByRight = (arr, fn) => - arr.reduceRight((acc, v) => { - if (!acc.some(x => fn(v, x))) acc.push(v); - return acc; - }, []); - const uniqueSymmetricDifference = (a, b) => [ - ...new Set([...a.filter(v => !b.includes(v)), ...b.filter(v => !a.includes(v))]) - ]; - const untildify = str => str.replace(/^~($|\/|\\)/, `${require('os').homedir()}$1`); - const unzip = arr => - arr.reduce( - (acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc), - Array.from({ - length: Math.max(...arr.map(x => x.length)) - }).map(x => []) - ); - const unzipWith = (arr, fn) => - arr - .reduce( - (acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc), - Array.from({ - length: Math.max(...arr.map(x => x.length)) - }).map(x => []) - ) - .map(val => fn(...val)); - const URLJoin = (...args) => - args - .join('/') - .replace(/[\/]+/g, '/') - .replace(/^(.+):\//, '$1://') - .replace(/^file:/, 'file:/') - .replace(/\/(\?|&|#[^!])/g, '$1') - .replace(/\?/g, '&') - .replace('&', '?'); - const UUIDGeneratorBrowser = () => - ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => - (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16) - ); - - const UUIDGeneratorNode = () => - ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => - (c ^ (crypto.randomBytes(1)[0] & (15 >> (c / 4)))).toString(16) - ); - const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n; - const when = (pred, whenTrue) => x => (pred(x) ? whenTrue(x) : x); - const without = (arr, ...args) => arr.filter(v => !args.includes(v)); - const words = (str, pattern = /[^a-zA-Z-]+/) => str.split(pattern).filter(Boolean); - const xProd = (a, b) => a.reduce((acc, x) => acc.concat(b.map(y => [x, y])), []); - const yesNo = (val, def = false) => - /^(y|yes)$/i.test(val) ? true : /^(n|no)$/i.test(val) ? false : def; - const zip = (...arrays) => { - const maxLength = Math.max(...arrays.map(x => x.length)); - return Array.from({ length: maxLength }).map((_, i) => { - return Array.from({ length: arrays.length }, (_, k) => arrays[k][i]); - }); - }; - const zipObject = (props, values) => - props.reduce((obj, prop, index) => ((obj[prop] = values[index]), obj), {}); - const zipWith = (...array) => { - const fn = typeof array[array.length - 1] === 'function' ? array.pop() : undefined; - return Array.from( - { length: Math.max(...array.map(a => a.length)) }, - (_, i) => (fn ? fn(...array.map(a => a[i])) : array.map(a => a[i])) - ); - }; + const stableSort = (arr, compare) => + arr + .map((item, index) => ({ item, index })) + .sort((a, b) => compare(a.item, b.item) || a.index - b.index) + .map(({ item }) => item); + const standardDeviation = (arr, usePopulation = false) => { + const mean = arr.reduce((acc, val) => acc + val, 0) / arr.length; + return Math.sqrt( + arr.reduce((acc, val) => acc.concat((val - mean) ** 2), []).reduce((acc, val) => acc + val, 0) / + (arr.length - (usePopulation ? 0 : 1)) + ); + }; + const stringPermutations = str => { + if (str.length <= 2) return str.length === 2 ? [str, str[1] + str[0]] : [str]; + return str + .split('') + .reduce( + (acc, letter, i) => + acc.concat(stringPermutations(str.slice(0, i) + str.slice(i + 1)).map(val => letter + val)), + [] + ); + }; + const stripHTMLTags = str => str.replace(/<[^>]*>/g, ''); + const sum = (...arr) => [...arr].reduce((acc, val) => acc + val, 0); + const sumBy = (arr, fn) => + arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0); + const sumPower = (end, power = 2, start = 1) => + Array(end + 1 - start) + .fill(0) + .map((x, i) => (i + start) ** power) + .reduce((a, b) => a + b, 0); + const symmetricDifference = (a, b) => { + const sA = new Set(a), + sB = new Set(b); + return [...a.filter(x => !sB.has(x)), ...b.filter(x => !sA.has(x))]; + }; + const symmetricDifferenceBy = (a, b, fn) => { + const sA = new Set(a.map(v => fn(v))), + sB = new Set(b.map(v => fn(v))); + return [...a.filter(x => !sB.has(fn(x))), ...b.filter(x => !sA.has(fn(x)))]; + }; + const symmetricDifferenceWith = (arr, val, comp) => [ + ...arr.filter(a => val.findIndex(b => comp(a, b)) === -1), + ...val.filter(a => arr.findIndex(b => comp(a, b)) === -1) + ]; + const tail = arr => (arr.length > 1 ? arr.slice(1) : arr); + const take = (arr, n = 1) => arr.slice(0, n); + const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length); + const takeRightWhile = (arr, func) => + arr.reduceRight((acc, el) => (func(el) ? acc : [el, ...acc]), []); + const takeWhile = (arr, func) => { + for (const [i, val] of arr.entries()) if (func(val)) return arr.slice(0, i); + return arr; + }; + const throttle = (fn, wait) => { + let inThrottle, lastFn, lastTime; + return function() { + const context = this, + args = arguments; + if (!inThrottle) { + fn.apply(context, args); + lastTime = Date.now(); + inThrottle = true; + } else { + clearTimeout(lastFn); + lastFn = setTimeout(function() { + if (Date.now() - lastTime >= wait) { + fn.apply(context, args); + lastTime = Date.now(); + } + }, Math.max(wait - (Date.now() - lastTime), 0)); + } + }; + }; + const timeTaken = callback => { + console.time('timeTaken'); + const r = callback(); + console.timeEnd('timeTaken'); + return r; + }; + const times = (n, fn, context = undefined) => { + let i = 0; + while (fn.call(context, i) !== false && ++i < n) {} + }; + const toCamelCase = str => { + let s = + str && + str + .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) + .map(x => x.slice(0, 1).toUpperCase() + x.slice(1).toLowerCase()) + .join(''); + return s.slice(0, 1).toLowerCase() + s.slice(1); + }; + const toCurrency = (n, curr, LanguageFormat = undefined) => + Intl.NumberFormat(LanguageFormat, { style: 'currency', currency: curr }).format(n); + const toDecimalMark = num => num.toLocaleString('en-US'); + const toHash = (object, key) => + Array.prototype.reduce.call( + object, + (acc, data, index) => ((acc[!key ? index : data[key]] = data), acc), + {} + ); + const toKebabCase = str => + str && + str + .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) + .map(x => x.toLowerCase()) + .join('-'); + const toOrdinalSuffix = num => { + const int = parseInt(num), + digits = [int % 10, int % 100], + ordinals = ['st', 'nd', 'rd', 'th'], + oPattern = [1, 2, 3, 4], + tPattern = [11, 12, 13, 14, 15, 16, 17, 18, 19]; + return oPattern.includes(digits[0]) && !tPattern.includes(digits[1]) + ? int + ordinals[digits[0] - 1] + : int + ordinals[3]; + }; + const toSafeInteger = num => + Math.round(Math.max(Math.min(num, Number.MAX_SAFE_INTEGER), Number.MIN_SAFE_INTEGER)); + const toSnakeCase = str => + str && + str + .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) + .map(x => x.toLowerCase()) + .join('_'); + const toggleClass = (el, className) => el.classList.toggle(className); + const tomorrow = (long = false) => { + let t = new Date(); + t.setDate(t.getDate() + 1); + const ret = `${t.getFullYear()}-${String(t.getMonth() + 1).padStart(2, '0')}-${String( + t.getDate() + ).padStart(2, '0')}`; + return !long ? ret : `${ret}T00:00:00`; + }; + const transform = (obj, fn, acc) => Object.keys(obj).reduce((a, k) => fn(a, obj[k], k, obj), acc); + const triggerEvent = (el, eventType, detail) => + el.dispatchEvent(new CustomEvent(eventType, { detail })); + const truncateString = (str, num) => + str.length > num ? str.slice(0, num > 3 ? num - 3 : num) + '...' : str; + const truthCheckCollection = (collection, pre) => collection.every(obj => obj[pre]); + const unary = fn => val => fn(val); + const uncurry = (fn, n = 1) => (...args) => { + const next = acc => args => args.reduce((x, y) => x(y), acc); + if (n > args.length) throw new RangeError('Arguments too few!'); + return next(fn)(args.slice(0, n)); + }; + const unescapeHTML = str => + str.replace( + /&|<|>|'|"/g, + tag => + ({ + '&': '&', + '<': '<', + '>': '>', + ''': "'", + '"': '"' + }[tag] || tag) + ); + const unflattenObject = obj => + Object.keys(obj).reduce((acc, k) => { + if (k.indexOf('.') !== -1) { + const keys = k.split('.'); + Object.assign( + acc, + JSON.parse( + '{' + + keys.map((v, i) => (i !== keys.length - 1 ? `"${v}":{` : `"${v}":`)).join('') + + obj[k] + + '}'.repeat(keys.length) + ) + ); + } else acc[k] = obj[k]; + return acc; + }, {}); + const unfold = (fn, seed) => { + let result = [], + val = [null, seed]; + while ((val = fn(val[1]))) result.push(val[0]); + return result; + }; + const union = (a, b) => Array.from(new Set([...a, ...b])); + const unionBy = (a, b, fn) => { + const s = new Set(a.map(fn)); + return Array.from(new Set([...a, ...b.filter(x => !s.has(fn(x)))])); + }; + const unionWith = (a, b, comp) => + Array.from(new Set([...a, ...b.filter(x => a.findIndex(y => comp(x, y)) === -1)])); + const uniqueElements = arr => [...new Set(arr)]; + const uniqueElementsBy = (arr, fn) => + arr.reduce((acc, v) => { + if (!acc.some(x => fn(v, x))) acc.push(v); + return acc; + }, []); + const uniqueElementsByRight = (arr, fn) => + arr.reduceRight((acc, v) => { + if (!acc.some(x => fn(v, x))) acc.push(v); + return acc; + }, []); + const uniqueSymmetricDifference = (a, b) => [ + ...new Set([...a.filter(v => !b.includes(v)), ...b.filter(v => !a.includes(v))]) + ]; + const untildify = str => str.replace(/^~($|\/|\\)/, `${require('os').homedir()}$1`); + const unzip = arr => + arr.reduce( + (acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc), + Array.from({ + length: Math.max(...arr.map(x => x.length)) + }).map(x => []) + ); + const unzipWith = (arr, fn) => + arr + .reduce( + (acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc), + Array.from({ + length: Math.max(...arr.map(x => x.length)) + }).map(x => []) + ) + .map(val => fn(...val)); + const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n; + const when = (pred, whenTrue) => x => (pred(x) ? whenTrue(x) : x); + const without = (arr, ...args) => arr.filter(v => !args.includes(v)); + const words = (str, pattern = /[^a-zA-Z-]+/) => str.split(pattern).filter(Boolean); + const xProd = (a, b) => a.reduce((acc, x) => acc.concat(b.map(y => [x, y])), []); + const yesNo = (val, def = false) => + /^(y|yes)$/i.test(val) ? true : /^(n|no)$/i.test(val) ? false : def; + const zip = (...arrays) => { + const maxLength = Math.max(...arrays.map(x => x.length)); + return Array.from({ length: maxLength }).map((_, i) => { + return Array.from({ length: arrays.length }, (_, k) => arrays[k][i]); + }); + }; + const zipObject = (props, values) => + props.reduce((obj, prop, index) => ((obj[prop] = values[index]), obj), {}); + const zipWith = (...array) => { + const fn = typeof array[array.length - 1] === 'function' ? array.pop() : undefined; + return Array.from( + { length: Math.max(...array.map(a => a.length)) }, + (_, i) => (fn ? fn(...array.map(a => a[i])) : array.map(a => a[i])) + ); + }; - module.exports = {all,allEqual,any,approximatelyEqual,arrayToCSV,arrayToHtmlList,ary,atob,attempt,average,averageBy,bifurcate,bifurcateBy,bind,bindAll,bindKey,binomialCoefficient,bottomVisible,btoa,byteSize,call,capitalize,capitalizeEveryWord,castArray,chainAsync,chunk,clampNumber,cloneRegExp,coalesce,coalesceFactory,collectInto,colorize,compact,compose,composeRight,converge,copyToClipboard,countBy,counter,countOccurrences,createElement,createEventHub,CSVToArray,CSVToJSON,currentURL,curry,dayOfYear,debounce,decapitalize,deepClone,deepFlatten,deepFreeze,defaults,defer,degreesToRads,delay,detectDeviceType,difference,differenceBy,differenceWith,dig,digitize,distance,drop,dropRight,dropRightWhile,dropWhile,elementContains,elementIsVisibleInViewport,elo,equals,escapeHTML,escapeRegExp,everyNth,extendHex,factorial,fibonacci,filterNonUnique,filterNonUniqueBy,findKey,findLast,findLastIndex,findLastKey,flatten,flattenObject,flip,forEachRight,formatDuration,forOwn,forOwnRight,fromCamelCase,functionName,functions,gcd,geometricProgression,get,getColonTimeFromDate,getDaysDiffBetweenDates,getImages,getMeridiemSuffixOfInteger,getScrollPosition,getStyle,getType,getURLParameters,groupBy,hammingDistance,hasClass,hasFlags,hashBrowser,hashNode,head,hexToRGB,hide,httpGet,httpPost,httpsRedirect,hz,indentString,indexOfAll,initial,initialize2DArray,initializeArrayWithRange,initializeArrayWithRangeRight,initializeArrayWithValues,initializeNDArray,inRange,insertAfter,insertBefore,intersection,intersectionBy,intersectionWith,invertKeyValues,is,isAbsoluteURL,isAfterDate,isAnagram,isArrayLike,isBeforeDate,isBoolean,isBrowser,isBrowserTabFocused,isDivisible,isDuplexStream,isEmpty,isEven,isFunction,isLowerCase,isNil,isNull,isNumber,isObject,isObjectLike,isPlainObject,isPrime,isPrimitive,isPromiseLike,isReadableStream,isSameDate,isSorted,isStream,isString,isSymbol,isTravisCI,isUndefined,isUpperCase,isValidJSON,isWritableStream,join,JSONtoCSV,JSONToFile,last,lcm,longestItem,lowercaseKeys,luhnCheck,mapKeys,mapObject,mapString,mapValues,mask,matches,matchesWith,maxBy,maxDate,maxN,median,memoize,merge,minBy,minDate,minN,mostPerformant,negate,nest,nodeListToArray,none,nthArg,nthElement,objectFromPairs,objectToPairs,observeMutations,off,offset,omit,omitBy,on,once,onUserInputChange,orderBy,over,overArgs,pad,palindrome,parseCookie,partial,partialRight,partition,percentile,permutations,pick,pickBy,pipeAsyncFunctions,pipeFunctions,pluralize,powerset,prefix,prettyBytes,primes,promisify,pull,pullAtIndex,pullAtValue,pullBy,radsToDegrees,randomHexColorCode,randomIntArrayInRange,randomIntegerInRange,randomNumberInRange,readFileLines,rearg,recordAnimationFrames,redirect,reducedFilter,reduceSuccessive,reduceWhich,reject,remove,removeNonASCII,renameKeys,reverseString,RGBToHex,round,runAsync,runPromisesInSeries,sample,sampleSize,scrollToTop,sdbm,serializeCookie,setStyle,shallowClone,shank,show,shuffle,similarity,size,sleep,smoothScroll,sortCharactersInString,sortedIndex,sortedIndexBy,sortedLastIndex,sortedLastIndexBy,splitLines,spreadOver,stableSort,standardDeviation,stringPermutations,stripHTMLTags,sum,sumBy,sumPower,symmetricDifference,symmetricDifferenceBy,symmetricDifferenceWith,tail,take,takeRight,takeRightWhile,takeWhile,throttle,times,timeTaken,toCamelCase,toCurrency,toDecimalMark,toggleClass,toHash,toKebabCase,tomorrow,toOrdinalSuffix,toSafeInteger,toSnakeCase,transform,triggerEvent,truncateString,truthCheckCollection,unary,uncurry,unescapeHTML,unflattenObject,unfold,union,unionBy,unionWith,uniqueElements,uniqueElementsBy,uniqueElementsByRight,uniqueSymmetricDifference,untildify,unzip,unzipWith,URLJoin,UUIDGeneratorBrowser,UUIDGeneratorNode,validateNumber,when,without,words,xProd,yesNo,zip,zipObject,zipWith}; + module.exports = {CSVToArray,CSVToJSON,JSONToFile,JSONtoCSV,RGBToHex,URLJoin,UUIDGeneratorBrowser,UUIDGeneratorNode,all,allEqual,any,approximatelyEqual,arrayToCSV,arrayToHtmlList,ary,atob,attempt,average,averageBy,bifurcate,bifurcateBy,bind,bindAll,bindKey,binomialCoefficient,bottomVisible,btoa,byteSize,call,capitalize,capitalizeEveryWord,castArray,chainAsync,chunk,clampNumber,cloneRegExp,coalesce,coalesceFactory,collectInto,colorize,compact,compose,composeRight,converge,copyToClipboard,countBy,countOccurrences,counter,createElement,createEventHub,currentURL,curry,dayOfYear,debounce,decapitalize,deepClone,deepFlatten,deepFreeze,defaults,defer,degreesToRads,delay,detectDeviceType,difference,differenceBy,differenceWith,dig,digitize,distance,drop,dropRight,dropRightWhile,dropWhile,elementContains,elementIsVisibleInViewport,elo,equals,escapeHTML,escapeRegExp,everyNth,extendHex,factorial,fibonacci,filterNonUnique,filterNonUniqueBy,findKey,findLast,findLastIndex,findLastKey,flatten,flattenObject,flip,forEachRight,forOwn,forOwnRight,formatDuration,fromCamelCase,functionName,functions,gcd,geometricProgression,get,getColonTimeFromDate,getDaysDiffBetweenDates,getImages,getMeridiemSuffixOfInteger,getScrollPosition,getStyle,getType,getURLParameters,groupBy,hammingDistance,hasClass,hasFlags,hashBrowser,hashNode,head,hexToRGB,hide,httpGet,httpPost,httpsRedirect,hz,inRange,indentString,indexOfAll,initial,initialize2DArray,initializeArrayWithRange,initializeArrayWithRangeRight,initializeArrayWithValues,initializeNDArray,insertAfter,insertBefore,intersection,intersectionBy,intersectionWith,invertKeyValues,is,isAbsoluteURL,isAfterDate,isAnagram,isArrayLike,isBeforeDate,isBoolean,isBrowser,isBrowserTabFocused,isDivisible,isDuplexStream,isEmpty,isEven,isFunction,isLowerCase,isNil,isNull,isNumber,isObject,isObjectLike,isPlainObject,isPrime,isPrimitive,isPromiseLike,isReadableStream,isSameDate,isSorted,isStream,isString,isSymbol,isTravisCI,isUndefined,isUpperCase,isValidJSON,isWritableStream,join,last,lcm,longestItem,lowercaseKeys,luhnCheck,mapKeys,mapObject,mapString,mapValues,mask,matches,matchesWith,maxBy,maxDate,maxN,median,memoize,merge,minBy,minDate,minN,mostPerformant,negate,nest,nodeListToArray,none,nthArg,nthElement,objectFromPairs,objectToPairs,observeMutations,off,offset,omit,omitBy,on,onUserInputChange,once,orderBy,over,overArgs,pad,palindrome,parseCookie,partial,partialRight,partition,percentile,permutations,pick,pickBy,pipeAsyncFunctions,pipeFunctions,pluralize,powerset,prefix,prettyBytes,primes,promisify,pull,pullAtIndex,pullAtValue,pullBy,radsToDegrees,randomHexColorCode,randomIntArrayInRange,randomIntegerInRange,randomNumberInRange,readFileLines,rearg,recordAnimationFrames,redirect,reduceSuccessive,reduceWhich,reducedFilter,reject,remove,removeNonASCII,renameKeys,reverseString,round,runAsync,runPromisesInSeries,sample,sampleSize,scrollToTop,sdbm,serializeCookie,setStyle,shallowClone,shank,show,shuffle,similarity,size,sleep,smoothScroll,sortCharactersInString,sortedIndex,sortedIndexBy,sortedLastIndex,sortedLastIndexBy,splitLines,spreadOver,stableSort,standardDeviation,stringPermutations,stripHTMLTags,sum,sumBy,sumPower,symmetricDifference,symmetricDifferenceBy,symmetricDifferenceWith,tail,take,takeRight,takeRightWhile,takeWhile,throttle,timeTaken,times,toCamelCase,toCurrency,toDecimalMark,toHash,toKebabCase,toOrdinalSuffix,toSafeInteger,toSnakeCase,toggleClass,tomorrow,transform,triggerEvent,truncateString,truthCheckCollection,unary,uncurry,unescapeHTML,unflattenObject,unfold,union,unionBy,unionWith,uniqueElements,uniqueElementsBy,uniqueElementsByRight,uniqueSymmetricDifference,untildify,unzip,unzipWith,validateNumber,when,without,words,xProd,yesNo,zip,zipObject,zipWith}; }))); diff --git a/snippet_data/snippetsArchive.json b/snippet_data/snippetsArchive.json index 9ee946ccd..42ec6f611 100644 --- a/snippet_data/snippetsArchive.json +++ b/snippet_data/snippetsArchive.json @@ -366,10 +366,12 @@ "codeBlocks": [ "const JSONToDate = arr => {\n const dt = new Date(parseInt(arr.toString().substr(6)));\n return `${dt.getDate()}/${dt.getMonth() + 1}/${dt.getFullYear()}`;\n};", "JSONToDate(/Date(1489525200000)/); // \"14/3/2017\"", - "const speechSynthesis = message => {\n const msg = new SpeechSynthesisUtterance(message);\n msg.voice = window.speechSynthesis.getVoices()[0];\n window.speechSynthesis.speak(msg);\n};", - "speechSynthesis('Hello, World'); // // plays the message", + "const squareSum = (...args) => args.reduce((squareSum, number) => squareSum + Math.pow(number, 2), 0);", + "squareSum(1, 2, 2); // 9", "const binarySearch = (arr, val, start = 0, end = arr.length - 1) => {\n if (start > end) return -1;\n const mid = Math.floor((start + end) / 2);\n if (arr[mid] > val) return binarySearch(arr, val, start, mid - 1);\n if (arr[mid] < val) return binarySearch(arr, val, mid + 1, end);\n return mid;\n};", "binarySearch([1, 4, 6, 7, 12, 13, 15, 18, 19, 20, 22, 24], 6); // 2\nbinarySearch([1, 4, 6, 7, 12, 13, 15, 18, 19, 20, 22, 24], 21); // -1", + "const celsiusToFahrenheit = degrees => 1.8 * degrees + 32;", + "celsiusToFahrenheit(33) // 91.4", "const cleanObj = (obj, keysToKeep = [], childIndicator) => {\n Object.keys(obj).forEach(key => {\n if (key === childIndicator) {\n cleanObj(obj[key], keysToKeep, childIndicator);\n } else if (!keysToKeep.includes(key)) {\n delete obj[key];\n }\n });\n return obj;\n};", "const testObj = { a: 1, b: 2, children: { a: 1, b: 2 } };\ncleanObj(testObj, ['a'], 'children'); // { a: 1, children : { a: 1}}", "const collatz = n => (n % 2 === 0 ? n / 2 : 3 * n + 1);", @@ -378,22 +380,28 @@ "countVowels('foobar'); // 3\ncountVowels('gym'); // 0", "const factors = (num, primes = false) => {\n const isPrime = num => {\n const boundary = Math.floor(Math.sqrt(num));\n for (var i = 2; i <= boundary; i++) if (num % i === 0) return false;\n return num >= 2;\n };\n const isNeg = num < 0;\n num = isNeg ? -num : num;\n let array = Array.from({ length: num - 1 })\n .map((val, i) => (num % (i + 2) === 0 ? i + 2 : false))\n .filter(val => val);\n if (isNeg)\n array = array.reduce((acc, val) => {\n acc.push(val);\n acc.push(-val);\n return acc;\n }, []);\n return primes ? array.filter(isPrime) : array;\n};", "factors(12); // [2,3,4,6,12]\nfactors(12, true); // [2,3]\nfactors(-12); // [2, -2, 3, -3, 4, -4, 6, -6, 12, -12]\nfactors(-12, true); // [2,3]", + "const fahrenheitToCelsius = degrees => (degrees - 32) * 5/9;", + "fahrenheitToCelsius(32); // 0", "const fibonacciCountUntilNum = num =>\n Math.ceil(Math.log(num * Math.sqrt(5) + 1 / 2) / Math.log((Math.sqrt(5) + 1) / 2));", "fibonacciCountUntilNum(10); // 7", "const fibonacciUntilNum = num => {\n let n = Math.ceil(Math.log(num * Math.sqrt(5) + 1 / 2) / Math.log((Math.sqrt(5) + 1) / 2));\n return Array.from({ length: n }).reduce(\n (acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i),\n []\n );\n};", "fibonacciUntilNum(10); // [ 0, 1, 1, 2, 3, 5, 8 ]", "const heronArea = (side_a, side_b, side_c) => {\n const p = (side_a + side_b + side_c) / 2\n return Math.sqrt(p * (p-side_a) * (p-side_b) * (p-side_c))\n };", "heronArea(3, 4, 5); // 6", - "const httpDelete = (url, callback, err = console.error) => {\n const request = new XMLHttpRequest();\n request.open('DELETE', url, true);\n request.onload = () => callback(request);\n request.onerror = () => err(request);\n request.send();\n};", - "httpDelete('https://website.com/users/123', request => {\n console.log(request.responseText);\n}); // 'Deletes a user from the database'", + "const howManyTimes = (num, divisor) => {\n if (divisor === 1 || divisor === -1) return Infinity;\n if (divisor === 0) return 0;\n let i = 0;\n while (Number.isInteger(num / divisor)) {\n i++;\n num = num / divisor;\n }\n return i;\n};", + "howManyTimes(100, 2); // 2\nhowManyTimes(100, 2.5); // 2\nhowManyTimes(100, 0); // 0\nhowManyTimes(100, -1); // Infinity", "const httpPut = (url, data, callback, err = console.error) => {\n const request = new XMLHttpRequest();\n request.open(\"PUT\", url, true);\n request.setRequestHeader('Content-type','application/json; charset=utf-8');\n request.onload = () => callback(request);\n request.onerror = () => err(request);\n request.send(data);\n};", "const password = \"fooBaz\";\nconst data = JSON.stringify(password);\nhttpPut('https://website.com/users/123', data, request => {\n console.log(request.responseText);\n}); // 'Updates a user's password in database'", "const isArmstrongNumber = digits =>\n (arr => arr.reduce((a, d) => a + parseInt(d) ** arr.length, 0) == digits)(\n (digits + '').split('')\n );", "isArmstrongNumber(1634); // true\nisArmstrongNumber(56); // false", "const isSimilar = (pattern, str) =>\n [...str].reduce(\n (matchIndex, char) =>\n char.toLowerCase() === (pattern[matchIndex] || '').toLowerCase()\n ? matchIndex + 1\n : matchIndex,\n 0\n ) === pattern.length;", "isSimilar('rt','Rohit'); // true\nisSimilar('tr','Rohit'); // false", + "const kmphToMph = (kmph) => 0.621371192 * kmph;", + "kmphToMph(10); // 16.09344000614692\nkmphToMph(345.4); // 138.24264965280207", "``` js\nconst levenshteinDistance = (string1, string2) => {\n if (string1.length === 0) return string2.length;\n if (string2.length === 0) return string1.length;\n let matrix = Array(string2.length + 1)\n .fill(0)\n .map((x, i) => [i]);\n matrix[0] = Array(string1.length + 1)\n .fill(0)\n .map((x, i) => i);\n for (let i = 1; i <= string2.length; i++) {\n for (let j = 1; j <= string1.length; j++) {\n if (string2[i - 1] === string1[j - 1]) {\n matrix[i][j] = matrix[i - 1][j - 1];\n } else {\n matrix[i][j] = Math.min(\n matrix[i - 1][j - 1] + 1,\n matrix[i][j - 1] + 1,\n matrix[i - 1][j] + 1\n );\n }\n }\n }\n return matrix[string2.length][string1.length];\n};\n```", "levenshteinDistance('30-seconds-of-code','30-seconds-of-python-code'); // 7\nconst compareStrings = (string1,string2) => (100 - levenshteinDistance(string1,string2) / Math.max(string1.length,string2.length));\ncompareStrings('30-seconds-of-code', '30-seconds-of-python-code'); // 99.72 (%)", + "const mphToKmph = (mph) => 1.6093440006146922 * mph;", + "mphToKmph(10); // 16.09344000614692\nmphToKmph(85.9); // 138.24264965280207", "const pipeLog = data => console.log(data) || data;", "pipeLog(1); // logs `1` and returns `1`", "const quickSort = ([n, ...nums], desc) =>\n isNaN(n)\n ? []\n : [\n ...quickSort(nums.filter(v => (desc ? v > n : v <= n)), desc),\n n,\n ...quickSort(nums.filter(v => (!desc ? v > n : v <= n)), desc)\n ];", @@ -402,14 +410,16 @@ "removeVowels(\"foobAr\"); // \"fbr\"\nremoveVowels(\"foobAr\",\"*\"); // \"f**b*r\"", "const solveRPN = rpn => {\n const OPERATORS = {\n '*': (a, b) => a * b,\n '+': (a, b) => a + b,\n '-': (a, b) => a - b,\n '/': (a, b) => a / b,\n '**': (a, b) => a ** b\n };\n const [stack, solve] = [\n [],\n rpn\n .replace(/\\^/g, '**')\n .split(/\\s+/g)\n .filter(el => !/\\s+/.test(el) && el !== '')\n ];\n solve.forEach(symbol => {\n if (!isNaN(parseFloat(symbol)) && isFinite(symbol)) {\n stack.push(symbol);\n } else if (Object.keys(OPERATORS).includes(symbol)) {\n const [a, b] = [stack.pop(), stack.pop()];\n stack.push(OPERATORS[symbol](parseFloat(b), parseFloat(a)));\n } else {\n throw `${symbol} is not a recognized symbol`;\n }\n });\n if (stack.length === 1) return stack.pop();\n else throw `${rpn} is not a proper RPN. Please check it and try again`;\n};", "solveRPN('15 7 1 1 + - / 3 * 2 1 1 + + -'); // 5\nsolveRPN('2 3 ^'); // 8", - "const howManyTimes = (num, divisor) => {\n if (divisor === 1 || divisor === -1) return Infinity;\n if (divisor === 0) return 0;\n let i = 0;\n while (Number.isInteger(num / divisor)) {\n i++;\n num = num / divisor;\n }\n return i;\n};", - "howManyTimes(100, 2); // 2\nhowManyTimes(100, 2.5); // 2\nhowManyTimes(100, 0); // 0\nhowManyTimes(100, -1); // Infinity" + "const speechSynthesis = message => {\n const msg = new SpeechSynthesisUtterance(message);\n msg.voice = window.speechSynthesis.getVoices()[0];\n window.speechSynthesis.speak(msg);\n};", + "speechSynthesis('Hello, World'); // // plays the message", + "const httpDelete = (url, callback, err = console.error) => {\n const request = new XMLHttpRequest();\n request.open('DELETE', url, true);\n request.onload = () => callback(request);\n request.onerror = () => err(request);\n request.send();\n};", + "httpDelete('https://website.com/users/123', request => {\n console.log(request.responseText);\n}); // 'Deletes a user from the database'" ], "tags": [] }, "meta": { "archived": true, - "hash": "50abe1eb4fadd6d7d8ab5c5dc027f0bf34e6c391b6da1367ddee907abd741a30" + "hash": "cd05a83026c948903673c6d9482c7c1a1c4da1d53e875c60cae3719d7959f79e" } }, { diff --git a/test/testlog b/test/testlog index 8b3507e5a..21afa7480 100644 --- a/test/testlog +++ b/test/testlog @@ -1,9 +1,9 @@ # Starting... -# 362 test suites found. +# 359 test suites found. -# PASS test/uniqueElements/uniqueElements.test.js +# PASS test/uniqueElements.test.js ok 1 — uniqueElements is a Function ok 2 — uniqueElements([1, 2, 2, 3, 4, 4, 5]) returns [1,2,3,4,5] @@ -19,7 +19,7 @@ ok 11 — uniqueElements(true) throws an error ok 12 — uniqueElements(false) throws an error ok 13 — uniqueElements([true, 0, 1, false, false, undefined, null]) takes less than 2s to run -# PASS test/toSnakeCase/toSnakeCase.test.js +# PASS test/toSnakeCase.test.js ok 14 — toSnakeCase is a Function ok 15 — toSnakeCase('camelCase') returns camel_case @@ -32,7 +32,7 @@ ok 21 — toSnakeCase({}) throws an error ok 22 — toSnakeCase(123) throws an error ok 23 — toSnakeCase(IAmListeningToFMWhileLoadingDifferentURLOnMyBrowserAndAlsoEditingSomeXMLAndHTML) takes less than 2s to run -# PASS test/toKebabCase/toKebabCase.test.js +# PASS test/toKebabCase.test.js ok 24 — toKebabCase is a Function ok 25 — toKebabCase('camelCase') returns camel-case @@ -45,7 +45,7 @@ ok 31 — toKebabCase({}) throws an erro ok 32 — toKebabCase(123) throws an erro ok 33 — toKebabCase(IAmListeningToFMWhileLoadingDifferentURLOnMyBrowserAndAlsoEditingSomeXMLAndHTML) takes less than 2s to run -# PASS test/toCamelCase/toCamelCase.test.js +# PASS test/toCamelCase.test.js ok 34 — toCamelCase is a Function ok 35 — toCamelCase('some_database_field_name') returns someDatabaseFieldName @@ -58,7 +58,7 @@ ok 41 — toCamelCase({}) throws a error ok 42 — toCamelCase(123) throws a error ok 43 — toCamelCase(some-mixed_string with spaces_underscores-and-hyphens) takes less than 2s to run -# PASS test/is/is.test.js +# PASS test/is.test.js ok 44 — is is a Function ok 45 — Works for arrays with data @@ -78,7 +78,7 @@ ok 58 — Works for booleans - returns true for primitive ok 59 — Works for booleans - returns true when using constructor ok 60 — Works for functions -# PASS test/average/average.test.js +# PASS test/average.test.js ok 61 — average is a Function ok 62 — average(true) returns 0 @@ -93,7 +93,7 @@ ok 70 — average({ a: 123}) returns NaN ok 71 — average([undefined, 0, string]) returns NaN ok 72 — average([1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 1122, 32124, 23232]) takes less than 2s to run -# PASS test/union/union.test.js +# PASS test/union.test.js ok 73 — union is a Function ok 74 — union([1, 2, 3], [4, 3, 2]) returns [1, 2, 3, 4] @@ -108,7 +108,7 @@ ok 82 — union([], {}) throws an error ok 83 — union(undefined, null) throws an error ok 84 — union([1, 2, 3], [4, 3, 2]) takes less than 2s to run -# PASS test/validateNumber/validateNumber.test.js +# PASS test/validateNumber.test.js ok 85 — validateNumber is a Function ok 86 — validateNumber(9) returns true @@ -124,7 +124,7 @@ ok 95 — validateNumber(true) returns false ok 96 — validateNumber(null) returns false ok 97 — validateNumber(123 * asd) returns false -# PASS test/toSafeInteger/toSafeInteger.test.js +# PASS test/toSafeInteger.test.js ok 98 — toSafeInteger is a Function ok 99 — Number(toSafeInteger(3.2)) is a number @@ -139,7 +139,7 @@ ok 107 — isNaN(toSafeInteger()) is true ok 108 — toSafeInteger(Infinity) returns 9007199254740991 ok 109 — toSafeInteger(3.2) takes less than 2s to run -# PASS test/isPrimitive/isPrimitive.test.js +# PASS test/isPrimitive.test.js ok 110 — isPrimitive is a Function ok 111 — isPrimitive(null) is primitive @@ -154,7 +154,7 @@ ok 119 — isPrimitive([1, 2, 3]) is not primitive ok 120 — isPrimitive({ a: 123 }) is not primitive ok 121 — isPrimitive({ a: 123 }) takes less than 2s to run -# PASS test/zipObject/zipObject.test.js +# PASS test/zipObject.test.js ok 122 — zipObject is a Function ok 123 — zipObject([a, b, c], [1, 2]) returns {a: 1, b: 2, c: undefined} @@ -167,7 +167,7 @@ ok 129 — zipObject(null, [1]) throws an error ok 130 — zipObject('string') throws an error ok 131 — zipObject('test', 'string') throws an error -# PASS test/quickSort/quickSort.test.js +# PASS test/quickSort.test.js ok 132 — quickSort is a Function ok 133 — quickSort([5, 6, 4, 3, 1, 2]) returns [1, 2, 3, 4, 5, 6] @@ -179,7 +179,7 @@ ok 138 — quickSort(null) throws an error ok 139 — quickSort(undefined) throws an error ok 140 — quickSort([11, 1, 324, 23232, -1, 53, 2, 524, 32, 13, 156, 133, 62, 12, 4]) takes less than 2s to run -# PASS test/round/round.test.js +# PASS test/round.test.js ok 141 — round is a Function ok 142 — round(1.005, 2) returns 1.01 @@ -193,7 +193,7 @@ ok 149 — round(132, 413, 4134) returns NaN ok 150 — round({a: 132}, 413) returns NaN ok 151 — round(123.3423345345345345344, 11) takes less than 2s to run -# PASS test/yesNo/yesNo.test.js +# PASS test/yesNo.test.js ok 152 — yesNo is a Function ok 153 — yesNo(Y) returns true @@ -209,7 +209,7 @@ ok 162 — yesNo({ 2: Yes }) returns false ok 163 — yesNo([Yes, No], true) returns true ok 164 — yesNo({ 2: Yes }, true) returns true -# PASS test/isSorted/isSorted.test.js +# PASS test/isSorted.test.js ok 165 — isSorted is a Function ok 166 — Array is sorted in ascending order @@ -224,7 +224,7 @@ ok 174 — Array is empty ok 175 — Array is not sorted, direction changed in array ok 176 — Array is not sorted, direction changed in array -# PASS test/words/words.test.js +# PASS test/words.test.js ok 177 — words is a Function ok 178 — words('I love javaScript!!') returns [I, love, javaScript] @@ -237,7 +237,7 @@ ok 184 — words({}) throws an error ok 185 — words([]) throws an error ok 186 — words(1234) throws an error -# PASS test/longestItem/longestItem.test.js +# PASS test/longestItem.test.js ok 187 — longestItem is a Function ok 188 — Returns the longest object from plain values @@ -249,7 +249,7 @@ ok 193 — Returns undefined without any input ok 194 — Returns first found of all similar ok 195 — Throws TypeError if all inputs are undefined -# PASS test/without/without.test.js +# PASS test/without.test.js ok 196 — without is a Function ok 197 — without([2, 1, 2, 3], 1, 2) returns [3] @@ -262,7 +262,7 @@ ok 203 — without(undefined) throws an error ok 204 — without(123) throws an error ok 205 — without({}) throws an error -# PASS test/chunk/chunk.test.js +# PASS test/chunk.test.js ok 206 — chunk is a Function ok 207 — chunk([1, 2, 3, 4, 5], 2) returns [[1,2],[3,4],[5]] @@ -275,7 +275,7 @@ ok 213 — chunk(undefined) throws an error ok 214 — chunk(null) throws an error ok 215 — chunk(This is a string, 2) takes less than 2s to run -# PASS test/zip/zip.test.js +# PASS test/zip.test.js ok 216 — zip is a Function ok 217 — zip([a, b], [1, 2], [true, false]) returns [[a, 1, true], [b, 2, false]] @@ -287,13 +287,13 @@ ok 222 — zip([a], [1, 2], [true, false]) returns an Array ok 223 — zip(null) throws an error ok 224 — zip(undefined) throws an error -# PASS test/uniqueElementsByRight/uniqueElementsByRight.test.js +# PASS test/uniqueElementsByRight.test.js ok 225 — uniqueElementsByRight is a Function ok 226 — uniqueElementsByRight works for properties ok 227 — uniqueElementsByRight works for nested properties -# PASS test/isEmpty/isEmpty.test.js +# PASS test/isEmpty.test.js ok 228 — isEmpty is a Function ok 229 — Returns true for empty Map @@ -307,25 +307,25 @@ ok 236 — Returns false for non-empty string ok 237 — Returns true - type is not considered a collection ok 238 — Returns true - type is not considered a collection -# PASS test/uniqueElementsBy/uniqueElementsBy.test.js +# PASS test/last.test.js -ok 239 — uniqueElementsBy is a Function -ok 240 — uniqueElementsBy works for properties -ok 241 — uniqueElementsBy works for nested properties +ok 239 — last is a Function +ok 240 — last({ a: 1234}) returns undefined +ok 241 — last([1, 2, 3]) returns 3 +ok 242 — last({ 0: false}) returns undefined +ok 243 — last(String) returns g +ok 244 — last(null) throws an Error +ok 245 — last(undefined) throws an Error +ok 246 — last() throws an Error +ok 247 — last([1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 1122, 32124, 23232]) takes less than 2s to run -# PASS test/last/last.test.js +# PASS test/uniqueElementsBy.test.js -ok 242 — last is a Function -ok 243 — last({ a: 1234}) returns undefined -ok 244 — last([1, 2, 3]) returns 3 -ok 245 — last({ 0: false}) returns undefined -ok 246 — last(String) returns g -ok 247 — last(null) throws an Error -ok 248 — last(undefined) throws an Error -ok 249 — last() throws an Error -ok 250 — last([1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 1122, 32124, 23232]) takes less than 2s to run +ok 248 — uniqueElementsBy is a Function +ok 249 — uniqueElementsBy works for properties +ok 250 — uniqueElementsBy works for nested properties -# PASS test/head/head.test.js +# PASS test/head.test.js ok 251 — head is a Function ok 252 — head({ a: 1234}) returns undefined @@ -337,7 +337,7 @@ ok 257 — head(undefined) throws an Error ok 258 — head() throws an Error ok 259 — head([1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 1122, 32124, 23232]) takes less than 2s to run -# PASS test/allEqual/allEqual.test.js +# PASS test/allEqual.test.js ok 260 — allEqual is a Function ok 261 — Truthy numbers @@ -350,13 +350,13 @@ ok 267 — Falsy trues ok 268 — Falsy falses ok 269 — False when there are different types -# PASS test/filterNonUniqueBy/filterNonUniqueBy.test.js +# PASS test/filterNonUniqueBy.test.js ok 270 — filterNonUniqueBy is a Function ok 271 — filterNonUniqueBy works for properties ok 272 — filterNonUniqueBy works for nested properties -# PASS test/all/all.test.js +# PASS test/all.test.js ok 273 — all is a Function ok 274 — Returns true for arrays with no falsey values @@ -368,7 +368,7 @@ ok 279 — Returns false for arrays with empty strings ok 280 — Returns true with predicate function ok 281 — Returns false with a predicate function -# PASS test/offset/offset.test.js +# PASS test/offset.test.js ok 282 — offset is a Function ok 283 — Offset of 0 returns the same array. @@ -378,7 +378,7 @@ ok 286 — Offset greater than the length of the array returns the same array. ok 287 — Offset less than the negative length of the array returns the same array. ok 288 — Offsetting empty array returns an empty array. -# PASS test/equals/equals.test.js +# PASS test/equals.test.js ok 289 — equals is a Function ok 290 — { a: [2, {e: 3}], b: [4], c: 'foo' } is equal to { a: [2, {e: 3}], b: [4], c: 'foo' } @@ -387,541 +387,479 @@ ok 292 — { a: [2, 3], b: [4] } is not equal to { a: [2, 3], b: [6] } ok 293 — [1,2,3] is not equal to [1,2,4] ok 294 — [1, 2, 3] should be equal to { 0: 1, 1: 2, 2: 3 }) - type is different, but their enumerable properties match. -# PASS test/isWritableStream/isWritableStream.test.js +# PASS test/randomIntArrayInRange.test.js -ok 295 — isWritableStream is a Function -ok 296 — isWritableStream returns false for read streams -ok 297 — isWritableStream returns true for write streams -ok 298 — isWritableStream returns true for duplex streams -ok 299 — isWritableStream returns false for non-streams +ok 295 — randomIntArrayInRange is a Function +ok 296 — The returned array contains only integers +ok 297 — The returned array has the proper length +ok 298 — The returned array's values lie between provided lowerLimit and upperLimit (both inclusive). -# PASS test/isReadableStream/isReadableStream.test.js +# PASS test/pluralize.test.js -ok 300 — isReadableStream is a Function -ok 301 — isReadableStream returns true for read streams -ok 302 — isReadableStream returns false for write streams -ok 303 — isReadableStream returns true for duplex streams -ok 304 — isReadableStream returns false for non-streams +ok 299 — pluralize is a Function +ok 300 — Produces the plural of the word +ok 301 — Produces the singular of the word +ok 302 — Produces the plural of the word +ok 303 — Prodices the defined plural of the word +ok 304 — Works with a dictionary -# PASS test/randomIntArrayInRange/randomIntArrayInRange.test.js +# PASS test/getImages.test.js -ok 305 — randomIntArrayInRange is a Function -ok 306 — The returned array contains only integers -ok 307 — The returned array has the proper length -ok 308 — The returned array's values lie between provided lowerLimit and upperLimit (both inclusive). +ok 305 — getImages is a Function +ok 306 — getImages returns an Array +ok 307 — getImages removes duplicates from images Array -# PASS test/pluralize/pluralize.test.js +# PASS test/sampleSize.test.js -ok 309 — pluralize is a Function -ok 310 — Produces the plural of the word -ok 311 — Produces the singular of the word -ok 312 — Produces the plural of the word -ok 313 — Prodices the defined plural of the word -ok 314 — Works with a dictionary +ok 308 — sampleSize is a Function +ok 309 — Returns a single element without n specified +ok 310 — Returns a random sample of specified size from an array +ok 311 — Returns all elements in an array if n >= length +ok 312 — Returns an empty array if original array is empty +ok 313 — Returns an empty array if n = 0 -# FAIL test/isDuplexStream/isDuplexStream.test.js +# PASS test/orderBy.test.js -ok 315 — isDuplexStream is a Function -not ok 316 ● isDuplexStream returns true for read streams -# -# expect(received).toBeTruthy() -# -# -# -# Received: -# -# Stack: -# -# at Object..test (test/isDuplexStream/isDuplexStream.test.js:10:68) -# -# 6 | test('isDuplexStream is a Function', () => { -# 7 | expect(isDuplexStream).toBeInstanceOf(Function); -# 8 | }); -# 9 | test('isDuplexStream returns true for read streams', () => { -# > 10 | expect(isDuplexStream(fs.createReadStream('isDuplexStream.js'))).toBeTruthy(); -# | ^ -# 11 | }); -# 12 | test('isDuplexStream returns true for write streams', () => { -# 13 | expect(isDuplexStream(fs.createWriteStream('isDuplexStream.js'))).toBeTruthy(); -# -# at new Promise () +ok 314 — orderBy is a Function +ok 315 — Returns a sorted array of objects ordered by properties and orders. +ok 316 — Returns a sorted array of objects ordered by properties and orders. -not ok 317 ● isDuplexStream returns true for write streams -# -# expect(received).toBeTruthy() -# -# -# -# Received: -# -# Stack: -# -# at Object..test (test/isDuplexStream/isDuplexStream.test.js:13:69) -# -# 9 | test('isDuplexStream returns true for read streams', () => { -# 10 | expect(isDuplexStream(fs.createReadStream('isDuplexStream.js'))).toBeTruthy(); -# 11 | }); -# 12 | test('isDuplexStream returns true for write streams', () => { -# > 13 | expect(isDuplexStream(fs.createWriteStream('isDuplexStream.js'))).toBeTruthy(); -# | ^ -# 14 | }); -# 15 | test('isDuplexStream returns true for duplex streams', () => { -# 16 | expect(isDuplexStream(new Stream.Duplex())).toBeTruthy(); -# -# at new Promise () +# PASS test/deepFreeze.test.js -ok 318 — isDuplexStream returns true for duplex streams -ok 319 — isDuplexStream returns false for non-streams +ok 317 — deepFreeze is a Function +ok 318 — modifying deeply freezed object prop throws an error in strict mode +ok 319 — should not modify deeply freezed object inside another object +ok 320 — should not add prop to deeply freezed empty object -# FAIL test/getImages/getImages.test.js +# PASS test/CSVToArray.test.js -# -# 16 | expect(getImages(TEST_HTML, false).length).toBeLessThanOrEqual(getImages(TEST_HTML, true).length); -# -# 17 | expect(getImages(TEST_HTML, true)).toEqual(expect.arrayContaining(getImages(TEST_HTML, false))); -# > 18 | });\n -# | ^ -# 19 | +ok 321 — CSVToArray is a Function +ok 322 — CSVToArray works with default delimiter +ok 323 — CSVToArray works with custom delimiter +ok 324 — CSVToArray omits the first row +ok 325 — CSVToArray omits the first row and works with a custom delimiter -# PASS test/sampleSize/sampleSize.test.js +# PASS test/isReadableStream.test.js -ok 320 — sampleSize is a Function -ok 321 — Returns a single element without n specified -ok 322 — Returns a random sample of specified size from an array -ok 323 — Returns all elements in an array if n >= length -ok 324 — Returns an empty array if original array is empty -ok 325 — Returns an empty array if n = 0 +ok 326 — isReadableStream is a Function +ok 327 — isReadableStream returns true for read streams +ok 328 — isReadableStream returns false for write streams +ok 329 — isReadableStream returns true for duplex streams +ok 330 — isReadableStream returns false for non-streams -# PASS test/orderBy/orderBy.test.js +# PASS test/isWritableStream.test.js -ok 326 — orderBy is a Function -ok 327 — Returns a sorted array of objects ordered by properties and orders. -ok 328 — Returns a sorted array of objects ordered by properties and orders. +ok 331 — isWritableStream is a Function +ok 332 — isWritableStream returns false for read streams +ok 333 — isWritableStream returns true for write streams +ok 334 — isWritableStream returns true for duplex streams +ok 335 — isWritableStream returns false for non-streams -# PASS test/deepFreeze/deepFreeze.test.js +# PASS test/any.test.js -ok 329 — deepFreeze is a Function -ok 330 — modifying deeply freezed object prop throws an error in strict mode -ok 331 — should not modify deeply freezed object inside another object -ok 332 — should not add prop to deeply freezed empty object +ok 336 — any is a Function +ok 337 — Returns true for arrays with at least one truthy value +ok 338 — Returns false for arrays with no truthy values +ok 339 — Returns false for arrays with no truthy values +ok 340 — Returns true with predicate function +ok 341 — Returns false with a predicate function -# PASS test/CSVToArray/CSVToArray.test.js - -ok 333 — CSVToArray is a Function -ok 334 — CSVToArray works with default delimiter -ok 335 — CSVToArray works with custom delimiter -ok 336 — CSVToArray omits the first row -ok 337 — CSVToArray omits the first row and works with a custom delimiter - -# PASS test/initializeArrayWithRange/initializeArrayWithRange.test.js - -ok 338 — initializeArrayWithRange is a Function -ok 339 — Initializes an array containing the numbers in the specified range (witout start value) -ok 340 — Initializes an array containing the numbers in the specified range -ok 341 — Initializes an array containing the numbers in the specified range (with step) - -# PASS test/randomIntegerInRange/randomIntegerInRange.test.js +# PASS test/randomIntegerInRange.test.js ok 342 — randomIntegerInRange is a Function ok 343 — The returned value is an integer ok 344 — The returned value lies between provided lowerLimit and upperLimit (both inclusive). -# PASS test/randomNumberInRange/randomNumberInRange.test.js +# PASS test/initializeArrayWithRange.test.js -ok 345 — randomNumberInRange is a Function -ok 346 — The returned value is a number -ok 347 — The returned value lies between provided lowerLimit and upperLimit (both inclusive). +ok 345 — initializeArrayWithRange is a Function +ok 346 — Initializes an array containing the numbers in the specified range (witout start value) +ok 347 — Initializes an array containing the numbers in the specified range +ok 348 — Initializes an array containing the numbers in the specified range (with step) -# PASS test/any/any.test.js +# PASS test/fahrenheitToCelsius.test.js -ok 348 — any is a Function -ok 349 — Returns true for arrays with at least one truthy value -ok 350 — Returns false for arrays with no truthy values -ok 351 — Returns false for arrays with no truthy values -ok 352 — Returns true with predicate function -ok 353 — Returns false with a predicate function +ok 349 — fahrenheitToCelsius is a Function +ok 350 — 32 Fahrenheit is 0 Celsius +ok 351 — 212 Fahrenheit is 100 Celsius +ok 352 — 150 Fahrenheit is 65.55555555555556 Celsius +ok 353 — 1000 Fahrenheit is 537.7777777777778 +ok 354 — Not a number value is NaN -# PASS test/toCurrency/toCurrency.test.js +# PASS test/randomNumberInRange.test.js -ok 354 — toCurrency is a Function -ok 355 — currency: Euro | currencyLangFormat: Local -ok 356 — currency: US Dollar | currencyLangFormat: English (United States) -ok 357 — currency: Japanese Yen | currencyLangFormat: Local +ok 355 — randomNumberInRange is a Function +ok 356 — The returned value is a number +ok 357 — The returned value lies between provided lowerLimit and upperLimit (both inclusive). -# PASS test/geometricProgression/geometricProgression.test.js +# PASS test/isDuplexStream.test.js -ok 358 — geometricProgression is a Function -ok 359 — Initializes an array containing the numbers in the specified range -ok 360 — Initializes an array containing the numbers in the specified range -ok 361 — Initializes an array containing the numbers in the specified range +ok 358 — isDuplexStream is a Function +ok 359 — isDuplexStream returns false for read streams +ok 360 — isDuplexStream returns false for write streams +ok 361 — isDuplexStream returns true for duplex streams +ok 362 — isDuplexStream returns false for non-streams -# PASS test/mapObject/mapObject.test.js +# PASS test/toCurrency.test.js -ok 362 — mapObject is a Function -ok 363 — mapObject([1, 2, 3], a => a * a) returns { 1: 1, 2: 4, 3: 9 } -ok 364 — mapObject([1, 2, 3, 4], (a, b) => b - a) returns { 1: -1, 2: -1, 3: -1, 4: -1 } -ok 365 — mapObject([1, 2, 3, 4], (a, b) => a - b) returns { 1: 1, 2: 1, 3: 1, 4: 1 } +ok 363 — toCurrency is a Function +ok 364 — currency: Euro | currencyLangFormat: Local +ok 365 — currency: US Dollar | currencyLangFormat: English (United States) +ok 366 — currency: Japanese Yen | currencyLangFormat: Local -# PASS test/join/join.test.js +# PASS test/join.test.js -ok 366 — join is a Function -ok 367 — Joins all elements of an array into a string and returns this string +ok 367 — join is a Function ok 368 — Joins all elements of an array into a string and returns this string ok 369 — Joins all elements of an array into a string and returns this string +ok 370 — Joins all elements of an array into a string and returns this string -# PASS test/isStream/isStream.test.js +# PASS test/mapObject.test.js -ok 370 — isStream is a Function -ok 371 — isStream returns true for read streams -ok 372 — isStream returns true for write streams -ok 373 — isStream returns true for duplex streams -ok 374 — isStream returns false for non-streams +ok 371 — mapObject is a Function +ok 372 — mapObject([1, 2, 3], a => a * a) returns { 1: 1, 2: 4, 3: 9 } +ok 373 — mapObject([1, 2, 3, 4], (a, b) => b - a) returns { 1: -1, 2: -1, 3: -1, 4: -1 } +ok 374 — mapObject([1, 2, 3, 4], (a, b) => a - b) returns { 1: 1, 2: 1, 3: 1, 4: 1 } -# PASS test/binomialCoefficient/binomialCoefficient.test.js +# PASS test/geometricProgression.test.js -ok 375 — binomialCoefficient is a Function -ok 376 — Returns the appropriate value -ok 377 — Returns the appropriate value -ok 378 — Returns the appropriate value -ok 379 — Returns NaN -ok 380 — Returns NaN +ok 375 — geometricProgression is a Function +ok 376 — Initializes an array containing the numbers in the specified range +ok 377 — Initializes an array containing the numbers in the specified range +ok 378 — Initializes an array containing the numbers in the specified range -# PASS test/mapString/mapString.test.js +# PASS test/binomialCoefficient.test.js -ok 381 — mapString is a Function -ok 382 — mapString returns a capitalized string -ok 383 — mapString can deal with indexes -ok 384 — mapString can deal with the full string +ok 379 — binomialCoefficient is a Function +ok 380 — Returns the appropriate value +ok 381 — Returns the appropriate value +ok 382 — Returns the appropriate value +ok 383 — Returns NaN +ok 384 — Returns NaN -# PASS test/dig/dig.test.js +# PASS test/mapString.test.js -ok 385 — dig is a Function -ok 386 — Dig target success -ok 387 — Dig target with falsey value -ok 388 — Dig target with array -ok 389 — Unknown target return undefined +ok 385 — mapString is a Function +ok 386 — mapString returns a capitalized string +ok 387 — mapString can deal with indexes +ok 388 — mapString can deal with the full string -# PASS test/reduceWhich/reduceWhich.test.js +# PASS test/dig.test.js -ok 390 — reduceWhich is a Function -ok 391 — Returns the minimum of an array -ok 392 — Returns the maximum of an array -ok 393 — Returns the object with the minimum specified value in an array +ok 389 — dig is a Function +ok 390 — Dig target success +ok 391 — Dig target with falsey value +ok 392 — Dig target with array +ok 393 — Unknown target return undefined -# PASS test/invertKeyValues/invertKeyValues.test.js +# PASS test/celsiusToFahrenheit.test.js -ok 394 — invertKeyValues is a Function -ok 395 — invertKeyValues({ a: 1, b: 2, c: 1 }) returns { 1: [ 'a', 'c' ], 2: [ 'b' ] } -ok 396 — invertKeyValues({ a: 1, b: 2, c: 1 }, value => 'group' + value) returns { group1: [ 'a', 'c' ], group2: [ 'b' ] } +ok 394 — celsiusToFahrenheit is a Function +ok 395 — 0 Celsius is 32 Fahrenheit +ok 396 — 100 Celsius is 212 Fahrenheit +ok 397 — -50 Celsius is -58 Fahrenheit +ok 398 — 1000 Celsius is 1832 Fahrenheit +ok 399 — Not a number value is NaN -# PASS test/fromCamelCase/fromCamelCase.test.js +# PASS test/reduceWhich.test.js -ok 397 — fromCamelCase is a Function -ok 398 — Converts a string from camelcase -ok 399 — Converts a string from camelcase -ok 400 — Converts a string from camelcase +ok 400 — reduceWhich is a Function +ok 401 — Returns the minimum of an array +ok 402 — Returns the maximum of an array +ok 403 — Returns the object with the minimum specified value in an array -# PASS test/approximatelyEqual/approximatelyEqual.test.js +# PASS test/isStream.test.js -ok 401 — approximatelyEqual is a Function -ok 402 — Works for PI / 2 -ok 403 — Works for 0.1 + 0.2 === 0.3 -ok 404 — Works for exactly equal values -ok 405 — Works for a custom epsilon +ok 404 — isStream is a Function +ok 405 — isStream returns true for read streams +ok 406 — isStream returns true for write streams +ok 407 — isStream returns true for duplex streams +ok 408 — isStream returns false for non-streams -# PASS test/shank/shank.test.js +# PASS test/invertKeyValues.test.js -ok 406 — shank is a Function -ok 407 — Returns an array with the added elements. -ok 408 — Returns an array with the removed elements. -ok 409 — Does not mutate the original array +ok 409 — invertKeyValues is a Function +ok 410 — invertKeyValues({ a: 1, b: 2, c: 1 }) returns { 1: [ 'a', 'c' ], 2: [ 'b' ] } +ok 411 — invertKeyValues({ a: 1, b: 2, c: 1 }, value => 'group' + value) returns { group1: [ 'a', 'c' ], group2: [ 'b' ] } -# PASS test/none/none.test.js +# PASS test/fromCamelCase.test.js -ok 410 — none is a Function -ok 411 — Returns true for arrays with no truthy values -ok 412 — Returns false for arrays with at least one truthy value -ok 413 — Returns true with a predicate function -ok 414 — Returns false with predicate function +ok 412 — fromCamelCase is a Function +ok 413 — Converts a string from camelcase +ok 414 — Converts a string from camelcase +ok 415 — Converts a string from camelcase -# PASS test/castArray/castArray.test.js +# PASS test/shank.test.js -ok 415 — castArray is a Function -ok 416 — Works for single values -ok 417 — Works for arrays with one value -ok 418 — Works for arrays with multiple value -ok 419 — Works for strings -ok 420 — Works for objects +ok 416 — shank is a Function +ok 417 — Returns an array with the added elements. +ok 418 — Returns an array with the removed elements. +ok 419 — Does not mutate the original array -# PASS test/randomHexColorCode/randomHexColorCode.test.js +# PASS test/approximatelyEqual.test.js -ok 421 — randomHexColorCode is a Function -ok 422 — randomHexColorCode has to proper length -ok 423 — The color code starts with "#" -ok 424 — The color code contains only valid hex-digits +ok 420 — approximatelyEqual is a Function +ok 421 — Works for PI / 2 +ok 422 — Works for 0.1 + 0.2 === 0.3 +ok 423 — Works for exactly equal values +ok 424 — Works for a custom epsilon -# PASS test/binarySearch/binarySearch.test.js +# PASS test/none.test.js -ok 425 — binarySearch is a Function -ok 426 — Finds item in array -ok 427 — Returns -1 when not found -ok 428 — Works with empty arrays -ok 429 — Works for one element arrays +ok 425 — none is a Function +ok 426 — Returns true for arrays with no truthy values +ok 427 — Returns false for arrays with at least one truthy value +ok 428 — Returns true with a predicate function +ok 429 — Returns false with predicate function -# PASS test/inRange/inRange.test.js +# PASS test/castArray.test.js -ok 430 — inRange is a Function -ok 431 — The given number falls within the given range -ok 432 — The given number falls within the given range -ok 433 — The given number does not falls within the given range -ok 434 — The given number does not falls within the given range +ok 430 — castArray is a Function +ok 431 — Works for single values +ok 432 — Works for arrays with one value +ok 433 — Works for arrays with multiple value +ok 434 — Works for strings +ok 435 — Works for objects -# PASS test/mask/mask.test.js +# PASS test/binarySearch.test.js -ok 435 — mask is a Function -ok 436 — Replaces all but the last num of characters with the specified mask character -ok 437 — Replaces all but the last num of characters with the specified mask character -ok 438 — Replaces all but the last num of characters with the specified mask character +ok 436 — binarySearch is a Function +ok 437 — Finds item in array +ok 438 — Returns -1 when not found +ok 439 — Works with empty arrays +ok 440 — Works for one element arrays -# PASS test/factorial/factorial.test.js +# PASS test/inRange.test.js -ok 439 — factorial is a Function -ok 440 — Calculates the factorial of 720 -ok 441 — Calculates the factorial of 0 -ok 442 — Calculates the factorial of 1 -ok 443 — Calculates the factorial of 4 -ok 444 — Calculates the factorial of 10 +ok 441 — inRange is a Function +ok 442 — The given number falls within the given range +ok 443 — The given number falls within the given range +ok 444 — The given number does not falls within the given range +ok 445 — The given number does not falls within the given range -# PASS test/toOrdinalSuffix/toOrdinalSuffix.test.js +# PASS test/mask.test.js -ok 445 — toOrdinalSuffix is a Function -ok 446 — Adds an ordinal suffix to a number -ok 447 — Adds an ordinal suffix to a number -ok 448 — Adds an ordinal suffix to a number -ok 449 — Adds an ordinal suffix to a number +ok 446 — mask is a Function +ok 447 — Replaces all but the last num of characters with the specified mask character +ok 448 — Replaces all but the last num of characters with the specified mask character +ok 449 — Replaces all but the last num of characters with the specified mask character -# PASS test/JSONtoCSV/JSONtoCSV.test.js +# PASS test/randomHexColorCode.test.js -ok 450 — JSONtoCSV is a Function -ok 451 — JSONtoCSV works with default delimiter -ok 452 — JSONtoCSV works with custom delimiter +ok 450 — randomHexColorCode is a Function +ok 451 — randomHexColorCode has to proper length +ok 452 — The color code starts with "#" +ok 453 — The color code contains only valid hex-digits -# PASS test/capitalize/capitalize.test.js +# PASS test/factorial.test.js -ok 453 — capitalize is a Function -ok 454 — Capitalizes the first letter of a string -ok 455 — Capitalizes the first letter of a string -ok 456 — Works with characters -ok 457 — "Works with single character words +ok 454 — factorial is a Function +ok 455 — Calculates the factorial of 720 +ok 456 — Calculates the factorial of 0 +ok 457 — Calculates the factorial of 1 +ok 458 — Calculates the factorial of 4 +ok 459 — Calculates the factorial of 10 -# PASS test/converge/converge.test.js +# PASS test/JSONtoCSV.test.js -ok 458 — converge is a Function -ok 459 — Produces the average of the array -ok 460 — Produces the strange concatenation +ok 460 — JSONtoCSV is a Function +ok 461 — JSONtoCSV works with default delimiter +ok 462 — JSONtoCSV works with custom delimiter -# PASS test/deepClone/deepClone.test.js +# PASS test/converge.test.js -ok 461 — deepClone is a Function -ok 462 — Shallow cloning works -ok 463 — Deep cloning works -ok 464 — Array shallow cloning works -ok 465 — Array deep cloning works +ok 463 — converge is a Function +ok 464 — Produces the average of the array +ok 465 — Produces the strange concatenation -# PASS test/isAnagram/isAnagram.test.js +# PASS test/capitalize.test.js -ok 466 — isAnagram is a Function -ok 467 — Checks valid anagram -ok 468 — Works with spaces -ok 469 — Ignores case -ok 470 — Ignores special characters +ok 466 — capitalize is a Function +ok 467 — Capitalizes the first letter of a string +ok 468 — Capitalizes the first letter of a string +ok 469 — Works with characters +ok 470 — "Works with single character words -# PASS test/tomorrow/tomorrow.test.js +# PASS test/toOrdinalSuffix.test.js -ok 471 — tomorrow is a Function -ok 472 — Returns the correct year -ok 473 — Returns the correct month -ok 474 — Returns the correct date +ok 471 — toOrdinalSuffix is a Function +ok 472 — Adds an ordinal suffix to a number +ok 473 — Adds an ordinal suffix to a number +ok 474 — Adds an ordinal suffix to a number +ok 475 — Adds an ordinal suffix to a number -# PASS test/shuffle/shuffle.test.js +# PASS test/deepClone.test.js -ok 475 — shuffle is a Function -ok 476 — Shuffles the array -ok 477 — New array contains all original elements -ok 478 — Works for empty arrays -ok 479 — Works for single-element arrays +ok 476 — deepClone is a Function +ok 477 — Shallow cloning works +ok 478 — Deep cloning works +ok 479 — Array shallow cloning works +ok 480 — Array deep cloning works -# PASS test/prettyBytes/prettyBytes.test.js +# PASS test/isAnagram.test.js -ok 480 — prettyBytes is a Function -ok 481 — Converts a number in bytes to a human-readable string. -ok 482 — Converts a number in bytes to a human-readable string. -ok 483 — Converts a number in bytes to a human-readable string. +ok 481 — isAnagram is a Function +ok 482 — Checks valid anagram +ok 483 — Works with spaces +ok 484 — Ignores case +ok 485 — Ignores special characters -# PASS test/stringPermutations/stringPermutations.test.js +# PASS test/tomorrow.test.js -ok 484 — stringPermutations is a Function -ok 485 — Generates all stringPermutations of a string -ok 486 — Works for single-letter strings -ok 487 — Works for empty strings +ok 486 — tomorrow is a Function +ok 487 — Returns the correct year +ok 488 — Returns the correct month +ok 489 — Returns the correct date -# PASS test/isString/isString.test.js +# PASS test/shuffle.test.js -ok 488 — isString is a Function -ok 489 — foo is a string -ok 490 — "10" is a string -ok 491 — Empty string is a string -ok 492 — 10 is not a string -ok 493 — true is not string +ok 490 — shuffle is a Function +ok 491 — Shuffles the array +ok 492 — New array contains all original elements +ok 493 — Works for empty arrays +ok 494 — Works for single-element arrays -# PASS test/dropRight/dropRight.test.js +# PASS test/prettyBytes.test.js -ok 494 — dropRight is a Function -ok 495 — Returns a new array with n elements removed from the right -ok 496 — Returns a new array with n elements removed from the right -ok 497 — Returns a new array with n elements removed from the right +ok 495 — prettyBytes is a Function +ok 496 — Converts a number in bytes to a human-readable string. +ok 497 — Converts a number in bytes to a human-readable string. +ok 498 — Converts a number in bytes to a human-readable string. -# PASS test/hexToRGB/hexToRGB.test.js +# PASS test/isString.test.js -ok 498 — hexToRGB is a Function -ok 499 — Converts a color code to a rgb() or rgba() string -ok 500 — Converts a color code to a rgb() or rgba() string -ok 501 — Converts a color code to a rgb() or rgba() string +ok 499 — isString is a Function +ok 500 — foo is a string +ok 501 — "10" is a string +ok 502 — Empty string is a string +ok 503 — 10 is not a string +ok 504 — true is not string -# PASS test/formatDuration/formatDuration.test.js +# PASS test/hexToRGB.test.js -ok 502 — formatDuration is a Function -ok 503 — Returns the human readable format of the given number of milliseconds -ok 504 — Returns the human readable format of the given number of milliseconds +ok 505 — hexToRGB is a Function +ok 506 — Converts a color code to a rgb() or rgba() string +ok 507 — Converts a color code to a rgb() or rgba() string +ok 508 — Converts a color code to a rgb() or rgba() string -# PASS test/partition/partition.test.js +# PASS test/dropRight.test.js -ok 505 — partition is a Function -ok 506 — Groups the elements into two arrays, depending on the provided function's truthiness for each element. +ok 509 — dropRight is a Function +ok 510 — Returns a new array with n elements removed from the right +ok 511 — Returns a new array with n elements removed from the right +ok 512 — Returns a new array with n elements removed from the right -# PASS test/capitalizeEveryWord/capitalizeEveryWord.test.js +# PASS test/partition.test.js -ok 507 — capitalizeEveryWord is a Function -ok 508 — Capitalizes the first letter of every word in a string -ok 509 — Works with characters -ok 510 — Works with one word string +ok 513 — partition is a Function +ok 514 — Groups the elements into two arrays, depending on the provided function's truthiness for each element. -# PASS test/isObjectLike/isObjectLike.test.js +# PASS test/stringPermutations.test.js -ok 511 — isObjectLike is a Function -ok 512 — Returns true for an object -ok 513 — Returns true for an array -ok 514 — Returns false for a function -ok 515 — Returns false for null +ok 515 — stringPermutations is a Function +ok 516 — Generates all stringPermutations of a string +ok 517 — Works for single-letter strings +ok 518 — Works for empty strings -# PASS test/standardDeviation/standardDeviation.test.js +# PASS test/formatDuration.test.js -ok 516 — standardDeviation is a Function -ok 517 — Returns the standard deviation of an array of numbers -ok 518 — Returns the standard deviation of an array of numbers +ok 519 — formatDuration is a Function +ok 520 — Returns the human readable format of the given number of milliseconds +ok 521 — Returns the human readable format of the given number of milliseconds -# PASS test/sumPower/sumPower.test.js +# PASS test/sumPower.test.js -ok 519 — sumPower is a Function -ok 520 — Returns the sum of the powers of all the numbers from start to end -ok 521 — Returns the sum of the powers of all the numbers from start to end -ok 522 — Returns the sum of the powers of all the numbers from start to end +ok 522 — sumPower is a Function +ok 523 — Returns the sum of the powers of all the numbers from start to end +ok 524 — Returns the sum of the powers of all the numbers from start to end +ok 525 — Returns the sum of the powers of all the numbers from start to end -# PASS test/untildify/untildify.test.js +# PASS test/isObjectLike.test.js -ok 523 — untildify is a Function -ok 524 — Contains no tildes -ok 525 — Does not alter the rest of the path -ok 526 — Does not alter paths without tildes +ok 526 — isObjectLike is a Function +ok 527 — Returns true for an object +ok 528 — Returns true for an array +ok 529 — Returns false for a function +ok 530 — Returns false for null -# PASS test/isObject/isObject.test.js +# PASS test/untildify.test.js -ok 527 — isObject is a Function -ok 528 — isObject([1, 2, 3, 4]) is a object -ok 529 — isObject([]) is a object -ok 530 — isObject({ a:1 }) is a object -ok 531 — isObject(true) is not a object +ok 531 — untildify is a Function +ok 532 — Contains no tildes +ok 533 — Does not alter the rest of the path +ok 534 — Does not alter paths without tildes -# PASS test/CSVToJSON/CSVToJSON.test.js +# PASS test/isObject.test.js -ok 532 — CSVToJSON is a Function -ok 533 — CSVToJSON works with default delimiter -ok 534 — CSVToJSON works with custom delimiter +ok 535 — isObject is a Function +ok 536 — isObject([1, 2, 3, 4]) is a object +ok 537 — isObject([]) is a object +ok 538 — isObject({ a:1 }) is a object +ok 539 — isObject(true) is not a object -# PASS test/reducedFilter/reducedFilter.test.js +# PASS test/standardDeviation.test.js -ok 535 — reducedFilter is a Function -ok 536 — Filter an array of objects based on a condition while also filtering out unspecified keys. +ok 540 — standardDeviation is a Function +ok 541 — Returns the standard deviation of an array of numbers +ok 542 — Returns the standard deviation of an array of numbers -# PASS test/URLJoin/URLJoin.test.js +# PASS test/capitalizeEveryWord.test.js -ok 537 — URLJoin is a Function -ok 538 — Returns proper URL -ok 539 — Returns proper URL +ok 543 — capitalizeEveryWord is a Function +ok 544 — Capitalizes the first letter of every word in a string +ok 545 — Works with characters +ok 546 — Works with one word string -# PASS test/unzip/unzip.test.js +# PASS test/unzip.test.js -ok 540 — unzip is a Function -ok 541 — unzip([['a', 1, true], ['b', 2, false]]) equals [['a','b'], [1, 2], [true, false]] -ok 542 — unzip([['a', 1, true], ['b', 2]]) equals [['a','b'], [1, 2], [true]] +ok 547 — unzip is a Function +ok 548 — unzip([['a', 1, true], ['b', 2, false]]) equals [['a','b'], [1, 2], [true, false]] +ok 549 — unzip([['a', 1, true], ['b', 2]]) equals [['a','b'], [1, 2], [true]] -# PASS test/sortedIndex/sortedIndex.test.js +# PASS test/URLJoin.test.js -ok 543 — sortedIndex is a Function -ok 544 — Returns the lowest index at which value should be inserted into array in order to maintain its sort order. -ok 545 — Returns the lowest index at which value should be inserted into array in order to maintain its sort order. +ok 550 — URLJoin is a Function +ok 551 — Returns proper URL +ok 552 — Returns proper URL -# PASS test/byteSize/byteSize.test.js +# PASS test/CSVToJSON.test.js -ok 546 — byteSize is a Function -ok 547 — Works for a single letter -ok 548 — Works for a common string -ok 549 — Works for emoji +ok 553 — CSVToJSON is a Function +ok 554 — CSVToJSON works with default delimiter +ok 555 — CSVToJSON works with custom delimiter -# PASS test/isAbsoluteURL/isAbsoluteURL.test.js +# PASS test/byteSize.test.js -ok 550 — isAbsoluteURL is a Function -ok 551 — Given string is an absolute URL -ok 552 — Given string is an absolute URL -ok 553 — Given string is not an absolute URL +ok 556 — byteSize is a Function +ok 557 — Works for a single letter +ok 558 — Works for a common string +ok 559 — Works for emoji -# PASS test/uniqueSymmetricDifference/uniqueSymmetricDifference.test.js +# PASS test/sortedIndex.test.js -ok 554 — uniqueSymmetricDifference is a Function -ok 555 — Returns the symmetric difference between two arrays. -ok 556 — Does not return duplicates from one array +ok 560 — sortedIndex is a Function +ok 561 — Returns the lowest index at which value should be inserted into array in order to maintain its sort order. +ok 562 — Returns the lowest index at which value should be inserted into array in order to maintain its sort order. -# PASS test/matches/matches.test.js +# PASS test/reducedFilter.test.js -ok 557 — matches is a Function -ok 558 — Matches returns true for two similar objects -ok 559 — Matches returns false for two non-similar objects +ok 563 — reducedFilter is a Function +ok 564 — Filter an array of objects based on a condition while also filtering out unspecified keys. -# PASS test/collectInto/collectInto.test.js +# PASS test/matches.test.js -ok 560 — collectInto is a Function -ok 561 — Works with multiple promises +ok 565 — matches is a Function +ok 566 — Matches returns true for two similar objects +ok 567 — Matches returns false for two non-similar objects -# PASS test/uncurry/uncurry.test.js +# PASS test/uncurry.test.js -ok 562 — uncurry is a Function -ok 563 — Works without a provided value for n -ok 564 — Works with n = 2 -ok 565 — Works with n = 3 +ok 568 — uncurry is a Function +ok 569 — Works without a provided value for n +ok 570 — Works with n = 2 +ok 571 — Works with n = 3 -# PASS test/isValidJSON/isValidJSON.test.js - -ok 566 — isValidJSON is a Function -ok 567 — {"name":"Adam","age":20} is a valid JSON -ok 568 — {"name":"Adam",age:"20"} is not a valid JSON -ok 569 — null is a valid JSON - -# PASS test/symmetricDifferenceWith/symmetricDifferenceWith.test.js - -ok 570 — symmetricDifferenceWith is a Function -ok 571 — Returns the symmetric difference between two arrays, using a provided function as a comparator - -# PASS test/pad/pad.test.js +# PASS test/pad.test.js ok 572 — pad is a Function ok 573 — cat is padded on both sides @@ -929,1319 +867,1328 @@ ok 574 — length of string is 8 ok 575 — pads 42 with "0" ok 576 — does not truncates if string exceeds length -# PASS test/groupBy/groupBy.test.js +# PASS test/isAbsoluteURL.test.js -ok 577 — groupBy is a Function -ok 578 — Groups the elements of an array based on the given function -ok 579 — Groups the elements of an array based on the given function +ok 577 — isAbsoluteURL is a Function +ok 578 — Given string is an absolute URL +ok 579 — Given string is an absolute URL +ok 580 — Given string is not an absolute URL -# PASS test/lowercaseKeys/lowercaseKeys.test.js +# PASS test/collectInto.test.js -ok 580 — lowercaseKeys is a Function -ok 581 — Lowercases object keys -ok 582 — Does not mutate original object +ok 581 — collectInto is a Function +ok 582 — Works with multiple promises -# PASS test/functionName/functionName.test.js +# PASS test/isValidJSON.test.js -ok 583 — functionName is a Function -ok 584 — Works for native functions -ok 585 — Works for functions -ok 586 — Works for arrow functions +ok 583 — isValidJSON is a Function +ok 584 — {"name":"Adam","age":20} is a valid JSON +ok 585 — {"name":"Adam",age:"20"} is not a valid JSON +ok 586 — null is a valid JSON -# PASS test/matchesWith/matchesWith.test.js +# PASS test/groupBy.test.js -ok 587 — matchesWith is a Function -ok 588 — Returns true for two objects with similar values, based on the provided function +ok 587 — groupBy is a Function +ok 588 — Groups the elements of an array based on the given function +ok 589 — Groups the elements of an array based on the given function -# PASS test/collatz/collatz.test.js +# PASS test/uniqueSymmetricDifference.test.js -ok 589 — collatz is a Function -ok 590 — When n is even, divide by 2 -ok 591 — When n is odd, times by 3 and add 1 -ok 592 — Eventually reaches 1 +ok 590 — uniqueSymmetricDifference is a Function +ok 591 — Returns the symmetric difference between two arrays. +ok 592 — Does not return duplicates from one array -# PASS test/reject/reject.test.js +# PASS test/symmetricDifferenceWith.test.js -ok 593 — reject is a Function -ok 594 — Works with numbers -ok 595 — Works with strings +ok 593 — symmetricDifferenceWith is a Function +ok 594 — Returns the symmetric difference between two arrays, using a provided function as a comparator -# PASS test/UUIDGeneratorNode/UUIDGeneratorNode.test.js +# PASS test/functionName.test.js -ok 596 — UUIDGeneratorNode is a Function -ok 597 — Contains dashes in the proper places -ok 598 — Only contains hexadecimal digits +ok 595 — functionName is a Function +ok 596 — Works for native functions +ok 597 — Works for functions +ok 598 — Works for arrow functions -# PASS test/symmetricDifference/symmetricDifference.test.js +# PASS test/lowercaseKeys.test.js -ok 599 — symmetricDifference is a Function -ok 600 — Returns the symmetric difference between two arrays. -ok 601 — Returns duplicates from one array +ok 599 — lowercaseKeys is a Function +ok 600 — Lowercases object keys +ok 601 — Does not mutate original object -# PASS test/luhnCheck/luhnCheck.test.js +# PASS test/matchesWith.test.js -ok 602 — luhnCheck is a Function -ok 603 — validates identification number -ok 604 — validates identification number -ok 605 — validates identification number +ok 602 — matchesWith is a Function +ok 603 — Returns true for two objects with similar values, based on the provided function -# PASS test/isBeforeDate/isBeforeDate.test.js +# PASS test/collatz.test.js -ok 606 — isBeforeDate is a Function -ok 607 — isBeforeDate produces the correct result -ok 608 — isBeforeDate produces the correct result +ok 604 — collatz is a Function +ok 605 — When n is even, divide by 2 +ok 606 — When n is odd, times by 3 and add 1 +ok 607 — Eventually reaches 1 -# PASS test/intersectionWith/intersectionWith.test.js +# PASS test/reject.test.js -ok 609 — intersectionWith is a Function -ok 610 — Returns a list of elements that exist in both arrays, using a provided comparator function +ok 608 — reject is a Function +ok 609 — Works with numbers +ok 610 — Works with strings -# PASS test/pipeAsyncFunctions/pipeAsyncFunctions.test.js +# PASS test/luhnCheck.test.js -ok 611 — pipeAsyncFunctions is a Function -ok 612 — pipeAsyncFunctions result should be 15 +ok 611 — luhnCheck is a Function +ok 612 — validates identification number +ok 613 — validates identification number +ok 614 — validates identification number -# PASS test/flattenObject/flattenObject.test.js +# PASS test/sample.test.js -ok 613 — flattenObject is a Function -ok 614 — Flattens an object with the paths for keys -ok 615 — Works with arrays +ok 615 — sample is a Function +ok 616 — Returns a random element from the array +ok 617 — Works for single-element arrays +ok 618 — Returns undefined for empty array -# PASS test/nthArg/nthArg.test.js +# PASS test/nthArg.test.js -ok 616 — nthArg is a Function -ok 617 — Returns the nth argument -ok 618 — Returns undefined if arguments too few -ok 619 — Works for negative values +ok 619 — nthArg is a Function +ok 620 — Returns the nth argument +ok 621 — Returns undefined if arguments too few +ok 622 — Works for negative values -# PASS test/sample/sample.test.js +# PASS test/UUIDGeneratorNode.test.js -ok 620 — sample is a Function -ok 621 — Returns a random element from the array -ok 622 — Works for single-element arrays -ok 623 — Returns undefined for empty array +ok 623 — UUIDGeneratorNode is a Function +ok 624 — Contains dashes in the proper places +ok 625 — Only contains hexadecimal digits -# PASS test/isAfterDate/isAfterDate.test.js +# PASS test/drop.test.js -ok 624 — isAfterDate is a Function -ok 625 — isAfterDate produces the correct result -ok 626 — isBeforeDate produces the correct result +ok 626 — drop is a Function +ok 627 — Works without the last argument +ok 628 — Removes appropriate element count as specified +ok 629 — Empties array given a count greater than length -# PASS test/drop/drop.test.js +# PASS test/isBeforeDate.test.js -ok 627 — drop is a Function -ok 628 — Works without the last argument -ok 629 — Removes appropriate element count as specified -ok 630 — Empties array given a count greater than length +ok 630 — isBeforeDate is a Function +ok 631 — isBeforeDate produces the correct result +ok 632 — isBeforeDate produces the correct result -# PASS test/functions/functions.test.js +# PASS test/symmetricDifference.test.js -ok 631 — functions is a Function -ok 632 — Returns own methods -ok 633 — Returns own and inherited methods +ok 633 — symmetricDifference is a Function +ok 634 — Returns the symmetric difference between two arrays. +ok 635 — Returns duplicates from one array -# PASS test/differenceBy/differenceBy.test.js +# PASS test/flattenObject.test.js -ok 634 — differenceBy is a Function -ok 635 — Works using a native function and numbers -ok 636 — Works with arrow function and objects +ok 636 — flattenObject is a Function +ok 637 — Flattens an object with the paths for keys +ok 638 — Works with arrays -# PASS test/renameKeys/renameKeys.test.js +# PASS test/elo.test.js -ok 637 — renameKeys is a Function -ok 638 — renameKeys is a Function +ok 639 — elo is a Function +ok 640 — Standard 1v1s +ok 641 — Standard 1v1s +ok 642 — 4 player FFA, all same rank -# PASS test/memoize/memoize.test.js +# PASS test/intersectionWith.test.js -ok 639 — memoize is a Function -ok 640 — Function works properly -ok 641 — Function works properly -ok 642 — Cache stores values +ok 643 — intersectionWith is a Function +ok 644 — Returns a list of elements that exist in both arrays, using a provided comparator function -# PASS test/elo/elo.test.js +# PASS test/functions.test.js -ok 643 — elo is a Function -ok 644 — Standard 1v1s -ok 645 — Standard 1v1s -ok 646 — 4 player FFA, all same rank +ok 645 — functions is a Function +ok 646 — Returns own methods +ok 647 — Returns own and inherited methods -# PASS test/isLowerCase/isLowerCase.test.js +# PASS test/isAfterDate.test.js -ok 647 — isLowerCase is a Function -ok 648 — passed string is a lowercase -ok 649 — passed string is a lowercase -ok 650 — passed value is not a lowercase +ok 648 — isAfterDate is a Function +ok 649 — isAfterDate produces the correct result +ok 650 — isBeforeDate produces the correct result -# PASS test/isSameDate/isSameDate.test.js +# PASS test/differenceBy.test.js -ok 651 — isSameDate is a Function -ok 652 — isSameDate produces the correct result -ok 653 — isSameDate produces the correct result +ok 651 — differenceBy is a Function +ok 652 — Works using a native function and numbers +ok 653 — Works with arrow function and objects -# PASS test/averageBy/averageBy.test.js +# PASS test/pipeAsyncFunctions.test.js -ok 654 — averageBy is a Function -ok 655 — Produces the right result with a function -ok 656 — Produces the right result with a property name +ok 654 — pipeAsyncFunctions is a Function +ok 655 — pipeAsyncFunctions result should be 15 -# PASS test/bindKey/bindKey.test.js +# PASS test/memoize.test.js -ok 657 — bindKey is a Function -ok 658 — Binds function to an object context +ok 656 — memoize is a Function +ok 657 — Function works properly +ok 658 — Function works properly +ok 659 — Cache stores values -# PASS test/isPromiseLike/isPromiseLike.test.js +# PASS test/renameKeys.test.js -ok 659 — isPromiseLike is a Function -ok 660 — Returns true for a promise-like object -ok 661 — Returns false for an empty object +ok 660 — renameKeys is a Function +ok 661 — renameKeys is a Function -# PASS test/symmetricDifferenceBy/symmetricDifferenceBy.test.js +# PASS test/isLowerCase.test.js -ok 662 — symmetricDifferenceBy is a Function -ok 663 — Returns the symmetric difference between two arrays, after applying the provided function to each array element of both +ok 662 — isLowerCase is a Function +ok 663 — passed string is a lowercase +ok 664 — passed string is a lowercase +ok 665 — passed value is not a lowercase -# PASS test/findLastKey/findLastKey.test.js +# PASS test/isSameDate.test.js -ok 664 — findLastKey is a Function -ok 665 — eturns the appropriate key +ok 666 — isSameDate is a Function +ok 667 — isSameDate produces the correct result +ok 668 — isSameDate produces the correct result -# PASS test/arrayToCSV/arrayToCSV.test.js +# PASS test/averageBy.test.js -ok 666 — arrayToCSV is a Function -ok 667 — arrayToCSV works with default delimiter -ok 668 — arrayToCSV works with custom delimiter +ok 669 — averageBy is a Function +ok 670 — Produces the right result with a function +ok 671 — Produces the right result with a property name -# PASS test/isArrayLike/isArrayLike.test.js +# PASS test/bindKey.test.js -ok 669 — isArrayLike is a Function -ok 670 — Returns true for a string -ok 671 — Returns true for an array -ok 672 — Returns false for null +ok 672 — bindKey is a Function +ok 673 — Binds function to an object context -# PASS test/truthCheckCollection/truthCheckCollection.test.js +# PASS test/findLastKey.test.js -ok 673 — truthCheckCollection is a Function -ok 674 — second argument is truthy on all elements of a collection +ok 674 — findLastKey is a Function +ok 675 — eturns the appropriate key -# PASS test/promisify/promisify.test.js +# PASS test/isPromiseLike.test.js -ok 675 — promisify is a Function -ok 676 — Returns a promise -ok 677 — Runs the function provided +ok 676 — isPromiseLike is a Function +ok 677 — Returns true for a promise-like object +ok 678 — Returns false for an empty object -# PASS test/isUpperCase/isUpperCase.test.js +# PASS test/arrayToCSV.test.js -ok 678 — isUpperCase is a Function -ok 679 — ABC is all upper case -ok 680 — abc is not all upper case -ok 681 — A3@$ is all uppercase +ok 679 — arrayToCSV is a Function +ok 680 — arrayToCSV works with default delimiter +ok 681 — arrayToCSV works with custom delimiter -# PASS test/pullAtValue/pullAtValue.test.js +# PASS test/promisify.test.js -ok 682 — pullAtValue is a Function -ok 683 — Pulls the specified values -ok 684 — Pulls the specified values +ok 682 — promisify is a Function +ok 683 — Returns a promise +ok 684 — Runs the function provided -# PASS test/minBy/minBy.test.js +# PASS test/isArrayLike.test.js -ok 685 — minBy is a Function -ok 686 — Produces the right result with a function -ok 687 — Produces the right result with a property name +ok 685 — isArrayLike is a Function +ok 686 — Returns true for a string +ok 687 — Returns true for an array +ok 688 — Returns false for null -# PASS test/maxBy/maxBy.test.js +# PASS test/minBy.test.js -ok 688 — maxBy is a Function -ok 689 — Produces the right result with a function -ok 690 — Produces the right result with a property name +ok 689 — minBy is a Function +ok 690 — Produces the right result with a function +ok 691 — Produces the right result with a property name -# PASS test/unzipWith/unzipWith.test.js +# PASS test/maxBy.test.js -ok 691 — unzipWith is a Function -ok 692 — unzipWith([[1, 10, 100], [2, 20, 200]], (...args) => args.reduce((acc, v) => acc + v, 0)) equals [3, 30, 300] +ok 692 — maxBy is a Function +ok 693 — Produces the right result with a function +ok 694 — Produces the right result with a property name -# PASS test/findKey/findKey.test.js +# PASS test/symmetricDifferenceBy.test.js -ok 693 — findKey is a Function -ok 694 — Returns the appropriate key +ok 695 — symmetricDifferenceBy is a Function +ok 696 — Returns the symmetric difference between two arrays, after applying the provided function to each array element of both -# PASS test/merge/merge.test.js +# PASS test/isUpperCase.test.js -ok 695 — merge is a Function -ok 696 — Merges two objects +ok 697 — isUpperCase is a Function +ok 698 — ABC is all upper case +ok 699 — abc is not all upper case +ok 700 — A3@$ is all uppercase -# PASS test/pullAtIndex/pullAtIndex.test.js +# PASS test/unzipWith.test.js -ok 697 — pullAtIndex is a Function -ok 698 — Pulls the given values -ok 699 — Pulls the given values +ok 701 — unzipWith is a Function +ok 702 — unzipWith([[1, 10, 100], [2, 20, 200]], (...args) => args.reduce((acc, v) => acc + v, 0)) equals [3, 30, 300] -# PASS test/coalesceFactory/coalesceFactory.test.js +# PASS test/truthCheckCollection.test.js -ok 700 — coalesceFactory is a Function -ok 701 — Returns a customized coalesce function +ok 703 — truthCheckCollection is a Function +ok 704 — second argument is truthy on all elements of a collection -# PASS test/indentString/indentString.test.js +# PASS test/pullAtValue.test.js -ok 702 — indentString is a Function -ok 703 — indentString is a Function -ok 704 — indentString is a Function +ok 705 — pullAtValue is a Function +ok 706 — Pulls the specified values +ok 707 — Pulls the specified values -# PASS test/bind/bind.test.js +# PASS test/findKey.test.js -ok 705 — bind is a Function -ok 706 — Binds to an object context +ok 708 — findKey is a Function +ok 709 — Returns the appropriate key -# PASS test/takeRight/takeRight.test.js +# PASS test/merge.test.js -ok 707 — takeRight is a Function -ok 708 — Returns an array with n elements removed from the end -ok 709 — Returns an array with n elements removed from the end +ok 710 — merge is a Function +ok 711 — Merges two objects -# PASS test/transform/transform.test.js +# PASS test/bind.test.js -ok 710 — transform is a Function -ok 711 — Transforms an object +ok 712 — bind is a Function +ok 713 — Binds to an object context -# PASS test/getURLParameters/getURLParameters.test.js +# PASS test/pullAtIndex.test.js -ok 712 — getURLParameters is a Function -ok 713 — Returns an object containing the parameters of the current URL +ok 714 — pullAtIndex is a Function +ok 715 — Pulls the given values +ok 716 — Pulls the given values -# PASS test/reduceSuccessive/reduceSuccessive.test.js +# PASS test/indentString.test.js -ok 714 — reduceSuccessive is a Function -ok 715 — Returns the array of successively reduced values +ok 717 — indentString is a Function +ok 718 — indentString is a Function +ok 719 — indentString is a Function -# PASS test/runPromisesInSeries/runPromisesInSeries.test.js +# PASS test/takeRight.test.js -ok 716 — runPromisesInSeries is a Function -ok 717 — Runs promises in series +ok 720 — takeRight is a Function +ok 721 — Returns an array with n elements removed from the end +ok 722 — Returns an array with n elements removed from the end -# PASS test/intersectionBy/intersectionBy.test.js +# PASS test/transform.test.js -ok 718 — intersectionBy is a Function -ok 719 — Returns a list of elements that exist in both arrays, after applying the provided function to each array element of both +ok 723 — transform is a Function +ok 724 — Transforms an object -# PASS test/isPlainObject/isPlainObject.test.js +# PASS test/gcd.test.js -ok 720 — isPlainObject is a Function -ok 721 — Returns true for a plain object -ok 722 — Returns false for a Map (example of non-plain object) +ok 725 — gcd is a Function +ok 726 — Calculates the greatest common divisor between two or more numbers/arrays +ok 727 — Calculates the greatest common divisor between two or more numbers/arrays -# PASS test/isNil/isNil.test.js +# PASS test/isNil.test.js -ok 723 — isNil is a Function -ok 724 — Returns true for null -ok 725 — Returns true for undefined -ok 726 — Returns false for an empty string +ok 728 — isNil is a Function +ok 729 — Returns true for null +ok 730 — Returns true for undefined +ok 731 — Returns false for an empty string -# PASS test/indexOfAll/indexOfAll.test.js +# PASS test/coalesceFactory.test.js -ok 727 — indexOfAll is a Function -ok 728 — Returns all indices of val in an array -ok 729 — When val is not found, return an empty array +ok 732 — coalesceFactory is a Function +ok 733 — Returns a customized coalesce function -# PASS test/pipeFunctions/pipeFunctions.test.js +# PASS test/take.test.js -ok 730 — pipeFunctions is a Function -ok 731 — Performs left-to-right function composition +ok 734 — take is a Function +ok 735 — Returns an array with n elements removed from the beginning. +ok 736 — Returns an array with n elements removed from the beginning. -# PASS test/gcd/gcd.test.js +# PASS test/indexOfAll.test.js -ok 732 — gcd is a Function -ok 733 — Calculates the greatest common divisor between two or more numbers/arrays -ok 734 — Calculates the greatest common divisor between two or more numbers/arrays +ok 737 — indexOfAll is a Function +ok 738 — Returns all indices of val in an array +ok 739 — When val is not found, return an empty array -# PASS test/extendHex/extendHex.test.js +# PASS test/extendHex.test.js -ok 735 — extendHex is a Function -ok 736 — Extends a 3-digit color code to a 6-digit color code -ok 737 — Extends a 3-digit color code to a 6-digit color code +ok 740 — extendHex is a Function +ok 741 — Extends a 3-digit color code to a 6-digit color code +ok 742 — Extends a 3-digit color code to a 6-digit color code -# PASS test/isTravisCI/isTravisCI.test.js - -ok 738 — isTravisCI is a Function -ok 739 — Running on Travis, correctly evaluates - -# PASS test/take/take.test.js - -ok 740 — take is a Function -ok 741 — Returns an array with n elements removed from the beginning. -ok 742 — Returns an array with n elements removed from the beginning. - -# PASS test/maxDate/maxDate.test.js +# PASS test/maxDate.test.js ok 743 — maxDate is a Function ok 744 — maxDate produces the maximum date -# PASS test/minDate/minDate.test.js +# PASS test/isPlainObject.test.js -ok 745 — minDate is a Function -ok 746 — minDate produces the maximum date +ok 745 — isPlainObject is a Function +ok 746 — Returns true for a plain object +ok 747 — Returns false for a Map (example of non-plain object) -# PASS test/chainAsync/chainAsync.test.js +# PASS test/intersectionBy.test.js -ok 747 — chainAsync is a Function -ok 748 — Calls all functions in an array +ok 748 — intersectionBy is a Function +ok 749 — Returns a list of elements that exist in both arrays, after applying the provided function to each array element of both -# PASS test/cleanObj/cleanObj.test.js +# PASS test/minDate.test.js -ok 749 — cleanObj is a Function -ok 750 — Removes any properties except the ones specified from a JSON object +ok 750 — minDate is a Function +ok 751 — minDate produces the maximum date -# PASS test/countBy/countBy.test.js +# PASS test/isTravisCI.test.js -ok 751 — countBy is a Function -ok 752 — Works for functions -ok 753 — Works for property names +ok 752 — isTravisCI is a Function +ok 753 — Running on Travis, correctly evaluates -# PASS test/overArgs/overArgs.test.js +# PASS test/getURLParameters.test.js -ok 754 — overArgs is a Function -ok 755 — Invokes the provided function with its arguments transformed +ok 754 — getURLParameters is a Function +ok 755 — Returns an object containing the parameters of the current URL -# PASS test/decapitalize/decapitalize.test.js +# PASS test/reduceSuccessive.test.js -ok 756 — decapitalize is a Function -ok 757 — Works with default parameter -ok 758 — Works with second parameter set to true +ok 756 — reduceSuccessive is a Function +ok 757 — Returns the array of successively reduced values -# PASS test/shallowClone/shallowClone.test.js +# PASS test/pipeFunctions.test.js -ok 759 — shallowClone is a Function -ok 760 — Shallow cloning works -ok 761 — Does not clone deeply +ok 758 — pipeFunctions is a Function +ok 759 — Performs left-to-right function composition -# PASS test/spreadOver/spreadOver.test.js +# PASS test/countBy.test.js -ok 762 — spreadOver is a Function -ok 763 — Takes a variadic function and returns a closure that accepts an array of arguments to map to the inputs of the function. +ok 760 — countBy is a Function +ok 761 — Works for functions +ok 762 — Works for property names -# PASS test/nthElement/nthElement.test.js +# PASS test/chainAsync.test.js -ok 764 — nthElement is a Function -ok 765 — Returns the nth element of an array. -ok 766 — Returns the nth element of an array. +ok 763 — chainAsync is a Function +ok 764 — Calls all functions in an array -# PASS test/hashNode/hashNode.test.js +# PASS test/cleanObj.test.js -ok 767 — hashNode is a Function -ok 768 — Produces the appropriate hash +ok 765 — cleanObj is a Function +ok 766 — Removes any properties except the ones specified from a JSON object -# PASS test/partialRight/partialRight.test.js +# PASS test/runPromisesInSeries.test.js -ok 769 — partialRight is a Function -ok 770 — Appends arguments +ok 767 — runPromisesInSeries is a Function +ok 768 — Runs promises in series -# PASS test/composeRight/composeRight.test.js +# PASS test/overArgs.test.js -ok 771 — composeRight is a Function -ok 772 — Performs left-to-right function composition +ok 769 — overArgs is a Function +ok 770 — Invokes the provided function with its arguments transformed -# PASS test/permutations/permutations.test.js +# PASS test/hashNode.test.js -ok 773 — permutations is a Function -ok 774 — Generates all permutations of an array +ok 771 — hashNode is a Function +ok 772 — Produces the appropriate hash -# PASS test/maxN/maxN.test.js +# PASS test/spreadOver.test.js -ok 775 — maxN is a Function -ok 776 — Returns the n maximum elements from the provided array -ok 777 — Returns the n maximum elements from the provided array +ok 773 — spreadOver is a Function +ok 774 — Takes a variadic function and returns a closure that accepts an array of arguments to map to the inputs of the function. -# PASS test/getDaysDiffBetweenDates/getDaysDiffBetweenDates.test.js +# PASS test/nthElement.test.js -ok 778 — getDaysDiffBetweenDates is a Function -ok 779 — Returns the difference in days between two dates +ok 775 — nthElement is a Function +ok 776 — Returns the nth element of an array. +ok 777 — Returns the nth element of an array. -# PASS test/minN/minN.test.js +# PASS test/decapitalize.test.js -ok 780 — minN is a Function -ok 781 — Returns the n minimum elements from the provided array +ok 778 — decapitalize is a Function +ok 779 — Works with default parameter +ok 780 — Works with second parameter set to true + +# PASS test/minN.test.js + +ok 781 — minN is a Function ok 782 — Returns the n minimum elements from the provided array +ok 783 — Returns the n minimum elements from the provided array -# PASS test/flatten/flatten.test.js +# PASS test/maxN.test.js -ok 783 — flatten is a Function -ok 784 — Flattens an array -ok 785 — Flattens an array +ok 784 — maxN is a Function +ok 785 — Returns the n maximum elements from the provided array +ok 786 — Returns the n maximum elements from the provided array -# PASS test/when/when.test.js +# PASS test/shallowClone.test.js -ok 786 — when is a Function -ok 787 — Returns the proper result -ok 788 — Returns the proper result +ok 787 — shallowClone is a Function +ok 788 — Shallow cloning works +ok 789 — Does not clone deeply -# PASS test/sortedLastIndexBy/sortedLastIndexBy.test.js +# PASS test/when.test.js -ok 789 — sortedLastIndexBy is a Function -ok 790 — Returns the highest index to insert the element without messing up the list order +ok 790 — when is a Function +ok 791 — Returns the proper result +ok 792 — Returns the proper result -# PASS test/compose/compose.test.js +# PASS test/flatten.test.js -ok 791 — compose is a Function -ok 792 — Performs right-to-left function composition +ok 793 — flatten is a Function +ok 794 — Flattens an array +ok 795 — Flattens an array -# PASS test/splitLines/splitLines.test.js +# PASS test/partialRight.test.js -ok 793 — splitLines is a Function -ok 794 — Splits a multiline string into an array of lines. +ok 796 — partialRight is a Function +ok 797 — Appends arguments -# PASS test/initializeArrayWithValues/initializeArrayWithValues.test.js +# PASS test/composeRight.test.js -ok 795 — initializeArrayWithValues is a Function -ok 796 — Initializes and fills an array with the specified values +ok 798 — composeRight is a Function +ok 799 — Performs left-to-right function composition -# PASS test/differenceWith/differenceWith.test.js +# PASS test/permutations.test.js -ok 797 — differenceWith is a Function -ok 798 — Filters out all values from an array +ok 800 — permutations is a Function +ok 801 — Generates all permutations of an array -# PASS test/percentile/percentile.test.js +# PASS test/compose.test.js -ok 799 — percentile is a Function -ok 800 — Uses the percentile formula to calculate how many numbers in the given array are less or equal to the given value. +ok 802 — compose is a Function +ok 803 — Performs right-to-left function composition -# PASS test/lcm/lcm.test.js +# PASS test/lcm.test.js -ok 801 — lcm is a Function -ok 802 — Returns the least common multiple of two or more numbers. -ok 803 — Returns the least common multiple of two or more numbers. +ok 804 — lcm is a Function +ok 805 — Returns the least common multiple of two or more numbers. +ok 806 — Returns the least common multiple of two or more numbers. -# PASS test/bindAll/bindAll.test.js +# PASS test/splitLines.test.js -ok 804 — bindAll is a Function -ok 805 — Binds to an object context +ok 807 — splitLines is a Function +ok 808 — Splits a multiline string into an array of lines. -# PASS test/mapValues/mapValues.test.js +# PASS test/bindAll.test.js -ok 806 — mapValues is a Function -ok 807 — Maps values +ok 809 — bindAll is a Function +ok 810 — Binds to an object context -# PASS test/partial/partial.test.js +# PASS test/percentile.test.js -ok 808 — partial is a Function -ok 809 — Prepends arguments +ok 811 — percentile is a Function +ok 812 — Uses the percentile formula to calculate how many numbers in the given array are less or equal to the given value. -# PASS test/unionWith/unionWith.test.js +# PASS test/sortedLastIndexBy.test.js -ok 810 — unionWith is a Function -ok 811 — Produces the appropriate results +ok 813 — sortedLastIndexBy is a Function +ok 814 — Returns the highest index to insert the element without messing up the list order -# PASS test/palindrome/palindrome.test.js +# PASS test/getDaysDiffBetweenDates.test.js -ok 812 — palindrome is a Function -ok 813 — Given string is a palindrome -ok 814 — Given string is not a palindrome +ok 815 — getDaysDiffBetweenDates is a Function +ok 816 — Returns the difference in days between two dates -# PASS test/degreesToRads/degreesToRads.test.js +# PASS test/differenceWith.test.js -ok 815 — degreesToRads is a Function -ok 816 — Returns the appropriate value +ok 817 — differenceWith is a Function +ok 818 — Filters out all values from an array -# PASS test/bifurcateBy/bifurcateBy.test.js +# PASS test/partial.test.js -ok 817 — bifurcateBy is a Function -ok 818 — Splits the collection into two groups +ok 819 — partial is a Function +ok 820 — Prepends arguments -# PASS test/size/size.test.js +# PASS test/size.test.js -ok 819 — size is a Function -ok 820 — Get size of arrays, objects or strings. -ok 821 — Get size of arrays, objects or strings. +ok 821 — size is a Function +ok 822 — Get size of arrays, objects or strings. +ok 823 — Get size of arrays, objects or strings. -# PASS test/bifurcate/bifurcate.test.js +# PASS test/mapValues.test.js -ok 822 — bifurcate is a Function -ok 823 — Splits the collection into two groups +ok 824 — mapValues is a Function +ok 825 — Maps values -# PASS test/median/median.test.js +# PASS test/unionWith.test.js -ok 824 — median is a Function -ok 825 — Returns the median of an array of numbers -ok 826 — Returns the median of an array of numbers +ok 826 — unionWith is a Function +ok 827 — Produces the appropriate results -# PASS test/forOwnRight/forOwnRight.test.js +# PASS test/median.test.js -ok 827 — forOwnRight is a Function -ok 828 — Iterates over an element's key-value pairs in reverse +ok 828 — median is a Function +ok 829 — Returns the median of an array of numbers +ok 830 — Returns the median of an array of numbers -# PASS test/sortedIndexBy/sortedIndexBy.test.js +# PASS test/palindrome.test.js -ok 829 — sortedIndexBy is a Function -ok 830 — Returns the lowest index to insert the element without messing up the list order +ok 831 — palindrome is a Function +ok 832 — Given string is a palindrome +ok 833 — Given string is not a palindrome -# PASS test/dropRightWhile/dropRightWhile.test.js +# PASS test/bifurcateBy.test.js -ok 831 — dropRightWhile is a Function -ok 832 — Removes elements from the end of an array until the passed function returns true. +ok 834 — bifurcateBy is a Function +ok 835 — Splits the collection into two groups -# PASS test/attempt/attempt.test.js +# PASS test/bifurcate.test.js -ok 833 — attempt is a Function -ok 834 — Returns a value -ok 835 — Returns an error +ok 836 — bifurcate is a Function +ok 837 — Splits the collection into two groups -# PASS test/sortedLastIndex/sortedLastIndex.test.js +# PASS test/initializeArrayWithValues.test.js -ok 836 — sortedLastIndex is a Function -ok 837 — Returns the highest index to insert the element without messing up the list order +ok 838 — initializeArrayWithValues is a Function +ok 839 — Initializes and fills an array with the specified values -# PASS test/rearg/rearg.test.js +# PASS test/attempt.test.js -ok 838 — rearg is a Function -ok 839 — Reorders arguments in invoked function +ok 840 — attempt is a Function +ok 841 — Returns a value +ok 842 — Returns an error -# PASS test/unescapeHTML/unescapeHTML.test.js +# PASS test/degreesToRads.test.js -ok 840 — unescapeHTML is a Function -ok 841 — Unescapes escaped HTML characters. +ok 843 — degreesToRads is a Function +ok 844 — Returns the appropriate value -# PASS test/pickBy/pickBy.test.js +# PASS test/rearg.test.js -ok 842 — pickBy is a Function -ok 843 — Creates an object composed of the properties the given function returns truthy for. +ok 845 — rearg is a Function +ok 846 — Reorders arguments in invoked function -# PASS test/isFunction/isFunction.test.js +# PASS test/forOwnRight.test.js -ok 844 — isFunction is a Function -ok 845 — passed value is a function -ok 846 — passed value is not a function +ok 847 — forOwnRight is a Function +ok 848 — Iterates over an element's key-value pairs in reverse -# PASS test/flip/flip.test.js +# PASS test/pickBy.test.js -ok 847 — flip is a Function -ok 848 — Flips argument order +ok 849 — pickBy is a Function +ok 850 — Creates an object composed of the properties the given function returns truthy for. -# PASS test/sortCharactersInString/sortCharactersInString.test.js +# PASS test/flip.test.js -ok 849 — sortCharactersInString is a Function -ok 850 — Alphabetically sorts the characters in a string. +ok 851 — flip is a Function +ok 852 — Flips argument order -# PASS test/compact/compact.test.js +# PASS test/sortedIndexBy.test.js -ok 851 — compact is a Function -ok 852 — Removes falsey values from an array +ok 853 — sortedIndexBy is a Function +ok 854 — Returns the lowest index to insert the element without messing up the list order -# PASS test/omitBy/omitBy.test.js +# PASS test/dropRightWhile.test.js -ok 853 — omitBy is a Function -ok 854 — Creates an object composed of the properties the given function returns falsey for +ok 855 — dropRightWhile is a Function +ok 856 — Removes elements from the end of an array until the passed function returns true. -# PASS test/isBoolean/isBoolean.test.js +# PASS test/get.test.js -ok 855 — isBoolean is a Function -ok 856 — passed value is not a boolean -ok 857 — passed value is not a boolean +ok 857 — get is a Function +ok 858 — Retrieve a property indicated by the selector from an object. -# PASS test/pullBy/pullBy.test.js +# PASS test/omitBy.test.js -ok 858 — pullBy is a Function -ok 859 — Pulls the specified values +ok 859 — omitBy is a Function +ok 860 — Creates an object composed of the properties the given function returns falsey for -# PASS test/get/get.test.js +# PASS test/compact.test.js -ok 860 — get is a Function -ok 861 — Retrieve a property indicated by the selector from an object. +ok 861 — compact is a Function +ok 862 — Removes falsey values from an array -# PASS test/unflattenObject/unflattenObject.test.js +# PASS test/unescapeHTML.test.js -ok 862 — unflattenObject is a Function -ok 863 — Unflattens an object with the paths for keys +ok 863 — unescapeHTML is a Function +ok 864 — Unescapes escaped HTML characters. -# PASS test/initialize2DArray/initialize2DArray.test.js +# PASS test/isFunction.test.js -ok 864 — initialize2DArray is a Function -ok 865 — Initializes a 2D array of given width and height and value +ok 865 — isFunction is a Function +ok 866 — passed value is a function +ok 867 — passed value is not a function -# PASS test/escapeHTML/escapeHTML.test.js +# PASS test/pullBy.test.js -ok 866 — escapeHTML is a Function -ok 867 — Escapes a string for use in HTML +ok 868 — pullBy is a Function +ok 869 — Pulls the specified values -# PASS test/stableSort/stableSort.test.js +# PASS test/sortedLastIndex.test.js -ok 868 — stableSort is a Function -ok 869 — Array is properly sorted +ok 870 — sortedLastIndex is a Function +ok 871 — Returns the highest index to insert the element without messing up the list order -# PASS test/isNumber/isNumber.test.js +# PASS test/isBoolean.test.js -ok 870 — isNumber is a Function -ok 871 — passed argument is a number -ok 872 — passed argument is not a number +ok 872 — isBoolean is a Function +ok 873 — passed value is not a boolean +ok 874 — passed value is not a boolean -# PASS test/objectFromPairs/objectFromPairs.test.js +# PASS test/escapeHTML.test.js -ok 873 — objectFromPairs is a Function -ok 874 — Creates an object from the given key-value pairs. +ok 875 — escapeHTML is a Function +ok 876 — Escapes a string for use in HTML -# PASS test/forEachRight/forEachRight.test.js +# PASS test/stableSort.test.js -ok 875 — forEachRight is a Function -ok 876 — Iterates over the array in reverse +ok 877 — stableSort is a Function +ok 878 — Array is properly sorted -# PASS test/stripHTMLTags/stripHTMLTags.test.js - -ok 877 — stripHTMLTags is a Function -ok 878 — Removes HTML tags - -# PASS test/xProd/xProd.test.js +# PASS test/xProd.test.js ok 879 — xProd is a Function ok 880 — xProd([1, 2], ['a', 'b']) returns [[1, 'a'], [1, 'b'], [2, 'a'], [2, 'b']] -# PASS test/objectToPairs/objectToPairs.test.js +# PASS test/isNumber.test.js -ok 881 — objectToPairs is a Function -ok 882 — Creates an array of key-value pair arrays from an object. +ok 881 — isNumber is a Function +ok 882 — passed argument is a number +ok 883 — passed argument is not a number -# PASS test/toDecimalMark/toDecimalMark.test.js +# PASS test/unflattenObject.test.js -ok 883 — toDecimalMark is a Function -ok 884 — convert a float-point arithmetic to the Decimal mark form +ok 884 — unflattenObject is a Function +ok 885 — Unflattens an object with the paths for keys -# PASS test/isArray/isArray.test.js +# PASS test/sortCharactersInString.test.js -ok 885 — isArray is a Function -ok 886 — passed value is an array -ok 887 — passed value is not an array +ok 886 — sortCharactersInString is a Function +ok 887 — Alphabetically sorts the characters in a string. -# PASS test/unfold/unfold.test.js +# PASS test/initialize2DArray.test.js -ok 888 — unfold is a Function -ok 889 — Works with a given function, producing an array +ok 888 — initialize2DArray is a Function +ok 889 — Initializes a 2D array of given width and height and value -# PASS test/findLastIndex/findLastIndex.test.js +# PASS test/unfold.test.js -ok 890 — findLastIndex is a Function -ok 891 — Finds last index for which the given function returns true +ok 890 — unfold is a Function +ok 891 — Works with a given function, producing an array -# PASS test/filterNonUnique/filterNonUnique.test.js +# PASS test/ary.test.js -ok 892 — filterNonUnique is a Function -ok 893 — Filters out the non-unique values in an array +ok 892 — ary is a Function +ok 893 — Discards arguments with index >=n -# PASS test/ary/ary.test.js +# PASS test/forEachRight.test.js -ok 894 — ary is a Function -ok 895 — Discards arguments with index >=n +ok 894 — forEachRight is a Function +ok 895 — Iterates over the array in reverse -# PASS test/takeRightWhile/takeRightWhile.test.js +# PASS test/stripHTMLTags.test.js -ok 896 — takeRightWhile is a Function -ok 897 — Removes elements until the function returns true +ok 896 — stripHTMLTags is a Function +ok 897 — Removes HTML tags -# PASS test/forOwn/forOwn.test.js +# PASS test/objectToPairs.test.js -ok 898 — forOwn is a Function -ok 899 — Iterates over an element's key-value pairs +ok 898 — objectToPairs is a Function +ok 899 — Creates an array of key-value pair arrays from an object. -# PASS test/countOccurrences/countOccurrences.test.js +# PASS test/objectFromPairs.test.js -ok 900 — countOccurrences is a Function -ok 901 — Counts the occurrences of a value in an array +ok 900 — objectFromPairs is a Function +ok 901 — Creates an object from the given key-value pairs. -# PASS test/curry/curry.test.js +# PASS test/forOwn.test.js -ok 902 — curry is a Function -ok 903 — curries a Math.pow -ok 904 — curries a Math.min +ok 902 — forOwn is a Function +ok 903 — Iterates over an element's key-value pairs -# PASS test/removeNonASCII/removeNonASCII.test.js +# PASS test/curry.test.js -ok 905 — removeNonASCII is a Function -ok 906 — Removes non-ASCII characters +ok 904 — curry is a Function +ok 905 — curries a Math.pow +ok 906 — curries a Math.min -# PASS test/dropWhile/dropWhile.test.js +# PASS test/toDecimalMark.test.js -ok 907 — dropWhile is a Function -ok 908 — Removes elements in an array until the passed function returns true. +ok 907 — toDecimalMark is a Function +ok 908 — convert a float-point arithmetic to the Decimal mark form -# PASS test/isNull/isNull.test.js +# PASS test/findLastIndex.test.js -ok 909 — isNull is a Function -ok 910 — passed argument is a null -ok 911 — passed argument is a null +ok 909 — findLastIndex is a Function +ok 910 — Finds last index for which the given function returns true -# PASS test/pick/pick.test.js +# PASS test/isNull.test.js -ok 912 — pick is a Function -ok 913 — Picks the key-value pairs corresponding to the given keys from an object. +ok 911 — isNull is a Function +ok 912 — passed argument is a null +ok 913 — passed argument is a null -# PASS test/truncateString/truncateString.test.js +# PASS test/pick.test.js -ok 914 — truncateString is a Function -ok 915 — Truncates a "boomerang" up to a specified length. +ok 914 — pick is a Function +ok 915 — Picks the key-value pairs corresponding to the given keys from an object. -# PASS test/remove/remove.test.js +# PASS test/dropWhile.test.js -ok 916 — remove is a Function -ok 917 — Removes elements from an array for which the given function returns false +ok 916 — dropWhile is a Function +ok 917 — Removes elements in an array until the passed function returns true. -# PASS test/defaults/defaults.test.js +# PASS test/filterNonUnique.test.js -ok 918 — defaults is a Function -ok 919 — Assigns default values for undefined properties +ok 918 — filterNonUnique is a Function +ok 919 — Filters out the non-unique values in an array -# PASS test/clampNumber/clampNumber.test.js +# PASS test/atob.test.js -ok 920 — clampNumber is a Function -ok 921 — Clamps num within the inclusive range specified by the boundary values a and b +ok 920 — atob is a Function +ok 921 — atob("Zm9vYmFy") equals "foobar" +ok 922 — atob("Z") returns "" -# PASS test/delay/delay.test.js +# PASS test/takeRightWhile.test.js -ok 922 — delay is a Function -ok 923 — Works as expecting, passing arguments properly +ok 923 — takeRightWhile is a Function +ok 924 — Removes elements until the function returns true -# PASS test/intersection/intersection.test.js +# PASS test/delay.test.js -ok 924 — intersection is a Function -ok 925 — Returns a list of elements that exist in both arrays +ok 925 — delay is a Function +ok 926 — Works as expecting, passing arguments properly -# PASS test/atob/atob.test.js +# PASS test/removeNonASCII.test.js -ok 926 — atob is a Function -ok 927 — atob("Zm9vYmFy") equals "foobar" -ok 928 — atob("Z") returns "" +ok 927 — removeNonASCII is a Function +ok 928 — Removes non-ASCII characters -# PASS test/parseCookie/parseCookie.test.js +# PASS test/remove.test.js -ok 929 — parseCookie is a Function -ok 930 — Parses the cookie +ok 929 — remove is a Function +ok 930 — Removes elements from an array for which the given function returns false -# PASS test/omit/omit.test.js +# PASS test/omit.test.js ok 931 — omit is a Function ok 932 — Omits the key-value pairs corresponding to the given keys from an object -# PASS test/similarity/similarity.test.js +# PASS test/defaults.test.js -ok 933 — similarity is a Function -ok 934 — Returns an array of elements that appear in both arrays. +ok 933 — defaults is a Function +ok 934 — Assigns default values for undefined properties -# PASS test/over/over.test.js +# PASS test/countOccurrences.test.js -ok 935 — over is a Function -ok 936 — Applies given functions over multiple arguments +ok 935 — countOccurrences is a Function +ok 936 — Counts the occurrences of a value in an array -# PASS test/pull/pull.test.js +# PASS test/clampNumber.test.js -ok 937 — pull is a Function -ok 938 — Pulls the specified values +ok 937 — clampNumber is a Function +ok 938 — Clamps num within the inclusive range specified by the boundary values a and b -# PASS test/findLast/findLast.test.js +# PASS test/intersection.test.js -ok 939 — findLast is a Function -ok 940 — Finds last element for which the given function returns true +ok 939 — intersection is a Function +ok 940 — Returns a list of elements that exist in both arrays -# PASS test/isEven/isEven.test.js +# PASS test/parseCookie.test.js -ok 941 — isEven is a Function -ok 942 — 4 is even number -ok 943 — 5 is not an even number +ok 941 — parseCookie is a Function +ok 942 — Parses the cookie -# PASS test/cloneRegExp/cloneRegExp.test.js +# PASS test/over.test.js -ok 944 — cloneRegExp is a Function -ok 945 — Clones regular expressions properly +ok 943 — over is a Function +ok 944 — Applies given functions over multiple arguments -# PASS test/takeWhile/takeWhile.test.js +# PASS test/truncateString.test.js -ok 946 — takeWhile is a Function -ok 947 — Removes elements until the function returns true +ok 945 — truncateString is a Function +ok 946 — Truncates a "boomerang" up to a specified length. -# PASS test/escapeRegExp/escapeRegExp.test.js +# PASS test/pull.test.js -ok 948 — escapeRegExp is a Function -ok 949 — Escapes a string to use in a regular expression +ok 947 — pull is a Function +ok 948 — Pulls the specified values -# PASS test/coalesce/coalesce.test.js +# PASS test/similarity.test.js -ok 950 — coalesce is a Function -ok 951 — Returns the first non-null/undefined argument +ok 949 — similarity is a Function +ok 950 — Returns an array of elements that appear in both arrays. -# PASS test/times/times.test.js +# PASS test/isEven.test.js -ok 952 — times is a Function -ok 953 — Runs a function the specified amount of times +ok 951 — isEven is a Function +ok 952 — 4 is even number +ok 953 — 5 is not an even number -# PASS test/fibonacci/fibonacci.test.js +# PASS test/findLast.test.js -ok 954 — fibonacci is a Function -ok 955 — Generates an array, containing the Fibonacci sequence +ok 954 — findLast is a Function +ok 955 — Finds last element for which the given function returns true -# PASS test/powerset/powerset.test.js +# PASS test/takeWhile.test.js -ok 956 — powerset is a Function -ok 957 — Returns the powerset of a given array of numbers. +ok 956 — takeWhile is a Function +ok 957 — Removes elements until the function returns true -# PASS test/hammingDistance/hammingDistance.test.js +# PASS test/times.test.js -ok 958 — hammingDistance is a Function -ok 959 — retuns hamming disance between 2 values +ok 958 — times is a Function +ok 959 — Runs a function the specified amount of times -# PASS test/primes/primes.test.js +# PASS test/cloneRegExp.test.js -ok 960 — primes is a Function -ok 961 — Generates primes up to a given number, using the Sieve of Eratosthenes. +ok 960 — cloneRegExp is a Function +ok 961 — Clones regular expressions properly -# PASS test/distance/distance.test.js +# PASS test/escapeRegExp.test.js -ok 962 — distance is a Function -ok 963 — Calculates the distance between two points +ok 962 — escapeRegExp is a Function +ok 963 — Escapes a string to use in a regular expression -# PASS test/difference/difference.test.js +# PASS test/coalesce.test.js -ok 964 — difference is a Function -ok 965 — Returns the difference between two arrays +ok 964 — coalesce is a Function +ok 965 — Returns the first non-null/undefined argument -# PASS test/tail/tail.test.js +# PASS test/tail.test.js ok 966 — tail is a Function ok 967 — Returns tail ok 968 — Returns tail -# PASS test/serializeCookie/serializeCookie.test.js +# PASS test/powerset.test.js -ok 969 — serializeCookie is a Function -ok 970 — Serializes the cookie +ok 969 — powerset is a Function +ok 970 — Returns the powerset of a given array of numbers. -# PASS test/deepFlatten/deepFlatten.test.js +# PASS test/primes.test.js -ok 971 — deepFlatten is a Function -ok 972 — Deep flattens an array +ok 971 — primes is a Function +ok 972 — Generates primes up to a given number, using the Sieve of Eratosthenes. -# PASS test/RGBToHex/RGBToHex.test.js +# PASS test/fibonacci.test.js -ok 973 — RGBToHex is a Function -ok 974 — Converts the values of RGB components to a color code. +ok 973 — fibonacci is a Function +ok 974 — Generates an array, containing the Fibonacci sequence -# PASS test/negate/negate.test.js +# PASS test/distance.test.js -ok 975 — negate is a Function -ok 976 — Negates a predicate function +ok 975 — distance is a Function +ok 976 — Calculates the distance between two points -# PASS test/everyNth/everyNth.test.js +# PASS test/negate.test.js -ok 977 — everyNth is a Function -ok 978 — Returns every nth element in an array +ok 977 — negate is a Function +ok 978 — Negates a predicate function -# PASS test/initial/initial.test.js +# PASS test/difference.test.js -ok 979 — initial is a Function -ok 980 — Returns all the elements of an array except the last one +ok 979 — difference is a Function +ok 980 — Returns the difference between two arrays -# PASS test/unionBy/unionBy.test.js +# PASS test/deepFlatten.test.js -ok 981 — unionBy is a Function -ok 982 — Produces the appropriate results +ok 981 — deepFlatten is a Function +ok 982 — Deep flattens an array -# PASS test/radsToDegrees/radsToDegrees.test.js +# PASS test/RGBToHex.test.js -ok 983 — radsToDegrees is a Function -ok 984 — Returns the appropriate value +ok 983 — RGBToHex is a Function +ok 984 — Converts the values of RGB components to a color code. -# PASS test/sleep/sleep.test.js +# PASS test/hammingDistance.test.js -ok 985 — sleep is a Function -ok 986 — Works as expected +ok 985 — hammingDistance is a Function +ok 986 — retuns hamming disance between 2 values -# PASS test/unary/unary.test.js +# PASS test/unionBy.test.js -ok 987 — unary is a Function -ok 988 — Discards arguments after the first one +ok 987 — unionBy is a Function +ok 988 — Produces the appropriate results -# PASS test/mapKeys/mapKeys.test.js +# PASS test/everyNth.test.js -ok 989 — mapKeys is a Function -ok 990 — Maps keys +ok 989 — everyNth is a Function +ok 990 — Returns every nth element in an array -# PASS test/reverseString/reverseString.test.js +# PASS test/serializeCookie.test.js -ok 991 — reverseString is a Function -ok 992 — Reverses a string. +ok 991 — serializeCookie is a Function +ok 992 — Serializes the cookie -# PASS test/isSymbol/isSymbol.test.js +# PASS test/initial.test.js -ok 993 — isSymbol is a Function -ok 994 — Checks if the given argument is a symbol +ok 993 — initial is a Function +ok 994 — Returns all the elements of an array except the last one -# PASS test/isUndefined/isUndefined.test.js +# PASS test/unary.test.js -ok 995 — isUndefined is a Function -ok 996 — Returns true for undefined +ok 995 — unary is a Function +ok 996 — Discards arguments after the first one -# PASS test/isDivisible/isDivisible.test.js +# PASS test/sleep.test.js -ok 997 — isDivisible is a Function -ok 998 — The number 6 is divisible by 3 +ok 997 — sleep is a Function +ok 998 — Works as expected -# PASS test/digitize/digitize.test.js +# PASS test/mapKeys.test.js -ok 999 — digitize is a Function -ok 1000 — Converts a number to an array of digits +ok 999 — mapKeys is a Function +ok 1000 — Maps keys -# PASS test/getType/getType.test.js +# PASS test/radsToDegrees.test.js -ok 1001 — getType is a Function -ok 1002 — Returns the native type of a value +ok 1001 — radsToDegrees is a Function +ok 1002 — Returns the appropriate value -# PASS test/call/call.test.js +# PASS test/isSymbol.test.js -ok 1003 — call is a Function -ok 1004 — Calls function on given object +ok 1003 — isSymbol is a Function +ok 1004 — Checks if the given argument is a symbol -# PASS test/debounce/debounce.test.js +# PASS test/call.test.js -ok 1005 — debounce is a Function -ok 1006 — Works as expected +ok 1005 — call is a Function +ok 1006 — Calls function on given object -# PASS test/sdbm/sdbm.test.js +# PASS test/reverseString.test.js -ok 1007 — sdbm is a Function -ok 1008 — Hashes the input string into a whole number. +ok 1007 — reverseString is a Function +ok 1008 — Reverses a string. -# PASS test/sum/sum.test.js +# PASS test/digitize.test.js -ok 1009 — sum is a Function -ok 1010 — Returns the sum of two or more numbers/arrays. +ok 1009 — digitize is a Function +ok 1010 — Converts a number to an array of digits -# PASS test/initializeArrayWithRangeRight/initializeArrayWithRangeRight.test.js +# PASS test/isUndefined.test.js -ok 1011 — initializeArrayWithRangeRight is a Function +ok 1011 — isUndefined is a Function +ok 1012 — Returns true for undefined -# PASS test/btoa/btoa.test.js +# PASS test/getType.test.js -ok 1012 — btoa is a Function -ok 1013 — btoa("foobar") equals "Zm9vYmFy" +ok 1013 — getType is a Function +ok 1014 — Returns the native type of a value -# PASS test/isPrime/isPrime.test.js +# PASS test/isDivisible.test.js -ok 1014 — isPrime is a Function -ok 1015 — passed number is a prime +ok 1015 — isDivisible is a Function +ok 1016 — The number 6 is divisible by 3 -# PASS test/elementIsVisibleInViewport/elementIsVisibleInViewport.test.js +# PASS test/sdbm.test.js -ok 1016 — elementIsVisibleInViewport is a Function +ok 1017 — sdbm is a Function +ok 1018 — Hashes the input string into a whole number. -# PASS test/getMeridiemSuffixOfInteger/getMeridiemSuffixOfInteger.test.js +# PASS test/mphToKmph.test.js -ok 1017 — getMeridiemSuffixOfInteger is a Function +ok 1019 — mphToKmph is a Function +ok 1020 — Returns kph from mph. -# PASS test/fibonacciCountUntilNum/fibonacciCountUntilNum.test.js +# PASS test/debounce.test.js -ok 1018 — fibonacciCountUntilNum is a Function +ok 1021 — debounce is a Function +ok 1022 — Works as expected -# PASS test/recordAnimationFrames/recordAnimationFrames.test.js +# PASS test/sum.test.js -ok 1019 — recordAnimationFrames is a Function +ok 1023 — sum is a Function +ok 1024 — Returns the sum of two or more numbers/arrays. -# PASS test/getColonTimeFromDate/getColonTimeFromDate.test.js +# PASS test/kmphToMph.test.js -ok 1020 — getColonTimeFromDate is a Function +ok 1025 — kmphToMph is a Function +ok 1026 — Returns mph from kph. -# PASS test/UUIDGeneratorBrowser/UUIDGeneratorBrowser.test.js +# PASS test/btoa.test.js -ok 1021 — UUIDGeneratorBrowser is a Function +ok 1027 — btoa is a Function +ok 1028 — btoa("foobar") equals "Zm9vYmFy" -# PASS test/levenshteinDistance/levenshteinDistance.test.js +# PASS test/isPrime.test.js -ok 1022 — levenshteinDistance is a Function +ok 1029 — isPrime is a Function +ok 1030 — passed number is a prime -# PASS test/isBrowserTabFocused/isBrowserTabFocused.test.js +# PASS test/initializeArrayWithRangeRight.test.js -ok 1023 — isBrowserTabFocused is a Function +ok 1031 — initializeArrayWithRangeRight is a Function -# PASS test/onUserInputChange/onUserInputChange.test.js +# PASS test/elementIsVisibleInViewport.test.js -ok 1024 — onUserInputChange is a Function +ok 1032 — elementIsVisibleInViewport is a Function -# PASS test/fibonacciUntilNum/fibonacciUntilNum.test.js +# PASS test/getMeridiemSuffixOfInteger.test.js -ok 1025 — fibonacciUntilNum is a Function +ok 1033 — getMeridiemSuffixOfInteger is a Function -# PASS test/getScrollPosition/getScrollPosition.test.js +# PASS test/fibonacciCountUntilNum.test.js -ok 1026 — getScrollPosition is a Function +ok 1034 — fibonacciCountUntilNum is a Function -# PASS test/isArmstrongNumber/isArmstrongNumber.test.js +# PASS test/recordAnimationFrames.test.js -ok 1027 — isArmstrongNumber is a Function +ok 1035 — recordAnimationFrames is a Function -# PASS test/initializeNDArray/initializeNDArray.test.js +# PASS test/UUIDGeneratorBrowser.test.js -ok 1028 — initializeNDArray is a Function +ok 1036 — UUIDGeneratorBrowser is a Function -# PASS test/observeMutations/observeMutations.test.js +# PASS test/getColonTimeFromDate.test.js -ok 1029 — observeMutations is a Function +ok 1037 — getColonTimeFromDate is a Function -# PASS test/detectDeviceType/detectDeviceType.test.js +# PASS test/levenshteinDistance.test.js -ok 1030 — detectDeviceType is a Function +ok 1038 — levenshteinDistance is a Function -# PASS test/nodeListToArray/nodeListToArray.test.js +# PASS test/isBrowserTabFocused.test.js -ok 1031 — nodeListToArray is a Function +ok 1039 — isBrowserTabFocused is a Function -# PASS test/arrayToHtmlList/arrayToHtmlList.test.js +# PASS test/getScrollPosition.test.js -ok 1032 — arrayToHtmlList is a Function +ok 1040 — getScrollPosition is a Function -# PASS test/elementContains/elementContains.test.js +# PASS test/fibonacciUntilNum.test.js -ok 1033 — elementContains is a Function +ok 1041 — fibonacciUntilNum is a Function -# PASS test/speechSynthesis/speechSynthesis.test.js +# PASS test/isArmstrongNumber.test.js -ok 1034 — speechSynthesis is a Function +ok 1042 — isArmstrongNumber is a Function -# PASS test/copyToClipboard/copyToClipboard.test.js +# PASS test/initializeNDArray.test.js -ok 1035 — copyToClipboard is a Function +ok 1043 — initializeNDArray is a Function -# PASS test/mostPerformant/mostPerformant.test.js +# PASS test/onUserInputChange.test.js -ok 1036 — mostPerformant is a Function +ok 1044 — onUserInputChange is a Function -# PASS test/createEventHub/createEventHub.test.js +# PASS test/observeMutations.test.js -ok 1037 — createEventHub is a Function +ok 1045 — observeMutations is a Function -# PASS test/readFileLines/readFileLines.test.js +# PASS test/detectDeviceType.test.js -ok 1038 — readFileLines is a Function +ok 1046 — detectDeviceType is a Function -# PASS test/createElement/createElement.test.js +# PASS test/copyToClipboard.test.js -ok 1039 — createElement is a Function +ok 1047 — copyToClipboard is a Function -# PASS test/httpsRedirect/httpsRedirect.test.js +# PASS test/speechSynthesis.test.js -ok 1040 — httpsRedirect is a Function +ok 1048 — speechSynthesis is a Function -# PASS test/isArrayBuffer/isArrayBuffer.test.js +# PASS test/elementContains.test.js -ok 1041 — isArrayBuffer is a Function +ok 1049 — elementContains is a Function -# PASS test/bottomVisible/bottomVisible.test.js +# PASS test/arrayToHtmlList.test.js -ok 1042 — bottomVisible is a Function +ok 1050 — arrayToHtmlList is a Function -# PASS test/smoothScroll/smoothScroll.test.js +# PASS test/nodeListToArray.test.js -ok 1043 — smoothScroll is a Function +ok 1051 — nodeListToArray is a Function -# PASS test/howManyTimes/howManyTimes.test.js +# PASS test/createEventHub.test.js -ok 1044 — howManyTimes is a Function +ok 1052 — createEventHub is a Function -# PASS test/insertBefore/insertBefore.test.js +# PASS test/mostPerformant.test.js -ok 1045 — insertBefore is a Function +ok 1053 — mostPerformant is a Function -# PASS test/removeVowels/removeVowels.test.js +# PASS test/httpsRedirect.test.js -ok 1046 — removeVowels is a Function +ok 1054 — httpsRedirect is a Function -# PASS test/triggerEvent/triggerEvent.test.js +# PASS test/createElement.test.js -ok 1047 — triggerEvent is a Function +ok 1055 — createElement is a Function -# PASS test/isTypedArray/isTypedArray.test.js +# PASS test/bottomVisible.test.js -ok 1048 — isTypedArray is a Function +ok 1056 — bottomVisible is a Function -# PASS test/countVowels/countVowels.test.js +# PASS test/readFileLines.test.js -ok 1049 — countVowels is a Function +ok 1057 — readFileLines is a Function -# PASS test/hashBrowser/hashBrowser.test.js +# PASS test/smoothScroll.test.js -ok 1050 — hashBrowser is a Function +ok 1058 — smoothScroll is a Function -# PASS test/insertAfter/insertAfter.test.js +# PASS test/triggerEvent.test.js -ok 1051 — insertAfter is a Function +ok 1059 — triggerEvent is a Function -# PASS test/toggleClass/toggleClass.test.js +# PASS test/removeVowels.test.js -ok 1052 — toggleClass is a Function +ok 1060 — removeVowels is a Function -# PASS test/scrollToTop/scrollToTop.test.js +# PASS test/insertBefore.test.js -ok 1053 — scrollToTop is a Function +ok 1061 — insertBefore is a Function -# PASS test/currentURL/currentURL.test.js +# PASS test/howManyTimes.test.js -ok 1054 — currentURL is a Function +ok 1062 — howManyTimes is a Function -# PASS test/httpDelete/httpDelete.test.js +# PASS test/insertAfter.test.js -ok 1055 — httpDelete is a Function +ok 1063 — insertAfter is a Function -# PASS test/JSONToDate/JSONToDate.test.js +# PASS test/hashBrowser.test.js -ok 1056 — JSONToDate is a Function +ok 1064 — hashBrowser is a Function -# PASS test/JSONToFile/JSONToFile.test.js +# PASS test/scrollToTop.test.js -ok 1057 — JSONToFile is a Function +ok 1065 — scrollToTop is a Function -# PASS test/isSimilar/isSimilar.test.js +# PASS test/toggleClass.test.js -ok 1058 — isSimilar is a Function +ok 1066 — toggleClass is a Function -# PASS test/isBrowser/isBrowser.test.js +# PASS test/countVowels.test.js -ok 1059 — isBrowser is a Function +ok 1067 — countVowels is a Function -# PASS test/dayOfYear/dayOfYear.test.js +# PASS test/currentURL.test.js -ok 1060 — dayOfYear is a Function +ok 1068 — currentURL is a Function -# PASS test/isWeakMap/isWeakMap.test.js +# PASS test/JSONToDate.test.js -ok 1061 — isWeakMap is a Function +ok 1069 — JSONToDate is a Function -# PASS test/heronArea/heronArea.test.js +# PASS test/JSONToFile.test.js -ok 1062 — heronArea is a Function +ok 1070 — JSONToFile is a Function -# PASS test/isWeakSet/isWeakSet.test.js +# PASS test/httpDelete.test.js -ok 1063 — isWeakSet is a Function +ok 1071 — httpDelete is a Function -# PASS test/timeTaken/timeTaken.test.js +# PASS test/isSimilar.test.js -ok 1064 — timeTaken is a Function +ok 1072 — isSimilar is a Function -# PASS test/solveRPN/solveRPN.test.js +# PASS test/heronArea.test.js -ok 1065 — solveRPN is a Function +ok 1073 — heronArea is a Function -# PASS test/isRegExp/isRegExp.test.js +# PASS test/timeTaken.test.js -ok 1066 — isRegExp is a Function +ok 1074 — timeTaken is a Function -# PASS test/colorize/colorize.test.js +# PASS test/squareSum.test.js -ok 1067 — colorize is a Function +ok 1075 — squareSum is a Function -# PASS test/runAsync/runAsync.test.js +# PASS test/dayOfYear.test.js -ok 1068 — runAsync is a Function +ok 1076 — dayOfYear is a Function -# PASS test/hasFlags/hasFlags.test.js +# PASS test/isBrowser.test.js -ok 1069 — hasFlags is a Function +ok 1077 — isBrowser is a Function -# PASS test/httpPost/httpPost.test.js +# PASS test/runAsync.test.js -ok 1070 — httpPost is a Function +ok 1078 — runAsync is a Function -# PASS test/throttle/throttle.test.js +# PASS test/hasClass.test.js -ok 1071 — throttle is a Function +ok 1079 — hasClass is a Function -# PASS test/hasClass/hasClass.test.js +# PASS test/setStyle.test.js -ok 1072 — hasClass is a Function +ok 1080 — setStyle is a Function -# PASS test/redirect/redirect.test.js +# PASS test/throttle.test.js -ok 1073 — redirect is a Function +ok 1081 — throttle is a Function -# PASS test/setStyle/setStyle.test.js +# PASS test/hasFlags.test.js -ok 1074 — setStyle is a Function +ok 1082 — hasFlags is a Function -# PASS test/getStyle/getStyle.test.js +# PASS test/getStyle.test.js -ok 1075 — getStyle is a Function +ok 1083 — getStyle is a Function -# PASS test/pipeLog/pipeLog.test.js +# PASS test/httpPost.test.js -ok 1076 — pipeLog is a Function +ok 1084 — httpPost is a Function -# PASS test/zipWith/zipWith.test.js +# PASS test/colorize.test.js -ok 1077 — zipWith is a Function +ok 1085 — colorize is a Function -# PASS test/counter/counter.test.js +# PASS test/redirect.test.js -ok 1078 — counter is a Function +ok 1086 — redirect is a Function -# PASS test/httpGet/httpGet.test.js +# PASS test/solveRPN.test.js -ok 1079 — httpGet is a Function +ok 1087 — solveRPN is a Function -# PASS test/httpPut/httpPut.test.js +# PASS test/httpPut.test.js -ok 1080 — httpPut is a Function +ok 1088 — httpPut is a Function -# PASS test/factors/factors.test.js +# PASS test/zipWith.test.js -ok 1081 — factors is a Function +ok 1089 — zipWith is a Function -# PASS test/prefix/prefix.test.js +# PASS test/counter.test.js -ok 1082 — prefix is a Function +ok 1090 — counter is a Function -# PASS test/toHash/toHash.test.js +# PASS test/pipeLog.test.js -ok 1083 — toHash is a Function +ok 1091 — pipeLog is a Function -# PASS test/isMap/isMap.test.js +# PASS test/httpGet.test.js -ok 1084 — isMap is a Function +ok 1092 — httpGet is a Function -# PASS test/sumBy/sumBy.test.js +# PASS test/factors.test.js -ok 1085 — sumBy is a Function +ok 1093 — factors is a Function -# PASS test/isSet/isSet.test.js +# PASS test/prefix.test.js -ok 1086 — isSet is a Function +ok 1094 — prefix is a Function -# PASS test/defer/defer.test.js +# PASS test/toHash.test.js -ok 1087 — defer is a Function +ok 1095 — toHash is a Function -# PASS test/once/once.test.js +# PASS test/defer.test.js -ok 1088 — once is a Function +ok 1096 — defer is a Function -# PASS test/show/show.test.js +# PASS test/sumBy.test.js -ok 1089 — show is a Function +ok 1097 — sumBy is a Function -# PASS test/nest/nest.test.js +# PASS test/hide.test.js -ok 1090 — nest is a Function +ok 1098 — hide is a Function -# PASS test/hide/hide.test.js +# PASS test/show.test.js -ok 1091 — hide is a Function +ok 1099 — show is a Function -# PASS test/off/off.test.js +# PASS test/once.test.js -ok 1092 — off is a Function +ok 1100 — once is a Function -# PASS test/on/on.test.js +# PASS test/nest.test.js -ok 1093 — on is a Function +ok 1101 — nest is a Function -# PASS test/hz/hz.test.js +# PASS test/off.test.js -ok 1094 — hz is a Function +ok 1102 — off is a Function -1..1094 +# PASS test/on.test.js -# Test Suites: 99% ██████████, 2 failed, 360 passed, 362 total -# Tests: 100% ██████████, 2 failed, 1092 passed, 1094 total -# Time: 26.219s +ok 1103 — on is a Function + +# PASS test/hz.test.js + +ok 1104 — hz is a Function + +1..1104 + +# Test Suites: 100% ██████████, 359 passed, 359 total +# Tests: 100% ██████████, 1104 passed, 1104 total +# Time: 24.850s # Ran all test suites. -undefined \ No newline at end of file