diff --git a/.npmignore b/.npmignore new file mode 100644 index 000000000..e92f3bf08 --- /dev/null +++ b/.npmignore @@ -0,0 +1,18 @@ +snippet-template.md +tag_database +travis.log +CONTRIBUTING.md +COLLABORATING.md +CODE_OF_CONDUCT.md +.travis.yml +.mdlrc.style.rb +.mdlrc +.codeclimate.yml +test/* +static-parts/* +snippets_archive/* +scripts/* +locale/* +docs/* +.travis/* +.github/* diff --git a/README.md b/README.md index 7083b13b8..bddfc47cd 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,10 @@ average(1, 2, 3);
View contents +* [`all`](#all) +* [`any`](#any) +* [`bifurcate`](#bifurcate) +* [`bifurcateBy`](#bifurcateby) * [`chunk`](#chunk) * [`compact`](#compact) * [`countBy`](#countby) @@ -134,6 +138,7 @@ average(1, 2, 3); * [`mapObject`](#mapobject-) * [`maxN`](#maxn) * [`minN`](#minn) +* [`none`](#none) * [`nthElement`](#nthelement) * [`partition`](#partition) * [`pull`](#pull) @@ -152,6 +157,7 @@ average(1, 2, 3); * [`sortedIndexBy`](#sortedindexby) * [`sortedLastIndex`](#sortedlastindex) * [`sortedLastIndexBy`](#sortedlastindexby) +* [`stableSort`](#stablesort-) * [`symmetricDifference`](#symmetricdifference) * [`symmetricDifferenceBy`](#symmetricdifferenceby) * [`symmetricDifferenceWith`](#symmetricdifferencewith) @@ -246,6 +252,7 @@ average(1, 2, 3); * [`sleep`](#sleep) * [`throttle`](#throttle) * [`times`](#times) +* [`uncurry`](#uncurry) * [`unfold`](#unfold)
@@ -255,9 +262,12 @@ average(1, 2, 3);
View contents +* [`approximatelyEqual`](#approximatelyequal) * [`average`](#average) * [`averageBy`](#averageby) +* [`binomialCoefficient`](#binomialcoefficient) * [`clampNumber`](#clampnumber) +* [`degreesToRads`](#degreestorads) * [`digitize`](#digitize) * [`distance`](#distance) * [`elo`](#elo-) @@ -278,6 +288,7 @@ average(1, 2, 3); * [`percentile`](#percentile) * [`powerset`](#powerset) * [`primes`](#primes) +* [`radsToDegrees`](#radstodegrees) * [`randomIntArrayInRange`](#randomintarrayinrange) * [`randomIntegerInRange`](#randomintegerinrange) * [`randomNumberInRange`](#randomnumberinrange) @@ -421,6 +432,7 @@ average(1, 2, 3); * [`hexToRGB`](#hextorgb-) * [`httpGet`](#httpget) * [`httpPost`](#httppost) +* [`mostPerformant`](#mostperformant) * [`nthArg`](#ntharg) * [`parseCookie`](#parsecookie) * [`prettyBytes`](#prettybytes) @@ -760,6 +772,100 @@ const unary = fn => val => fn(val); --- ## 📚 Array +### all + +Returns `true` if the provided predicate function returns `true` for all elements in a collection, `false` otherwise. + +Use `Array.every()` to test if all elements in the collection return `true` based on `fn`. +Omit the second argument, `fn`, to use `Boolean` as a default. + +```js +const all = (arr, fn = Boolean) => arr.every(fn); +``` + +
+Examples + +```js +all([4, 2, 3], x => x > 1); // true +all([1, 2, 3]); // true +``` + +
+ +
[⬆ Back to top](#table-of-contents) + + +### any + +Returns `true` if the provided predicate function returns `true` for at least one element in a collection, `false` otherwise. + +Use `Array.some()` to test if any elements in the collection return `true` based on `fn`. +Omit the second argument, `fn`, to use `Boolean` as a default. + +```js +const any = (arr, fn = Boolean) => arr.some(fn); +``` + +
+Examples + +```js +any([0, 1, 2, 0], x => x >= 2); // true +any([0, 0, 1, 0]); // true +``` + +
+ +
[⬆ Back to top](#table-of-contents) + + +### bifurcate + +Splits values into two groups. If an element in `filter` is truthy, the corresponding element in the collection belongs to the first group; otherwise, it belongs to the second group. + +Use `Array.reduce()` and `Array.push()` to add elements to groups, based on `filter`. + +```js +const bifurcate = (arr, filter) => + arr.reduce((acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc), [[], []]); +``` + +
+Examples + +```js +bifurcate(['beep', 'boop', 'foo', 'bar'], [true, true, false, true]); // [ ['beep', 'boop', 'bar'], ['foo'] ] +``` + +
+ +
[⬆ Back to top](#table-of-contents) + + +### bifurcateBy + +Splits values into two groups according to a predicate function, which specifies which group an element in the input collection belongs to. If the predicate function returns a truthy value, the collection element belongs to the first group; otherwise, it belongs to the second group. + +Use `Array.reduce()` and `Array.push()` to add elements to groups, based on the value returned by `fn` for each element. + +```js +const bifurcateBy = (arr, fn) => + arr.reduce((acc, val, i) => (acc[fn(val, i) ? 0 : 1].push(val), acc), [[], []]); +``` + +
+Examples + +```js +bifurcateBy(['beep', 'boop', 'foo', 'bar'], x => x[0] === 'b'); // [ ['beep', 'boop', 'bar'], ['foo'] ] +``` + +
+ +
[⬆ Back to top](#table-of-contents) + + ### chunk Chunks an array into smaller arrays of a specified size. @@ -1665,6 +1771,30 @@ minN([1, 2, 3], 2); // [1,2]
[⬆ Back to top](#table-of-contents) +### none + +Returns `true` if the provided predicate function returns `false` for all elements in a collection, `false` otherwise. + +Use `Array.some()` to test if any elements in the collection return `true` based on `fn`. +Omit the second argument, `fn`, to use `Boolean` as a default. + +```js +const none = (arr, fn = Boolean) => !arr.some(fn); +``` + +
+Examples + +```js +none([0, 1, 3, 0], x => x == 2); // true +none([0, 0, 0]); // true +``` + +
+ +
[⬆ Back to top](#table-of-contents) + + ### nthElement Returns the nth element of an array. @@ -2199,6 +2329,36 @@ sortedLastIndexBy([{ x: 4 }, { x: 5 }], { x: 4 }, o => o.x); // 1
[⬆ Back to top](#table-of-contents) +### stableSort ![advanced](/advanced.svg) + +Performs stable sorting of an array, preserving the initial indexes of items when their values are the same. +Does not mutate the original array, but returns a new array instead. + +Use `Array.map()` to pair each element of the input array with its corresponding index. +Use `Array.sort()` and a `compare` function to sort the list, preserving their initial order if the items compared are equal. +Use `Array.map()` to convert back to the initial array items. + +```js +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); +``` + +
+Examples + +```js +const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; +const stable = stableSort(arr, () => 0); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] +``` + +
+ +
[⬆ Back to top](#table-of-contents) + + ### symmetricDifference Returns the symmetric difference between two arrays. @@ -4199,6 +4359,38 @@ console.log(output); // 01234
[⬆ Back to top](#table-of-contents) +### uncurry + +Uncurries a function up to depth `n`. + +Return a variadic function. +Use `Array.reduce()` on the provided arguments to call each subsequent curry level of the function. +If the `length` of the provided arguments is less than `n` throw an error. +Otherwise, call `fn` with the proper amount of arguments, using `Array.slice(0, n)`. +Omit the second argument, `n`, to uncurry up to depth `1`. + +```js +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)); +}; +``` + +
+Examples + +```js +const add = x => y => z => x + y + z; +const uncurriedAdd = uncurry(add, 3); +uncurriedAdd(1, 2, 3); // 6 +``` + +
+ +
[⬆ Back to top](#table-of-contents) + + ### unfold Builds an array, using an iterator function and an initial seed value. @@ -4230,6 +4422,29 @@ unfold(f, 10); // [-10, -20, -30, -40, -50] --- ## ➗ Math +### approximatelyEqual + +Checks if two numbers are approximately equal to each other. + +Use `Math.abs()` to compare the absolute difference of the two values to `epsilon`. +Omit the third parameter, `epsilon`, to use a default value of `0.001`. + +```js +const approximatelyEqual = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) < epsilon; +``` + +
+Examples + +```js +approximatelyEqual(Math.PI / 2.0, 1.5708); // true +``` + +
+ +
[⬆ Back to top](#table-of-contents) + + ### average Returns the average of two or more numbers. @@ -4278,6 +4493,41 @@ averageBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], 'n'); // 5
[⬆ Back to top](#table-of-contents) +### binomialCoefficient + +Evaluates the binomial coefficient of two integers `n` and `k`. + +Use `Number.isNaN()` to check if any of the two values is `NaN`. +Check if `k` is less than `0`, greater than or equal to `n`, equal to `1` or `n - 1` and return the appropriate result. +Check if `n - k` is less than `k` and switch their values accordingly. +Loop from `2` through `k` and calculate the binomial coefficient. +Use `Math.round()` to account for rounding errors in the calculation. + +```js +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); +}; +``` + +
+Examples + +```js +binomialCoefficient(8, 2); // 28 +``` + +
+ +
[⬆ Back to top](#table-of-contents) + + ### clampNumber Clamps `num` within the inclusive range specified by the boundary values `a` and `b`. @@ -4302,6 +4552,28 @@ clampNumber(1, -1, -5); // -1
[⬆ Back to top](#table-of-contents) +### degreesToRads + +Converts an angle from degrees to radians. + +Use `Math.PI` and the degree to radian formula to convert the angle from degrees to radians. + +```js +const degreesToRads = deg => deg * Math.PI / 180.0; +``` + +
+Examples + +```js +degreesToRads(90.0); // ~1.5708 +``` + +
+ +
[⬆ Back to top](#table-of-contents) + + ### digitize Converts a number to an array of digits. @@ -4850,6 +5122,28 @@ primes(10); // [2,3,5,7]
[⬆ Back to top](#table-of-contents) +### radsToDegrees + +Converts an angle from radians to degrees. + +Use `Math.PI` and the radian to degree formula to convert the angle from radians to degrees. + +```js +const radsToDegrees = rad => rad * 180.0 / Math.PI; +``` + +
+Examples + +```js +radsToDegrees(Math.PI / 2); // 90 +``` + +
+ +
[⬆ Back to top](#table-of-contents) + + ### randomIntArrayInRange Returns an array of n random integers in the specified range. @@ -7719,6 +8013,46 @@ Logs: {
[⬆ Back to top](#table-of-contents) +### mostPerformant + +Returns the index of the function in an array of functions which executed the fastest. + +Use `Array.map()` to generate an array where each value is the total time taken to execute the function after `iterations` times. Use the difference in `performance.now()` values before and after to get the total time in milliseconds to a high degree of accuracy. +Use `Math.min()` to find the minimum execution time, and return the index of that shortest time which corresponds to the index of the most performant function. +Omit the second argument, `iterations`, to use a default of 10,000 iterations. The more iterations, the more reliable the result but the longer it will take. + +```js +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)); +}; +``` + +
+Examples + +```js +mostPerformant([ + () => { + // Loops through the entire array before returning `false` + [1, 2, 3, 4, 5, 6, 7, 8, 9, '10'].every(el => typeof el === 'number'); + }, + () => { + // Only needs to reach index `1` before returning false + [1, '2', 3, 4, 5, 6, 7, 8, 9, 10].every(el => typeof el === 'number'); + } +]); // 1 +``` + +
+ +
[⬆ Back to top](#table-of-contents) + + ### nthArg Creates a function that gets the argument at index `n`. If `n` is negative, the nth argument from the end is returned. diff --git a/dist/_30s.es5.js b/dist/_30s.es5.js index dfae2893e..0bc6ed0a8 100644 --- a/dist/_30s.es5.js +++ b/dist/_30s.es5.js @@ -34,6 +34,11 @@ var UUIDGeneratorNode = function UUIDGeneratorNode() { }); }; +var all = function all(arr) { + var fn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Boolean; + return arr.every(fn); +}; + var anagrams = function anagrams(str) { if (str.length <= 2) return str.length === 2 ? [str, str[1] + str[0]] : [str]; return str.split('').reduce(function (acc, letter, i) { @@ -43,6 +48,16 @@ var anagrams = function anagrams(str) { }, []); }; +var any = function any(arr) { + var fn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Boolean; + return arr.some(fn); +}; + +var approximatelyEqual = function approximatelyEqual(v1, v2) { + var epsilon = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0.001; + return Math.abs(v1 - v2) < epsilon; +}; + var arrayToHtmlList = function arrayToHtmlList(arr, listID) { return arr.map(function (item) { return document.querySelector('#' + listID).innerHTML += '
  • ' + item + '
  • '; @@ -95,6 +110,18 @@ var averageBy = function averageBy(arr, fn) { }, 0) / arr.length; }; +var bifurcate = function bifurcate(arr, filter) { + return arr.reduce(function (acc, val, i) { + return acc[filter[i] ? 0 : 1].push(val), acc; + }, [[], []]); +}; + +var bifurcateBy = function bifurcateBy(arr, fn) { + return arr.reduce(function (acc, val, i) { + return acc[fn(val, i) ? 0 : 1].push(val), acc; + }, [[], []]); +}; + var bind = function bind(fn, context) { for (var _len = arguments.length, args = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { args[_key - 2] = arguments[_key]; @@ -127,6 +154,18 @@ var bindKey = function bindKey(context, fn) { }; }; +var binomialCoefficient = function 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; + var res = n; + for (var j = 2; j <= k; j++) { + res *= (n - j + 1) / j; + }return Math.round(res); +}; + var bottomVisible = function bottomVisible() { return document.documentElement.clientHeight + window.scrollY >= (document.documentElement.scrollHeight || document.documentElement.clientHeight); }; @@ -428,6 +467,10 @@ var defer = function defer(fn) { return setTimeout.apply(undefined, [fn, 1].concat(args)); }; +var degreesToRads = function degreesToRads(deg) { + return deg * Math.PI / 180.0; +}; + var delay = function delay(fn, wait) { for (var _len = arguments.length, args = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { args[_key - 2] = arguments[_key]; @@ -1294,12 +1337,31 @@ var minN = function minN(arr) { }).slice(0, n); }; +function _toConsumableArray$13(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + +var mostPerformant = function mostPerformant(fns) { + var iterations = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 10000; + + var times = fns.map(function (fn) { + var before = performance.now(); + for (var i = 0; i < iterations; i++) { + fn(); + }return performance.now() - before; + }); + return times.indexOf(Math.min.apply(Math, _toConsumableArray$13(times))); +}; + var negate = function negate(func) { return function () { return !func.apply(undefined, arguments); }; }; +var none = function none(arr) { + var fn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Boolean; + return !arr.some(fn); +}; + var nthArg = function nthArg(n) { return function () { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { @@ -1405,10 +1467,10 @@ var once = function once(fn) { var _slicedToArray$2 = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); -function _toConsumableArray$13(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } +function _toConsumableArray$14(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } var orderBy = function orderBy(arr, props, orders) { - return [].concat(_toConsumableArray$13(arr)).sort(function (a, b) { + return [].concat(_toConsumableArray$14(arr)).sort(function (a, b) { return props.reduce(function (acc, prop, i) { if (acc === 0) { var _ref = orders && orders[i] === 'desc' ? [b[prop], a[prop]] : [a[prop], b[prop]], @@ -1439,7 +1501,7 @@ var over = function over() { }; }; -function _toConsumableArray$14(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } +function _toConsumableArray$15(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } var overArgs = function overArgs(fn, transforms) { return function () { @@ -1447,7 +1509,7 @@ var overArgs = function overArgs(fn, transforms) { args[_key] = arguments[_key]; } - return fn.apply(undefined, _toConsumableArray$14(args.map(function (val, i) { + return fn.apply(undefined, _toConsumableArray$15(args.map(function (val, i) { return transforms[i](val); }))); }; @@ -1674,6 +1736,10 @@ var pullBy = function pullBy(arr) { }); }; +var radsToDegrees = function radsToDegrees(rad) { + return rad * 180.0 / Math.PI; +}; + var randomHexColorCode = function randomHexColorCode() { var n = (Math.random() * 0xfffff * 1000000).toString(16); return '#' + n.slice(0, 6); @@ -1699,7 +1765,7 @@ var readFileLines = function readFileLines(filename) { return fs$1.readFileSync(filename).toString('UTF8').split('\n'); }; -function _toConsumableArray$15(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } +function _toConsumableArray$16(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } var rearg = function rearg(fn, indexes) { return function () { @@ -1707,7 +1773,7 @@ var rearg = function rearg(fn, indexes) { args[_key] = arguments[_key]; } - return fn.apply(undefined, _toConsumableArray$15(args.reduce(function (acc, val, i) { + return fn.apply(undefined, _toConsumableArray$16(args.reduce(function (acc, val, i) { return acc[indexes.indexOf(i)] = val, acc; }, Array.from({ length: indexes.length })))); }; @@ -1753,10 +1819,10 @@ var removeNonASCII = function removeNonASCII(str) { return str.replace(/[^\x20-\x7E]/g, ''); }; -function _toConsumableArray$16(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } +function _toConsumableArray$17(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } var reverseString = function reverseString(str) { - return [].concat(_toConsumableArray$16(str)).reverse().join(''); + return [].concat(_toConsumableArray$17(str)).reverse().join(''); }; var round = function round(n) { @@ -1879,10 +1945,10 @@ var sleep = function sleep(ms) { }); }; -function _toConsumableArray$17(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } +function _toConsumableArray$18(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } var sortCharactersInString = function sortCharactersInString(str) { - return [].concat(_toConsumableArray$17(str)).sort(function (a, b) { + return [].concat(_toConsumableArray$18(str)).sort(function (a, b) { return a.localeCompare(b); }).join(''); }; @@ -1929,14 +1995,25 @@ var splitLines = function splitLines(str) { return str.split(/\r?\n/); }; -function _toConsumableArray$18(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } +function _toConsumableArray$19(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } var spreadOver = function spreadOver(fn) { return function (argsArr) { - return fn.apply(undefined, _toConsumableArray$18(argsArr)); + return fn.apply(undefined, _toConsumableArray$19(argsArr)); }; }; +var stableSort = function stableSort(arr, compare) { + return arr.map(function (item, index) { + return { item: item, index: index }; + }).sort(function (a, b) { + return compare(a.item, b.item) || a.index - b.index; + }).map(function (_ref) { + var item = _ref.item; + return item; + }); +}; + var standardDeviation = function standardDeviation(arr) { var usePopulation = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; @@ -1982,19 +2059,19 @@ var sumPower = function sumPower(end) { }, 0); }; -function _toConsumableArray$19(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } +function _toConsumableArray$20(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } var symmetricDifference = function symmetricDifference(a, b) { var sA = new Set(a), sB = new Set(b); - return [].concat(_toConsumableArray$19(a.filter(function (x) { + return [].concat(_toConsumableArray$20(a.filter(function (x) { return !sB.has(x); - })), _toConsumableArray$19(b.filter(function (x) { + })), _toConsumableArray$20(b.filter(function (x) { return !sA.has(x); }))); }; -function _toConsumableArray$20(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } +function _toConsumableArray$21(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } var symmetricDifferenceBy = function symmetricDifferenceBy(a, b, fn) { var sA = new Set(a.map(function (v) { @@ -2003,21 +2080,21 @@ var symmetricDifferenceBy = function symmetricDifferenceBy(a, b, fn) { sB = new Set(b.map(function (v) { return fn(v); })); - return [].concat(_toConsumableArray$20(a.filter(function (x) { + return [].concat(_toConsumableArray$21(a.filter(function (x) { return !sB.has(fn(x)); - })), _toConsumableArray$20(b.filter(function (x) { + })), _toConsumableArray$21(b.filter(function (x) { return !sA.has(fn(x)); }))); }; -function _toConsumableArray$21(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } +function _toConsumableArray$22(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } var symmetricDifferenceWith = function symmetricDifferenceWith(arr, val, comp) { - return [].concat(_toConsumableArray$21(arr.filter(function (a) { + return [].concat(_toConsumableArray$22(arr.filter(function (a) { return val.findIndex(function (b) { return comp(a, b); }) === -1; - })), _toConsumableArray$21(val.filter(function (a) { + })), _toConsumableArray$22(val.filter(function (a) { return arr.findIndex(function (b) { return comp(a, b); }) === -1; @@ -2205,6 +2282,25 @@ var unary = function unary(fn) { }; }; +var uncurry = function uncurry(fn) { + var n = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; + return function () { + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + var next = function next(acc) { + return function (args) { + return args.reduce(function (x, y) { + return x(y); + }, acc); + }; + }; + if (n > args.length) throw new RangeError('Arguments too few!'); + return next(fn)(args.slice(0, n)); + }; +}; + var unescapeHTML = function unescapeHTML(str) { return str.replace(/&|<|>|'|"/g, function (tag) { return { @@ -2237,62 +2333,46 @@ var unfold = function unfold(fn, seed) { }return result; }; -function _toConsumableArray$22(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } +function _toConsumableArray$23(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } var union = function union(a, b) { - return Array.from(new Set([].concat(_toConsumableArray$22(a), _toConsumableArray$22(b)))); + return Array.from(new Set([].concat(_toConsumableArray$23(a), _toConsumableArray$23(b)))); }; -function _toConsumableArray$23(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } +function _toConsumableArray$24(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } var unionBy = function unionBy(a, b, fn) { var s = new Set(a.map(function (v) { return fn(v); })); - return Array.from(new Set([].concat(_toConsumableArray$23(a), _toConsumableArray$23(b.filter(function (x) { + return Array.from(new Set([].concat(_toConsumableArray$24(a), _toConsumableArray$24(b.filter(function (x) { return !s.has(fn(x)); }))))); }; -function _toConsumableArray$24(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } +function _toConsumableArray$25(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } var unionWith = function unionWith(a, b, comp) { - return Array.from(new Set([].concat(_toConsumableArray$24(a), _toConsumableArray$24(b.filter(function (x) { + return Array.from(new Set([].concat(_toConsumableArray$25(a), _toConsumableArray$25(b.filter(function (x) { return a.findIndex(function (y) { return comp(x, y); }) === -1; }))))); }; -function _toConsumableArray$25(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } +function _toConsumableArray$26(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } var uniqueElements = function uniqueElements(arr) { - return [].concat(_toConsumableArray$25(new Set(arr))); + return [].concat(_toConsumableArray$26(new Set(arr))); }; var untildify = function untildify(str) { return str.replace(/^~($|\/|\\)/, (typeof require !== "undefined" && require('os').homedir()) + "$1"); }; -function _toConsumableArray$26(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } - -var unzip = function unzip(arr) { - return arr.reduce(function (acc, val) { - return val.forEach(function (v, i) { - return acc[i].push(v); - }), acc; - }, Array.from({ - length: Math.max.apply(Math, _toConsumableArray$26(arr.map(function (x) { - return x.length; - }))) - }).map(function (x) { - return []; - })); -}; - function _toConsumableArray$27(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } -var unzipWith = function unzipWith(arr, fn) { +var unzip = function unzip(arr) { return arr.reduce(function (acc, val) { return val.forEach(function (v, i) { return acc[i].push(v); @@ -2303,8 +2383,24 @@ var unzipWith = function unzipWith(arr, fn) { }))) }).map(function (x) { return []; + })); +}; + +function _toConsumableArray$28(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + +var unzipWith = function unzipWith(arr, fn) { + return arr.reduce(function (acc, val) { + return val.forEach(function (v, i) { + return acc[i].push(v); + }), acc; + }, Array.from({ + length: Math.max.apply(Math, _toConsumableArray$28(arr.map(function (x) { + return x.length; + }))) + }).map(function (x) { + return []; })).map(function (val) { - return fn.apply(undefined, _toConsumableArray$27(val)); + return fn.apply(undefined, _toConsumableArray$28(val)); }); }; @@ -2341,14 +2437,14 @@ var yesNo = function yesNo(val) { ); }; -function _toConsumableArray$28(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } +function _toConsumableArray$29(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } var zip = function zip() { for (var _len = arguments.length, arrays = Array(_len), _key = 0; _key < _len; _key++) { arrays[_key] = arguments[_key]; } - var maxLength = Math.max.apply(Math, _toConsumableArray$28(arrays.map(function (x) { + var maxLength = Math.max.apply(Math, _toConsumableArray$29(arrays.map(function (x) { return x.length; }))); return Array.from({ length: maxLength }).map(function (_, i) { @@ -2364,7 +2460,7 @@ var zipObject = function zipObject(props, values) { }, {}); }; -function _toConsumableArray$29(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } +function _toConsumableArray$30(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } var zipWith = function zipWith() { for (var _len = arguments.length, arrays = Array(_len), _key = 0; _key < _len; _key++) { @@ -2374,7 +2470,7 @@ var zipWith = function zipWith() { var length = arrays.length; var fn = length > 1 ? arrays[length - 1] : undefined; fn = typeof fn == 'function' ? (arrays.pop(), fn) : undefined; - var maxLength = Math.max.apply(Math, _toConsumableArray$29(arrays.map(function (x) { + var maxLength = Math.max.apply(Math, _toConsumableArray$30(arrays.map(function (x) { return x.length; }))); var result = Array.from({ length: maxLength }).map(function (_, i) { @@ -2383,11 +2479,11 @@ var zipWith = function zipWith() { }); }); return fn ? result.map(function (arr) { - return fn.apply(undefined, _toConsumableArray$29(arr)); + return fn.apply(undefined, _toConsumableArray$30(arr)); }) : result; }; -var imports = { JSONToFile: JSONToFile, RGBToHex: RGBToHex, URLJoin: URLJoin, UUIDGeneratorBrowser: UUIDGeneratorBrowser, UUIDGeneratorNode: UUIDGeneratorNode, anagrams: anagrams, arrayToHtmlList: arrayToHtmlList, ary: ary, atob: atob, attempt: attempt, average: average, averageBy: averageBy, bind: bind, bindAll: bindAll, bindKey: bindKey, bottomVisible: bottomVisible, btoa: btoa, byteSize: byteSize, call: call, capitalize: capitalize, capitalizeEveryWord: capitalizeEveryWord, castArray: castArray, chainAsync: chainAsync, chunk: chunk, clampNumber: clampNumber, cloneRegExp: cloneRegExp, coalesce: coalesce, coalesceFactory: coalesceFactory, collectInto: collectInto, colorize: colorize, compact: compact, compose: compose, composeRight: composeRight, converge: converge, copyToClipboard: copyToClipboard, countBy: countBy, countOccurrences: countOccurrences, createElement: createElement, createEventHub: createEventHub, currentURL: currentURL, curry: curry, debounce: debounce, decapitalize: decapitalize, deepClone: deepClone, deepFlatten: deepFlatten, defaults: defaults, defer: defer, delay: delay, detectDeviceType: detectDeviceType, difference: difference, differenceBy: differenceBy, differenceWith: differenceWith, digitize: digitize, distance: distance, drop: drop, dropRight: dropRight, dropRightWhile: dropRightWhile, dropWhile: dropWhile, elementIsVisibleInViewport: elementIsVisibleInViewport, elo: elo, equals: equals, escapeHTML: escapeHTML, escapeRegExp: escapeRegExp, everyNth: everyNth, extendHex: extendHex, factorial: factorial, fibonacci: fibonacci, filterNonUnique: filterNonUnique, findKey: findKey, findLast: findLast, findLastIndex: findLastIndex, findLastKey: findLastKey, flatten: flatten, flattenObject: flattenObject, flip: flip, forEachRight: forEachRight, forOwn: forOwn, forOwnRight: forOwnRight, formatDuration: formatDuration, fromCamelCase: fromCamelCase, functionName: functionName, functions: functions, gcd: gcd, geometricProgression: geometricProgression, get: get, getColonTimeFromDate: getColonTimeFromDate, getDaysDiffBetweenDates: getDaysDiffBetweenDates, getMeridiemSuffixOfInteger: getMeridiemSuffixOfInteger, getScrollPosition: getScrollPosition, getStyle: getStyle, getType: getType, getURLParameters: getURLParameters, groupBy: groupBy, hammingDistance: hammingDistance, hasClass: hasClass, hasFlags: hasFlags, hashBrowser: hashBrowser, hashNode: hashNode, head: head, hexToRGB: hexToRGB, hide: hide, httpGet: httpGet, httpPost: httpPost, httpsRedirect: httpsRedirect, inRange: inRange, indexOfAll: indexOfAll, initial: initial, initialize2DArray: initialize2DArray, initializeArrayWithRange: initializeArrayWithRange, initializeArrayWithRangeRight: initializeArrayWithRangeRight, initializeArrayWithValues: initializeArrayWithValues, intersection: intersection, intersectionBy: intersectionBy, intersectionWith: intersectionWith, invertKeyValues: invertKeyValues, is: is, isAbsoluteURL: isAbsoluteURL, isArrayLike: isArrayLike, isBoolean: isBoolean, isDivisible: isDivisible, isEmpty: isEmpty, isEven: isEven, isFunction: isFunction, isLowerCase: isLowerCase, isNil: isNil, isNull: isNull, isNumber: isNumber, isObject: isObject, isObjectLike: isObjectLike, isPlainObject: isPlainObject, isPrime: isPrime, isPrimitive: isPrimitive, isPromiseLike: isPromiseLike, isSorted: isSorted, isString: isString, isSymbol: isSymbol, isTravisCI: isTravisCI, isUndefined: isUndefined, isUpperCase: isUpperCase, isValidJSON: isValidJSON, join: join, last: last, lcm: lcm, longestItem: longestItem, lowercaseKeys: lowercaseKeys, luhnCheck: luhnCheck, mapKeys: mapKeys, mapObject: mapObject, mapValues: mapValues, mask: mask, matches: matches, matchesWith: matchesWith, maxBy: maxBy, maxN: maxN, median: median, memoize: memoize, merge: merge, minBy: minBy, minN: minN, negate: negate, nthArg: nthArg, nthElement: nthElement, objectFromPairs: objectFromPairs, objectToPairs: objectToPairs, observeMutations: observeMutations, off: off, omit: omit, omitBy: omitBy, on: on, onUserInputChange: onUserInputChange, once: once, orderBy: orderBy, over: over, overArgs: overArgs, palindrome: palindrome, parseCookie: parseCookie, partial: partial, partialRight: partialRight, partition: partition, percentile: percentile, pick: pick, pickBy: pickBy, pipeAsyncFunctions: pipeAsyncFunctions, pipeFunctions: pipeFunctions, pluralize: pluralize, powerset: powerset, prettyBytes: prettyBytes, primes: primes, promisify: promisify, pull: pull, pullAtIndex: pullAtIndex, pullAtValue: pullAtValue, pullBy: pullBy, randomHexColorCode: randomHexColorCode, randomIntArrayInRange: randomIntArrayInRange, randomIntegerInRange: randomIntegerInRange, randomNumberInRange: randomNumberInRange, readFileLines: readFileLines, rearg: rearg, redirect: redirect, reduceSuccessive: reduceSuccessive, reduceWhich: reduceWhich, reducedFilter: reducedFilter, remove: remove, removeNonASCII: removeNonASCII, reverseString: reverseString, round: round, runAsync: runAsync, runPromisesInSeries: runPromisesInSeries, sample: sample, sampleSize: sampleSize, scrollToTop: scrollToTop, sdbm: sdbm, serializeCookie: serializeCookie, setStyle: setStyle, shallowClone: shallowClone, show: show, shuffle: shuffle, similarity: similarity, size: size, sleep: sleep, sortCharactersInString: sortCharactersInString, sortedIndex: sortedIndex, sortedIndexBy: sortedIndexBy, sortedLastIndex: sortedLastIndex, sortedLastIndexBy: sortedLastIndexBy, splitLines: splitLines, spreadOver: spreadOver, standardDeviation: standardDeviation, stripHTMLTags: stripHTMLTags, sum: sum, sumBy: sumBy, sumPower: sumPower, symmetricDifference: symmetricDifference, symmetricDifferenceBy: symmetricDifferenceBy, symmetricDifferenceWith: symmetricDifferenceWith, tail: tail, take: take, takeRight: takeRight, takeRightWhile: takeRightWhile, takeWhile: takeWhile, throttle: throttle, timeTaken: timeTaken, times: times, toCamelCase: toCamelCase, toCurrency: toCurrency, toDecimalMark: toDecimalMark, toKebabCase: toKebabCase, toOrdinalSuffix: toOrdinalSuffix, toSafeInteger: toSafeInteger, toSnakeCase: toSnakeCase, toggleClass: toggleClass, tomorrow: tomorrow, transform: transform, truncateString: truncateString, truthCheckCollection: truthCheckCollection, unary: unary, unescapeHTML: unescapeHTML, unflattenObject: unflattenObject, unfold: unfold, union: union, unionBy: unionBy, unionWith: unionWith, uniqueElements: uniqueElements, untildify: untildify, unzip: unzip, unzipWith: unzipWith, validateNumber: validateNumber, without: without, words: words, xProd: xProd, yesNo: yesNo, zip: zip, zipObject: zipObject, zipWith: zipWith }; +var imports = { JSONToFile: JSONToFile, RGBToHex: RGBToHex, URLJoin: URLJoin, UUIDGeneratorBrowser: UUIDGeneratorBrowser, UUIDGeneratorNode: UUIDGeneratorNode, all: all, anagrams: anagrams, any: any, approximatelyEqual: approximatelyEqual, arrayToHtmlList: arrayToHtmlList, ary: ary, atob: atob, attempt: attempt, average: average, averageBy: averageBy, bifurcate: bifurcate, bifurcateBy: bifurcateBy, bind: bind, bindAll: bindAll, bindKey: bindKey, binomialCoefficient: binomialCoefficient, bottomVisible: bottomVisible, btoa: btoa, byteSize: byteSize, call: call, capitalize: capitalize, capitalizeEveryWord: capitalizeEveryWord, castArray: castArray, chainAsync: chainAsync, chunk: chunk, clampNumber: clampNumber, cloneRegExp: cloneRegExp, coalesce: coalesce, coalesceFactory: coalesceFactory, collectInto: collectInto, colorize: colorize, compact: compact, compose: compose, composeRight: composeRight, converge: converge, copyToClipboard: copyToClipboard, countBy: countBy, countOccurrences: countOccurrences, createElement: createElement, createEventHub: createEventHub, currentURL: currentURL, curry: curry, debounce: debounce, decapitalize: decapitalize, deepClone: deepClone, deepFlatten: deepFlatten, defaults: defaults, defer: defer, degreesToRads: degreesToRads, delay: delay, detectDeviceType: detectDeviceType, difference: difference, differenceBy: differenceBy, differenceWith: differenceWith, digitize: digitize, distance: distance, drop: drop, dropRight: dropRight, dropRightWhile: dropRightWhile, dropWhile: dropWhile, elementIsVisibleInViewport: elementIsVisibleInViewport, elo: elo, equals: equals, escapeHTML: escapeHTML, escapeRegExp: escapeRegExp, everyNth: everyNth, extendHex: extendHex, factorial: factorial, fibonacci: fibonacci, filterNonUnique: filterNonUnique, findKey: findKey, findLast: findLast, findLastIndex: findLastIndex, findLastKey: findLastKey, flatten: flatten, flattenObject: flattenObject, flip: flip, forEachRight: forEachRight, forOwn: forOwn, forOwnRight: forOwnRight, formatDuration: formatDuration, fromCamelCase: fromCamelCase, functionName: functionName, functions: functions, gcd: gcd, geometricProgression: geometricProgression, get: get, getColonTimeFromDate: getColonTimeFromDate, getDaysDiffBetweenDates: getDaysDiffBetweenDates, getMeridiemSuffixOfInteger: getMeridiemSuffixOfInteger, getScrollPosition: getScrollPosition, getStyle: getStyle, getType: getType, getURLParameters: getURLParameters, groupBy: groupBy, hammingDistance: hammingDistance, hasClass: hasClass, hasFlags: hasFlags, hashBrowser: hashBrowser, hashNode: hashNode, head: head, hexToRGB: hexToRGB, hide: hide, httpGet: httpGet, httpPost: httpPost, httpsRedirect: httpsRedirect, inRange: inRange, indexOfAll: indexOfAll, initial: initial, initialize2DArray: initialize2DArray, initializeArrayWithRange: initializeArrayWithRange, initializeArrayWithRangeRight: initializeArrayWithRangeRight, initializeArrayWithValues: initializeArrayWithValues, intersection: intersection, intersectionBy: intersectionBy, intersectionWith: intersectionWith, invertKeyValues: invertKeyValues, is: is, isAbsoluteURL: isAbsoluteURL, isArrayLike: isArrayLike, isBoolean: isBoolean, isDivisible: isDivisible, isEmpty: isEmpty, isEven: isEven, isFunction: isFunction, isLowerCase: isLowerCase, isNil: isNil, isNull: isNull, isNumber: isNumber, isObject: isObject, isObjectLike: isObjectLike, isPlainObject: isPlainObject, isPrime: isPrime, isPrimitive: isPrimitive, isPromiseLike: isPromiseLike, isSorted: isSorted, isString: isString, isSymbol: isSymbol, isTravisCI: isTravisCI, isUndefined: isUndefined, isUpperCase: isUpperCase, isValidJSON: isValidJSON, join: join, last: last, lcm: lcm, longestItem: longestItem, lowercaseKeys: lowercaseKeys, luhnCheck: luhnCheck, mapKeys: mapKeys, mapObject: mapObject, mapValues: mapValues, mask: mask, matches: matches, matchesWith: matchesWith, maxBy: maxBy, maxN: maxN, median: median, memoize: memoize, merge: merge, minBy: minBy, minN: minN, mostPerformant: mostPerformant, negate: negate, none: none, nthArg: nthArg, nthElement: nthElement, objectFromPairs: objectFromPairs, objectToPairs: objectToPairs, observeMutations: observeMutations, off: off, omit: omit, omitBy: omitBy, on: on, onUserInputChange: onUserInputChange, once: once, orderBy: orderBy, over: over, overArgs: overArgs, palindrome: palindrome, parseCookie: parseCookie, partial: partial, partialRight: partialRight, partition: partition, percentile: percentile, pick: pick, pickBy: pickBy, pipeAsyncFunctions: pipeAsyncFunctions, pipeFunctions: pipeFunctions, pluralize: pluralize, powerset: powerset, prettyBytes: prettyBytes, primes: primes, promisify: promisify, pull: pull, pullAtIndex: pullAtIndex, pullAtValue: pullAtValue, pullBy: pullBy, radsToDegrees: radsToDegrees, randomHexColorCode: randomHexColorCode, randomIntArrayInRange: randomIntArrayInRange, randomIntegerInRange: randomIntegerInRange, randomNumberInRange: randomNumberInRange, readFileLines: readFileLines, rearg: rearg, redirect: redirect, reduceSuccessive: reduceSuccessive, reduceWhich: reduceWhich, reducedFilter: reducedFilter, remove: remove, removeNonASCII: removeNonASCII, reverseString: reverseString, round: round, runAsync: runAsync, runPromisesInSeries: runPromisesInSeries, sample: sample, sampleSize: sampleSize, scrollToTop: scrollToTop, sdbm: sdbm, serializeCookie: serializeCookie, setStyle: setStyle, shallowClone: shallowClone, show: show, shuffle: shuffle, similarity: similarity, size: size, sleep: sleep, sortCharactersInString: sortCharactersInString, sortedIndex: sortedIndex, sortedIndexBy: sortedIndexBy, sortedLastIndex: sortedLastIndex, sortedLastIndexBy: sortedLastIndexBy, splitLines: splitLines, spreadOver: spreadOver, stableSort: stableSort, standardDeviation: standardDeviation, stripHTMLTags: stripHTMLTags, sum: sum, sumBy: sumBy, sumPower: sumPower, symmetricDifference: symmetricDifference, symmetricDifferenceBy: symmetricDifferenceBy, symmetricDifferenceWith: symmetricDifferenceWith, tail: tail, take: take, takeRight: takeRight, takeRightWhile: takeRightWhile, takeWhile: takeWhile, throttle: throttle, timeTaken: timeTaken, times: times, toCamelCase: toCamelCase, toCurrency: toCurrency, toDecimalMark: toDecimalMark, toKebabCase: toKebabCase, toOrdinalSuffix: toOrdinalSuffix, toSafeInteger: toSafeInteger, toSnakeCase: toSnakeCase, toggleClass: toggleClass, tomorrow: tomorrow, transform: transform, truncateString: truncateString, truthCheckCollection: truthCheckCollection, unary: unary, uncurry: uncurry, unescapeHTML: unescapeHTML, unflattenObject: unflattenObject, unfold: unfold, union: union, unionBy: unionBy, unionWith: unionWith, uniqueElements: uniqueElements, untildify: untildify, unzip: unzip, unzipWith: unzipWith, validateNumber: validateNumber, without: without, words: words, xProd: xProd, yesNo: yesNo, zip: zip, zipObject: zipObject, zipWith: zipWith }; return imports; diff --git a/dist/_30s.es5.min.js b/dist/_30s.es5.min.js index 6cc06c235..8121c7fea 100644 --- a/dist/_30s.es5.min.js +++ b/dist/_30s.es5.min.js @@ -1 +1 @@ -(function(e,t){'object'==typeof exports&&'undefined'!=typeof module?module.exports=t():'function'==typeof define&&define.amd?define(t):e._30s=t()})(this,function(){'use strict';function e(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t>e/4).toString(16)})},UUIDGeneratorNode:function(){return'10000000-1000-4000-8000-100000000000'.replace(/[018]/g,function(e){return(e^V.randomBytes(1)[0]&15>>e/4).toString(16)})},anagrams:function e(t){return 2>=t.length?2===t.length?[t,t[1]+t[0]]:[t]:t.split('').reduce(function(n,r,l){return n.concat(e(t.slice(0,l)+t.slice(l+1)).map(function(e){return r+e}))},[])},arrayToHtmlList:function(e,t){return e.map(function(e){return document.querySelector('#'+t).innerHTML+='
  • '+e+'
  • '})},ary:function(t,r){return function(){for(var n=arguments.length,i=Array(n),l=0;l=(document.documentElement.scrollHeight||document.documentElement.clientHeight)},btoa:function(e){return new Buffer(e,'binary').toString('base64')},byteSize:function(e){return new Blob([e]).size},call:function(e){for(var t=arguments.length,n=Array(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:U(e/8.64e7),hour:U(e/3.6e6)%24,minute:U(e/6e4)%60,second:U(e/1e3)%60,millisecond:U(e)%1e3};return Object.entries(t).filter(function(e){return 0!==e[1]}).map(function(e){return e[1]+' '+(1===e[1]?e[0]:e[0]+'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?', '+(255&n):'')+')'},hide:function(){for(var e=arguments.length,t=Array(e),n=0;nn&&(n=t),null==n?0<=e&&e=t&&ee[1]?-1:1,r=!0,l=!1;try{for(var o,a=e.entries()[Symbol.iterator]();!(r=(o=a.next()).done);r=!0){var s=o.value,c=ee(s,2),d=c[0],i=c[1];if(d===e.length-1)return n;if(0<(i-e[d+1])*n)return 0}}catch(e){l=!0,t=e}finally{try{!r&&a.return&&a.return()}finally{if(l)throw t}}},isString:function(e){return'string'==typeof e},isSymbol:function(e){return'symbol'===('undefined'==typeof e?'undefined':te(e))},isTravisCI:function(){return'TRAVIS'in process.env&&'CI'in process.env},isUndefined:function(e){return e===void 0},isUpperCase:function(e){return e===e.toUpperCase()},isValidJSON:function(e){try{return JSON.parse(e),!0}catch(t){return!1}},join:function(e){var t=1i-n&&(t='mouse',e(t),document.removeEventListener('mousemove',r)),n=i};document.addEventListener('touchstart',function(){'touch'==t||(t='touch',e(t),document.addEventListener('mousemove',r))})},once:function(e){var t=!1;return function(){if(!t){t=!0;for(var n=arguments.length,r=Array(n),i=0;ic?1:sMath.abs(e))return e+(r?' ':'')+i[0];var l=P(U(Math.log10(0>e?-e:e)/3),i.length-1),o=+((0>e?-e:e)/W(1e3,l)).toPrecision(t);return(0>e?'-':'')+o+(r?' ':'')+i[l]},primes:function(e){var t=Array.from({length:e-1}).map(function(e,t){return t+2}),n=U(D(e)),r=Array.from({length:n-1}).map(function(e,t){return t+2});return r.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),r=0;re[e.length-1],r=e.findIndex(function(e){return n?t>=e:t<=e});return-1===r?e.length:r},sortedIndexBy:function(e,t,n){var r=n(e[0])>n(e[e.length-1]),i=n(t),l=e.findIndex(function(e){return r?i>=n(e):i<=n(e)});return-1===l?e.length:l},sortedLastIndex:function(e,t){var n=e[0]>e[e.length-1],r=e.map(function(e,t){return[t,e]}).reverse().findIndex(function(e){return n?t<=e[1]:t>=e[1]});return-1===r?0:e.length-r-1},sortedLastIndexBy:function(e,t,n){var r=n(e[0])>n(e[e.length-1]),i=n(t),l=e.map(function(e,t){return[t,n(e)]}).reverse().findIndex(function(e){return r?i<=e[1]:i>=e[1]});return-1===l?0:e.length-l},splitLines:function(e){return e.split(/\r?\n/)},spreadOver:function(e){return function(t){return e.apply(void 0,x(t))}},standardDeviation:function(e){var t=1]*>/g,'')},sum:function(){for(var e=arguments.length,t=Array(e),n=0;n=t&&(e.apply(l,o),i=Date.now())},t-(Date.now()-i))):(e.apply(l,o),i=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,3',"'":'\'',""":'"'}[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?'"'+e+'":':'"'+e+'":{'}).join('')+e[n]+'}'.repeat(r.length)))}else t[n]=e[n];return t},{})},unfold:function(e,t){for(var n=[],r=[null,t];r=e(r[1]);)n.push(r[0]);return n},union:function(e,t){return Array.from(new Set([].concat(L(e),L(t))))},unionBy:function(e,t,n){var r=new Set(e.map(function(e){return n(e)}));return Array.from(new Set([].concat(I(e),I(t.filter(function(e){return!r.has(n(e))})))))},unionWith:function(e,t,n){return Array.from(new Set([].concat(w(e),w(t.filter(function(t){return-1===e.findIndex(function(e){return n(t,e)})})))))},uniqueElements:function(e){return[].concat(T(new Set(e)))},untildify:function(e){return e.replace(/^~($|\/|\\)/,('undefined'!=typeof require&&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:F.apply(Math,B(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:F.apply(Math,R(e.map(function(e){return e.length})))}).map(function(){return[]})).map(function(e){return t.apply(void 0,R(e))})},validateNumber:function(e){return!isNaN(parseFloat(e))&&isFinite(e)&&+e==e},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^$.randomBytes(1)[0]&15>>e/4).toString(16)})},all:function(e){var t=1=t.length?2===t.length?[t,t[1]+t[0]]:[t]:t.split('').reduce(function(n,r,l){return n.concat(e(t.slice(0,l)+t.slice(l+1)).map(function(e){return r+e}))},[])},any:function(e){var t=1'})},ary:function(t,r){return function(){for(var n=arguments.length,i=Array(n),l=0;lt||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 new Buffer(e,'binary').toString('base64')},byteSize:function(e){return new Blob([e]).size},call:function(e){for(var t=arguments.length,n=Array(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:P(e/8.64e7),hour:P(e/3.6e6)%24,minute:P(e/6e4)%60,second:P(e/1e3)%60,millisecond:P(e)%1e3};return Object.entries(t).filter(function(e){return 0!==e[1]}).map(function(e){return e[1]+' '+(1===e[1]?e[0]:e[0]+'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?', '+(255&n):'')+')'},hide:function(){for(var e=arguments.length,t=Array(e),n=0;nn&&(n=t),null==n?0<=e&&e=t&&ee[1]?-1:1,r=!0,l=!1;try{for(var o,a=e.entries()[Symbol.iterator]();!(r=(o=a.next()).done);r=!0){var s=o.value,c=re(s,2),d=c[0],i=c[1];if(d===e.length-1)return n;if(0<(i-e[d+1])*n)return 0}}catch(e){l=!0,t=e}finally{try{!r&&a.return&&a.return()}finally{if(l)throw t}}},isString:function(e){return'string'==typeof e},isSymbol:function(e){return'symbol'===('undefined'==typeof e?'undefined':ie(e))},isTravisCI:function(){return'TRAVIS'in process.env&&'CI'in process.env},isUndefined:function(e){return e===void 0},isUpperCase:function(e){return e===e.toUpperCase()},isValidJSON:function(e){try{return JSON.parse(e),!0}catch(t){return!1}},join:function(e){var t=1i-n&&(t='mouse',e(t),document.removeEventListener('mousemove',r)),n=i};document.addEventListener('touchstart',function(){'touch'==t||(t='touch',e(t),document.addEventListener('mousemove',r))})},once:function(e){var t=!1;return function(){if(!t){t=!0;for(var n=arguments.length,r=Array(n),i=0;ic?1:sG(e))return e+(r?' ':'')+i[0];var l=F(P(Math.log10(0>e?-e:e)/3),i.length-1),o=+((0>e?-e:e)/U(1e3,l)).toPrecision(t);return(0>e?'-':'')+o+(r?' ':'')+i[l]},primes:function(e){var t=Array.from({length:e-1}).map(function(e,t){return t+2}),n=P(z(e)),r=Array.from({length:n-1}).map(function(e,t){return t+2});return r.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),r=0;re[e.length-1],r=e.findIndex(function(e){return n?t>=e:t<=e});return-1===r?e.length:r},sortedIndexBy:function(e,t,n){var r=n(e[0])>n(e[e.length-1]),i=n(t),l=e.findIndex(function(e){return r?i>=n(e):i<=n(e)});return-1===l?e.length:l},sortedLastIndex:function(e,t){var n=e[0]>e[e.length-1],r=e.map(function(e,t){return[t,e]}).reverse().findIndex(function(e){return n?t<=e[1]:t>=e[1]});return-1===r?0:e.length-r-1},sortedLastIndexBy:function(e,t,n){var r=n(e[0])>n(e[e.length-1]),i=n(t),l=e.map(function(e,t){return[t,n(e)]}).reverse().findIndex(function(e){return r?i<=e[1]:i>=e[1]});return-1===l?0:e.length-l},splitLines:function(e){return e.split(/\r?\n/)},spreadOver:function(e){return function(t){return e.apply(void 0,C(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]*>/g,'')},sum:function(){for(var e=arguments.length,t=Array(e),n=0;n=t&&(e.apply(l,o),i=Date.now())},t-(Date.now()-i))):(e.apply(l,o),i=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 function(e){return function(t){return t.reduce(function(e,t){return e(t)},e)}}(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?'"'+e+'":':'"'+e+'":{'}).join('')+e[n]+'}'.repeat(r.length)))}else t[n]=e[n];return t},{})},unfold:function(e,t){for(var n=[],r=[null,t];r=e(r[1]);)n.push(r[0]);return n},union:function(e,t){return Array.from(new Set([].concat(w(e),w(t))))},unionBy:function(e,t,n){var r=new Set(e.map(function(e){return n(e)}));return Array.from(new Set([].concat(L(e),L(t.filter(function(e){return!r.has(n(e))})))))},unionWith:function(e,t,n){return Array.from(new Set([].concat(T(e),T(t.filter(function(t){return-1===e.findIndex(function(e){return n(t,e)})})))))},uniqueElements:function(e){return[].concat(B(new Set(e)))},untildify:function(e){return e.replace(/^~($|\/|\\)/,('undefined'!=typeof require&&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:H.apply(Math,R(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:H.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},without:function(e){for(var t=arguments.length,n=Array(1 (c ^ (crypto$1.randomBytes(1)[0] & (15 >> (c / 4)))).toString(16) ); +const all = (arr, fn = Boolean) => arr.every(fn); + const anagrams = str => { if (str.length <= 2) return str.length === 2 ? [str, str[1] + str[0]] : [str]; return str @@ -36,6 +38,10 @@ const anagrams = str => { ); }; +const any = (arr, fn = Boolean) => arr.some(fn); + +const approximatelyEqual = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) < epsilon; + const arrayToHtmlList = (arr, listID) => arr.map(item => (document.querySelector('#' + listID).innerHTML += `
  • ${item}
  • `)); @@ -57,6 +63,12 @@ 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, ...args) => function() { return fn.apply(context, args.concat(...arguments)); @@ -75,6 +87,17 @@ const bindKey = (context, fn, ...args) => return context[fn].apply(context, args.concat(...arguments)); }; +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); @@ -217,6 +240,8 @@ 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 = () => @@ -752,8 +777,19 @@ const minBy = (arr, fn) => Math.min(...arr.map(typeof fn === 'function' ? fn : v 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 none = (arr, fn = Boolean) => !arr.some(fn); + const nthArg = n => (...args) => args.slice(n)[0]; const nthElement = (arr, n = 0) => (n > 0 ? arr.slice(n, n + 1) : arr.slice(n))[0]; @@ -952,6 +988,8 @@ const pullBy = (arr, ...args) => { 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); @@ -1122,6 +1160,12 @@ 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( @@ -1272,6 +1316,12 @@ const truthCheckCollection = (collection, pre) => collection.every(obj => obj[pr 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, @@ -1373,6 +1423,6 @@ const zipWith = (...arrays) => { return fn ? result.map(arr => fn(...arr)) : result; }; -var imports = {JSONToFile,RGBToHex,URLJoin,UUIDGeneratorBrowser,UUIDGeneratorNode,anagrams,arrayToHtmlList,ary,atob,attempt,average,averageBy,bind,bindAll,bindKey,bottomVisible,btoa,byteSize,call,capitalize,capitalizeEveryWord,castArray,chainAsync,chunk,clampNumber,cloneRegExp,coalesce,coalesceFactory,collectInto,colorize,compact,compose,composeRight,converge,copyToClipboard,countBy,countOccurrences,createElement,createEventHub,currentURL,curry,debounce,decapitalize,deepClone,deepFlatten,defaults,defer,delay,detectDeviceType,difference,differenceBy,differenceWith,digitize,distance,drop,dropRight,dropRightWhile,dropWhile,elementIsVisibleInViewport,elo,equals,escapeHTML,escapeRegExp,everyNth,extendHex,factorial,fibonacci,filterNonUnique,findKey,findLast,findLastIndex,findLastKey,flatten,flattenObject,flip,forEachRight,forOwn,forOwnRight,formatDuration,fromCamelCase,functionName,functions,gcd,geometricProgression,get,getColonTimeFromDate,getDaysDiffBetweenDates,getMeridiemSuffixOfInteger,getScrollPosition,getStyle,getType,getURLParameters,groupBy,hammingDistance,hasClass,hasFlags,hashBrowser,hashNode,head,hexToRGB,hide,httpGet,httpPost,httpsRedirect,inRange,indexOfAll,initial,initialize2DArray,initializeArrayWithRange,initializeArrayWithRangeRight,initializeArrayWithValues,intersection,intersectionBy,intersectionWith,invertKeyValues,is,isAbsoluteURL,isArrayLike,isBoolean,isDivisible,isEmpty,isEven,isFunction,isLowerCase,isNil,isNull,isNumber,isObject,isObjectLike,isPlainObject,isPrime,isPrimitive,isPromiseLike,isSorted,isString,isSymbol,isTravisCI,isUndefined,isUpperCase,isValidJSON,join,last,lcm,longestItem,lowercaseKeys,luhnCheck,mapKeys,mapObject,mapValues,mask,matches,matchesWith,maxBy,maxN,median,memoize,merge,minBy,minN,negate,nthArg,nthElement,objectFromPairs,objectToPairs,observeMutations,off,omit,omitBy,on,onUserInputChange,once,orderBy,over,overArgs,palindrome,parseCookie,partial,partialRight,partition,percentile,pick,pickBy,pipeAsyncFunctions,pipeFunctions,pluralize,powerset,prettyBytes,primes,promisify,pull,pullAtIndex,pullAtValue,pullBy,randomHexColorCode,randomIntArrayInRange,randomIntegerInRange,randomNumberInRange,readFileLines,rearg,redirect,reduceSuccessive,reduceWhich,reducedFilter,remove,removeNonASCII,reverseString,round,runAsync,runPromisesInSeries,sample,sampleSize,scrollToTop,sdbm,serializeCookie,setStyle,shallowClone,show,shuffle,similarity,size,sleep,sortCharactersInString,sortedIndex,sortedIndexBy,sortedLastIndex,sortedLastIndexBy,splitLines,spreadOver,standardDeviation,stripHTMLTags,sum,sumBy,sumPower,symmetricDifference,symmetricDifferenceBy,symmetricDifferenceWith,tail,take,takeRight,takeRightWhile,takeWhile,throttle,timeTaken,times,toCamelCase,toCurrency,toDecimalMark,toKebabCase,toOrdinalSuffix,toSafeInteger,toSnakeCase,toggleClass,tomorrow,transform,truncateString,truthCheckCollection,unary,unescapeHTML,unflattenObject,unfold,union,unionBy,unionWith,uniqueElements,untildify,unzip,unzipWith,validateNumber,without,words,xProd,yesNo,zip,zipObject,zipWith,} +var imports = {JSONToFile,RGBToHex,URLJoin,UUIDGeneratorBrowser,UUIDGeneratorNode,all,anagrams,any,approximatelyEqual,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,createElement,createEventHub,currentURL,curry,debounce,decapitalize,deepClone,deepFlatten,defaults,defer,degreesToRads,delay,detectDeviceType,difference,differenceBy,differenceWith,digitize,distance,drop,dropRight,dropRightWhile,dropWhile,elementIsVisibleInViewport,elo,equals,escapeHTML,escapeRegExp,everyNth,extendHex,factorial,fibonacci,filterNonUnique,findKey,findLast,findLastIndex,findLastKey,flatten,flattenObject,flip,forEachRight,forOwn,forOwnRight,formatDuration,fromCamelCase,functionName,functions,gcd,geometricProgression,get,getColonTimeFromDate,getDaysDiffBetweenDates,getMeridiemSuffixOfInteger,getScrollPosition,getStyle,getType,getURLParameters,groupBy,hammingDistance,hasClass,hasFlags,hashBrowser,hashNode,head,hexToRGB,hide,httpGet,httpPost,httpsRedirect,inRange,indexOfAll,initial,initialize2DArray,initializeArrayWithRange,initializeArrayWithRangeRight,initializeArrayWithValues,intersection,intersectionBy,intersectionWith,invertKeyValues,is,isAbsoluteURL,isArrayLike,isBoolean,isDivisible,isEmpty,isEven,isFunction,isLowerCase,isNil,isNull,isNumber,isObject,isObjectLike,isPlainObject,isPrime,isPrimitive,isPromiseLike,isSorted,isString,isSymbol,isTravisCI,isUndefined,isUpperCase,isValidJSON,join,last,lcm,longestItem,lowercaseKeys,luhnCheck,mapKeys,mapObject,mapValues,mask,matches,matchesWith,maxBy,maxN,median,memoize,merge,minBy,minN,mostPerformant,negate,none,nthArg,nthElement,objectFromPairs,objectToPairs,observeMutations,off,omit,omitBy,on,onUserInputChange,once,orderBy,over,overArgs,palindrome,parseCookie,partial,partialRight,partition,percentile,pick,pickBy,pipeAsyncFunctions,pipeFunctions,pluralize,powerset,prettyBytes,primes,promisify,pull,pullAtIndex,pullAtValue,pullBy,radsToDegrees,randomHexColorCode,randomIntArrayInRange,randomIntegerInRange,randomNumberInRange,readFileLines,rearg,redirect,reduceSuccessive,reduceWhich,reducedFilter,remove,removeNonASCII,reverseString,round,runAsync,runPromisesInSeries,sample,sampleSize,scrollToTop,sdbm,serializeCookie,setStyle,shallowClone,show,shuffle,similarity,size,sleep,sortCharactersInString,sortedIndex,sortedIndexBy,sortedLastIndex,sortedLastIndexBy,splitLines,spreadOver,stableSort,standardDeviation,stripHTMLTags,sum,sumBy,sumPower,symmetricDifference,symmetricDifferenceBy,symmetricDifferenceWith,tail,take,takeRight,takeRightWhile,takeWhile,throttle,timeTaken,times,toCamelCase,toCurrency,toDecimalMark,toKebabCase,toOrdinalSuffix,toSafeInteger,toSnakeCase,toggleClass,tomorrow,transform,truncateString,truthCheckCollection,unary,uncurry,unescapeHTML,unflattenObject,unfold,union,unionBy,unionWith,uniqueElements,untildify,unzip,unzipWith,validateNumber,without,words,xProd,yesNo,zip,zipObject,zipWith,} export default imports; diff --git a/dist/_30s.js b/dist/_30s.js index e18bc84a1..b57412c38 100644 --- a/dist/_30s.js +++ b/dist/_30s.js @@ -31,6 +31,8 @@ const UUIDGeneratorNode = () => (c ^ (crypto$1.randomBytes(1)[0] & (15 >> (c / 4)))).toString(16) ); +const all = (arr, fn = Boolean) => arr.every(fn); + const anagrams = str => { if (str.length <= 2) return str.length === 2 ? [str, str[1] + str[0]] : [str]; return str @@ -42,6 +44,10 @@ const anagrams = str => { ); }; +const any = (arr, fn = Boolean) => arr.some(fn); + +const approximatelyEqual = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) < epsilon; + const arrayToHtmlList = (arr, listID) => arr.map(item => (document.querySelector('#' + listID).innerHTML += `
  • ${item}
  • `)); @@ -63,6 +69,12 @@ 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, ...args) => function() { return fn.apply(context, args.concat(...arguments)); @@ -81,6 +93,17 @@ const bindKey = (context, fn, ...args) => return context[fn].apply(context, args.concat(...arguments)); }; +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); @@ -223,6 +246,8 @@ 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 = () => @@ -758,8 +783,19 @@ const minBy = (arr, fn) => Math.min(...arr.map(typeof fn === 'function' ? fn : v 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 none = (arr, fn = Boolean) => !arr.some(fn); + const nthArg = n => (...args) => args.slice(n)[0]; const nthElement = (arr, n = 0) => (n > 0 ? arr.slice(n, n + 1) : arr.slice(n))[0]; @@ -958,6 +994,8 @@ const pullBy = (arr, ...args) => { 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); @@ -1128,6 +1166,12 @@ 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( @@ -1278,6 +1322,12 @@ const truthCheckCollection = (collection, pre) => collection.every(obj => obj[pr 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, @@ -1379,7 +1429,7 @@ const zipWith = (...arrays) => { return fn ? result.map(arr => fn(...arr)) : result; }; -var imports = {JSONToFile,RGBToHex,URLJoin,UUIDGeneratorBrowser,UUIDGeneratorNode,anagrams,arrayToHtmlList,ary,atob,attempt,average,averageBy,bind,bindAll,bindKey,bottomVisible,btoa,byteSize,call,capitalize,capitalizeEveryWord,castArray,chainAsync,chunk,clampNumber,cloneRegExp,coalesce,coalesceFactory,collectInto,colorize,compact,compose,composeRight,converge,copyToClipboard,countBy,countOccurrences,createElement,createEventHub,currentURL,curry,debounce,decapitalize,deepClone,deepFlatten,defaults,defer,delay,detectDeviceType,difference,differenceBy,differenceWith,digitize,distance,drop,dropRight,dropRightWhile,dropWhile,elementIsVisibleInViewport,elo,equals,escapeHTML,escapeRegExp,everyNth,extendHex,factorial,fibonacci,filterNonUnique,findKey,findLast,findLastIndex,findLastKey,flatten,flattenObject,flip,forEachRight,forOwn,forOwnRight,formatDuration,fromCamelCase,functionName,functions,gcd,geometricProgression,get,getColonTimeFromDate,getDaysDiffBetweenDates,getMeridiemSuffixOfInteger,getScrollPosition,getStyle,getType,getURLParameters,groupBy,hammingDistance,hasClass,hasFlags,hashBrowser,hashNode,head,hexToRGB,hide,httpGet,httpPost,httpsRedirect,inRange,indexOfAll,initial,initialize2DArray,initializeArrayWithRange,initializeArrayWithRangeRight,initializeArrayWithValues,intersection,intersectionBy,intersectionWith,invertKeyValues,is,isAbsoluteURL,isArrayLike,isBoolean,isDivisible,isEmpty,isEven,isFunction,isLowerCase,isNil,isNull,isNumber,isObject,isObjectLike,isPlainObject,isPrime,isPrimitive,isPromiseLike,isSorted,isString,isSymbol,isTravisCI,isUndefined,isUpperCase,isValidJSON,join,last,lcm,longestItem,lowercaseKeys,luhnCheck,mapKeys,mapObject,mapValues,mask,matches,matchesWith,maxBy,maxN,median,memoize,merge,minBy,minN,negate,nthArg,nthElement,objectFromPairs,objectToPairs,observeMutations,off,omit,omitBy,on,onUserInputChange,once,orderBy,over,overArgs,palindrome,parseCookie,partial,partialRight,partition,percentile,pick,pickBy,pipeAsyncFunctions,pipeFunctions,pluralize,powerset,prettyBytes,primes,promisify,pull,pullAtIndex,pullAtValue,pullBy,randomHexColorCode,randomIntArrayInRange,randomIntegerInRange,randomNumberInRange,readFileLines,rearg,redirect,reduceSuccessive,reduceWhich,reducedFilter,remove,removeNonASCII,reverseString,round,runAsync,runPromisesInSeries,sample,sampleSize,scrollToTop,sdbm,serializeCookie,setStyle,shallowClone,show,shuffle,similarity,size,sleep,sortCharactersInString,sortedIndex,sortedIndexBy,sortedLastIndex,sortedLastIndexBy,splitLines,spreadOver,standardDeviation,stripHTMLTags,sum,sumBy,sumPower,symmetricDifference,symmetricDifferenceBy,symmetricDifferenceWith,tail,take,takeRight,takeRightWhile,takeWhile,throttle,timeTaken,times,toCamelCase,toCurrency,toDecimalMark,toKebabCase,toOrdinalSuffix,toSafeInteger,toSnakeCase,toggleClass,tomorrow,transform,truncateString,truthCheckCollection,unary,unescapeHTML,unflattenObject,unfold,union,unionBy,unionWith,uniqueElements,untildify,unzip,unzipWith,validateNumber,without,words,xProd,yesNo,zip,zipObject,zipWith,} +var imports = {JSONToFile,RGBToHex,URLJoin,UUIDGeneratorBrowser,UUIDGeneratorNode,all,anagrams,any,approximatelyEqual,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,createElement,createEventHub,currentURL,curry,debounce,decapitalize,deepClone,deepFlatten,defaults,defer,degreesToRads,delay,detectDeviceType,difference,differenceBy,differenceWith,digitize,distance,drop,dropRight,dropRightWhile,dropWhile,elementIsVisibleInViewport,elo,equals,escapeHTML,escapeRegExp,everyNth,extendHex,factorial,fibonacci,filterNonUnique,findKey,findLast,findLastIndex,findLastKey,flatten,flattenObject,flip,forEachRight,forOwn,forOwnRight,formatDuration,fromCamelCase,functionName,functions,gcd,geometricProgression,get,getColonTimeFromDate,getDaysDiffBetweenDates,getMeridiemSuffixOfInteger,getScrollPosition,getStyle,getType,getURLParameters,groupBy,hammingDistance,hasClass,hasFlags,hashBrowser,hashNode,head,hexToRGB,hide,httpGet,httpPost,httpsRedirect,inRange,indexOfAll,initial,initialize2DArray,initializeArrayWithRange,initializeArrayWithRangeRight,initializeArrayWithValues,intersection,intersectionBy,intersectionWith,invertKeyValues,is,isAbsoluteURL,isArrayLike,isBoolean,isDivisible,isEmpty,isEven,isFunction,isLowerCase,isNil,isNull,isNumber,isObject,isObjectLike,isPlainObject,isPrime,isPrimitive,isPromiseLike,isSorted,isString,isSymbol,isTravisCI,isUndefined,isUpperCase,isValidJSON,join,last,lcm,longestItem,lowercaseKeys,luhnCheck,mapKeys,mapObject,mapValues,mask,matches,matchesWith,maxBy,maxN,median,memoize,merge,minBy,minN,mostPerformant,negate,none,nthArg,nthElement,objectFromPairs,objectToPairs,observeMutations,off,omit,omitBy,on,onUserInputChange,once,orderBy,over,overArgs,palindrome,parseCookie,partial,partialRight,partition,percentile,pick,pickBy,pipeAsyncFunctions,pipeFunctions,pluralize,powerset,prettyBytes,primes,promisify,pull,pullAtIndex,pullAtValue,pullBy,radsToDegrees,randomHexColorCode,randomIntArrayInRange,randomIntegerInRange,randomNumberInRange,readFileLines,rearg,redirect,reduceSuccessive,reduceWhich,reducedFilter,remove,removeNonASCII,reverseString,round,runAsync,runPromisesInSeries,sample,sampleSize,scrollToTop,sdbm,serializeCookie,setStyle,shallowClone,show,shuffle,similarity,size,sleep,sortCharactersInString,sortedIndex,sortedIndexBy,sortedLastIndex,sortedLastIndexBy,splitLines,spreadOver,stableSort,standardDeviation,stripHTMLTags,sum,sumBy,sumPower,symmetricDifference,symmetricDifferenceBy,symmetricDifferenceWith,tail,take,takeRight,takeRightWhile,takeWhile,throttle,timeTaken,times,toCamelCase,toCurrency,toDecimalMark,toKebabCase,toOrdinalSuffix,toSafeInteger,toSnakeCase,toggleClass,tomorrow,transform,truncateString,truthCheckCollection,unary,uncurry,unescapeHTML,unflattenObject,unfold,union,unionBy,unionWith,uniqueElements,untildify,unzip,unzipWith,validateNumber,without,words,xProd,yesNo,zip,zipObject,zipWith,} return imports; diff --git a/dist/_30s.min.js b/dist/_30s.min.js index 5004ecf1b..acdc95069 100644 --- a/dist/_30s.min.js +++ b/dist/_30s.min.js @@ -1 +1 @@ -(function(a,b){'object'==typeof exports&&'undefined'!=typeof module?module.exports=b():'function'==typeof define&&define.amd?define(b):a._30s=b()})(this,function(){'use strict';var a=Math.round,b=Math.sqrt,c=Math.log,d=Math.floor,e=Math.min,g=Math.max,h=Math.ceil;const i='undefined'!=typeof require&&require('fs'),j='undefined'!=typeof require&&require('crypto'),k=(a)=>2>=a.length?2===a.length?[a,a[1]+a[0]]:[a]:a.split('').reduce((b,c,d)=>b.concat(k(a.slice(0,d)+a.slice(d+1)).map((a)=>c+a)),[]),l=(a,b=a.length,...c)=>b<=c.length?a(...c):l.bind(null,a,b,...c),m=(a)=>{let b=Object.assign({},a);return Object.keys(b).forEach((c)=>b[c]='object'==typeof a[c]?m(a[c]):a[c]),b},n=(a)=>[].concat(...a.map((a)=>Array.isArray(a)?n(a):a)),o=([...c],d=32,e)=>{const[g,a]=c,b=(a,b)=>1/(1+10**((b-a)/400)),h=(c,h)=>(e||c)+d*(h-b(h?g:a,h?a:g));if(2===c.length)return[h(g,1),h(a,0)];for(let a,b=0;b{if(c===d)return!0;if(c instanceof Date&&d instanceof Date)return c.getTime()===d.getTime();if(!c||!d||'object'!=typeof c&&'object'!=typeof d)return c===d;if(null===c||void 0===c||null===d||void 0===d)return!1;if(c.prototype!==d.prototype)return!1;let e=Object.keys(c);return!(e.length!==Object.keys(d).length)&&e.every((a)=>p(c[a],d[a]))},q=(a)=>0>a?(()=>{throw new TypeError('Negative numbers are not allowed!')})():1>=a?1:a*q(a-1),r=(a,b=1)=>1===b?a.reduce((b,a)=>b.concat(a),[]):a.reduce((c,a)=>c.concat(Array.isArray(a)?r(a,b-1):a),[]),s=(a,b='')=>Object.keys(a).reduce((c,d)=>{const e=b.length?b+'.':'';return'object'==typeof a[d]?Object.assign(c,s(a[d],e+d)):c[e+d]=a[d],c},{}),t=(...a)=>{const c=(a,b)=>b?t(b,a%b):a;return[...a].reduce((d,a)=>c(d,a))},u='undefined'!=typeof require&&require('crypto'),v='undefined'!=typeof require&&require('fs'),w=()=>{const a=document.documentElement.scrollTop||document.body.scrollTop;0i.writeFile(`${b}.json`,JSON.stringify(a,null,2)),RGBToHex:(a,c,d)=>((a<<16)+(c<<8)+d).toString(16).padStart(6,'0'),URLJoin:(...a)=>a.join('/').replace(/[\/]+/g,'/').replace(/^(.+):\//,'$1://').replace(/^file:/,'file:/').replace(/\/(\?|&|#[^!])/g,'$1').replace(/\?/g,'&').replace('&','?'),UUIDGeneratorBrowser:()=>'10000000-1000-4000-8000-100000000000'.replace(/[018]/g,(a)=>(a^crypto.getRandomValues(new Uint8Array(1))[0]&15>>a/4).toString(16)),UUIDGeneratorNode:()=>'10000000-1000-4000-8000-100000000000'.replace(/[018]/g,(a)=>(a^j.randomBytes(1)[0]&15>>a/4).toString(16)),anagrams:k,arrayToHtmlList:(a,b)=>a.map((a)=>document.querySelector('#'+b).innerHTML+=`
  • ${a}
  • `),ary:(a,b)=>(...c)=>a(...c.slice(0,b)),atob:(a)=>new Buffer(a,'base64').toString('binary'),attempt:(a,...b)=>{try{return a(b)}catch(a){return a instanceof Error?a:new Error(a)}},average:(...a)=>[...a].reduce((a,b)=>a+b,0)/a.length,averageBy:(a,b)=>a.map('function'==typeof b?b:(a)=>a[b]).reduce((a,b)=>a+b,0)/a.length,bind:(a,b,...c)=>function(){return a.apply(b,c.concat(...arguments))},bindAll:(a,...b)=>b.forEach((b)=>(f=a[b],a[b]=function(){return f.apply(a)})),bindKey:(a,b,...c)=>function(){return a[b].apply(a,c.concat(...arguments))},bottomVisible:()=>document.documentElement.clientHeight+window.scrollY>=(document.documentElement.scrollHeight||document.documentElement.clientHeight),btoa:(a)=>new Buffer(a,'binary').toString('base64'),byteSize:(a)=>new Blob([a]).size,call:(a,...b)=>(c)=>c[a](...b),capitalize:([a,...b],c=!1)=>a.toUpperCase()+(c?b.join('').toLowerCase():b.join('')),capitalizeEveryWord:(a)=>a.replace(/\b[a-z]/g,(a)=>a.toUpperCase()),castArray:(a)=>Array.isArray(a)?a:[a],chainAsync:(a)=>{let b=0;const c=()=>a[b++](c);c()},chunk:(a,b)=>Array.from({length:h(a.length/b)},(c,d)=>a.slice(d*b,d*b+b)),clampNumber:(c,d,a)=>g(e(c,g(d,a)),e(d,a)),cloneRegExp:(a)=>new RegExp(a.source,a.flags),coalesce:(...a)=>a.find((a)=>![void 0,null].includes(a)),coalesceFactory:(a)=>(...b)=>b.find(a),collectInto:(a)=>(...b)=>a(b),colorize:(...a)=>({black:`\x1b[30m${a.join(' ')}`,red:`\x1b[31m${a.join(' ')}`,green:`\x1b[32m${a.join(' ')}`,yellow:`\x1b[33m${a.join(' ')}`,blue:`\x1b[34m${a.join(' ')}`,magenta:`\x1b[35m${a.join(' ')}`,cyan:`\x1b[36m${a.join(' ')}`,white:`\x1b[37m${a.join(' ')}`,bgBlack:`\x1b[40m${a.join(' ')}\x1b[0m`,bgRed:`\x1b[41m${a.join(' ')}\x1b[0m`,bgGreen:`\x1b[42m${a.join(' ')}\x1b[0m`,bgYellow:`\x1b[43m${a.join(' ')}\x1b[0m`,bgBlue:`\x1b[44m${a.join(' ')}\x1b[0m`,bgMagenta:`\x1b[45m${a.join(' ')}\x1b[0m`,bgCyan:`\x1b[46m${a.join(' ')}\x1b[0m`,bgWhite:`\x1b[47m${a.join(' ')}\x1b[0m`}),compact:(a)=>a.filter(Boolean),compose:(...a)=>a.reduce((a,b)=>(...c)=>a(b(...c))),composeRight:(...a)=>a.reduce((a,b)=>(...c)=>b(a(...c))),converge:(a,b)=>(...c)=>a(...b.map((a)=>a.apply(null,c))),copyToClipboard:(a)=>{const b=document.createElement('textarea');b.value=a,b.setAttribute('readonly',''),b.style.position='absolute',b.style.left='-9999px',document.body.appendChild(b);const c=!!(0a.map('function'==typeof b?b:(a)=>a[b]).reduce((a,b)=>(a[b]=(a[b]||0)+1,a),{}),countOccurrences:(a,b)=>a.reduce((c,a)=>a===b?c+1:c+0,0),createElement:(a)=>{const b=document.createElement('div');return b.innerHTML=a,b.firstElementChild},createEventHub:()=>({hub:Object.create(null),emit(a,b){(this.hub[a]||[]).forEach((a)=>a(b))},on(a,b){this.hub[a]||(this.hub[a]=[]),this.hub[a].push(b)},off(a,b){const c=(this.hub[a]||[]).findIndex((a)=>a===b);-1window.location.href,curry:l,debounce:(a,b=0)=>{let c;return function(...d){clearTimeout(c),c=setTimeout(()=>a.apply(this,d),b)}},decapitalize:([a,...b],c=!1)=>a.toLowerCase()+(c?b.join('').toUpperCase():b.join('')),deepClone:m,deepFlatten:n,defaults:(a,...b)=>Object.assign({},a,...b.reverse(),a),defer:(a,...b)=>setTimeout(a,1,...b),delay:(a,b,...c)=>setTimeout(a,b,...c),detectDeviceType:()=>/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)?'Mobile':'Desktop',difference:(c,a)=>{const b=new Set(a);return c.filter((a)=>!b.has(a))},differenceBy:(c,a,b)=>{const d=new Set(a.map((a)=>b(a)));return c.filter((a)=>!d.has(b(a)))},differenceWith:(a,b,c)=>a.filter((d)=>-1===b.findIndex((a)=>c(d,a))),digitize:(a)=>[...`${a}`].map((a)=>parseInt(a)),distance:(a,b,c,d)=>Math.hypot(c-a,d-b),drop:(a,b=1)=>a.slice(b),dropRight:(a,b=1)=>a.slice(0,-b),dropRightWhile:(a,b)=>{for(;0{for(;0{const{top:c,left:d,bottom:e,right:g}=a.getBoundingClientRect(),{innerHeight:h,innerWidth:i}=window;return b?(0a.replace(/[&<>'"]/g,(a)=>({"&":'&',"<":'<',">":'>',"'":''','"':'"'})[a]||a),escapeRegExp:(a)=>a.replace(/[.*+?^${}()|[\]\\]/g,'\\$&'),everyNth:(a,b)=>a.filter((a,c)=>c%b==b-1),extendHex:(a)=>'#'+a.slice(a.startsWith('#')?1:0).split('').map((a)=>a+a).join(''),factorial:q,fibonacci:(a)=>Array.from({length:a}).reduce((a,b,c)=>a.concat(1a.filter((b)=>a.indexOf(b)===a.lastIndexOf(b)),findKey:(a,b)=>Object.keys(a).find((c)=>b(a[c],c,a)),findLast:(a,b)=>a.filter(b).slice(-1)[0],findLastIndex:(a,b)=>a.map((a,b)=>[b,a]).filter((c)=>b(c[1],c[0],a)).slice(-1)[0][0],findLastKey:(a,b)=>Object.keys(a).reverse().find((c)=>b(a[c],c,a)),flatten:r,flattenObject:s,flip:(a)=>(b,...c)=>a(...c,b),forEachRight:(a,b)=>a.slice(0).reverse().forEach(b),forOwn:(a,b)=>Object.keys(a).forEach((c)=>b(a[c],c,a)),forOwnRight:(a,b)=>Object.keys(a).reverse().forEach((c)=>b(a[c],c,a)),formatDuration:(a)=>{0>a&&(a=-a);const b={day:d(a/8.64e7),hour:d(a/3.6e6)%24,minute:d(a/6e4)%60,second:d(a/1e3)%60,millisecond:d(a)%1e3};return Object.entries(b).filter((a)=>0!==a[1]).map((a)=>a[1]+' '+(1===a[1]?a[0]:a[0]+'s')).join(', ')},fromCamelCase:(a,b='_')=>a.replace(/([a-z\d])([A-Z])/g,'$1'+b+'$2').replace(/([A-Z]+)([A-Z][a-z\d]+)/g,'$1'+b+'$2').toLowerCase(),functionName:(a)=>(console.debug(a.name),a),functions:(a,b=!1)=>(b?[...Object.keys(a),...Object.keys(Object.getPrototypeOf(a))]:Object.keys(a)).filter((b)=>'function'==typeof a[b]),gcd:t,geometricProgression:(a,b=1,e=2)=>Array.from({length:d(c(a/b)/c(e))+1}).map((a,c)=>b*e**c),get:(a,...b)=>[...b].map((b)=>b.replace(/\[([^\[\]]*)\]/g,'.$1.').split('.').filter((a)=>''!==a).reduce((a,b)=>a&&a[b],a)),getColonTimeFromDate:(a)=>a.toTimeString().slice(0,8),getDaysDiffBetweenDates:(a,b)=>(b-a)/86400000,getMeridiemSuffixOfInteger:(a)=>0===a||24===a?'12am':12===a?'12pm':12>a?a%12+'am':a%12+'pm',getScrollPosition:(a=window)=>({x:a.pageXOffset===void 0?a.scrollLeft:a.pageXOffset,y:a.pageYOffset===void 0?a.scrollTop:a.pageYOffset}),getStyle:(a,b)=>getComputedStyle(a)[b],getType:(a)=>a===void 0?'undefined':null===a?'null':a.constructor.name.toLowerCase(),getURLParameters:(a)=>(a.match(/([^?=&]+)(=([^&]*))/g)||[]).reduce((b,a)=>(b[a.slice(0,a.indexOf('='))]=a.slice(a.indexOf('=')+1),b),{}),groupBy:(a,b)=>a.map('function'==typeof b?b:(a)=>a[b]).reduce((b,c,d)=>(b[c]=(b[c]||[]).concat(a[d]),b),{}),hammingDistance:(a,b)=>((a^b).toString(2).match(/1/g)||'').length,hasClass:(a,b)=>a.classList.contains(b),hasFlags:(...a)=>a.every((a)=>process.argv.includes(/^-{1,2}/.test(a)?a:'--'+a)),hashBrowser:(a)=>crypto.subtle.digest('SHA-256',new TextEncoder('utf-8').encode(a)).then((a)=>{let b=[],c=new DataView(a);for(let d=0;dnew Promise((b)=>setTimeout(()=>b(u.createHash('sha256').update(a).digest('hex')),0)),head:(a)=>a[0],hexToRGB:(a)=>{let b=!1,c=a.slice(a.startsWith('#')?1:0);return 3===c.length?c=[...c].map((a)=>a+a).join(''):8===c.length&&(b=!0),c=parseInt(c,16),'rgb'+(b?'a':'')+'('+(c>>>(b?24:16))+', '+((c&(b?16711680:65280))>>>(b?16:8))+', '+((c&(b?65280:255))>>>(b?8:0))+(b?`, ${255&c}`:'')+')'},hide:(...a)=>[...a].forEach((a)=>a.style.display='none'),httpGet:(a,b,c=console.error)=>{const d=new XMLHttpRequest;d.open('GET',a,!0),d.onload=()=>b(d.responseText),d.onerror=()=>c(d),d.send()},httpPost:(a,b,c,d=console.error)=>{const e=new XMLHttpRequest;e.open('POST',a,!0),e.setRequestHeader('Content-type','application/json; charset=utf-8'),e.onload=()=>c(e.responseText),e.onerror=()=>d(e),e.send(b)},httpsRedirect:()=>{'https:'!==location.protocol&&location.replace('https://'+location.href.split('//')[1])},inRange:(a,b,c=null)=>(c&&b>c&&(c=b),null==c?0<=a&&a=b&&a{const c=[];return a.forEach((a,d)=>a===b&&c.push(d)),c},initial:(a)=>a.slice(0,-1),initialize2DArray:(a,b,c=null)=>Array.from({length:b}).map(()=>Array.from({length:a}).fill(c)),initializeArrayWithRange:(a,b=0,c=1)=>Array.from({length:h((a+1-b)/c)}).map((a,d)=>d*c+b),initializeArrayWithRangeRight:(a,b=0,c=1)=>Array.from({length:h((a+1-b)/c)}).map((a,d,e)=>(e.length-d-1)*c+b),initializeArrayWithValues:(a,b=0)=>Array(a).fill(b),intersection:(c,a)=>{const b=new Set(a);return c.filter((a)=>b.has(a))},intersectionBy:(c,a,b)=>{const d=new Set(a.map((a)=>b(a)));return c.filter((a)=>d.has(b(a)))},intersectionWith:(c,a,b)=>c.filter((c)=>-1!==a.findIndex((a)=>b(c,a))),invertKeyValues:(a,b)=>Object.keys(a).reduce((c,d)=>{const e=b?b(a[d]):a[d];return c[e]=c[e]||[],c[e].push(d),c},{}),is:(a,b)=>b instanceof a,isAbsoluteURL:(a)=>/^[a-z][a-z0-9+.-]*:/.test(a),isArrayLike:(a)=>{try{return[...a],!0}catch(a){return!1}},isBoolean:(a)=>'boolean'==typeof a,isDivisible:(a,b)=>0==a%b,isEmpty:(a)=>null==a||!(Object.keys(a)||a).length,isEven:(a)=>0==a%2,isFunction:(a)=>'function'==typeof a,isLowerCase:(a)=>a===a.toLowerCase(),isNil:(a)=>a===void 0||null===a,isNull:(a)=>null===a,isNumber:(a)=>'number'==typeof a,isObject:(a)=>a===Object(a),isObjectLike:(a)=>null!==a&&'object'==typeof a,isPlainObject:(a)=>!!a&&'object'==typeof a&&a.constructor===Object,isPrime:(a)=>{const c=d(b(a));for(var e=2;e<=c;e++)if(0==a%e)return!1;return 2<=a},isPrimitive:(a)=>!['object','function'].includes(typeof a)||null===a,isPromiseLike:(a)=>null!==a&&('object'==typeof a||'function'==typeof a)&&'function'==typeof a.then,isSorted:(a)=>{const b=a[0]>a[1]?-1:1;for(let[c,d]of a.entries()){if(c===a.length-1)return b;if(0<(d-a[c+1])*b)return 0}},isString:(a)=>'string'==typeof a,isSymbol:(a)=>'symbol'==typeof a,isTravisCI:()=>'TRAVIS'in process.env&&'CI'in process.env,isUndefined:(a)=>a===void 0,isUpperCase:(a)=>a===a.toUpperCase(),isValidJSON:(a)=>{try{return JSON.parse(a),!0}catch(a){return!1}},join:(a,b=',',c=b)=>a.reduce((d,e,g)=>g===a.length-2?d+e+c:g===a.length-1?d+e:d+e+b,''),last:(a)=>a[a.length-1],lcm:(...a)=>{const b=(a,c)=>c?b(c,a%c):a,c=(a,c)=>a*c/b(a,c);return[...a].reduce((d,a)=>c(d,a))},longestItem:(...a)=>[...a].sort((c,a)=>a.length-c.length)[0],lowercaseKeys:(a)=>Object.keys(a).reduce((b,c)=>(b[c.toLowerCase()]=a[c],b),{}),luhnCheck:(a)=>{let b=(a+'').split('').reverse().map((a)=>parseInt(a)),c=b.splice(0,1)[0],d=b.reduce((a,b,c)=>0==c%2?a+2*b%9||9:a+b,0);return d+=c,0==d%10},mapKeys:(a,b)=>Object.keys(a).reduce((c,d)=>(c[b(a[d],d,a)]=a[d],c),{}),mapObject:(b,c)=>((d)=>(d=[b,b.map(c)],d[0].reduce((a,b,c)=>(a[b]=d[1][c],a),{})))(),mapValues:(a,b)=>Object.keys(a).reduce((c,d)=>(c[d]=b(a[d],d,a),c),{}),mask:(a,b=4,c='*')=>(''+a).slice(0,-b).replace(/./g,c)+(''+a).slice(-b),matches:(a,b)=>Object.keys(b).every((c)=>a.hasOwnProperty(c)&&a[c]===b[c]),matchesWith:(a,b,c)=>Object.keys(b).every((d)=>a.hasOwnProperty(d)&&c?c(a[d],b[d],d,a,b):a[d]==b[d]),maxBy:(a,b)=>g(...a.map('function'==typeof b?b:(a)=>a[b])),maxN:(a,b=1)=>[...a].sort((c,a)=>a-c).slice(0,b),median:(a)=>{const b=d(a.length/2),c=[...a].sort((c,a)=>c-a);return 0==a.length%2?(c[b-1]+c[b])/2:c[b]},memoize:(a)=>{const b=new Map,c=function(c){return b.has(c)?b.get(c):b.set(c,a.call(this,c))&&b.get(c)};return c.cache=b,c},merge:(...a)=>[...a].reduce((b,c)=>Object.keys(c).reduce((d,a)=>(b[a]=b.hasOwnProperty(a)?[].concat(b[a]).concat(c[a]):c[a],b),{}),{}),minBy:(a,b)=>e(...a.map('function'==typeof b?b:(a)=>a[b])),minN:(a,b=1)=>[...a].sort((c,a)=>c-a).slice(0,b),negate:(a)=>(...b)=>!a(...b),nthArg:(a)=>(...b)=>b.slice(a)[0],nthElement:(a,b=0)=>(0a.reduce((b,a)=>(b[a[0]]=a[1],b),{}),objectToPairs:(a)=>Object.keys(a).map((b)=>[b,a[b]]),observeMutations:(a,b,c)=>{const d=new MutationObserver((a)=>a.forEach((a)=>b(a)));return d.observe(a,Object.assign({childList:!0,attributes:!0,attributeOldValue:!0,characterData:!0,characterDataOldValue:!0,subtree:!0},c)),d},off:(a,b,c,d=!1)=>a.removeEventListener(b,c,d),omit:(a,b)=>Object.keys(a).filter((a)=>!b.includes(a)).reduce((b,c)=>(b[c]=a[c],b),{}),omitBy:(a,b)=>Object.keys(a).filter((c)=>!b(a[c],c)).reduce((b,c)=>(b[c]=a[c],b),{}),on:(a,b,c,d={})=>{const e=(a)=>a.target.matches(d.target)&&c.call(a.target,a);if(a.addEventListener(b,d.target?e:c,d.options||!1),d.target)return e},onUserInputChange:(a)=>{let b='mouse',c=0;const d=()=>{const e=performance.now();20>e-c&&(b='mouse',a(b),document.removeEventListener('mousemove',d)),c=e};document.addEventListener('touchstart',()=>{'touch'==b||(b='touch',a(b),document.addEventListener('mousemove',d))})},once:(a)=>{let b=!1;return function(...c){if(!b)return b=!0,a.apply(this,c)}},orderBy:(a,c,d)=>[...a].sort((e,a)=>c.reduce((b,c,g)=>{if(0===b){const[h,i]=d&&'desc'===d[g]?[a[c],e[c]]:[e[c],a[c]];b=h>i?1:h(...b)=>a.map((a)=>a.apply(null,b)),overArgs:(a,b)=>(...c)=>a(...c.map((a,c)=>b[c](a))),palindrome:(a)=>{const b=a.toLowerCase().replace(/[\W_]/g,'');return b===b.split('').reverse().join('')},parseCookie:(a)=>a.split(';').map((a)=>a.split('=')).reduce((a,b)=>(a[decodeURIComponent(b[0].trim())]=decodeURIComponent(b[1].trim()),a),{}),partial:(a,...b)=>(...c)=>a(...b,...c),partialRight:(a,...b)=>(...c)=>a(...c,...b),partition:(a,b)=>a.reduce((a,c,d,e)=>(a[b(c,d,e)?0:1].push(c),a),[[],[]]),percentile:(a,b)=>100*a.reduce((a,c)=>a+(cb.reduce((b,c)=>(c in a&&(b[c]=a[c]),b),{}),pickBy:(a,b)=>Object.keys(a).filter((c)=>b(a[c],c)).reduce((b,c)=>(b[c]=a[c],b),{}),pipeAsyncFunctions:(...a)=>(b)=>a.reduce((a,b)=>a.then(b),Promise.resolve(b)),pipeFunctions:(...a)=>a.reduce((a,b)=>(...c)=>b(a(...c))),pluralize:(a,b,c=b+'s')=>{const d=(a,b,c=b+'s')=>[1,-1].includes(+a)?b:c;return'object'==typeof a?(b,c)=>d(b,c,a[c]):d(a,b,c)},powerset:(a)=>a.reduce((b,a)=>b.concat(b.map((b)=>[a].concat(b))),[[]]),prettyBytes:(a,b=3,c=!0)=>{const g=['B','KB','MB','GB','TB','PB','EB','ZB','YB'];if(1>Math.abs(a))return a+(c?' ':'')+g[0];const h=e(d(Math.log10(0>a?-a:a)/3),g.length-1),i=+((0>a?-a:a)/1e3**h).toPrecision(b);return(0>a?'-':'')+i+(c?' ':'')+g[h]},primes:(a)=>{let c=Array.from({length:a-1}).map((a,b)=>b+2),e=d(b(a)),g=Array.from({length:e-1}).map((a,b)=>b+2);return g.forEach((a)=>c=c.filter((b)=>0!=b%a||b===a)),c},promisify:(a)=>(...b)=>new Promise((c,d)=>a(...b,(a,b)=>a?d(a):c(b))),pull:(a,...b)=>{let c=Array.isArray(b[0])?b[0]:b,d=a.filter((a)=>!c.includes(a));a.length=0,d.forEach((b)=>a.push(b))},pullAtIndex:(a,b)=>{let c=[],d=a.map((a,d)=>b.includes(d)?c.push(a):a).filter((a,c)=>!b.includes(c));return a.length=0,d.forEach((b)=>a.push(b)),c},pullAtValue:(a,b)=>{let c=[],d=a.forEach((a)=>b.includes(a)?c.push(a):a),e=a.filter((a)=>!b.includes(a));return a.length=0,e.forEach((b)=>a.push(b)),c},pullBy:(a,...b)=>{const c=b.length;let d=1d(a)),g=a.filter((a)=>!e.includes(d(a)));a.length=0,g.forEach((b)=>a.push(b))},randomHexColorCode:()=>{let a=(1e6*(1048575*Math.random())).toString(16);return'#'+a.slice(0,6)},randomIntArrayInRange:(a,b,c=1)=>Array.from({length:c},()=>d(Math.random()*(b-a+1))+a),randomIntegerInRange:(a,b)=>d(Math.random()*(b-a+1))+a,randomNumberInRange:(a,b)=>Math.random()*(b-a)+a,readFileLines:(a)=>v.readFileSync(a).toString('UTF8').split('\n'),rearg:(a,b)=>(...c)=>a(...c.reduce((a,c,d)=>(a[b.indexOf(d)]=c,a),Array.from({length:b.length}))),redirect:(a,b=!0)=>b?window.location.href=a:window.location.replace(a),reduceSuccessive:(a,b,c)=>a.reduce((a,c,d,e)=>(a.push(b(a.slice(-1)[0],c,d,e)),a),[c]),reduceWhich:(a,c=(c,a)=>c-a)=>a.reduce((d,a)=>0<=c(d,a)?a:d),reducedFilter:(a,b,c)=>a.filter(c).map((a)=>b.reduce((b,c)=>(b[c]=a[c],b),{})),remove:(a,b)=>Array.isArray(a)?a.filter(b).reduce((b,c)=>(a.splice(a.indexOf(c),1),b.concat(c)),[]):[],removeNonASCII:(a)=>a.replace(/[^\x20-\x7E]/g,''),reverseString:(a)=>[...a].join(''),round:(b,c=0)=>+`${a(`${b}e${c}`)}e-${c}`,runAsync:(a)=>{const b=new Worker(URL.createObjectURL(new Blob([`postMessage((${a})());`]),{type:'application/javascript; charset=utf-8'}));return new Promise((a,c)=>{b.onmessage=({data:c})=>{a(c),b.terminate()},b.onerror=(a)=>{c(a),b.terminate()}})},runPromisesInSeries:(a)=>a.reduce((a,b)=>a.then(b),Promise.resolve()),sample:(a)=>a[d(Math.random()*a.length)],sampleSize:([...a],b=1)=>{for(let c=a.length;c;){const b=d(Math.random()*c--);[a[c],a[b]]=[a[b],a[c]]}return a.slice(0,b)},scrollToTop:w,sdbm:(a)=>{let b=a.split('');return b.reduce((a,b)=>a=b.charCodeAt(0)+(a<<6)+(a<<16)-a,0)},serializeCookie:(a,b)=>`${encodeURIComponent(a)}=${encodeURIComponent(b)}`,setStyle:(a,b,c)=>a.style[b]=c,shallowClone:(a)=>Object.assign({},a),show:(...a)=>[...a].forEach((a)=>a.style.display=''),shuffle:([...a])=>{for(let b=a.length;b;){const c=d(Math.random()*b--);[a[b],a[c]]=[a[c],a[b]]}return a},similarity:(a,b)=>a.filter((a)=>b.includes(a)),size:(a)=>Array.isArray(a)?a.length:a&&'object'==typeof a?a.size||a.length||Object.keys(a).length:'string'==typeof a?new Blob([a]).size:0,sleep:(a)=>new Promise((b)=>setTimeout(b,a)),sortCharactersInString:(a)=>[...a].sort((c,a)=>c.localeCompare(a)).join(''),sortedIndex:(a,b)=>{const c=a[0]>a[a.length-1],d=a.findIndex((a)=>c?b>=a:b<=a);return-1===d?a.length:d},sortedIndexBy:(a,b,c)=>{const d=c(a[0])>c(a[a.length-1]),e=c(b),g=a.findIndex((a)=>d?e>=c(a):e<=c(a));return-1===g?a.length:g},sortedLastIndex:(a,b)=>{const c=a[0]>a[a.length-1],d=a.map((a,b)=>[b,a]).reverse().findIndex((a)=>c?b<=a[1]:b>=a[1]);return-1===d?0:a.length-d-1},sortedLastIndexBy:(a,b,c)=>{const d=c(a[0])>c(a[a.length-1]),e=c(b),g=a.map((a,b)=>[b,c(a)]).reverse().findIndex((a)=>d?e<=a[1]:e>=a[1]);return-1===g?0:a.length-g},splitLines:(a)=>a.split(/\r?\n/),spreadOver:(a)=>(b)=>a(...b),standardDeviation:(a,c=!1)=>{const d=a.reduce((a,b)=>a+b,0)/a.length;return b(a.reduce((a,b)=>a.concat((b-d)**2),[]).reduce((a,b)=>a+b,0)/(a.length-(c?0:1)))},stripHTMLTags:(a)=>a.replace(/<[^>]*>/g,''),sum:(...a)=>[...a].reduce((a,b)=>a+b,0),sumBy:(a,b)=>a.map('function'==typeof b?b:(a)=>a[b]).reduce((a,b)=>a+b,0),sumPower:(a,b=2,c=1)=>Array(a+1-c).fill(0).map((a,d)=>(d+c)**b).reduce((c,a)=>c+a,0),symmetricDifference:(c,a)=>{const b=new Set(c),d=new Set(a);return[...c.filter((a)=>!d.has(a)),...a.filter((a)=>!b.has(a))]},symmetricDifferenceBy:(c,a,b)=>{const d=new Set(c.map((a)=>b(a))),e=new Set(a.map((a)=>b(a)));return[...c.filter((a)=>!e.has(b(a))),...a.filter((a)=>!d.has(b(a)))]},symmetricDifferenceWith:(b,c,d)=>[...b.filter((e)=>-1===c.findIndex((a)=>d(e,a))),...c.filter((c)=>-1===b.findIndex((a)=>d(c,a)))],tail:(a)=>1a.slice(0,b),takeRight:(a,b=1)=>a.slice(a.length-b,a.length),takeRightWhile:(a,b)=>{for(let c of a.reverse().keys())if(b(a[c]))return a.reverse().slice(a.length-c,a.length);return a},takeWhile:(a,b)=>{for(let c of a.keys())if(b(a[c]))return a.slice(0,c);return a},throttle:(a,b)=>{let c,d,e;return function(){const g=this,h=arguments;c?(clearTimeout(d),d=setTimeout(function(){Date.now()-e>=b&&(a.apply(g,h),e=Date.now())},b-(Date.now()-e))):(a.apply(g,h),e=Date.now(),c=!0)}},timeTaken:(a)=>{console.time('timeTaken');const b=a();return console.timeEnd('timeTaken'),b},times:(a,b,c=void 0)=>{for(let d=0;!1!==b.call(c,d)&&++d{let b=a&&a.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g).map((a)=>a.slice(0,1).toUpperCase()+a.slice(1).toLowerCase()).join('');return b.slice(0,1).toLowerCase()+b.slice(1)},toCurrency:(a,b,c=void 0)=>Intl.NumberFormat(c,{style:'currency',currency:b}).format(a),toDecimalMark:(a)=>a.toLocaleString('en-US'),toKebabCase:(a)=>a&&a.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g).map((a)=>a.toLowerCase()).join('-'),toOrdinalSuffix:(a)=>{const b=parseInt(a),c=[b%10,b%100],d=['st','nd','rd','th'];return[1,2,3,4].includes(c[0])&&![11,12,13,14,15,16,17,18,19].includes(c[1])?b+d[c[0]-1]:b+d[3]},toSafeInteger:(b)=>a(g(e(b,Number.MAX_SAFE_INTEGER),Number.MIN_SAFE_INTEGER)),toSnakeCase:(a)=>a&&a.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g).map((a)=>a.toLowerCase()).join('_'),toggleClass:(a,b)=>a.classList.toggle(b),tomorrow:()=>{let a=new Date;return a.setDate(a.getDate()+1),`${a.getFullYear()}-${(a.getMonth()+1+'').padStart(2,'0')}-${(a.getDate()+'').padStart(2,'0')}`},transform:(b,c,a)=>Object.keys(b).reduce((d,a)=>c(d,b[a],a,b),a),truncateString:(a,b)=>a.length>b?a.slice(0,3a.every((a)=>a[b]),unary:(a)=>(b)=>a(b),unescapeHTML:(a)=>a.replace(/&|<|>|'|"/g,(a)=>({"&":'&',"<":'<',">":'>',"'":'\'',""":'"'})[a]||a),unflattenObject:(a)=>Object.keys(a).reduce((b,c)=>{if(-1!==c.indexOf('.')){const d=c.split('.');Object.assign(b,JSON.parse('{'+d.map((a,b)=>b===d.length-1?`"${a}":`:`"${a}":{`).join('')+a[c]+'}'.repeat(d.length)))}else b[c]=a[c];return b},{}),unfold:(a,b)=>{let c=[],d=[null,b];for(;d=a(d[1]);)c.push(d[0]);return c},union:(c,a)=>Array.from(new Set([...c,...a])),unionBy:(c,a,b)=>{const d=new Set(c.map((a)=>b(a)));return Array.from(new Set([...c,...a.filter((a)=>!d.has(b(a)))]))},unionWith:(c,a,b)=>Array.from(new Set([...c,...a.filter((a)=>-1===c.findIndex((c)=>b(a,c)))])),uniqueElements:(a)=>[...new Set(a)],untildify:(a)=>a.replace(/^~($|\/|\\)/,`${'undefined'!=typeof require&&require('os').homedir()}$1`),unzip:(a)=>a.reduce((a,b)=>(b.forEach((b,c)=>a[c].push(b)),a),Array.from({length:g(...a.map((a)=>a.length))}).map(()=>[])),unzipWith:(a,b)=>a.reduce((a,b)=>(b.forEach((b,c)=>a[c].push(b)),a),Array.from({length:g(...a.map((a)=>a.length))}).map(()=>[])).map((a)=>b(...a)),validateNumber:(a)=>!isNaN(parseFloat(a))&&isFinite(a)&&+a==a,without:(a,...b)=>a.filter((a)=>!b.includes(a)),words:(a,b=/[^a-zA-Z-]+/)=>a.split(b).filter(Boolean),xProd:(c,a)=>c.reduce((b,c)=>b.concat(a.map((a)=>[c,a])),[]),yesNo:(a,b=!1)=>!!/^(y|yes)$/i.test(a)||!/^(n|no)$/i.test(a)&&b,zip:(...a)=>{const b=g(...a.map((a)=>a.length));return Array.from({length:b}).map((b,c)=>Array.from({length:a.length},(b,d)=>a[d][c]))},zipObject:(a,b)=>a.reduce((a,c,d)=>(a[c]=b[d],a),{}),zipWith:(...a)=>{const b=a.length;let c=1a.length)),e=Array.from({length:d}).map((b,c)=>Array.from({length:a.length},(b,d)=>a[d][c]));return c?e.map((a)=>c(...a)):e}}}); +(function(a,b){'object'==typeof exports&&'undefined'!=typeof module?module.exports=b():'function'==typeof define&&define.amd?define(b):a._30s=b()})(this,function(){'use strict';var a=Math.sqrt,b=Math.log,c=Math.floor,d=Math.PI,e=Math.min,g=Math.max,h=Math.ceil,i=Math.round,j=Math.abs;const k='undefined'!=typeof require&&require('fs'),l='undefined'!=typeof require&&require('crypto'),m=(a)=>2>=a.length?2===a.length?[a,a[1]+a[0]]:[a]:a.split('').reduce((b,c,d)=>b.concat(m(a.slice(0,d)+a.slice(d+1)).map((a)=>c+a)),[]),n=(a,b=a.length,...c)=>b<=c.length?a(...c):n.bind(null,a,b,...c),o=(a)=>{let b=Object.assign({},a);return Object.keys(b).forEach((c)=>b[c]='object'==typeof a[c]?o(a[c]):a[c]),b},p=(a)=>[].concat(...a.map((a)=>Array.isArray(a)?p(a):a)),q=([...c],d=32,e)=>{const[g,a]=c,b=(a,b)=>1/(1+10**((b-a)/400)),h=(c,h)=>(e||c)+d*(h-b(h?g:a,h?a:g));if(2===c.length)return[h(g,1),h(a,0)];for(let a,b=0;b{if(c===d)return!0;if(c instanceof Date&&d instanceof Date)return c.getTime()===d.getTime();if(!c||!d||'object'!=typeof c&&'object'!=typeof d)return c===d;if(null===c||void 0===c||null===d||void 0===d)return!1;if(c.prototype!==d.prototype)return!1;let e=Object.keys(c);return!(e.length!==Object.keys(d).length)&&e.every((a)=>r(c[a],d[a]))},s=(a)=>0>a?(()=>{throw new TypeError('Negative numbers are not allowed!')})():1>=a?1:a*s(a-1),t=(a,b=1)=>1===b?a.reduce((b,a)=>b.concat(a),[]):a.reduce((c,a)=>c.concat(Array.isArray(a)?t(a,b-1):a),[]),u=(a,b='')=>Object.keys(a).reduce((c,d)=>{const e=b.length?b+'.':'';return'object'==typeof a[d]?Object.assign(c,u(a[d],e+d)):c[e+d]=a[d],c},{}),v=(...a)=>{const c=(a,b)=>b?v(b,a%b):a;return[...a].reduce((d,a)=>c(d,a))},w='undefined'!=typeof require&&require('crypto'),x='undefined'!=typeof require&&require('fs'),y=()=>{const a=document.documentElement.scrollTop||document.body.scrollTop;0k.writeFile(`${b}.json`,JSON.stringify(a,null,2)),RGBToHex:(a,c,d)=>((a<<16)+(c<<8)+d).toString(16).padStart(6,'0'),URLJoin:(...a)=>a.join('/').replace(/[\/]+/g,'/').replace(/^(.+):\//,'$1://').replace(/^file:/,'file:/').replace(/\/(\?|&|#[^!])/g,'$1').replace(/\?/g,'&').replace('&','?'),UUIDGeneratorBrowser:()=>'10000000-1000-4000-8000-100000000000'.replace(/[018]/g,(a)=>(a^crypto.getRandomValues(new Uint8Array(1))[0]&15>>a/4).toString(16)),UUIDGeneratorNode:()=>'10000000-1000-4000-8000-100000000000'.replace(/[018]/g,(a)=>(a^l.randomBytes(1)[0]&15>>a/4).toString(16)),all:(a,b=Boolean)=>a.every(b),anagrams:m,any:(a,b=Boolean)=>a.some(b),approximatelyEqual:(a,b,c=1e-3)=>j(a-b)a.map((a)=>document.querySelector('#'+b).innerHTML+=`
  • ${a}
  • `),ary:(a,b)=>(...c)=>a(...c.slice(0,b)),atob:(a)=>new Buffer(a,'base64').toString('binary'),attempt:(a,...b)=>{try{return a(b)}catch(a){return a instanceof Error?a:new Error(a)}},average:(...a)=>[...a].reduce((a,b)=>a+b,0)/a.length,averageBy:(a,b)=>a.map('function'==typeof b?b:(a)=>a[b]).reduce((a,b)=>a+b,0)/a.length,bifurcate:(a,b)=>a.reduce((a,c,d)=>(a[b[d]?0:1].push(c),a),[[],[]]),bifurcateBy:(a,b)=>a.reduce((a,c,d)=>(a[b(c,d)?0:1].push(c),a),[[],[]]),bind:(a,b,...c)=>function(){return a.apply(b,c.concat(...arguments))},bindAll:(a,...b)=>b.forEach((b)=>(f=a[b],a[b]=function(){return f.apply(a)})),bindKey:(a,b,...c)=>function(){return a[b].apply(a,c.concat(...arguments))},binomialCoefficient:(a,b)=>{var c=Number.isNaN;if(c(a)||c(b))return NaN;if(0>b||b>a)return 0;if(0===b||b===a)return 1;if(1===b||b===a-1)return a;a-bdocument.documentElement.clientHeight+window.scrollY>=(document.documentElement.scrollHeight||document.documentElement.clientHeight),btoa:(a)=>new Buffer(a,'binary').toString('base64'),byteSize:(a)=>new Blob([a]).size,call:(a,...b)=>(c)=>c[a](...b),capitalize:([a,...b],c=!1)=>a.toUpperCase()+(c?b.join('').toLowerCase():b.join('')),capitalizeEveryWord:(a)=>a.replace(/\b[a-z]/g,(a)=>a.toUpperCase()),castArray:(a)=>Array.isArray(a)?a:[a],chainAsync:(a)=>{let b=0;const c=()=>a[b++](c);c()},chunk:(a,b)=>Array.from({length:h(a.length/b)},(c,d)=>a.slice(d*b,d*b+b)),clampNumber:(c,d,a)=>g(e(c,g(d,a)),e(d,a)),cloneRegExp:(a)=>new RegExp(a.source,a.flags),coalesce:(...a)=>a.find((a)=>![void 0,null].includes(a)),coalesceFactory:(a)=>(...b)=>b.find(a),collectInto:(a)=>(...b)=>a(b),colorize:(...a)=>({black:`\x1b[30m${a.join(' ')}`,red:`\x1b[31m${a.join(' ')}`,green:`\x1b[32m${a.join(' ')}`,yellow:`\x1b[33m${a.join(' ')}`,blue:`\x1b[34m${a.join(' ')}`,magenta:`\x1b[35m${a.join(' ')}`,cyan:`\x1b[36m${a.join(' ')}`,white:`\x1b[37m${a.join(' ')}`,bgBlack:`\x1b[40m${a.join(' ')}\x1b[0m`,bgRed:`\x1b[41m${a.join(' ')}\x1b[0m`,bgGreen:`\x1b[42m${a.join(' ')}\x1b[0m`,bgYellow:`\x1b[43m${a.join(' ')}\x1b[0m`,bgBlue:`\x1b[44m${a.join(' ')}\x1b[0m`,bgMagenta:`\x1b[45m${a.join(' ')}\x1b[0m`,bgCyan:`\x1b[46m${a.join(' ')}\x1b[0m`,bgWhite:`\x1b[47m${a.join(' ')}\x1b[0m`}),compact:(a)=>a.filter(Boolean),compose:(...a)=>a.reduce((a,b)=>(...c)=>a(b(...c))),composeRight:(...a)=>a.reduce((a,b)=>(...c)=>b(a(...c))),converge:(a,b)=>(...c)=>a(...b.map((a)=>a.apply(null,c))),copyToClipboard:(a)=>{const b=document.createElement('textarea');b.value=a,b.setAttribute('readonly',''),b.style.position='absolute',b.style.left='-9999px',document.body.appendChild(b);const c=!!(0a.map('function'==typeof b?b:(a)=>a[b]).reduce((a,b)=>(a[b]=(a[b]||0)+1,a),{}),countOccurrences:(a,b)=>a.reduce((c,a)=>a===b?c+1:c+0,0),createElement:(a)=>{const b=document.createElement('div');return b.innerHTML=a,b.firstElementChild},createEventHub:()=>({hub:Object.create(null),emit(a,b){(this.hub[a]||[]).forEach((a)=>a(b))},on(a,b){this.hub[a]||(this.hub[a]=[]),this.hub[a].push(b)},off(a,b){const c=(this.hub[a]||[]).findIndex((a)=>a===b);-1window.location.href,curry:n,debounce:(a,b=0)=>{let c;return function(...d){clearTimeout(c),c=setTimeout(()=>a.apply(this,d),b)}},decapitalize:([a,...b],c=!1)=>a.toLowerCase()+(c?b.join('').toUpperCase():b.join('')),deepClone:o,deepFlatten:p,defaults:(a,...b)=>Object.assign({},a,...b.reverse(),a),defer:(a,...b)=>setTimeout(a,1,...b),degreesToRads:(a)=>a*d/180,delay:(a,b,...c)=>setTimeout(a,b,...c),detectDeviceType:()=>/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)?'Mobile':'Desktop',difference:(c,a)=>{const b=new Set(a);return c.filter((a)=>!b.has(a))},differenceBy:(c,a,b)=>{const d=new Set(a.map((a)=>b(a)));return c.filter((a)=>!d.has(b(a)))},differenceWith:(a,b,c)=>a.filter((d)=>-1===b.findIndex((a)=>c(d,a))),digitize:(a)=>[...`${a}`].map((a)=>parseInt(a)),distance:(a,b,c,d)=>Math.hypot(c-a,d-b),drop:(a,b=1)=>a.slice(b),dropRight:(a,b=1)=>a.slice(0,-b),dropRightWhile:(a,b)=>{for(;0{for(;0{const{top:c,left:d,bottom:e,right:g}=a.getBoundingClientRect(),{innerHeight:h,innerWidth:i}=window;return b?(0a.replace(/[&<>'"]/g,(a)=>({"&":'&',"<":'<',">":'>',"'":''','"':'"'})[a]||a),escapeRegExp:(a)=>a.replace(/[.*+?^${}()|[\]\\]/g,'\\$&'),everyNth:(a,b)=>a.filter((a,c)=>c%b==b-1),extendHex:(a)=>'#'+a.slice(a.startsWith('#')?1:0).split('').map((a)=>a+a).join(''),factorial:s,fibonacci:(a)=>Array.from({length:a}).reduce((a,b,c)=>a.concat(1a.filter((b)=>a.indexOf(b)===a.lastIndexOf(b)),findKey:(a,b)=>Object.keys(a).find((c)=>b(a[c],c,a)),findLast:(a,b)=>a.filter(b).slice(-1)[0],findLastIndex:(a,b)=>a.map((a,b)=>[b,a]).filter((c)=>b(c[1],c[0],a)).slice(-1)[0][0],findLastKey:(a,b)=>Object.keys(a).reverse().find((c)=>b(a[c],c,a)),flatten:t,flattenObject:u,flip:(a)=>(b,...c)=>a(...c,b),forEachRight:(a,b)=>a.slice(0).reverse().forEach(b),forOwn:(a,b)=>Object.keys(a).forEach((c)=>b(a[c],c,a)),forOwnRight:(a,b)=>Object.keys(a).reverse().forEach((c)=>b(a[c],c,a)),formatDuration:(a)=>{0>a&&(a=-a);const b={day:c(a/8.64e7),hour:c(a/3.6e6)%24,minute:c(a/6e4)%60,second:c(a/1e3)%60,millisecond:c(a)%1e3};return Object.entries(b).filter((a)=>0!==a[1]).map((a)=>a[1]+' '+(1===a[1]?a[0]:a[0]+'s')).join(', ')},fromCamelCase:(a,b='_')=>a.replace(/([a-z\d])([A-Z])/g,'$1'+b+'$2').replace(/([A-Z]+)([A-Z][a-z\d]+)/g,'$1'+b+'$2').toLowerCase(),functionName:(a)=>(console.debug(a.name),a),functions:(a,b=!1)=>(b?[...Object.keys(a),...Object.keys(Object.getPrototypeOf(a))]:Object.keys(a)).filter((b)=>'function'==typeof a[b]),gcd:v,geometricProgression:(a,d=1,e=2)=>Array.from({length:c(b(a/d)/b(e))+1}).map((a,b)=>d*e**b),get:(a,...b)=>[...b].map((b)=>b.replace(/\[([^\[\]]*)\]/g,'.$1.').split('.').filter((a)=>''!==a).reduce((a,b)=>a&&a[b],a)),getColonTimeFromDate:(a)=>a.toTimeString().slice(0,8),getDaysDiffBetweenDates:(a,b)=>(b-a)/86400000,getMeridiemSuffixOfInteger:(a)=>0===a||24===a?'12am':12===a?'12pm':12>a?a%12+'am':a%12+'pm',getScrollPosition:(a=window)=>({x:a.pageXOffset===void 0?a.scrollLeft:a.pageXOffset,y:a.pageYOffset===void 0?a.scrollTop:a.pageYOffset}),getStyle:(a,b)=>getComputedStyle(a)[b],getType:(a)=>a===void 0?'undefined':null===a?'null':a.constructor.name.toLowerCase(),getURLParameters:(a)=>(a.match(/([^?=&]+)(=([^&]*))/g)||[]).reduce((b,a)=>(b[a.slice(0,a.indexOf('='))]=a.slice(a.indexOf('=')+1),b),{}),groupBy:(a,b)=>a.map('function'==typeof b?b:(a)=>a[b]).reduce((b,c,d)=>(b[c]=(b[c]||[]).concat(a[d]),b),{}),hammingDistance:(a,b)=>((a^b).toString(2).match(/1/g)||'').length,hasClass:(a,b)=>a.classList.contains(b),hasFlags:(...a)=>a.every((a)=>process.argv.includes(/^-{1,2}/.test(a)?a:'--'+a)),hashBrowser:(a)=>crypto.subtle.digest('SHA-256',new TextEncoder('utf-8').encode(a)).then((a)=>{let b=[],c=new DataView(a);for(let d=0;dnew Promise((b)=>setTimeout(()=>b(w.createHash('sha256').update(a).digest('hex')),0)),head:(a)=>a[0],hexToRGB:(a)=>{let b=!1,c=a.slice(a.startsWith('#')?1:0);return 3===c.length?c=[...c].map((a)=>a+a).join(''):8===c.length&&(b=!0),c=parseInt(c,16),'rgb'+(b?'a':'')+'('+(c>>>(b?24:16))+', '+((c&(b?16711680:65280))>>>(b?16:8))+', '+((c&(b?65280:255))>>>(b?8:0))+(b?`, ${255&c}`:'')+')'},hide:(...a)=>[...a].forEach((a)=>a.style.display='none'),httpGet:(a,b,c=console.error)=>{const d=new XMLHttpRequest;d.open('GET',a,!0),d.onload=()=>b(d.responseText),d.onerror=()=>c(d),d.send()},httpPost:(a,b,c,d=console.error)=>{const e=new XMLHttpRequest;e.open('POST',a,!0),e.setRequestHeader('Content-type','application/json; charset=utf-8'),e.onload=()=>c(e.responseText),e.onerror=()=>d(e),e.send(b)},httpsRedirect:()=>{'https:'!==location.protocol&&location.replace('https://'+location.href.split('//')[1])},inRange:(a,b,c=null)=>(c&&b>c&&(c=b),null==c?0<=a&&a=b&&a{const c=[];return a.forEach((a,d)=>a===b&&c.push(d)),c},initial:(a)=>a.slice(0,-1),initialize2DArray:(a,b,c=null)=>Array.from({length:b}).map(()=>Array.from({length:a}).fill(c)),initializeArrayWithRange:(a,b=0,c=1)=>Array.from({length:h((a+1-b)/c)}).map((a,d)=>d*c+b),initializeArrayWithRangeRight:(a,b=0,c=1)=>Array.from({length:h((a+1-b)/c)}).map((a,d,e)=>(e.length-d-1)*c+b),initializeArrayWithValues:(a,b=0)=>Array(a).fill(b),intersection:(c,a)=>{const b=new Set(a);return c.filter((a)=>b.has(a))},intersectionBy:(c,a,b)=>{const d=new Set(a.map((a)=>b(a)));return c.filter((a)=>d.has(b(a)))},intersectionWith:(c,a,b)=>c.filter((c)=>-1!==a.findIndex((a)=>b(c,a))),invertKeyValues:(a,b)=>Object.keys(a).reduce((c,d)=>{const e=b?b(a[d]):a[d];return c[e]=c[e]||[],c[e].push(d),c},{}),is:(a,b)=>b instanceof a,isAbsoluteURL:(a)=>/^[a-z][a-z0-9+.-]*:/.test(a),isArrayLike:(a)=>{try{return[...a],!0}catch(a){return!1}},isBoolean:(a)=>'boolean'==typeof a,isDivisible:(a,b)=>0==a%b,isEmpty:(a)=>null==a||!(Object.keys(a)||a).length,isEven:(a)=>0==a%2,isFunction:(a)=>'function'==typeof a,isLowerCase:(a)=>a===a.toLowerCase(),isNil:(a)=>a===void 0||null===a,isNull:(a)=>null===a,isNumber:(a)=>'number'==typeof a,isObject:(a)=>a===Object(a),isObjectLike:(a)=>null!==a&&'object'==typeof a,isPlainObject:(a)=>!!a&&'object'==typeof a&&a.constructor===Object,isPrime:(b)=>{const d=c(a(b));for(var e=2;e<=d;e++)if(0==b%e)return!1;return 2<=b},isPrimitive:(a)=>!['object','function'].includes(typeof a)||null===a,isPromiseLike:(a)=>null!==a&&('object'==typeof a||'function'==typeof a)&&'function'==typeof a.then,isSorted:(a)=>{const b=a[0]>a[1]?-1:1;for(let[c,d]of a.entries()){if(c===a.length-1)return b;if(0<(d-a[c+1])*b)return 0}},isString:(a)=>'string'==typeof a,isSymbol:(a)=>'symbol'==typeof a,isTravisCI:()=>'TRAVIS'in process.env&&'CI'in process.env,isUndefined:(a)=>a===void 0,isUpperCase:(a)=>a===a.toUpperCase(),isValidJSON:(a)=>{try{return JSON.parse(a),!0}catch(a){return!1}},join:(a,b=',',c=b)=>a.reduce((d,e,g)=>g===a.length-2?d+e+c:g===a.length-1?d+e:d+e+b,''),last:(a)=>a[a.length-1],lcm:(...a)=>{const b=(a,c)=>c?b(c,a%c):a,c=(a,c)=>a*c/b(a,c);return[...a].reduce((d,a)=>c(d,a))},longestItem:(...a)=>[...a].sort((c,a)=>a.length-c.length)[0],lowercaseKeys:(a)=>Object.keys(a).reduce((b,c)=>(b[c.toLowerCase()]=a[c],b),{}),luhnCheck:(a)=>{let b=(a+'').split('').reverse().map((a)=>parseInt(a)),c=b.splice(0,1)[0],d=b.reduce((a,b,c)=>0==c%2?a+2*b%9||9:a+b,0);return d+=c,0==d%10},mapKeys:(a,b)=>Object.keys(a).reduce((c,d)=>(c[b(a[d],d,a)]=a[d],c),{}),mapObject:(b,c)=>((d)=>(d=[b,b.map(c)],d[0].reduce((a,b,c)=>(a[b]=d[1][c],a),{})))(),mapValues:(a,b)=>Object.keys(a).reduce((c,d)=>(c[d]=b(a[d],d,a),c),{}),mask:(a,b=4,c='*')=>(''+a).slice(0,-b).replace(/./g,c)+(''+a).slice(-b),matches:(a,b)=>Object.keys(b).every((c)=>a.hasOwnProperty(c)&&a[c]===b[c]),matchesWith:(a,b,c)=>Object.keys(b).every((d)=>a.hasOwnProperty(d)&&c?c(a[d],b[d],d,a,b):a[d]==b[d]),maxBy:(a,b)=>g(...a.map('function'==typeof b?b:(a)=>a[b])),maxN:(a,b=1)=>[...a].sort((c,a)=>a-c).slice(0,b),median:(a)=>{const b=c(a.length/2),d=[...a].sort((c,a)=>c-a);return 0==a.length%2?(d[b-1]+d[b])/2:d[b]},memoize:(a)=>{const b=new Map,c=function(c){return b.has(c)?b.get(c):b.set(c,a.call(this,c))&&b.get(c)};return c.cache=b,c},merge:(...a)=>[...a].reduce((b,c)=>Object.keys(c).reduce((d,a)=>(b[a]=b.hasOwnProperty(a)?[].concat(b[a]).concat(c[a]):c[a],b),{}),{}),minBy:(a,b)=>e(...a.map('function'==typeof b?b:(a)=>a[b])),minN:(a,b=1)=>[...a].sort((c,a)=>c-a).slice(0,b),mostPerformant:(a,b=1e4)=>{const c=a.map((a)=>{const c=performance.now();for(let c=0;c(...b)=>!a(...b),none:(a,b=Boolean)=>!a.some(b),nthArg:(a)=>(...b)=>b.slice(a)[0],nthElement:(a,b=0)=>(0a.reduce((b,a)=>(b[a[0]]=a[1],b),{}),objectToPairs:(a)=>Object.keys(a).map((b)=>[b,a[b]]),observeMutations:(a,b,c)=>{const d=new MutationObserver((a)=>a.forEach((a)=>b(a)));return d.observe(a,Object.assign({childList:!0,attributes:!0,attributeOldValue:!0,characterData:!0,characterDataOldValue:!0,subtree:!0},c)),d},off:(a,b,c,d=!1)=>a.removeEventListener(b,c,d),omit:(a,b)=>Object.keys(a).filter((a)=>!b.includes(a)).reduce((b,c)=>(b[c]=a[c],b),{}),omitBy:(a,b)=>Object.keys(a).filter((c)=>!b(a[c],c)).reduce((b,c)=>(b[c]=a[c],b),{}),on:(a,b,c,d={})=>{const e=(a)=>a.target.matches(d.target)&&c.call(a.target,a);if(a.addEventListener(b,d.target?e:c,d.options||!1),d.target)return e},onUserInputChange:(a)=>{let b='mouse',c=0;const d=()=>{const e=performance.now();20>e-c&&(b='mouse',a(b),document.removeEventListener('mousemove',d)),c=e};document.addEventListener('touchstart',()=>{'touch'==b||(b='touch',a(b),document.addEventListener('mousemove',d))})},once:(a)=>{let b=!1;return function(...c){if(!b)return b=!0,a.apply(this,c)}},orderBy:(a,c,d)=>[...a].sort((e,a)=>c.reduce((b,c,g)=>{if(0===b){const[h,i]=d&&'desc'===d[g]?[a[c],e[c]]:[e[c],a[c]];b=h>i?1:h(...b)=>a.map((a)=>a.apply(null,b)),overArgs:(a,b)=>(...c)=>a(...c.map((a,c)=>b[c](a))),palindrome:(a)=>{const b=a.toLowerCase().replace(/[\W_]/g,'');return b===b.split('').reverse().join('')},parseCookie:(a)=>a.split(';').map((a)=>a.split('=')).reduce((a,b)=>(a[decodeURIComponent(b[0].trim())]=decodeURIComponent(b[1].trim()),a),{}),partial:(a,...b)=>(...c)=>a(...b,...c),partialRight:(a,...b)=>(...c)=>a(...c,...b),partition:(a,b)=>a.reduce((a,c,d,e)=>(a[b(c,d,e)?0:1].push(c),a),[[],[]]),percentile:(a,b)=>100*a.reduce((a,c)=>a+(cb.reduce((b,c)=>(c in a&&(b[c]=a[c]),b),{}),pickBy:(a,b)=>Object.keys(a).filter((c)=>b(a[c],c)).reduce((b,c)=>(b[c]=a[c],b),{}),pipeAsyncFunctions:(...a)=>(b)=>a.reduce((a,b)=>a.then(b),Promise.resolve(b)),pipeFunctions:(...a)=>a.reduce((a,b)=>(...c)=>b(a(...c))),pluralize:(a,b,c=b+'s')=>{const d=(a,b,c=b+'s')=>[1,-1].includes(+a)?b:c;return'object'==typeof a?(b,c)=>d(b,c,a[c]):d(a,b,c)},powerset:(a)=>a.reduce((b,a)=>b.concat(b.map((b)=>[a].concat(b))),[[]]),prettyBytes:(a,b=3,d=!0)=>{const g=['B','KB','MB','GB','TB','PB','EB','ZB','YB'];if(1>j(a))return a+(d?' ':'')+g[0];const h=e(c(Math.log10(0>a?-a:a)/3),g.length-1),i=+((0>a?-a:a)/1e3**h).toPrecision(b);return(0>a?'-':'')+i+(d?' ':'')+g[h]},primes:(b)=>{let d=Array.from({length:b-1}).map((a,b)=>b+2),e=c(a(b)),g=Array.from({length:e-1}).map((a,b)=>b+2);return g.forEach((a)=>d=d.filter((b)=>0!=b%a||b===a)),d},promisify:(a)=>(...b)=>new Promise((c,d)=>a(...b,(a,b)=>a?d(a):c(b))),pull:(a,...b)=>{let c=Array.isArray(b[0])?b[0]:b,d=a.filter((a)=>!c.includes(a));a.length=0,d.forEach((b)=>a.push(b))},pullAtIndex:(a,b)=>{let c=[],d=a.map((a,d)=>b.includes(d)?c.push(a):a).filter((a,c)=>!b.includes(c));return a.length=0,d.forEach((b)=>a.push(b)),c},pullAtValue:(a,b)=>{let c=[],d=a.forEach((a)=>b.includes(a)?c.push(a):a),e=a.filter((a)=>!b.includes(a));return a.length=0,e.forEach((b)=>a.push(b)),c},pullBy:(a,...b)=>{const c=b.length;let d=1d(a)),g=a.filter((a)=>!e.includes(d(a)));a.length=0,g.forEach((b)=>a.push(b))},radsToDegrees:(a)=>180*a/d,randomHexColorCode:()=>{let a=(1e6*(1048575*Math.random())).toString(16);return'#'+a.slice(0,6)},randomIntArrayInRange:(a,b,d=1)=>Array.from({length:d},()=>c(Math.random()*(b-a+1))+a),randomIntegerInRange:(a,b)=>c(Math.random()*(b-a+1))+a,randomNumberInRange:(a,b)=>Math.random()*(b-a)+a,readFileLines:(a)=>x.readFileSync(a).toString('UTF8').split('\n'),rearg:(a,b)=>(...c)=>a(...c.reduce((a,c,d)=>(a[b.indexOf(d)]=c,a),Array.from({length:b.length}))),redirect:(a,b=!0)=>b?window.location.href=a:window.location.replace(a),reduceSuccessive:(a,b,c)=>a.reduce((a,c,d,e)=>(a.push(b(a.slice(-1)[0],c,d,e)),a),[c]),reduceWhich:(a,c=(c,a)=>c-a)=>a.reduce((d,a)=>0<=c(d,a)?a:d),reducedFilter:(a,b,c)=>a.filter(c).map((a)=>b.reduce((b,c)=>(b[c]=a[c],b),{})),remove:(a,b)=>Array.isArray(a)?a.filter(b).reduce((b,c)=>(a.splice(a.indexOf(c),1),b.concat(c)),[]):[],removeNonASCII:(a)=>a.replace(/[^\x20-\x7E]/g,''),reverseString:(a)=>[...a].join(''),round:(a,b=0)=>+`${i(`${a}e${b}`)}e-${b}`,runAsync:(a)=>{const b=new Worker(URL.createObjectURL(new Blob([`postMessage((${a})());`]),{type:'application/javascript; charset=utf-8'}));return new Promise((a,c)=>{b.onmessage=({data:c})=>{a(c),b.terminate()},b.onerror=(a)=>{c(a),b.terminate()}})},runPromisesInSeries:(a)=>a.reduce((a,b)=>a.then(b),Promise.resolve()),sample:(a)=>a[c(Math.random()*a.length)],sampleSize:([...a],b=1)=>{for(let d=a.length;d;){const b=c(Math.random()*d--);[a[d],a[b]]=[a[b],a[d]]}return a.slice(0,b)},scrollToTop:y,sdbm:(a)=>{let b=a.split('');return b.reduce((a,b)=>a=b.charCodeAt(0)+(a<<6)+(a<<16)-a,0)},serializeCookie:(a,b)=>`${encodeURIComponent(a)}=${encodeURIComponent(b)}`,setStyle:(a,b,c)=>a.style[b]=c,shallowClone:(a)=>Object.assign({},a),show:(...a)=>[...a].forEach((a)=>a.style.display=''),shuffle:([...a])=>{for(let b=a.length;b;){const d=c(Math.random()*b--);[a[b],a[d]]=[a[d],a[b]]}return a},similarity:(a,b)=>a.filter((a)=>b.includes(a)),size:(a)=>Array.isArray(a)?a.length:a&&'object'==typeof a?a.size||a.length||Object.keys(a).length:'string'==typeof a?new Blob([a]).size:0,sleep:(a)=>new Promise((b)=>setTimeout(b,a)),sortCharactersInString:(a)=>[...a].sort((c,a)=>c.localeCompare(a)).join(''),sortedIndex:(a,b)=>{const c=a[0]>a[a.length-1],d=a.findIndex((a)=>c?b>=a:b<=a);return-1===d?a.length:d},sortedIndexBy:(a,b,c)=>{const d=c(a[0])>c(a[a.length-1]),e=c(b),g=a.findIndex((a)=>d?e>=c(a):e<=c(a));return-1===g?a.length:g},sortedLastIndex:(a,b)=>{const c=a[0]>a[a.length-1],d=a.map((a,b)=>[b,a]).reverse().findIndex((a)=>c?b<=a[1]:b>=a[1]);return-1===d?0:a.length-d-1},sortedLastIndexBy:(a,b,c)=>{const d=c(a[0])>c(a[a.length-1]),e=c(b),g=a.map((a,b)=>[b,c(a)]).reverse().findIndex((a)=>d?e<=a[1]:e>=a[1]);return-1===g?0:a.length-g},splitLines:(a)=>a.split(/\r?\n/),spreadOver:(a)=>(b)=>a(...b),stableSort:(a,c)=>a.map((a,b)=>({item:a,index:b})).sort((d,a)=>c(d.item,a.item)||d.index-a.index).map(({item:a})=>a),standardDeviation:(b,c=!1)=>{const d=b.reduce((a,b)=>a+b,0)/b.length;return a(b.reduce((a,b)=>a.concat((b-d)**2),[]).reduce((a,b)=>a+b,0)/(b.length-(c?0:1)))},stripHTMLTags:(a)=>a.replace(/<[^>]*>/g,''),sum:(...a)=>[...a].reduce((a,b)=>a+b,0),sumBy:(a,b)=>a.map('function'==typeof b?b:(a)=>a[b]).reduce((a,b)=>a+b,0),sumPower:(a,b=2,c=1)=>Array(a+1-c).fill(0).map((a,d)=>(d+c)**b).reduce((c,a)=>c+a,0),symmetricDifference:(c,a)=>{const b=new Set(c),d=new Set(a);return[...c.filter((a)=>!d.has(a)),...a.filter((a)=>!b.has(a))]},symmetricDifferenceBy:(c,a,b)=>{const d=new Set(c.map((a)=>b(a))),e=new Set(a.map((a)=>b(a)));return[...c.filter((a)=>!e.has(b(a))),...a.filter((a)=>!d.has(b(a)))]},symmetricDifferenceWith:(b,c,d)=>[...b.filter((e)=>-1===c.findIndex((a)=>d(e,a))),...c.filter((c)=>-1===b.findIndex((a)=>d(c,a)))],tail:(a)=>1a.slice(0,b),takeRight:(a,b=1)=>a.slice(a.length-b,a.length),takeRightWhile:(a,b)=>{for(let c of a.reverse().keys())if(b(a[c]))return a.reverse().slice(a.length-c,a.length);return a},takeWhile:(a,b)=>{for(let c of a.keys())if(b(a[c]))return a.slice(0,c);return a},throttle:(a,b)=>{let c,d,e;return function(){const g=this,h=arguments;c?(clearTimeout(d),d=setTimeout(function(){Date.now()-e>=b&&(a.apply(g,h),e=Date.now())},b-(Date.now()-e))):(a.apply(g,h),e=Date.now(),c=!0)}},timeTaken:(a)=>{console.time('timeTaken');const b=a();return console.timeEnd('timeTaken'),b},times:(a,b,c=void 0)=>{for(let d=0;!1!==b.call(c,d)&&++d{let b=a&&a.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g).map((a)=>a.slice(0,1).toUpperCase()+a.slice(1).toLowerCase()).join('');return b.slice(0,1).toLowerCase()+b.slice(1)},toCurrency:(a,b,c=void 0)=>Intl.NumberFormat(c,{style:'currency',currency:b}).format(a),toDecimalMark:(a)=>a.toLocaleString('en-US'),toKebabCase:(a)=>a&&a.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g).map((a)=>a.toLowerCase()).join('-'),toOrdinalSuffix:(a)=>{const b=parseInt(a),c=[b%10,b%100],d=['st','nd','rd','th'];return[1,2,3,4].includes(c[0])&&![11,12,13,14,15,16,17,18,19].includes(c[1])?b+d[c[0]-1]:b+d[3]},toSafeInteger:(a)=>i(g(e(a,Number.MAX_SAFE_INTEGER),Number.MIN_SAFE_INTEGER)),toSnakeCase:(a)=>a&&a.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g).map((a)=>a.toLowerCase()).join('_'),toggleClass:(a,b)=>a.classList.toggle(b),tomorrow:()=>{let a=new Date;return a.setDate(a.getDate()+1),`${a.getFullYear()}-${(a.getMonth()+1+'').padStart(2,'0')}-${(a.getDate()+'').padStart(2,'0')}`},transform:(b,c,a)=>Object.keys(b).reduce((d,a)=>c(d,b[a],a,b),a),truncateString:(a,b)=>a.length>b?a.slice(0,3a.every((a)=>a[b]),unary:(a)=>(b)=>a(b),uncurry:(a,b=1)=>(...c)=>{if(b>c.length)throw new RangeError('Arguments too few!');return((a)=>(b)=>b.reduce((a,b)=>a(b),a))(a)(c.slice(0,b))},unescapeHTML:(a)=>a.replace(/&|<|>|'|"/g,(a)=>({"&":'&',"<":'<',">":'>',"'":'\'',""":'"'})[a]||a),unflattenObject:(a)=>Object.keys(a).reduce((b,c)=>{if(-1!==c.indexOf('.')){const d=c.split('.');Object.assign(b,JSON.parse('{'+d.map((a,b)=>b===d.length-1?`"${a}":`:`"${a}":{`).join('')+a[c]+'}'.repeat(d.length)))}else b[c]=a[c];return b},{}),unfold:(a,b)=>{let c=[],d=[null,b];for(;d=a(d[1]);)c.push(d[0]);return c},union:(c,a)=>Array.from(new Set([...c,...a])),unionBy:(c,a,b)=>{const d=new Set(c.map((a)=>b(a)));return Array.from(new Set([...c,...a.filter((a)=>!d.has(b(a)))]))},unionWith:(c,a,b)=>Array.from(new Set([...c,...a.filter((a)=>-1===c.findIndex((c)=>b(a,c)))])),uniqueElements:(a)=>[...new Set(a)],untildify:(a)=>a.replace(/^~($|\/|\\)/,`${'undefined'!=typeof require&&require('os').homedir()}$1`),unzip:(a)=>a.reduce((a,b)=>(b.forEach((b,c)=>a[c].push(b)),a),Array.from({length:g(...a.map((a)=>a.length))}).map(()=>[])),unzipWith:(a,b)=>a.reduce((a,b)=>(b.forEach((b,c)=>a[c].push(b)),a),Array.from({length:g(...a.map((a)=>a.length))}).map(()=>[])).map((a)=>b(...a)),validateNumber:(a)=>!isNaN(parseFloat(a))&&isFinite(a)&&+a==a,without:(a,...b)=>a.filter((a)=>!b.includes(a)),words:(a,b=/[^a-zA-Z-]+/)=>a.split(b).filter(Boolean),xProd:(c,a)=>c.reduce((b,c)=>b.concat(a.map((a)=>[c,a])),[]),yesNo:(a,b=!1)=>!!/^(y|yes)$/i.test(a)||!/^(n|no)$/i.test(a)&&b,zip:(...a)=>{const b=g(...a.map((a)=>a.length));return Array.from({length:b}).map((b,c)=>Array.from({length:a.length},(b,d)=>a[d][c]))},zipObject:(a,b)=>a.reduce((a,c,d)=>(a[c]=b[d],a),{}),zipWith:(...a)=>{const b=a.length;let c=1a.length)),e=Array.from({length:d}).map((b,c)=>Array.from({length:a.length},(b,d)=>a[d][c]));return c?e.map((a)=>c(...a)):e}}}); diff --git a/docs/index.html b/docs/index.html index 385f479a6..d8b48804d 100644 --- a/docs/index.html +++ b/docs/index.html @@ -50,7 +50,7 @@ scrollToTop(); } }, false); - }

    logo 30 seconds of code Curated collection of useful JavaScript snippets that you can understand in 30 seconds or less.

     

    Adapter

    ary

    Creates a function that accepts up to n arguments, ignoring any additional arguments.

    Call the provided function, fn, with up to n arguments, using Array.slice(0,n) and the spread operator (...).

    const ary = (fn, n) => (...args) => fn(...args.slice(0, n));
    +      }

    logo 30 seconds of code Curated collection of useful JavaScript snippets that you can understand in 30 seconds or less.

     

    Adapter

    ary

    Creates a function that accepts up to n arguments, ignoring any additional arguments.

    Call the provided function, fn, with up to n arguments, using Array.slice(0,n) and the spread operator (...).

    const ary = (fn, n) => (...args) => fn(...args.slice(0, n));
     
    const firstTwoMax = ary(Math.max, 2);
     [[2, 6, 'a'], [8, 4, 6], [10]].map(x => firstTwoMax(...x)); // [6, 8, 10]
     

    call

    Given a key and a set of arguments, call them when given a context. Primarily useful in composition.

    Use a closure to call a stored key with stored arguments.

    const call = (key, ...args) => context => context[key](...args);
    @@ -123,7 +123,19 @@ Object.assig
     arrayMax([1, 2, 3]); // 3
     

    unary

    Creates a function that accepts up to one argument, ignoring any additional arguments.

    Call the provided function, fn, with just the first argument given.

    const unary = fn => val => fn(val);
     
    ['6', '8', '10'].map(unary(parseInt)); // [6, 8, 10]
    -

    Array

    chunk

    Chunks an array into smaller arrays of a specified size.

    Use Array.from() to create a new array, that fits the number of chunks that will be produced. Use Array.slice() to map each element of the new array to a chunk the length of size. If the original array can't be split evenly, the final chunk will contain the remaining elements.

    const chunk = (arr, size) =>
    +

    Array

    all

    Returns true if the provided predicate function returns true for all elements in a collection, false otherwise.

    Use Array.every() to test if all elements in the collection return true based on fn. Omit the second argument, fn, to use Boolean as a default.

    const all = (arr, fn = Boolean) => arr.every(fn);
    +
    all([4, 2, 3], x => x > 1); // true
    +all([1, 2, 3]); // true
    +

    any

    Returns true if the provided predicate function returns true for at least one element in a collection, false otherwise.

    Use Array.some() to test if any elements in the collection return true based on fn. Omit the second argument, fn, to use Boolean as a default.

    const any = (arr, fn = Boolean) => arr.some(fn);
    +
    any([0, 1, 2, 0], x => x >= 2); // true
    +any([0, 0, 1, 0]); // true
    +

    bifurcate

    Splits values into two groups. If an element in filter is truthy, the corresponding element in the collection belongs to the first group; otherwise, it belongs to the second group.

    Use Array.reduce() and Array.push() to add elements to groups, based on filter.

    const bifurcate = (arr, filter) =>
    +  arr.reduce((acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc), [[], []]);
    +
    bifurcate(['beep', 'boop', 'foo', 'bar'], [true, true, false, true]); // [ ['beep', 'boop', 'bar'], ['foo'] ]
    +

    bifurcateBy

    Splits values into two groups according to a predicate function, which specifies which group an element in the input collection belongs to. If the predicate function returns a truthy value, the collection element belongs to the first group; otherwise, it belongs to the second group.

    Use Array.reduce() and Array.push() to add elements to groups, based on the value returned by fn for each element.

    const bifurcateBy = (arr, fn) =>
    +  arr.reduce((acc, val, i) => (acc[fn(val, i) ? 0 : 1].push(val), acc), [[], []]);
    +
    bifurcateBy(['beep', 'boop', 'foo', 'bar'], x => x[0] === 'b'); // [ ['beep', 'boop', 'bar'], ['foo'] ]
    +

    chunk

    Chunks an array into smaller arrays of a specified size.

    Use Array.from() to create a new array, that fits the number of chunks that will be produced. Use Array.slice() to map each element of the new array to a chunk the length of size. If the original array can't be split evenly, the final chunk will contain the remaining elements.

    const chunk = (arr, size) =>
       Array.from({ length: Math.ceil(arr.length / size) }, (v, i) =>
         arr.slice(i * size, i * size + size)
       );
    @@ -283,6 +295,9 @@ Object.assig
     

    minN

    Returns the n minimum elements from the provided array. If n is greater than or equal to the provided array's length, then return the original array(sorted in ascending order).

    Use Array.sort() combined with the spread operator (...) to create a shallow clone of the array and sort it in ascending order. Use Array.slice() to get the specified number of elements. Omit the second argument, n, to get a one-element array.

    const minN = (arr, n = 1) => [...arr].sort((a, b) => a - b).slice(0, n);
     
    minN([1, 2, 3]); // [1]
     minN([1, 2, 3], 2); // [1,2]
    +

    none

    Returns true if the provided predicate function returns false for all elements in a collection, false otherwise.

    Use Array.some() to test if any elements in the collection return true based on fn. Omit the second argument, fn, to use Boolean as a default.

    const none = (arr, fn = Boolean) => !arr.some(fn);
    +
    none([0, 1, 3, 0], x => x == 2); // true
    +none([0, 0, 0]); // true
     

    nthElement

    Returns the nth element of an array.

    Use Array.slice() to get an array containing the nth element at the first place. If the index is out of bounds, return []. Omit the second argument, n, to get the first element of the array.

    const nthElement = (arr, n = 0) => (n > 0 ? arr.slice(n, n + 1) : arr.slice(n))[0];
     
    nthElement(['a', 'b', 'c'], 1); // 'b'
     nthElement(['a', 'b', 'b'], -3); // 'a'
    @@ -433,6 +448,13 @@ Object.assig
       return index === -1 ? 0 : arr.length - index;
     };
     
    sortedLastIndexBy([{ x: 4 }, { x: 5 }], { x: 4 }, o => o.x); // 1
    +

    stableSortadvanced

    Performs stable sorting of an array, preserving the initial indexes of items when their values are the same. Does not mutate the original array, but returns a new array instead.

    Use Array.map() to pair each element of the input array with its corresponding index. Use Array.sort() and a compare function to sort the list, preserving their initial order if the items compared are equal. Use Array.map() to convert back to the initial array items.

    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 arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    +const stable = stableSort(arr, () => 0); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
     

    symmetricDifference

    Returns the symmetric difference between two arrays.

    Create a Set from each array, then use Array.filter() on each of them to only keep values not contained in the other.

    const symmetricDifference = (a, b) => {
       const sA = new Set(a),
         sB = new Set(b);
    @@ -967,6 +989,14 @@ document.bodyShow examples
    var output = '';
     times(5, i => (output += i));
     console.log(output); // 01234
    +

    uncurry

    Uncurries a function up to depth n.

    Return a variadic function. Use Array.reduce() on the provided arguments to call each subsequent curry level of the function. If the length of the provided arguments is less than n throw an error. Otherwise, call fn with the proper amount of arguments, using Array.slice(0, n). Omit the second argument, n, to uncurry up to depth 1.

    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 add = x => y => z => x + y + z;
    +const uncurriedAdd = uncurry(add, 3);
    +uncurriedAdd(1, 2, 3); // 6
     

    unfold

    Builds an array, using an iterator function and an initial seed value.

    Use a while loop and Array.push() to call the function repeatedly until it returns false. The iterator function accepts one argument (seed) and must always return an array with two elements ([value, nextSeed]) or false to terminate.

    const unfold = (fn, seed) => {
       let result = [],
         val = [null, seed];
    @@ -975,7 +1005,9 @@ console.log<
     };
     
    var f = n => (n > 50 ? false : [-n, n + 10]);
     unfold(f, 10); // [-10, -20, -30, -40, -50]
    -

    Math

    average

    Returns the average of two or more numbers.

    Use Array.reduce() to add each value to an accumulator, initialized with a value of 0, divide by the length of the array.

    const average = (...nums) => [...nums].reduce((acc, val) => acc + val, 0) / nums.length;
    +

    Math

    approximatelyEqual

    Checks if two numbers are approximately equal to each other.

    Use Math.abs() to compare the absolute difference of the two values to epsilon. Omit the third parameter, epsilon, to use a default value of 0.001.

    const approximatelyEqual = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) < epsilon;
    +
    approximatelyEqual(Math.PI / 2.0, 1.5708); // true
    +

    average

    Returns the average of two or more numbers.

    Use Array.reduce() to add each value to an accumulator, initialized with a value of 0, divide by the length of the array.

    const average = (...nums) => [...nums].reduce((acc, val) => acc + val, 0) / nums.length;
     
    average(...[1, 2, 3]); // 2
     average(1, 2, 3); // 2
     

    averageBy

    Returns the average of an array, after mapping each element to a value using the provided function.

    Use Array.map() to map each element to the value returned by fn, Array.reduce() to add each value to an accumulator, initialized with a value of 0, divide by the length of the array.

    const averageBy = (arr, fn) =>
    @@ -983,9 +1015,22 @@ console.log<
       arr.length;
     
    averageBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], o => o.n); // 5
     averageBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], 'n'); // 5
    +

    binomialCoefficient

    Evaluates the binomial coefficient of two integers n and k.

    Use Number.isNaN() to check if any of the two values is NaN. Check if k is less than 0, greater than or equal to n, equal to 1 or n - 1 and return the appropriate result. Check if n - k is less than k and switch their values accordingly. Loop from 2 through k and calculate the binomial coefficient. Use Math.round() to account for rounding errors in the calculation.

    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);
    +};
    +
    binomialCoefficient(8, 2); // 28
     

    clampNumber

    Clamps num within the inclusive range specified by the boundary values a and b.

    If num falls within the range, return num. Otherwise, return the nearest number in the range.

    const clampNumber = (num, a, b) => Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b));
     
    clampNumber(2, 3, 5); // 3
     clampNumber(1, -1, -5); // -1
    +

    degreesToRads

    Converts an angle from degrees to radians.

    Use Math.PI and the degree to radian formula to convert the angle from degrees to radians.

    const degreesToRads = deg => deg * Math.PI / 180.0;
    +
    degreesToRads(90.0); // ~1.5708
     

    digitize

    Converts a number to an array of digits.

    Convert the number to a string, using the spread operator (...) to build an array. Use Array.map() and parseInt() to transform each value to an integer.

    const digitize = n => [...`${n}`].map(i => parseInt(i));
     
    digitize(123); // [1, 2, 3]
     

    distance

    Returns the distance between two points.

    Use Math.hypot() to calculate the Euclidean distance between two points.

    const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0);
    @@ -1109,6 +1154,8 @@ own individual rating by supplying it as the third argument.
       return arr;
     };
     
    primes(10); // [2,3,5,7]
    +

    radsToDegrees

    Converts an angle from radians to degrees.

    Use Math.PI and the radian to degree formula to convert the angle from radians to degrees.

    const radsToDegrees = rad => rad * 180.0 / Math.PI;
    +
    radsToDegrees(Math.PI / 2); // 90
     

    randomIntArrayInRange

    Returns an array of n random integers in the specified range.

    Use Array.from() to create an empty array of the specific length, Math.random() to generate a random number and map it to the desired range, using Math.floor() to make it an integer.

    const randomIntArrayInRange = (min, max, n = 1) =>
       Array.from({ length: n }, () => Math.floor(Math.random() * (max - min + 1)) + min);
     
    randomIntArrayInRange(12, 35, 10); // [ 34, 14, 27, 17, 30, 27, 20, 26, 21, 14 ]
    @@ -1840,6 +1887,24 @@ Logs: {
       "id": 101
     }
     */
    +

    mostPerformant

    Returns the index of the function in an array of functions which executed the fastest.

    Use Array.map() to generate an array where each value is the total time taken to execute the function after iterations times. Use the difference in performance.now() values before and after to get the total time in milliseconds to a high degree of accuracy. Use Math.min() to find the minimum execution time, and return the index of that shortest time which corresponds to the index of the most performant function. Omit the second argument, iterations, to use a default of 10,000 iterations. The more iterations, the more reliable the result but the longer it will take.

    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));
    +};
    +
    mostPerformant([
    +  () => {
    +    // Loops through the entire array before returning `false`
    +    [1, 2, 3, 4, 5, 6, 7, 8, 9, '10'].every(el => typeof el === 'number');
    +  },
    +  () => {
    +    // Only needs to reach index `1` before returning false
    +    [1, '2', 3, 4, 5, 6, 7, 8, 9, 10].every(el => typeof el === 'number');
    +  }
    +]); // 1
     

    nthArg

    Creates a function that gets the argument at index n. If n is negative, the nth argument from the end is returned.

    Use Array.slice() to get the desired argument at index n.

    const nthArg = n => (...args) => args.slice(n)[0];
     
    const third = nthArg(2);
     third(1, 2, 3); // 3
    diff --git a/package.json b/package.json
    index 094ca7ffd..4dd3113d2 100644
    --- a/package.json
    +++ b/package.json
    @@ -19,7 +19,7 @@
       },
       "name": "30-seconds-of-code",
       "description": "A collection of useful JavaScript snippets.",
    -  "version": "0.0.1",
    +  "version": "0.0.2",
       "main": "dist/_30s.js",
       "module": "dist/_30s.esm.js",
       "scripts": {
    diff --git a/snippet-template.md b/snippet-template.md
    index 1ee62a2f0..31cc8b26d 100644
    --- a/snippet-template.md
    +++ b/snippet-template.md
    @@ -10,5 +10,5 @@ const functionName = arguments =>
     ```
     
     ```js
    -functionName('sampleInput') // 'sampleOutput'
    +functionName('sampleInput'); // 'sampleOutput'
     ```
    diff --git a/snippets/all.md b/snippets/all.md
    new file mode 100644
    index 000000000..17cadbc9f
    --- /dev/null
    +++ b/snippets/all.md
    @@ -0,0 +1,15 @@
    +### all
    +
    +Returns `true` if the provided predicate function returns `true` for all elements in a collection, `false` otherwise.
    +
    +Use `Array.every()` to test if all elements in the collection return `true` based on `fn`.
    +Omit the second argument, `fn`, to use `Boolean` as a default.
    +
    +```js
    +const all = (arr, fn = Boolean) => arr.every(fn);
    +```
    +
    +```js
    +all([4, 2, 3], x => x > 1); // true
    +all([1, 2, 3]); // true
    +```
    diff --git a/snippets/any.md b/snippets/any.md
    new file mode 100644
    index 000000000..31368cc7a
    --- /dev/null
    +++ b/snippets/any.md
    @@ -0,0 +1,15 @@
    +### any
    +
    +Returns `true` if the provided predicate function returns `true` for at least one element in a collection, `false` otherwise.
    +
    +Use `Array.some()` to test if any elements in the collection return `true` based on `fn`.
    +Omit the second argument, `fn`, to use `Boolean` as a default.
    +
    +```js
    +const any = (arr, fn = Boolean) => arr.some(fn);
    +```
    +
    +```js
    +any([0, 1, 2, 0], x => x >= 2); // true
    +any([0, 0, 1, 0]); // true
    +```
    diff --git a/snippets/approximatelyEqual.md b/snippets/approximatelyEqual.md
    new file mode 100644
    index 000000000..88773c163
    --- /dev/null
    +++ b/snippets/approximatelyEqual.md
    @@ -0,0 +1,14 @@
    +### approximatelyEqual
    +
    +Checks if two numbers are approximately equal to each other.
    +
    +Use `Math.abs()` to compare the absolute difference of the two values to `epsilon`.
    +Omit the third parameter, `epsilon`, to use a default value of `0.001`.
    +
    +```js
    +const approximatelyEqual = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) < epsilon;
    +```
    +
    +```js
    +approximatelyEqual(Math.PI / 2.0, 1.5708); // true
    +```
    diff --git a/snippets/bifurcate.md b/snippets/bifurcate.md
    new file mode 100644
    index 000000000..2e124711f
    --- /dev/null
    +++ b/snippets/bifurcate.md
    @@ -0,0 +1,14 @@
    +### bifurcate
    +
    +Splits values into two groups. If an element in `filter` is truthy, the corresponding element in the collection belongs to the first group; otherwise, it belongs to the second group.
    +
    +Use `Array.reduce()` and `Array.push()` to add elements to groups, based on `filter`.
    +
    +```js
    +const bifurcate = (arr, filter) =>
    +  arr.reduce((acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc), [[], []]);
    +```
    +
    +```js
    +bifurcate(['beep', 'boop', 'foo', 'bar'], [true, true, false, true]); // [ ['beep', 'boop', 'bar'], ['foo'] ]
    +```
    diff --git a/snippets/bifurcateBy.md b/snippets/bifurcateBy.md
    new file mode 100644
    index 000000000..46a00116f
    --- /dev/null
    +++ b/snippets/bifurcateBy.md
    @@ -0,0 +1,14 @@
    +### bifurcateBy
    +
    +Splits values into two groups according to a predicate function, which specifies which group an element in the input collection belongs to. If the predicate function returns a truthy value, the collection element belongs to the first group; otherwise, it belongs to the second group.
    +
    +Use `Array.reduce()` and `Array.push()` to add elements to groups, based on the value returned by `fn` for each element.
    +
    +```js
    +const bifurcateBy = (arr, fn) =>
    +  arr.reduce((acc, val, i) => (acc[fn(val, i) ? 0 : 1].push(val), acc), [[], []]);
    +```
    +
    +```js
    +bifurcateBy(['beep', 'boop', 'foo', 'bar'], x => x[0] === 'b'); // [ ['beep', 'boop', 'bar'], ['foo'] ]
    +```
    diff --git a/snippets/binomialCoefficient.md b/snippets/binomialCoefficient.md
    new file mode 100644
    index 000000000..d5ff87d16
    --- /dev/null
    +++ b/snippets/binomialCoefficient.md
    @@ -0,0 +1,26 @@
    +### binomialCoefficient
    +
    +Evaluates the binomial coefficient of two integers `n` and `k`.
    +
    +Use `Number.isNaN()` to check if any of the two values is `NaN`.
    +Check if `k` is less than `0`, greater than or equal to `n`, equal to `1` or `n - 1` and return the appropriate result.
    +Check if `n - k` is less than `k` and switch their values accordingly.
    +Loop from `2` through `k` and calculate the binomial coefficient.
    +Use `Math.round()` to account for rounding errors in the calculation.
    +
    +```js
    +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);
    +};
    +```
    +
    +```js
    +binomialCoefficient(8, 2); // 28
    +```
    diff --git a/snippets/degreesToRads.md b/snippets/degreesToRads.md
    new file mode 100644
    index 000000000..ed3a2ee0e
    --- /dev/null
    +++ b/snippets/degreesToRads.md
    @@ -0,0 +1,13 @@
    +### degreesToRads
    +
    +Converts an angle from degrees to radians.
    +
    +Use `Math.PI` and the degree to radian formula to convert the angle from degrees to radians.
    +
    +```js
    +const degreesToRads = deg => deg * Math.PI / 180.0;
    +```
    +
    +```js
    +degreesToRads(90.0); // ~1.5708
    +```
    diff --git a/snippets/mostPerformant.md b/snippets/mostPerformant.md
    new file mode 100644
    index 000000000..66cd591e2
    --- /dev/null
    +++ b/snippets/mostPerformant.md
    @@ -0,0 +1,31 @@
    +### mostPerformant
    +
    +Returns the index of the function in an array of functions which executed the fastest.
    +
    +Use `Array.map()` to generate an array where each value is the total time taken to execute the function after `iterations` times. Use the difference in `performance.now()` values before and after to get the total time in milliseconds to a high degree of accuracy.
    +Use `Math.min()` to find the minimum execution time, and return the index of that shortest time which corresponds to the index of the most performant function. 
    +Omit the second argument, `iterations`, to use a default of 10,000 iterations. The more iterations, the more reliable the result but the longer it will take.
    +
    +```js
    +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));
    +};
    +```
    +
    +```js
    +mostPerformant([
    +  () => {
    +    // Loops through the entire array before returning `false`
    +    [1, 2, 3, 4, 5, 6, 7, 8, 9, '10'].every(el => typeof el === 'number');
    +  },
    +  () => {
    +    // Only needs to reach index `1` before returning false
    +    [1, '2', 3, 4, 5, 6, 7, 8, 9, 10].every(el => typeof el === 'number');
    +  }
    +]); // 1
    +```
    diff --git a/snippets/none.md b/snippets/none.md
    new file mode 100644
    index 000000000..1b9af0c2a
    --- /dev/null
    +++ b/snippets/none.md
    @@ -0,0 +1,15 @@
    +### none
    +
    +Returns `true` if the provided predicate function returns `false` for all elements in a collection, `false` otherwise.
    +
    +Use `Array.some()` to test if any elements in the collection return `true` based on `fn`.
    +Omit the second argument, `fn`, to use `Boolean` as a default.
    +
    +```js
    +const none = (arr, fn = Boolean) => !arr.some(fn);
    +```
    +
    +```js
    +none([0, 1, 3, 0], x => x == 2); // true
    +none([0, 0, 0]); // true
    +```
    diff --git a/snippets/radsToDegrees.md b/snippets/radsToDegrees.md
    new file mode 100644
    index 000000000..d8dd54958
    --- /dev/null
    +++ b/snippets/radsToDegrees.md
    @@ -0,0 +1,13 @@
    +### radsToDegrees
    +
    +Converts an angle from radians to degrees.
    +
    +Use `Math.PI` and the radian to degree formula to convert the angle from radians to degrees.
    +
    +```js
    +const radsToDegrees = rad => rad * 180.0 / Math.PI;
    +```
    +
    +```js
    +radsToDegrees(Math.PI / 2); // 90
    +```
    diff --git a/snippets/stableSort.md b/snippets/stableSort.md
    new file mode 100644
    index 000000000..5a37fb1d6
    --- /dev/null
    +++ b/snippets/stableSort.md
    @@ -0,0 +1,21 @@
    +### stableSort
    +
    +Performs stable sorting of an array, preserving the initial indexes of items when their values are the same. 
    +Does not mutate the original array, but returns a new array instead.
    +
    +Use `Array.map()` to pair each element of the input array with its corresponding index. 
    +Use `Array.sort()` and a `compare` function to sort the list, preserving their initial order if the items compared are equal.
    +Use `Array.map()` to convert back to the initial array items.
    +
    +```js
    +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);
    +```
    +
    +```js
    +const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    +const stable = stableSort(arr, () => 0); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    +```
    diff --git a/snippets/uncurry.md b/snippets/uncurry.md
    new file mode 100644
    index 000000000..c5757e88d
    --- /dev/null
    +++ b/snippets/uncurry.md
    @@ -0,0 +1,23 @@
    +### uncurry
    +
    +Uncurries a function up to depth `n`.
    +
    +Return a variadic function.
    +Use `Array.reduce()` on the provided arguments to call each subsequent curry level of the function.
    +If the `length` of the provided arguments is less than `n` throw an error.
    +Otherwise, call `fn` with the proper amount of arguments, using `Array.slice(0, n)`.
    +Omit the second argument, `n`, to uncurry up to depth `1`.
    +
    +```js
    +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));
    +};
    +```
    +
    +```js
    +const add = x => y => z => x + y + z;
    +const uncurriedAdd = uncurry(add, 3);
    +uncurriedAdd(1, 2, 3); // 6
    +```
    diff --git a/tag_database b/tag_database
    index 10cc1708a..54db11193 100644
    --- a/tag_database
    +++ b/tag_database
    @@ -1,12 +1,18 @@
    +all:array,function
    +any:array,function
    +approximatelyEqual:math
     arrayToHtmlList:browser,array
     ary:adapter,function
     atob:node,string,utility
     attempt:function
     average:math,array
     averageBy:math,array,function
    +bifurcate:array
    +bifurcateBy:array,function
     bind:function,object
     bindAll:object,function
     bindKey:function,object
    +binomialCoefficient:math
     bottomVisible:browser
     btoa:node,string,utility
     byteSize:string
    @@ -39,6 +45,7 @@ deepClone:object,recursion
     deepFlatten:array,recursion
     defaults:object
     defer:function
    +degreesToRads:math
     delay:function
     detectDeviceType:browser
     difference:array,math
    @@ -153,7 +160,9 @@ memoize:function
     merge:object,array
     minBy:math,array,function
     minN:array,math
    +mostPerformant:utility,function
     negate:function
    +none:array,function
     nthArg:utility,function
     nthElement:array
     objectFromPairs:object,array
    @@ -188,6 +197,7 @@ pull:array
     pullAtIndex:array
     pullAtValue:array
     pullBy:array,function,advanced
    +radsToDegrees:math
     randomHexColorCode:utility,random
     randomIntArrayInRange:math,utility,random
     randomIntegerInRange:math,utility,random
    @@ -224,6 +234,7 @@ sortedLastIndex:array,math
     sortedLastIndexBy:array,math,function
     splitLines:string
     spreadOver:adapter
    +stableSort:array,sort,advanced
     standardDeviation:math,array
     stringPermutations:string,recursion
     stripHTMLTags:string,utility,regexp
    @@ -254,6 +265,7 @@ transform:object,array
     truncateString:string
     truthCheckCollection:object,logic,array
     unary:adapter,function
    +uncurry:function
     unescapeHTML:string,browser
     unflattenObject:object,advanced
     unfold:function,array
    diff --git a/test/all/all.js b/test/all/all.js
    new file mode 100644
    index 000000000..6be892a3c
    --- /dev/null
    +++ b/test/all/all.js
    @@ -0,0 +1,2 @@
    +const all = (arr, fn = Boolean) => arr.every(fn);
    +module.exports = all;
    \ No newline at end of file
    diff --git a/test/all/all.test.js b/test/all/all.test.js
    new file mode 100644
    index 000000000..60ac82f4a
    --- /dev/null
    +++ b/test/all/all.test.js
    @@ -0,0 +1,21 @@
    +const test = require('tape');
    +const all = require('./all.js');
    +
    +test('Testing all', (t) => {
    +  //For more information on all the methods supported by tape
    +  //Please go to https://github.com/substack/tape
    +  t.true(typeof all === 'function', 'all is a Function');
    +  t.true(all([4,1,2,3]), 'Returns true for arrays with no falsey values');
    +  t.false(all([0,1]), 'Returns false for arrays with 0');
    +  t.false(all([NaN,1]), 'Returns false for arrays with NaN');
    +  t.false(all([undefined,1]), 'Returns false for arrays with undefined');
    +  t.false(all([null,1]), 'Returns false for arrays with null');
    +  t.false(all(['',1]), 'Returns false for arrays with empty strings');
    +  t.true(all([4,1,2,3], x => x >= 1), 'Returns true with predicate function');
    +  t.false(all([0,1], x => x >= 1), 'Returns false with a predicate function');
    +  //t.deepEqual(all(args..), 'Expected');
    +  //t.equal(all(args..), 'Expected');
    +  //t.false(all(args..), 'Expected');
    +  //t.throws(all(args..), 'Expected');
    +  t.end();
    +});
    diff --git a/test/any/any.js b/test/any/any.js
    new file mode 100644
    index 000000000..5004b3309
    --- /dev/null
    +++ b/test/any/any.js
    @@ -0,0 +1,2 @@
    +const any = (arr, fn = Boolean) => arr.some(fn);
    +module.exports = any;
    \ No newline at end of file
    diff --git a/test/any/any.test.js b/test/any/any.test.js
    new file mode 100644
    index 000000000..63399b385
    --- /dev/null
    +++ b/test/any/any.test.js
    @@ -0,0 +1,18 @@
    +const test = require('tape');
    +const any = require('./any.js');
    +
    +test('Testing any', (t) => {
    +  //For more information on all the methods supported by tape
    +  //Please go to https://github.com/substack/tape
    +  t.true(typeof any === 'function', 'any is a Function');
    +  t.true(any([0,1,2,3]), 'Returns true for arrays with at least one truthy value');
    +  t.false(any([0,0]), 'Returns false for arrays with no truthy values');
    +  t.false(any([NaN,0,undefined,null,'']), 'Returns false for arrays with no truthy values');
    +  t.true(any([4,1,0,3], x => x >= 1), 'Returns true with predicate function');
    +  t.false(any([0,1], x => x < 0), 'Returns false with a predicate function');
    +  //t.deepEqual(any(args..), 'Expected');
    +  //t.equal(any(args..), 'Expected');
    +  //t.false(any(args..), 'Expected');
    +  //t.throws(any(args..), 'Expected');
    +  t.end();
    +});
    diff --git a/test/approximatelyEqual/approximatelyEqual.js b/test/approximatelyEqual/approximatelyEqual.js
    new file mode 100644
    index 000000000..85fecb15b
    --- /dev/null
    +++ b/test/approximatelyEqual/approximatelyEqual.js
    @@ -0,0 +1,2 @@
    +const approximatelyEqual = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) < epsilon;
    +module.exports = approximatelyEqual;
    \ No newline at end of file
    diff --git a/test/approximatelyEqual/approximatelyEqual.test.js b/test/approximatelyEqual/approximatelyEqual.test.js
    new file mode 100644
    index 000000000..44221aeb8
    --- /dev/null
    +++ b/test/approximatelyEqual/approximatelyEqual.test.js
    @@ -0,0 +1,17 @@
    +const test = require('tape');
    +const approximatelyEqual = require('./approximatelyEqual.js');
    +
    +test('Testing approximatelyEqual', (t) => {
    +  //For more information on all the methods supported by tape
    +  //Please go to https://github.com/substack/tape
    +  t.true(typeof approximatelyEqual === 'function', 'approximatelyEqual is a Function');
    +  t.true(approximatelyEqual(Math.PI / 2.0 , 1.5708), 'Works for PI / 2');
    +  t.true(approximatelyEqual(0.1 + 0.2, 0.3), 'Works for 0.1 + 0.2 === 0.3');
    +  t.true(approximatelyEqual(0.5, 0.5), 'Works for exactly equal values');
    +  t.true(approximatelyEqual(0.501, 0.5, 0.1), 'Works for a custom epsilon');
    +  //t.deepEqual(approximatelyEqual(args..), 'Expected');
    +  //t.equal(approximatelyEqual(args..), 'Expected');
    +  //t.false(approximatelyEqual(args..), 'Expected');
    +  //t.throws(approximatelyEqual(args..), 'Expected');
    +  t.end();
    +});
    diff --git a/test/arrayToHtmlList/arrayToHtmlList.test.js b/test/arrayToHtmlList/arrayToHtmlList.test.js
    index 1f8885778..7cb8f4582 100644
    --- a/test/arrayToHtmlList/arrayToHtmlList.test.js
    +++ b/test/arrayToHtmlList/arrayToHtmlList.test.js
    @@ -5,9 +5,10 @@ test('Testing arrayToHtmlList', (t) => {
       //For more information on all the methods supported by tape
       //Please go to https://github.com/substack/tape
       t.true(typeof arrayToHtmlList === 'function', 'arrayToHtmlList is a Function');
    +  t.pass('Tested by @chalarangelo on 16/02/2018');
       //t.deepEqual(arrayToHtmlList(args..), 'Expected');
       //t.equal(arrayToHtmlList(args..), 'Expected');
       //t.false(arrayToHtmlList(args..), 'Expected');
       //t.throws(arrayToHtmlList(args..), 'Expected');
       t.end();
    -});
    \ No newline at end of file
    +});
    diff --git a/test/average/average.test.js b/test/average/average.test.js
    index dff7df5a7..16a9471c7 100644
    --- a/test/average/average.test.js
    +++ b/test/average/average.test.js
    @@ -19,6 +19,6 @@ test('Testing average', (t) => {
       let start = new Date().getTime();
       average(153, 44, 55, 64, 71, 1122, 322774, 2232, 23423, 234, 3631);
       let end = new Date().getTime();  
    -  t.true((end - start) < 2000, 'head([1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 1122, 32124, 23232]) takes less than 2s to run');
    +  t.true((end - start) < 2000, 'average([1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 1122, 32124, 23232]) takes less than 2s to run');
       t.end();
     });
    \ No newline at end of file
    diff --git a/test/bifurcate/bifurcate.js b/test/bifurcate/bifurcate.js
    new file mode 100644
    index 000000000..95d7f8f50
    --- /dev/null
    +++ b/test/bifurcate/bifurcate.js
    @@ -0,0 +1,3 @@
    +const bifurcate = (arr, filter) =>
    +arr.reduce((acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc), [[], []]);
    +module.exports = bifurcate;
    \ No newline at end of file
    diff --git a/test/bifurcate/bifurcate.test.js b/test/bifurcate/bifurcate.test.js
    new file mode 100644
    index 000000000..c65333ee0
    --- /dev/null
    +++ b/test/bifurcate/bifurcate.test.js
    @@ -0,0 +1,14 @@
    +const test = require('tape');
    +const bifurcate = require('./bifurcate.js');
    +
    +test('Testing bifurcate', (t) => {
    +  //For more information on all the methods supported by tape
    +  //Please go to https://github.com/substack/tape
    +  t.true(typeof bifurcate === 'function', 'bifurcate is a Function');
    +  t.deepEqual(bifurcate([ 'beep', 'boop', 'foo', 'bar' ], [ true, true, false, true ]), [ ['beep', 'boop', 'bar'], ['foo'] ], 'Splits the collection into two groups');
    +  //t.deepEqual(bifurcate(args..), 'Expected');
    +  //t.equal(bifurcate(args..), 'Expected');
    +  //t.false(bifurcate(args..), 'Expected');
    +  //t.throws(bifurcate(args..), 'Expected');
    +  t.end();
    +});
    diff --git a/test/bifurcateBy/bifurcateBy.js b/test/bifurcateBy/bifurcateBy.js
    new file mode 100644
    index 000000000..bdf04a7ce
    --- /dev/null
    +++ b/test/bifurcateBy/bifurcateBy.js
    @@ -0,0 +1,3 @@
    +const bifurcateBy = (arr, fn) =>
    +arr.reduce((acc, val, i) => (acc[fn(val, i) ? 0 : 1].push(val), acc), [[], []]);
    +module.exports = bifurcateBy;
    \ No newline at end of file
    diff --git a/test/bifurcateBy/bifurcateBy.test.js b/test/bifurcateBy/bifurcateBy.test.js
    new file mode 100644
    index 000000000..a6c293638
    --- /dev/null
    +++ b/test/bifurcateBy/bifurcateBy.test.js
    @@ -0,0 +1,14 @@
    +const test = require('tape');
    +const bifurcateBy = require('./bifurcateBy.js');
    +
    +test('Testing bifurcateBy', (t) => {
    +  //For more information on all the methods supported by tape
    +  //Please go to https://github.com/substack/tape
    +  t.true(typeof bifurcateBy === 'function', 'bifurcateBy is a Function');
    +  t.deepEqual(bifurcateBy([ 'beep', 'boop', 'foo', 'bar' ], x => x[0] === 'b'), [ ['beep', 'boop', 'bar'], ['foo'] ], 'Splits the collection into two groups');
    +  //t.deepEqual(bifurcateBy(args..), 'Expected');
    +  //t.equal(bifurcateBy(args..), 'Expected');
    +  //t.false(bifurcateBy(args..), 'Expected');
    +  //t.throws(bifurcateBy(args..), 'Expected');
    +  t.end();
    +});
    diff --git a/test/binomialCoefficient/binomialCoefficient.js b/test/binomialCoefficient/binomialCoefficient.js
    new file mode 100644
    index 000000000..a9808585d
    --- /dev/null
    +++ b/test/binomialCoefficient/binomialCoefficient.js
    @@ -0,0 +1,11 @@
    +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);
    +};
    +module.exports = binomialCoefficient;
    \ No newline at end of file
    diff --git a/test/binomialCoefficient/binomialCoefficient.test.js b/test/binomialCoefficient/binomialCoefficient.test.js
    new file mode 100644
    index 000000000..2f0e8ab20
    --- /dev/null
    +++ b/test/binomialCoefficient/binomialCoefficient.test.js
    @@ -0,0 +1,18 @@
    +const test = require('tape');
    +const binomialCoefficient = require('./binomialCoefficient.js');
    +
    +test('Testing binomialCoefficient', (t) => {
    +  //For more information on all the methods supported by tape
    +  //Please go to https://github.com/substack/tape
    +  t.true(typeof binomialCoefficient === 'function', 'binomialCoefficient is a Function');
    +  t.equal(binomialCoefficient(8, 2), 28, 'Returns the appropriate value');
    +  t.equal(binomialCoefficient(0, 0), 1, 'Returns the appropriate value');
    +  t.equal(binomialCoefficient(5, 3), 10, 'Returns the appropriate value');
    +  t.true(Number.isNaN(binomialCoefficient(NaN, 3)), 'Returns NaN');
    +  t.true(Number.isNaN(binomialCoefficient(5, NaN)), 'Returns NaN');
    +  //t.deepEqual(binomialCoefficient(args..), 'Expected');
    +  //t.equal(binomialCoefficient(args..), 'Expected');
    +  //t.false(binomialCoefficient(args..), 'Expected');
    +  //t.throws(binomialCoefficient(args..), 'Expected');
    +  t.end();
    +});
    diff --git a/test/chainAsync/chainAsync.test.js b/test/chainAsync/chainAsync.test.js
    index d013df52f..a1e6edd06 100644
    --- a/test/chainAsync/chainAsync.test.js
    +++ b/test/chainAsync/chainAsync.test.js
    @@ -5,22 +5,19 @@ test('Testing chainAsync', (t) => {
       //For more information on all the methods supported by tape
       //Please go to https://github.com/substack/tape
       t.true(typeof chainAsync === 'function', 'chainAsync is a Function');
    -  //t.deepEqual(chainAsync(args..), 'Expected');
    -  // chainAsync([
    -  //   next => {
    -  //     next();
    -  //   },
    -  //   next => {
    -  //     (() =>{
    -  //       next()
    -  //     })();
    -  //   },
    -  //   next => {
    -  //     t.pass("Calls all functions in an array");
    -  //     next();
    -  //   }
    -  // ]);
    -  //
    +  chainAsync([
    +    next => {
    +      next();
    +    },
    +    next => {
    +      (() => {
    +        next();
    +      })();
    +    },
    +    next => {
    +      t.pass("Calls all functions in an array");
    +    }
    +  ]);
       // // Ensure we wait for the 2nd assertion to be made
       // t.plan(2);
     
    diff --git a/test/createElement/createElement.test.js b/test/createElement/createElement.test.js
    index f773ea672..6923ec245 100644
    --- a/test/createElement/createElement.test.js
    +++ b/test/createElement/createElement.test.js
    @@ -5,9 +5,10 @@ test('Testing createElement', (t) => {
       //For more information on all the methods supported by tape
       //Please go to https://github.com/substack/tape
       t.true(typeof createElement === 'function', 'createElement is a Function');
    +  t.pass('Tested by @chalarangelo on 16/02/2018');
       //t.deepEqual(createElement(args..), 'Expected');
       //t.equal(createElement(args..), 'Expected');
       //t.false(createElement(args..), 'Expected');
       //t.throws(createElement(args..), 'Expected');
       t.end();
    -});
    \ No newline at end of file
    +});
    diff --git a/test/createEventHub/createEventHub.test.js b/test/createEventHub/createEventHub.test.js
    index 759c461b3..101d07aef 100644
    --- a/test/createEventHub/createEventHub.test.js
    +++ b/test/createEventHub/createEventHub.test.js
    @@ -5,9 +5,10 @@ test('Testing createEventHub', (t) => {
       //For more information on all the methods supported by tape
       //Please go to https://github.com/substack/tape
       t.true(typeof createEventHub === 'function', 'createEventHub is a Function');
    +  t.pass('Tested by @chalarangelo on 16/02/2018');
       //t.deepEqual(createEventHub(args..), 'Expected');
       //t.equal(createEventHub(args..), 'Expected');
       //t.false(createEventHub(args..), 'Expected');
       //t.throws(createEventHub(args..), 'Expected');
       t.end();
    -});
    \ No newline at end of file
    +});
    diff --git a/test/currentURL/currentURL.test.js b/test/currentURL/currentURL.test.js
    index e7dba8ee4..e190ad429 100644
    --- a/test/currentURL/currentURL.test.js
    +++ b/test/currentURL/currentURL.test.js
    @@ -5,9 +5,10 @@ test('Testing currentURL', (t) => {
       //For more information on all the methods supported by tape
       //Please go to https://github.com/substack/tape
       t.true(typeof currentURL === 'function', 'currentURL is a Function');
    +  t.pass('Tested by @chalarangelo on 16/02/2018');
       //t.deepEqual(currentURL(args..), 'Expected');
       //t.equal(currentURL(args..), 'Expected');
       //t.false(currentURL(args..), 'Expected');
       //t.throws(currentURL(args..), 'Expected');
       t.end();
    -});
    \ No newline at end of file
    +});
    diff --git a/test/debounce/debounce.test.js b/test/debounce/debounce.test.js
    index f1a35323c..867aac93a 100644
    --- a/test/debounce/debounce.test.js
    +++ b/test/debounce/debounce.test.js
    @@ -5,9 +5,10 @@ test('Testing debounce', (t) => {
       //For more information on all the methods supported by tape
       //Please go to https://github.com/substack/tape
       t.true(typeof debounce === 'function', 'debounce is a Function');
    +  debounce(() => {t.pass('Works as expected');}, 250);
       //t.deepEqual(debounce(args..), 'Expected');
       //t.equal(debounce(args..), 'Expected');
       //t.false(debounce(args..), 'Expected');
       //t.throws(debounce(args..), 'Expected');
       t.end();
    -});
    \ No newline at end of file
    +});
    diff --git a/test/defaults/defaults.test.js b/test/defaults/defaults.test.js
    index ab1afa29e..b3c519f9d 100644
    --- a/test/defaults/defaults.test.js
    +++ b/test/defaults/defaults.test.js
    @@ -5,9 +5,10 @@ test('Testing defaults', (t) => {
       //For more information on all the methods supported by tape
       //Please go to https://github.com/substack/tape
       t.true(typeof defaults === 'function', 'defaults is a Function');
    +  t.deepEqual(defaults({ a: 1 }, { b: 2 }, { b: 6 }, { a: 3 }), { a: 1, b: 2 }, 'Assigns default values for undefined properties');
       //t.deepEqual(defaults(args..), 'Expected');
       //t.equal(defaults(args..), 'Expected');
       //t.false(defaults(args..), 'Expected');
       //t.throws(defaults(args..), 'Expected');
       t.end();
    -});
    \ No newline at end of file
    +});
    diff --git a/test/defer/defer.test.js b/test/defer/defer.test.js
    index faa5731c9..23e125b90 100644
    --- a/test/defer/defer.test.js
    +++ b/test/defer/defer.test.js
    @@ -5,9 +5,10 @@ test('Testing defer', (t) => {
       //For more information on all the methods supported by tape
       //Please go to https://github.com/substack/tape
       t.true(typeof defer === 'function', 'defer is a Function');
    +  t.pass('Tested by @chalarangelo on 16/02/2018');
       //t.deepEqual(defer(args..), 'Expected');
       //t.equal(defer(args..), 'Expected');
       //t.false(defer(args..), 'Expected');
       //t.throws(defer(args..), 'Expected');
       t.end();
    -});
    \ No newline at end of file
    +});
    diff --git a/test/degreesToRads/degreesToRads.js b/test/degreesToRads/degreesToRads.js
    new file mode 100644
    index 000000000..da6d51836
    --- /dev/null
    +++ b/test/degreesToRads/degreesToRads.js
    @@ -0,0 +1,2 @@
    +const degreesToRads = deg => deg * Math.PI / 180.0;
    +module.exports = degreesToRads;
    \ No newline at end of file
    diff --git a/test/degreesToRads/degreesToRads.test.js b/test/degreesToRads/degreesToRads.test.js
    new file mode 100644
    index 000000000..8ec980a10
    --- /dev/null
    +++ b/test/degreesToRads/degreesToRads.test.js
    @@ -0,0 +1,15 @@
    +const test = require('tape');
    +const degreesToRads = require('./degreesToRads.js');
    +
    +test('Testing degreesToRads', (t) => {
    +  //For more information on all the methods supported by tape
    +  //Please go to https://github.com/substack/tape
    +  const approxeq = (v1,v2, diff = 0.001) => Math.abs(v1 - v2) < diff; // Use to account for rounding errors
    +  t.true(typeof degreesToRads === 'function', 'degreesToRads is a Function');
    +  t.true(approxeq(degreesToRads(90.0), Math.PI / 2), 'Returns the appropriate value');
    +  //t.deepEqual(degreesToRads(args..), 'Expected');
    +  //t.equal(degreesToRads(args..), 'Expected');
    +  //t.false(degreesToRads(args..), 'Expected');
    +  //t.throws(degreesToRads(args..), 'Expected');
    +  t.end();
    +});
    diff --git a/test/delay/delay.test.js b/test/delay/delay.test.js
    index 544f8632d..8404b3bcb 100644
    --- a/test/delay/delay.test.js
    +++ b/test/delay/delay.test.js
    @@ -5,9 +5,16 @@ test('Testing delay', (t) => {
       //For more information on all the methods supported by tape
       //Please go to https://github.com/substack/tape
       t.true(typeof delay === 'function', 'delay is a Function');
    +  delay(
    +    function(text) {
    +      t.equals(text, 'test', 'Works as expecting, passing arguments properly');
    +    },
    +    1000,
    +    'test'
    +  );
       //t.deepEqual(delay(args..), 'Expected');
       //t.equal(delay(args..), 'Expected');
       //t.false(delay(args..), 'Expected');
       //t.throws(delay(args..), 'Expected');
       t.end();
    -});
    \ No newline at end of file
    +});
    diff --git a/test/getScrollPosition/getScrollPosition.test.js b/test/getScrollPosition/getScrollPosition.test.js
    index ded20c020..9f7fd14d7 100644
    --- a/test/getScrollPosition/getScrollPosition.test.js
    +++ b/test/getScrollPosition/getScrollPosition.test.js
    @@ -5,9 +5,10 @@ test('Testing getScrollPosition', (t) => {
       //For more information on all the methods supported by tape
       //Please go to https://github.com/substack/tape
       t.true(typeof getScrollPosition === 'function', 'getScrollPosition is a Function');
    +  t.pass('Tested by @chalarangelo on 16/02/2018');
       //t.deepEqual(getScrollPosition(args..), 'Expected');
       //t.equal(getScrollPosition(args..), 'Expected');
       //t.false(getScrollPosition(args..), 'Expected');
       //t.throws(getScrollPosition(args..), 'Expected');
       t.end();
    -});
    \ No newline at end of file
    +});
    diff --git a/test/getStyle/getStyle.test.js b/test/getStyle/getStyle.test.js
    index 11c2c9244..23bac0147 100644
    --- a/test/getStyle/getStyle.test.js
    +++ b/test/getStyle/getStyle.test.js
    @@ -5,9 +5,10 @@ test('Testing getStyle', (t) => {
       //For more information on all the methods supported by tape
       //Please go to https://github.com/substack/tape
       t.true(typeof getStyle === 'function', 'getStyle is a Function');
    +  t.pass('Tested by @chalarangelo on 16/02/2018');
       //t.deepEqual(getStyle(args..), 'Expected');
       //t.equal(getStyle(args..), 'Expected');
       //t.false(getStyle(args..), 'Expected');
       //t.throws(getStyle(args..), 'Expected');
       t.end();
    -});
    \ No newline at end of file
    +});
    diff --git a/test/hasFlags/hasFlags.test.js b/test/hasFlags/hasFlags.test.js
    index 0245051be..be0d4c301 100644
    --- a/test/hasFlags/hasFlags.test.js
    +++ b/test/hasFlags/hasFlags.test.js
    @@ -5,9 +5,10 @@ test('Testing hasFlags', (t) => {
       //For more information on all the methods supported by tape
       //Please go to https://github.com/substack/tape
       t.true(typeof hasFlags === 'function', 'hasFlags is a Function');
    +  t.pass('Tested by @chalarangelo on 16/02/2018');
       //t.deepEqual(hasFlags(args..), 'Expected');
       //t.equal(hasFlags(args..), 'Expected');
       //t.false(hasFlags(args..), 'Expected');
       //t.throws(hasFlags(args..), 'Expected');
       t.end();
    -});
    \ No newline at end of file
    +});
    diff --git a/test/hashBrowser/hashBrowser.test.js b/test/hashBrowser/hashBrowser.test.js
    index d01cafc5b..5464dd95d 100644
    --- a/test/hashBrowser/hashBrowser.test.js
    +++ b/test/hashBrowser/hashBrowser.test.js
    @@ -5,9 +5,10 @@ test('Testing hashBrowser', (t) => {
       //For more information on all the methods supported by tape
       //Please go to https://github.com/substack/tape
       t.true(typeof hashBrowser === 'function', 'hashBrowser is a Function');
    +  t.pass('Tested by @chalarangelo on 16/02/2018');
       //t.deepEqual(hashBrowser(args..), 'Expected');
       //t.equal(hashBrowser(args..), 'Expected');
       //t.false(hashBrowser(args..), 'Expected');
       //t.throws(hashBrowser(args..), 'Expected');
       t.end();
    -});
    \ No newline at end of file
    +});
    diff --git a/test/hide/hide.test.js b/test/hide/hide.test.js
    index d93d3fa74..af1971858 100644
    --- a/test/hide/hide.test.js
    +++ b/test/hide/hide.test.js
    @@ -5,9 +5,10 @@ test('Testing hide', (t) => {
       //For more information on all the methods supported by tape
       //Please go to https://github.com/substack/tape
       t.true(typeof hide === 'function', 'hide is a Function');
    +  t.pass('Tested by @chalarangelo on 16/02/2018');
       //t.deepEqual(hide(args..), 'Expected');
       //t.equal(hide(args..), 'Expected');
       //t.false(hide(args..), 'Expected');
       //t.throws(hide(args..), 'Expected');
       t.end();
    -});
    \ No newline at end of file
    +});
    diff --git a/test/mostPerformant/mostPerformant.js b/test/mostPerformant/mostPerformant.js
    new file mode 100644
    index 000000000..ae084a5cf
    --- /dev/null
    +++ b/test/mostPerformant/mostPerformant.js
    @@ -0,0 +1,9 @@
    +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));
    +};
    +module.exports = mostPerformant;
    \ No newline at end of file
    diff --git a/test/mostPerformant/mostPerformant.test.js b/test/mostPerformant/mostPerformant.test.js
    new file mode 100644
    index 000000000..95a560f91
    --- /dev/null
    +++ b/test/mostPerformant/mostPerformant.test.js
    @@ -0,0 +1,14 @@
    +const test = require('tape');
    +const mostPerformant = require('./mostPerformant.js');
    +
    +test('Testing mostPerformant', (t) => {
    +  //For more information on all the methods supported by tape
    +  //Please go to https://github.com/substack/tape
    +  t.true(typeof mostPerformant === 'function', 'mostPerformant is a Function');
    +  t.pass('Tested by @chalarangelo on 16/02/2018');
    +  //t.deepEqual(mostPerformant(args..), 'Expected');
    +  //t.equal(mostPerformant(args..), 'Expected');
    +  //t.false(mostPerformant(args..), 'Expected');
    +  //t.throws(mostPerformant(args..), 'Expected');
    +  t.end();
    +});
    diff --git a/test/none/none.js b/test/none/none.js
    new file mode 100644
    index 000000000..2e81d7d72
    --- /dev/null
    +++ b/test/none/none.js
    @@ -0,0 +1,2 @@
    +const none = (arr, fn = Boolean) => !arr.some(fn);
    +module.exports = none;
    \ No newline at end of file
    diff --git a/test/none/none.test.js b/test/none/none.test.js
    new file mode 100644
    index 000000000..af6209d91
    --- /dev/null
    +++ b/test/none/none.test.js
    @@ -0,0 +1,17 @@
    +const test = require('tape');
    +const none = require('./none.js');
    +
    +test('Testing none', (t) => {
    +  //For more information on all the methods supported by tape
    +  //Please go to https://github.com/substack/tape
    +  t.true(typeof none === 'function', 'none is a Function');
    +  t.true(none([0,undefined,NaN,null,'']), 'Returns true for arrays with no truthy values');
    +  t.false(none([0,1]), 'Returns false for arrays with at least one truthy value');
    +  t.true(none([4,1,0,3], x => x < 0), 'Returns true with a predicate function');
    +  t.false(none([0,1,2], x => x === 1), 'Returns false with predicate function');
    +  //t.deepEqual(none(args..), 'Expected');
    +  //t.equal(none(args..), 'Expected');
    +  //t.false(none(args..), 'Expected');
    +  //t.throws(none(args..), 'Expected');
    +  t.end();
    +});
    diff --git a/test/off/off.test.js b/test/off/off.test.js
    index 030e7797a..8a3eca663 100644
    --- a/test/off/off.test.js
    +++ b/test/off/off.test.js
    @@ -5,9 +5,10 @@ test('Testing off', (t) => {
       //For more information on all the methods supported by tape
       //Please go to https://github.com/substack/tape
       t.true(typeof off === 'function', 'off is a Function');
    +  t.pass('Tested by @chalarangelo on 16/02/2018');
       //t.deepEqual(off(args..), 'Expected');
       //t.equal(off(args..), 'Expected');
       //t.false(off(args..), 'Expected');
       //t.throws(off(args..), 'Expected');
       t.end();
    -});
    \ No newline at end of file
    +});
    diff --git a/test/on/on.test.js b/test/on/on.test.js
    index 5bfa58a76..f14e85ad0 100644
    --- a/test/on/on.test.js
    +++ b/test/on/on.test.js
    @@ -5,9 +5,10 @@ test('Testing on', (t) => {
       //For more information on all the methods supported by tape
       //Please go to https://github.com/substack/tape
       t.true(typeof on === 'function', 'on is a Function');
    +  t.pass('Tested by @chalarangelo on 16/02/2018');
       //t.deepEqual(on(args..), 'Expected');
       //t.equal(on(args..), 'Expected');
       //t.false(on(args..), 'Expected');
       //t.throws(on(args..), 'Expected');
       t.end();
    -});
    \ No newline at end of file
    +});
    diff --git a/test/onUserInputChange/onUserInputChange.test.js b/test/onUserInputChange/onUserInputChange.test.js
    index c4c181806..bbc726d63 100644
    --- a/test/onUserInputChange/onUserInputChange.test.js
    +++ b/test/onUserInputChange/onUserInputChange.test.js
    @@ -5,9 +5,10 @@ test('Testing onUserInputChange', (t) => {
       //For more information on all the methods supported by tape
       //Please go to https://github.com/substack/tape
       t.true(typeof onUserInputChange === 'function', 'onUserInputChange is a Function');
    +  t.pass('Tested by @chalarangelo on 16/02/2018');
       //t.deepEqual(onUserInputChange(args..), 'Expected');
       //t.equal(onUserInputChange(args..), 'Expected');
       //t.false(onUserInputChange(args..), 'Expected');
       //t.throws(onUserInputChange(args..), 'Expected');
       t.end();
    -});
    \ No newline at end of file
    +});
    diff --git a/test/once/once.test.js b/test/once/once.test.js
    index 6d457fe01..89aba3872 100644
    --- a/test/once/once.test.js
    +++ b/test/once/once.test.js
    @@ -5,9 +5,10 @@ test('Testing once', (t) => {
       //For more information on all the methods supported by tape
       //Please go to https://github.com/substack/tape
       t.true(typeof once === 'function', 'once is a Function');
    +  t.pass('Tested by @chalarangelo on 16/02/2018');
       //t.deepEqual(once(args..), 'Expected');
       //t.equal(once(args..), 'Expected');
       //t.false(once(args..), 'Expected');
       //t.throws(once(args..), 'Expected');
       t.end();
    -});
    \ No newline at end of file
    +});
    diff --git a/test/radsToDegrees/radsToDegrees.js b/test/radsToDegrees/radsToDegrees.js
    new file mode 100644
    index 000000000..d9a370b78
    --- /dev/null
    +++ b/test/radsToDegrees/radsToDegrees.js
    @@ -0,0 +1,2 @@
    +const radsToDegrees = rad => rad * 180.0 / Math.PI;
    +module.exports = radsToDegrees;
    \ No newline at end of file
    diff --git a/test/radsToDegrees/radsToDegrees.test.js b/test/radsToDegrees/radsToDegrees.test.js
    new file mode 100644
    index 000000000..446485d76
    --- /dev/null
    +++ b/test/radsToDegrees/radsToDegrees.test.js
    @@ -0,0 +1,14 @@
    +const test = require('tape');
    +const radsToDegrees = require('./radsToDegrees.js');
    +
    +test('Testing radsToDegrees', (t) => {
    +  //For more information on all the methods supported by tape
    +  //Please go to https://github.com/substack/tape
    +  t.true(typeof radsToDegrees === 'function', 'radsToDegrees is a Function');
    +  t.equal(radsToDegrees(Math.PI / 2), 90, 'Returns the appropriate value');
    +  //t.deepEqual(radsToDegrees(args..), 'Expected');
    +  //t.equal(radsToDegrees(args..), 'Expected');
    +  //t.false(radsToDegrees(args..), 'Expected');
    +  //t.throws(radsToDegrees(args..), 'Expected');
    +  t.end();
    +});
    diff --git a/test/randomHexColorCode/randomHexColorCode.test.js b/test/randomHexColorCode/randomHexColorCode.test.js
    index eb2cdba9f..7d9946955 100644
    --- a/test/randomHexColorCode/randomHexColorCode.test.js
    +++ b/test/randomHexColorCode/randomHexColorCode.test.js
    @@ -7,7 +7,9 @@ test('Testing randomHexColorCode', (t) => {
       t.true(typeof randomHexColorCode === 'function', 'randomHexColorCode is a Function');
       //t.deepEqual(randomHexColorCode(args..), 'Expected');
       t.equal(randomHexColorCode().length, 7);
    +  t.true(randomHexColorCode().startsWith('#'),'The color code starts with "#"');
    +  t.true(randomHexColorCode().slice(1).match(/[^0123456789abcdef]/i) === null,'The color code contains only valid hex-digits');
       //t.false(randomHexColorCode(args..), 'Expected');
       //t.throws(randomHexColorCode(args..), 'Expected');
       t.end();
    -});
    \ No newline at end of file
    +});
    diff --git a/test/setStyle/setStyle.test.js b/test/setStyle/setStyle.test.js
    index 796ab1316..3c8e4aa94 100644
    --- a/test/setStyle/setStyle.test.js
    +++ b/test/setStyle/setStyle.test.js
    @@ -5,9 +5,10 @@ test('Testing setStyle', (t) => {
       //For more information on all the methods supported by tape
       //Please go to https://github.com/substack/tape
       t.true(typeof setStyle === 'function', 'setStyle is a Function');
    +  t.pass('Tested by @chalarangelo on 16/02/2018');
       //t.deepEqual(setStyle(args..), 'Expected');
       //t.equal(setStyle(args..), 'Expected');
       //t.false(setStyle(args..), 'Expected');
       //t.throws(setStyle(args..), 'Expected');
       t.end();
    -});
    \ No newline at end of file
    +});
    diff --git a/test/show/show.test.js b/test/show/show.test.js
    index 06cf5e26e..859735338 100644
    --- a/test/show/show.test.js
    +++ b/test/show/show.test.js
    @@ -5,9 +5,10 @@ test('Testing show', (t) => {
       //For more information on all the methods supported by tape
       //Please go to https://github.com/substack/tape
       t.true(typeof show === 'function', 'show is a Function');
    +  t.pass('Tested by @chalarangelo on 16/02/2018');
       //t.deepEqual(show(args..), 'Expected');
       //t.equal(show(args..), 'Expected');
       //t.false(show(args..), 'Expected');
       //t.throws(show(args..), 'Expected');
       t.end();
    -});
    \ No newline at end of file
    +});
    diff --git a/test/sleep/sleep.test.js b/test/sleep/sleep.test.js
    index 8d5388924..57beb16e2 100644
    --- a/test/sleep/sleep.test.js
    +++ b/test/sleep/sleep.test.js
    @@ -5,9 +5,13 @@ test('Testing sleep', (t) => {
       //For more information on all the methods supported by tape
       //Please go to https://github.com/substack/tape
       t.true(typeof sleep === 'function', 'sleep is a Function');
    +  async function sleepyWork() {
    +    await sleep(1000);
    +    t.pass('Works as expected');
    +  }
       //t.deepEqual(sleep(args..), 'Expected');
       //t.equal(sleep(args..), 'Expected');
       //t.false(sleep(args..), 'Expected');
       //t.throws(sleep(args..), 'Expected');
       t.end();
    -});
    \ No newline at end of file
    +});
    diff --git a/test/stableSort/stableSort.js b/test/stableSort/stableSort.js
    new file mode 100644
    index 000000000..452d6b726
    --- /dev/null
    +++ b/test/stableSort/stableSort.js
    @@ -0,0 +1,6 @@
    +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);
    +module.exports = stableSort;
    \ No newline at end of file
    diff --git a/test/stableSort/stableSort.test.js b/test/stableSort/stableSort.test.js
    new file mode 100644
    index 000000000..e8cf95496
    --- /dev/null
    +++ b/test/stableSort/stableSort.test.js
    @@ -0,0 +1,17 @@
    +const test = require('tape');
    +const stableSort = require('./stableSort.js');
    +
    +test('Testing stableSort', (t) => {
    +  //For more information on all the methods supported by tape
    +  //Please go to https://github.com/substack/tape
    +  t.true(typeof stableSort === 'function', 'stableSort is a Function');
    +  //t.deepEqual(stableSort(args..), 'Expected');
    +  //t.equal(stableSort(args..), 'Expected');
    +  //t.false(stableSort(args..), 'Expected');
    +  //t.throws(stableSort(args..), 'Expected');
    +  
    +  const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    +  const compare = () => 0;
    +  t.deepEqual(stableSort(arr, compare), arr, 'Array is properly sorted');
    +  t.end();
    +});
    diff --git a/test/throttle/throttle.test.js b/test/throttle/throttle.test.js
    index 4de75afdb..fcd88a603 100644
    --- a/test/throttle/throttle.test.js
    +++ b/test/throttle/throttle.test.js
    @@ -5,9 +5,10 @@ test('Testing throttle', (t) => {
       //For more information on all the methods supported by tape
       //Please go to https://github.com/substack/tape
       t.true(typeof throttle === 'function', 'throttle is a Function');
    +  t.pass('Tested by @chalarangelo on 16/02/2018');
       //t.deepEqual(throttle(args..), 'Expected');
       //t.equal(throttle(args..), 'Expected');
       //t.false(throttle(args..), 'Expected');
       //t.throws(throttle(args..), 'Expected');
       t.end();
    -});
    \ No newline at end of file
    +});
    diff --git a/test/timeTaken/timeTaken.test.js b/test/timeTaken/timeTaken.test.js
    index 45d8aa0eb..fd72e9d13 100644
    --- a/test/timeTaken/timeTaken.test.js
    +++ b/test/timeTaken/timeTaken.test.js
    @@ -5,9 +5,10 @@ test('Testing timeTaken', (t) => {
       //For more information on all the methods supported by tape
       //Please go to https://github.com/substack/tape
       t.true(typeof timeTaken === 'function', 'timeTaken is a Function');
    +  t.pass('Tested by @chalarangelo on 16/02/2018');
       //t.deepEqual(timeTaken(args..), 'Expected');
       //t.equal(timeTaken(args..), 'Expected');
       //t.false(timeTaken(args..), 'Expected');
       //t.throws(timeTaken(args..), 'Expected');
       t.end();
    -});
    \ No newline at end of file
    +});
    diff --git a/test/toggleClass/toggleClass.test.js b/test/toggleClass/toggleClass.test.js
    index f7424a31d..f0bbe14d6 100644
    --- a/test/toggleClass/toggleClass.test.js
    +++ b/test/toggleClass/toggleClass.test.js
    @@ -5,9 +5,10 @@ test('Testing toggleClass', (t) => {
       //For more information on all the methods supported by tape
       //Please go to https://github.com/substack/tape
       t.true(typeof toggleClass === 'function', 'toggleClass is a Function');
    +  t.pass('Tested by @chalarangelo on 16/02/2018');
       //t.deepEqual(toggleClass(args..), 'Expected');
       //t.equal(toggleClass(args..), 'Expected');
       //t.false(toggleClass(args..), 'Expected');
       //t.throws(toggleClass(args..), 'Expected');
       t.end();
    -});
    \ No newline at end of file
    +});
    diff --git a/test/uncurry/uncurry.js b/test/uncurry/uncurry.js
    new file mode 100644
    index 000000000..a926982d5
    --- /dev/null
    +++ b/test/uncurry/uncurry.js
    @@ -0,0 +1,6 @@
    +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));
    +};
    +module.exports = uncurry;
    \ No newline at end of file
    diff --git a/test/uncurry/uncurry.test.js b/test/uncurry/uncurry.test.js
    new file mode 100644
    index 000000000..76ef507fa
    --- /dev/null
    +++ b/test/uncurry/uncurry.test.js
    @@ -0,0 +1,20 @@
    +const test = require('tape');
    +const uncurry = require('./uncurry.js');
    +
    +test('Testing uncurry', (t) => {
    +  //For more information on all the methods supported by tape
    +  //Please go to https://github.com/substack/tape
    +  t.true(typeof uncurry === 'function', 'uncurry is a Function');
    +  const add = x => y => z => x + y + z;
    +  const add1 = uncurry(add);
    +  const add2 = uncurry(add, 2);
    +  const add3 = uncurry(add, 3);
    +  t.equal(add1(1)(2)(3), 6, 'Works without a provided value for n');
    +  t.equal(add2(1,2)(3), 6, 'Works without n = 2');
    +  t.equal(add3(1,2,3), 6, 'Works withoutn = 3');
    +  //t.deepEqual(uncurry(args..), 'Expected');
    +  //t.equal(uncurry(args..), 'Expected');
    +  //t.false(uncurry(args..), 'Expected');
    +  //t.throws(uncurry(args..), 'Expected');
    +  t.end();
    +});