diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index dea9a381e..3d6967438 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -13,4 +13,3 @@
## Guidelines
- [ ] I have read the guidelines in the [CONTRIBUTING](https://github.com/30-seconds/30-seconds-of-code/blob/master/CONTRIBUTING.md) document.
-- [ ] My PR doesn't include any `testlog` changes.
diff --git a/README.md b/README.md
index e96ff2f5a..be4d6ab5d 100644
--- a/README.md
+++ b/README.md
@@ -670,7 +670,7 @@ const sum = pipeAsyncFunctions(
x => x + 3,
async x => (await x) + 4
);
-(async () => {
+(async() => {
console.log(await sum(5)); // 15 (after one second)
})();
```
@@ -2315,9 +2315,9 @@ The `func` is invoked with three arguments (`value, index, array`).
const remove = (arr, func) =>
Array.isArray(arr)
? arr.filter(func).reduce((acc, val) => {
- arr.splice(arr.indexOf(val), 1);
- return acc.concat(val);
- }, [])
+ arr.splice(arr.indexOf(val), 1);
+ return acc.concat(val);
+ }, [])
: [];
```
@@ -5490,7 +5490,6 @@ Otherwise, return the product of `n` and the factorial of `n - 1`.
Throws an exception if `n` is a negative number.
```js
-
const factorial = n =>
n < 0
? (() => {
@@ -6719,7 +6718,6 @@ Use `Object.keys(obj)` to iterate over the object's keys.
Use `Array.prototype.reduce()` to create a new object with the same values and mapped keys using `fn`.
```js
-
const deepMapKeys = (obj, f) =>
Array.isArray(obj)
? obj.map(val => deepMapKeys(val, f))
@@ -6799,7 +6797,6 @@ Use the `in` operator to check if `target` exists in `obj`.
If found, return the value of `obj[target]`, otherwise use `Object.values(obj)` and `Array.prototype.reduce()` to recursively call `dig` on each nested object until the first matching key/value pair is found.
```js
-
const dig = (obj, target) =>
target in obj
? obj[target]
diff --git a/docs/adapter.html b/docs/adapter.html
index 9b853af6c..d2314ae49 100644
--- a/docs/adapter.html
+++ b/docs/adapter.html
@@ -131,7 +131,7 @@ Object. assig
x => x + 3 ,
async x => ( await x) + 4
);
-( async () => {
+( async () => {
console. log ( await sum ( 5 ));
})();
dig Returns the target value in a nested JSON object, based on the given key.
Use the in operator to check if target exists in obj. If found, return the value of obj[target], otherwise use Object.values(obj) and Array.prototype.reduce() to recursively call dig on each nested object until the first matching key/value pair is found.
const dig = ( obj, target) =>
target in obj
? obj[ target]
: Object. values ( obj). reduce (( acc, val) => {
diff --git a/scripts/tdd.js b/scripts/tdd.js
index e8145e7a5..16f261a63 100644
--- a/scripts/tdd.js
+++ b/scripts/tdd.js
@@ -29,7 +29,7 @@ try {
undefinedTests.forEach(snippet => {
const exportTest = [
`const expect = require('expect');`,
- `const {${snippet}} = require('._30s.js');`,
+ `const {${snippet}} = require('./_30s.js');`,
`\ntest('${snippet} is a Function', () => {`,
` expect(${snippet}).toBeInstanceOf(Function);`,
`});\n`
diff --git a/snippets/deepMapKeys.md b/snippets/deepMapKeys.md
index e0223cb81..c736420ee 100644
--- a/snippets/deepMapKeys.md
+++ b/snippets/deepMapKeys.md
@@ -8,7 +8,6 @@ Use `Object.keys(obj)` to iterate over the object's keys.
Use `Array.prototype.reduce()` to create a new object with the same values and mapped keys using `fn`.
```js
-
const deepMapKeys = (obj, f) =>
Array.isArray(obj)
? obj.map(val => deepMapKeys(val, f))
diff --git a/snippets/dig.md b/snippets/dig.md
index a349ef2d3..737130b6e 100644
--- a/snippets/dig.md
+++ b/snippets/dig.md
@@ -6,7 +6,6 @@ Use the `in` operator to check if `target` exists in `obj`.
If found, return the value of `obj[target]`, otherwise use `Object.values(obj)` and `Array.prototype.reduce()` to recursively call `dig` on each nested object until the first matching key/value pair is found.
```js
-
const dig = (obj, target) =>
target in obj
? obj[target]
diff --git a/snippets/factorial.md b/snippets/factorial.md
index 2266247b4..cf3acc9cc 100644
--- a/snippets/factorial.md
+++ b/snippets/factorial.md
@@ -8,7 +8,6 @@ Otherwise, return the product of `n` and the factorial of `n - 1`.
Throws an exception if `n` is a negative number.
```js
-
const factorial = n =>
n < 0
? (() => {
diff --git a/snippets/pipeAsyncFunctions.md b/snippets/pipeAsyncFunctions.md
index 8c93add3b..47d6f620c 100644
--- a/snippets/pipeAsyncFunctions.md
+++ b/snippets/pipeAsyncFunctions.md
@@ -17,7 +17,7 @@ const sum = pipeAsyncFunctions(
x => x + 3,
async x => (await x) + 4
);
-(async () => {
+(async() => {
console.log(await sum(5)); // 15 (after one second)
})();
```
diff --git a/snippets/remove.md b/snippets/remove.md
index a8c472774..58de9c2e0 100644
--- a/snippets/remove.md
+++ b/snippets/remove.md
@@ -9,9 +9,9 @@ The `func` is invoked with three arguments (`value, index, array`).
const remove = (arr, func) =>
Array.isArray(arr)
? arr.filter(func).reduce((acc, val) => {
- arr.splice(arr.indexOf(val), 1);
- return acc.concat(val);
- }, [])
+ arr.splice(arr.indexOf(val), 1);
+ return acc.concat(val);
+ }, [])
: [];
```
diff --git a/test/_30s.js b/test/_30s.js
index 79687037f..90fcd8c9a 100644
--- a/test/_30s.js
+++ b/test/_30s.js
@@ -1,36 +1,51 @@
-const crypto = typeof require !== "undefined" && require('crypto');
-const fs = typeof require !== "undefined" && require('fs');
-
-
const all = (arr, fn = Boolean) => arr.every(fn);
-
const allEqual = arr => arr.every(val => val === arr[0]);
-
const any = (arr, fn = Boolean) => arr.some(fn);
-
const approximatelyEqual = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) < epsilon;
-
const arrayToCSV = (arr, delimiter = ',') =>
+const crypto = typeof require !== "undefined" && require('crypto');
+const fs = typeof require !== "undefined" && require('fs');
+
+
+const all = (arr, fn = Boolean) => arr.every(fn);
+
+const allEqual = arr => arr.every(val => val === arr[0]);
+
+const any = (arr, fn = Boolean) => arr.some(fn);
+
+const approximatelyEqual = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) < epsilon;
+
+const arrayToCSV = (arr, delimiter = ',') =>
arr.map(v => v.map(x => `"${x}"`).join(delimiter)).join('\n');
-
const arrayToHtmlList = (arr, listID) =>
+
+const arrayToHtmlList = (arr, listID) =>
(el => (
(el = document.querySelector('#' + listID)),
(el.innerHTML += arr.map(item => `${item} `).join(''))
))();
-
const ary = (fn, n) => (...args) => fn(...args.slice(0, n));
-
const atob = str => Buffer.from(str, 'base64').toString('binary');
-
const attempt = (fn, ...args) => {
+
+const ary = (fn, n) => (...args) => fn(...args.slice(0, n));
+
+const atob = str => Buffer.from(str, 'base64').toString('binary');
+
+const attempt = (fn, ...args) => {
try {
return fn(...args);
} catch (e) {
return e instanceof Error ? e : new Error(e);
}
};
-
const average = (...nums) => nums.reduce((acc, val) => acc + val, 0) / nums.length;
-
const averageBy = (arr, fn) =>
+
+const average = (...nums) => nums.reduce((acc, val) => acc + val, 0) / nums.length;
+
+const averageBy = (arr, fn) =>
arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0) /
arr.length;
-
const bifurcate = (arr, filter) =>
+
+const bifurcate = (arr, filter) =>
arr.reduce((acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc), [[], []]);
-
const bifurcateBy = (arr, fn) =>
+
+const bifurcateBy = (arr, fn) =>
arr.reduce((acc, val, i) => (acc[fn(val, i) ? 0 : 1].push(val), acc), [[], []]);
-
const bind = (fn, context, ...boundArgs) => (...args) => fn.apply(context, [...boundArgs, ...args]);
-
const bindAll = (obj, ...fns) =>
+
+const bind = (fn, context, ...boundArgs) => (...args) => fn.apply(context, [...boundArgs, ...args]);
+
+const bindAll = (obj, ...fns) =>
fns.forEach(
fn => (
(f = obj[fn]),
@@ -39,9 +54,11 @@ const fs = typeof require !== "undefined" && require('fs');
})
)
);
-
const bindKey = (context, fn, ...boundArgs) => (...args) =>
+
+const bindKey = (context, fn, ...boundArgs) => (...args) =>
context[fn].apply(context, [...boundArgs, ...args]);
-
const binomialCoefficient = (n, k) => {
+
+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;
@@ -51,31 +68,44 @@ const fs = typeof require !== "undefined" && require('fs');
for (let j = 2; j <= k; j++) res *= (n - j + 1) / j;
return Math.round(res);
};
-
const bottomVisible = () =>
+
+const bottomVisible = () =>
document.documentElement.clientHeight + window.scrollY >=
(document.documentElement.scrollHeight || document.documentElement.clientHeight);
-
const btoa = str => Buffer.from(str, 'binary').toString('base64');
-
const byteSize = str => new Blob([str]).size;
-const call = (key, ...args) => context => context[key](...args);
-
const capitalize = ([first, ...rest], lowerRest = false) =>
+
+const btoa = str => Buffer.from(str, 'binary').toString('base64');
+
+const byteSize = str => new Blob([str]).size;
+const call = (key, ...args) => context => context[key](...args);
+
+const capitalize = ([first, ...rest], lowerRest = false) =>
first.toUpperCase() + (lowerRest ? rest.join('').toLowerCase() : rest.join(''));
-
const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase());
-
const castArray = val => (Array.isArray(val) ? val : [val]);
-
const chainAsync = fns => {
+
+const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase());
+
+const castArray = val => (Array.isArray(val) ? val : [val]);
+
+const chainAsync = fns => {
let curr = 0;
const next = () => fns[curr++](next);
next();
};
-
const chunk = (arr, size) =>
+
+const chunk = (arr, size) =>
Array.from({ length: Math.ceil(arr.length / size) }, (v, i) =>
arr.slice(i * size, i * size + size)
);
-
const clampNumber = (num, a, b) => Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b));
-
const cloneRegExp = regExp => new RegExp(regExp.source, regExp.flags);
-
const coalesce = (...args) => args.find(_ => ![undefined, null].includes(_));
-
const coalesceFactory = valid => (...args) => args.find(valid);
-const collectInto = fn => (...args) => fn(args);
-
const colorize = (...args) => ({
+
+const clampNumber = (num, a, b) => Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b));
+
+const cloneRegExp = regExp => new RegExp(regExp.source, regExp.flags);
+
+const coalesce = (...args) => args.find(_ => ![undefined, null].includes(_));
+
+const coalesceFactory = valid => (...args) => args.find(valid);
+const collectInto = fn => (...args) => fn(args);
+
+const colorize = (...args) => ({
black: `\x1b[30m${args.join(' ')}`,
red: `\x1b[31m${args.join(' ')}`,
green: `\x1b[32m${args.join(' ')}`,
@@ -93,12 +123,18 @@ const collectInto = fn => (...args) => fn(args);
bgCyan: `\x1b[46m${args.join(' ')}\x1b[0m`,
bgWhite: `\x1b[47m${args.join(' ')}\x1b[0m`
});
-
const compact = arr => arr.filter(Boolean);
-
const compactWhitespace = str => str.replace(/\s{2,}/g,' ');
-
const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)));
-
const composeRight = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args)));
-
const converge = (converger, fns) => (...args) => converger(...fns.map(fn => fn.apply(null, args)));
-
const copyToClipboard = str => {
+
+const compact = arr => arr.filter(Boolean);
+
+const compactWhitespace = str => str.replace(/\s{2,}/g,' ');
+
+const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)));
+
+const composeRight = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args)));
+
+const converge = (converger, fns) => (...args) => converger(...fns.map(fn => fn.apply(null, args)));
+
+const copyToClipboard = str => {
const el = document.createElement('textarea');
el.value = str;
el.setAttribute('readonly', '');
@@ -115,12 +151,14 @@ const collectInto = fn => (...args) => fn(args);
document.getSelection().addRange(selected);
}
};
-
const countBy = (arr, fn) =>
+
+const countBy = (arr, fn) =>
arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => {
acc[val] = (acc[val] || 0) + 1;
return acc;
}, {});
-
const counter = (selector, start, end, step = 1, duration = 2000) => {
+
+const counter = (selector, start, end, step = 1, duration = 2000) => {
let current = start,
_step = (end - start) * step < 0 ? -step : step,
timer = setInterval(() => {
@@ -131,13 +169,16 @@ const collectInto = fn => (...args) => fn(args);
}, Math.abs(Math.floor(duration / (end - start))));
return timer;
};
-
const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0);
-
const createElement = str => {
+
+const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0);
+
+const createElement = str => {
const el = document.createElement('div');
el.innerHTML = str;
return el.firstElementChild;
};
-
const createEventHub = () => ({
+
+const createEventHub = () => ({
hub: Object.create(null),
emit(event, data) {
(this.hub[event] || []).forEach(handler => handler(data));
@@ -151,12 +192,14 @@ const collectInto = fn => (...args) => fn(args);
if (i > -1) this.hub[event].splice(i, 1);
}
});
-
const CSVToArray = (data, delimiter = ',', omitFirstRow = false) =>
+
+const CSVToArray = (data, delimiter = ',', omitFirstRow = false) =>
data
.slice(omitFirstRow ? data.indexOf('\n') + 1 : 0)
.split('\n')
.map(v => v.split(delimiter));
-
const CSVToJSON = (data, delimiter = ',') => {
+
+const CSVToJSON = (data, delimiter = ',') => {
const titles = data.slice(0, data.indexOf('\n')).split(delimiter);
return data
.slice(data.indexOf('\n') + 1)
@@ -166,34 +209,43 @@ const collectInto = fn => (...args) => fn(args);
return titles.reduce((obj, title, index) => ((obj[title] = values[index]), obj), {});
});
};
-
const currentURL = () => window.location.href;
-
const curry = (fn, arity = fn.length, ...args) =>
+
+const currentURL = () => window.location.href;
+
+const curry = (fn, arity = fn.length, ...args) =>
arity <= args.length ? fn(...args) : curry.bind(null, fn, arity, ...args);
-
const dayOfYear = date =>
+
+const dayOfYear = date =>
Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24);
-
const debounce = (fn, ms = 0) => {
+
+const debounce = (fn, ms = 0) => {
let timeoutId;
return function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => fn.apply(this, args), ms);
};
};
-
const decapitalize = ([first, ...rest], upperRest = false) =>
+
+const decapitalize = ([first, ...rest], upperRest = false) =>
first.toLowerCase() + (upperRest ? rest.join('').toUpperCase() : rest.join(''));
-
const deepClone = obj => {
+
+const deepClone = obj => {
let clone = Object.assign({}, obj);
Object.keys(clone).forEach(
key => (clone[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key])
);
return Array.isArray(obj) ? (clone.length = obj.length) && Array.from(clone) : clone;
};
-
const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v)));
-
const deepFreeze = obj =>
+
+const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v)));
+
+const deepFreeze = obj =>
Object.keys(obj).forEach(
prop =>
!(obj[prop] instanceof Object) || Object.isFrozen(obj[prop]) ? null : deepFreeze(obj[prop])
) || Object.freeze(obj);
-
+
+
const deepMapKeys = (obj, f) =>
Array.isArray(obj)
? obj.map(val => deepMapKeys(val, f))
@@ -205,24 +257,33 @@ const deepMapKeys = (obj, f) =>
return acc;
}, {})
: obj;
-
const defaults = (obj, ...defs) => Object.assign({}, obj, ...defs.reverse(), obj);
-
const defer = (fn, ...args) => setTimeout(fn, 1, ...args);
-
const degreesToRads = deg => (deg * Math.PI) / 180.0;
-
const delay = (fn, wait, ...args) => setTimeout(fn, wait, ...args);
-
const detectDeviceType = () =>
+
+const defaults = (obj, ...defs) => Object.assign({}, obj, ...defs.reverse(), obj);
+
+const defer = (fn, ...args) => setTimeout(fn, 1, ...args);
+
+const degreesToRads = deg => (deg * Math.PI) / 180.0;
+
+const delay = (fn, wait, ...args) => setTimeout(fn, wait, ...args);
+
+const detectDeviceType = () =>
/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
? 'Mobile'
: 'Desktop';
-
const difference = (a, b) => {
+
+const difference = (a, b) => {
const s = new Set(b);
return a.filter(x => !s.has(x));
};
-
const differenceBy = (a, b, fn) => {
+
+const differenceBy = (a, b, fn) => {
const s = new Set(b.map(fn));
return a.filter(x => !s.has(fn(x)));
};
-
const differenceWith = (arr, val, comp) => arr.filter(a => val.findIndex(b => comp(a, b)) === -1);
-
+
+const differenceWith = (arr, val, comp) => arr.filter(a => val.findIndex(b => comp(a, b)) === -1);
+
+
const dig = (obj, target) =>
target in obj
? obj[target]
@@ -230,20 +291,28 @@ const dig = (obj, target) =>
if (acc !== undefined) return acc;
if (typeof val === 'object') return dig(val, target);
}, undefined);
-
const digitize = n => [...`${n}`].map(i => parseInt(i));
-
const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0);
-
const drop = (arr, n = 1) => arr.slice(n);
-
const dropRight = (arr, n = 1) => arr.slice(0, -n);
-
const dropRightWhile = (arr, func) => {
+
+const digitize = n => [...`${n}`].map(i => parseInt(i));
+
+const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0);
+
+const drop = (arr, n = 1) => arr.slice(n);
+
+const dropRight = (arr, n = 1) => arr.slice(0, -n);
+
+const dropRightWhile = (arr, func) => {
while (arr.length > 0 && !func(arr[arr.length - 1])) arr = arr.slice(0, -1);
return arr;
};
-
const dropWhile = (arr, func) => {
+
+const dropWhile = (arr, func) => {
while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1);
return arr;
};
-
const elementContains = (parent, child) => parent !== child && parent.contains(child);
-
const elementIsVisibleInViewport = (el, partiallyVisible = false) => {
+
+const elementContains = (parent, child) => parent !== child && parent.contains(child);
+
+const elementIsVisibleInViewport = (el, partiallyVisible = false) => {
const { top, left, bottom, right } = el.getBoundingClientRect();
const { innerHeight, innerWidth } = window;
return partiallyVisible
@@ -251,7 +320,8 @@ const dig = (obj, target) =>
((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth))
: top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth;
};
-
const elo = ([...ratings], kFactor = 32, selfRating) => {
+
+const elo = ([...ratings], kFactor = 32, selfRating) => {
const [a, b] = ratings;
const expectedScore = (self, opponent) => 1 / (1 + 10 ** ((opponent - self) / 400));
const newRating = (rating, i) =>
@@ -267,7 +337,8 @@ const dig = (obj, target) =>
}
return ratings;
};
-
const equals = (a, b) => {
+
+const equals = (a, b) => {
if (a === b) return true;
if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
if (!a || !b || (typeof a !== 'object' && typeof b !== 'object')) return a === b;
@@ -277,7 +348,8 @@ const dig = (obj, target) =>
if (keys.length !== Object.keys(b).length) return false;
return keys.every(k => equals(a[k], b[k]));
};
-
const escapeHTML = str =>
+
+const escapeHTML = str =>
str.replace(
/[&<>'"]/g,
tag =>
@@ -289,16 +361,20 @@ const dig = (obj, target) =>
'"': '"'
}[tag] || tag)
);
-
const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
-
const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === nth - 1);
-
const extendHex = shortHex =>
+
+const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+
+const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === nth - 1);
+
+const extendHex = shortHex =>
'#' +
shortHex
.slice(shortHex.startsWith('#') ? 1 : 0)
.split('')
.map(x => x + x)
.join('');
-
+
+
const factorial = n =>
n < 0
? (() => {
@@ -307,42 +383,53 @@ const factorial = n =>
: n <= 1
? 1
: n * factorial(n - 1);
-
const fibonacci = n =>
+
+const fibonacci = n =>
Array.from({ length: n }).reduce(
(acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i),
[]
);
-const filterFalsy = arr => arr.filter(Boolean);
-
const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i));
-
const filterNonUniqueBy = (arr, fn) =>
+const filterFalsy = arr => arr.filter(Boolean);
+
+const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i));
+
+const filterNonUniqueBy = (arr, fn) =>
arr.filter((v, i) => arr.every((x, j) => (i === j) === fn(v, x, i, j)));
-
const findKey = (obj, fn) => Object.keys(obj).find(key => fn(obj[key], key, obj));
-
const findLast = (arr, fn) => arr.filter(fn).pop();
-
const findLastIndex = (arr, fn) =>
+
+const findKey = (obj, fn) => Object.keys(obj).find(key => fn(obj[key], key, obj));
+
+const findLast = (arr, fn) => arr.filter(fn).pop();
+
+const findLastIndex = (arr, fn) =>
arr
.map((val, i) => [i, val])
.filter(([i, val]) => fn(val, i, arr))
.pop()[0];
-
const findLastKey = (obj, fn) =>
+
+const findLastKey = (obj, fn) =>
Object.keys(obj)
.reverse()
.find(key => fn(obj[key], key, obj));
-
const flatten = (arr, depth = 1) =>
+
+const flatten = (arr, depth = 1) =>
arr.reduce((a, v) => a.concat(depth > 1 && Array.isArray(v) ? flatten(v, depth - 1) : v), []);
-
const flattenObject = (obj, prefix = '') =>
+
+const flattenObject = (obj, prefix = '') =>
Object.keys(obj).reduce((acc, k) => {
const pre = prefix.length ? prefix + '.' : '';
if (typeof obj[k] === 'object') Object.assign(acc, flattenObject(obj[k], pre + k));
else acc[pre + k] = obj[k];
return acc;
}, {});
-const flip = fn => (first, ...rest) => fn(...rest, first);
-
const forEachRight = (arr, callback) =>
+const flip = fn => (first, ...rest) => fn(...rest, first);
+
+const forEachRight = (arr, callback) =>
arr
.slice(0)
.reverse()
.forEach(callback);
-
const formatDuration = ms => {
+
+const formatDuration = ms => {
if (ms < 0) ms = -ms;
const time = {
day: Math.floor(ms / 86400000),
@@ -356,31 +443,39 @@ const flip = fn => (first, ...rest) => fn(...rest, first);
.map(([key, val]) => `${val} ${key}${val !== 1 ? 's' : ''}`)
.join(', ');
};
-
const forOwn = (obj, fn) => Object.keys(obj).forEach(key => fn(obj[key], key, obj));
-
const forOwnRight = (obj, fn) =>
+
+const forOwn = (obj, fn) => Object.keys(obj).forEach(key => fn(obj[key], key, obj));
+
+const forOwnRight = (obj, fn) =>
Object.keys(obj)
.reverse()
.forEach(key => fn(obj[key], key, obj));
-
const fromCamelCase = (str, separator = '_') =>
+
+const fromCamelCase = (str, separator = '_') =>
str
.replace(/([a-z\d])([A-Z])/g, '$1' + separator + '$2')
.replace(/([A-Z]+)([A-Z][a-z\d]+)/g, '$1' + separator + '$2')
.toLowerCase();
-
const functionName = fn => (console.debug(fn.name), fn);
-
const functions = (obj, inherited = false) =>
+
+const functionName = fn => (console.debug(fn.name), fn);
+
+const functions = (obj, inherited = false) =>
(inherited
? [...Object.keys(obj), ...Object.keys(Object.getPrototypeOf(obj))]
: Object.keys(obj)
).filter(key => typeof obj[key] === 'function');
-
const gcd = (...arr) => {
+
+const gcd = (...arr) => {
const _gcd = (x, y) => (!y ? x : gcd(y, x % y));
return [...arr].reduce((a, b) => _gcd(a, b));
};
-
const geometricProgression = (end, start = 1, step = 2) =>
+
+const geometricProgression = (end, start = 1, step = 2) =>
Array.from({ length: Math.floor(Math.log(end / start) / Math.log(step)) + 1 }).map(
(v, i) => start * step ** i
);
-
const get = (from, ...selectors) =>
+
+const get = (from, ...selectors) =>
[...selectors].map(s =>
s
.replace(/\[([^\[\]]*)\]/g, '.$1.')
@@ -388,14 +483,18 @@ const flip = fn => (first, ...rest) => fn(...rest, first);
.filter(t => t !== '')
.reduce((prev, cur) => prev && prev[cur], from)
);
-
const getColonTimeFromDate = date => date.toTimeString().slice(0, 8);
-
const getDaysDiffBetweenDates = (dateInitial, dateFinal) =>
+
+const getColonTimeFromDate = date => date.toTimeString().slice(0, 8);
+
+const getDaysDiffBetweenDates = (dateInitial, dateFinal) =>
(dateFinal - dateInitial) / (1000 * 3600 * 24);
-
const getImages = (el, includeDuplicates = false) => {
+
+const getImages = (el, includeDuplicates = false) => {
const images = [...el.getElementsByTagName('img')].map(img => img.getAttribute('src'));
return includeDuplicates ? images : [...new Set(images)];
};
-
const getMeridiemSuffixOfInteger = num =>
+
+const getMeridiemSuffixOfInteger = num =>
num === 0 || num === 24
? 12 + 'am'
: num === 12
@@ -403,28 +502,37 @@ const flip = fn => (first, ...rest) => fn(...rest, first);
: num < 12
? (num % 12) + 'am'
: (num % 12) + 'pm';
-
const getScrollPosition = (el = window) => ({
+
+const getScrollPosition = (el = window) => ({
x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft,
y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop
});
-
const getStyle = (el, ruleName) => getComputedStyle(el)[ruleName];
-
const getType = v =>
+
+const getStyle = (el, ruleName) => getComputedStyle(el)[ruleName];
+
+const getType = v =>
v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name.toLowerCase();
-
const getURLParameters = url =>
+
+const getURLParameters = url =>
(url.match(/([^?=&]+)(=([^&]*))/g) || []).reduce(
(a, v) => ((a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1)), a),
{}
);
-
const groupBy = (arr, fn) =>
+
+const groupBy = (arr, fn) =>
arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val, i) => {
acc[val] = (acc[val] || []).concat(arr[i]);
return acc;
}, {});
-
const hammingDistance = (num1, num2) => ((num1 ^ num2).toString(2).match(/1/g) || '').length;
-
const hasClass = (el, className) => el.classList.contains(className);
-
const hasFlags = (...flags) =>
+
+const hammingDistance = (num1, num2) => ((num1 ^ num2).toString(2).match(/1/g) || '').length;
+
+const hasClass = (el, className) => el.classList.contains(className);
+
+const hasFlags = (...flags) =>
flags.every(flag => process.argv.includes(/^-{1,2}/.test(flag) ? flag : '--' + flag));
-
const hashBrowser = val =>
+
+const hashBrowser = val =>
crypto.subtle.digest('SHA-256', new TextEncoder('utf-8').encode(val)).then(h => {
let hexes = [],
view = new DataView(h);
@@ -432,7 +540,8 @@ const flip = fn => (first, ...rest) => fn(...rest, first);
hexes.push(('00000000' + view.getUint32(i).toString(16)).slice(-8));
return hexes.join('');
});
-
+
+
const hashNode = val =>
new Promise(resolve =>
setTimeout(
@@ -446,8 +555,10 @@ const hashNode = val =>
0
)
);
-
const head = arr => arr[0];
-
const hexToRGB = hex => {
+
+const head = arr => arr[0];
+
+const hexToRGB = hex => {
let alpha = false,
h = hex.slice(hex.startsWith('#') ? 1 : 0);
if (h.length === 3) h = [...h].map(x => x + x).join('');
@@ -466,15 +577,18 @@ const hashNode = val =>
')'
);
};
-
const hide = (...el) => [...el].forEach(e => (e.style.display = 'none'));
-
const httpGet = (url, callback, err = console.error) => {
+
+const hide = (...el) => [...el].forEach(e => (e.style.display = 'none'));
+
+const httpGet = (url, callback, err = console.error) => {
const request = new XMLHttpRequest();
request.open('GET', url, true);
request.onload = () => callback(request.responseText);
request.onerror = () => err(request);
request.send();
};
-
const httpPost = (url, data, callback, err = console.error) => {
+
+const httpPost = (url, data, callback, err = console.error) => {
const request = new XMLHttpRequest();
request.open('POST', url, true);
request.setRequestHeader('Content-type', 'application/json; charset=utf-8');
@@ -482,56 +596,77 @@ const hashNode = val =>
request.onerror = () => err(request);
request.send(data);
};
-
const httpsRedirect = () => {
+
+const httpsRedirect = () => {
if (location.protocol !== 'https:') location.replace('https://' + location.href.split('//')[1]);
};
-
const hz = (fn, iterations = 100) => {
+
+const hz = (fn, iterations = 100) => {
const before = performance.now();
for (let i = 0; i < iterations; i++) fn();
return (1000 * iterations) / (performance.now() - before);
};
-
const indentString = (str, count, indent = ' ') => str.replace(/^/gm, indent.repeat(count));
-
const indexOfAll = (arr, val) => arr.reduce((acc, el, i) => (el === val ? [...acc, i] : acc), []);
-
const initial = arr => arr.slice(0, -1);
-
const initialize2DArray = (w, h, val = null) =>
+
+const indentString = (str, count, indent = ' ') => str.replace(/^/gm, indent.repeat(count));
+
+const indexOfAll = (arr, val) => arr.reduce((acc, el, i) => (el === val ? [...acc, i] : acc), []);
+
+const initial = arr => arr.slice(0, -1);
+
+const initialize2DArray = (w, h, val = null) =>
Array.from({ length: h }).map(() => Array.from({ length: w }).fill(val));
-
const initializeArrayWithRange = (end, start = 0, step = 1) =>
+
+const initializeArrayWithRange = (end, start = 0, step = 1) =>
Array.from({ length: Math.ceil((end - start + 1) / step) }, (v, i) => i * step + start);
-
const initializeArrayWithRangeRight = (end, start = 0, step = 1) =>
+
+const initializeArrayWithRangeRight = (end, start = 0, step = 1) =>
Array.from({ length: Math.ceil((end + 1 - start) / step) }).map(
(v, i, arr) => (arr.length - i - 1) * step + start
);
-
const initializeArrayWithValues = (n, val = 0) => Array(n).fill(val);
-
const initializeNDArray = (val, ...args) =>
+
+const initializeArrayWithValues = (n, val = 0) => Array(n).fill(val);
+
+const initializeNDArray = (val, ...args) =>
args.length === 0
? val
: Array.from({ length: args[0] }).map(() => initializeNDArray(val, ...args.slice(1)));
-
const inRange = (n, start, end = null) => {
+
+const inRange = (n, start, end = null) => {
if (end && start > end) [end, start] = [start, end];
return end == null ? n >= 0 && n < start : n >= start && n < end;
};
-
const insertAfter = (el, htmlString) => el.insertAdjacentHTML('afterend', htmlString);
-
const insertBefore = (el, htmlString) => el.insertAdjacentHTML('beforebegin', htmlString);
-
const intersection = (a, b) => {
+
+const insertAfter = (el, htmlString) => el.insertAdjacentHTML('afterend', htmlString);
+
+const insertBefore = (el, htmlString) => el.insertAdjacentHTML('beforebegin', htmlString);
+
+const intersection = (a, b) => {
const s = new Set(b);
return a.filter(x => s.has(x));
};
-
const intersectionBy = (a, b, fn) => {
+
+const intersectionBy = (a, b, fn) => {
const s = new Set(b.map(fn));
return a.filter(x => s.has(fn(x)));
};
-
const intersectionWith = (a, b, comp) => a.filter(x => b.findIndex(y => comp(x, y)) !== -1);
-
const invertKeyValues = (obj, fn) =>
+
+const intersectionWith = (a, b, comp) => a.filter(x => b.findIndex(y => comp(x, y)) !== -1);
+
+const invertKeyValues = (obj, fn) =>
Object.keys(obj).reduce((acc, key) => {
const val = fn ? fn(obj[key]) : obj[key];
acc[val] = acc[val] || [];
acc[val].push(key);
return acc;
}, {});
-
const is = (type, val) => ![, null].includes(val) && val.constructor === type;
-
const isAbsoluteURL = str => /^[a-z][a-z0-9+.-]*:/.test(str);
-
const isAfterDate = (dateA, dateB) => dateA > dateB;
-
const isAnagram = (str1, str2) => {
+
+const is = (type, val) => ![, null].includes(val) && val.constructor === type;
+
+const isAbsoluteURL = str => /^[a-z][a-z0-9+.-]*:/.test(str);
+
+const isAfterDate = (dateA, dateB) => dateA > dateB;
+
+const isAnagram = (str1, str2) => {
const normalize = str =>
str
.toLowerCase()
@@ -541,13 +676,20 @@ const hashNode = val =>
.join('');
return normalize(str1) === normalize(str2);
};
-
const isArrayLike = obj => obj != null && typeof obj[Symbol.iterator] === 'function';
-
const isBeforeDate = (dateA, dateB) => dateA < dateB;
-
const isBoolean = val => typeof val === 'boolean';
-
const isBrowser = () => ![typeof window, typeof document].includes('undefined');
-
const isBrowserTabFocused = () => !document.hidden;
-
const isDivisible = (dividend, divisor) => dividend % divisor === 0;
-
const isDuplexStream = val =>
+
+const isArrayLike = obj => obj != null && typeof obj[Symbol.iterator] === 'function';
+
+const isBeforeDate = (dateA, dateB) => dateA < dateB;
+
+const isBoolean = val => typeof val === 'boolean';
+
+const isBrowser = () => ![typeof window, typeof document].includes('undefined');
+
+const isBrowserTabFocused = () => !document.hidden;
+
+const isDivisible = (dividend, divisor) => dividend % divisor === 0;
+
+const isDuplexStream = val =>
val !== null &&
typeof val === 'object' &&
typeof val.pipe === 'function' &&
@@ -555,35 +697,52 @@ const hashNode = val =>
typeof val._readableState === 'object' &&
typeof val._write === 'function' &&
typeof val._writableState === 'object';
-
const isEmpty = val => val == null || !(Object.keys(val) || val).length;
-
const isEven = num => num % 2 === 0;
-
const isFunction = val => typeof val === 'function';
-
const isLowerCase = str => str === str.toLowerCase();
-
const isNegativeZero = val => val === 0 && 1 / val === -Infinity;
-
const isNil = val => val === undefined || val === null;
-
const isNull = val => val === null;
-
const isNumber = val => typeof val === 'number';
-
const isObject = obj => obj === Object(obj);
-
const isObjectLike = val => val !== null && typeof val === 'object';
-
const isPlainObject = val => !!val && typeof val === 'object' && val.constructor === Object;
-
const isPrime = num => {
+
+const isEmpty = val => val == null || !(Object.keys(val) || val).length;
+
+const isEven = num => num % 2 === 0;
+
+const isFunction = val => typeof val === 'function';
+
+const isLowerCase = str => str === str.toLowerCase();
+
+const isNegativeZero = val => val === 0 && 1 / val === -Infinity;
+
+const isNil = val => val === undefined || val === null;
+
+const isNull = val => val === null;
+
+const isNumber = val => typeof val === 'number';
+
+const isObject = obj => obj === Object(obj);
+
+const isObjectLike = val => val !== null && typeof val === 'object';
+
+const isPlainObject = val => !!val && typeof val === 'object' && val.constructor === Object;
+
+const isPrime = num => {
const boundary = Math.floor(Math.sqrt(num));
for (var i = 2; i <= boundary; i++) if (num % i === 0) return false;
return num >= 2;
};
-
const isPrimitive = val => Object(val) !== val;
-
const isPromiseLike = obj =>
+
+const isPrimitive = val => Object(val) !== val;
+
+const isPromiseLike = obj =>
obj !== null &&
(typeof obj === 'object' || typeof obj === 'function') &&
typeof obj.then === 'function';
-
const isReadableStream = val =>
+
+const isReadableStream = val =>
val !== null &&
typeof val === 'object' &&
typeof val.pipe === 'function' &&
typeof val._read === 'function' &&
typeof val._readableState === 'object';
-
const isSameDate = (dateA, dateB) => dateA.toISOString() === dateB.toISOString();
-
const isSorted = arr => {
+
+const isSameDate = (dateA, dateB) => dateA.toISOString() === dateB.toISOString();
+
+const isSorted = arr => {
let direction = -(arr[0] - arr[1]);
for (let [i, val] of arr.entries()) {
direction = !direction ? -(arr[i - 1] - arr[i]) : direction;
@@ -591,13 +750,20 @@ const hashNode = val =>
else if ((val - arr[i + 1]) * direction > 0) return 0;
}
};
-
const isStream = val => val !== null && typeof val === 'object' && typeof val.pipe === 'function';
-
const isString = val => typeof val === 'string';
-
const isSymbol = val => typeof val === 'symbol';
-
const isTravisCI = () => 'TRAVIS' in process.env && 'CI' in process.env;
-
const isUndefined = val => val === undefined;
-
const isUpperCase = str => str === str.toUpperCase();
-
const isValidJSON = str => {
+
+const isStream = val => val !== null && typeof val === 'object' && typeof val.pipe === 'function';
+
+const isString = val => typeof val === 'string';
+
+const isSymbol = val => typeof val === 'symbol';
+
+const isTravisCI = () => 'TRAVIS' in process.env && 'CI' in process.env;
+
+const isUndefined = val => val === undefined;
+
+const isUpperCase = str => str === str.toUpperCase();
+
+const isValidJSON = str => {
try {
JSON.parse(str);
return true;
@@ -605,13 +771,15 @@ const hashNode = val =>
return false;
}
};
-
const isWritableStream = val =>
+
+const isWritableStream = val =>
val !== null &&
typeof val === 'object' &&
typeof val.pipe === 'function' &&
typeof val._write === 'function' &&
typeof val._writableState === 'object';
-
const join = (arr, separator = ',', end = separator) =>
+
+const join = (arr, separator = ',', end = separator) =>
arr.reduce(
(acc, val, i) =>
i === arr.length - 2
@@ -621,7 +789,8 @@ const hashNode = val =>
: acc + val + separator,
''
);
-
const JSONtoCSV = (arr, columns, delimiter = ',') =>
+
+const JSONtoCSV = (arr, columns, delimiter = ',') =>
[
columns.join(delimiter),
...arr.map(obj =>
@@ -631,22 +800,28 @@ const hashNode = val =>
)
)
].join('\n');
-
+
+
const JSONToFile = (obj, filename) =>
fs.writeFile(`${filename}.json`, JSON.stringify(obj, null, 2));
-
const last = arr => arr[arr.length - 1];
-
const lcm = (...arr) => {
+
+const last = arr => arr[arr.length - 1];
+
+const lcm = (...arr) => {
const gcd = (x, y) => (!y ? x : gcd(y, x % y));
const _lcm = (x, y) => (x * y) / gcd(x, y);
return [...arr].reduce((a, b) => _lcm(a, b));
};
-
const longestItem = (...vals) => vals.reduce((a, x) => (x.length > a.length ? x : a));
-
const lowercaseKeys = obj =>
+
+const longestItem = (...vals) => vals.reduce((a, x) => (x.length > a.length ? x : a));
+
+const lowercaseKeys = obj =>
Object.keys(obj).reduce((acc, key) => {
acc[key.toLowerCase()] = obj[key];
return acc;
}, {});
-
const luhnCheck = num => {
+
+const luhnCheck = num => {
let arr = (num + '')
.split('')
.reverse()
@@ -656,44 +831,56 @@ const JSONToFile = (obj, filename) =>
sum += lastDigit;
return sum % 10 === 0;
};
-
const mapKeys = (obj, fn) =>
+
+const mapKeys = (obj, fn) =>
Object.keys(obj).reduce((acc, k) => {
acc[fn(obj[k], k, obj)] = obj[k];
return acc;
}, {});
-
const mapObject = (arr, fn) =>
+
+const mapObject = (arr, fn) =>
(a => (
(a = [arr, arr.map(fn)]), a[0].reduce((acc, val, ind) => ((acc[val] = a[1][ind]), acc), {})
))();
-
const mapString = (str, fn) =>
+
+const mapString = (str, fn) =>
str
.split('')
.map((c, i) => fn(c, i, str))
.join('');
-
const mapValues = (obj, fn) =>
+
+const mapValues = (obj, fn) =>
Object.keys(obj).reduce((acc, k) => {
acc[k] = fn(obj[k], k, obj);
return acc;
}, {});
-
const mask = (cc, num = 4, mask = '*') => `${cc}`.slice(-num).padStart(`${cc}`.length, mask);
-
const matches = (obj, source) =>
+
+const mask = (cc, num = 4, mask = '*') => `${cc}`.slice(-num).padStart(`${cc}`.length, mask);
+
+const matches = (obj, source) =>
Object.keys(source).every(key => obj.hasOwnProperty(key) && obj[key] === source[key]);
-
const matchesWith = (obj, source, fn) =>
+
+const matchesWith = (obj, source, fn) =>
Object.keys(source).every(
key =>
obj.hasOwnProperty(key) && fn
? fn(obj[key], source[key], key, obj, source)
: obj[key] == source[key]
);
-
const maxBy = (arr, fn) => Math.max(...arr.map(typeof fn === 'function' ? fn : val => val[fn]));
-
const maxDate = (...dates) => new Date(Math.max.apply(null, ...dates));
-
const maxN = (arr, n = 1) => [...arr].sort((a, b) => b - a).slice(0, n);
-
const median = arr => {
+
+const maxBy = (arr, fn) => Math.max(...arr.map(typeof fn === 'function' ? fn : val => val[fn]));
+
+const maxDate = (...dates) => new Date(Math.max.apply(null, ...dates));
+
+const maxN = (arr, n = 1) => [...arr].sort((a, b) => b - a).slice(0, n);
+
+const median = arr => {
const mid = Math.floor(arr.length / 2),
nums = [...arr].sort((a, b) => a - b);
return arr.length % 2 !== 0 ? nums[mid] : (nums[mid - 1] + nums[mid]) / 2;
};
-
const memoize = fn => {
+
+const memoize = fn => {
const cache = new Map();
const cached = function(val) {
return cache.has(val) ? cache.get(val) : cache.set(val, fn.call(this, val)) && cache.get(val);
@@ -701,7 +888,8 @@ const JSONToFile = (obj, filename) =>
cached.cache = cache;
return cached;
};
-
const merge = (...objs) =>
+
+const merge = (...objs) =>
[...objs].reduce(
(acc, obj) =>
Object.keys(obj).reduce((a, k) => {
@@ -710,11 +898,16 @@ const JSONToFile = (obj, filename) =>
}, {}),
{}
);
-
const midpoint = ([x1, y1], [x2, y2]) => [(x1 + x2) / 2, (y1 + y2) / 2];
-
const minBy = (arr, fn) => Math.min(...arr.map(typeof fn === 'function' ? fn : val => val[fn]));
-
const minDate = (...dates) => new Date(Math.min.apply(null, ...dates));
-
const minN = (arr, n = 1) => [...arr].sort((a, b) => a - b).slice(0, n);
-
const mostPerformant = (fns, iterations = 10000) => {
+
+const midpoint = ([x1, y1], [x2, y2]) => [(x1 + x2) / 2, (y1 + y2) / 2];
+
+const minBy = (arr, fn) => Math.min(...arr.map(typeof fn === 'function' ? fn : val => val[fn]));
+
+const minDate = (...dates) => new Date(Math.min.apply(null, ...dates));
+
+const minN = (arr, n = 1) => [...arr].sort((a, b) => a - b).slice(0, n);
+
+const mostPerformant = (fns, iterations = 10000) => {
const times = fns.map(fn => {
const before = performance.now();
for (let i = 0; i < iterations; i++) fn();
@@ -722,18 +915,27 @@ const JSONToFile = (obj, filename) =>
});
return times.indexOf(Math.min(...times));
};
-
const negate = func => (...args) => !func(...args);
-
const nest = (items, id = null, link = 'parent_id') =>
+
+const negate = func => (...args) => !func(...args);
+
+const nest = (items, id = null, link = 'parent_id') =>
items
.filter(item => item[link] === id)
.map(item => ({ ...item, children: nest(items, item.id) }));
-
const nodeListToArray = nodeList => [...nodeList];
-
const none = (arr, fn = Boolean) => !arr.some(fn);
-
const nthArg = n => (...args) => args.slice(n)[0];
-
const nthElement = (arr, n = 0) => (n === -1 ? arr.slice(n) : arr.slice(n, n + 1))[0];
-
const objectFromPairs = arr => arr.reduce((a, [key, val]) => ((a[key] = val), a), {});
-
const objectToPairs = obj => Object.keys(obj).map(k => [k, obj[k]]);
-
const observeMutations = (element, callback, options) => {
+
+const nodeListToArray = nodeList => [...nodeList];
+
+const none = (arr, fn = Boolean) => !arr.some(fn);
+
+const nthArg = n => (...args) => args.slice(n)[0];
+
+const nthElement = (arr, n = 0) => (n === -1 ? arr.slice(n) : arr.slice(n, n + 1))[0];
+
+const objectFromPairs = arr => arr.reduce((a, [key, val]) => ((a[key] = val), a), {});
+
+const objectToPairs = obj => Object.keys(obj).map(k => [k, obj[k]]);
+
+const observeMutations = (element, callback, options) => {
const observer = new MutationObserver(mutations => mutations.forEach(m => callback(m)));
observer.observe(
element,
@@ -751,22 +953,28 @@ const JSONToFile = (obj, filename) =>
);
return observer;
};
-
const off = (el, evt, fn, opts = false) => el.removeEventListener(evt, fn, opts);
-
const offset = (arr, offset) => [...arr.slice(offset), ...arr.slice(0, offset)];
-
const omit = (obj, arr) =>
+
+const off = (el, evt, fn, opts = false) => el.removeEventListener(evt, fn, opts);
+
+const offset = (arr, offset) => [...arr.slice(offset), ...arr.slice(0, offset)];
+
+const omit = (obj, arr) =>
Object.keys(obj)
.filter(k => !arr.includes(k))
.reduce((acc, key) => ((acc[key] = obj[key]), acc), {});
-
const omitBy = (obj, fn) =>
+
+const omitBy = (obj, fn) =>
Object.keys(obj)
.filter(k => !fn(obj[k], k))
.reduce((acc, key) => ((acc[key] = obj[key]), acc), {});
-
const on = (el, evt, fn, opts = {}) => {
+
+const on = (el, evt, fn, opts = {}) => {
const delegatorFn = e => e.target.matches(opts.target) && fn.call(e.target, e);
el.addEventListener(evt, opts.target ? delegatorFn : fn, opts.options || false);
if (opts.target) return delegatorFn;
};
-
const once = fn => {
+
+const once = fn => {
let called = false;
return function(...args) {
if (called) return;
@@ -774,7 +982,8 @@ const JSONToFile = (obj, filename) =>
return fn.apply(this, args);
};
};
-
const onUserInputChange = callback => {
+
+const onUserInputChange = callback => {
let type = 'mouse',
lastTime = 0;
const mousemoveHandler = () => {
@@ -788,7 +997,8 @@ const JSONToFile = (obj, filename) =>
(type = 'touch'), callback(type), document.addEventListener('mousemove', mousemoveHandler);
});
};
-
const orderBy = (arr, props, orders) =>
+
+const orderBy = (arr, props, orders) =>
[...arr].sort((a, b) =>
props.reduce((acc, prop, i) => {
if (acc === 0) {
@@ -798,15 +1008,20 @@ const JSONToFile = (obj, filename) =>
return acc;
}, 0)
);
-
const over = (...fns) => (...args) => fns.map(fn => fn.apply(null, args));
-
const overArgs = (fn, transforms) => (...args) => fn(...args.map((val, i) => transforms[i](val)));
-
const pad = (str, length, char = ' ') =>
+
+const over = (...fns) => (...args) => fns.map(fn => fn.apply(null, args));
+
+const overArgs = (fn, transforms) => (...args) => fn(...args.map((val, i) => transforms[i](val)));
+
+const pad = (str, length, char = ' ') =>
str.padStart((str.length + length) / 2, char).padEnd(length, char);
-
const palindrome = str => {
+
+const palindrome = str => {
const s = str.toLowerCase().replace(/[\W_]/g, '');
return s === [...s].reverse().join('');
};
-
const parseCookie = str =>
+
+const parseCookie = str =>
str
.split(';')
.map(v => v.split('='))
@@ -814,9 +1029,12 @@ const JSONToFile = (obj, filename) =>
acc[decodeURIComponent(v[0].trim())] = decodeURIComponent(v[1].trim());
return acc;
}, {});
-
const partial = (fn, ...partials) => (...args) => fn(...partials, ...args);
-
const partialRight = (fn, ...partials) => (...args) => fn(...args, ...partials);
-
const partition = (arr, fn) =>
+
+const partial = (fn, ...partials) => (...args) => fn(...partials, ...args);
+
+const partialRight = (fn, ...partials) => (...args) => fn(...args, ...partials);
+
+const partition = (arr, fn) =>
arr.reduce(
(acc, val, i, arr) => {
acc[fn(val, i, arr) ? 0 : 1].push(val);
@@ -824,9 +1042,11 @@ const JSONToFile = (obj, filename) =>
},
[[], []]
);
-
const percentile = (arr, val) =>
+
+const percentile = (arr, val) =>
(100 * arr.reduce((acc, v) => acc + (v < val ? 1 : 0) + (v === val ? 0.5 : 0), 0)) / arr.length;
-
const permutations = arr => {
+
+const permutations = arr => {
if (arr.length <= 2) return arr.length === 2 ? [arr, [arr[1], arr[0]]] : arr;
return arr.reduce(
(acc, item, i) =>
@@ -836,22 +1056,29 @@ const JSONToFile = (obj, filename) =>
[]
);
};
-
const pick = (obj, arr) =>
+
+const pick = (obj, arr) =>
arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {});
-
const pickBy = (obj, fn) =>
+
+const pickBy = (obj, fn) =>
Object.keys(obj)
.filter(k => fn(obj[k], k))
.reduce((acc, key) => ((acc[key] = obj[key]), acc), {});
-
const pipeAsyncFunctions = (...fns) => arg => fns.reduce((p, f) => p.then(f), Promise.resolve(arg));
-
const pipeFunctions = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args)));
-
const pluralize = (val, word, plural = word + 's') => {
+
+const pipeAsyncFunctions = (...fns) => arg => fns.reduce((p, f) => p.then(f), Promise.resolve(arg));
+
+const pipeFunctions = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args)));
+
+const pluralize = (val, word, plural = word + 's') => {
const _pluralize = (num, word, plural = word + 's') =>
[1, -1].includes(Number(num)) ? word : plural;
if (typeof val === 'object') return (num, word) => _pluralize(num, word, val[word]);
return _pluralize(val, word, plural);
};
-
const powerset = arr => arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]);
-
const prefix = prop => {
+
+const powerset = arr => arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]);
+
+const prefix = prop => {
const capitalizedProp = prop.charAt(0).toUpperCase() + prop.slice(1);
const prefixes = ['', 'webkit', 'moz', 'ms', 'o'];
const i = prefixes.findIndex(
@@ -859,31 +1086,36 @@ const JSONToFile = (obj, filename) =>
);
return i !== -1 ? (i === 0 ? prop : prefixes[i] + capitalizedProp) : null;
};
-
const prettyBytes = (num, precision = 3, addSpace = true) => {
+
+const prettyBytes = (num, precision = 3, addSpace = true) => {
const UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
if (Math.abs(num) < 1) return num + (addSpace ? ' ' : '') + UNITS[0];
const exponent = Math.min(Math.floor(Math.log10(num < 0 ? -num : num) / 3), UNITS.length - 1);
const n = Number(((num < 0 ? -num : num) / 1000 ** exponent).toPrecision(precision));
return (num < 0 ? '-' : '') + n + (addSpace ? ' ' : '') + UNITS[exponent];
};
-
const primes = num => {
+
+const primes = num => {
let arr = Array.from({ length: num - 1 }).map((x, i) => i + 2),
sqroot = Math.floor(Math.sqrt(num)),
numsTillSqroot = Array.from({ length: sqroot - 1 }).map((x, i) => i + 2);
numsTillSqroot.forEach(x => (arr = arr.filter(y => y % x !== 0 || y === x)));
return arr;
};
-
const promisify = func => (...args) =>
+
+const promisify = func => (...args) =>
new Promise((resolve, reject) =>
func(...args, (err, result) => (err ? reject(err) : resolve(result)))
);
-
const pull = (arr, ...args) => {
+
+const pull = (arr, ...args) => {
let argState = Array.isArray(args[0]) ? args[0] : args;
let pulled = arr.filter((v, i) => !argState.includes(v));
arr.length = 0;
pulled.forEach(v => arr.push(v));
};
-
const pullAtIndex = (arr, pullArr) => {
+
+const pullAtIndex = (arr, pullArr) => {
let removed = [];
let pulled = arr
.map((v, i) => (pullArr.includes(i) ? removed.push(v) : v))
@@ -892,7 +1124,8 @@ const JSONToFile = (obj, filename) =>
pulled.forEach(v => arr.push(v));
return removed;
};
-
const pullAtValue = (arr, pullArr) => {
+
+const pullAtValue = (arr, pullArr) => {
let removed = [],
pushToRemove = arr.forEach((v, i) => (pullArr.includes(v) ? removed.push(v) : v)),
mutateTo = arr.filter((v, i) => !pullArr.includes(v));
@@ -900,7 +1133,8 @@ const JSONToFile = (obj, filename) =>
mutateTo.forEach(v => arr.push(v));
return removed;
};
-
const pullBy = (arr, ...args) => {
+
+const pullBy = (arr, ...args) => {
const length = args.length;
let fn = length > 1 ? args[length - 1] : undefined;
fn = typeof fn == 'function' ? (args.pop(), fn) : undefined;
@@ -909,23 +1143,31 @@ const JSONToFile = (obj, filename) =>
arr.length = 0;
pulled.forEach(v => arr.push(v));
};
-
const radsToDegrees = rad => (rad * 180.0) / Math.PI;
-
const randomHexColorCode = () => {
+
+const radsToDegrees = rad => (rad * 180.0) / Math.PI;
+
+const randomHexColorCode = () => {
let n = (Math.random() * 0xfffff * 1000000).toString(16);
return '#' + n.slice(0, 6);
};
-
const randomIntArrayInRange = (min, max, n = 1) =>
+
+const randomIntArrayInRange = (min, max, n = 1) =>
Array.from({ length: n }, () => Math.floor(Math.random() * (max - min + 1)) + min);
-
const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
-
const randomNumberInRange = (min, max) => Math.random() * (max - min) + min;
-
+
+const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
+
+const randomNumberInRange = (min, max) => Math.random() * (max - min) + min;
+
+
const readFileLines = filename =>
fs
.readFileSync(filename)
.toString('UTF8')
.split('\n');
-
const rearg = (fn, indexes) => (...args) => fn(...indexes.map(i => args[i]));
-
const recordAnimationFrames = (callback, autoStart = true) => {
+
+const rearg = (fn, indexes) => (...args) => fn(...indexes.map(i => args[i]));
+
+const recordAnimationFrames = (callback, autoStart = true) => {
let running = true,
raf;
const stop = () => {
@@ -945,29 +1187,37 @@ const readFileLines = filename =>
if (autoStart) start();
return { start, stop };
};
-
const redirect = (url, asLink = true) =>
+
+const redirect = (url, asLink = true) =>
asLink ? (window.location.href = url) : window.location.replace(url);
-
const reducedFilter = (data, keys, fn) =>
+
+const reducedFilter = (data, keys, fn) =>
data.filter(fn).map(el =>
keys.reduce((acc, key) => {
acc[key] = el[key];
return acc;
}, {})
);
-
const reduceSuccessive = (arr, fn, acc) =>
+
+const reduceSuccessive = (arr, fn, acc) =>
arr.reduce((res, val, i, arr) => (res.push(fn(res.slice(-1)[0], val, i, arr)), res), [acc]);
-
const reduceWhich = (arr, comparator = (a, b) => a - b) =>
+
+const reduceWhich = (arr, comparator = (a, b) => a - b) =>
arr.reduce((a, b) => (comparator(a, b) >= 0 ? b : a));
-
const reject = (pred, array) => array.filter((...args) => !pred(...args));
-
const remove = (arr, func) =>
+
+const reject = (pred, array) => array.filter((...args) => !pred(...args));
+
+const remove = (arr, func) =>
Array.isArray(arr)
? arr.filter(func).reduce((acc, val) => {
arr.splice(arr.indexOf(val), 1);
return acc.concat(val);
}, [])
: [];
-
const removeNonASCII = str => str.replace(/[^\x20-\x7E]/g, '');
-
const renameKeys = (keysMap, obj) =>
+
+const removeNonASCII = str => str.replace(/[^\x20-\x7E]/g, '');
+
+const renameKeys = (keysMap, obj) =>
Object.keys(obj).reduce(
(acc, key) => ({
...acc,
@@ -975,10 +1225,14 @@ const readFileLines = filename =>
}),
{}
);
-
const reverseString = str => [...str].reverse().join('');
-
const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0');
-
const round = (n, decimals = 0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`);
-
const runAsync = fn => {
+
+const reverseString = str => [...str].reverse().join('');
+
+const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0');
+
+const round = (n, decimals = 0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`);
+
+const runAsync = fn => {
const worker = new Worker(
URL.createObjectURL(new Blob([`postMessage((${fn})());`]), {
type: 'application/javascript; charset=utf-8'
@@ -993,9 +1247,12 @@ const readFileLines = filename =>
};
});
};
-
const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve());
-
const sample = arr => arr[Math.floor(Math.random() * arr.length)];
-
const sampleSize = ([...arr], n = 1) => {
+
+const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve());
+
+const sample = arr => arr[Math.floor(Math.random() * arr.length)];
+
+const sampleSize = ([...arr], n = 1) => {
let m = arr.length;
while (m) {
const i = Math.floor(Math.random() * m--);
@@ -1003,14 +1260,16 @@ const readFileLines = filename =>
}
return arr.slice(0, n);
};
-
const scrollToTop = () => {
+
+const scrollToTop = () => {
const c = document.documentElement.scrollTop || document.body.scrollTop;
if (c > 0) {
window.requestAnimationFrame(scrollToTop);
window.scrollTo(0, c - c / 8);
}
};
-
const sdbm = str => {
+
+const sdbm = str => {
let arr = str.split('');
return arr.reduce(
(hashCode, currentVal) =>
@@ -1018,16 +1277,22 @@ const readFileLines = filename =>
0
);
};
-
const serializeCookie = (name, val) => `${encodeURIComponent(name)}=${encodeURIComponent(val)}`;
-
const setStyle = (el, ruleName, val) => (el.style[ruleName] = val);
-
const shallowClone = obj => Object.assign({}, obj);
-
const shank = (arr, index = 0, delCount = 0, ...elements) =>
+
+const serializeCookie = (name, val) => `${encodeURIComponent(name)}=${encodeURIComponent(val)}`;
+
+const setStyle = (el, ruleName, val) => (el.style[ruleName] = val);
+
+const shallowClone = obj => Object.assign({}, obj);
+
+const shank = (arr, index = 0, delCount = 0, ...elements) =>
arr
.slice(0, index)
.concat(elements)
.concat(arr.slice(index + delCount));
-
const show = (...el) => [...el].forEach(e => (e.style.display = ''));
-
const shuffle = ([...arr]) => {
+
+const show = (...el) => [...el].forEach(e => (e.style.display = ''));
+
+const shuffle = ([...arr]) => {
let m = arr.length;
while (m) {
const i = Math.floor(Math.random() * m--);
@@ -1035,8 +1300,10 @@ const readFileLines = filename =>
}
return arr;
};
-
const similarity = (arr, values) => arr.filter(v => values.includes(v));
-
const size = val =>
+
+const similarity = (arr, values) => arr.filter(v => values.includes(v));
+
+const size = val =>
Array.isArray(val)
? val.length
: val && typeof val === 'object'
@@ -1044,29 +1311,36 @@ const readFileLines = filename =>
: typeof val === 'string'
? new Blob([val]).size
: 0;
-
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
-
const smoothScroll = element =>
+
+const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
+
+const smoothScroll = element =>
document.querySelector(element).scrollIntoView({
behavior: 'smooth'
});
-
const sortCharactersInString = str => [...str].sort((a, b) => a.localeCompare(b)).join('');
-
const sortedIndex = (arr, n) => {
+
+const sortCharactersInString = str => [...str].sort((a, b) => a.localeCompare(b)).join('');
+
+const sortedIndex = (arr, n) => {
const isDescending = arr[0] > arr[arr.length - 1];
const index = arr.findIndex(el => (isDescending ? n >= el : n <= el));
return index === -1 ? arr.length : index;
};
-
const sortedIndexBy = (arr, n, fn) => {
+
+const sortedIndexBy = (arr, n, fn) => {
const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]);
const val = fn(n);
const index = arr.findIndex(el => (isDescending ? val >= fn(el) : val <= fn(el)));
return index === -1 ? arr.length : index;
};
-
const sortedLastIndex = (arr, n) => {
+
+const sortedLastIndex = (arr, n) => {
const isDescending = arr[0] > arr[arr.length - 1];
const index = arr.reverse().findIndex(el => (isDescending ? n <= el : n >= el));
return index === -1 ? 0 : arr.length - index;
};
-
const sortedLastIndexBy = (arr, n, fn) => {
+
+const sortedLastIndexBy = (arr, n, fn) => {
const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]);
const val = fn(n);
const index = arr
@@ -1075,21 +1349,26 @@ const readFileLines = filename =>
.findIndex(el => (isDescending ? val <= el : val >= el));
return index === -1 ? 0 : arr.length - index;
};
-
const splitLines = str => str.split(/\r?\n/);
-const spreadOver = fn => argsArr => fn(...argsArr);
-
const stableSort = (arr, compare) =>
+
+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 standardDeviation = (arr, usePopulation = false) => {
const mean = arr.reduce((acc, val) => acc + val, 0) / arr.length;
return Math.sqrt(
arr.reduce((acc, val) => acc.concat((val - mean) ** 2), []).reduce((acc, val) => acc + val, 0) /
(arr.length - (usePopulation ? 0 : 1))
);
};
-
const stringPermutations = str => {
+
+const stringPermutations = str => {
if (str.length <= 2) return str.length === 2 ? [str, str[1] + str[0]] : [str];
return str
.split('')
@@ -1099,39 +1378,52 @@ const spreadOver = fn => argsArr => fn(...argsArr);
[]
);
};
-
const stripHTMLTags = str => str.replace(/<[^>]*>/g, '');
-
const sum = (...arr) => [...arr].reduce((acc, val) => acc + val, 0);
-
const sumBy = (arr, fn) =>
+
+const stripHTMLTags = str => str.replace(/<[^>]*>/g, '');
+
+const sum = (...arr) => [...arr].reduce((acc, val) => acc + val, 0);
+
+const sumBy = (arr, fn) =>
arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0);
-
const sumPower = (end, power = 2, start = 1) =>
+
+const sumPower = (end, power = 2, start = 1) =>
Array(end + 1 - start)
.fill(0)
.map((x, i) => (i + start) ** power)
.reduce((a, b) => a + b, 0);
-
const symmetricDifference = (a, b) => {
+
+const symmetricDifference = (a, b) => {
const sA = new Set(a),
sB = new Set(b);
return [...a.filter(x => !sB.has(x)), ...b.filter(x => !sA.has(x))];
};
-
const symmetricDifferenceBy = (a, b, fn) => {
+
+const symmetricDifferenceBy = (a, b, fn) => {
const sA = new Set(a.map(v => fn(v))),
sB = new Set(b.map(v => fn(v)));
return [...a.filter(x => !sB.has(fn(x))), ...b.filter(x => !sA.has(fn(x)))];
};
-
const symmetricDifferenceWith = (arr, val, comp) => [
+
+const symmetricDifferenceWith = (arr, val, comp) => [
...arr.filter(a => val.findIndex(b => comp(a, b)) === -1),
...val.filter(a => arr.findIndex(b => comp(a, b)) === -1)
];
-
const tail = arr => (arr.length > 1 ? arr.slice(1) : arr);
-
const take = (arr, n = 1) => arr.slice(0, n);
-
const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length);
-
const takeRightWhile = (arr, func) =>
+
+const tail = arr => (arr.length > 1 ? arr.slice(1) : arr);
+
+const take = (arr, n = 1) => arr.slice(0, n);
+
+const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length);
+
+const takeRightWhile = (arr, func) =>
arr.reduceRight((acc, el) => (func(el) ? acc : [el, ...acc]), []);
-
const takeWhile = (arr, func) => {
+
+const takeWhile = (arr, func) => {
for (const [i, val] of arr.entries()) if (func(val)) return arr.slice(0, i);
return arr;
};
-
const throttle = (fn, wait) => {
+
+const throttle = (fn, wait) => {
let inThrottle, lastFn, lastTime;
return function() {
const context = this,
@@ -1151,17 +1443,20 @@ const spreadOver = fn => argsArr => fn(...argsArr);
}
};
};
-
const times = (n, fn, context = undefined) => {
+
+const times = (n, fn, context = undefined) => {
let i = 0;
while (fn.call(context, i) !== false && ++i < n) {}
};
-
const timeTaken = callback => {
+
+const timeTaken = callback => {
console.time('timeTaken');
const r = callback();
console.timeEnd('timeTaken');
return r;
};
-
const toCamelCase = str => {
+
+const toCamelCase = str => {
let s =
str &&
str
@@ -1170,23 +1465,29 @@ const spreadOver = fn => argsArr => fn(...argsArr);
.join('');
return s.slice(0, 1).toLowerCase() + s.slice(1);
};
-
const toCurrency = (n, curr, LanguageFormat = undefined) =>
+
+const toCurrency = (n, curr, LanguageFormat = undefined) =>
Intl.NumberFormat(LanguageFormat, { style: 'currency', currency: curr }).format(n);
-
const toDecimalMark = num => num.toLocaleString('en-US');
-
const toggleClass = (el, className) => el.classList.toggle(className);
-
const toHash = (object, key) =>
+
+const toDecimalMark = num => num.toLocaleString('en-US');
+
+const toggleClass = (el, className) => el.classList.toggle(className);
+
+const toHash = (object, key) =>
Array.prototype.reduce.call(
object,
(acc, data, index) => ((acc[!key ? index : data[key]] = data), acc),
{}
);
-
const toKebabCase = str =>
+
+const toKebabCase = str =>
str &&
str
.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
.map(x => x.toLowerCase())
.join('-');
-
const tomorrow = (long = false) => {
+
+const tomorrow = (long = false) => {
let t = new Date();
t.setDate(t.getDate() + 1);
const ret = `${t.getFullYear()}-${String(t.getMonth() + 1).padStart(2, '0')}-${String(
@@ -1194,7 +1495,8 @@ const spreadOver = fn => argsArr => fn(...argsArr);
).padStart(2, '0')}`;
return !long ? ret : `${ret}T00:00:00`;
};
-
const toOrdinalSuffix = num => {
+
+const toOrdinalSuffix = num => {
const int = parseInt(num),
digits = [int % 10, int % 100],
ordinals = ['st', 'nd', 'rd', 'th'],
@@ -1204,32 +1506,42 @@ const spreadOver = fn => argsArr => fn(...argsArr);
? int + ordinals[digits[0] - 1]
: int + ordinals[3];
};
-
const toSafeInteger = num =>
+
+const toSafeInteger = num =>
Math.round(Math.max(Math.min(num, Number.MAX_SAFE_INTEGER), Number.MIN_SAFE_INTEGER));
-
const toSnakeCase = str =>
+
+const toSnakeCase = str =>
str &&
str
.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
.map(x => x.toLowerCase())
.join('_');
-
const toTitleCase = str =>
+
+const toTitleCase = str =>
str
.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
.map(x => x.charAt(0).toUpperCase() + x.slice(1))
.join(' ');
-
const transform = (obj, fn, acc) => Object.keys(obj).reduce((a, k) => fn(a, obj[k], k, obj), acc);
-
const triggerEvent = (el, eventType, detail) =>
+
+const transform = (obj, fn, acc) => Object.keys(obj).reduce((a, k) => fn(a, obj[k], k, obj), acc);
+
+const triggerEvent = (el, eventType, detail) =>
el.dispatchEvent(new CustomEvent(eventType, { detail }));
-
const truncateString = (str, num) =>
+
+const truncateString = (str, num) =>
str.length > num ? str.slice(0, num > 3 ? num - 3 : num) + '...' : str;
-
const truthCheckCollection = (collection, pre) => collection.every(obj => obj[pre]);
-
const unary = fn => val => fn(val);
-
const uncurry = (fn, n = 1) => (...args) => {
+
+const truthCheckCollection = (collection, pre) => collection.every(obj => obj[pre]);
+
+const unary = fn => val => fn(val);
+
+const uncurry = (fn, n = 1) => (...args) => {
const next = acc => args => args.reduce((x, y) => x(y), acc);
if (n > args.length) throw new RangeError('Arguments too few!');
return next(fn)(args.slice(0, n));
};
-
const unescapeHTML = str =>
+
+const unescapeHTML = str =>
str.replace(
/&|<|>|'|"/g,
tag =>
@@ -1241,7 +1553,8 @@ const spreadOver = fn => argsArr => fn(...argsArr);
'"': '"'
}[tag] || tag)
);
-
const unflattenObject = obj =>
+
+const unflattenObject = obj =>
Object.keys(obj).reduce((acc, k) => {
if (k.indexOf('.') !== -1) {
const keys = k.split('.');
@@ -1257,42 +1570,53 @@ const spreadOver = fn => argsArr => fn(...argsArr);
} else acc[k] = obj[k];
return acc;
}, {});
-
const unfold = (fn, seed) => {
+
+const unfold = (fn, seed) => {
let result = [],
val = [null, seed];
while ((val = fn(val[1]))) result.push(val[0]);
return result;
};
-
const union = (a, b) => Array.from(new Set([...a, ...b]));
-
const unionBy = (a, b, fn) => {
+
+const union = (a, b) => Array.from(new Set([...a, ...b]));
+
+const unionBy = (a, b, fn) => {
const s = new Set(a.map(fn));
return Array.from(new Set([...a, ...b.filter(x => !s.has(fn(x)))]));
};
-
const unionWith = (a, b, comp) =>
+
+const unionWith = (a, b, comp) =>
Array.from(new Set([...a, ...b.filter(x => a.findIndex(y => comp(x, y)) === -1)]));
-
const uniqueElements = arr => [...new Set(arr)];
-
const uniqueElementsBy = (arr, fn) =>
+
+const uniqueElements = arr => [...new Set(arr)];
+
+const uniqueElementsBy = (arr, fn) =>
arr.reduce((acc, v) => {
if (!acc.some(x => fn(v, x))) acc.push(v);
return acc;
}, []);
-
const uniqueElementsByRight = (arr, fn) =>
+
+const uniqueElementsByRight = (arr, fn) =>
arr.reduceRight((acc, v) => {
if (!acc.some(x => fn(v, x))) acc.push(v);
return acc;
}, []);
-
const uniqueSymmetricDifference = (a, b) => [
+
+const uniqueSymmetricDifference = (a, b) => [
...new Set([...a.filter(v => !b.includes(v)), ...b.filter(v => !a.includes(v))])
];
-
const untildify = str => str.replace(/^~($|\/|\\)/, `${require('os').homedir()}$1`);
-
const unzip = arr =>
+
+const untildify = str => str.replace(/^~($|\/|\\)/, `${require('os').homedir()}$1`);
+
+const unzip = arr =>
arr.reduce(
(acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc),
Array.from({
length: Math.max(...arr.map(x => x.length))
}).map(x => [])
);
-
const unzipWith = (arr, fn) =>
+
+const unzipWith = (arr, fn) =>
arr
.reduce(
(acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc),
@@ -1301,7 +1625,8 @@ const spreadOver = fn => argsArr => fn(...argsArr);
}).map(x => [])
)
.map(val => fn(...val));
-
const URLJoin = (...args) =>
+
+const URLJoin = (...args) =>
args
.join('/')
.replace(/[\/]+/g, '/')
@@ -1310,46 +1635,60 @@ const spreadOver = fn => argsArr => fn(...argsArr);
.replace(/\/(\?|&|#[^!])/g, '$1')
.replace(/\?/g, '&')
.replace('&', '?');
-
const UUIDGeneratorBrowser = () =>
+
+const UUIDGeneratorBrowser = () =>
([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
(c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16)
);
-
+
+
const UUIDGeneratorNode = () =>
([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
(c ^ (crypto.randomBytes(1)[0] & (15 >> (c / 4)))).toString(16)
);
-
const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n;
-
const when = (pred, whenTrue) => x => (pred(x) ? whenTrue(x) : x);
-
const without = (arr, ...args) => arr.filter(v => !args.includes(v));
-
const words = (str, pattern = /[^a-zA-Z-]+/) => str.split(pattern).filter(Boolean);
-
const xProd = (a, b) => a.reduce((acc, x) => acc.concat(b.map(y => [x, y])), []);
-
const yesNo = (val, def = false) =>
+
+const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n;
+
+const when = (pred, whenTrue) => x => (pred(x) ? whenTrue(x) : x);
+
+const without = (arr, ...args) => arr.filter(v => !args.includes(v));
+
+const words = (str, pattern = /[^a-zA-Z-]+/) => str.split(pattern).filter(Boolean);
+
+const xProd = (a, b) => a.reduce((acc, x) => acc.concat(b.map(y => [x, y])), []);
+
+const yesNo = (val, def = false) =>
/^(y|yes)$/i.test(val) ? true : /^(n|no)$/i.test(val) ? false : def;
-
const zip = (...arrays) => {
+
+const zip = (...arrays) => {
const maxLength = Math.max(...arrays.map(x => x.length));
return Array.from({ length: maxLength }).map((_, i) => {
return Array.from({ length: arrays.length }, (_, k) => arrays[k][i]);
});
};
-
const zipObject = (props, values) =>
+
+const zipObject = (props, values) =>
props.reduce((obj, prop, index) => ((obj[prop] = values[index]), obj), {});
-
const zipWith = (...array) => {
+
+const zipWith = (...array) => {
const fn = typeof array[array.length - 1] === 'function' ? array.pop() : undefined;
return Array.from(
{ length: Math.max(...array.map(a => a.length)) },
(_, i) => (fn ? fn(...array.map(a => a[i])) : array.map(a => a[i]))
);
};
-
const binarySearch = (arr, val, start = 0, end = arr.length - 1) => {
+
+const binarySearch = (arr, val, start = 0, end = arr.length - 1) => {
if (start > end) return -1;
const mid = Math.floor((start + end) / 2);
if (arr[mid] > val) return binarySearch(arr, val, start, mid - 1);
if (arr[mid] < val) return binarySearch(arr, val, mid + 1, end);
return mid;
};
-
const celsiusToFahrenheit = degrees => 1.8 * degrees + 32;
-
const cleanObj = (obj, keysToKeep = [], childIndicator) => {
+
+const celsiusToFahrenheit = degrees => 1.8 * degrees + 32;
+
+const cleanObj = (obj, keysToKeep = [], childIndicator) => {
Object.keys(obj).forEach(key => {
if (key === childIndicator) {
cleanObj(obj[key], keysToKeep, childIndicator);
@@ -1359,9 +1698,12 @@ const UUIDGeneratorNode = () =>
});
return obj;
};
-
const collatz = n => (n % 2 === 0 ? n / 2 : 3 * n + 1);
-
const countVowels = str => (str.match(/[aeiou]/gi) || []).length;
-
const factors = (num, primes = false) => {
+
+const collatz = n => (n % 2 === 0 ? n / 2 : 3 * n + 1);
+
+const countVowels = str => (str.match(/[aeiou]/gi) || []).length;
+
+const factors = (num, primes = false) => {
const isPrime = num => {
const boundary = Math.floor(Math.sqrt(num));
for (var i = 2; i <= boundary; i++) if (num % i === 0) return false;
@@ -1380,21 +1722,26 @@ const UUIDGeneratorNode = () =>
}, []);
return primes ? array.filter(isPrime) : array;
};
-
const fahrenheitToCelsius = degrees => (degrees - 32) * 5/9;
-
const fibonacciCountUntilNum = num =>
+
+const fahrenheitToCelsius = degrees => (degrees - 32) * 5/9;
+
+const fibonacciCountUntilNum = num =>
Math.ceil(Math.log(num * Math.sqrt(5) + 1 / 2) / Math.log((Math.sqrt(5) + 1) / 2));
-
const fibonacciUntilNum = num => {
+
+const fibonacciUntilNum = num => {
let n = Math.ceil(Math.log(num * Math.sqrt(5) + 1 / 2) / Math.log((Math.sqrt(5) + 1) / 2));
return Array.from({ length: n }).reduce(
(acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i),
[]
);
};
-
const heronArea = (side_a, side_b, side_c) => {
+
+const heronArea = (side_a, side_b, side_c) => {
const p = (side_a + side_b + side_c) / 2
return Math.sqrt(p * (p-side_a) * (p-side_b) * (p-side_c))
};
-
const howManyTimes = (num, divisor) => {
+
+const howManyTimes = (num, divisor) => {
if (divisor === 1 || divisor === -1) return Infinity;
if (divisor === 0) return 0;
let i = 0;
@@ -1404,14 +1751,16 @@ const UUIDGeneratorNode = () =>
}
return i;
};
-
const httpDelete = (url, callback, err = console.error) => {
+
+const httpDelete = (url, callback, err = console.error) => {
const request = new XMLHttpRequest();
request.open('DELETE', url, true);
request.onload = () => callback(request);
request.onerror = () => err(request);
request.send();
};
-
const httpPut = (url, data, callback, err = console.error) => {
+
+const httpPut = (url, data, callback, err = console.error) => {
const request = new XMLHttpRequest();
request.open("PUT", url, true);
request.setRequestHeader('Content-type','application/json; charset=utf-8');
@@ -1419,11 +1768,13 @@ const UUIDGeneratorNode = () =>
request.onerror = () => err(request);
request.send(data);
};
-
const isArmstrongNumber = digits =>
+
+const isArmstrongNumber = digits =>
(arr => arr.reduce((a, d) => a + parseInt(d) ** arr.length, 0) == digits)(
(digits + '').split('')
);
-
const isSimilar = (pattern, str) =>
+
+const isSimilar = (pattern, str) =>
[...str].reduce(
(matchIndex, char) =>
char.toLowerCase() === (pattern[matchIndex] || '').toLowerCase()
@@ -1431,12 +1782,15 @@ const UUIDGeneratorNode = () =>
: matchIndex,
0
) === pattern.length;
-
const JSONToDate = arr => {
+
+const JSONToDate = arr => {
const dt = new Date(parseInt(arr.toString().substr(6)));
return `${dt.getDate()}/${dt.getMonth() + 1}/${dt.getFullYear()}`;
};
-
const kmphToMph = (kmph) => 0.621371192 * kmph;
-
const levenshteinDistance = (string1, string2) => {
+
+const kmphToMph = (kmph) => 0.621371192 * kmph;
+
+const levenshteinDistance = (string1, string2) => {
if (string1.length === 0) return string2.length;
if (string2.length === 0) return string1.length;
let matrix = Array(string2.length + 1)
@@ -1460,9 +1814,12 @@ const UUIDGeneratorNode = () =>
}
return matrix[string2.length][string1.length];
};
-
const mphToKmph = (mph) => 1.6093440006146922 * mph;
-
const pipeLog = data => console.log(data) || data;
-
const quickSort = ([n, ...nums], desc) =>
+
+const mphToKmph = (mph) => 1.6093440006146922 * mph;
+
+const pipeLog = data => console.log(data) || data;
+
+const quickSort = ([n, ...nums], desc) =>
isNaN(n)
? []
: [
@@ -1470,8 +1827,10 @@ const UUIDGeneratorNode = () =>
n,
...quickSort(nums.filter(v => (!desc ? v > n : v <= n)), desc)
];
-
const removeVowels = (str, repl = '') => str.replace(/[aeiou]/gi, repl);
-
const solveRPN = rpn => {
+
+const removeVowels = (str, repl = '') => str.replace(/[aeiou]/gi, repl);
+
+const solveRPN = rpn => {
const OPERATORS = {
'*': (a, b) => a * b,
'+': (a, b) => a + b,
@@ -1499,12 +1858,14 @@ const UUIDGeneratorNode = () =>
if (stack.length === 1) return stack.pop();
else throw `${rpn} is not a proper RPN. Please check it and try again`;
};
-
const speechSynthesis = message => {
+
+const speechSynthesis = message => {
const msg = new SpeechSynthesisUtterance(message);
msg.voice = window.speechSynthesis.getVoices()[0];
window.speechSynthesis.speak(msg);
};
-
const squareSum = (...args) => args.reduce((squareSum, number) => squareSum + Math.pow(number, 2), 0);
-
-
+
+const squareSum = (...args) => args.reduce((squareSum, number) => squareSum + Math.pow(number, 2), 0);
+
+
module.exports = {all,allEqual,any,approximatelyEqual,arrayToCSV,arrayToHtmlList,ary,atob,attempt,average,averageBy,bifurcate,bifurcateBy,bind,bindAll,bindKey,binomialCoefficient,bottomVisible,btoa,byteSize,call,capitalize,capitalizeEveryWord,castArray,chainAsync,chunk,clampNumber,cloneRegExp,coalesce,coalesceFactory,collectInto,colorize,compact,compactWhitespace,compose,composeRight,converge,copyToClipboard,countBy,counter,countOccurrences,createElement,createEventHub,CSVToArray,CSVToJSON,currentURL,curry,dayOfYear,debounce,decapitalize,deepClone,deepFlatten,deepFreeze,deepMapKeys,defaults,defer,degreesToRads,delay,detectDeviceType,difference,differenceBy,differenceWith,dig,digitize,distance,drop,dropRight,dropRightWhile,dropWhile,elementContains,elementIsVisibleInViewport,elo,equals,escapeHTML,escapeRegExp,everyNth,extendHex,factorial,fibonacci,filterFalsy,filterNonUnique,filterNonUniqueBy,findKey,findLast,findLastIndex,findLastKey,flatten,flattenObject,flip,forEachRight,formatDuration,forOwn,forOwnRight,fromCamelCase,functionName,functions,gcd,geometricProgression,get,getColonTimeFromDate,getDaysDiffBetweenDates,getImages,getMeridiemSuffixOfInteger,getScrollPosition,getStyle,getType,getURLParameters,groupBy,hammingDistance,hasClass,hasFlags,hashBrowser,hashNode,head,hexToRGB,hide,httpGet,httpPost,httpsRedirect,hz,indentString,indexOfAll,initial,initialize2DArray,initializeArrayWithRange,initializeArrayWithRangeRight,initializeArrayWithValues,initializeNDArray,inRange,insertAfter,insertBefore,intersection,intersectionBy,intersectionWith,invertKeyValues,is,isAbsoluteURL,isAfterDate,isAnagram,isArrayLike,isBeforeDate,isBoolean,isBrowser,isBrowserTabFocused,isDivisible,isDuplexStream,isEmpty,isEven,isFunction,isLowerCase,isNegativeZero,isNil,isNull,isNumber,isObject,isObjectLike,isPlainObject,isPrime,isPrimitive,isPromiseLike,isReadableStream,isSameDate,isSorted,isStream,isString,isSymbol,isTravisCI,isUndefined,isUpperCase,isValidJSON,isWritableStream,join,JSONtoCSV,JSONToFile,last,lcm,longestItem,lowercaseKeys,luhnCheck,mapKeys,mapObject,mapString,mapValues,mask,matches,matchesWith,maxBy,maxDate,maxN,median,memoize,merge,midpoint,minBy,minDate,minN,mostPerformant,negate,nest,nodeListToArray,none,nthArg,nthElement,objectFromPairs,objectToPairs,observeMutations,off,offset,omit,omitBy,on,once,onUserInputChange,orderBy,over,overArgs,pad,palindrome,parseCookie,partial,partialRight,partition,percentile,permutations,pick,pickBy,pipeAsyncFunctions,pipeFunctions,pluralize,powerset,prefix,prettyBytes,primes,promisify,pull,pullAtIndex,pullAtValue,pullBy,radsToDegrees,randomHexColorCode,randomIntArrayInRange,randomIntegerInRange,randomNumberInRange,readFileLines,rearg,recordAnimationFrames,redirect,reducedFilter,reduceSuccessive,reduceWhich,reject,remove,removeNonASCII,renameKeys,reverseString,RGBToHex,round,runAsync,runPromisesInSeries,sample,sampleSize,scrollToTop,sdbm,serializeCookie,setStyle,shallowClone,shank,show,shuffle,similarity,size,sleep,smoothScroll,sortCharactersInString,sortedIndex,sortedIndexBy,sortedLastIndex,sortedLastIndexBy,splitLines,spreadOver,stableSort,standardDeviation,stringPermutations,stripHTMLTags,sum,sumBy,sumPower,symmetricDifference,symmetricDifferenceBy,symmetricDifferenceWith,tail,take,takeRight,takeRightWhile,takeWhile,throttle,times,timeTaken,toCamelCase,toCurrency,toDecimalMark,toggleClass,toHash,toKebabCase,tomorrow,toOrdinalSuffix,toSafeInteger,toSnakeCase,toTitleCase,transform,triggerEvent,truncateString,truthCheckCollection,unary,uncurry,unescapeHTML,unflattenObject,unfold,union,unionBy,unionWith,uniqueElements,uniqueElementsBy,uniqueElementsByRight,uniqueSymmetricDifference,untildify,unzip,unzipWith,URLJoin,UUIDGeneratorBrowser,UUIDGeneratorNode,validateNumber,when,without,words,xProd,yesNo,zip,zipObject,zipWith,binarySearch,celsiusToFahrenheit,cleanObj,collatz,countVowels,factors,fahrenheitToCelsius,fibonacciCountUntilNum,fibonacciUntilNum,heronArea,howManyTimes,httpDelete,httpPut,isArmstrongNumber,isSimilar,JSONToDate,kmphToMph,levenshteinDistance,mphToKmph,pipeLog,quickSort,removeVowels,solveRPN,speechSynthesis,squareSum}
\ No newline at end of file