diff --git a/dist/_30s.es5.js b/dist/_30s.es5.js
new file mode 100644
index 000000000..a798209c9
--- /dev/null
+++ b/dist/_30s.es5.js
@@ -0,0 +1,1101 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ (global._30s = factory());
+}(this, (function () { 'use strict';
+
+var anagrams = function anagrams(str) {
+ if (str.length <= 2) return str.length === 2 ? [str, str[1] + str[0]] : [str];
+ return str.split('').reduce(function (acc, letter, i) {
+ return acc.concat(anagrams(str.slice(0, i) + str.slice(i + 1)).map(function (val) {
+ return letter + val;
+ }));
+ }, []);
+};
+
+var arrayToHtmlList = function arrayToHtmlList(arr, listID) {
+ return arr.map(function (item) {
+ return document.querySelector('#' + listID).innerHTML += '
' + item + '';
+ });
+};
+
+var average = function average() {
+ var _ref;
+
+ var nums = (_ref = []).concat.apply(_ref, arguments);
+ return nums.reduce(function (acc, val) {
+ return acc + val;
+ }, 0) / nums.length;
+};
+
+var bottomVisible = function bottomVisible() {
+ return document.documentElement.clientHeight + window.scrollY >= (document.documentElement.scrollHeight || document.documentElement.clientHeight);
+};
+
+var byteSize = function byteSize(str) {
+ return new Blob([str]).size;
+};
+
+var call = function call(key) {
+ for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
+ args[_key - 1] = arguments[_key];
+ }
+
+ return function (context) {
+ return context[key].apply(context, args);
+ };
+};
+
+function _toArray(arr) { return Array.isArray(arr) ? arr : Array.from(arr); }
+
+var capitalize = function capitalize(_ref) {
+ var _ref2 = _toArray(_ref),
+ first = _ref2[0],
+ rest = _ref2.slice(1);
+
+ var lowerRest = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
+ return first.toUpperCase() + (lowerRest ? rest.join('').toLowerCase() : rest.join(''));
+};
+
+var capitalizeEveryWord = function capitalizeEveryWord(str) {
+ return str.replace(/\b[a-z]/g, function (char) {
+ return char.toUpperCase();
+ });
+};
+
+var chainAsync = function chainAsync(fns) {
+ var curr = 0;
+ var next = function next() {
+ return fns[curr++](next);
+ };
+ next();
+};
+
+var chunk = function chunk(arr, size) {
+ return Array.from({ length: Math.ceil(arr.length / size) }, function (v, i) {
+ return arr.slice(i * size, i * size + size);
+ });
+};
+
+var clampNumber = function clampNumber(num, a, b) {
+ return Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b));
+};
+
+var cleanObj = function cleanObj(obj) {
+ var keysToKeep = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
+ var childIndicator = arguments[2];
+
+ Object.keys(obj).forEach(function (key) {
+ if (key === childIndicator) {
+ cleanObj(obj[key], keysToKeep, childIndicator);
+ } else if (!keysToKeep.includes(key)) {
+ delete obj[key];
+ }
+ });
+ return obj;
+};
+
+var coalesce = function coalesce() {
+ for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
+ args[_key] = arguments[_key];
+ }
+
+ return args.find(function (_) {
+ return ![undefined, null].includes(_);
+ });
+};
+
+var coalesceFactory = function coalesceFactory(valid) {
+ return function () {
+ for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
+ args[_key] = arguments[_key];
+ }
+
+ return args.find(valid);
+ };
+};
+
+var collatz = function collatz(n) {
+ return n % 2 == 0 ? n / 2 : 3 * n + 1;
+};
+
+var collectInto = function collectInto(fn) {
+ return function () {
+ for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
+ args[_key] = arguments[_key];
+ }
+
+ return fn(args);
+ };
+};
+
+var compact = function compact(arr) {
+ return arr.filter(Boolean);
+};
+
+var compose = function compose() {
+ for (var _len = arguments.length, fns = Array(_len), _key = 0; _key < _len; _key++) {
+ fns[_key] = arguments[_key];
+ }
+
+ return fns.reduce(function (f, g) {
+ return function () {
+ return f(g.apply(undefined, arguments));
+ };
+ });
+};
+
+var countOccurrences = function countOccurrences(arr, value) {
+ return arr.reduce(function (a, v) {
+ return v === value ? a + 1 : a + 0;
+ }, 0);
+};
+
+var countVowels = function countVowels(str) {
+ return (str.match(/[aeiou]/gi) || []).length;
+};
+
+var currentURL = function currentURL() {
+ return window.location.href;
+};
+
+var curry = function curry(fn) {
+ for (var _len = arguments.length, args = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
+ args[_key - 2] = arguments[_key];
+ }
+
+ var arity = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : fn.length;
+ return arity <= args.length ? fn.apply(undefined, args) : curry.bind.apply(curry, [null, fn, arity].concat(args));
+};
+
+function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
+
+var deepFlatten = function deepFlatten(arr) {
+ var _ref;
+
+ return (_ref = []).concat.apply(_ref, _toConsumableArray(arr.map(function (v) {
+ return Array.isArray(v) ? deepFlatten(v) : v;
+ })));
+};
+
+var detectDeviceType = function detectDeviceType() {
+ return (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ? 'Mobile' : 'Desktop'
+ );
+};
+
+var difference = function difference(a, b) {
+ var s = new Set(b);
+ return a.filter(function (x) {
+ return !s.has(x);
+ });
+};
+
+var differenceWith = function differenceWith(arr, val, comp) {
+ return arr.filter(function (a) {
+ return !val.find(function (b) {
+ return comp(a, b);
+ });
+ });
+};
+
+function _toConsumableArray$1(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
+
+var digitize = function digitize(n) {
+ return [].concat(_toConsumableArray$1('' + n)).map(function (i) {
+ return parseInt(i);
+ });
+};
+
+var distance = function distance(x0, y0, x1, y1) {
+ return Math.hypot(x1 - x0, y1 - y0);
+};
+
+function _toConsumableArray$2(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
+
+var distinctValuesOfArray = function distinctValuesOfArray(arr) {
+ return [].concat(_toConsumableArray$2(new Set(arr)));
+};
+
+var dropElements = function dropElements(arr, func) {
+ while (arr.length > 0 && !func(arr[0])) {
+ arr = arr.slice(1);
+ }return arr;
+};
+
+var dropRight = function dropRight(arr) {
+ var n = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
+ return arr.slice(0, -n);
+};
+
+var elementIsVisibleInViewport = function elementIsVisibleInViewport(el) {
+ var partiallyVisible = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
+
+ var _el$getBoundingClient = el.getBoundingClientRect(),
+ top = _el$getBoundingClient.top,
+ left = _el$getBoundingClient.left,
+ bottom = _el$getBoundingClient.bottom,
+ right = _el$getBoundingClient.right;
+
+ var _window = window,
+ innerHeight = _window.innerHeight,
+ innerWidth = _window.innerWidth;
+
+ return partiallyVisible ? (top > 0 && top < innerHeight || bottom > 0 && bottom < innerHeight) && (left > 0 && left < innerWidth || right > 0 && right < innerWidth) : top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth;
+};
+
+var escapeHTML = function escapeHTML(str) {
+ return str.replace(/[&<>'"]/g, function (tag) {
+ return {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ "'": ''',
+ '"': '"'
+ }[tag] || tag;
+ });
+};
+
+var escapeRegExp = function escapeRegExp(str) {
+ return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+};
+
+var everyNth = function everyNth(arr, nth) {
+ return arr.filter(function (e, i) {
+ return i % nth === nth - 1;
+ });
+};
+
+var extendHex = function extendHex(shortHex) {
+ return '#' + shortHex.slice(shortHex.startsWith('#') ? 1 : 0).split('').map(function (x) {
+ return x + x;
+ }).join('');
+};
+
+var factorial = function factorial(n) {
+ return n < 0 ? function () {
+ throw new TypeError('Negative numbers are not allowed!');
+ }() : n <= 1 ? 1 : n * factorial(n - 1);
+};
+
+var fibonacci = function fibonacci(n) {
+ return Array.from({ length: n }).reduce(function (acc, val, i) {
+ return acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i);
+ }, []);
+};
+
+var fibonacciCountUntilNum = function fibonacciCountUntilNum(num) {
+ return Math.ceil(Math.log(num * Math.sqrt(5) + 1 / 2) / Math.log((Math.sqrt(5) + 1) / 2));
+};
+
+var fibonacciUntilNum = function fibonacciUntilNum(num) {
+ var n = Math.ceil(Math.log(num * Math.sqrt(5) + 1 / 2) / Math.log((Math.sqrt(5) + 1) / 2));
+ return Array.from({ length: n }).reduce(function (acc, val, i) {
+ return acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i);
+ }, []);
+};
+
+var filterNonUnique = function filterNonUnique(arr) {
+ return arr.filter(function (i) {
+ return arr.indexOf(i) === arr.lastIndexOf(i);
+ });
+};
+
+function _toConsumableArray$3(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
+
+var flatten = function flatten(arr) {
+ var _ref;
+
+ return (_ref = []).concat.apply(_ref, _toConsumableArray$3(arr));
+};
+
+var flattenDepth = function flattenDepth(arr) {
+ var depth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
+ return depth != 1 ? arr.reduce(function (a, v) {
+ return a.concat(Array.isArray(v) ? flattenDepth(v, depth - 1) : v);
+ }, []) : arr.reduce(function (a, v) {
+ return a.concat(v);
+ }, []);
+};
+
+var flip = function flip(fn) {
+ return function () {
+ for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
+ args[_key] = arguments[_key];
+ }
+
+ return fn.apply(undefined, [args.pop()].concat(args));
+ };
+};
+
+var fromCamelCase = function fromCamelCase(str) {
+ var separator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '_';
+ return str.replace(/([a-z\d])([A-Z])/g, '$1' + separator + '$2').replace(/([A-Z]+)([A-Z][a-z\d]+)/g, '$1' + separator + '$2').toLowerCase();
+};
+
+var functionName = function functionName(fn) {
+ return console.debug(fn.name), fn;
+};
+
+var gcd = function gcd() {
+ var _ref;
+
+ var data = (_ref = []).concat.apply(_ref, arguments);
+ var helperGcd = function helperGcd(x, y) {
+ return !y ? x : gcd(y, x % y);
+ };
+ return data.reduce(function (a, b) {
+ return helperGcd(a, b);
+ });
+};
+
+var getDaysDiffBetweenDates = function getDaysDiffBetweenDates(dateInitial, dateFinal) {
+ return (dateFinal - dateInitial) / (1000 * 3600 * 24);
+};
+
+var getScrollPosition = function getScrollPosition() {
+ var el = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : window;
+ return {
+ x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft,
+ y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop
+ };
+};
+
+var getStyle = function getStyle(el, ruleName) {
+ return getComputedStyle(el)[ruleName];
+};
+
+var getType = function getType(v) {
+ return v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name.toLowerCase();
+};
+
+var getURLParameters = function getURLParameters(url) {
+ return url.match(/([^?=&]+)(=([^&]*))/g).reduce(function (a, v) {
+ return a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1), a;
+ }, {});
+};
+
+var groupBy = function groupBy(arr, func) {
+ return arr.map(typeof func === 'function' ? func : function (val) {
+ return val[func];
+ }).reduce(function (acc, val, i) {
+ acc[val] = (acc[val] || []).concat(arr[i]);
+ return acc;
+ }, {});
+};
+
+var hammingDistance = function hammingDistance(num1, num2) {
+ return ((num1 ^ num2).toString(2).match(/1/g) || '').length;
+};
+
+var hasClass = function hasClass(el, className) {
+ return el.classList.contains(className);
+};
+
+var head = function head(arr) {
+ return arr[0];
+};
+
+function _toConsumableArray$4(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
+
+var hexToRGB = function hexToRGB(hex) {
+ var alpha = false,
+ h = hex.slice(hex.startsWith('#') ? 1 : 0);
+ if (h.length === 3) h = [].concat(_toConsumableArray$4(h)).map(function (x) {
+ return x + x;
+ }).join('');else if (h.length === 8) alpha = true;
+ h = parseInt(h, 16);
+ return 'rgb' + (alpha ? 'a' : '') + '(' + (h >>> (alpha ? 24 : 16)) + ', ' + ((h & (alpha ? 0x00ff0000 : 0x00ff00)) >>> (alpha ? 16 : 8)) + ', ' + ((h & (alpha ? 0x0000ff00 : 0x0000ff)) >>> (alpha ? 8 : 0)) + (alpha ? ', ' + (h & 0x000000ff) : '') + ')';
+};
+
+var hide = function hide() {
+ for (var _len = arguments.length, el = Array(_len), _key = 0; _key < _len; _key++) {
+ el[_key] = arguments[_key];
+ }
+
+ return [].concat(el).forEach(function (e) {
+ return e.style.display = 'none';
+ });
+};
+
+var httpsRedirect = function httpsRedirect() {
+ if (location.protocol !== 'https:') location.replace('https://' + location.href.split('//')[1]);
+};
+
+var initial = function initial(arr) {
+ return arr.slice(0, -1);
+};
+
+var initialize2DArray = function initialize2DArray(w, h) {
+ var val = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
+ return Array(h).fill().map(function () {
+ return Array(w).fill(val);
+ });
+};
+
+var initializeArrayWithRange = function initializeArrayWithRange(end) {
+ var start = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
+ return Array.from({ length: end + 1 - start }).map(function (v, i) {
+ return i + start;
+ });
+};
+
+var initializeArrayWithValues = function initializeArrayWithValues(n) {
+ var value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
+ return Array(n).fill(value);
+};
+
+var inRange = function inRange(n, start) {
+ var end = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
+
+ if (end && start > end) end = [start, start = end][0];
+ return end == null ? n >= 0 && n < start : n >= start && n < end;
+};
+
+var intersection = function intersection(a, b) {
+ var s = new Set(b);
+ return a.filter(function (x) {
+ return s.has(x);
+ });
+};
+
+var isArmstrongNumber = function isArmstrongNumber(digits) {
+ return function (arr) {
+ return arr.reduce(function (a, d) {
+ return a + Math.pow(parseInt(d), arr.length);
+ }, 0) == digits;
+ }((digits + '').split(''));
+};
+
+var isArray = function isArray(val) {
+ return !!val && Array.isArray(val);
+};
+
+var isBoolean = function isBoolean(val) {
+ return typeof val === 'boolean';
+};
+
+var isDivisible = function isDivisible(dividend, divisor) {
+ return dividend % divisor === 0;
+};
+
+var isEven = function isEven(num) {
+ return num % 2 === 0;
+};
+
+var isFunction = function isFunction(val) {
+ return val && typeof val === 'function';
+};
+
+var isNumber = function isNumber(val) {
+ return typeof val === 'number';
+};
+
+var isPrime = function isPrime(num) {
+ var boundary = Math.floor(Math.sqrt(num));
+ for (var i = 2; i * i <= boundary; i++) {
+ if (num % i == 0) return false;
+ }return num >= 2;
+};
+
+var isString = function isString(val) {
+ return typeof val === 'string';
+};
+
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
+
+var isSymbol = function isSymbol(val) {
+ return (typeof val === 'undefined' ? 'undefined' : _typeof(val)) === 'symbol';
+};
+
+var JSONToDate = function JSONToDate(arr) {
+ var dt = new Date(parseInt(arr.toString().substr(6)));
+ return dt.getDate() + "/" + (dt.getMonth() + 1) + "/" + dt.getFullYear();
+};
+
+var fs = typeof require !== "undefined" && require('fs');
+var JSONToFile = function JSONToFile(obj, filename) {
+ return fs.writeFile(filename + ".json", JSON.stringify(obj, null, 2));
+};
+
+var last = function last(arr) {
+ return arr[arr.length - 1];
+};
+
+var lcm = function lcm() {
+ var _ref;
+
+ var gcd = function gcd(x, y) {
+ return !y ? x : gcd(y, x % y);
+ };
+ var _lcm = function _lcm(x, y) {
+ return x * y / gcd(x, y);
+ };
+ return (_ref = []).concat.apply(_ref, arguments).reduce(function (a, b) {
+ return _lcm(a, b);
+ });
+};
+
+var lowercaseKeys = function lowercaseKeys(obj) {
+ return Object.keys(obj).reduce(function (acc, key) {
+ acc[key.toLowerCase()] = obj[key];
+ return acc;
+ }, {});
+};
+
+var mapObject = function mapObject(arr, fn) {
+ return function (a) {
+ return a = [arr, arr.map(fn)], a[0].reduce(function (acc, val, ind) {
+ return acc[val] = a[1][ind], acc;
+ }, {});
+ }();
+};
+
+function _toConsumableArray$5(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
+
+var max = function max() {
+ var _ref;
+
+ return Math.max.apply(Math, _toConsumableArray$5((_ref = []).concat.apply(_ref, arguments)));
+};
+
+function _toConsumableArray$6(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
+
+var median = function median(arr) {
+ var mid = Math.floor(arr.length / 2),
+ nums = [].concat(_toConsumableArray$6(arr)).sort(function (a, b) {
+ return a - b;
+ });
+ return arr.length % 2 !== 0 ? nums[mid] : (nums[mid - 1] + nums[mid]) / 2;
+};
+
+function _toConsumableArray$7(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
+
+var min = function min(arr) {
+ var _ref;
+
+ return Math.min.apply(Math, _toConsumableArray$7((_ref = []).concat.apply(_ref, _toConsumableArray$7(arr))));
+};
+
+var negate = function negate(func) {
+ return function () {
+ return !func.apply(undefined, arguments);
+ };
+};
+
+var nthElement = function nthElement(arr) {
+ var n = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
+ return (n > 0 ? arr.slice(n, n + 1) : arr.slice(n))[0];
+};
+
+var objectFromPairs = function objectFromPairs(arr) {
+ return arr.reduce(function (a, v) {
+ return a[v[0]] = v[1], a;
+ }, {});
+};
+
+var objectToPairs = function objectToPairs(obj) {
+ return Object.keys(obj).map(function (k) {
+ return [k, obj[k]];
+ });
+};
+
+var onUserInputChange = function onUserInputChange(callback) {
+ var type = 'mouse',
+ lastTime = 0;
+ var mousemoveHandler = function mousemoveHandler() {
+ var now = performance.now();
+ if (now - lastTime < 20) type = 'mouse', callback(type), document.removeEventListener('mousemove', mousemoveHandler);
+ lastTime = now;
+ };
+ document.addEventListener('touchstart', function () {
+ if (type === 'touch') return;
+ type = 'touch', callback(type), document.addEventListener('mousemove', mousemoveHandler);
+ });
+};
+
+var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
+
+function _toConsumableArray$8(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
+
+var orderBy = function orderBy(arr, props, orders) {
+ return [].concat(_toConsumableArray$8(arr)).sort(function (a, b) {
+ return props.reduce(function (acc, prop, i) {
+ if (acc === 0) {
+ var _ref = orders && orders[i] === 'desc' ? [b[prop], a[prop]] : [a[prop], b[prop]],
+ _ref2 = _slicedToArray(_ref, 2),
+ p1 = _ref2[0],
+ p2 = _ref2[1];
+
+ acc = p1 > p2 ? 1 : p1 < p2 ? -1 : 0;
+ }
+ return acc;
+ }, 0);
+ });
+};
+
+var palindrome = function palindrome(str) {
+ var s = str.toLowerCase().replace(/[\W_]/g, '');
+ return s === s.split('').reverse().join('');
+};
+
+var percentile = function percentile(arr, val) {
+ return 100 * arr.reduce(function (acc, v) {
+ return acc + (v < val ? 1 : 0) + (v === val ? 0.5 : 0);
+ }, 0) / arr.length;
+};
+
+var pick = function pick(obj, arr) {
+ return arr.reduce(function (acc, curr) {
+ return curr in obj && (acc[curr] = obj[curr]), acc;
+ }, {});
+};
+
+var pipeFunctions = function pipeFunctions() {
+ for (var _len = arguments.length, fns = Array(_len), _key = 0; _key < _len; _key++) {
+ fns[_key] = arguments[_key];
+ }
+
+ return fns.reduce(function (f, g) {
+ return function () {
+ return g(f.apply(undefined, arguments));
+ };
+ });
+};
+
+var powerset = function powerset(arr) {
+ return arr.reduce(function (a, v) {
+ return a.concat(a.map(function (r) {
+ return [v].concat(r);
+ }));
+ }, [[]]);
+};
+
+var primes = function primes(num) {
+ var arr = Array.from({ length: num - 1 }).map(function (x, i) {
+ return i + 2;
+ }),
+ sqroot = Math.floor(Math.sqrt(num)),
+ numsTillSqroot = Array.from({ length: sqroot - 1 }).map(function (x, i) {
+ return i + 2;
+ });
+ numsTillSqroot.forEach(function (x) {
+ return arr = arr.filter(function (y) {
+ return y % x !== 0 || y == x;
+ });
+ });
+ return arr;
+};
+
+var promisify = function promisify(func) {
+ return function () {
+ for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
+ args[_key] = arguments[_key];
+ }
+
+ return new Promise(function (resolve, reject) {
+ return func.apply(undefined, args.concat([function (err, result) {
+ return err ? reject(err) : resolve(result);
+ }]));
+ });
+ };
+};
+
+var pull = function pull(arr) {
+ for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
+ args[_key - 1] = arguments[_key];
+ }
+
+ var argState = Array.isArray(args[0]) ? args[0] : args;
+ var pulled = arr.filter(function (v, i) {
+ return !argState.includes(v);
+ });
+ arr.length = 0;
+ pulled.forEach(function (v) {
+ return arr.push(v);
+ });
+};
+
+var pullAtIndex = function pullAtIndex(arr, pullArr) {
+ var removed = [];
+ var pulled = arr.map(function (v, i) {
+ return pullArr.includes(i) ? removed.push(v) : v;
+ }).filter(function (v, i) {
+ return !pullArr.includes(i);
+ });
+ arr.length = 0;
+ pulled.forEach(function (v) {
+ return arr.push(v);
+ });
+ return removed;
+};
+
+var pullAtValue = function pullAtValue(arr, pullArr) {
+ var removed = [],
+ pushToRemove = arr.forEach(function (v, i) {
+ return pullArr.includes(v) ? removed.push(v) : v;
+ }),
+ mutateTo = arr.filter(function (v, i) {
+ return !pullArr.includes(v);
+ });
+ arr.length = 0;
+ mutateTo.forEach(function (v) {
+ return arr.push(v);
+ });
+ return removed;
+};
+
+function _toConsumableArray$9(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
+
+function _toArray$1(arr) { return Array.isArray(arr) ? arr : Array.from(arr); }
+
+var quickSort = function quickSort(_ref, desc) {
+ var _ref2 = _toArray$1(_ref),
+ n = _ref2[0],
+ nums = _ref2.slice(1);
+
+ return isNaN(n) ? [] : [].concat(_toConsumableArray$9(quickSort(nums.filter(function (v) {
+ return desc ? v > n : v <= n;
+ }), desc)), [n], _toConsumableArray$9(quickSort(nums.filter(function (v) {
+ return !desc ? v > n : v <= n;
+ }), desc)));
+};
+
+var randomHexColorCode = function randomHexColorCode() {
+ var n = (Math.random() * 0xfffff | 0).toString(16);
+ return '#' + (n.length !== 6 ? (Math.random() * 0xf | 0).toString(16) + n : n);
+};
+
+var randomIntegerInRange = function randomIntegerInRange(min, max) {
+ return Math.floor(Math.random() * (max - min + 1)) + min;
+};
+
+var randomNumberInRange = function randomNumberInRange(min, max) {
+ return Math.random() * (max - min) + min;
+};
+
+var fs$1 = typeof require !== "undefined" && require('fs');
+var readFileLines = function readFileLines(filename) {
+ return fs$1.readFileSync(filename).toString('UTF8').split('\n');
+};
+
+var redirect = function redirect(url) {
+ var asLink = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
+ return asLink ? window.location.href = url : window.location.replace(url);
+};
+
+var remove = function remove(arr, func) {
+ return Array.isArray(arr) ? arr.filter(func).reduce(function (acc, val) {
+ arr.splice(arr.indexOf(val), 1);
+ return acc.concat(val);
+ }, []) : [];
+};
+
+var repeatString = function repeatString() {
+ var str = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
+ var num = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2;
+
+ return num >= 0 ? str.repeat(num) : str;
+};
+
+var reverseString = function reverseString(str) {
+ return str.split('').reverse().join('');
+};
+
+var RGBToHex = function RGBToHex(r, g, b) {
+ return ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0');
+};
+
+var round = function round(n) {
+ var decimals = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
+ return Number(Math.round(n + "e" + decimals) + "e-" + decimals);
+};
+
+var runPromisesInSeries = function runPromisesInSeries(ps) {
+ return ps.reduce(function (p, next) {
+ return p.then(next);
+ }, Promise.resolve());
+};
+
+var sample = function sample(arr) {
+ return arr[Math.floor(Math.random() * arr.length)];
+};
+
+var scrollToTop = function scrollToTop() {
+ var c = document.documentElement.scrollTop || document.body.scrollTop;
+ if (c > 0) {
+ window.requestAnimationFrame(scrollToTop);
+ window.scrollTo(0, c - c / 8);
+ }
+};
+
+var sdbm = function sdbm(str) {
+ var arr = str.split('');
+ return arr.reduce(function (hashCode, currentVal) {
+ return hashCode = currentVal.charCodeAt(0) + (hashCode << 6) + (hashCode << 16) - hashCode;
+ }, 0);
+};
+
+var select = function select(from, selector) {
+ return selector.split('.').reduce(function (prev, cur) {
+ return prev && prev[cur];
+ }, from);
+};
+
+var setStyle = function setStyle(el, ruleName, value) {
+ return el.style[ruleName] = value;
+};
+
+var shallowClone = function shallowClone(obj) {
+ return Object.assign({}, obj);
+};
+
+var show = function show() {
+ for (var _len = arguments.length, el = Array(_len), _key = 0; _key < _len; _key++) {
+ el[_key] = arguments[_key];
+ }
+
+ return [].concat(el).forEach(function (e) {
+ return e.style.display = '';
+ });
+};
+
+function _toArray$2(arr) { return Array.isArray(arr) ? arr : Array.from(arr); }
+
+var shuffle = function shuffle(_ref) {
+ var _ref2 = _toArray$2(_ref),
+ arr = _ref2.slice(0);
+
+ var m = arr.length;
+ while (m) {
+ var i = Math.floor(Math.random() * m--);
+ var _ref3 = [arr[i], arr[m]];
+ arr[m] = _ref3[0];
+ arr[i] = _ref3[1];
+ }
+ return arr;
+};
+
+var similarity = function similarity(arr, values) {
+ return arr.filter(function (v) {
+ return values.includes(v);
+ });
+};
+
+var sleep = function sleep(ms) {
+ return new Promise(function (resolve) {
+ return setTimeout(resolve, ms);
+ });
+};
+
+var sortCharactersInString = function sortCharactersInString(str) {
+ return str.split('').sort(function (a, b) {
+ return a.localeCompare(b);
+ }).join('');
+};
+
+var speechSynthesis = function speechSynthesis(message) {
+ var msg = new SpeechSynthesisUtterance(message);
+ msg.voice = window.speechSynthesis.getVoices()[0];
+ window.speechSynthesis.speak(msg);
+};
+
+var splitLines = function splitLines(str) {
+ return str.split(/\r?\n/);
+};
+
+function _toConsumableArray$10(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
+
+var spreadOver = function spreadOver(fn) {
+ return function (argsArr) {
+ return fn.apply(undefined, _toConsumableArray$10(argsArr));
+ };
+};
+
+var standardDeviation = function standardDeviation(arr) {
+ var usePopulation = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
+
+ var mean = arr.reduce(function (acc, val) {
+ return acc + val;
+ }, 0) / arr.length;
+ return Math.sqrt(arr.reduce(function (acc, val) {
+ return acc.concat(Math.pow(val - mean, 2));
+ }, []).reduce(function (acc, val) {
+ return acc + val;
+ }, 0) / (arr.length - (usePopulation ? 0 : 1)));
+};
+
+var sum = function sum() {
+ var _ref;
+
+ return (_ref = []).concat.apply(_ref, arguments).reduce(function (acc, val) {
+ return acc + val;
+ }, 0);
+};
+
+function _toConsumableArray$11(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
+
+var symmetricDifference = function symmetricDifference(a, b) {
+ var sA = new Set(a),
+ sB = new Set(b);
+ return [].concat(_toConsumableArray$11(a.filter(function (x) {
+ return !sB.has(x);
+ })), _toConsumableArray$11(b.filter(function (x) {
+ return !sA.has(x);
+ })));
+};
+
+var tail = function tail(arr) {
+ return arr.length > 1 ? arr.slice(1) : arr;
+};
+
+var take = function take(arr) {
+ var n = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
+ return arr.slice(0, n);
+};
+
+var takeRight = function takeRight(arr) {
+ var n = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
+ return arr.slice(arr.length - n, arr.length);
+};
+
+var timeTaken = function timeTaken(callback) {
+ console.time('timeTaken');
+ var r = callback();
+ console.timeEnd('timeTaken');
+ return r;
+};
+
+var toCamelCase = function toCamelCase(str) {
+ var s = str && str.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g).map(function (x) {
+ return x.slice(0, 1).toUpperCase() + x.slice(1).toLowerCase();
+ }).join('');
+ return s.slice(0, 1).toLowerCase() + s.slice(1);
+};
+
+var toDecimalMark = function toDecimalMark(num) {
+ return num.toLocaleString('en-US');
+};
+
+var toEnglishDate = function toEnglishDate(time) {
+ try {
+ return new Date(time).toISOString().split('T')[0].replace(/-/g, '/');
+ } catch (e) {}
+};
+
+var toggleClass = function toggleClass(el, className) {
+ return el.classList.toggle(className);
+};
+
+var toKebabCase = function toKebabCase(str) {
+ return str && str.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g).map(function (x) {
+ return x.toLowerCase();
+ }).join('-');
+};
+
+var tomorrow = function tomorrow() {
+ return new Date(new Date().getTime() + 86400000).toISOString().split('T')[0];
+};
+
+var toOrdinalSuffix = function toOrdinalSuffix(num) {
+ var int = parseInt(num),
+ digits = [int % 10, int % 100],
+ ordinals = ['st', 'nd', 'rd', 'th'],
+ oPattern = [1, 2, 3, 4],
+ tPattern = [11, 12, 13, 14, 15, 16, 17, 18, 19];
+ return oPattern.includes(digits[0]) && !tPattern.includes(digits[1]) ? int + ordinals[digits[0] - 1] : int + ordinals[3];
+};
+
+var toSnakeCase = function toSnakeCase(str) {
+ str && str.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g).map(function (x) {
+ return x.toLowerCase();
+ }).join('_');
+};
+
+var truncateString = function truncateString(str, num) {
+ return str.length > num ? str.slice(0, num > 3 ? num - 3 : num) + '...' : str;
+};
+
+var truthCheckCollection = function truthCheckCollection(collection, pre) {
+ return collection.every(function (obj) {
+ return obj[pre];
+ });
+};
+
+var unescapeHTML = function unescapeHTML(str) {
+ return str.replace(/&|<|>|'|"/g, function (tag) {
+ return {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ ''': "'",
+ '"': '"'
+ }[tag] || tag;
+ });
+};
+
+function _toConsumableArray$12(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
+
+var union = function union(a, b) {
+ return Array.from(new Set([].concat(_toConsumableArray$12(a), _toConsumableArray$12(b))));
+};
+
+var UUIDGeneratorBrowser = function UUIDGeneratorBrowser() {
+ return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, function (c) {
+ return (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16);
+ });
+};
+
+var crypto$1 = typeof require !== "undefined" && require('crypto');
+var UUIDGeneratorNode = function UUIDGeneratorNode() {
+ return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, function (c) {
+ return (c ^ crypto$1.randomBytes(1)[0] & 15 >> c / 4).toString(16);
+ });
+};
+
+var validateNumber = function validateNumber(n) {
+ return !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n;
+};
+
+var without = function without(arr) {
+ for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
+ args[_key - 1] = arguments[_key];
+ }
+
+ return arr.filter(function (v) {
+ return !args.includes(v);
+ });
+};
+
+var words = function words(str) {
+ var pattern = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : /[^a-zA-Z-]+/;
+ return str.split(pattern).filter(Boolean);
+};
+
+function _toConsumableArray$13(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
+
+var zip = function zip() {
+ for (var _len = arguments.length, arrays = Array(_len), _key = 0; _key < _len; _key++) {
+ arrays[_key] = arguments[_key];
+ }
+
+ var maxLength = Math.max.apply(Math, _toConsumableArray$13(arrays.map(function (x) {
+ return x.length;
+ })));
+ return Array.from({ length: maxLength }).map(function (_, i) {
+ return Array.from({ length: arrays.length }, function (_, k) {
+ return arrays[k][i];
+ });
+ });
+};
+
+var zipObject = function zipObject(props, values) {
+ return props.reduce(function (obj, prop, index) {
+ return obj[prop] = values[index], obj;
+ }, {});
+};
+
+var imports = { anagrams: anagrams, arrayToHtmlList: arrayToHtmlList, average: average, bottomVisible: bottomVisible, byteSize: byteSize, call: call, capitalize: capitalize, capitalizeEveryWord: capitalizeEveryWord, chainAsync: chainAsync, chunk: chunk, clampNumber: clampNumber, cleanObj: cleanObj, coalesce: coalesce, coalesceFactory: coalesceFactory, collatz: collatz, collectInto: collectInto, compact: compact, compose: compose, countOccurrences: countOccurrences, countVowels: countVowels, currentURL: currentURL, curry: curry, deepFlatten: deepFlatten, detectDeviceType: detectDeviceType, difference: difference, differenceWith: differenceWith, digitize: digitize, distance: distance, distinctValuesOfArray: distinctValuesOfArray, dropElements: dropElements, dropRight: dropRight, elementIsVisibleInViewport: elementIsVisibleInViewport, escapeHTML: escapeHTML, escapeRegExp: escapeRegExp, everyNth: everyNth, extendHex: extendHex, factorial: factorial, fibonacci: fibonacci, fibonacciCountUntilNum: fibonacciCountUntilNum, fibonacciUntilNum: fibonacciUntilNum, filterNonUnique: filterNonUnique, flatten: flatten, flattenDepth: flattenDepth, flip: flip, fromCamelCase: fromCamelCase, functionName: functionName, gcd: gcd, getDaysDiffBetweenDates: getDaysDiffBetweenDates, getScrollPosition: getScrollPosition, getStyle: getStyle, getType: getType, getURLParameters: getURLParameters, groupBy: groupBy, hammingDistance: hammingDistance, hasClass: hasClass, head: head, hexToRGB: hexToRGB, hide: hide, httpsRedirect: httpsRedirect, initial: initial, initialize2DArray: initialize2DArray, initializeArrayWithRange: initializeArrayWithRange, initializeArrayWithValues: initializeArrayWithValues, inRange: inRange, intersection: intersection, isArmstrongNumber: isArmstrongNumber, isArray: isArray, isBoolean: isBoolean, isDivisible: isDivisible, isEven: isEven, isFunction: isFunction, isNumber: isNumber, isPrime: isPrime, isString: isString, isSymbol: isSymbol, JSONToDate: JSONToDate, JSONToFile: JSONToFile, last: last, lcm: lcm, lowercaseKeys: lowercaseKeys, mapObject: mapObject, max: max, median: median, min: min, negate: negate, nthElement: nthElement, objectFromPairs: objectFromPairs, objectToPairs: objectToPairs, onUserInputChange: onUserInputChange, orderBy: orderBy, palindrome: palindrome, percentile: percentile, pick: pick, pipeFunctions: pipeFunctions, powerset: powerset, primes: primes, promisify: promisify, pull: pull, pullAtIndex: pullAtIndex, pullAtValue: pullAtValue, quickSort: quickSort, randomHexColorCode: randomHexColorCode, randomIntegerInRange: randomIntegerInRange, randomNumberInRange: randomNumberInRange, readFileLines: readFileLines, redirect: redirect, remove: remove, repeatString: repeatString, reverseString: reverseString, RGBToHex: RGBToHex, round: round, runPromisesInSeries: runPromisesInSeries, sample: sample, scrollToTop: scrollToTop, sdbm: sdbm, select: select, setStyle: setStyle, shallowClone: shallowClone, show: show, shuffle: shuffle, similarity: similarity, sleep: sleep, sortCharactersInString: sortCharactersInString, speechSynthesis: speechSynthesis, splitLines: splitLines, spreadOver: spreadOver, standardDeviation: standardDeviation, sum: sum, symmetricDifference: symmetricDifference, tail: tail, take: take, takeRight: takeRight, timeTaken: timeTaken, toCamelCase: toCamelCase, toDecimalMark: toDecimalMark, toEnglishDate: toEnglishDate, toggleClass: toggleClass, toKebabCase: toKebabCase, tomorrow: tomorrow, toOrdinalSuffix: toOrdinalSuffix, toSnakeCase: toSnakeCase, truncateString: truncateString, truthCheckCollection: truthCheckCollection, unescapeHTML: unescapeHTML, union: union, UUIDGeneratorBrowser: UUIDGeneratorBrowser, UUIDGeneratorNode: UUIDGeneratorNode, validateNumber: validateNumber, without: without, words: words, zip: zip, zipObject: zipObject };
+
+return imports;
+
+})));
diff --git a/dist/_30s.es5.min.js b/dist/_30s.es5.min.js
new file mode 100644
index 000000000..e5913f715
--- /dev/null
+++ b/dist/_30s.es5.min.js
@@ -0,0 +1 @@
+(function(a,b){'object'==typeof exports&&'undefined'!=typeof module?module.exports=b():'function'==typeof define&&define.amd?define(b):a._30s=b()})(this,function(){'use strict';function a(a){return Array.isArray(a)?a:Array.from(a)}function b(a){if(Array.isArray(a)){for(var b=0,c=Array(a.length);b=b.length?2===b.length?[b,b[1]+b[0]]:[b]:b.split('').reduce(function(c,d,e){return c.concat(a(b.slice(0,e)+b.slice(e+1)).map(function(a){return d+a}))},[])},arrayToHtmlList:function(a,b){return a.map(function(a){return document.querySelector('#'+b).innerHTML+=''+a+''})},average:function(){var a,b=(a=[]).concat.apply(a,arguments);return b.reduce(function(a,b){return a+b},0)/b.length},bottomVisible:function(){return document.documentElement.clientHeight+window.scrollY>=(document.documentElement.scrollHeight||document.documentElement.clientHeight)},byteSize:function(a){return new Blob([a]).size},call:function(a){for(var b=arguments.length,c=Array(1'"]/g,function(a){return{"&":'&',"<":'<',">":'>',"'":''','"':'"'}[a]||a})},escapeRegExp:function(a){return a.replace(/[.*+?^${}()|[\]\\]/g,'\\$&')},everyNth:function(a,b){return a.filter(function(a,c){return c%b==b-1})},extendHex:function(a){return'#'+a.slice(a.startsWith('#')?1:0).split('').map(function(a){return a+a}).join('')},factorial:function a(b){return 0>b?function(){throw new TypeError('Negative numbers are not allowed!')}():1>=b?1:b*a(b-1)},fibonacci:function(a){return Array.from({length:a}).reduce(function(a,b,c){return a.concat(1>>(b?24:16))+', '+((c&(b?16711680:65280))>>>(b?16:8))+', '+((c&(b?65280:255))>>>(b?8:0))+(b?', '+(255&c):'')+')'},hide:function(){for(var a=arguments.length,b=Array(a),c=0;cc&&(c=b),null==c?0<=a&&a=b&&ae-c&&(b='mouse',a(b),document.removeEventListener('mousemove',d)),c=e};document.addEventListener('touchstart',function(){'touch'==b||(b='touch',a(b),document.addEventListener('mousemove',d))})},orderBy:function(a,c,d){return[].concat(j(a)).sort(function(e,a){return c.reduce(function(b,c,f){if(0===b){var g=d&&'desc'===d[f]?[a[c],e[c]]:[e[c],a[c]],h=A(g,2),i=h[0],j=h[1];b=i>j?1:ie:a<=e}),c)),[e],k(a(f.filter(function(a){return c?a<=e:a>e}),c)))},randomHexColorCode:function(){var a=(0|1048575*Math.random()).toString(16);return'#'+(6===a.length?a:(0|15*Math.random()).toString(16)+a)},randomIntegerInRange:function(a,b){return r(Math.random()*(b-a+1))+a},randomNumberInRange:function(a,b){return Math.random()*(b-a)+a},readFileLines:function(a){return B.readFileSync(a).toString('UTF8').split('\n')},redirect:function(a){var b=1b?a.slice(0,3',"'":'\'',""":'"'}[a]||a})},union:function(c,a){return Array.from(new Set([].concat(p(c),p(a))))},UUIDGeneratorBrowser:function(){return'10000000-1000-4000-8000-100000000000'.replace(/[018]/g,function(a){return(a^crypto.getRandomValues(new Uint8Array(1))[0]&15>>a/4).toString(16)})},UUIDGeneratorNode:function(){return'10000000-1000-4000-8000-100000000000'.replace(/[018]/g,function(a){return(a^C.randomBytes(1)[0]&15>>a/4).toString(16)})},validateNumber:function(a){return!isNaN(parseFloat(a))&&isFinite(a)&&+a==a},without:function(a){for(var b=arguments.length,c=Array(1 {
+ if (str.length <= 2) return str.length === 2 ? [str, str[1] + str[0]] : [str];
+ return str
+ .split('')
+ .reduce(
+ (acc, letter, i) =>
+ acc.concat(anagrams(str.slice(0, i) + str.slice(i + 1)).map(val => letter + val)),
+ []
+ );
+};
+
+const arrayToHtmlList = (arr, listID) =>
+ arr.map(item => (document.querySelector('#' + listID).innerHTML += `${item}`));
+
+const average = (...arr) => {
+ const nums = [].concat(...arr);
+ return nums.reduce((acc, val) => acc + val, 0) / nums.length;
+};
+
+const bottomVisible = () =>
+ document.documentElement.clientHeight + window.scrollY >=
+ (document.documentElement.scrollHeight || document.documentElement.clientHeight);
+
+const byteSize = str => new Blob([str]).size;
+
+const call = (key, ...args) => context => context[key](...args);
+
+const capitalize = ([first, ...rest], lowerRest = false) =>
+ first.toUpperCase() + (lowerRest ? rest.join('').toLowerCase() : rest.join(''));
+
+const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase());
+
+const chainAsync = fns => {
+ let curr = 0;
+ const next = () => fns[curr++](next);
+ next();
+};
+
+const chunk = (arr, size) =>
+ Array.from({ length: Math.ceil(arr.length / size) }, (v, i) =>
+ arr.slice(i * size, i * size + size)
+ );
+
+const clampNumber = (num, a, b) => Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b));
+
+const cleanObj = (obj, keysToKeep = [], childIndicator) => {
+ Object.keys(obj).forEach(key => {
+ if (key === childIndicator) {
+ cleanObj(obj[key], keysToKeep, childIndicator);
+ } else if (!keysToKeep.includes(key)) {
+ delete obj[key];
+ }
+ });
+ return obj;
+};
+
+const coalesce = (...args) => args.find(_ => ![undefined, null].includes(_));
+
+const coalesceFactory = valid => (...args) => args.find(valid);
+
+const collatz = n => (n % 2 == 0 ? n / 2 : 3 * n + 1);
+
+const collectInto = fn => (...args) => fn(args);
+
+const compact = arr => arr.filter(Boolean);
+
+const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)));
+
+const countOccurrences = (arr, value) => arr.reduce((a, v) => (v === value ? a + 1 : a + 0), 0);
+
+const countVowels = str => (str.match(/[aeiou]/gi) || []).length;
+
+const currentURL = () => window.location.href;
+
+const curry = (fn, arity = fn.length, ...args) =>
+ arity <= args.length ? fn(...args) : curry.bind(null, fn, arity, ...args);
+
+const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v)));
+
+const detectDeviceType = () =>
+ /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
+ ? 'Mobile'
+ : 'Desktop';
+
+const difference = (a, b) => {
+ const s = new Set(b);
+ return a.filter(x => !s.has(x));
+};
+
+const differenceWith = (arr, val, comp) => arr.filter(a => !val.find(b => comp(a, b)));
+
+const digitize = n => [...('' + n)].map(i => parseInt(i));
+
+const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0);
+
+const distinctValuesOfArray = arr => [...new Set(arr)];
+
+const dropElements = (arr, func) => {
+ while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1);
+ return arr;
+};
+
+const dropRight = (arr, n = 1) => arr.slice(0, -n);
+
+const elementIsVisibleInViewport = (el, partiallyVisible = false) => {
+ const { top, left, bottom, right } = el.getBoundingClientRect();
+ const { innerHeight, innerWidth } = window;
+ return partiallyVisible
+ ? ((top > 0 && top < innerHeight) || (bottom > 0 && bottom < innerHeight)) &&
+ ((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth))
+ : top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth;
+};
+
+const escapeHTML = str =>
+ str.replace(
+ /[&<>'"]/g,
+ tag =>
+ ({
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ "'": ''',
+ '"': '"'
+ }[tag] || tag)
+ );
+
+const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+
+const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === nth - 1);
+
+const extendHex = shortHex =>
+ '#' +
+ shortHex
+ .slice(shortHex.startsWith('#') ? 1 : 0)
+ .split('')
+ .map(x => x + x)
+ .join('');
+
+const factorial = n =>
+ n < 0
+ ? (() => {
+ throw new TypeError('Negative numbers are not allowed!');
+ })()
+ : n <= 1 ? 1 : n * factorial(n - 1);
+
+const fibonacci = n =>
+ Array.from({ length: n }).reduce(
+ (acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i),
+ []
+ );
+
+const fibonacciCountUntilNum = num =>
+ Math.ceil(Math.log(num * Math.sqrt(5) + 1 / 2) / Math.log((Math.sqrt(5) + 1) / 2));
+
+const fibonacciUntilNum = num => {
+ let n = Math.ceil(Math.log(num * Math.sqrt(5) + 1 / 2) / Math.log((Math.sqrt(5) + 1) / 2));
+ return Array.from({ length: n }).reduce(
+ (acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i),
+ []
+ );
+};
+
+const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i));
+
+const flatten = arr => [].concat(...arr);
+
+const flattenDepth = (arr, depth = 1) =>
+ depth != 1
+ ? arr.reduce((a, v) => a.concat(Array.isArray(v) ? flattenDepth(v, depth - 1) : v), [])
+ : arr.reduce((a, v) => a.concat(v), []);
+
+const flip = fn => (...args) => fn(args.pop(), ...args);
+
+const fromCamelCase = (str, separator = '_') =>
+ str
+ .replace(/([a-z\d])([A-Z])/g, '$1' + separator + '$2')
+ .replace(/([A-Z]+)([A-Z][a-z\d]+)/g, '$1' + separator + '$2')
+ .toLowerCase();
+
+const functionName = fn => (console.debug(fn.name), fn);
+
+const gcd = (...arr) => {
+ let data = [].concat(...arr);
+ const helperGcd = (x, y) => (!y ? x : gcd(y, x % y));
+ return data.reduce((a, b) => helperGcd(a, b));
+};
+
+const getDaysDiffBetweenDates = (dateInitial, dateFinal) =>
+ (dateFinal - dateInitial) / (1000 * 3600 * 24);
+
+const getScrollPosition = (el = window) => ({
+ x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft,
+ y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop
+});
+
+const getStyle = (el, ruleName) => getComputedStyle(el)[ruleName];
+
+const getType = v =>
+ v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name.toLowerCase();
+
+const getURLParameters = url =>
+ url
+ .match(/([^?=&]+)(=([^&]*))/g)
+ .reduce((a, v) => (a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1), a), {});
+
+const groupBy = (arr, func) =>
+ arr.map(typeof func === 'function' ? func : val => val[func]).reduce((acc, val, i) => {
+ acc[val] = (acc[val] || []).concat(arr[i]);
+ return acc;
+ }, {});
+
+const hammingDistance = (num1, num2) => ((num1 ^ num2).toString(2).match(/1/g) || '').length;
+
+const hasClass = (el, className) => el.classList.contains(className);
+
+const head = arr => arr[0];
+
+const hexToRGB = hex => {
+ let alpha = false,
+ h = hex.slice(hex.startsWith('#') ? 1 : 0);
+ if (h.length === 3) h = [...h].map(x => x + x).join('');
+ else if (h.length === 8) alpha = true;
+ h = parseInt(h, 16);
+ return (
+ 'rgb' +
+ (alpha ? 'a' : '') +
+ '(' +
+ (h >>> (alpha ? 24 : 16)) +
+ ', ' +
+ ((h & (alpha ? 0x00ff0000 : 0x00ff00)) >>> (alpha ? 16 : 8)) +
+ ', ' +
+ ((h & (alpha ? 0x0000ff00 : 0x0000ff)) >>> (alpha ? 8 : 0)) +
+ (alpha ? `, ${h & 0x000000ff}` : '') +
+ ')'
+ );
+};
+
+const hide = (...el) => [...el].forEach(e => (e.style.display = 'none'));
+
+const httpsRedirect = () => {
+ if (location.protocol !== 'https:') location.replace('https://' + location.href.split('//')[1]);
+};
+
+const initial = arr => arr.slice(0, -1);
+
+const initialize2DArray = (w, h, val = null) =>
+ Array(h)
+ .fill()
+ .map(() => Array(w).fill(val));
+
+const initializeArrayWithRange = (end, start = 0) =>
+ Array.from({ length: end + 1 - start }).map((v, i) => i + start);
+
+const initializeArrayWithValues = (n, value = 0) => Array(n).fill(value);
+
+const inRange = (n, start, end = null) => {
+ if (end && start > end) end = [start, (start = end)][0];
+ return end == null ? n >= 0 && n < start : n >= start && n < end;
+};
+
+const intersection = (a, b) => {
+ const s = new Set(b);
+ return a.filter(x => s.has(x));
+};
+
+const isArmstrongNumber = digits =>
+ (arr => arr.reduce((a, d) => a + Math.pow(parseInt(d), arr.length), 0) == digits)(
+ (digits + '').split('')
+ );
+
+const isArray = val => !!val && Array.isArray(val);
+
+const isBoolean = val => typeof val === 'boolean';
+
+const isDivisible = (dividend, divisor) => dividend % divisor === 0;
+
+const isEven = num => num % 2 === 0;
+
+const isFunction = val => val && typeof val === 'function';
+
+const isNumber = val => typeof val === 'number';
+
+const isPrime = num => {
+ const boundary = Math.floor(Math.sqrt(num));
+ for (var i = 2; i * i <= boundary; i++) if (num % i == 0) return false;
+ return num >= 2;
+};
+
+const isString = val => typeof val === 'string';
+
+const isSymbol = val => typeof val === 'symbol';
+
+const JSONToDate = arr => {
+ const dt = new Date(parseInt(arr.toString().substr(6)));
+ return `${dt.getDate()}/${dt.getMonth() + 1}/${dt.getFullYear()}`;
+};
+
+const fs = typeof require !== "undefined" && require('fs');
+const JSONToFile = (obj, filename) =>
+ fs.writeFile(`${filename}.json`, JSON.stringify(obj, null, 2));
+
+const last = arr => arr[arr.length - 1];
+
+const lcm = (...arr) => {
+ const gcd = (x, y) => (!y ? x : gcd(y, x % y));
+ const _lcm = (x, y) => x * y / gcd(x, y);
+ return [].concat(...arr).reduce((a, b) => _lcm(a, b));
+};
+
+const lowercaseKeys = obj =>
+ Object.keys(obj).reduce((acc, key) => {
+ acc[key.toLowerCase()] = obj[key];
+ return acc;
+ }, {});
+
+const mapObject = (arr, fn) =>
+ (a => (
+ a = [arr, arr.map(fn)], a[0].reduce((acc, val, ind) => (acc[val] = a[1][ind], acc), {})))();
+
+const max = (...arr) => Math.max(...[].concat(...arr));
+
+const median = arr => {
+ const mid = Math.floor(arr.length / 2),
+ nums = [...arr].sort((a, b) => a - b);
+ return arr.length % 2 !== 0 ? nums[mid] : (nums[mid - 1] + nums[mid]) / 2;
+};
+
+const min = arr => Math.min(...[].concat(...arr));
+
+const negate = func => (...args) => !func(...args);
+
+const nthElement = (arr, n = 0) => (n > 0 ? arr.slice(n, n + 1) : arr.slice(n))[0];
+
+const objectFromPairs = arr => arr.reduce((a, v) => (a[v[0]] = v[1], a), {});
+
+const objectToPairs = obj => Object.keys(obj).map(k => [k, obj[k]]);
+
+const onUserInputChange = callback => {
+ let type = 'mouse',
+ lastTime = 0;
+ const mousemoveHandler = () => {
+ const now = performance.now();
+ if (now - lastTime < 20)
+ type = 'mouse', callback(type), document.removeEventListener('mousemove', mousemoveHandler);
+ lastTime = now;
+ };
+ document.addEventListener('touchstart', () => {
+ if (type === 'touch') return;
+ type = 'touch', callback(type), document.addEventListener('mousemove', mousemoveHandler);
+ });
+};
+
+const orderBy = (arr, props, orders) =>
+ [...arr].sort((a, b) =>
+ props.reduce((acc, prop, i) => {
+ if (acc === 0) {
+ const [p1, p2] = orders && orders[i] === 'desc' ? [b[prop], a[prop]] : [a[prop], b[prop]];
+ acc = p1 > p2 ? 1 : p1 < p2 ? -1 : 0;
+ }
+ return acc;
+ }, 0)
+ );
+
+const palindrome = str => {
+ const s = str.toLowerCase().replace(/[\W_]/g, '');
+ return (
+ s ===
+ s
+ .split('')
+ .reverse()
+ .join('')
+ );
+};
+
+const percentile = (arr, val) =>
+ 100 * arr.reduce((acc, v) => acc + (v < val ? 1 : 0) + (v === val ? 0.5 : 0), 0) / arr.length;
+
+const pick = (obj, arr) =>
+ arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {});
+
+const pipeFunctions = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args)));
+
+const powerset = arr => arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]);
+
+const primes = num => {
+ let arr = Array.from({ length: num - 1 }).map((x, i) => i + 2),
+ sqroot = Math.floor(Math.sqrt(num)),
+ numsTillSqroot = Array.from({ length: sqroot - 1 }).map((x, i) => i + 2);
+ numsTillSqroot.forEach(x => (arr = arr.filter(y => y % x !== 0 || y == x)));
+ return arr;
+};
+
+const promisify = func => (...args) =>
+ new Promise((resolve, reject) =>
+ func(...args, (err, result) => (err ? reject(err) : resolve(result)))
+ );
+
+const pull = (arr, ...args) => {
+ let argState = Array.isArray(args[0]) ? args[0] : args;
+ let pulled = arr.filter((v, i) => !argState.includes(v));
+ arr.length = 0;
+ pulled.forEach(v => arr.push(v));
+};
+
+const pullAtIndex = (arr, pullArr) => {
+ let removed = [];
+ let pulled = arr
+ .map((v, i) => (pullArr.includes(i) ? removed.push(v) : v))
+ .filter((v, i) => !pullArr.includes(i));
+ arr.length = 0;
+ pulled.forEach(v => arr.push(v));
+ return removed;
+};
+
+const pullAtValue = (arr, pullArr) => {
+ let removed = [],
+ pushToRemove = arr.forEach((v, i) => (pullArr.includes(v) ? removed.push(v) : v)),
+ mutateTo = arr.filter((v, i) => !pullArr.includes(v));
+ arr.length = 0;
+ mutateTo.forEach(v => arr.push(v));
+ return removed;
+};
+
+const quickSort = ([n, ...nums], desc) =>
+ isNaN(n)
+ ? []
+ : [
+ ...quickSort(nums.filter(v => (desc ? v > n : v <= n)), desc),
+ n,
+ ...quickSort(nums.filter(v => (!desc ? v > n : v <= n)), desc)
+ ];
+
+const randomHexColorCode = () => {
+ let n = ((Math.random() * 0xfffff) | 0).toString(16);
+ return '#' + (n.length !== 6 ? ((Math.random() * 0xf) | 0).toString(16) + n : n);
+};
+
+const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
+
+const randomNumberInRange = (min, max) => Math.random() * (max - min) + min;
+
+const fs$1 = typeof require !== "undefined" && require('fs');
+const readFileLines = filename =>
+ fs$1
+ .readFileSync(filename)
+ .toString('UTF8')
+ .split('\n');
+
+const redirect = (url, asLink = true) =>
+ asLink ? (window.location.href = url) : window.location.replace(url);
+
+const remove = (arr, func) =>
+ Array.isArray(arr)
+ ? arr.filter(func).reduce((acc, val) => {
+ arr.splice(arr.indexOf(val), 1);
+ return acc.concat(val);
+ }, [])
+ : [];
+
+const repeatString = (str = '', num = 2) => {
+ return num >= 0 ? str.repeat(num) : str;
+};
+
+const reverseString = str =>
+ str
+ .split('')
+ .reverse()
+ .join('');
+
+const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0');
+
+const round = (n, decimals = 0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`);
+
+const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve());
+
+const sample = arr => arr[Math.floor(Math.random() * arr.length)];
+
+const scrollToTop = () => {
+ const c = document.documentElement.scrollTop || document.body.scrollTop;
+ if (c > 0) {
+ window.requestAnimationFrame(scrollToTop);
+ window.scrollTo(0, c - c / 8);
+ }
+};
+
+const sdbm = str => {
+ let arr = str.split('');
+ return arr.reduce(
+ (hashCode, currentVal) =>
+ (hashCode = currentVal.charCodeAt(0) + (hashCode << 6) + (hashCode << 16) - hashCode),
+ 0
+ );
+};
+
+const select = (from, selector) =>
+ selector.split('.').reduce((prev, cur) => prev && prev[cur], from);
+
+const setStyle = (el, ruleName, value) => (el.style[ruleName] = value);
+
+const shallowClone = obj => Object.assign({}, obj);
+
+const show = (...el) => [...el].forEach(e => (e.style.display = ''));
+
+const shuffle = ([...arr]) => {
+ let m = arr.length;
+ while (m) {
+ const i = Math.floor(Math.random() * m--);
+ [arr[m], arr[i]] = [arr[i], arr[m]];
+ }
+ return arr;
+};
+
+const similarity = (arr, values) => arr.filter(v => values.includes(v));
+
+const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
+
+const sortCharactersInString = str =>
+ str
+ .split('')
+ .sort((a, b) => a.localeCompare(b))
+ .join('');
+
+const speechSynthesis = message => {
+ const msg = new SpeechSynthesisUtterance(message);
+ msg.voice = window.speechSynthesis.getVoices()[0];
+ window.speechSynthesis.speak(msg);
+};
+
+const splitLines = str => str.split(/\r?\n/);
+
+const spreadOver = fn => argsArr => fn(...argsArr);
+
+const standardDeviation = (arr, usePopulation = false) => {
+ const mean = arr.reduce((acc, val) => acc + val, 0) / arr.length;
+ return Math.sqrt(
+ arr
+ .reduce((acc, val) => acc.concat(Math.pow(val - mean, 2)), [])
+ .reduce((acc, val) => acc + val, 0) /
+ (arr.length - (usePopulation ? 0 : 1))
+ );
+};
+
+const sum = (...arr) => [].concat(...arr).reduce((acc, val) => acc + val, 0);
+
+const symmetricDifference = (a, b) => {
+ const sA = new Set(a),
+ sB = new Set(b);
+ return [...a.filter(x => !sB.has(x)), ...b.filter(x => !sA.has(x))];
+};
+
+const tail = arr => (arr.length > 1 ? arr.slice(1) : arr);
+
+const take = (arr, n = 1) => arr.slice(0, n);
+
+const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length);
+
+const timeTaken = callback => {
+ console.time('timeTaken');
+ const r = callback();
+ console.timeEnd('timeTaken');
+ return r;
+};
+
+const toCamelCase = str => {
+ let s =
+ str &&
+ str
+ .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
+ .map(x => x.slice(0, 1).toUpperCase() + x.slice(1).toLowerCase())
+ .join('');
+ return s.slice(0, 1).toLowerCase() + s.slice(1);
+};
+
+const toDecimalMark = num => num.toLocaleString('en-US');
+
+const toEnglishDate = time => {
+ try {
+ return new Date(time)
+ .toISOString()
+ .split('T')[0]
+ .replace(/-/g, '/');
+ } catch (e) {}
+};
+
+const toggleClass = (el, className) => el.classList.toggle(className);
+
+const toKebabCase = str =>
+ str &&
+ str
+ .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
+ .map(x => x.toLowerCase())
+ .join('-');
+
+const tomorrow = () => new Date(new Date().getTime() + 86400000).toISOString().split('T')[0];
+
+const toOrdinalSuffix = num => {
+ const int = parseInt(num),
+ digits = [int % 10, int % 100],
+ ordinals = ['st', 'nd', 'rd', 'th'],
+ oPattern = [1, 2, 3, 4],
+ tPattern = [11, 12, 13, 14, 15, 16, 17, 18, 19];
+ return oPattern.includes(digits[0]) && !tPattern.includes(digits[1])
+ ? int + ordinals[digits[0] - 1]
+ : int + ordinals[3];
+};
+
+const toSnakeCase = str => {
+ str &&
+ str
+ .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
+ .map(x => x.toLowerCase())
+ .join('_');
+};
+
+const truncateString = (str, num) =>
+ str.length > num ? str.slice(0, num > 3 ? num - 3 : num) + '...' : str;
+
+const truthCheckCollection = (collection, pre) => collection.every(obj => obj[pre]);
+
+const unescapeHTML = str =>
+ str.replace(
+ /&|<|>|'|"/g,
+ tag =>
+ ({
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ ''': "'",
+ '"': '"'
+ }[tag] || tag)
+ );
+
+const union = (a, b) => Array.from(new Set([...a, ...b]));
+
+const UUIDGeneratorBrowser = () =>
+ ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
+ (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16)
+ );
+
+const crypto$1 = typeof require !== "undefined" && require('crypto');
+const UUIDGeneratorNode = () =>
+ ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
+ (c ^ (crypto$1.randomBytes(1)[0] & (15 >> (c / 4)))).toString(16)
+ );
+
+const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n;
+
+const without = (arr, ...args) => arr.filter(v => !args.includes(v));
+
+const words = (str, pattern = /[^a-zA-Z-]+/) => str.split(pattern).filter(Boolean);
+
+const zip = (...arrays) => {
+ const maxLength = Math.max(...arrays.map(x => x.length));
+ return Array.from({ length: maxLength }).map((_, i) => {
+ return Array.from({ length: arrays.length }, (_, k) => arrays[k][i]);
+ });
+};
+
+const zipObject = (props, values) =>
+ props.reduce((obj, prop, index) => (obj[prop] = values[index], obj), {});
+
+var imports = {anagrams,arrayToHtmlList,average,bottomVisible,byteSize,call,capitalize,capitalizeEveryWord,chainAsync,chunk,clampNumber,cleanObj,coalesce,coalesceFactory,collatz,collectInto,compact,compose,countOccurrences,countVowels,currentURL,curry,deepFlatten,detectDeviceType,difference,differenceWith,digitize,distance,distinctValuesOfArray,dropElements,dropRight,elementIsVisibleInViewport,escapeHTML,escapeRegExp,everyNth,extendHex,factorial,fibonacci,fibonacciCountUntilNum,fibonacciUntilNum,filterNonUnique,flatten,flattenDepth,flip,fromCamelCase,functionName,gcd,getDaysDiffBetweenDates,getScrollPosition,getStyle,getType,getURLParameters,groupBy,hammingDistance,hasClass,head,hexToRGB,hide,httpsRedirect,initial,initialize2DArray,initializeArrayWithRange,initializeArrayWithValues,inRange,intersection,isArmstrongNumber,isArray,isBoolean,isDivisible,isEven,isFunction,isNumber,isPrime,isString,isSymbol,JSONToDate,JSONToFile,last,lcm,lowercaseKeys,mapObject,max,median,min,negate,nthElement,objectFromPairs,objectToPairs,onUserInputChange,orderBy,palindrome,percentile,pick,pipeFunctions,powerset,primes,promisify,pull,pullAtIndex,pullAtValue,quickSort,randomHexColorCode,randomIntegerInRange,randomNumberInRange,readFileLines,redirect,remove,repeatString,reverseString,RGBToHex,round,runPromisesInSeries,sample,scrollToTop,sdbm,select,setStyle,shallowClone,show,shuffle,similarity,sleep,sortCharactersInString,speechSynthesis,splitLines,spreadOver,standardDeviation,sum,symmetricDifference,tail,take,takeRight,timeTaken,toCamelCase,toDecimalMark,toEnglishDate,toggleClass,toKebabCase,tomorrow,toOrdinalSuffix,toSnakeCase,truncateString,truthCheckCollection,unescapeHTML,union,UUIDGeneratorBrowser,UUIDGeneratorNode,validateNumber,without,words,zip,zipObject,}
+
+export default imports;
diff --git a/dist/_30s.js b/dist/_30s.js
new file mode 100644
index 000000000..a5f06c222
--- /dev/null
+++ b/dist/_30s.js
@@ -0,0 +1,672 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ (global._30s = factory());
+}(this, (function () { 'use strict';
+
+const anagrams = str => {
+ if (str.length <= 2) return str.length === 2 ? [str, str[1] + str[0]] : [str];
+ return str
+ .split('')
+ .reduce(
+ (acc, letter, i) =>
+ acc.concat(anagrams(str.slice(0, i) + str.slice(i + 1)).map(val => letter + val)),
+ []
+ );
+};
+
+const arrayToHtmlList = (arr, listID) =>
+ arr.map(item => (document.querySelector('#' + listID).innerHTML += `${item}`));
+
+const average = (...arr) => {
+ const nums = [].concat(...arr);
+ return nums.reduce((acc, val) => acc + val, 0) / nums.length;
+};
+
+const bottomVisible = () =>
+ document.documentElement.clientHeight + window.scrollY >=
+ (document.documentElement.scrollHeight || document.documentElement.clientHeight);
+
+const byteSize = str => new Blob([str]).size;
+
+const call = (key, ...args) => context => context[key](...args);
+
+const capitalize = ([first, ...rest], lowerRest = false) =>
+ first.toUpperCase() + (lowerRest ? rest.join('').toLowerCase() : rest.join(''));
+
+const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase());
+
+const chainAsync = fns => {
+ let curr = 0;
+ const next = () => fns[curr++](next);
+ next();
+};
+
+const chunk = (arr, size) =>
+ Array.from({ length: Math.ceil(arr.length / size) }, (v, i) =>
+ arr.slice(i * size, i * size + size)
+ );
+
+const clampNumber = (num, a, b) => Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b));
+
+const cleanObj = (obj, keysToKeep = [], childIndicator) => {
+ Object.keys(obj).forEach(key => {
+ if (key === childIndicator) {
+ cleanObj(obj[key], keysToKeep, childIndicator);
+ } else if (!keysToKeep.includes(key)) {
+ delete obj[key];
+ }
+ });
+ return obj;
+};
+
+const coalesce = (...args) => args.find(_ => ![undefined, null].includes(_));
+
+const coalesceFactory = valid => (...args) => args.find(valid);
+
+const collatz = n => (n % 2 == 0 ? n / 2 : 3 * n + 1);
+
+const collectInto = fn => (...args) => fn(args);
+
+const compact = arr => arr.filter(Boolean);
+
+const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)));
+
+const countOccurrences = (arr, value) => arr.reduce((a, v) => (v === value ? a + 1 : a + 0), 0);
+
+const countVowels = str => (str.match(/[aeiou]/gi) || []).length;
+
+const currentURL = () => window.location.href;
+
+const curry = (fn, arity = fn.length, ...args) =>
+ arity <= args.length ? fn(...args) : curry.bind(null, fn, arity, ...args);
+
+const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v)));
+
+const detectDeviceType = () =>
+ /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
+ ? 'Mobile'
+ : 'Desktop';
+
+const difference = (a, b) => {
+ const s = new Set(b);
+ return a.filter(x => !s.has(x));
+};
+
+const differenceWith = (arr, val, comp) => arr.filter(a => !val.find(b => comp(a, b)));
+
+const digitize = n => [...('' + n)].map(i => parseInt(i));
+
+const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0);
+
+const distinctValuesOfArray = arr => [...new Set(arr)];
+
+const dropElements = (arr, func) => {
+ while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1);
+ return arr;
+};
+
+const dropRight = (arr, n = 1) => arr.slice(0, -n);
+
+const elementIsVisibleInViewport = (el, partiallyVisible = false) => {
+ const { top, left, bottom, right } = el.getBoundingClientRect();
+ const { innerHeight, innerWidth } = window;
+ return partiallyVisible
+ ? ((top > 0 && top < innerHeight) || (bottom > 0 && bottom < innerHeight)) &&
+ ((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth))
+ : top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth;
+};
+
+const escapeHTML = str =>
+ str.replace(
+ /[&<>'"]/g,
+ tag =>
+ ({
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ "'": ''',
+ '"': '"'
+ }[tag] || tag)
+ );
+
+const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+
+const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === nth - 1);
+
+const extendHex = shortHex =>
+ '#' +
+ shortHex
+ .slice(shortHex.startsWith('#') ? 1 : 0)
+ .split('')
+ .map(x => x + x)
+ .join('');
+
+const factorial = n =>
+ n < 0
+ ? (() => {
+ throw new TypeError('Negative numbers are not allowed!');
+ })()
+ : n <= 1 ? 1 : n * factorial(n - 1);
+
+const fibonacci = n =>
+ Array.from({ length: n }).reduce(
+ (acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i),
+ []
+ );
+
+const fibonacciCountUntilNum = num =>
+ Math.ceil(Math.log(num * Math.sqrt(5) + 1 / 2) / Math.log((Math.sqrt(5) + 1) / 2));
+
+const fibonacciUntilNum = num => {
+ let n = Math.ceil(Math.log(num * Math.sqrt(5) + 1 / 2) / Math.log((Math.sqrt(5) + 1) / 2));
+ return Array.from({ length: n }).reduce(
+ (acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i),
+ []
+ );
+};
+
+const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i));
+
+const flatten = arr => [].concat(...arr);
+
+const flattenDepth = (arr, depth = 1) =>
+ depth != 1
+ ? arr.reduce((a, v) => a.concat(Array.isArray(v) ? flattenDepth(v, depth - 1) : v), [])
+ : arr.reduce((a, v) => a.concat(v), []);
+
+const flip = fn => (...args) => fn(args.pop(), ...args);
+
+const fromCamelCase = (str, separator = '_') =>
+ str
+ .replace(/([a-z\d])([A-Z])/g, '$1' + separator + '$2')
+ .replace(/([A-Z]+)([A-Z][a-z\d]+)/g, '$1' + separator + '$2')
+ .toLowerCase();
+
+const functionName = fn => (console.debug(fn.name), fn);
+
+const gcd = (...arr) => {
+ let data = [].concat(...arr);
+ const helperGcd = (x, y) => (!y ? x : gcd(y, x % y));
+ return data.reduce((a, b) => helperGcd(a, b));
+};
+
+const getDaysDiffBetweenDates = (dateInitial, dateFinal) =>
+ (dateFinal - dateInitial) / (1000 * 3600 * 24);
+
+const getScrollPosition = (el = window) => ({
+ x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft,
+ y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop
+});
+
+const getStyle = (el, ruleName) => getComputedStyle(el)[ruleName];
+
+const getType = v =>
+ v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name.toLowerCase();
+
+const getURLParameters = url =>
+ url
+ .match(/([^?=&]+)(=([^&]*))/g)
+ .reduce((a, v) => (a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1), a), {});
+
+const groupBy = (arr, func) =>
+ arr.map(typeof func === 'function' ? func : val => val[func]).reduce((acc, val, i) => {
+ acc[val] = (acc[val] || []).concat(arr[i]);
+ return acc;
+ }, {});
+
+const hammingDistance = (num1, num2) => ((num1 ^ num2).toString(2).match(/1/g) || '').length;
+
+const hasClass = (el, className) => el.classList.contains(className);
+
+const head = arr => arr[0];
+
+const hexToRGB = hex => {
+ let alpha = false,
+ h = hex.slice(hex.startsWith('#') ? 1 : 0);
+ if (h.length === 3) h = [...h].map(x => x + x).join('');
+ else if (h.length === 8) alpha = true;
+ h = parseInt(h, 16);
+ return (
+ 'rgb' +
+ (alpha ? 'a' : '') +
+ '(' +
+ (h >>> (alpha ? 24 : 16)) +
+ ', ' +
+ ((h & (alpha ? 0x00ff0000 : 0x00ff00)) >>> (alpha ? 16 : 8)) +
+ ', ' +
+ ((h & (alpha ? 0x0000ff00 : 0x0000ff)) >>> (alpha ? 8 : 0)) +
+ (alpha ? `, ${h & 0x000000ff}` : '') +
+ ')'
+ );
+};
+
+const hide = (...el) => [...el].forEach(e => (e.style.display = 'none'));
+
+const httpsRedirect = () => {
+ if (location.protocol !== 'https:') location.replace('https://' + location.href.split('//')[1]);
+};
+
+const initial = arr => arr.slice(0, -1);
+
+const initialize2DArray = (w, h, val = null) =>
+ Array(h)
+ .fill()
+ .map(() => Array(w).fill(val));
+
+const initializeArrayWithRange = (end, start = 0) =>
+ Array.from({ length: end + 1 - start }).map((v, i) => i + start);
+
+const initializeArrayWithValues = (n, value = 0) => Array(n).fill(value);
+
+const inRange = (n, start, end = null) => {
+ if (end && start > end) end = [start, (start = end)][0];
+ return end == null ? n >= 0 && n < start : n >= start && n < end;
+};
+
+const intersection = (a, b) => {
+ const s = new Set(b);
+ return a.filter(x => s.has(x));
+};
+
+const isArmstrongNumber = digits =>
+ (arr => arr.reduce((a, d) => a + Math.pow(parseInt(d), arr.length), 0) == digits)(
+ (digits + '').split('')
+ );
+
+const isArray = val => !!val && Array.isArray(val);
+
+const isBoolean = val => typeof val === 'boolean';
+
+const isDivisible = (dividend, divisor) => dividend % divisor === 0;
+
+const isEven = num => num % 2 === 0;
+
+const isFunction = val => val && typeof val === 'function';
+
+const isNumber = val => typeof val === 'number';
+
+const isPrime = num => {
+ const boundary = Math.floor(Math.sqrt(num));
+ for (var i = 2; i * i <= boundary; i++) if (num % i == 0) return false;
+ return num >= 2;
+};
+
+const isString = val => typeof val === 'string';
+
+const isSymbol = val => typeof val === 'symbol';
+
+const JSONToDate = arr => {
+ const dt = new Date(parseInt(arr.toString().substr(6)));
+ return `${dt.getDate()}/${dt.getMonth() + 1}/${dt.getFullYear()}`;
+};
+
+const fs = typeof require !== "undefined" && require('fs');
+const JSONToFile = (obj, filename) =>
+ fs.writeFile(`${filename}.json`, JSON.stringify(obj, null, 2));
+
+const last = arr => arr[arr.length - 1];
+
+const lcm = (...arr) => {
+ const gcd = (x, y) => (!y ? x : gcd(y, x % y));
+ const _lcm = (x, y) => x * y / gcd(x, y);
+ return [].concat(...arr).reduce((a, b) => _lcm(a, b));
+};
+
+const lowercaseKeys = obj =>
+ Object.keys(obj).reduce((acc, key) => {
+ acc[key.toLowerCase()] = obj[key];
+ return acc;
+ }, {});
+
+const mapObject = (arr, fn) =>
+ (a => (
+ a = [arr, arr.map(fn)], a[0].reduce((acc, val, ind) => (acc[val] = a[1][ind], acc), {})))();
+
+const max = (...arr) => Math.max(...[].concat(...arr));
+
+const median = arr => {
+ const mid = Math.floor(arr.length / 2),
+ nums = [...arr].sort((a, b) => a - b);
+ return arr.length % 2 !== 0 ? nums[mid] : (nums[mid - 1] + nums[mid]) / 2;
+};
+
+const min = arr => Math.min(...[].concat(...arr));
+
+const negate = func => (...args) => !func(...args);
+
+const nthElement = (arr, n = 0) => (n > 0 ? arr.slice(n, n + 1) : arr.slice(n))[0];
+
+const objectFromPairs = arr => arr.reduce((a, v) => (a[v[0]] = v[1], a), {});
+
+const objectToPairs = obj => Object.keys(obj).map(k => [k, obj[k]]);
+
+const onUserInputChange = callback => {
+ let type = 'mouse',
+ lastTime = 0;
+ const mousemoveHandler = () => {
+ const now = performance.now();
+ if (now - lastTime < 20)
+ type = 'mouse', callback(type), document.removeEventListener('mousemove', mousemoveHandler);
+ lastTime = now;
+ };
+ document.addEventListener('touchstart', () => {
+ if (type === 'touch') return;
+ type = 'touch', callback(type), document.addEventListener('mousemove', mousemoveHandler);
+ });
+};
+
+const orderBy = (arr, props, orders) =>
+ [...arr].sort((a, b) =>
+ props.reduce((acc, prop, i) => {
+ if (acc === 0) {
+ const [p1, p2] = orders && orders[i] === 'desc' ? [b[prop], a[prop]] : [a[prop], b[prop]];
+ acc = p1 > p2 ? 1 : p1 < p2 ? -1 : 0;
+ }
+ return acc;
+ }, 0)
+ );
+
+const palindrome = str => {
+ const s = str.toLowerCase().replace(/[\W_]/g, '');
+ return (
+ s ===
+ s
+ .split('')
+ .reverse()
+ .join('')
+ );
+};
+
+const percentile = (arr, val) =>
+ 100 * arr.reduce((acc, v) => acc + (v < val ? 1 : 0) + (v === val ? 0.5 : 0), 0) / arr.length;
+
+const pick = (obj, arr) =>
+ arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {});
+
+const pipeFunctions = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args)));
+
+const powerset = arr => arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]);
+
+const primes = num => {
+ let arr = Array.from({ length: num - 1 }).map((x, i) => i + 2),
+ sqroot = Math.floor(Math.sqrt(num)),
+ numsTillSqroot = Array.from({ length: sqroot - 1 }).map((x, i) => i + 2);
+ numsTillSqroot.forEach(x => (arr = arr.filter(y => y % x !== 0 || y == x)));
+ return arr;
+};
+
+const promisify = func => (...args) =>
+ new Promise((resolve, reject) =>
+ func(...args, (err, result) => (err ? reject(err) : resolve(result)))
+ );
+
+const pull = (arr, ...args) => {
+ let argState = Array.isArray(args[0]) ? args[0] : args;
+ let pulled = arr.filter((v, i) => !argState.includes(v));
+ arr.length = 0;
+ pulled.forEach(v => arr.push(v));
+};
+
+const pullAtIndex = (arr, pullArr) => {
+ let removed = [];
+ let pulled = arr
+ .map((v, i) => (pullArr.includes(i) ? removed.push(v) : v))
+ .filter((v, i) => !pullArr.includes(i));
+ arr.length = 0;
+ pulled.forEach(v => arr.push(v));
+ return removed;
+};
+
+const pullAtValue = (arr, pullArr) => {
+ let removed = [],
+ pushToRemove = arr.forEach((v, i) => (pullArr.includes(v) ? removed.push(v) : v)),
+ mutateTo = arr.filter((v, i) => !pullArr.includes(v));
+ arr.length = 0;
+ mutateTo.forEach(v => arr.push(v));
+ return removed;
+};
+
+const quickSort = ([n, ...nums], desc) =>
+ isNaN(n)
+ ? []
+ : [
+ ...quickSort(nums.filter(v => (desc ? v > n : v <= n)), desc),
+ n,
+ ...quickSort(nums.filter(v => (!desc ? v > n : v <= n)), desc)
+ ];
+
+const randomHexColorCode = () => {
+ let n = ((Math.random() * 0xfffff) | 0).toString(16);
+ return '#' + (n.length !== 6 ? ((Math.random() * 0xf) | 0).toString(16) + n : n);
+};
+
+const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
+
+const randomNumberInRange = (min, max) => Math.random() * (max - min) + min;
+
+const fs$1 = typeof require !== "undefined" && require('fs');
+const readFileLines = filename =>
+ fs$1
+ .readFileSync(filename)
+ .toString('UTF8')
+ .split('\n');
+
+const redirect = (url, asLink = true) =>
+ asLink ? (window.location.href = url) : window.location.replace(url);
+
+const remove = (arr, func) =>
+ Array.isArray(arr)
+ ? arr.filter(func).reduce((acc, val) => {
+ arr.splice(arr.indexOf(val), 1);
+ return acc.concat(val);
+ }, [])
+ : [];
+
+const repeatString = (str = '', num = 2) => {
+ return num >= 0 ? str.repeat(num) : str;
+};
+
+const reverseString = str =>
+ str
+ .split('')
+ .reverse()
+ .join('');
+
+const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0');
+
+const round = (n, decimals = 0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`);
+
+const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve());
+
+const sample = arr => arr[Math.floor(Math.random() * arr.length)];
+
+const scrollToTop = () => {
+ const c = document.documentElement.scrollTop || document.body.scrollTop;
+ if (c > 0) {
+ window.requestAnimationFrame(scrollToTop);
+ window.scrollTo(0, c - c / 8);
+ }
+};
+
+const sdbm = str => {
+ let arr = str.split('');
+ return arr.reduce(
+ (hashCode, currentVal) =>
+ (hashCode = currentVal.charCodeAt(0) + (hashCode << 6) + (hashCode << 16) - hashCode),
+ 0
+ );
+};
+
+const select = (from, selector) =>
+ selector.split('.').reduce((prev, cur) => prev && prev[cur], from);
+
+const setStyle = (el, ruleName, value) => (el.style[ruleName] = value);
+
+const shallowClone = obj => Object.assign({}, obj);
+
+const show = (...el) => [...el].forEach(e => (e.style.display = ''));
+
+const shuffle = ([...arr]) => {
+ let m = arr.length;
+ while (m) {
+ const i = Math.floor(Math.random() * m--);
+ [arr[m], arr[i]] = [arr[i], arr[m]];
+ }
+ return arr;
+};
+
+const similarity = (arr, values) => arr.filter(v => values.includes(v));
+
+const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
+
+const sortCharactersInString = str =>
+ str
+ .split('')
+ .sort((a, b) => a.localeCompare(b))
+ .join('');
+
+const speechSynthesis = message => {
+ const msg = new SpeechSynthesisUtterance(message);
+ msg.voice = window.speechSynthesis.getVoices()[0];
+ window.speechSynthesis.speak(msg);
+};
+
+const splitLines = str => str.split(/\r?\n/);
+
+const spreadOver = fn => argsArr => fn(...argsArr);
+
+const standardDeviation = (arr, usePopulation = false) => {
+ const mean = arr.reduce((acc, val) => acc + val, 0) / arr.length;
+ return Math.sqrt(
+ arr
+ .reduce((acc, val) => acc.concat(Math.pow(val - mean, 2)), [])
+ .reduce((acc, val) => acc + val, 0) /
+ (arr.length - (usePopulation ? 0 : 1))
+ );
+};
+
+const sum = (...arr) => [].concat(...arr).reduce((acc, val) => acc + val, 0);
+
+const symmetricDifference = (a, b) => {
+ const sA = new Set(a),
+ sB = new Set(b);
+ return [...a.filter(x => !sB.has(x)), ...b.filter(x => !sA.has(x))];
+};
+
+const tail = arr => (arr.length > 1 ? arr.slice(1) : arr);
+
+const take = (arr, n = 1) => arr.slice(0, n);
+
+const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length);
+
+const timeTaken = callback => {
+ console.time('timeTaken');
+ const r = callback();
+ console.timeEnd('timeTaken');
+ return r;
+};
+
+const toCamelCase = str => {
+ let s =
+ str &&
+ str
+ .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
+ .map(x => x.slice(0, 1).toUpperCase() + x.slice(1).toLowerCase())
+ .join('');
+ return s.slice(0, 1).toLowerCase() + s.slice(1);
+};
+
+const toDecimalMark = num => num.toLocaleString('en-US');
+
+const toEnglishDate = time => {
+ try {
+ return new Date(time)
+ .toISOString()
+ .split('T')[0]
+ .replace(/-/g, '/');
+ } catch (e) {}
+};
+
+const toggleClass = (el, className) => el.classList.toggle(className);
+
+const toKebabCase = str =>
+ str &&
+ str
+ .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
+ .map(x => x.toLowerCase())
+ .join('-');
+
+const tomorrow = () => new Date(new Date().getTime() + 86400000).toISOString().split('T')[0];
+
+const toOrdinalSuffix = num => {
+ const int = parseInt(num),
+ digits = [int % 10, int % 100],
+ ordinals = ['st', 'nd', 'rd', 'th'],
+ oPattern = [1, 2, 3, 4],
+ tPattern = [11, 12, 13, 14, 15, 16, 17, 18, 19];
+ return oPattern.includes(digits[0]) && !tPattern.includes(digits[1])
+ ? int + ordinals[digits[0] - 1]
+ : int + ordinals[3];
+};
+
+const toSnakeCase = str => {
+ str &&
+ str
+ .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
+ .map(x => x.toLowerCase())
+ .join('_');
+};
+
+const truncateString = (str, num) =>
+ str.length > num ? str.slice(0, num > 3 ? num - 3 : num) + '...' : str;
+
+const truthCheckCollection = (collection, pre) => collection.every(obj => obj[pre]);
+
+const unescapeHTML = str =>
+ str.replace(
+ /&|<|>|'|"/g,
+ tag =>
+ ({
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ ''': "'",
+ '"': '"'
+ }[tag] || tag)
+ );
+
+const union = (a, b) => Array.from(new Set([...a, ...b]));
+
+const UUIDGeneratorBrowser = () =>
+ ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
+ (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16)
+ );
+
+const crypto$1 = typeof require !== "undefined" && require('crypto');
+const UUIDGeneratorNode = () =>
+ ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
+ (c ^ (crypto$1.randomBytes(1)[0] & (15 >> (c / 4)))).toString(16)
+ );
+
+const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n;
+
+const without = (arr, ...args) => arr.filter(v => !args.includes(v));
+
+const words = (str, pattern = /[^a-zA-Z-]+/) => str.split(pattern).filter(Boolean);
+
+const zip = (...arrays) => {
+ const maxLength = Math.max(...arrays.map(x => x.length));
+ return Array.from({ length: maxLength }).map((_, i) => {
+ return Array.from({ length: arrays.length }, (_, k) => arrays[k][i]);
+ });
+};
+
+const zipObject = (props, values) =>
+ props.reduce((obj, prop, index) => (obj[prop] = values[index], obj), {});
+
+var imports = {anagrams,arrayToHtmlList,average,bottomVisible,byteSize,call,capitalize,capitalizeEveryWord,chainAsync,chunk,clampNumber,cleanObj,coalesce,coalesceFactory,collatz,collectInto,compact,compose,countOccurrences,countVowels,currentURL,curry,deepFlatten,detectDeviceType,difference,differenceWith,digitize,distance,distinctValuesOfArray,dropElements,dropRight,elementIsVisibleInViewport,escapeHTML,escapeRegExp,everyNth,extendHex,factorial,fibonacci,fibonacciCountUntilNum,fibonacciUntilNum,filterNonUnique,flatten,flattenDepth,flip,fromCamelCase,functionName,gcd,getDaysDiffBetweenDates,getScrollPosition,getStyle,getType,getURLParameters,groupBy,hammingDistance,hasClass,head,hexToRGB,hide,httpsRedirect,initial,initialize2DArray,initializeArrayWithRange,initializeArrayWithValues,inRange,intersection,isArmstrongNumber,isArray,isBoolean,isDivisible,isEven,isFunction,isNumber,isPrime,isString,isSymbol,JSONToDate,JSONToFile,last,lcm,lowercaseKeys,mapObject,max,median,min,negate,nthElement,objectFromPairs,objectToPairs,onUserInputChange,orderBy,palindrome,percentile,pick,pipeFunctions,powerset,primes,promisify,pull,pullAtIndex,pullAtValue,quickSort,randomHexColorCode,randomIntegerInRange,randomNumberInRange,readFileLines,redirect,remove,repeatString,reverseString,RGBToHex,round,runPromisesInSeries,sample,scrollToTop,sdbm,select,setStyle,shallowClone,show,shuffle,similarity,sleep,sortCharactersInString,speechSynthesis,splitLines,spreadOver,standardDeviation,sum,symmetricDifference,tail,take,takeRight,timeTaken,toCamelCase,toDecimalMark,toEnglishDate,toggleClass,toKebabCase,tomorrow,toOrdinalSuffix,toSnakeCase,truncateString,truthCheckCollection,unescapeHTML,union,UUIDGeneratorBrowser,UUIDGeneratorNode,validateNumber,without,words,zip,zipObject,}
+
+return imports;
+
+})));
diff --git a/dist/_30s.min.js b/dist/_30s.min.js
new file mode 100644
index 000000000..d30867b5d
--- /dev/null
+++ b/dist/_30s.min.js
@@ -0,0 +1 @@
+(function(a,b){'object'==typeof exports&&'undefined'!=typeof module?module.exports=b():'function'==typeof define&&define.amd?define(b):a._30s=b()})(this,function(){'use strict';var a=Math.floor,b=Math.sqrt,c=Math.pow,d=Math.log,e=Math.min,f=Math.max,g=Math.ceil;const h=(a)=>2>=a.length?2===a.length?[a,a[1]+a[0]]:[a]:a.split('').reduce((b,c,d)=>b.concat(h(a.slice(0,d)+a.slice(d+1)).map((a)=>c+a)),[]),i=(a,b=[],c)=>(Object.keys(a).forEach((d)=>{d===c?i(a[d],b,c):!b.includes(d)&&delete a[d]}),a),j=(a,b=a.length,...c)=>b<=c.length?a(...c):j.bind(null,a,b,...c),k=(a)=>[].concat(...a.map((a)=>Array.isArray(a)?k(a):a)),l=(a)=>0>a?(()=>{throw new TypeError('Negative numbers are not allowed!')})():1>=a?1:a*l(a-1),m=(a,b=1)=>1==b?a.reduce((b,a)=>b.concat(a),[]):a.reduce((c,a)=>c.concat(Array.isArray(a)?m(a,b-1):a),[]),n=(...a)=>{let b=[].concat(...a);const c=(a,b)=>b?n(b,a%b):a;return b.reduce((d,a)=>c(d,a))},o='undefined'!=typeof require&&require('fs'),p=([a,...b],c)=>isNaN(a)?[]:[...p(b.filter((b)=>c?b>a:b<=a),c),a,...p(b.filter((b)=>c?b<=a:b>a),c)],q='undefined'!=typeof require&&require('fs'),r=()=>{const a=document.documentElement.scrollTop||document.body.scrollTop;0a.map((a)=>document.querySelector('#'+b).innerHTML+=`${a}`),average:(...a)=>{const b=[].concat(...a);return b.reduce((a,b)=>a+b,0)/b.length},bottomVisible:()=>document.documentElement.clientHeight+window.scrollY>=(document.documentElement.scrollHeight||document.documentElement.clientHeight),byteSize:(a)=>new Blob([a]).size,call:(a,...b)=>(c)=>c[a](...b),capitalize:([a,...b],c=!1)=>a.toUpperCase()+(c?b.join('').toLowerCase():b.join('')),capitalizeEveryWord:(a)=>a.replace(/\b[a-z]/g,(a)=>a.toUpperCase()),chainAsync:(a)=>{let b=0;const c=()=>a[b++](c);c()},chunk:(a,b)=>Array.from({length:g(a.length/b)},(c,d)=>a.slice(d*b,d*b+b)),clampNumber:(c,d,a)=>f(e(c,f(d,a)),e(d,a)),cleanObj:i,coalesce:(...a)=>a.find((a)=>![void 0,null].includes(a)),coalesceFactory:(a)=>(...b)=>b.find(a),collatz:(a)=>0==a%2?a/2:3*a+1,collectInto:(a)=>(...b)=>a(b),compact:(a)=>a.filter(Boolean),compose:(...a)=>a.reduce((a,b)=>(...c)=>a(b(...c))),countOccurrences:(a,b)=>a.reduce((c,a)=>a===b?c+1:c+0,0),countVowels:(a)=>(a.match(/[aeiou]/gi)||[]).length,currentURL:()=>window.location.href,curry:j,deepFlatten:k,detectDeviceType:()=>/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)?'Mobile':'Desktop',difference:(c,a)=>{const b=new Set(a);return c.filter((a)=>!b.has(a))},differenceWith:(a,b,c)=>a.filter((d)=>!b.find((a)=>c(d,a))),digitize:(a)=>[...(''+a)].map((a)=>parseInt(a)),distance:(a,b,c,d)=>Math.hypot(c-a,d-b),distinctValuesOfArray:(a)=>[...new Set(a)],dropElements:(a,b)=>{for(;0a.slice(0,-b),elementIsVisibleInViewport:(a,b=!1)=>{const{top:c,left:d,bottom:e,right:f}=a.getBoundingClientRect(),{innerHeight:g,innerWidth:h}=window;return b?(0a.replace(/[&<>'"]/g,(a)=>({"&":'&',"<":'<',">":'>',"'":''','"':'"'})[a]||a),escapeRegExp:(a)=>a.replace(/[.*+?^${}()|[\]\\]/g,'\\$&'),everyNth:(a,b)=>a.filter((a,c)=>c%b==b-1),extendHex:(a)=>'#'+a.slice(a.startsWith('#')?1:0).split('').map((a)=>a+a).join(''),factorial:l,fibonacci:(a)=>Array.from({length:a}).reduce((a,b,c)=>a.concat(1g(d(2.23606797749979*a+1/2)/0.48121182505960347),fibonacciUntilNum:(a)=>{let b=g(d(2.23606797749979*a+1/2)/0.48121182505960347);return Array.from({length:b}).reduce((a,b,c)=>a.concat(1a.filter((b)=>a.indexOf(b)===a.lastIndexOf(b)),flatten:(a)=>[].concat(...a),flattenDepth:m,flip:(a)=>(...b)=>a(b.pop(),...b),fromCamelCase:(a,b='_')=>a.replace(/([a-z\d])([A-Z])/g,'$1'+b+'$2').replace(/([A-Z]+)([A-Z][a-z\d]+)/g,'$1'+b+'$2').toLowerCase(),functionName:(a)=>(console.debug(a.name),a),gcd:n,getDaysDiffBetweenDates:(a,b)=>(b-a)/86400000,getScrollPosition:(a=window)=>({x:a.pageXOffset===void 0?a.scrollLeft:a.pageXOffset,y:a.pageYOffset===void 0?a.scrollTop:a.pageYOffset}),getStyle:(a,b)=>getComputedStyle(a)[b],getType:(a)=>a===void 0?'undefined':null===a?'null':a.constructor.name.toLowerCase(),getURLParameters:(a)=>a.match(/([^?=&]+)(=([^&]*))/g).reduce((b,a)=>(b[a.slice(0,a.indexOf('='))]=a.slice(a.indexOf('=')+1),b),{}),groupBy:(a,b)=>a.map('function'==typeof b?b:(a)=>a[b]).reduce((b,c,d)=>(b[c]=(b[c]||[]).concat(a[d]),b),{}),hammingDistance:(a,b)=>((a^b).toString(2).match(/1/g)||'').length,hasClass:(a,b)=>a.classList.contains(b),head:(a)=>a[0],hexToRGB:(a)=>{let b=!1,c=a.slice(a.startsWith('#')?1:0);return 3===c.length?c=[...c].map((a)=>a+a).join(''):8===c.length&&(b=!0),c=parseInt(c,16),'rgb'+(b?'a':'')+'('+(c>>>(b?24:16))+', '+((c&(b?16711680:65280))>>>(b?16:8))+', '+((c&(b?65280:255))>>>(b?8:0))+(b?`, ${255&c}`:'')+')'},hide:(...a)=>[...a].forEach((a)=>a.style.display='none'),httpsRedirect:()=>{'https:'!==location.protocol&&location.replace('https://'+location.href.split('//')[1])},initial:(a)=>a.slice(0,-1),initialize2DArray:(a,b,c=null)=>Array(b).fill().map(()=>Array(a).fill(c)),initializeArrayWithRange:(a,b=0)=>Array.from({length:a+1-b}).map((a,c)=>c+b),initializeArrayWithValues:(a,b=0)=>Array(a).fill(b),inRange:(a,b,c=null)=>(c&&b>c&&(c=b),null==c?0<=a&&a=b&&a{const b=new Set(a);return c.filter((a)=>b.has(a))},isArmstrongNumber:(a)=>((b)=>b.reduce((e,a)=>e+c(parseInt(a),b.length),0)==a)((a+'').split('')),isArray:(a)=>!!a&&Array.isArray(a),isBoolean:(a)=>'boolean'==typeof a,isDivisible:(a,b)=>0==a%b,isEven:(a)=>0==a%2,isFunction:(a)=>a&&'function'==typeof a,isNumber:(a)=>'number'==typeof a,isPrime:(c)=>{const d=a(b(c));for(var e=2;e*e<=d;e++)if(0==c%e)return!1;return 2<=c},isString:(a)=>'string'==typeof a,isSymbol:(a)=>'symbol'==typeof a,JSONToDate:(a)=>{const b=new Date(parseInt(a.toString().substr(6)));return`${b.getDate()}/${b.getMonth()+1}/${b.getFullYear()}`},JSONToFile:(a,b)=>o.writeFile(`${b}.json`,JSON.stringify(a,null,2)),last:(a)=>a[a.length-1],lcm:(...a)=>{const b=(a,c)=>c?b(c,a%c):a,c=(a,c)=>a*c/b(a,c);return[].concat(...a).reduce((d,a)=>c(d,a))},lowercaseKeys:(a)=>Object.keys(a).reduce((b,c)=>(b[c.toLowerCase()]=a[c],b),{}),mapObject:(b,c)=>((d)=>(d=[b,b.map(c)],d[0].reduce((a,b,c)=>(a[b]=d[1][c],a),{})))(),max:(...a)=>f(...[].concat(...a)),median:(b)=>{const c=a(b.length/2),d=[...b].sort((c,a)=>c-a);return 0==b.length%2?(d[c-1]+d[c])/2:d[c]},min:(a)=>e(...[].concat(...a)),negate:(a)=>(...b)=>!a(...b),nthElement:(a,b=0)=>(0a.reduce((b,a)=>(b[a[0]]=a[1],b),{}),objectToPairs:(a)=>Object.keys(a).map((b)=>[b,a[b]]),onUserInputChange:(a)=>{let b='mouse',c=0;const d=()=>{const e=performance.now();20>e-c&&(b='mouse',a(b),document.removeEventListener('mousemove',d)),c=e};document.addEventListener('touchstart',()=>{'touch'==b||(b='touch',a(b),document.addEventListener('mousemove',d))})},orderBy:(a,c,d)=>[...a].sort((e,a)=>c.reduce((b,c,f)=>{if(0===b){const[g,h]=d&&'desc'===d[f]?[a[c],e[c]]:[e[c],a[c]];b=g>h?1:g{const b=a.toLowerCase().replace(/[\W_]/g,'');return b===b.split('').reverse().join('')},percentile:(a,b)=>100*a.reduce((a,c)=>a+(cb.reduce((b,c)=>(c in a&&(b[c]=a[c]),b),{}),pipeFunctions:(...a)=>a.reduce((a,b)=>(...c)=>b(a(...c))),powerset:(a)=>a.reduce((b,a)=>b.concat(b.map((b)=>[a].concat(b))),[[]]),primes:(c)=>{let d=Array.from({length:c-1}).map((a,b)=>b+2),e=a(b(c)),f=Array.from({length:e-1}).map((a,b)=>b+2);return f.forEach((a)=>d=d.filter((b)=>0!=b%a||b==a)),d},promisify:(a)=>(...b)=>new Promise((c,d)=>a(...b,(a,b)=>a?d(a):c(b))),pull:(a,...b)=>{let c=Array.isArray(b[0])?b[0]:b,d=a.filter((a)=>!c.includes(a));a.length=0,d.forEach((b)=>a.push(b))},pullAtIndex:(a,b)=>{let c=[],d=a.map((a,d)=>b.includes(d)?c.push(a):a).filter((a,c)=>!b.includes(c));return a.length=0,d.forEach((b)=>a.push(b)),c},pullAtValue:(a,b)=>{let c=[],d=a.forEach((a)=>b.includes(a)?c.push(a):a),e=a.filter((a)=>!b.includes(a));return a.length=0,e.forEach((b)=>a.push(b)),c},quickSort:p,randomHexColorCode:()=>{let a=(0|1048575*Math.random()).toString(16);return'#'+(6===a.length?a:(0|15*Math.random()).toString(16)+a)},randomIntegerInRange:(b,c)=>a(Math.random()*(c-b+1))+b,randomNumberInRange:(a,b)=>Math.random()*(b-a)+a,readFileLines:(a)=>q.readFileSync(a).toString('UTF8').split('\n'),redirect:(a,b=!0)=>b?window.location.href=a:window.location.replace(a),remove:(a,b)=>Array.isArray(a)?a.filter(b).reduce((b,c)=>(a.splice(a.indexOf(c),1),b.concat(c)),[]):[],repeatString:(a='',b=2)=>0<=b?a.repeat(b):a,reverseString:(a)=>a.split('').reverse().join(''),RGBToHex:(a,c,d)=>((a<<16)+(c<<8)+d).toString(16).padStart(6,'0'),round:(a,b=0)=>+`${Math.round(`${a}e${b}`)}e-${b}`,runPromisesInSeries:(a)=>a.reduce((a,b)=>a.then(b),Promise.resolve()),sample:(b)=>b[a(Math.random()*b.length)],scrollToTop:r,sdbm:(a)=>{let b=a.split('');return b.reduce((a,b)=>a=b.charCodeAt(0)+(a<<6)+(a<<16)-a,0)},select:(a,b)=>b.split('.').reduce((a,b)=>a&&a[b],a),setStyle:(a,b,c)=>a.style[b]=c,shallowClone:(a)=>Object.assign({},a),show:(...a)=>[...a].forEach((a)=>a.style.display=''),shuffle:([...b])=>{for(let c=b.length;c;){const d=a(Math.random()*c--);[b[c],b[d]]=[b[d],b[c]]}return b},similarity:(a,b)=>a.filter((a)=>b.includes(a)),sleep:(a)=>new Promise((b)=>setTimeout(b,a)),sortCharactersInString:(a)=>a.split('').sort((c,a)=>c.localeCompare(a)).join(''),speechSynthesis:(a)=>{const b=new SpeechSynthesisUtterance(a);b.voice=window.speechSynthesis.getVoices()[0],window.speechSynthesis.speak(b)},splitLines:(a)=>a.split(/\r?\n/),spreadOver:(a)=>(b)=>a(...b),standardDeviation:(a,d=!1)=>{const e=a.reduce((a,b)=>a+b,0)/a.length;return b(a.reduce((a,b)=>a.concat(c(b-e,2)),[]).reduce((a,b)=>a+b,0)/(a.length-(d?0:1)))},sum:(...a)=>[].concat(...a).reduce((a,b)=>a+b,0),symmetricDifference:(c,a)=>{const b=new Set(c),d=new Set(a);return[...c.filter((a)=>!d.has(a)),...a.filter((a)=>!b.has(a))]},tail:(a)=>1a.slice(0,b),takeRight:(a,b=1)=>a.slice(a.length-b,a.length),timeTaken:(a)=>{console.time('timeTaken');const b=a();return console.timeEnd('timeTaken'),b},toCamelCase:(a)=>{let b=a&&a.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g).map((a)=>a.slice(0,1).toUpperCase()+a.slice(1).toLowerCase()).join('');return b.slice(0,1).toLowerCase()+b.slice(1)},toDecimalMark:(a)=>a.toLocaleString('en-US'),toEnglishDate:(a)=>{try{return new Date(a).toISOString().split('T')[0].replace(/-/g,'/')}catch(a){}},toggleClass:(a,b)=>a.classList.toggle(b),toKebabCase:(a)=>a&&a.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g).map((a)=>a.toLowerCase()).join('-'),tomorrow:()=>new Date(new Date().getTime()+8.64e7).toISOString().split('T')[0],toOrdinalSuffix:(a)=>{const b=parseInt(a),c=[b%10,b%100],d=['st','nd','rd','th'];return[1,2,3,4].includes(c[0])&&![11,12,13,14,15,16,17,18,19].includes(c[1])?b+d[c[0]-1]:b+d[3]},toSnakeCase:(a)=>{a&&a.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g).map((a)=>a.toLowerCase()).join('_')},truncateString:(a,b)=>a.length>b?a.slice(0,3a.every((a)=>a[b]),unescapeHTML:(a)=>a.replace(/&|<|>|'|"/g,(a)=>({"&":'&',"<":'<',">":'>',"'":'\'',""":'"'})[a]||a),union:(c,a)=>Array.from(new Set([...c,...a])),UUIDGeneratorBrowser:()=>'10000000-1000-4000-8000-100000000000'.replace(/[018]/g,(a)=>(a^crypto.getRandomValues(new Uint8Array(1))[0]&15>>a/4).toString(16)),UUIDGeneratorNode:()=>'10000000-1000-4000-8000-100000000000'.replace(/[018]/g,(a)=>(a^s.randomBytes(1)[0]&15>>a/4).toString(16)),validateNumber:(a)=>!isNaN(parseFloat(a))&&isFinite(a)&&+a==a,without:(a,...b)=>a.filter((a)=>!b.includes(a)),words:(a,b=/[^a-zA-Z-]+/)=>a.split(b).filter(Boolean),zip:(...a)=>{const b=f(...a.map((a)=>a.length));return Array.from({length:b}).map((b,c)=>Array.from({length:a.length},(b,d)=>a[d][c]))},zipObject:(a,b)=>a.reduce((a,c,d)=>(a[c]=b[d],a),{})}});
diff --git a/scripts/module.js b/scripts/module.js
index 295e50fd9..981b86760 100644
--- a/scripts/module.js
+++ b/scripts/module.js
@@ -1,74 +1,74 @@
/*
Builds the `_30s` module.
*/
+// Load modules
const fs = require('fs-extra');
const cp = require('child_process');
const path = require('path');
const chalk = require('chalk');
-
+// Set variables for paths
const SNIPPETS_PATH = './snippets';
const TEMP_PATH = './temp';
const IMPORTS = './imports.js';
-
+// Regex for selecting code blocks
const codeRE = /```\s*js([\s\S]*?)```/;
-
+// Start the timer of the script
console.time('Module');
-
+// Load tag data from the database and snippets from their folder
try {
const tagDatabase = fs.readFileSync('tag_database', 'utf8');
const snippets = fs.readdirSync(SNIPPETS_PATH);
-
+ // Create `temp` folder if it doesn't already exist.
if (!fs.existsSync(TEMP_PATH)) {
fs.mkdirSync(TEMP_PATH);
}
-
+ // Write `imports.js`
fs.writeFileSync(IMPORTS, '');
-
let exportStr = 'export default {';
-
+ // Read all snippets and store them appropriately
for (const snippet of snippets) {
const snippetData = fs.readFileSync(
path.join(SNIPPETS_PATH, snippet),
'utf8'
);
const snippetName = snippet.replace('.md', '');
-
+ // Check if a snippet is Node-only
const isNodeSnippet = tagDatabase
.slice(tagDatabase.indexOf(snippetName) + snippetName.length + 1)
.split('\n')[0]
.includes('node');
-
+ // Read `imports.js` and write the data
const importData = fs.readFileSync(IMPORTS);
fs.writeFileSync(
IMPORTS,
importData + `\nimport { ${snippetName} } from './temp/${snippetName}.js'`
);
exportStr += `${snippetName},`;
-
+ // Find the code in each snippet
const code = snippetData.match(codeRE)[1].replace('\n', '');
-
+ // Store the data to be written
const toWrite = isNodeSnippet
? `${code
.replace('const ' + snippetName, 'export const ' + snippetName)
// Prevents errors from being thrown in browser environment
.replace('require(', 'typeof require !== "undefined" && require(')}`
: `export ${code}`;
-
+ // Write data to the proper file
fs.writeFileSync(`${TEMP_PATH}/${snippetName}.js`, toWrite);
}
-
+ // Write to the proper files and start the `rollup` script
exportStr += '}';
-
fs.appendFileSync(IMPORTS, `\n${exportStr}`);
-
cp.execSync('node ./scripts/rollup.js');
-
+ // Clean up temporary data
fs.removeSync(TEMP_PATH);
fs.unlink(IMPORTS);
-
+ // Log a success message
console.log(`${chalk.green('SUCCESS!')} Snippet module built!`);
+ // Log the time taken
console.timeEnd('Module');
} catch (err) {
+ // Handle errors (hopefully not!)
console.log(`${chalk.red('ERROR!')} During module creation: ${err}`);
process.exit(1);
}
diff --git a/scripts/rollup.js b/scripts/rollup.js
index 216ba426c..4fe1951a6 100644
--- a/scripts/rollup.js
+++ b/scripts/rollup.js
@@ -1,17 +1,21 @@
+/*
+ Part of the process for building the `_30s` module.
+*/
+// Load modules
const fs = require('fs-extra');
const { rollup } = require('rollup');
const babel = require('rollup-plugin-babel');
const minify = require('rollup-plugin-babel-minify');
-
+// Set variables for paths
const INPUT_FILE = './imports.js';
const MODULE_NAME = '_30s';
const DIST = './dist';
-
+// Create `dist` folder if not existing
if (!fs.existsSync(DIST)) fs.mkdirSync(DIST);
-
+// Setup babel and minification
const es5 = babel({ presets: [['env', { modules: false }]] });
const min = minify({ comments: false });
-
+// Create the bundles
(async () => {
const bundle = await rollup({ input: INPUT_FILE });
const bundleES5 = await rollup({ input: INPUT_FILE, plugins: [es5] });