UNPKG

54.8 kBJavaScriptView Raw
1const fs = typeof require !== "undefined" && require('fs');
2const crypto = typeof require !== "undefined" && require('crypto');
3
4const CSVToArray = (data, delimiter = ',', omitFirstRow = false) =>
5 data
6 .slice(omitFirstRow ? data.indexOf('\n') + 1 : 0)
7 .split('\n')
8 .map(v => v.split(delimiter));
9const CSVToJSON = (data, delimiter = ',') => {
10 const titles = data.slice(0, data.indexOf('\n')).split(delimiter);
11 return data
12 .slice(data.indexOf('\n') + 1)
13 .split('\n')
14 .map(v => {
15 const values = v.split(delimiter);
16 return titles.reduce((obj, title, index) => ((obj[title] = values[index]), obj), {});
17 });
18};
19const JSONToFile = (obj, filename) =>
20 fs.writeFile(`${filename}.json`, JSON.stringify(obj, null, 2));
21const JSONtoCSV = (arr, columns, delimiter = ',') =>
22 [
23 columns.join(delimiter),
24 ...arr.map(obj =>
25 columns.reduce(
26 (acc, key) => `${acc}${!acc.length ? '' : delimiter}"${!obj[key] ? '' : obj[key]}"`,
27 ''
28 )
29 )
30 ].join('\n');
31const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0');
32const URLJoin = (...args) =>
33 args
34 .join('/')
35 .replace(/[\/]+/g, '/')
36 .replace(/^(.+):\//, '$1://')
37 .replace(/^file:/, 'file:/')
38 .replace(/\/(\?|&|#[^!])/g, '$1')
39 .replace(/\?/g, '&')
40 .replace('&', '?');
41const UUIDGeneratorBrowser = () =>
42 ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
43 (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16)
44 );
45const UUIDGeneratorNode = () =>
46 ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
47 (c ^ (crypto.randomBytes(1)[0] & (15 >> (c / 4)))).toString(16)
48 );
49const all = (arr, fn = Boolean) => arr.every(fn);
50const allEqual = arr => arr.every(val => val === arr[0]);
51const any = (arr, fn = Boolean) => arr.some(fn);
52const approximatelyEqual = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) < epsilon;
53const arrayToCSV = (arr, delimiter = ',') =>
54 arr.map(v => v.map(x => `"${x}"`).join(delimiter)).join('\n');
55const arrayToHtmlList = (arr, listID) =>
56 (el => (
57 (el = document.querySelector('#' + listID)),
58 (el.innerHTML += arr.map(item => `<li>${item}</li>`).join(''))
59 ))();
60const ary = (fn, n) => (...args) => fn(...args.slice(0, n));
61const atob = str => Buffer.from(str, 'base64').toString('binary');
62const attempt = (fn, ...args) => {
63 try {
64 return fn(...args);
65 } catch (e) {
66 return e instanceof Error ? e : new Error(e);
67 }
68};
69const average = (...nums) => nums.reduce((acc, val) => acc + val, 0) / nums.length;
70const averageBy = (arr, fn) =>
71 arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0) /
72 arr.length;
73const bifurcate = (arr, filter) =>
74 arr.reduce((acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc), [[], []]);
75const bifurcateBy = (arr, fn) =>
76 arr.reduce((acc, val, i) => (acc[fn(val, i) ? 0 : 1].push(val), acc), [[], []]);
77const bind = (fn, context, ...boundArgs) => (...args) => fn.apply(context, [...boundArgs, ...args]);
78const bindAll = (obj, ...fns) =>
79 fns.forEach(
80 fn => (
81 (f = obj[fn]),
82 (obj[fn] = function() {
83 return f.apply(obj);
84 })
85 )
86 );
87const bindKey = (context, fn, ...boundArgs) => (...args) =>
88 context[fn].apply(context, [...boundArgs, ...args]);
89const binomialCoefficient = (n, k) => {
90 if (Number.isNaN(n) || Number.isNaN(k)) return NaN;
91 if (k < 0 || k > n) return 0;
92 if (k === 0 || k === n) return 1;
93 if (k === 1 || k === n - 1) return n;
94 if (n - k < k) k = n - k;
95 let res = n;
96 for (let j = 2; j <= k; j++) res *= (n - j + 1) / j;
97 return Math.round(res);
98};
99const bottomVisible = () =>
100 document.documentElement.clientHeight + window.scrollY >=
101 (document.documentElement.scrollHeight || document.documentElement.clientHeight);
102const btoa = str => Buffer.from(str, 'binary').toString('base64');
103const byteSize = str => new Blob([str]).size;
104const call = (key, ...args) => context => context[key](...args);
105const capitalize = ([first, ...rest], lowerRest = false) =>
106 first.toUpperCase() + (lowerRest ? rest.join('').toLowerCase() : rest.join(''));
107const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase());
108const castArray = val => (Array.isArray(val) ? val : [val]);
109const chainAsync = fns => {
110 let curr = 0;
111 const next = () => fns[curr++](next);
112 next();
113};
114const chunk = (arr, size) =>
115 Array.from({ length: Math.ceil(arr.length / size) }, (v, i) =>
116 arr.slice(i * size, i * size + size)
117 );
118const clampNumber = (num, a, b) => Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b));
119const cloneRegExp = regExp => new RegExp(regExp.source, regExp.flags);
120const coalesce = (...args) => args.find(_ => ![undefined, null].includes(_));
121const coalesceFactory = valid => (...args) => args.find(valid);
122const collectInto = fn => (...args) => fn(args);
123const colorize = (...args) => ({
124 black: `\x1b[30m${args.join(' ')}`,
125 red: `\x1b[31m${args.join(' ')}`,
126 green: `\x1b[32m${args.join(' ')}`,
127 yellow: `\x1b[33m${args.join(' ')}`,
128 blue: `\x1b[34m${args.join(' ')}`,
129 magenta: `\x1b[35m${args.join(' ')}`,
130 cyan: `\x1b[36m${args.join(' ')}`,
131 white: `\x1b[37m${args.join(' ')}`,
132 bgBlack: `\x1b[40m${args.join(' ')}\x1b[0m`,
133 bgRed: `\x1b[41m${args.join(' ')}\x1b[0m`,
134 bgGreen: `\x1b[42m${args.join(' ')}\x1b[0m`,
135 bgYellow: `\x1b[43m${args.join(' ')}\x1b[0m`,
136 bgBlue: `\x1b[44m${args.join(' ')}\x1b[0m`,
137 bgMagenta: `\x1b[45m${args.join(' ')}\x1b[0m`,
138 bgCyan: `\x1b[46m${args.join(' ')}\x1b[0m`,
139 bgWhite: `\x1b[47m${args.join(' ')}\x1b[0m`
140});
141const compact = arr => arr.filter(Boolean);
142const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)));
143const composeRight = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args)));
144const converge = (converger, fns) => (...args) => converger(...fns.map(fn => fn.apply(null, args)));
145const copyToClipboard = str => {
146 const el = document.createElement('textarea');
147 el.value = str;
148 el.setAttribute('readonly', '');
149 el.style.position = 'absolute';
150 el.style.left = '-9999px';
151 document.body.appendChild(el);
152 const selected =
153 document.getSelection().rangeCount > 0 ? document.getSelection().getRangeAt(0) : false;
154 el.select();
155 document.execCommand('copy');
156 document.body.removeChild(el);
157 if (selected) {
158 document.getSelection().removeAllRanges();
159 document.getSelection().addRange(selected);
160 }
161};
162const countBy = (arr, fn) =>
163 arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => {
164 acc[val] = (acc[val] || 0) + 1;
165 return acc;
166 }, {});
167const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0);
168const counter = (selector, start, end, step = 1, duration = 2000) => {
169 let current = start,
170 _step = (end - start) * step < 0 ? -step : step,
171 timer = setInterval(() => {
172 current += _step;
173 document.querySelector(selector).innerHTML = current;
174 if (current >= end) document.querySelector(selector).innerHTML = end;
175 if (current >= end) clearInterval(timer);
176 }, Math.abs(Math.floor(duration / (end - start))));
177 return timer;
178};
179const createElement = str => {
180 const el = document.createElement('div');
181 el.innerHTML = str;
182 return el.firstElementChild;
183};
184const createEventHub = () => ({
185 hub: Object.create(null),
186 emit(event, data) {
187 (this.hub[event] || []).forEach(handler => handler(data));
188 },
189 on(event, handler) {
190 if (!this.hub[event]) this.hub[event] = [];
191 this.hub[event].push(handler);
192 },
193 off(event, handler) {
194 const i = (this.hub[event] || []).findIndex(h => h === handler);
195 if (i > -1) this.hub[event].splice(i, 1);
196 }
197});
198const currentURL = () => window.location.href;
199const curry = (fn, arity = fn.length, ...args) =>
200 arity <= args.length ? fn(...args) : curry.bind(null, fn, arity, ...args);
201const dayOfYear = date =>
202 Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24);
203const debounce = (fn, ms = 0) => {
204 let timeoutId;
205 return function(...args) {
206 clearTimeout(timeoutId);
207 timeoutId = setTimeout(() => fn.apply(this, args), ms);
208 };
209};
210const decapitalize = ([first, ...rest], upperRest = false) =>
211 first.toLowerCase() + (upperRest ? rest.join('').toUpperCase() : rest.join(''));
212const deepClone = obj => {
213 let clone = Object.assign({}, obj);
214 Object.keys(clone).forEach(
215 key => (clone[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key])
216 );
217 return Array.isArray(obj) ? (clone.length = obj.length) && Array.from(clone) : clone;
218};
219const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v)));
220const deepFreeze = obj =>
221 Object.keys(obj).forEach(
222 prop =>
223 !(obj[prop] instanceof Object) || Object.isFrozen(obj[prop]) ? null : deepFreeze(obj[prop])
224 ) || Object.freeze(obj);
225const defaults = (obj, ...defs) => Object.assign({}, obj, ...defs.reverse(), obj);
226const defer = (fn, ...args) => setTimeout(fn, 1, ...args);
227const degreesToRads = deg => (deg * Math.PI) / 180.0;
228const delay = (fn, wait, ...args) => setTimeout(fn, wait, ...args);
229const detectDeviceType = () =>
230 /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
231 ? 'Mobile'
232 : 'Desktop';
233const difference = (a, b) => {
234 const s = new Set(b);
235 return a.filter(x => !s.has(x));
236};
237const differenceBy = (a, b, fn) => {
238 const s = new Set(b.map(fn));
239 return a.filter(x => !s.has(fn(x)));
240};
241const differenceWith = (arr, val, comp) => arr.filter(a => val.findIndex(b => comp(a, b)) === -1);
242const dig = (obj, target) =>
243 target in obj
244 ? obj[target]
245 : Object.values(obj).reduce((acc, val) => {
246 if (acc !== undefined) return acc;
247 if (typeof val === 'object') return dig(val, target);
248 }, undefined);
249const digitize = n => [...`${n}`].map(i => parseInt(i));
250const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0);
251const drop = (arr, n = 1) => arr.slice(n);
252const dropRight = (arr, n = 1) => arr.slice(0, -n);
253const dropRightWhile = (arr, func) => {
254 while (arr.length > 0 && !func(arr[arr.length - 1])) arr = arr.slice(0, -1);
255 return arr;
256};
257const dropWhile = (arr, func) => {
258 while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1);
259 return arr;
260};
261const elementContains = (parent, child) => parent !== child && parent.contains(child);
262const elementIsVisibleInViewport = (el, partiallyVisible = false) => {
263 const { top, left, bottom, right } = el.getBoundingClientRect();
264 const { innerHeight, innerWidth } = window;
265 return partiallyVisible
266 ? ((top > 0 && top < innerHeight) || (bottom > 0 && bottom < innerHeight)) &&
267 ((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth))
268 : top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth;
269};
270const elo = ([...ratings], kFactor = 32, selfRating) => {
271 const [a, b] = ratings;
272 const expectedScore = (self, opponent) => 1 / (1 + 10 ** ((opponent - self) / 400));
273 const newRating = (rating, i) =>
274 (selfRating || rating) + kFactor * (i - expectedScore(i ? a : b, i ? b : a));
275 if (ratings.length === 2) return [newRating(a, 1), newRating(b, 0)];
276
277 for (let i = 0, len = ratings.length; i < len; i++) {
278 let j = i;
279 while (j < len - 1) {
280 j++;
281 [ratings[i], ratings[j]] = elo([ratings[i], ratings[j]], kFactor);
282 }
283 }
284 return ratings;
285};
286const equals = (a, b) => {
287 if (a === b) return true;
288 if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
289 if (!a || !b || (typeof a !== 'object' && typeof b !== 'object')) return a === b;
290 if (a === null || a === undefined || b === null || b === undefined) return false;
291 if (a.prototype !== b.prototype) return false;
292 let keys = Object.keys(a);
293 if (keys.length !== Object.keys(b).length) return false;
294 return keys.every(k => equals(a[k], b[k]));
295};
296const escapeHTML = str =>
297 str.replace(
298 /[&<>'"]/g,
299 tag =>
300 ({
301 '&': '&amp;',
302 '<': '&lt;',
303 '>': '&gt;',
304 "'": '&#39;',
305 '"': '&quot;'
306 }[tag] || tag)
307 );
308const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
309const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === nth - 1);
310const extendHex = shortHex =>
311 '#' +
312 shortHex
313 .slice(shortHex.startsWith('#') ? 1 : 0)
314 .split('')
315 .map(x => x + x)
316 .join('');
317const factorial = n =>
318 n < 0
319 ? (() => {
320 throw new TypeError('Negative numbers are not allowed!');
321 })()
322 : n <= 1
323 ? 1
324 : n * factorial(n - 1);
325const fibonacci = n =>
326 Array.from({ length: n }).reduce(
327 (acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i),
328 []
329 );
330const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i));
331const filterNonUniqueBy = (arr, fn) =>
332 arr.filter((v, i) => arr.every((x, j) => (i === j) === fn(v, x, i, j)));
333const findKey = (obj, fn) => Object.keys(obj).find(key => fn(obj[key], key, obj));
334const findLast = (arr, fn) => arr.filter(fn).pop();
335const findLastIndex = (arr, fn) =>
336 arr
337 .map((val, i) => [i, val])
338 .filter(([i, val]) => fn(val, i, arr))
339 .pop()[0];
340const findLastKey = (obj, fn) =>
341 Object.keys(obj)
342 .reverse()
343 .find(key => fn(obj[key], key, obj));
344const flatten = (arr, depth = 1) =>
345 arr.reduce((a, v) => a.concat(depth > 1 && Array.isArray(v) ? flatten(v, depth - 1) : v), []);
346const flattenObject = (obj, prefix = '') =>
347 Object.keys(obj).reduce((acc, k) => {
348 const pre = prefix.length ? prefix + '.' : '';
349 if (typeof obj[k] === 'object') Object.assign(acc, flattenObject(obj[k], pre + k));
350 else acc[pre + k] = obj[k];
351 return acc;
352 }, {});
353const flip = fn => (first, ...rest) => fn(...rest, first);
354const forEachRight = (arr, callback) =>
355 arr
356 .slice(0)
357 .reverse()
358 .forEach(callback);
359const forOwn = (obj, fn) => Object.keys(obj).forEach(key => fn(obj[key], key, obj));
360const forOwnRight = (obj, fn) =>
361 Object.keys(obj)
362 .reverse()
363 .forEach(key => fn(obj[key], key, obj));
364const formatDuration = ms => {
365 if (ms < 0) ms = -ms;
366 const time = {
367 day: Math.floor(ms / 86400000),
368 hour: Math.floor(ms / 3600000) % 24,
369 minute: Math.floor(ms / 60000) % 60,
370 second: Math.floor(ms / 1000) % 60,
371 millisecond: Math.floor(ms) % 1000
372 };
373 return Object.entries(time)
374 .filter(val => val[1] !== 0)
375 .map(([key, val]) => `${val} ${key}${val !== 1 ? 's' : ''}`)
376 .join(', ');
377};
378const fromCamelCase = (str, separator = '_') =>
379 str
380 .replace(/([a-z\d])([A-Z])/g, '$1' + separator + '$2')
381 .replace(/([A-Z]+)([A-Z][a-z\d]+)/g, '$1' + separator + '$2')
382 .toLowerCase();
383const functionName = fn => (console.debug(fn.name), fn);
384const functions = (obj, inherited = false) =>
385 (inherited
386 ? [...Object.keys(obj), ...Object.keys(Object.getPrototypeOf(obj))]
387 : Object.keys(obj)
388 ).filter(key => typeof obj[key] === 'function');
389const gcd = (...arr) => {
390 const _gcd = (x, y) => (!y ? x : gcd(y, x % y));
391 return [...arr].reduce((a, b) => _gcd(a, b));
392};
393const geometricProgression = (end, start = 1, step = 2) =>
394 Array.from({ length: Math.floor(Math.log(end / start) / Math.log(step)) + 1 }).map(
395 (v, i) => start * step ** i
396 );
397const get = (from, ...selectors) =>
398 [...selectors].map(s =>
399 s
400 .replace(/\[([^\[\]]*)\]/g, '.$1.')
401 .split('.')
402 .filter(t => t !== '')
403 .reduce((prev, cur) => prev && prev[cur], from)
404 );
405const getColonTimeFromDate = date => date.toTimeString().slice(0, 8);
406const getDaysDiffBetweenDates = (dateInitial, dateFinal) =>
407 (dateFinal - dateInitial) / (1000 * 3600 * 24);
408const getImages = (el, includeDuplicates = false) => {
409 const images = [...el.getElementsByTagName('img')].map(img => img.getAttribute('src'));
410 return includeDuplicates ? images : [...new Set(images)];
411};
412const getMeridiemSuffixOfInteger = num =>
413 num === 0 || num === 24
414 ? 12 + 'am'
415 : num === 12
416 ? 12 + 'pm'
417 : num < 12
418 ? (num % 12) + 'am'
419 : (num % 12) + 'pm';
420const getScrollPosition = (el = window) => ({
421 x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft,
422 y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop
423});
424const getStyle = (el, ruleName) => getComputedStyle(el)[ruleName];
425const getType = v =>
426 v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name.toLowerCase();
427const getURLParameters = url =>
428 (url.match(/([^?=&]+)(=([^&]*))/g) || []).reduce(
429 (a, v) => ((a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1)), a),
430 {}
431 );
432const groupBy = (arr, fn) =>
433 arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val, i) => {
434 acc[val] = (acc[val] || []).concat(arr[i]);
435 return acc;
436 }, {});
437const hammingDistance = (num1, num2) => ((num1 ^ num2).toString(2).match(/1/g) || '').length;
438const hasClass = (el, className) => el.classList.contains(className);
439const hasFlags = (...flags) =>
440 flags.every(flag => process.argv.includes(/^-{1,2}/.test(flag) ? flag : '--' + flag));
441const hashBrowser = val =>
442 crypto.subtle.digest('SHA-256', new TextEncoder('utf-8').encode(val)).then(h => {
443 let hexes = [],
444 view = new DataView(h);
445 for (let i = 0; i < view.byteLength; i += 4)
446 hexes.push(('00000000' + view.getUint32(i).toString(16)).slice(-8));
447 return hexes.join('');
448 });
449const hashNode = val =>
450 new Promise(resolve =>
451 setTimeout(
452 () =>
453 resolve(
454 crypto
455 .createHash('sha256')
456 .update(val)
457 .digest('hex')
458 ),
459 0
460 )
461 );
462const head = arr => arr[0];
463const hexToRGB = hex => {
464 let alpha = false,
465 h = hex.slice(hex.startsWith('#') ? 1 : 0);
466 if (h.length === 3) h = [...h].map(x => x + x).join('');
467 else if (h.length === 8) alpha = true;
468 h = parseInt(h, 16);
469 return (
470 'rgb' +
471 (alpha ? 'a' : '') +
472 '(' +
473 (h >>> (alpha ? 24 : 16)) +
474 ', ' +
475 ((h & (alpha ? 0x00ff0000 : 0x00ff00)) >>> (alpha ? 16 : 8)) +
476 ', ' +
477 ((h & (alpha ? 0x0000ff00 : 0x0000ff)) >>> (alpha ? 8 : 0)) +
478 (alpha ? `, ${h & 0x000000ff}` : '') +
479 ')'
480 );
481};
482const hide = (...el) => [...el].forEach(e => (e.style.display = 'none'));
483const httpGet = (url, callback, err = console.error) => {
484 const request = new XMLHttpRequest();
485 request.open('GET', url, true);
486 request.onload = () => callback(request.responseText);
487 request.onerror = () => err(request);
488 request.send();
489};
490const httpPost = (url, data, callback, err = console.error) => {
491 const request = new XMLHttpRequest();
492 request.open('POST', url, true);
493 request.setRequestHeader('Content-type', 'application/json; charset=utf-8');
494 request.onload = () => callback(request.responseText);
495 request.onerror = () => err(request);
496 request.send(data);
497};
498const httpsRedirect = () => {
499 if (location.protocol !== 'https:') location.replace('https://' + location.href.split('//')[1]);
500};
501const hz = (fn, iterations = 100) => {
502 const before = performance.now();
503 for (let i = 0; i < iterations; i++) fn();
504 return (1000 * iterations) / (performance.now() - before);
505};
506const inRange = (n, start, end = null) => {
507 if (end && start > end) [end, start] = [start, end];
508 return end == null ? n >= 0 && n < start : n >= start && n < end;
509};
510const indentString = (str, count, indent = ' ') => str.replace(/^/gm, indent.repeat(count));
511const indexOfAll = (arr, val) => arr.reduce((acc, el, i) => (el === val ? [...acc, i] : acc), []);
512const initial = arr => arr.slice(0, -1);
513const initialize2DArray = (w, h, val = null) =>
514 Array.from({ length: h }).map(() => Array.from({ length: w }).fill(val));
515const initializeArrayWithRange = (end, start = 0, step = 1) =>
516 Array.from({ length: Math.ceil((end - start + 1) / step) }, (v, i) => i * step + start);
517const initializeArrayWithRangeRight = (end, start = 0, step = 1) =>
518 Array.from({ length: Math.ceil((end + 1 - start) / step) }).map(
519 (v, i, arr) => (arr.length - i - 1) * step + start
520 );
521const initializeArrayWithValues = (n, val = 0) => Array(n).fill(val);
522const initializeNDArray = (val, ...args) =>
523 args.length === 0
524 ? val
525 : Array.from({ length: args[0] }).map(() => initializeNDArray(val, ...args.slice(1)));
526const insertAfter = (el, htmlString) => el.insertAdjacentHTML('afterend', htmlString);
527const insertBefore = (el, htmlString) => el.insertAdjacentHTML('beforebegin', htmlString);
528const intersection = (a, b) => {
529 const s = new Set(b);
530 return a.filter(x => s.has(x));
531};
532const intersectionBy = (a, b, fn) => {
533 const s = new Set(b.map(fn));
534 return a.filter(x => s.has(fn(x)));
535};
536const intersectionWith = (a, b, comp) => a.filter(x => b.findIndex(y => comp(x, y)) !== -1);
537const invertKeyValues = (obj, fn) =>
538 Object.keys(obj).reduce((acc, key) => {
539 const val = fn ? fn(obj[key]) : obj[key];
540 acc[val] = acc[val] || [];
541 acc[val].push(key);
542 return acc;
543 }, {});
544const is = (type, val) => ![, null].includes(val) && val.constructor === type;
545const isAbsoluteURL = str => /^[a-z][a-z0-9+.-]*:/.test(str);
546const isAfterDate = (dateA, dateB) => dateA > dateB;
547const isAnagram = (str1, str2) => {
548 const normalize = str =>
549 str
550 .toLowerCase()
551 .replace(/[^a-z0-9]/gi, '')
552 .split('')
553 .sort()
554 .join('');
555 return normalize(str1) === normalize(str2);
556};
557const isArrayLike = obj => obj != null && typeof obj[Symbol.iterator] === 'function';
558const isBeforeDate = (dateA, dateB) => dateA < dateB;
559const isBoolean = val => typeof val === 'boolean';
560const isBrowser = () => ![typeof window, typeof document].includes('undefined');
561const isBrowserTabFocused = () => !document.hidden;
562const isDivisible = (dividend, divisor) => dividend % divisor === 0;
563const isDuplexStream = val =>
564 val !== null &&
565 typeof val === 'object' &&
566 typeof val.pipe === 'function' &&
567 typeof val._read === 'function' &&
568 typeof val._readableState === 'object' &&
569 typeof val._write === 'function' &&
570 typeof val._writableState === 'object';
571const isEmpty = val => val == null || !(Object.keys(val) || val).length;
572const isEven = num => num % 2 === 0;
573const isFunction = val => typeof val === 'function';
574const isLowerCase = str => str === str.toLowerCase();
575const isNegativeZero = val => val === 0 && 1 / val === -Infinity;
576const isNil = val => val === undefined || val === null;
577const isNull = val => val === null;
578const isNumber = val => typeof val === 'number';
579const isObject = obj => obj === Object(obj);
580const isObjectLike = val => val !== null && typeof val === 'object';
581const isPlainObject = val => !!val && typeof val === 'object' && val.constructor === Object;
582const isPrime = num => {
583 const boundary = Math.floor(Math.sqrt(num));
584 for (var i = 2; i <= boundary; i++) if (num % i === 0) return false;
585 return num >= 2;
586};
587const isPrimitive = val => Object(val) !== val;
588const isPromiseLike = obj =>
589 obj !== null &&
590 (typeof obj === 'object' || typeof obj === 'function') &&
591 typeof obj.then === 'function';
592const isReadableStream = val =>
593 val !== null &&
594 typeof val === 'object' &&
595 typeof val.pipe === 'function' &&
596 typeof val._read === 'function' &&
597 typeof val._readableState === 'object';
598const isSameDate = (dateA, dateB) => dateA.toISOString() === dateB.toISOString();
599const isSorted = arr => {
600 let direction = -(arr[0] - arr[1]);
601 for (let [i, val] of arr.entries()) {
602 direction = !direction ? -(arr[i - 1] - arr[i]) : direction;
603 if (i === arr.length - 1) return !direction ? 0 : direction;
604 else if ((val - arr[i + 1]) * direction > 0) return 0;
605 }
606};
607const isStream = val => val !== null && typeof val === 'object' && typeof val.pipe === 'function';
608const isString = val => typeof val === 'string';
609const isSymbol = val => typeof val === 'symbol';
610const isTravisCI = () => 'TRAVIS' in process.env && 'CI' in process.env;
611const isUndefined = val => val === undefined;
612const isUpperCase = str => str === str.toUpperCase();
613const isValidJSON = str => {
614 try {
615 JSON.parse(str);
616 return true;
617 } catch (e) {
618 return false;
619 }
620};
621const isWritableStream = val =>
622 val !== null &&
623 typeof val === 'object' &&
624 typeof val.pipe === 'function' &&
625 typeof val._write === 'function' &&
626 typeof val._writableState === 'object';
627const join = (arr, separator = ',', end = separator) =>
628 arr.reduce(
629 (acc, val, i) =>
630 i === arr.length - 2
631 ? acc + val + end
632 : i === arr.length - 1
633 ? acc + val
634 : acc + val + separator,
635 ''
636 );
637const last = arr => arr[arr.length - 1];
638const lcm = (...arr) => {
639 const gcd = (x, y) => (!y ? x : gcd(y, x % y));
640 const _lcm = (x, y) => (x * y) / gcd(x, y);
641 return [...arr].reduce((a, b) => _lcm(a, b));
642};
643const longestItem = (...vals) => vals.reduce((a, x) => (x.length > a.length ? x : a));
644const lowercaseKeys = obj =>
645 Object.keys(obj).reduce((acc, key) => {
646 acc[key.toLowerCase()] = obj[key];
647 return acc;
648 }, {});
649const luhnCheck = num => {
650 let arr = (num + '')
651 .split('')
652 .reverse()
653 .map(x => parseInt(x));
654 let lastDigit = arr.splice(0, 1)[0];
655 let sum = arr.reduce((acc, val, i) => (i % 2 !== 0 ? acc + val : acc + ((val * 2) % 9) || 9), 0);
656 sum += lastDigit;
657 return sum % 10 === 0;
658};
659const mapKeys = (obj, fn) =>
660 Object.keys(obj).reduce((acc, k) => {
661 acc[fn(obj[k], k, obj)] = obj[k];
662 return acc;
663 }, {});
664const mapObject = (arr, fn) =>
665 (a => (
666 (a = [arr, arr.map(fn)]), a[0].reduce((acc, val, ind) => ((acc[val] = a[1][ind]), acc), {})
667 ))();
668const mapString = (str, fn) =>
669 str
670 .split('')
671 .map((c, i) => fn(c, i, str))
672 .join('');
673const mapValues = (obj, fn) =>
674 Object.keys(obj).reduce((acc, k) => {
675 acc[k] = fn(obj[k], k, obj);
676 return acc;
677 }, {});
678const mask = (cc, num = 4, mask = '*') => `${cc}`.slice(-num).padStart(`${cc}`.length, mask);
679const matches = (obj, source) =>
680 Object.keys(source).every(key => obj.hasOwnProperty(key) && obj[key] === source[key]);
681const matchesWith = (obj, source, fn) =>
682 Object.keys(source).every(
683 key =>
684 obj.hasOwnProperty(key) && fn
685 ? fn(obj[key], source[key], key, obj, source)
686 : obj[key] == source[key]
687 );
688const maxBy = (arr, fn) => Math.max(...arr.map(typeof fn === 'function' ? fn : val => val[fn]));
689const maxDate = (...dates) => new Date(Math.max.apply(null, ...dates));
690const maxN = (arr, n = 1) => [...arr].sort((a, b) => b - a).slice(0, n);
691const median = arr => {
692 const mid = Math.floor(arr.length / 2),
693 nums = [...arr].sort((a, b) => a - b);
694 return arr.length % 2 !== 0 ? nums[mid] : (nums[mid - 1] + nums[mid]) / 2;
695};
696const memoize = fn => {
697 const cache = new Map();
698 const cached = function(val) {
699 return cache.has(val) ? cache.get(val) : cache.set(val, fn.call(this, val)) && cache.get(val);
700 };
701 cached.cache = cache;
702 return cached;
703};
704const merge = (...objs) =>
705 [...objs].reduce(
706 (acc, obj) =>
707 Object.keys(obj).reduce((a, k) => {
708 acc[k] = acc.hasOwnProperty(k) ? [].concat(acc[k]).concat(obj[k]) : obj[k];
709 return acc;
710 }, {}),
711 {}
712 );
713const minBy = (arr, fn) => Math.min(...arr.map(typeof fn === 'function' ? fn : val => val[fn]));
714const minDate = (...dates) => new Date(Math.min.apply(null, ...dates));
715const minN = (arr, n = 1) => [...arr].sort((a, b) => a - b).slice(0, n);
716const mostPerformant = (fns, iterations = 10000) => {
717 const times = fns.map(fn => {
718 const before = performance.now();
719 for (let i = 0; i < iterations; i++) fn();
720 return performance.now() - before;
721 });
722 return times.indexOf(Math.min(...times));
723};
724const negate = func => (...args) => !func(...args);
725const nest = (items, id = null, link = 'parent_id') =>
726 items
727 .filter(item => item[link] === id)
728 .map(item => ({ ...item, children: nest(items, item.id) }));
729const nodeListToArray = nodeList => [...nodeList];
730const none = (arr, fn = Boolean) => !arr.some(fn);
731const nthArg = n => (...args) => args.slice(n)[0];
732const nthElement = (arr, n = 0) => (n === -1 ? arr.slice(n) : arr.slice(n, n + 1))[0];
733const objectFromPairs = arr => arr.reduce((a, [key, val]) => ((a[key] = val), a), {});
734const objectToPairs = obj => Object.keys(obj).map(k => [k, obj[k]]);
735const observeMutations = (element, callback, options) => {
736 const observer = new MutationObserver(mutations => mutations.forEach(m => callback(m)));
737 observer.observe(
738 element,
739 Object.assign(
740 {
741 childList: true,
742 attributes: true,
743 attributeOldValue: true,
744 characterData: true,
745 characterDataOldValue: true,
746 subtree: true
747 },
748 options
749 )
750 );
751 return observer;
752};
753const off = (el, evt, fn, opts = false) => el.removeEventListener(evt, fn, opts);
754const offset = (arr, offset) => [...arr.slice(offset), ...arr.slice(0, offset)];
755const omit = (obj, arr) =>
756 Object.keys(obj)
757 .filter(k => !arr.includes(k))
758 .reduce((acc, key) => ((acc[key] = obj[key]), acc), {});
759const omitBy = (obj, fn) =>
760 Object.keys(obj)
761 .filter(k => !fn(obj[k], k))
762 .reduce((acc, key) => ((acc[key] = obj[key]), acc), {});
763const on = (el, evt, fn, opts = {}) => {
764 const delegatorFn = e => e.target.matches(opts.target) && fn.call(e.target, e);
765 el.addEventListener(evt, opts.target ? delegatorFn : fn, opts.options || false);
766 if (opts.target) return delegatorFn;
767};
768const onUserInputChange = callback => {
769 let type = 'mouse',
770 lastTime = 0;
771 const mousemoveHandler = () => {
772 const now = performance.now();
773 if (now - lastTime < 20)
774 (type = 'mouse'), callback(type), document.removeEventListener('mousemove', mousemoveHandler);
775 lastTime = now;
776 };
777 document.addEventListener('touchstart', () => {
778 if (type === 'touch') return;
779 (type = 'touch'), callback(type), document.addEventListener('mousemove', mousemoveHandler);
780 });
781};
782const once = fn => {
783 let called = false;
784 return function(...args) {
785 if (called) return;
786 called = true;
787 return fn.apply(this, args);
788 };
789};
790const orderBy = (arr, props, orders) =>
791 [...arr].sort((a, b) =>
792 props.reduce((acc, prop, i) => {
793 if (acc === 0) {
794 const [p1, p2] = orders && orders[i] === 'desc' ? [b[prop], a[prop]] : [a[prop], b[prop]];
795 acc = p1 > p2 ? 1 : p1 < p2 ? -1 : 0;
796 }
797 return acc;
798 }, 0)
799 );
800const over = (...fns) => (...args) => fns.map(fn => fn.apply(null, args));
801const overArgs = (fn, transforms) => (...args) => fn(...args.map((val, i) => transforms[i](val)));
802const pad = (str, length, char = ' ') =>
803 str.padStart((str.length + length) / 2, char).padEnd(length, char);
804const palindrome = str => {
805 const s = str.toLowerCase().replace(/[\W_]/g, '');
806 return s === [...s].reverse().join('');
807};
808const parseCookie = str =>
809 str
810 .split(';')
811 .map(v => v.split('='))
812 .reduce((acc, v) => {
813 acc[decodeURIComponent(v[0].trim())] = decodeURIComponent(v[1].trim());
814 return acc;
815 }, {});
816const partial = (fn, ...partials) => (...args) => fn(...partials, ...args);
817const partialRight = (fn, ...partials) => (...args) => fn(...args, ...partials);
818const partition = (arr, fn) =>
819 arr.reduce(
820 (acc, val, i, arr) => {
821 acc[fn(val, i, arr) ? 0 : 1].push(val);
822 return acc;
823 },
824 [[], []]
825 );
826const percentile = (arr, val) =>
827 (100 * arr.reduce((acc, v) => acc + (v < val ? 1 : 0) + (v === val ? 0.5 : 0), 0)) / arr.length;
828const permutations = arr => {
829 if (arr.length <= 2) return arr.length === 2 ? [arr, [arr[1], arr[0]]] : arr;
830 return arr.reduce(
831 (acc, item, i) =>
832 acc.concat(
833 permutations([...arr.slice(0, i), ...arr.slice(i + 1)]).map(val => [item, ...val])
834 ),
835 []
836 );
837};
838const pick = (obj, arr) =>
839 arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {});
840const pickBy = (obj, fn) =>
841 Object.keys(obj)
842 .filter(k => fn(obj[k], k))
843 .reduce((acc, key) => ((acc[key] = obj[key]), acc), {});
844const pipeAsyncFunctions = (...fns) => arg => fns.reduce((p, f) => p.then(f), Promise.resolve(arg));
845const pipeFunctions = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args)));
846const pluralize = (val, word, plural = word + 's') => {
847 const _pluralize = (num, word, plural = word + 's') =>
848 [1, -1].includes(Number(num)) ? word : plural;
849 if (typeof val === 'object') return (num, word) => _pluralize(num, word, val[word]);
850 return _pluralize(val, word, plural);
851};
852const powerset = arr => arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]);
853const prefix = prop => {
854 const capitalizedProp = prop.charAt(0).toUpperCase() + prop.slice(1);
855 const prefixes = ['', 'webkit', 'moz', 'ms', 'o'];
856 const i = prefixes.findIndex(
857 prefix => typeof document.body.style[prefix ? prefix + capitalizedProp : prop] !== 'undefined'
858 );
859 return i !== -1 ? (i === 0 ? prop : prefixes[i] + capitalizedProp) : null;
860};
861const prettyBytes = (num, precision = 3, addSpace = true) => {
862 const UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
863 if (Math.abs(num) < 1) return num + (addSpace ? ' ' : '') + UNITS[0];
864 const exponent = Math.min(Math.floor(Math.log10(num < 0 ? -num : num) / 3), UNITS.length - 1);
865 const n = Number(((num < 0 ? -num : num) / 1000 ** exponent).toPrecision(precision));
866 return (num < 0 ? '-' : '') + n + (addSpace ? ' ' : '') + UNITS[exponent];
867};
868const primes = num => {
869 let arr = Array.from({ length: num - 1 }).map((x, i) => i + 2),
870 sqroot = Math.floor(Math.sqrt(num)),
871 numsTillSqroot = Array.from({ length: sqroot - 1 }).map((x, i) => i + 2);
872 numsTillSqroot.forEach(x => (arr = arr.filter(y => y % x !== 0 || y === x)));
873 return arr;
874};
875const promisify = func => (...args) =>
876 new Promise((resolve, reject) =>
877 func(...args, (err, result) => (err ? reject(err) : resolve(result)))
878 );
879const pull = (arr, ...args) => {
880 let argState = Array.isArray(args[0]) ? args[0] : args;
881 let pulled = arr.filter((v, i) => !argState.includes(v));
882 arr.length = 0;
883 pulled.forEach(v => arr.push(v));
884};
885const pullAtIndex = (arr, pullArr) => {
886 let removed = [];
887 let pulled = arr
888 .map((v, i) => (pullArr.includes(i) ? removed.push(v) : v))
889 .filter((v, i) => !pullArr.includes(i));
890 arr.length = 0;
891 pulled.forEach(v => arr.push(v));
892 return removed;
893};
894const pullAtValue = (arr, pullArr) => {
895 let removed = [],
896 pushToRemove = arr.forEach((v, i) => (pullArr.includes(v) ? removed.push(v) : v)),
897 mutateTo = arr.filter((v, i) => !pullArr.includes(v));
898 arr.length = 0;
899 mutateTo.forEach(v => arr.push(v));
900 return removed;
901};
902const pullBy = (arr, ...args) => {
903 const length = args.length;
904 let fn = length > 1 ? args[length - 1] : undefined;
905 fn = typeof fn == 'function' ? (args.pop(), fn) : undefined;
906 let argState = (Array.isArray(args[0]) ? args[0] : args).map(val => fn(val));
907 let pulled = arr.filter((v, i) => !argState.includes(fn(v)));
908 arr.length = 0;
909 pulled.forEach(v => arr.push(v));
910};
911const radsToDegrees = rad => (rad * 180.0) / Math.PI;
912const randomHexColorCode = () => {
913 let n = (Math.random() * 0xfffff * 1000000).toString(16);
914 return '#' + n.slice(0, 6);
915};
916const randomIntArrayInRange = (min, max, n = 1) =>
917 Array.from({ length: n }, () => Math.floor(Math.random() * (max - min + 1)) + min);
918const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
919const randomNumberInRange = (min, max) => Math.random() * (max - min) + min;
920const readFileLines = filename =>
921 fs
922 .readFileSync(filename)
923 .toString('UTF8')
924 .split('\n');
925const rearg = (fn, indexes) => (...args) => fn(...indexes.map(i => args[i]));
926const recordAnimationFrames = (callback, autoStart = true) => {
927 let running = true,
928 raf;
929 const stop = () => {
930 running = false;
931 cancelAnimationFrame(raf);
932 };
933 const start = () => {
934 running = true;
935 run();
936 };
937 const run = () => {
938 raf = requestAnimationFrame(() => {
939 callback();
940 if (running) run();
941 });
942 };
943 if (autoStart) start();
944 return { start, stop };
945};
946const redirect = (url, asLink = true) =>
947 asLink ? (window.location.href = url) : window.location.replace(url);
948const reduceSuccessive = (arr, fn, acc) =>
949 arr.reduce((res, val, i, arr) => (res.push(fn(res.slice(-1)[0], val, i, arr)), res), [acc]);
950const reduceWhich = (arr, comparator = (a, b) => a - b) =>
951 arr.reduce((a, b) => (comparator(a, b) >= 0 ? b : a));
952const reducedFilter = (data, keys, fn) =>
953 data.filter(fn).map(el =>
954 keys.reduce((acc, key) => {
955 acc[key] = el[key];
956 return acc;
957 }, {})
958 );
959const reject = (pred, array) => array.filter((...args) => !pred(...args));
960const remove = (arr, func) =>
961 Array.isArray(arr)
962 ? arr.filter(func).reduce((acc, val) => {
963 arr.splice(arr.indexOf(val), 1);
964 return acc.concat(val);
965 }, [])
966 : [];
967const removeNonASCII = str => str.replace(/[^\x20-\x7E]/g, '');
968const renameKeys = (keysMap, obj) =>
969 Object.keys(obj).reduce(
970 (acc, key) => ({
971 ...acc,
972 ...{ [keysMap[key] || key]: obj[key] }
973 }),
974 {}
975 );
976const reverseString = str => [...str].reverse().join('');
977const round = (n, decimals = 0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`);
978const runAsync = fn => {
979 const worker = new Worker(
980 URL.createObjectURL(new Blob([`postMessage((${fn})());`]), {
981 type: 'application/javascript; charset=utf-8'
982 })
983 );
984 return new Promise((res, rej) => {
985 worker.onmessage = ({ data }) => {
986 res(data), worker.terminate();
987 };
988 worker.onerror = err => {
989 rej(err), worker.terminate();
990 };
991 });
992};
993const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve());
994const sample = arr => arr[Math.floor(Math.random() * arr.length)];
995const sampleSize = ([...arr], n = 1) => {
996 let m = arr.length;
997 while (m) {
998 const i = Math.floor(Math.random() * m--);
999 [arr[m], arr[i]] = [arr[i], arr[m]];
1000 }
1001 return arr.slice(0, n);
1002};
1003const scrollToTop = () => {
1004 const c = document.documentElement.scrollTop || document.body.scrollTop;
1005 if (c > 0) {
1006 window.requestAnimationFrame(scrollToTop);
1007 window.scrollTo(0, c - c / 8);
1008 }
1009};
1010const sdbm = str => {
1011 let arr = str.split('');
1012 return arr.reduce(
1013 (hashCode, currentVal) =>
1014 (hashCode = currentVal.charCodeAt(0) + (hashCode << 6) + (hashCode << 16) - hashCode),
1015 0
1016 );
1017};
1018const serializeCookie = (name, val) => `${encodeURIComponent(name)}=${encodeURIComponent(val)}`;
1019const setStyle = (el, ruleName, val) => (el.style[ruleName] = val);
1020const shallowClone = obj => Object.assign({}, obj);
1021const shank = (arr, index = 0, delCount = 0, ...elements) =>
1022 arr
1023 .slice(0, index)
1024 .concat(elements)
1025 .concat(arr.slice(index + delCount));
1026const show = (...el) => [...el].forEach(e => (e.style.display = ''));
1027const shuffle = ([...arr]) => {
1028 let m = arr.length;
1029 while (m) {
1030 const i = Math.floor(Math.random() * m--);
1031 [arr[m], arr[i]] = [arr[i], arr[m]];
1032 }
1033 return arr;
1034};
1035const similarity = (arr, values) => arr.filter(v => values.includes(v));
1036const size = val =>
1037 Array.isArray(val)
1038 ? val.length
1039 : val && typeof val === 'object'
1040 ? val.size || val.length || Object.keys(val).length
1041 : typeof val === 'string'
1042 ? new Blob([val]).size
1043 : 0;
1044const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
1045const smoothScroll = element =>
1046 document.querySelector(element).scrollIntoView({
1047 behavior: 'smooth'
1048 });
1049const sortCharactersInString = str => [...str].sort((a, b) => a.localeCompare(b)).join('');
1050const sortedIndex = (arr, n) => {
1051 const isDescending = arr[0] > arr[arr.length - 1];
1052 const index = arr.findIndex(el => (isDescending ? n >= el : n <= el));
1053 return index === -1 ? arr.length : index;
1054};
1055const sortedIndexBy = (arr, n, fn) => {
1056 const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]);
1057 const val = fn(n);
1058 const index = arr.findIndex(el => (isDescending ? val >= fn(el) : val <= fn(el)));
1059 return index === -1 ? arr.length : index;
1060};
1061const sortedLastIndex = (arr, n) => {
1062 const isDescending = arr[0] > arr[arr.length - 1];
1063 const index = arr.reverse().findIndex(el => (isDescending ? n <= el : n >= el));
1064 return index === -1 ? 0 : arr.length - index;
1065};
1066const sortedLastIndexBy = (arr, n, fn) => {
1067 const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]);
1068 const val = fn(n);
1069 const index = arr
1070 .map(fn)
1071 .reverse()
1072 .findIndex(el => (isDescending ? val <= el : val >= el));
1073 return index === -1 ? 0 : arr.length - index;
1074};
1075const splitLines = str => str.split(/\r?\n/);
1076const spreadOver = fn => argsArr => fn(...argsArr);
1077const stableSort = (arr, compare) =>
1078 arr
1079 .map((item, index) => ({ item, index }))
1080 .sort((a, b) => compare(a.item, b.item) || a.index - b.index)
1081 .map(({ item }) => item);
1082const standardDeviation = (arr, usePopulation = false) => {
1083 const mean = arr.reduce((acc, val) => acc + val, 0) / arr.length;
1084 return Math.sqrt(
1085 arr.reduce((acc, val) => acc.concat((val - mean) ** 2), []).reduce((acc, val) => acc + val, 0) /
1086 (arr.length - (usePopulation ? 0 : 1))
1087 );
1088};
1089const stringPermutations = str => {
1090 if (str.length <= 2) return str.length === 2 ? [str, str[1] + str[0]] : [str];
1091 return str
1092 .split('')
1093 .reduce(
1094 (acc, letter, i) =>
1095 acc.concat(stringPermutations(str.slice(0, i) + str.slice(i + 1)).map(val => letter + val)),
1096 []
1097 );
1098};
1099const stripHTMLTags = str => str.replace(/<[^>]*>/g, '');
1100const sum = (...arr) => [...arr].reduce((acc, val) => acc + val, 0);
1101const sumBy = (arr, fn) =>
1102 arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0);
1103const sumPower = (end, power = 2, start = 1) =>
1104 Array(end + 1 - start)
1105 .fill(0)
1106 .map((x, i) => (i + start) ** power)
1107 .reduce((a, b) => a + b, 0);
1108const symmetricDifference = (a, b) => {
1109 const sA = new Set(a),
1110 sB = new Set(b);
1111 return [...a.filter(x => !sB.has(x)), ...b.filter(x => !sA.has(x))];
1112};
1113const symmetricDifferenceBy = (a, b, fn) => {
1114 const sA = new Set(a.map(v => fn(v))),
1115 sB = new Set(b.map(v => fn(v)));
1116 return [...a.filter(x => !sB.has(fn(x))), ...b.filter(x => !sA.has(fn(x)))];
1117};
1118const symmetricDifferenceWith = (arr, val, comp) => [
1119 ...arr.filter(a => val.findIndex(b => comp(a, b)) === -1),
1120 ...val.filter(a => arr.findIndex(b => comp(a, b)) === -1)
1121];
1122const tail = arr => (arr.length > 1 ? arr.slice(1) : arr);
1123const take = (arr, n = 1) => arr.slice(0, n);
1124const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length);
1125const takeRightWhile = (arr, func) =>
1126 arr.reduceRight((acc, el) => (func(el) ? acc : [el, ...acc]), []);
1127const takeWhile = (arr, func) => {
1128 for (const [i, val] of arr.entries()) if (func(val)) return arr.slice(0, i);
1129 return arr;
1130};
1131const throttle = (fn, wait) => {
1132 let inThrottle, lastFn, lastTime;
1133 return function() {
1134 const context = this,
1135 args = arguments;
1136 if (!inThrottle) {
1137 fn.apply(context, args);
1138 lastTime = Date.now();
1139 inThrottle = true;
1140 } else {
1141 clearTimeout(lastFn);
1142 lastFn = setTimeout(function() {
1143 if (Date.now() - lastTime >= wait) {
1144 fn.apply(context, args);
1145 lastTime = Date.now();
1146 }
1147 }, Math.max(wait - (Date.now() - lastTime), 0));
1148 }
1149 };
1150};
1151const timeTaken = callback => {
1152 console.time('timeTaken');
1153 const r = callback();
1154 console.timeEnd('timeTaken');
1155 return r;
1156};
1157const times = (n, fn, context = undefined) => {
1158 let i = 0;
1159 while (fn.call(context, i) !== false && ++i < n) {}
1160};
1161const toCamelCase = str => {
1162 let s =
1163 str &&
1164 str
1165 .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
1166 .map(x => x.slice(0, 1).toUpperCase() + x.slice(1).toLowerCase())
1167 .join('');
1168 return s.slice(0, 1).toLowerCase() + s.slice(1);
1169};
1170const toCurrency = (n, curr, LanguageFormat = undefined) =>
1171 Intl.NumberFormat(LanguageFormat, { style: 'currency', currency: curr }).format(n);
1172const toDecimalMark = num => num.toLocaleString('en-US');
1173const toHash = (object, key) =>
1174 Array.prototype.reduce.call(
1175 object,
1176 (acc, data, index) => ((acc[!key ? index : data[key]] = data), acc),
1177 {}
1178 );
1179const toKebabCase = str =>
1180 str &&
1181 str
1182 .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
1183 .map(x => x.toLowerCase())
1184 .join('-');
1185const toOrdinalSuffix = num => {
1186 const int = parseInt(num),
1187 digits = [int % 10, int % 100],
1188 ordinals = ['st', 'nd', 'rd', 'th'],
1189 oPattern = [1, 2, 3, 4],
1190 tPattern = [11, 12, 13, 14, 15, 16, 17, 18, 19];
1191 return oPattern.includes(digits[0]) && !tPattern.includes(digits[1])
1192 ? int + ordinals[digits[0] - 1]
1193 : int + ordinals[3];
1194};
1195const toSafeInteger = num =>
1196 Math.round(Math.max(Math.min(num, Number.MAX_SAFE_INTEGER), Number.MIN_SAFE_INTEGER));
1197const toSnakeCase = str =>
1198 str &&
1199 str
1200 .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
1201 .map(x => x.toLowerCase())
1202 .join('_');
1203const toTitleCase = str =>
1204 str
1205 .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
1206 .map(x => x.charAt(0).toUpperCase() + x.slice(1))
1207 .join(' ');
1208const toggleClass = (el, className) => el.classList.toggle(className);
1209const tomorrow = (long = false) => {
1210 let t = new Date();
1211 t.setDate(t.getDate() + 1);
1212 const ret = `${t.getFullYear()}-${String(t.getMonth() + 1).padStart(2, '0')}-${String(
1213 t.getDate()
1214 ).padStart(2, '0')}`;
1215 return !long ? ret : `${ret}T00:00:00`;
1216};
1217const transform = (obj, fn, acc) => Object.keys(obj).reduce((a, k) => fn(a, obj[k], k, obj), acc);
1218const triggerEvent = (el, eventType, detail) =>
1219 el.dispatchEvent(new CustomEvent(eventType, { detail }));
1220const truncateString = (str, num) =>
1221 str.length > num ? str.slice(0, num > 3 ? num - 3 : num) + '...' : str;
1222const truthCheckCollection = (collection, pre) => collection.every(obj => obj[pre]);
1223const unary = fn => val => fn(val);
1224const uncurry = (fn, n = 1) => (...args) => {
1225 const next = acc => args => args.reduce((x, y) => x(y), acc);
1226 if (n > args.length) throw new RangeError('Arguments too few!');
1227 return next(fn)(args.slice(0, n));
1228};
1229const unescapeHTML = str =>
1230 str.replace(
1231 /&amp;|&lt;|&gt;|&#39;|&quot;/g,
1232 tag =>
1233 ({
1234 '&amp;': '&',
1235 '&lt;': '<',
1236 '&gt;': '>',
1237 '&#39;': "'",
1238 '&quot;': '"'
1239 }[tag] || tag)
1240 );
1241const unflattenObject = obj =>
1242 Object.keys(obj).reduce((acc, k) => {
1243 if (k.indexOf('.') !== -1) {
1244 const keys = k.split('.');
1245 Object.assign(
1246 acc,
1247 JSON.parse(
1248 '{' +
1249 keys.map((v, i) => (i !== keys.length - 1 ? `"${v}":{` : `"${v}":`)).join('') +
1250 obj[k] +
1251 '}'.repeat(keys.length)
1252 )
1253 );
1254 } else acc[k] = obj[k];
1255 return acc;
1256 }, {});
1257const unfold = (fn, seed) => {
1258 let result = [],
1259 val = [null, seed];
1260 while ((val = fn(val[1]))) result.push(val[0]);
1261 return result;
1262};
1263const union = (a, b) => Array.from(new Set([...a, ...b]));
1264const unionBy = (a, b, fn) => {
1265 const s = new Set(a.map(fn));
1266 return Array.from(new Set([...a, ...b.filter(x => !s.has(fn(x)))]));
1267};
1268const unionWith = (a, b, comp) =>
1269 Array.from(new Set([...a, ...b.filter(x => a.findIndex(y => comp(x, y)) === -1)]));
1270const uniqueElements = arr => [...new Set(arr)];
1271const uniqueElementsBy = (arr, fn) =>
1272 arr.reduce((acc, v) => {
1273 if (!acc.some(x => fn(v, x))) acc.push(v);
1274 return acc;
1275 }, []);
1276const uniqueElementsByRight = (arr, fn) =>
1277 arr.reduceRight((acc, v) => {
1278 if (!acc.some(x => fn(v, x))) acc.push(v);
1279 return acc;
1280 }, []);
1281const uniqueSymmetricDifference = (a, b) => [
1282 ...new Set([...a.filter(v => !b.includes(v)), ...b.filter(v => !a.includes(v))])
1283];
1284const untildify = str => str.replace(/^~($|\/|\\)/, `${require('os').homedir()}$1`);
1285const unzip = arr =>
1286 arr.reduce(
1287 (acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc),
1288 Array.from({
1289 length: Math.max(...arr.map(x => x.length))
1290 }).map(x => [])
1291 );
1292const unzipWith = (arr, fn) =>
1293 arr
1294 .reduce(
1295 (acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc),
1296 Array.from({
1297 length: Math.max(...arr.map(x => x.length))
1298 }).map(x => [])
1299 )
1300 .map(val => fn(...val));
1301const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n;
1302const when = (pred, whenTrue) => x => (pred(x) ? whenTrue(x) : x);
1303const without = (arr, ...args) => arr.filter(v => !args.includes(v));
1304const words = (str, pattern = /[^a-zA-Z-]+/) => str.split(pattern).filter(Boolean);
1305const xProd = (a, b) => a.reduce((acc, x) => acc.concat(b.map(y => [x, y])), []);
1306const yesNo = (val, def = false) =>
1307 /^(y|yes)$/i.test(val) ? true : /^(n|no)$/i.test(val) ? false : def;
1308const zip = (...arrays) => {
1309 const maxLength = Math.max(...arrays.map(x => x.length));
1310 return Array.from({ length: maxLength }).map((_, i) => {
1311 return Array.from({ length: arrays.length }, (_, k) => arrays[k][i]);
1312 });
1313};
1314const zipObject = (props, values) =>
1315 props.reduce((obj, prop, index) => ((obj[prop] = values[index]), obj), {});
1316const zipWith = (...array) => {
1317 const fn = typeof array[array.length - 1] === 'function' ? array.pop() : undefined;
1318 return Array.from(
1319 { length: Math.max(...array.map(a => a.length)) },
1320 (_, i) => (fn ? fn(...array.map(a => a[i])) : array.map(a => a[i]))
1321 );
1322};
1323
1324export { CSVToArray, CSVToJSON, JSONToFile, JSONtoCSV, RGBToHex, URLJoin, UUIDGeneratorBrowser, UUIDGeneratorNode, all, allEqual, any, approximatelyEqual, arrayToCSV, arrayToHtmlList, ary, atob, attempt, average, averageBy, bifurcate, bifurcateBy, bind, bindAll, bindKey, binomialCoefficient, bottomVisible, btoa, byteSize, call, capitalize, capitalizeEveryWord, castArray, chainAsync, chunk, clampNumber, cloneRegExp, coalesce, coalesceFactory, collectInto, colorize, compact, compose, composeRight, converge, copyToClipboard, countBy, countOccurrences, counter, createElement, createEventHub, currentURL, curry, dayOfYear, debounce, decapitalize, deepClone, deepFlatten, deepFreeze, defaults, defer, degreesToRads, delay, detectDeviceType, difference, differenceBy, differenceWith, dig, digitize, distance, drop, dropRight, dropRightWhile, dropWhile, elementContains, elementIsVisibleInViewport, elo, equals, escapeHTML, escapeRegExp, everyNth, extendHex, factorial, fibonacci, filterNonUnique, filterNonUniqueBy, findKey, findLast, findLastIndex, findLastKey, flatten, flattenObject, flip, forEachRight, forOwn, forOwnRight, formatDuration, fromCamelCase, functionName, functions, gcd, geometricProgression, get, getColonTimeFromDate, getDaysDiffBetweenDates, getImages, getMeridiemSuffixOfInteger, getScrollPosition, getStyle, getType, getURLParameters, groupBy, hammingDistance, hasClass, hasFlags, hashBrowser, hashNode, head, hexToRGB, hide, httpGet, httpPost, httpsRedirect, hz, inRange, indentString, indexOfAll, initial, initialize2DArray, initializeArrayWithRange, initializeArrayWithRangeRight, initializeArrayWithValues, initializeNDArray, insertAfter, insertBefore, intersection, intersectionBy, intersectionWith, invertKeyValues, is, isAbsoluteURL, isAfterDate, isAnagram, isArrayLike, isBeforeDate, isBoolean, isBrowser, isBrowserTabFocused, isDivisible, isDuplexStream, isEmpty, isEven, isFunction, isLowerCase, isNegativeZero, isNil, isNull, isNumber, isObject, isObjectLike, isPlainObject, isPrime, isPrimitive, isPromiseLike, isReadableStream, isSameDate, isSorted, isStream, isString, isSymbol, isTravisCI, isUndefined, isUpperCase, isValidJSON, isWritableStream, join, last, lcm, longestItem, lowercaseKeys, luhnCheck, mapKeys, mapObject, mapString, mapValues, mask, matches, matchesWith, maxBy, maxDate, maxN, median, memoize, merge, minBy, minDate, minN, mostPerformant, negate, nest, nodeListToArray, none, nthArg, nthElement, objectFromPairs, objectToPairs, observeMutations, off, offset, omit, omitBy, on, onUserInputChange, once, orderBy, over, overArgs, pad, palindrome, parseCookie, partial, partialRight, partition, percentile, permutations, pick, pickBy, pipeAsyncFunctions, pipeFunctions, pluralize, powerset, prefix, prettyBytes, primes, promisify, pull, pullAtIndex, pullAtValue, pullBy, radsToDegrees, randomHexColorCode, randomIntArrayInRange, randomIntegerInRange, randomNumberInRange, readFileLines, rearg, recordAnimationFrames, redirect, reduceSuccessive, reduceWhich, reducedFilter, reject, remove, removeNonASCII, renameKeys, reverseString, round, runAsync, runPromisesInSeries, sample, sampleSize, scrollToTop, sdbm, serializeCookie, setStyle, shallowClone, shank, show, shuffle, similarity, size, sleep, smoothScroll, sortCharactersInString, sortedIndex, sortedIndexBy, sortedLastIndex, sortedLastIndexBy, splitLines, spreadOver, stableSort, standardDeviation, stringPermutations, stripHTMLTags, sum, sumBy, sumPower, symmetricDifference, symmetricDifferenceBy, symmetricDifferenceWith, tail, take, takeRight, takeRightWhile, takeWhile, throttle, timeTaken, times, toCamelCase, toCurrency, toDecimalMark, toHash, toKebabCase, toOrdinalSuffix, toSafeInteger, toSnakeCase, toTitleCase, toggleClass, tomorrow, transform, triggerEvent, truncateString, truthCheckCollection, unary, uncurry, unescapeHTML, unflattenObject, unfold, union, unionBy, unionWith, uniqueElements, uniqueElementsBy, uniqueElementsByRight, uniqueSymmetricDifference, untildify, unzip, unzipWith, validateNumber, when, without, words, xProd, yesNo, zip, zipObject, zipWith };
1325
\No newline at end of file