1 | const fs = typeof require !== "undefined" && require('fs');
|
2 | const crypto = typeof require !== "undefined" && require('crypto');
|
3 |
|
4 | const CSVToArray = (data, delimiter = ',', omitFirstRow = false) =>
|
5 | data
|
6 | .slice(omitFirstRow ? data.indexOf('\n') + 1 : 0)
|
7 | .split('\n')
|
8 | .map(v => v.split(delimiter));
|
9 | const 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 | };
|
19 | const JSONToFile = (obj, filename) =>
|
20 | fs.writeFile(`${filename}.json`, JSON.stringify(obj, null, 2));
|
21 | const 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');
|
31 | const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0');
|
32 | const 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('&', '?');
|
41 | const 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 | );
|
45 | const UUIDGeneratorNode = () =>
|
46 | ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
|
47 | (c ^ (crypto.randomBytes(1)[0] & (15 >> (c / 4)))).toString(16)
|
48 | );
|
49 | const all = (arr, fn = Boolean) => arr.every(fn);
|
50 | const allEqual = arr => arr.every(val => val === arr[0]);
|
51 | const any = (arr, fn = Boolean) => arr.some(fn);
|
52 | const approximatelyEqual = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) < epsilon;
|
53 | const arrayToCSV = (arr, delimiter = ',') =>
|
54 | arr.map(v => v.map(x => `"${x}"`).join(delimiter)).join('\n');
|
55 | const arrayToHtmlList = (arr, listID) =>
|
56 | (el => (
|
57 | (el = document.querySelector('#' + listID)),
|
58 | (el.innerHTML += arr.map(item => `<li>${item}</li>`).join(''))
|
59 | ))();
|
60 | const ary = (fn, n) => (...args) => fn(...args.slice(0, n));
|
61 | const atob = str => Buffer.from(str, 'base64').toString('binary');
|
62 | const attempt = (fn, ...args) => {
|
63 | try {
|
64 | return fn(...args);
|
65 | } catch (e) {
|
66 | return e instanceof Error ? e : new Error(e);
|
67 | }
|
68 | };
|
69 | const average = (...nums) => nums.reduce((acc, val) => acc + val, 0) / nums.length;
|
70 | const averageBy = (arr, fn) =>
|
71 | arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0) /
|
72 | arr.length;
|
73 | const bifurcate = (arr, filter) =>
|
74 | arr.reduce((acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc), [[], []]);
|
75 | const bifurcateBy = (arr, fn) =>
|
76 | arr.reduce((acc, val, i) => (acc[fn(val, i) ? 0 : 1].push(val), acc), [[], []]);
|
77 | const bind = (fn, context, ...boundArgs) => (...args) => fn.apply(context, [...boundArgs, ...args]);
|
78 | const bindAll = (obj, ...fns) =>
|
79 | fns.forEach(
|
80 | fn => (
|
81 | (f = obj[fn]),
|
82 | (obj[fn] = function() {
|
83 | return f.apply(obj);
|
84 | })
|
85 | )
|
86 | );
|
87 | const bindKey = (context, fn, ...boundArgs) => (...args) =>
|
88 | context[fn].apply(context, [...boundArgs, ...args]);
|
89 | const 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 | };
|
99 | const bottomVisible = () =>
|
100 | document.documentElement.clientHeight + window.scrollY >=
|
101 | (document.documentElement.scrollHeight || document.documentElement.clientHeight);
|
102 | const btoa = str => Buffer.from(str, 'binary').toString('base64');
|
103 | const byteSize = str => new Blob([str]).size;
|
104 | const call = (key, ...args) => context => context[key](...args);
|
105 | const capitalize = ([first, ...rest], lowerRest = false) =>
|
106 | first.toUpperCase() + (lowerRest ? rest.join('').toLowerCase() : rest.join(''));
|
107 | const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase());
|
108 | const castArray = val => (Array.isArray(val) ? val : [val]);
|
109 | const chainAsync = fns => {
|
110 | let curr = 0;
|
111 | const next = () => fns[curr++](next);
|
112 | next();
|
113 | };
|
114 | const chunk = (arr, size) =>
|
115 | Array.from({ length: Math.ceil(arr.length / size) }, (v, i) =>
|
116 | arr.slice(i * size, i * size + size)
|
117 | );
|
118 | const clampNumber = (num, a, b) => Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b));
|
119 | const cloneRegExp = regExp => new RegExp(regExp.source, regExp.flags);
|
120 | const coalesce = (...args) => args.find(_ => ![undefined, null].includes(_));
|
121 | const coalesceFactory = valid => (...args) => args.find(valid);
|
122 | const collectInto = fn => (...args) => fn(args);
|
123 | const 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 | });
|
141 | const compact = arr => arr.filter(Boolean);
|
142 | const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)));
|
143 | const composeRight = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args)));
|
144 | const converge = (converger, fns) => (...args) => converger(...fns.map(fn => fn.apply(null, args)));
|
145 | const 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 | };
|
162 | const 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 | }, {});
|
167 | const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0);
|
168 | const 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 | };
|
179 | const createElement = str => {
|
180 | const el = document.createElement('div');
|
181 | el.innerHTML = str;
|
182 | return el.firstElementChild;
|
183 | };
|
184 | const 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 | });
|
198 | const currentURL = () => window.location.href;
|
199 | const curry = (fn, arity = fn.length, ...args) =>
|
200 | arity <= args.length ? fn(...args) : curry.bind(null, fn, arity, ...args);
|
201 | const dayOfYear = date =>
|
202 | Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24);
|
203 | const debounce = (fn, ms = 0) => {
|
204 | let timeoutId;
|
205 | return function(...args) {
|
206 | clearTimeout(timeoutId);
|
207 | timeoutId = setTimeout(() => fn.apply(this, args), ms);
|
208 | };
|
209 | };
|
210 | const decapitalize = ([first, ...rest], upperRest = false) =>
|
211 | first.toLowerCase() + (upperRest ? rest.join('').toUpperCase() : rest.join(''));
|
212 | const 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 | };
|
219 | const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v)));
|
220 | const 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);
|
225 | const defaults = (obj, ...defs) => Object.assign({}, obj, ...defs.reverse(), obj);
|
226 | const defer = (fn, ...args) => setTimeout(fn, 1, ...args);
|
227 | const degreesToRads = deg => (deg * Math.PI) / 180.0;
|
228 | const delay = (fn, wait, ...args) => setTimeout(fn, wait, ...args);
|
229 | const detectDeviceType = () =>
|
230 | /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
|
231 | ? 'Mobile'
|
232 | : 'Desktop';
|
233 | const difference = (a, b) => {
|
234 | const s = new Set(b);
|
235 | return a.filter(x => !s.has(x));
|
236 | };
|
237 | const differenceBy = (a, b, fn) => {
|
238 | const s = new Set(b.map(fn));
|
239 | return a.filter(x => !s.has(fn(x)));
|
240 | };
|
241 | const differenceWith = (arr, val, comp) => arr.filter(a => val.findIndex(b => comp(a, b)) === -1);
|
242 | const 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);
|
249 | const digitize = n => [...`${n}`].map(i => parseInt(i));
|
250 | const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0);
|
251 | const drop = (arr, n = 1) => arr.slice(n);
|
252 | const dropRight = (arr, n = 1) => arr.slice(0, -n);
|
253 | const dropRightWhile = (arr, func) => {
|
254 | while (arr.length > 0 && !func(arr[arr.length - 1])) arr = arr.slice(0, -1);
|
255 | return arr;
|
256 | };
|
257 | const dropWhile = (arr, func) => {
|
258 | while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1);
|
259 | return arr;
|
260 | };
|
261 | const elementContains = (parent, child) => parent !== child && parent.contains(child);
|
262 | const 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 | };
|
270 | const 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 | };
|
286 | const 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 | };
|
296 | const escapeHTML = str =>
|
297 | str.replace(
|
298 | /[&<>'"]/g,
|
299 | tag =>
|
300 | ({
|
301 | '&': '&',
|
302 | '<': '<',
|
303 | '>': '>',
|
304 | "'": ''',
|
305 | '"': '"'
|
306 | }[tag] || tag)
|
307 | );
|
308 | const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
309 | const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === nth - 1);
|
310 | const extendHex = shortHex =>
|
311 | '#' +
|
312 | shortHex
|
313 | .slice(shortHex.startsWith('#') ? 1 : 0)
|
314 | .split('')
|
315 | .map(x => x + x)
|
316 | .join('');
|
317 | const 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);
|
325 | const 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 | );
|
330 | const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i));
|
331 | const filterNonUniqueBy = (arr, fn) =>
|
332 | arr.filter((v, i) => arr.every((x, j) => (i === j) === fn(v, x, i, j)));
|
333 | const findKey = (obj, fn) => Object.keys(obj).find(key => fn(obj[key], key, obj));
|
334 | const findLast = (arr, fn) => arr.filter(fn).pop();
|
335 | const findLastIndex = (arr, fn) =>
|
336 | arr
|
337 | .map((val, i) => [i, val])
|
338 | .filter(([i, val]) => fn(val, i, arr))
|
339 | .pop()[0];
|
340 | const findLastKey = (obj, fn) =>
|
341 | Object.keys(obj)
|
342 | .reverse()
|
343 | .find(key => fn(obj[key], key, obj));
|
344 | const flatten = (arr, depth = 1) =>
|
345 | arr.reduce((a, v) => a.concat(depth > 1 && Array.isArray(v) ? flatten(v, depth - 1) : v), []);
|
346 | const 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 | }, {});
|
353 | const flip = fn => (first, ...rest) => fn(...rest, first);
|
354 | const forEachRight = (arr, callback) =>
|
355 | arr
|
356 | .slice(0)
|
357 | .reverse()
|
358 | .forEach(callback);
|
359 | const forOwn = (obj, fn) => Object.keys(obj).forEach(key => fn(obj[key], key, obj));
|
360 | const forOwnRight = (obj, fn) =>
|
361 | Object.keys(obj)
|
362 | .reverse()
|
363 | .forEach(key => fn(obj[key], key, obj));
|
364 | const 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 | };
|
378 | const 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();
|
383 | const functionName = fn => (console.debug(fn.name), fn);
|
384 | const 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');
|
389 | const gcd = (...arr) => {
|
390 | const _gcd = (x, y) => (!y ? x : gcd(y, x % y));
|
391 | return [...arr].reduce((a, b) => _gcd(a, b));
|
392 | };
|
393 | const 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 | );
|
397 | const 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 | );
|
405 | const getColonTimeFromDate = date => date.toTimeString().slice(0, 8);
|
406 | const getDaysDiffBetweenDates = (dateInitial, dateFinal) =>
|
407 | (dateFinal - dateInitial) / (1000 * 3600 * 24);
|
408 | const getImages = (el, includeDuplicates = false) => {
|
409 | const images = [...el.getElementsByTagName('img')].map(img => img.getAttribute('src'));
|
410 | return includeDuplicates ? images : [...new Set(images)];
|
411 | };
|
412 | const 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';
|
420 | const getScrollPosition = (el = window) => ({
|
421 | x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft,
|
422 | y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop
|
423 | });
|
424 | const getStyle = (el, ruleName) => getComputedStyle(el)[ruleName];
|
425 | const getType = v =>
|
426 | v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name.toLowerCase();
|
427 | const getURLParameters = url =>
|
428 | (url.match(/([^?=&]+)(=([^&]*))/g) || []).reduce(
|
429 | (a, v) => ((a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1)), a),
|
430 | {}
|
431 | );
|
432 | const 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 | }, {});
|
437 | const hammingDistance = (num1, num2) => ((num1 ^ num2).toString(2).match(/1/g) || '').length;
|
438 | const hasClass = (el, className) => el.classList.contains(className);
|
439 | const hasFlags = (...flags) =>
|
440 | flags.every(flag => process.argv.includes(/^-{1,2}/.test(flag) ? flag : '--' + flag));
|
441 | const 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 | });
|
449 | const 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 | );
|
462 | const head = arr => arr[0];
|
463 | const 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 | };
|
482 | const hide = (...el) => [...el].forEach(e => (e.style.display = 'none'));
|
483 | const 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 | };
|
490 | const 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 | };
|
498 | const httpsRedirect = () => {
|
499 | if (location.protocol !== 'https:') location.replace('https://' + location.href.split('//')[1]);
|
500 | };
|
501 | const 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 | };
|
506 | const 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 | };
|
510 | const indentString = (str, count, indent = ' ') => str.replace(/^/gm, indent.repeat(count));
|
511 | const indexOfAll = (arr, val) => arr.reduce((acc, el, i) => (el === val ? [...acc, i] : acc), []);
|
512 | const initial = arr => arr.slice(0, -1);
|
513 | const initialize2DArray = (w, h, val = null) =>
|
514 | Array.from({ length: h }).map(() => Array.from({ length: w }).fill(val));
|
515 | const initializeArrayWithRange = (end, start = 0, step = 1) =>
|
516 | Array.from({ length: Math.ceil((end - start + 1) / step) }, (v, i) => i * step + start);
|
517 | const 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 | );
|
521 | const initializeArrayWithValues = (n, val = 0) => Array(n).fill(val);
|
522 | const initializeNDArray = (val, ...args) =>
|
523 | args.length === 0
|
524 | ? val
|
525 | : Array.from({ length: args[0] }).map(() => initializeNDArray(val, ...args.slice(1)));
|
526 | const insertAfter = (el, htmlString) => el.insertAdjacentHTML('afterend', htmlString);
|
527 | const insertBefore = (el, htmlString) => el.insertAdjacentHTML('beforebegin', htmlString);
|
528 | const intersection = (a, b) => {
|
529 | const s = new Set(b);
|
530 | return a.filter(x => s.has(x));
|
531 | };
|
532 | const intersectionBy = (a, b, fn) => {
|
533 | const s = new Set(b.map(fn));
|
534 | return a.filter(x => s.has(fn(x)));
|
535 | };
|
536 | const intersectionWith = (a, b, comp) => a.filter(x => b.findIndex(y => comp(x, y)) !== -1);
|
537 | const 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 | }, {});
|
544 | const is = (type, val) => ![, null].includes(val) && val.constructor === type;
|
545 | const isAbsoluteURL = str => /^[a-z][a-z0-9+.-]*:/.test(str);
|
546 | const isAfterDate = (dateA, dateB) => dateA > dateB;
|
547 | const 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 | };
|
557 | const isArrayLike = obj => obj != null && typeof obj[Symbol.iterator] === 'function';
|
558 | const isBeforeDate = (dateA, dateB) => dateA < dateB;
|
559 | const isBoolean = val => typeof val === 'boolean';
|
560 | const isBrowser = () => ![typeof window, typeof document].includes('undefined');
|
561 | const isBrowserTabFocused = () => !document.hidden;
|
562 | const isDivisible = (dividend, divisor) => dividend % divisor === 0;
|
563 | const 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';
|
571 | const isEmpty = val => val == null || !(Object.keys(val) || val).length;
|
572 | const isEven = num => num % 2 === 0;
|
573 | const isFunction = val => typeof val === 'function';
|
574 | const isLowerCase = str => str === str.toLowerCase();
|
575 | const isNegativeZero = val => val === 0 && 1 / val === -Infinity;
|
576 | const isNil = val => val === undefined || val === null;
|
577 | const isNull = val => val === null;
|
578 | const isNumber = val => typeof val === 'number';
|
579 | const isObject = obj => obj === Object(obj);
|
580 | const isObjectLike = val => val !== null && typeof val === 'object';
|
581 | const isPlainObject = val => !!val && typeof val === 'object' && val.constructor === Object;
|
582 | const 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 | };
|
587 | const isPrimitive = val => Object(val) !== val;
|
588 | const isPromiseLike = obj =>
|
589 | obj !== null &&
|
590 | (typeof obj === 'object' || typeof obj === 'function') &&
|
591 | typeof obj.then === 'function';
|
592 | const isReadableStream = val =>
|
593 | val !== null &&
|
594 | typeof val === 'object' &&
|
595 | typeof val.pipe === 'function' &&
|
596 | typeof val._read === 'function' &&
|
597 | typeof val._readableState === 'object';
|
598 | const isSameDate = (dateA, dateB) => dateA.toISOString() === dateB.toISOString();
|
599 | const 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 | };
|
607 | const isStream = val => val !== null && typeof val === 'object' && typeof val.pipe === 'function';
|
608 | const isString = val => typeof val === 'string';
|
609 | const isSymbol = val => typeof val === 'symbol';
|
610 | const isTravisCI = () => 'TRAVIS' in process.env && 'CI' in process.env;
|
611 | const isUndefined = val => val === undefined;
|
612 | const isUpperCase = str => str === str.toUpperCase();
|
613 | const isValidJSON = str => {
|
614 | try {
|
615 | JSON.parse(str);
|
616 | return true;
|
617 | } catch (e) {
|
618 | return false;
|
619 | }
|
620 | };
|
621 | const isWritableStream = val =>
|
622 | val !== null &&
|
623 | typeof val === 'object' &&
|
624 | typeof val.pipe === 'function' &&
|
625 | typeof val._write === 'function' &&
|
626 | typeof val._writableState === 'object';
|
627 | const 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 | );
|
637 | const last = arr => arr[arr.length - 1];
|
638 | const 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 | };
|
643 | const longestItem = (...vals) => vals.reduce((a, x) => (x.length > a.length ? x : a));
|
644 | const lowercaseKeys = obj =>
|
645 | Object.keys(obj).reduce((acc, key) => {
|
646 | acc[key.toLowerCase()] = obj[key];
|
647 | return acc;
|
648 | }, {});
|
649 | const 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 | };
|
659 | const mapKeys = (obj, fn) =>
|
660 | Object.keys(obj).reduce((acc, k) => {
|
661 | acc[fn(obj[k], k, obj)] = obj[k];
|
662 | return acc;
|
663 | }, {});
|
664 | const mapObject = (arr, fn) =>
|
665 | (a => (
|
666 | (a = [arr, arr.map(fn)]), a[0].reduce((acc, val, ind) => ((acc[val] = a[1][ind]), acc), {})
|
667 | ))();
|
668 | const mapString = (str, fn) =>
|
669 | str
|
670 | .split('')
|
671 | .map((c, i) => fn(c, i, str))
|
672 | .join('');
|
673 | const mapValues = (obj, fn) =>
|
674 | Object.keys(obj).reduce((acc, k) => {
|
675 | acc[k] = fn(obj[k], k, obj);
|
676 | return acc;
|
677 | }, {});
|
678 | const mask = (cc, num = 4, mask = '*') => `${cc}`.slice(-num).padStart(`${cc}`.length, mask);
|
679 | const matches = (obj, source) =>
|
680 | Object.keys(source).every(key => obj.hasOwnProperty(key) && obj[key] === source[key]);
|
681 | const 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 | );
|
688 | const maxBy = (arr, fn) => Math.max(...arr.map(typeof fn === 'function' ? fn : val => val[fn]));
|
689 | const maxDate = (...dates) => new Date(Math.max.apply(null, ...dates));
|
690 | const maxN = (arr, n = 1) => [...arr].sort((a, b) => b - a).slice(0, n);
|
691 | const 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 | };
|
696 | const 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 | };
|
704 | const 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 | );
|
713 | const minBy = (arr, fn) => Math.min(...arr.map(typeof fn === 'function' ? fn : val => val[fn]));
|
714 | const minDate = (...dates) => new Date(Math.min.apply(null, ...dates));
|
715 | const minN = (arr, n = 1) => [...arr].sort((a, b) => a - b).slice(0, n);
|
716 | const 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 | };
|
724 | const negate = func => (...args) => !func(...args);
|
725 | const nest = (items, id = null, link = 'parent_id') =>
|
726 | items
|
727 | .filter(item => item[link] === id)
|
728 | .map(item => ({ ...item, children: nest(items, item.id) }));
|
729 | const nodeListToArray = nodeList => [...nodeList];
|
730 | const none = (arr, fn = Boolean) => !arr.some(fn);
|
731 | const nthArg = n => (...args) => args.slice(n)[0];
|
732 | const nthElement = (arr, n = 0) => (n === -1 ? arr.slice(n) : arr.slice(n, n + 1))[0];
|
733 | const objectFromPairs = arr => arr.reduce((a, [key, val]) => ((a[key] = val), a), {});
|
734 | const objectToPairs = obj => Object.keys(obj).map(k => [k, obj[k]]);
|
735 | const 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 | };
|
753 | const off = (el, evt, fn, opts = false) => el.removeEventListener(evt, fn, opts);
|
754 | const offset = (arr, offset) => [...arr.slice(offset), ...arr.slice(0, offset)];
|
755 | const omit = (obj, arr) =>
|
756 | Object.keys(obj)
|
757 | .filter(k => !arr.includes(k))
|
758 | .reduce((acc, key) => ((acc[key] = obj[key]), acc), {});
|
759 | const omitBy = (obj, fn) =>
|
760 | Object.keys(obj)
|
761 | .filter(k => !fn(obj[k], k))
|
762 | .reduce((acc, key) => ((acc[key] = obj[key]), acc), {});
|
763 | const 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 | };
|
768 | const 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 | };
|
782 | const 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 | };
|
790 | const 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 | );
|
800 | const over = (...fns) => (...args) => fns.map(fn => fn.apply(null, args));
|
801 | const overArgs = (fn, transforms) => (...args) => fn(...args.map((val, i) => transforms[i](val)));
|
802 | const pad = (str, length, char = ' ') =>
|
803 | str.padStart((str.length + length) / 2, char).padEnd(length, char);
|
804 | const palindrome = str => {
|
805 | const s = str.toLowerCase().replace(/[\W_]/g, '');
|
806 | return s === [...s].reverse().join('');
|
807 | };
|
808 | const 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 | }, {});
|
816 | const partial = (fn, ...partials) => (...args) => fn(...partials, ...args);
|
817 | const partialRight = (fn, ...partials) => (...args) => fn(...args, ...partials);
|
818 | const 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 | );
|
826 | const percentile = (arr, val) =>
|
827 | (100 * arr.reduce((acc, v) => acc + (v < val ? 1 : 0) + (v === val ? 0.5 : 0), 0)) / arr.length;
|
828 | const 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 | };
|
838 | const pick = (obj, arr) =>
|
839 | arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {});
|
840 | const pickBy = (obj, fn) =>
|
841 | Object.keys(obj)
|
842 | .filter(k => fn(obj[k], k))
|
843 | .reduce((acc, key) => ((acc[key] = obj[key]), acc), {});
|
844 | const pipeAsyncFunctions = (...fns) => arg => fns.reduce((p, f) => p.then(f), Promise.resolve(arg));
|
845 | const pipeFunctions = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args)));
|
846 | const 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 | };
|
852 | const powerset = arr => arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]);
|
853 | const 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 | };
|
861 | const 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 | };
|
868 | const 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 | };
|
875 | const promisify = func => (...args) =>
|
876 | new Promise((resolve, reject) =>
|
877 | func(...args, (err, result) => (err ? reject(err) : resolve(result)))
|
878 | );
|
879 | const 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 | };
|
885 | const 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 | };
|
894 | const 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 | };
|
902 | const 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 | };
|
911 | const radsToDegrees = rad => (rad * 180.0) / Math.PI;
|
912 | const randomHexColorCode = () => {
|
913 | let n = (Math.random() * 0xfffff * 1000000).toString(16);
|
914 | return '#' + n.slice(0, 6);
|
915 | };
|
916 | const randomIntArrayInRange = (min, max, n = 1) =>
|
917 | Array.from({ length: n }, () => Math.floor(Math.random() * (max - min + 1)) + min);
|
918 | const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
|
919 | const randomNumberInRange = (min, max) => Math.random() * (max - min) + min;
|
920 | const readFileLines = filename =>
|
921 | fs
|
922 | .readFileSync(filename)
|
923 | .toString('UTF8')
|
924 | .split('\n');
|
925 | const rearg = (fn, indexes) => (...args) => fn(...indexes.map(i => args[i]));
|
926 | const 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 | };
|
946 | const redirect = (url, asLink = true) =>
|
947 | asLink ? (window.location.href = url) : window.location.replace(url);
|
948 | const reduceSuccessive = (arr, fn, acc) =>
|
949 | arr.reduce((res, val, i, arr) => (res.push(fn(res.slice(-1)[0], val, i, arr)), res), [acc]);
|
950 | const reduceWhich = (arr, comparator = (a, b) => a - b) =>
|
951 | arr.reduce((a, b) => (comparator(a, b) >= 0 ? b : a));
|
952 | const 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 | );
|
959 | const reject = (pred, array) => array.filter((...args) => !pred(...args));
|
960 | const 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 | : [];
|
967 | const removeNonASCII = str => str.replace(/[^\x20-\x7E]/g, '');
|
968 | const renameKeys = (keysMap, obj) =>
|
969 | Object.keys(obj).reduce(
|
970 | (acc, key) => ({
|
971 | ...acc,
|
972 | ...{ [keysMap[key] || key]: obj[key] }
|
973 | }),
|
974 | {}
|
975 | );
|
976 | const reverseString = str => [...str].reverse().join('');
|
977 | const round = (n, decimals = 0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`);
|
978 | const 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 | };
|
993 | const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve());
|
994 | const sample = arr => arr[Math.floor(Math.random() * arr.length)];
|
995 | const 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 | };
|
1003 | const 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 | };
|
1010 | const 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 | };
|
1018 | const serializeCookie = (name, val) => `${encodeURIComponent(name)}=${encodeURIComponent(val)}`;
|
1019 | const setStyle = (el, ruleName, val) => (el.style[ruleName] = val);
|
1020 | const shallowClone = obj => Object.assign({}, obj);
|
1021 | const shank = (arr, index = 0, delCount = 0, ...elements) =>
|
1022 | arr
|
1023 | .slice(0, index)
|
1024 | .concat(elements)
|
1025 | .concat(arr.slice(index + delCount));
|
1026 | const show = (...el) => [...el].forEach(e => (e.style.display = ''));
|
1027 | const 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 | };
|
1035 | const similarity = (arr, values) => arr.filter(v => values.includes(v));
|
1036 | const 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;
|
1044 | const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
|
1045 | const smoothScroll = element =>
|
1046 | document.querySelector(element).scrollIntoView({
|
1047 | behavior: 'smooth'
|
1048 | });
|
1049 | const sortCharactersInString = str => [...str].sort((a, b) => a.localeCompare(b)).join('');
|
1050 | const 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 | };
|
1055 | const 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 | };
|
1061 | const 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 | };
|
1066 | const 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 | };
|
1075 | const splitLines = str => str.split(/\r?\n/);
|
1076 | const spreadOver = fn => argsArr => fn(...argsArr);
|
1077 | const 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);
|
1082 | const 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 | };
|
1089 | const 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 | };
|
1099 | const stripHTMLTags = str => str.replace(/<[^>]*>/g, '');
|
1100 | const sum = (...arr) => [...arr].reduce((acc, val) => acc + val, 0);
|
1101 | const sumBy = (arr, fn) =>
|
1102 | arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0);
|
1103 | const 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);
|
1108 | const 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 | };
|
1113 | const 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 | };
|
1118 | const 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 | ];
|
1122 | const tail = arr => (arr.length > 1 ? arr.slice(1) : arr);
|
1123 | const take = (arr, n = 1) => arr.slice(0, n);
|
1124 | const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length);
|
1125 | const takeRightWhile = (arr, func) =>
|
1126 | arr.reduceRight((acc, el) => (func(el) ? acc : [el, ...acc]), []);
|
1127 | const takeWhile = (arr, func) => {
|
1128 | for (const [i, val] of arr.entries()) if (func(val)) return arr.slice(0, i);
|
1129 | return arr;
|
1130 | };
|
1131 | const 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 | };
|
1151 | const timeTaken = callback => {
|
1152 | console.time('timeTaken');
|
1153 | const r = callback();
|
1154 | console.timeEnd('timeTaken');
|
1155 | return r;
|
1156 | };
|
1157 | const times = (n, fn, context = undefined) => {
|
1158 | let i = 0;
|
1159 | while (fn.call(context, i) !== false && ++i < n) {}
|
1160 | };
|
1161 | const 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 | };
|
1170 | const toCurrency = (n, curr, LanguageFormat = undefined) =>
|
1171 | Intl.NumberFormat(LanguageFormat, { style: 'currency', currency: curr }).format(n);
|
1172 | const toDecimalMark = num => num.toLocaleString('en-US');
|
1173 | const toHash = (object, key) =>
|
1174 | Array.prototype.reduce.call(
|
1175 | object,
|
1176 | (acc, data, index) => ((acc[!key ? index : data[key]] = data), acc),
|
1177 | {}
|
1178 | );
|
1179 | const 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('-');
|
1185 | const 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 | };
|
1195 | const toSafeInteger = num =>
|
1196 | Math.round(Math.max(Math.min(num, Number.MAX_SAFE_INTEGER), Number.MIN_SAFE_INTEGER));
|
1197 | const 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('_');
|
1203 | const 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(' ');
|
1208 | const toggleClass = (el, className) => el.classList.toggle(className);
|
1209 | const 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 | };
|
1217 | const transform = (obj, fn, acc) => Object.keys(obj).reduce((a, k) => fn(a, obj[k], k, obj), acc);
|
1218 | const triggerEvent = (el, eventType, detail) =>
|
1219 | el.dispatchEvent(new CustomEvent(eventType, { detail }));
|
1220 | const truncateString = (str, num) =>
|
1221 | str.length > num ? str.slice(0, num > 3 ? num - 3 : num) + '...' : str;
|
1222 | const truthCheckCollection = (collection, pre) => collection.every(obj => obj[pre]);
|
1223 | const unary = fn => val => fn(val);
|
1224 | const 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 | };
|
1229 | const unescapeHTML = str =>
|
1230 | str.replace(
|
1231 | /&|<|>|'|"/g,
|
1232 | tag =>
|
1233 | ({
|
1234 | '&': '&',
|
1235 | '<': '<',
|
1236 | '>': '>',
|
1237 | ''': "'",
|
1238 | '"': '"'
|
1239 | }[tag] || tag)
|
1240 | );
|
1241 | const 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 | }, {});
|
1257 | const unfold = (fn, seed) => {
|
1258 | let result = [],
|
1259 | val = [null, seed];
|
1260 | while ((val = fn(val[1]))) result.push(val[0]);
|
1261 | return result;
|
1262 | };
|
1263 | const union = (a, b) => Array.from(new Set([...a, ...b]));
|
1264 | const 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 | };
|
1268 | const unionWith = (a, b, comp) =>
|
1269 | Array.from(new Set([...a, ...b.filter(x => a.findIndex(y => comp(x, y)) === -1)]));
|
1270 | const uniqueElements = arr => [...new Set(arr)];
|
1271 | const uniqueElementsBy = (arr, fn) =>
|
1272 | arr.reduce((acc, v) => {
|
1273 | if (!acc.some(x => fn(v, x))) acc.push(v);
|
1274 | return acc;
|
1275 | }, []);
|
1276 | const uniqueElementsByRight = (arr, fn) =>
|
1277 | arr.reduceRight((acc, v) => {
|
1278 | if (!acc.some(x => fn(v, x))) acc.push(v);
|
1279 | return acc;
|
1280 | }, []);
|
1281 | const uniqueSymmetricDifference = (a, b) => [
|
1282 | ...new Set([...a.filter(v => !b.includes(v)), ...b.filter(v => !a.includes(v))])
|
1283 | ];
|
1284 | const untildify = str => str.replace(/^~($|\/|\\)/, `${require('os').homedir()}$1`);
|
1285 | const 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 | );
|
1292 | const 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));
|
1301 | const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n;
|
1302 | const when = (pred, whenTrue) => x => (pred(x) ? whenTrue(x) : x);
|
1303 | const without = (arr, ...args) => arr.filter(v => !args.includes(v));
|
1304 | const words = (str, pattern = /[^a-zA-Z-]+/) => str.split(pattern).filter(Boolean);
|
1305 | const xProd = (a, b) => a.reduce((acc, x) => acc.concat(b.map(y => [x, y])), []);
|
1306 | const yesNo = (val, def = false) =>
|
1307 | /^(y|yes)$/i.test(val) ? true : /^(n|no)$/i.test(val) ? false : def;
|
1308 | const 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 | };
|
1314 | const zipObject = (props, values) =>
|
1315 | props.reduce((obj, prop, index) => ((obj[prop] = values[index]), obj), {});
|
1316 | const 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 |
|
1324 | export { 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 |