From e9dcd807c4080a5040228a544e5f80fe7fa41b2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Feje=C5=A1?= Date: Wed, 20 Dec 2017 12:48:43 +0100 Subject: [PATCH 01/61] fix webber description --- scripts/web-script.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/web-script.js b/scripts/web-script.js index 27e84fcc4..bbfb5015f 100644 --- a/scripts/web-script.js +++ b/scripts/web-script.js @@ -1,6 +1,6 @@ /* - This is the builder script that generates the README file. - Run using `npm run builder`. + This is the builder script that generates the index.html file. + Run using `npm run webber`. */ // Load modules const fs = require('fs-extra'), path = require('path'), chalk = require('chalk'), From 4fb63c22cd0eea24403c5b753c08d4c56e521dd2 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Wed, 20 Dec 2017 14:18:42 +0200 Subject: [PATCH 02/61] Fixed website responsiveness --- docs/index.html | 19 +- docs/mini.css | 2 +- docs/mini/flavor.scss | 50 ++ package-lock.json | 1230 +++++++++++++++++++++++++++++++++ package.json | 1 + static-parts/index-start.html | 19 +- 6 files changed, 1288 insertions(+), 33 deletions(-) diff --git a/docs/index.html b/docs/index.html index e32341c1f..c059096a6 100644 --- a/docs/index.html +++ b/docs/index.html @@ -13,19 +13,6 @@ - - - -
-

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

- -
-
- -
 

Array

-

arrayMax

-

Returns the maximum value in an array.

-

Use Math.max() combined with the spread operator (...) to get the maximum value in the array.

-
const arrayMax = arr => Math.max(...arr);
-// arrayMax([10, 1, 5]) -> 10
-
-

arrayMin

-

Returns the minimum value in an array.

-

Use Math.min() combined with the spread operator (...) to get the minimum value in the array.

-
const arrayMin = arr => Math.min(...arr);
-// arrayMin([10, 1, 5]) -> 1
-
-

chunk

-

Chunks an array into smaller arrays of a specified size.

-

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

-
const chunk = (arr, size) =>
-  Array.from({length: Math.ceil(arr.length / size)}, (v, i) => arr.slice(i * size, i * size + size));
-// chunk([1,2,3,4,5], 2) -> [[1,2],[3,4],[5]]
-
-

compact

-

Removes falsey values from an array.

-

Use Array.filter() to filter out falsey values (false, null, 0, "", undefined, and NaN).

-
const compact = (arr) => arr.filter(Boolean);
-// compact([0, 1, false, 2, '', 3, 'a', 'e'*23, NaN, 's', 34]) -> [ 1, 2, 3, 'a', 's', 34 ]
-
-

countOccurrences

-

Counts the occurrences of a value in an array.

-

Use Array.reduce() to increment a counter each time you encounter the specific value inside the array.

-
const countOccurrences = (arr, value) => arr.reduce((a, v) => v === value ? a + 1 : a + 0, 0);
-// countOccurrences([1,1,2,1,2,3], 1) -> 3
-
-

deepFlatten

-

Deep flattens an array.

-

Use recursion. -Use Array.concat() with an empty array ([]) and the spread operator (...) to flatten an array. -Recursively flatten each element that is an array.

-
const deepFlatten = arr => [].concat(...arr.map(v => Array.isArray(v) ? deepFlatten(v) : v));
-// deepFlatten([1,[2],[[3],4],5]) -> [1,2,3,4,5]
-
-

difference

-

Returns the difference between two arrays.

-

Create a Set from b, then use Array.filter() on a to only keep values not contained in b.

-
const difference = (a, b) => { const s = new Set(b); return a.filter(x => !s.has(x)); };
-// difference([1,2,3], [1,2,4]) -> [3]
-
-

differenceWith

-

Filters out all values from an array for which the comparator function does not return true.

-

Use Array.filter() and Array.find() to find the appropriate values.

-
const differenceWith = (arr, val, comp) => arr.filter(a => !val.find(b => comp(a, b)))
-// differenceWith([1, 1.2, 1.5, 3], [1.9, 3], (a,b) => Math.round(a) == Math.round(b)) -> [1, 1.2]
-
-

distinctValuesOfArray

-

Returns all the distinct values of an array.

-

Use ES6 Set and the ...rest operator to discard all duplicated values.

-
const distinctValuesOfArray = arr => [...new Set(arr)];
-// distinctValuesOfArray([1,2,2,3,4,4,5]) -> [1,2,3,4,5]
-
-

dropElements

-

Removes elements in an array until the passed function returns true. Returns the remaining elements in the array.

-

Loop through the array, using Array.slice() to drop the first element of the array until the returned value from the function is true. -Returns the remaining elements.

-
const dropElements = (arr, func) => {
-  while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1);
+    }

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

 

Array

arrayMax

Returns the maximum value in an array.

Use Math.max() combined with the spread operator (...) to get the maximum value in the array.

const arrayMax = arr => Math.max(...arr);
+// arrayMax([10, 1, 5]) -> 10
+

arrayMin

Returns the minimum value in an array.

Use Math.min() combined with the spread operator (...) to get the minimum value in the array.

const arrayMin = arr => Math.min(...arr);
+// arrayMin([10, 1, 5]) -> 1
+

chunk

Chunks an array into smaller arrays of a specified size.

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

const chunk = (arr, size) =>
+  Array.from({length: Math.ceil(arr.length / size)}, (v, i) => arr.slice(i * size, i * size + size));
+// chunk([1,2,3,4,5], 2) -> [[1,2],[3,4],[5]]
+

compact

Removes falsey values from an array.

Use Array.filter() to filter out falsey values (false, null, 0, "", undefined, and NaN).

const compact = (arr) => arr.filter(Boolean);
+// compact([0, 1, false, 2, '', 3, 'a', 'e'*23, NaN, 's', 34]) -> [ 1, 2, 3, 'a', 's', 34 ]
+

countOccurrences

Counts the occurrences of a value in an array.

Use Array.reduce() to increment a counter each time you encounter the specific value inside the array.

const countOccurrences = (arr, value) => arr.reduce((a, v) => v === value ? a + 1 : a + 0, 0);
+// countOccurrences([1,1,2,1,2,3], 1) -> 3
+

deepFlatten

Deep flattens an array.

Use recursion. Use Array.concat() with an empty array ([]) and the spread operator (...) to flatten an array. Recursively flatten each element that is an array.

const deepFlatten = arr => [].concat(...arr.map(v => Array.isArray(v) ? deepFlatten(v) : v));
+// deepFlatten([1,[2],[[3],4],5]) -> [1,2,3,4,5]
+

difference

Returns the difference between two arrays.

Create a Set from b, then use Array.filter() on a to only keep values not contained in b.

const difference = (a, b) => { const s = new Set(b); return a.filter(x => !s.has(x)); };
+// difference([1,2,3], [1,2,4]) -> [3]
+

differenceWith

Filters out all values from an array for which the comparator function does not return true.

Use Array.filter() and Array.find() to find the appropriate values.

const differenceWith = (arr, val, comp) => arr.filter(a => !val.find(b => comp(a, b)))
+// differenceWith([1, 1.2, 1.5, 3], [1.9, 3], (a,b) => Math.round(a) == Math.round(b)) -> [1, 1.2]
+

distinctValuesOfArray

Returns all the distinct values of an array.

Use ES6 Set and the ...rest operator to discard all duplicated values.

const distinctValuesOfArray = arr => [...new Set(arr)];
+// distinctValuesOfArray([1,2,2,3,4,4,5]) -> [1,2,3,4,5]
+

dropElements

Removes elements in an array until the passed function returns true. Returns the remaining elements in the array.

Loop through the array, using Array.slice() to drop the first element of the array until the returned value from the function is true. Returns the remaining elements.

const dropElements = (arr, func) => {
+  while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1);
   return arr;
 };
-// dropElements([1, 2, 3, 4], n => n >= 3) -> [3,4]
-
-

dropRight

-

Returns a new array with n elements removed from the right

-

Check if n is shorter than the given array and use Array.slice() to slice it accordingly or return an empty array.

-
const dropRight = (arr, n = 1) => n < arr.length ? arr.slice(0, arr.length - n) : []
-//dropRight([1,2,3]) -> [1,2]
-//dropRight([1,2,3], 2) -> [1]
-//dropRight([1,2,3], 42) -> []
-
-

everyNth

-

Returns every nth element in an array.

-

Use Array.filter() to create a new array that contains every nth element of a given array.

-
const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === 0);
-// everyNth([1,2,3,4,5,6], 2) -> [ 1, 3, 5 ]
-
-

filterNonUnique

-

Filters out the non-unique values in an array.

-

Use Array.filter() for an array containing only the unique values.

-
const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i));
-// filterNonUnique([1,2,2,3,4,4,5]) -> [1,3,5]
-
-

flatten

-

Flattens an array.

-

Use Array.reduce() to get all elements inside the array and concat() to flatten them.

-
const flatten = arr => arr.reduce((a, v) => a.concat(v), []);
-// flatten([1,[2],3,4]) -> [1,2,3,4]
-
-

flattenDepth

-

Flattens an array up to the specified depth.

-

Use recursion, decrementing depth by 1 for each level of depth. -Use Array.reduce() and Array.concat() to merge elements or arrays. -Base case, for depth equal to 1 stops recursion. -Omit the second element, depth to flatten only to a depth of 1 (single flatten).

-
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), []);
-// flattenDepth([1,[2],[[[3],4],5]], 2) -> [1,2,[3],4,5]
-
-

groupBy

-

Groups the element of an array based on the given function.

-

Use Array.map() to map the values of an array to a function or property name. -Use Array.reduce() to create an object, where the keys are produced from the mapped results.

-
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; }, {});
-// groupBy([6.1, 4.2, 6.3], Math.floor) -> {4: [4.2], 6: [6.1, 6.3]}
-// groupBy(['one', 'two', 'three'], 'length') -> {3: ['one', 'two'], 5: ['three']}
-
-

-

Returns the head of a list.

-

Use arr[0] to return the first element of the passed array.

-
const head = arr => arr[0];
-// head([1,2,3]) -> 1
-
-

initial

-

Returns all the elements of an array except the last one.

-

Use arr.slice(0,-1)to return all but the last element of the array.

-
const initial = arr => arr.slice(0, -1);
-// initial([1,2,3]) -> [1,2]
-
-

initialize2DArray

-

Initializes an 2D array of given width and height and value.

-

Use Array.map() to generate h rows where each is a new array of size w initialize with value. If value is not provided, default to null.

-
const initialize2DArray = (w, h, val = null) => Array(h).fill().map(() => Array(w).fill(val));
-// initializeArrayWithRange(2, 2, 0) -> [[0,0], [0,0]]
-
-

initializeArrayWithRange

-

Initializes an array containing the numbers in the specified range where start and end are inclusive.

-

Use Array((end + 1) - start) to create an array of the desired length, Array.map() to fill with the desired values in a range. -You can omit start to use a default value of 0.

-
const initializeArrayWithRange = (end, start = 0) => 
-  Array.from({ length: (end + 1) - start }).map((v, i) => i + start);
-// initializeArrayWithRange(5) -> [0,1,2,3,4,5]
-// initializeArrayWithRange(7, 3) -> [3,4,5,6,7]
-
-

initializeArrayWithValues

-

Initializes and fills an array with the specified values.

-

Use Array(n) to create an array of the desired length, fill(v) to fill it with the desired values. -You can omit value to use a default value of 0.

-
const initializeArrayWithValues = (n, value = 0) => Array(n).fill(value);
-// initializeArrayWithValues(5, 2) -> [2,2,2,2,2]
-
-

intersection

-

Returns a list of elements that exist in both arrays.

-

Create a Set from b, then use Array.filter() on a to only keep values contained in b.

-
const intersection = (a, b) => { const s = new Set(b); return a.filter(x => s.has(x)); };
-// intersection([1,2,3], [4,3,2]) -> [2,3]
-
-

last

-

Returns the last element in an array.

-

Use arr.length - 1 to compute index of the last element of the given array and returning it.

-
const last = arr => arr[arr.length - 1];
-// last([1,2,3]) -> 3
-
-

mapObject

-

Maps the values of an array to an object using a function, where the key-value pairs consist of the original value as the key and the mapped value.

-

Use an anonymous inner function scope to declare an undefined memory space, using closures to store a return value. Use a new Array to stor the array with a map of the function over its data set and a comma operator to return a second step, without needing to move from one context to another (due to closures and order of operations).

-
const mapObject = (arr, fn) => 
-  (a => (a = [arr, arr.map(fn)], a[0].reduce( (acc,val,ind) => (acc[val] = a[1][ind], acc), {}) )) ( );
+// dropElements([1, 2, 3, 4], n => n >= 3) -> [3,4]
+

dropRight

Returns a new array with n elements removed from the right

Check if n is shorter than the given array and use Array.slice() to slice it accordingly or return an empty array.

const dropRight = (arr, n = 1) => n < arr.length ? arr.slice(0, arr.length - n) : []
+//dropRight([1,2,3]) -> [1,2]
+//dropRight([1,2,3], 2) -> [1]
+//dropRight([1,2,3], 42) -> []
+

everyNth

Returns every nth element in an array.

Use Array.filter() to create a new array that contains every nth element of a given array.

const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === 0);
+// everyNth([1,2,3,4,5,6], 2) -> [ 1, 3, 5 ]
+

filterNonUnique

Filters out the non-unique values in an array.

Use Array.filter() for an array containing only the unique values.

const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i));
+// filterNonUnique([1,2,2,3,4,4,5]) -> [1,3,5]
+

flatten

Flattens an array.

Use Array.reduce() to get all elements inside the array and concat() to flatten them.

const flatten = arr => arr.reduce((a, v) => a.concat(v), []);
+// flatten([1,[2],3,4]) -> [1,2,3,4]
+

flattenDepth

Flattens an array up to the specified depth.

Use recursion, decrementing depth by 1 for each level of depth. Use Array.reduce() and Array.concat() to merge elements or arrays. Base case, for depth equal to 1 stops recursion. Omit the second element, depth to flatten only to a depth of 1 (single flatten).

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), []);
+// flattenDepth([1,[2],[[[3],4],5]], 2) -> [1,2,[3],4,5]
+

groupBy

Groups the element of an array based on the given function.

Use Array.map() to map the values of an array to a function or property name. Use Array.reduce() to create an object, where the keys are produced from the mapped results.

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; }, {});
+// groupBy([6.1, 4.2, 6.3], Math.floor) -> {4: [4.2], 6: [6.1, 6.3]}
+// groupBy(['one', 'two', 'three'], 'length') -> {3: ['one', 'two'], 5: ['three']}
+

Returns the head of a list.

Use arr[0] to return the first element of the passed array.

const head = arr => arr[0];
+// head([1,2,3]) -> 1
+

initial

Returns all the elements of an array except the last one.

Use arr.slice(0,-1)to return all but the last element of the array.

const initial = arr => arr.slice(0, -1);
+// initial([1,2,3]) -> [1,2]
+

initialize2DArray

Initializes an 2D array of given width and height and value.

Use Array.map() to generate h rows where each is a new array of size w initialize with value. If value is not provided, default to null.

const initialize2DArray = (w, h, val = null) => Array(h).fill().map(() => Array(w).fill(val));
+// initializeArrayWithRange(2, 2, 0) -> [[0,0], [0,0]]
+

initializeArrayWithRange

Initializes an array containing the numbers in the specified range where start and end are inclusive.

Use Array((end + 1) - start) to create an array of the desired length, Array.map() to fill with the desired values in a range. You can omit start to use a default value of 0.

const initializeArrayWithRange = (end, start = 0) => 
+  Array.from({ length: (end + 1) - start }).map((v, i) => i + start);
+// initializeArrayWithRange(5) -> [0,1,2,3,4,5]
+// initializeArrayWithRange(7, 3) -> [3,4,5,6,7]
+

initializeArrayWithValues

Initializes and fills an array with the specified values.

Use Array(n) to create an array of the desired length, fill(v) to fill it with the desired values. You can omit value to use a default value of 0.

const initializeArrayWithValues = (n, value = 0) => Array(n).fill(value);
+// initializeArrayWithValues(5, 2) -> [2,2,2,2,2]
+

intersection

Returns a list of elements that exist in both arrays.

Create a Set from b, then use Array.filter() on a to only keep values contained in b.

const intersection = (a, b) => { const s = new Set(b); return a.filter(x => s.has(x)); };
+// intersection([1,2,3], [4,3,2]) -> [2,3]
+

last

Returns the last element in an array.

Use arr.length - 1 to compute index of the last element of the given array and returning it.

const last = arr => arr[arr.length - 1];
+// last([1,2,3]) -> 3
+

mapObject

Maps the values of an array to an object using a function, where the key-value pairs consist of the original value as the key and the mapped value.

Use an anonymous inner function scope to declare an undefined memory space, using closures to store a return value. Use a new Array to stor the array with a map of the function over its data set and a comma operator to return a second step, without needing to move from one context to another (due to closures and order of operations).

const mapObject = (arr, fn) => 
+  (a => (a = [arr, arr.map(fn)], a[0].reduce( (acc,val,ind) => (acc[val] = a[1][ind], acc), {}) )) ( );
 /*
-const squareIt = arr => mapObject(arr, a => a*a)
+const squareIt = arr => mapObject(arr, a => a*a)
 squareIt([1,2,3]) // { 1: 1, 2: 4, 3: 9 }
 */
-
-

nthElement

-

Returns the nth element of an array.

-

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

-
const nthElement = (arr, n=0) => (n>0? arr.slice(n,n+1) : arr.slice(n))[0];
-// nthElement(['a','b','c'],1) -> 'b'
-// nthElement(['a','b','b'],-3) -> 'a'
-
-

pick

-

Picks the key-value pairs corresponding to the given keys from an object.

-

Use Array.reduce() to convert the filtered/picked keys back to a object with the corresponding key-value pair if the key exist in the obj.

-
const pick = (obj, arr) =>
-  arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {});
-// pick({ 'a': 1, 'b': '2', 'c': 3 }, ['a', 'c']) -> { 'a': 1, 'c': 3 }
-
-

pull

-

Mutates the original array to filter out the values specified.

-

Use Array.filter() and Array.includes() to pull out the values that are not needed. -Use Array.length = 0 to mutate the passed in array by resetting it's length to zero and Array.push() to re-populate it with only the pulled values.

-

(For a snippet that does not mutate the original array see without)

-
const pull = (arr, ...args) => {
-  let pulled = arr.filter((v, i) => !args.toString().split(',').includes(v));
-  arr.length = 0; pulled.forEach(v => arr.push(v));
+

nthElement

Returns the nth element of an array.

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

const nthElement = (arr, n=0) => (n>0? arr.slice(n,n+1) : arr.slice(n))[0];
+// nthElement(['a','b','c'],1) -> 'b'
+// nthElement(['a','b','b'],-3) -> 'a'
+

pick

Picks the key-value pairs corresponding to the given keys from an object.

Use Array.reduce() to convert the filtered/picked keys back to a object with the corresponding key-value pair if the key exist in the obj.

const pick = (obj, arr) =>
+  arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {});
+// pick({ 'a': 1, 'b': '2', 'c': 3 }, ['a', 'c']) -> { 'a': 1, 'c': 3 }
+

pull

Mutates the original array to filter out the values specified.

Use Array.filter() and Array.includes() to pull out the values that are not needed. Use Array.length = 0 to mutate the passed in array by resetting it's length to zero and Array.push() to re-populate it with only the pulled values.

(For a snippet that does not mutate the original array see without)

const pull = (arr, ...args) => {
+  let pulled = arr.filter((v, i) => !args.toString().split(',').includes(v));
+  arr.length = 0; pulled.forEach(v => arr.push(v));
 };
 
 // let myArray1 = ['a', 'b', 'c', 'a', 'b', 'c'];
 // pull(myArray1, 'a', 'c');
-// console.log(myArray1) -> [ 'b', 'b' ]
+// console.log(myArray1) -> [ 'b', 'b' ]
 
 // let myArray2 = ['a', 'b', 'c', 'a', 'b', 'c'];
 // pull(myArray2, ['a', 'c']);
-// console.log(myArray2) -> [ 'b', 'b' ]
-
-

pullAtIndex

-

Mutates the original array to filter out the values at the specified indexes.

-

Use Array.filter() and Array.includes() to pull out the values that are not needed. -Use Array.length = 0 to mutate the passed in array by resetting it's length to zero and Array.push() to re-populate it with only the pulled values. -Use Array.push() to keep track of pulled values

-
const pullAtIndex = (arr, pullArr) => {
+// console.log(myArray2) -> [ 'b', 'b' ]
+

pullAtIndex

Mutates the original array to filter out the values at the specified indexes.

Use Array.filter() and Array.includes() to pull out the values that are not needed. Use Array.length = 0 to mutate the passed in array by resetting it's length to zero and Array.push() to re-populate it with only the pulled values. Use Array.push() to keep track of pulled values

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))
+  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));
+  pulled.forEach(v => arr.push(v));
   return removed;
 }
 
 // let myArray = ['a', 'b', 'c', 'd'];
 // let pulled = pullAtIndex(myArray, [1, 3]);
 
-// console.log(myArray); -> [ 'a', 'c' ]
-// console.log(pulled); -> [ 'b', 'd' ]
-
-

pullAtValue

-

Mutates the original array to filter out the values specified. Returns the removed elements.

-

Use Array.filter() and Array.includes() to pull out the values that are not needed. -Use Array.length = 0 to mutate the passed in array by resetting it's length to zero and Array.push() to re-populate it with only the pulled values. -Use Array.push() to keep track of pulled values

-
const pullAtValue = (arr, pullArr) => {
+// console.log(myArray); -> [ 'a', 'c' ]
+// console.log(pulled); -> [ 'b', 'd' ]
+

pullAtValue

Mutates the original array to filter out the values specified. Returns the removed elements.

Use Array.filter() and Array.includes() to pull out the values that are not needed. Use Array.length = 0 to mutate the passed in array by resetting it's length to zero and Array.push() to re-populate it with only the pulled values. Use Array.push() to keep track of pulled values

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));
+    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));
+  mutateTo.forEach(v => arr.push(v));
   return removed;
 }
 /*
 let myArray = ['a', 'b', 'c', 'd'];
 let pulled = pullAtValue(myArray, ['b', 'd']);
-console.log(myArray); -> [ 'a', 'c' ]
-console.log(pulled); -> [ 'b', 'd' ]
+console.log(myArray); -> [ 'a', 'c' ]
+console.log(pulled); -> [ 'b', 'd' ]
 */
-
-

remove

-

Removes elements from an array for which the given function returns false.

-

Use Array.filter() to find array elements that return truthy values and Array.reduce() to remove elements using Array.splice(). -The func is invoked with three arguments (value, index, array).

-
const remove = (arr, func) =>
-  Array.isArray(arr) ? arr.filter(func).reduce((acc, val) => {
+

remove

Removes elements from an array for which the given function returns false.

Use Array.filter() to find array elements that return truthy values and Array.reduce() to remove elements using Array.splice(). The func is invoked with three arguments (value, index, array).

const remove = (arr, func) =>
+  Array.isArray(arr) ? arr.filter(func).reduce((acc, val) => {
     arr.splice(arr.indexOf(val), 1); return acc.concat(val);
     }, [])
   : [];
-// remove([1, 2, 3, 4], n => n % 2 == 0) -> [2, 4]
-
-

sample

-

Returns a random element from an array.

-

Use Math.random() to generate a random number, multiply it with length and round it of to the nearest whole number using Math.floor(). -This method also works with strings.

-
const sample = arr => arr[Math.floor(Math.random() * arr.length)];
-// sample([3, 7, 9, 11]) -> 9
-
-

shuffle

-

Randomizes the order of the values of an array.

-

Use Array.sort() to reorder elements, using Math.random() in the comparator.

-
const shuffle = arr => arr.sort(() => Math.random() - 0.5);
-// shuffle([1,2,3]) -> [2,3,1]
-
-

similarity

-

Returns an array of elements that appear in both arrays.

-

Use filter() to remove values that are not part of values, determined using includes().

-
const similarity = (arr, values) => arr.filter(v => values.includes(v));
-// similarity([1,2,3], [1,2,4]) -> [1,2]
-
-

symmetricDifference

-

Returns the symmetric difference between two arrays.

-

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

-
const symmetricDifference = (a, b) => {
+// remove([1, 2, 3, 4], n => n % 2 == 0) -> [2, 4]
+

sample

Returns a random element from an array.

Use Math.random() to generate a random number, multiply it with length and round it of to the nearest whole number using Math.floor(). This method also works with strings.

const sample = arr => arr[Math.floor(Math.random() * arr.length)];
+// sample([3, 7, 9, 11]) -> 9
+

shuffle

Randomizes the order of the values of an array.

Use Array.sort() to reorder elements, using Math.random() in the comparator.

const shuffle = arr => arr.sort(() => Math.random() - 0.5);
+// shuffle([1,2,3]) -> [2,3,1]
+

similarity

Returns an array of elements that appear in both arrays.

Use filter() to remove values that are not part of values, determined using includes().

const similarity = (arr, values) => arr.filter(v => values.includes(v));
+// similarity([1,2,3], [1,2,4]) -> [1,2]
+

symmetricDifference

Returns the symmetric difference between two arrays.

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

const symmetricDifference = (a, b) => {
   const sA = new Set(a), sB = new Set(b);
-  return [...a.filter(x => !sB.has(x)), ...b.filter(x => !sA.has(x))];
+  return [...a.filter(x => !sB.has(x)), ...b.filter(x => !sA.has(x))];
 }
-// symmetricDifference([1,2,3], [1,2,4]) -> [3,4]
-
-

tail

-

Returns all elements in an array except for the first one.

-

Return arr.slice(1) if the array's length is more than 1, otherwise return the whole array.

-
const tail = arr => arr.length > 1 ? arr.slice(1) : arr;
-// tail([1,2,3]) -> [2,3]
-// tail([1]) -> [1]
-
-

take

-

Returns an array with n elements removed from the beginning.

-

Use Array.slice() to create a slice of the array with n elements taken from the beginning.

-
const take = (arr, n = 1) => arr.slice(0, n);
-// take([1, 2, 3], 5) -> [1, 2, 3]
-// take([1, 2, 3], 0) -> []
-
-

takeRight

-

Returns an array with n elements removed from the end.

-

Use Array.slice() to create a slice of the array with n elements taken from the end.

-
const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length);
-// takeRight([1, 2, 3], 2) -> [ 2, 3 ]
-// takeRight([1, 2, 3]) -> [3]
-
-

union

-

Returns every element that exists in any of the two arrays once.

-

Create a Set with all values of a and b and convert to an array.

-
const union = (a, b) => Array.from(new Set([...a, ...b]));
-// union([1,2,3], [4,3,2]) -> [1,2,3,4]
-
-

without

-

Filters out the elements of an array, that have one of the specified values.

-

Use Array.filter() to create an array excluding(using !Array.includes()) all given values.

-

(For a snippet that mutates the original array see pull)

-
const without = (arr, ...args) => arr.filter(v => !args.includes(v));
-// without([2, 1, 2, 3], 1, 2) -> [3]
-
-

zip

-

Creates an array of elements, grouped based on the position in the original arrays.

-

Use Math.max.apply() to get the longest array in the arguments. -Creates an array with that length as return value and use Array.from() with a map-function to create an array of grouped elements. -If lengths of the argument-arrays vary, undefined is used where no value could be found.

-
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]);
+// symmetricDifference([1,2,3], [1,2,4]) -> [3,4]
+

tail

Returns all elements in an array except for the first one.

Return arr.slice(1) if the array's length is more than 1, otherwise return the whole array.

const tail = arr => arr.length > 1 ? arr.slice(1) : arr;
+// tail([1,2,3]) -> [2,3]
+// tail([1]) -> [1]
+

take

Returns an array with n elements removed from the beginning.

Use Array.slice() to create a slice of the array with n elements taken from the beginning.

const take = (arr, n = 1) => arr.slice(0, n);
+// take([1, 2, 3], 5) -> [1, 2, 3]
+// take([1, 2, 3], 0) -> []
+

takeRight

Returns an array with n elements removed from the end.

Use Array.slice() to create a slice of the array with n elements taken from the end.

const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length);
+// takeRight([1, 2, 3], 2) -> [ 2, 3 ]
+// takeRight([1, 2, 3]) -> [3]
+

union

Returns every element that exists in any of the two arrays once.

Create a Set with all values of a and b and convert to an array.

const union = (a, b) => Array.from(new Set([...a, ...b]));
+// union([1,2,3], [4,3,2]) -> [1,2,3,4]
+

without

Filters out the elements of an array, that have one of the specified values.

Use Array.filter() to create an array excluding(using !Array.includes()) all given values.

(For a snippet that mutates the original array see pull)

const without = (arr, ...args) => arr.filter(v => !args.includes(v));
+// without([2, 1, 2, 3], 1, 2) -> [3]
+

zip

Creates an array of elements, grouped based on the position in the original arrays.

Use Math.max.apply() to get the longest array in the arguments. Creates an array with that length as return value and use Array.from() with a map-function to create an array of grouped elements. If lengths of the argument-arrays vary, undefined is used where no value could be found.

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]);
   })
 }
-//zip(['a', 'b'], [1, 2], [true, false]); -> [['a', 1, true], ['b', 2, false]]
-//zip(['a'], [1, 2], [true, false]); -> [['a', 1, true], [undefined, 2, false]]
-
-

Browser

-

arrayToHtmlList

-

Converts the given array elements into <li> tags and appends them to the list of the given id.

-

Use Array.map() and document.querySelector() to create a list of html tags.

-
const arrayToHtmlList = (arr, listID) => arr.map(item => document.querySelector("#"+listID).innerHTML+=`<li>${item}</li>`);
+//zip(['a', 'b'], [1, 2], [true, false]); -> [['a', 1, true], ['b', 2, false]]
+//zip(['a'], [1, 2], [true, false]); -> [['a', 1, true], [undefined, 2, false]]
+

Browser

arrayToHtmlList

Converts the given array elements into <li> tags and appends them to the list of the given id.

Use Array.map() and document.querySelector() to create a list of html tags.

const arrayToHtmlList = (arr, listID) => arr.map(item => document.querySelector("#"+listID).innerHTML+=`<li>${item}</li>`);
 // arrayToHtmlList(['item 1', 'item 2'],'myListID')
-
-

bottomVisible

-

Returns true if the bottom of the page is visible, false otherwise.

-

Use scrollY, scrollHeight and clientHeight to determine if the bottom of the page is visible.

-
const bottomVisible = () =>
-  document.documentElement.clientHeight + window.scrollY >= (document.documentElement.scrollHeight || document.documentElement.clientHeight);
-// bottomVisible() -> true
-
-

currentURL

-

Returns the current URL.

-

Use window.location.href to get current URL.

-
const currentURL = () => window.location.href;
-// currentUrl() -> 'https://google.com'
-
-

elementIsVisibleInViewport

-

Returns true if the element specified is visible in the viewport, false otherwise.

-

Use Element.getBoundingClientRect() and the window.inner(Width|Height) values -to determine if a given element is visible in the viewport. -Omit the second argument to determine if the element is entirely visible, or specify true to determine if -it is partially visible.

-
const elementIsVisibleInViewport = (el, partiallyVisible = false) => {
+

bottomVisible

Returns true if the bottom of the page is visible, false otherwise.

Use scrollY, scrollHeight and clientHeight to determine if the bottom of the page is visible.

const bottomVisible = () =>
+  document.documentElement.clientHeight + window.scrollY >= (document.documentElement.scrollHeight || document.documentElement.clientHeight);
+// bottomVisible() -> true
+

currentURL

Returns the current URL.

Use window.location.href to get current URL.

const currentURL = () => window.location.href;
+// currentUrl() -> 'https://google.com'
+

elementIsVisibleInViewport

Returns true if the element specified is visible in the viewport, false otherwise.

Use Element.getBoundingClientRect() and the window.inner(Width|Height) values to determine if a given element is visible in the viewport. Omit the second argument to determine if the element is entirely visible, or specify true to determine if it is partially visible.

const elementIsVisibleInViewport = (el, partiallyVisible = false) => {
   const { top, left, bottom, right } = el.getBoundingClientRect();
   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;
+    ? ((top > 0 && top < innerHeight) || (bottom > 0 && bottom < innerHeight)) &&
+      ((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth))
+    : top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth;
 };
 // e.g. 100x100 viewport and a 10x10px element at position {top: -1, left: 0, bottom: 9, right: 10}
-// elementIsVisibleInViewport(el) -> false (not fully visible)
-// elementIsVisibleInViewport(el, true) -> true (partially visible)
-
-

getScrollPosition

-

Returns the scroll position of the current page.

-

Use pageXOffset and pageYOffset if they are defined, otherwise scrollLeft and scrollTop. -You can omit el to use a default value of window.

-
const getScrollPosition = (el = window) =>
+// elementIsVisibleInViewport(el) -> false (not fully visible)
+// elementIsVisibleInViewport(el, true) -> true (partially visible)
+

getScrollPosition

Returns the scroll position of the current page.

Use pageXOffset and pageYOffset if they are defined, otherwise scrollLeft and scrollTop. You can omit el to use a default value of window.

const getScrollPosition = (el = window) =>
   ({x: (el.pageXOffset !== undefined) ? el.pageXOffset : el.scrollLeft,
     y: (el.pageYOffset !== undefined) ? el.pageYOffset : el.scrollTop});
-// getScrollPosition() -> {x: 0, y: 200}
-
-

getURLParameters

-

Returns an object containing the parameters of the current URL.

-

Use match() with an appropriate regular expression to get all key-value pairs, Array.reduce() to map and combine them into a single object. -Pass location.search as the argument to apply to the current url.

-
const getURLParameters = url =>
-  url.match(/([^?=&]+)(=([^&]*))/g).reduce(
-    (a, v) => (a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1), a), {}
+// getScrollPosition() -> {x: 0, y: 200}
+

getURLParameters

Returns an object containing the parameters of the current URL.

Use match() with an appropriate regular expression to get all key-value pairs, Array.reduce() to map and combine them into a single object. Pass location.search as the argument to apply to the current url.

const getURLParameters = url =>
+  url.match(/([^?=&]+)(=([^&]*))/g).reduce(
+    (a, v) => (a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1), a), {}
   );
-// getURLParameters('http://url.com/page?name=Adam&surname=Smith') -> {name: 'Adam', surname: 'Smith'}
-
-

redirect

-

Redirects to a specified URL.

-

Use window.location.href or window.location.replace() to redirect to url. -Pass a second argument to simulate a link click (true - default) or an HTTP redirect (false).

-
const redirect = (url, asLink = true) =>
+// getURLParameters('http://url.com/page?name=Adam&surname=Smith') -> {name: 'Adam', surname: 'Smith'}
+

redirect

Redirects to a specified URL.

Use window.location.href or window.location.replace() to redirect to url. Pass a second argument to simulate a link click (true - default) or an HTTP redirect (false).

const redirect = (url, asLink = true) =>
   asLink ? window.location.href = url : window.location.replace(url);
 // redirect('https://google.com')
-
-

scrollToTop

-

Smooth-scrolls to the top of the page.

-

Get distance from top using document.documentElement.scrollTop or document.body.scrollTop. -Scroll by a fraction of the distance from top. Use window.requestAnimationFrame() to animate the scrolling.

-
const scrollToTop = () => {
+

scrollToTop

Smooth-scrolls to the top of the page.

Get distance from top using document.documentElement.scrollTop or document.body.scrollTop. Scroll by a fraction of the distance from top. Use window.requestAnimationFrame() to animate the scrolling.

const scrollToTop = () => {
   const c = document.documentElement.scrollTop || document.body.scrollTop;
-  if (c > 0) {
+  if (c > 0) {
     window.requestAnimationFrame(scrollToTop);
     window.scrollTo(0, c - c / 8);
   }
 };
 // scrollToTop()
-
-

Date

-

getDaysDiffBetweenDates

-

Returns the difference (in days) between two dates.

-

Calculate the difference (in days) between to Date objects.

-
const getDaysDiffBetweenDates = (dateInitial, dateFinal) => (dateFinal - dateInitial) / (1000 * 3600 * 24);
-// getDaysDiffBetweenDates(new Date("2017-12-13"), new Date("2017-12-22")) -> 9
-
-

JSONToDate

-

Converts a JSON object to a date.

-

Use Date(), to convert dates in JSON format to readable format (dd/mm/yyyy).

-
const JSONToDate = arr => {
+

Date

getDaysDiffBetweenDates

Returns the difference (in days) between two dates.

Calculate the difference (in days) between to Date objects.

const getDaysDiffBetweenDates = (dateInitial, dateFinal) => (dateFinal - dateInitial) / (1000 * 3600 * 24);
+// getDaysDiffBetweenDates(new Date("2017-12-13"), new Date("2017-12-22")) -> 9
+

JSONToDate

Converts a JSON object to a date.

Use Date(), to convert dates in JSON format to readable format (dd/mm/yyyy).

const JSONToDate = arr => {
   const dt = new Date(parseInt(arr.toString().substr(6)));
   return `${ dt.getDate() }/${ dt.getMonth() + 1 }/${ dt.getFullYear() }`
 };
-// JSONToDate(/Date(1489525200000)/) -> "14/3/2017"
-
-

toEnglishDate

-

Converts a date from American format to English format.

-

Use Date.toISOString(), split('T') and replace() to convert a date from American format to English format. -Throws an error if the passed time cannot be converted to a date.

-
const toEnglishDate  = (time) =>
+// JSONToDate(/Date(1489525200000)/) -> "14/3/2017"
+

toEnglishDate

Converts a date from American format to English format.

Use Date.toISOString(), split('T') and replace() to convert a date from American format to English format. Throws an error if the passed time cannot be converted to a date.

const toEnglishDate  = (time) =>
   {try{return new Date(time).toISOString().split('T')[0].replace(/-/g, '/')}catch(e){return}};
-// toEnglishDate('09/21/2010') -> '21/09/2010'
-
-

Function

-

chainAsync

-

Chains asynchronous functions.

-

Loop through an array of functions containing asynchronous events, calling next when each asynchronous event has completed.

-
const chainAsync = fns => { let curr = 0; const next = () => fns[curr++](next); next(); };
+// toEnglishDate('09/21/2010') -> '21/09/2010'
+

Function

chainAsync

Chains asynchronous functions.

Loop through an array of functions containing asynchronous events, calling next when each asynchronous event has completed.

const chainAsync = fns => { let curr = 0; const next = () => fns[curr++](next); next(); };
 /*
 chainAsync([
-  next => { console.log('0 seconds'); setTimeout(next, 1000); },
-  next => { console.log('1 second');  setTimeout(next, 1000); },
-  next => { console.log('2 seconds'); }
+  next => { console.log('0 seconds'); setTimeout(next, 1000); },
+  next => { console.log('1 second');  setTimeout(next, 1000); },
+  next => { console.log('2 seconds'); }
 ])
 */
-
-

compose

-

Performs right-to-left function composition.

-

Use Array.reduce() to perform right-to-left function composition. -The last (rightmost) function can accept one or more arguments; the remaining functions must be unary.

-
const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)));
+

compose

Performs right-to-left function composition.

Use Array.reduce() to perform right-to-left function composition. The last (rightmost) function can accept one or more arguments; the remaining functions must be unary.

const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)));
 /*
-const add5 = x => x + 5
-const multiply = (x, y) => x * y
+const add5 = x => x + 5
+const multiply = (x, y) => x * y
 const multiplyAndAdd5 = compose(add5, multiply)
-multiplyAndAdd5(5, 2) -> 15
+multiplyAndAdd5(5, 2) -> 15
 */
-
-

curry

-

Curries a function.

-

Use recursion. -If the number of provided arguments (args) is sufficient, call the passed function f. -Otherwise return a curried function f that expects the rest of the arguments. -If you want to curry a function that accepts a variable number of arguments (a variadic function, e.g. Math.min()), you can optionally pass the number of arguments to the second parameter arity.

-
const curry = (fn, arity = fn.length, ...args) =>
+

curry

Curries a function.

Use recursion. If the number of provided arguments (args) is sufficient, call the passed function f. Otherwise return a curried function f that expects the rest of the arguments. If you want to curry a function that accepts a variable number of arguments (a variadic function, e.g. Math.min()), you can optionally pass the number of arguments to the second parameter arity.

const curry = (fn, arity = fn.length, ...args) =>
   arity <= args.length
     ? fn(...args)
     : curry.bind(null, fn, arity, ...args);
-// curry(Math.pow)(2)(10) -> 1024
-// curry(Math.min, 3)(10)(50)(2) -> 2
-
-

functionName

-

Logs the name of a function.

-

Use console.debug() and the name property of the passed method to log the method's name to the debug channel of the console.

-
const functionName = fn => (console.debug(fn.name), fn);
-// functionName(Math.max) -> max (logged in debug channel of console)
-
-

pipe

-

Performs left-to-right function composition.

-

Use Array.reduce() with the spread operator (...) to perform left-to-right function composition. -The first (leftmost) function can accept one or more arguments; the remaining functions must be unary.

-
const pipeFunctions = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args)));
+// curry(Math.pow)(2)(10) -> 1024
+// curry(Math.min, 3)(10)(50)(2) -> 2
+

functionName

Logs the name of a function.

Use console.debug() and the name property of the passed method to log the method's name to the debug channel of the console.

const functionName = fn => (console.debug(fn.name), fn);
+// functionName(Math.max) -> max (logged in debug channel of console)
+

pipe

Performs left-to-right function composition.

Use Array.reduce() with the spread operator (...) to perform left-to-right function composition. The first (leftmost) function can accept one or more arguments; the remaining functions must be unary.

const pipeFunctions = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args)));
 /*
-const add5 = x => x + 5
-const multiply = (x, y) => x * y
+const add5 = x => x + 5
+const multiply = (x, y) => x * y
 const multiplyAndAdd5 = pipeFunctions(multiply, add5)
-multiplyAndAdd5(5, 2) -> 15
+multiplyAndAdd5(5, 2) -> 15
 */
-
-

promisify

-

Converts an asynchronous function to return a promise.

-

Use currying to return a function returning a Promise that calls the original function. -Use the ...rest operator to pass in all the parameters.

-

In Node 8+, you can use util.promisify

-
const promisify = func =>
-  (...args) =>
-    new Promise((resolve, reject) =>
-      func(...args, (err, result) =>
+

promisify

Converts an asynchronous function to return a promise.

Use currying to return a function returning a Promise that calls the original function. Use the ...rest operator to pass in all the parameters.

In Node 8+, you can use util.promisify

const promisify = func =>
+  (...args) =>
+    new Promise((resolve, reject) =>
+      func(...args, (err, result) =>
         err ? reject(err) : resolve(result))
     );
-// const delay = promisify((d, cb) => setTimeout(cb, d))
-// delay(2000).then(() => console.log('Hi!')) -> Promise resolves after 2s
-
-

runPromisesInSeries

-

Runs an array of promises in series.

-

Use Array.reduce() to create a promise chain, where each promise returns the next promise when resolved.

-
const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve());
-// const delay = (d) => new Promise(r => setTimeout(r, d))
-// runPromisesInSeries([() => delay(1000), () => delay(2000)]) -> executes each promise sequentially, taking a total of 3 seconds to complete
-
-

sleep

-

Delays the execution of an asynchronous function.

-

Delay executing part of an async function, by putting it to sleep, returning a Promise.

-
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
+// const delay = promisify((d, cb) => setTimeout(cb, d))
+// delay(2000).then(() => console.log('Hi!')) -> Promise resolves after 2s
+

runPromisesInSeries

Runs an array of promises in series.

Use Array.reduce() to create a promise chain, where each promise returns the next promise when resolved.

const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve());
+// const delay = (d) => new Promise(r => setTimeout(r, d))
+// runPromisesInSeries([() => delay(1000), () => delay(2000)]) -> executes each promise sequentially, taking a total of 3 seconds to complete
+

sleep

Delays the execution of an asynchronous function.

Delay executing part of an async function, by putting it to sleep, returning a Promise.

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
 /*
 async function sleepyWork() {
   console.log('I\'m going to sleep for 1 second.');
@@ -716,215 +247,93 @@ async function sleepyWork() {
   console.log('I woke up after 1 second.');
 }
 */
-
-

Math

-

arrayAverage

-

Returns the average of an array of numbers.

-

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

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

arraySum

-

Returns the sum of an array of numbers.

-

Use Array.reduce() to add each value to an accumulator, initialized with a value of 0.

-
const arraySum = arr => arr.reduce((acc, val) => acc + val, 0);
-// arraySum([1,2,3,4]) -> 10
-
-

collatz

-

Applies the Collatz algorithm.

-

If n is even, return n/2. Otherwise return 3n+1.

-
const collatz = n => (n % 2 == 0) ? (n / 2) : (3 * n + 1);
-// collatz(8) --> 4
-// collatz(5) --> 16
-
-

digitize

-

Converts a number to an array of digits.

-

Convert the number to a string, using spread operators in ES6([...string]) build an array. -Use Array.map() and parseInt() to transform each value to an integer.

-
const digitize = n => [...''+n].map(i => parseInt(i));
-// digitize(2334) -> [2, 3, 3, 4]
-
-

distance

-

Returns the distance between two points.

-

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

-
const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0);
-// distance(1,1, 2,3) -> 2.23606797749979
-
-

factorial

-

Calculates the factorial of a number.

-

Use recursion. -If n is less than or equal to 1, return 1. -Otherwise, return the product of n and the factorial of n - 1. -Throws an exception if n is a negative number.

-
const factorial = n =>
-  n < 0 ? (() => { throw new TypeError('Negative numbers are not allowed!') })()
+

Math

arrayAverage

Returns the average of an array of numbers.

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

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

arraySum

Returns the sum of an array of numbers.

Use Array.reduce() to add each value to an accumulator, initialized with a value of 0.

const arraySum = arr => arr.reduce((acc, val) => acc + val, 0);
+// arraySum([1,2,3,4]) -> 10
+

collatz

Applies the Collatz algorithm.

If n is even, return n/2. Otherwise return 3n+1.

const collatz = n => (n % 2 == 0) ? (n / 2) : (3 * n + 1);
+// collatz(8) --> 4
+// collatz(5) --> 16
+

digitize

Converts a number to an array of digits.

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

const digitize = n => [...''+n].map(i => parseInt(i));
+// digitize(2334) -> [2, 3, 3, 4]
+

distance

Returns the distance between two points.

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

const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0);
+// distance(1,1, 2,3) -> 2.23606797749979
+

factorial

Calculates the factorial of a number.

Use recursion. If n is less than or equal to 1, return 1. Otherwise, return the product of n and the factorial of n - 1. Throws an exception if n is a negative number.

const factorial = n =>
+  n < 0 ? (() => { throw new TypeError('Negative numbers are not allowed!') })()
   : n <= 1 ? 1 : n * factorial(n - 1);
-// factorial(6) -> 720
-
-

fibonacci

-

Generates an array, containing the Fibonacci sequence, up until the nth term.

-

Create an empty array of the specific length, initializing the first two values (0 and 1). -Use Array.reduce() to add values into the array, using the sum of the last two values, except for the first two.

-
const fibonacci = n =>
-  Array(n).fill(0).reduce((acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), []);
-// fibonacci(5) -> [0,1,1,2,3]
-
-

gcd

-

Calculates the greatest common divisor between two numbers.

-

Use recursion. -Base case is when y equals 0. In this case, return x. -Otherwise, return the GCD of y and the remainder of the division x/y.

-
const gcd = (x, y) => !y ? x : gcd(y, x % y);
-// gcd (8, 36) -> 4
-
-

hammingDistance

-

Calculates the Hamming distance between two values.

-

Use XOR operator (^) to find the bit difference between the two numbers, convert to binary string using toString(2). -Count and return the number of 1s in the string, using match(/1/g).

-
const hammingDistance = (num1, num2) =>
+// factorial(6) -> 720
+

fibonacci

Generates an array, containing the Fibonacci sequence, up until the nth term.

Create an empty array of the specific length, initializing the first two values (0 and 1). Use Array.reduce() to add values into the array, using the sum of the last two values, except for the first two.

const fibonacci = n =>
+  Array(n).fill(0).reduce((acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), []);
+// fibonacci(5) -> [0,1,1,2,3]
+

gcd

Calculates the greatest common divisor between two numbers.

Use recursion. Base case is when y equals 0. In this case, return x. Otherwise, return the GCD of y and the remainder of the division x/y.

const gcd = (x, y) => !y ? x : gcd(y, x % y);
+// gcd (8, 36) -> 4
+

hammingDistance

Calculates the Hamming distance between two values.

Use XOR operator (^) to find the bit difference between the two numbers, convert to binary string using toString(2). Count and return the number of 1s in the string, using match(/1/g).

const hammingDistance = (num1, num2) =>
   ((num1 ^ num2).toString(2).match(/1/g) || '').length;
-// hammingDistance(2,3) -> 1
-
-

isArmstrongNumber

-

Checks if the given number is an armstrong number or not.

-

Convert the given number into array of digits. Use Math.pow() to get the appropriate power for each digit and sum them up. If the sum is equal to the number itself, return true otherwise false.

-
const isArmstrongNumber = digits => 
-  ( arr => arr.reduce( ( a, d ) => a + Math.pow( parseInt( d ), arr.length ), 0 ) == digits ? true : false )( ( digits+'' ).split( '' ) );
-// isArmstrongNumber(1634) -> true
-// isArmstrongNumber(371) -> true
-// isArmstrongNumber(56) -> false
-
-

isDivisible

-

Checks if the first numeric argument is divisible by the second one.

-

Use the modulo operator (%) to check if the remainder is equal to 0.

-
const isDivisible = (dividend, divisor) => dividend % divisor === 0;
-// isDivisible(6,3) -> true
-
-

isEven

-

Returns true if the given number is even, false otherwise.

-

Checks whether a number is odd or even using the modulo (%) operator. -Returns true if the number is even, false if the number is odd.

-
const isEven = num => num % 2 === 0;
-// isEven(3) -> false
-
-

isPrime

-

Checks if the provided integer is a prime number.

-

Returns false if the provided number has positive divisors other than 1 and itself or if the number itself is less than 2.

-
const isPrime = num => {
+// hammingDistance(2,3) -> 1
+

isArmstrongNumber

Checks if the given number is an armstrong number or not.

Convert the given number into array of digits. Use Math.pow() to get the appropriate power for each digit and sum them up. If the sum is equal to the number itself, return true otherwise false.

const isArmstrongNumber = digits => 
+  ( arr => arr.reduce( ( a, d ) => a + Math.pow( parseInt( d ), arr.length ), 0 ) == digits ? true : false )( ( digits+'' ).split( '' ) );
+// isArmstrongNumber(1634) -> true
+// isArmstrongNumber(371) -> true
+// isArmstrongNumber(56) -> false
+

isDivisible

Checks if the first numeric argument is divisible by the second one.

Use the modulo operator (%) to check if the remainder is equal to 0.

const isDivisible = (dividend, divisor) => dividend % divisor === 0;
+// isDivisible(6,3) -> true
+

isEven

Returns true if the given number is even, false otherwise.

Checks whether a number is odd or even using the modulo (%) operator. Returns true if the number is even, false if the number is odd.

const isEven = num => num % 2 === 0;
+// isEven(3) -> false
+

isPrime

Checks if the provided integer is a prime number.

Returns false if the provided number has positive divisors other than 1 and itself or if the number itself is less than 2.

const isPrime = num => {
   for (var i = 2; i < num; i++) if (num % i == 0) return false;
-  return num >= 2;
+  return num >= 2;
 }
-// isPrime(11) -> true
-// isPrime(12) -> false
-// isPrime(1) -> false
-
-

lcm

-

Returns the least common multiple of two numbers.

-

Use the greatest common divisor (GCD) formula and Math.abs() to determine the least common multiple. -The GCD formula uses recursion.

-
const lcm = (x,y) => {
-  const gcd = (x, y) => !y ? x : gcd(y, x % y);
+// isPrime(11) -> true
+// isPrime(12) -> false
+// isPrime(1) -> false
+

lcm

Returns the least common multiple of two numbers.

Use the greatest common divisor (GCD) formula and Math.abs() to determine the least common multiple. The GCD formula uses recursion.

const lcm = (x,y) => {
+  const gcd = (x, y) => !y ? x : gcd(y, x % y);
   return Math.abs(x*y)/(gcd(x,y));
 };
-// lcm(12,7) -> 84
-
-

median

-

Returns the median of an array of numbers.

-

Find the middle of the array, use Array.sort() to sort the values. -Return the number at the midpoint if length is odd, otherwise the average of the two middle numbers.

-
const median = arr => {
-  const mid = Math.floor(arr.length / 2), nums = [...arr].sort((a, b) => a - b);
+// lcm(12,7) -> 84
+

median

Returns the median of an array of numbers.

Find the middle of the array, use Array.sort() to sort the values. Return the number at the midpoint if length is odd, otherwise the average of the two middle numbers.

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;
 };
-// median([5,6,50,1,-5]) -> 5
-// median([0,10,-2,7]) -> 3.5
-
-

palindrome

-

Returns true if the given string is a palindrome, false otherwise.

-

Convert string toLowerCase() and use replace() to remove non-alphanumeric characters from it. -Then, split('') into individual characters, reverse(), join('') and compare to the original, unreversed string, after converting it tolowerCase().

-
const palindrome = str => {
+// median([5,6,50,1,-5]) -> 5
+// median([0,10,-2,7]) -> 3.5
+

palindrome

Returns true if the given string is a palindrome, false otherwise.

Convert string toLowerCase() and use replace() to remove non-alphanumeric characters from it. Then, split('') into individual characters, reverse(), join('') and compare to the original, unreversed string, after converting it tolowerCase().

const palindrome = str => {
   const s = str.toLowerCase().replace(/[\W_]/g,'');
   return s === s.split('').reverse().join('');
 }
-// palindrome('taco cat') -> true
-
-

percentile

-

Uses the percentile formula to calculate how many numbers in the given array are less or equal to the given value.

-

Use Array.reduce() to calculate how many numbers are below the value and how many are the same value and apply the percentile formula.

-
const percentile = (arr, val) =>
-  100 * arr.reduce((acc,v) => acc + (v < val ? 1 : 0) + (v === val ? 0.5 : 0), 0) / arr.length;
-// percentile([1,2,3,4,5,6,7,8,9,10], 6) -> 55
-
-

powerset

-

Returns the powerset of a given array of numbers.

-

Use Array.reduce() combined with Array.map() to iterate over elements and combine into an array containing all combinations.

-
const powerset = arr =>
-  arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]);
-// powerset([1,2]) -> [[], [1], [2], [2,1]]
-
-

randomIntegerInRange

-

Returns a random integer in the specified range.

-

Use Math.random() to generate a random number and map it to the desired range, using Math.floor() to make it an integer.

-
const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
-// randomIntegerInRange(0, 5) -> 2
-
-

randomNumberInRange

-

Returns a random number in the specified range.

-

Use Math.random() to generate a random value, map it to the desired range using multiplication.

-
const randomNumberInRange = (min, max) => Math.random() * (max - min) + min;
-// randomNumberInRange(2,10) -> 6.0211363285087005
-
-

round

-

Rounds a number to a specified amount of digits.

-

Use Math.round() and template literals to round the number to the specified number of digits. -Omit the second argument, decimals to round to an integer.

-
const round = (n, decimals=0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`);
-// round(1.005, 2) -> 1.01
-
-

standardDeviation

-

Returns the standard deviation of an array of numbers.

-

Use Array.reduce() to calculate the mean, variance and the sum of the variance of the values, the variance of the values, then -determine the standard deviation. -You can omit the second argument to get the sample standard deviation or set it to true to get the population standard deviation.

-
const standardDeviation = (arr, usePopulation = false) => {
-  const mean = arr.reduce((acc, val) => acc + val, 0) / arr.length;
+// palindrome('taco cat') -> true
+

percentile

Uses the percentile formula to calculate how many numbers in the given array are less or equal to the given value.

Use Array.reduce() to calculate how many numbers are below the value and how many are the same value and apply the percentile formula.

const percentile = (arr, val) =>
+  100 * arr.reduce((acc,v) => acc + (v < val ? 1 : 0) + (v === val ? 0.5 : 0), 0) / arr.length;
+// percentile([1,2,3,4,5,6,7,8,9,10], 6) -> 55
+

powerset

Returns the powerset of a given array of numbers.

Use Array.reduce() combined with Array.map() to iterate over elements and combine into an array containing all combinations.

const powerset = arr =>
+  arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]);
+// powerset([1,2]) -> [[], [1], [2], [2,1]]
+

randomIntegerInRange

Returns a random integer in the specified range.

Use Math.random() to generate a random number and map it to the desired range, using Math.floor() to make it an integer.

const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
+// randomIntegerInRange(0, 5) -> 2
+

randomNumberInRange

Returns a random number in the specified range.

Use Math.random() to generate a random value, map it to the desired range using multiplication.

const randomNumberInRange = (min, max) => Math.random() * (max - min) + min;
+// randomNumberInRange(2,10) -> 6.0211363285087005
+

round

Rounds a number to a specified amount of digits.

Use Math.round() and template literals to round the number to the specified number of digits. Omit the second argument, decimals to round to an integer.

const round = (n, decimals=0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`);
+// round(1.005, 2) -> 1.01
+

standardDeviation

Returns the standard deviation of an array of numbers.

Use Array.reduce() to calculate the mean, variance and the sum of the variance of the values, the variance of the values, then determine the standard deviation. You can omit the second argument to get the sample standard deviation or set it to true to get the population standard deviation.

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))
+    arr.reduce((acc, val) => acc.concat(Math.pow(val - mean, 2)), [])
+       .reduce((acc, val) => acc + val, 0) / (arr.length - (usePopulation ? 0 : 1))
   );
 };
-// standardDeviation([10,2,38,23,38,23,21]) -> 13.284434142114991 (sample)
-// standardDeviation([10,2,38,23,38,23,21], true) -> 12.29899614287479 (population)
-
-

Media

-

speechSynthesis

-

Performs speech synthesis (experimental).

-

Use SpeechSynthesisUtterance.voice and window.speechSynthesis.getVoices() to convert a message to speech. -Use window.speechSynthesis.speak() to play the message.

-

Learn more about the SpeechSynthesisUtterance interface of the Web Speech API.

-
const speechSynthesis = message => {
+// standardDeviation([10,2,38,23,38,23,21]) -> 13.284434142114991 (sample)
+// standardDeviation([10,2,38,23,38,23,21], true) -> 12.29899614287479 (population)
+

Media

speechSynthesis

Performs speech synthesis (experimental).

Use SpeechSynthesisUtterance.voice and window.speechSynthesis.getVoices() to convert a message to speech. Use window.speechSynthesis.speak() to play the message.

Learn more about the SpeechSynthesisUtterance interface of the Web Speech API.

const speechSynthesis = message => {
   const msg = new SpeechSynthesisUtterance(message);
   msg.voice = window.speechSynthesis.getVoices()[0];
   window.speechSynthesis.speak(msg);
 };
-// speechSynthesis('Hello, World') -> plays the message
-
-

Node

-

JSONToFile

-

Writes a JSON object to a file.

-

Use fs.writeFile(), template literals and JSON.stringify() to write a json object to a .json file.

-
const fs = require('fs');
-const JSONToFile = (obj, filename) => fs.writeFile(`${filename}.json`, JSON.stringify(obj, null, 2))
-// JSONToFile({test: "is passed"}, 'testJsonFile') -> writes the object to 'testJsonFile.json'
-
-

readFileLines

-

Returns an array of lines from the specified file.

-

Use readFileSync function in fs node package to create a Buffer from a file. -convert buffer to string using toString(encoding) function. -creating an array from contents of file by spliting file content line by line (each \n).

-
const fs = require('fs');
-const readFileLines = filename => fs.readFileSync(filename).toString('UTF8').split('\n');
+// speechSynthesis('Hello, World') -> plays the message
+

Node

JSONToFile

Writes a JSON object to a file.

Use fs.writeFile(), template literals and JSON.stringify() to write a json object to a .json file.

const fs = require('fs');
+const JSONToFile = (obj, filename) => fs.writeFile(`${filename}.json`, JSON.stringify(obj, null, 2))
+// JSONToFile({test: "is passed"}, 'testJsonFile') -> writes the object to 'testJsonFile.json'
+

readFileLines

Returns an array of lines from the specified file.

Use readFileSync function in fs node package to create a Buffer from a file. convert buffer to string using toString(encoding) function. creating an array from contents of file by spliting file content line by line (each \n).

const fs = require('fs');
+const readFileLines = filename => fs.readFileSync(filename).toString('UTF8').split('\n');
 /*
 contents of test.txt :
   line1
@@ -932,16 +341,10 @@ contents of test.txt :
   line3
   ___________________________
 let arr = readFileLines('test.txt')
-console.log(arr) // -> ['line1', 'line2', 'line3']
+console.log(arr) // -> ['line1', 'line2', 'line3']
 */
-
-

Object

-

cleanObj

-

Removes any properties except the ones specified from a JSON object.

-

Use Object.keys() method to loop over given json object and deleting keys that are not included in given array. -Also if you give it a special key (childIndicator) it will search deeply inside it to apply function to inner objects too.

-
const cleanObj = (obj, keysToKeep = [], childIndicator) => {
-  Object.keys(obj).forEach(key => {
+

Object

cleanObj

Removes any properties except the ones specified from a JSON object.

Use Object.keys() method to loop over given json object and deleting keys that are not included in given array. Also if you give it a special key (childIndicator) it will search deeply inside it to apply function to inner objects too.

const cleanObj = (obj, keysToKeep = [], childIndicator) => {
+  Object.keys(obj).forEach(key => {
     if (key === childIndicator) {
       cleanObj(obj[key], keysToKeep, childIndicator);
     } else if (!keysToKeep.includes(key)) {
@@ -951,32 +354,19 @@ Also if you give it a special key (childIndicator) it will search d
 }
 /*
   const testObj = {a: 1, b: 2, children: {a: 1, b: 2}}
-  cleanObj(testObj, ["a"],"children")
+  cleanObj(testObj, ["a"],"children")
   console.log(testObj)// { a: 1, children : { a: 1}}
 */
-
-

objectFromPairs

-

Creates an object from the given key-value pairs.

-

Use Array.reduce() to create and combine key-value pairs.

-
const objectFromPairs = arr => arr.reduce((a, v) => (a[v[0]] = v[1], a), {});
-// objectFromPairs([['a',1],['b',2]]) -> {a: 1, b: 2}
-
-

objectToPairs

-

Creates an array of key-value pair arrays from an object.

-

Use Object.keys() and Array.map() to iterate over the object's keys and produce an array with key-value pairs.

-
const objectToPairs = obj => Object.keys(obj).map(k => [k, obj[k]]);
-// objectToPairs({a: 1, b: 2}) -> [['a',1],['b',2]])
-
-

orderBy

-

Returns a sorted array of objects ordered by properties and orders.

-

Uses a custom implementation of sort, that reduces the props array argument with a default value of 0, it uses destructuring to swap the properties position depending on the order passed. -If no orders array is passed it sort by 'asc' by default.

-
const orderBy = (arr, props, orders) =>
-  arr.sort((a, b) =>
-    props.reduce((acc, prop, i) => {
+

objectFromPairs

Creates an object from the given key-value pairs.

Use Array.reduce() to create and combine key-value pairs.

const objectFromPairs = arr => arr.reduce((a, v) => (a[v[0]] = v[1], a), {});
+// objectFromPairs([['a',1],['b',2]]) -> {a: 1, b: 2}
+

objectToPairs

Creates an array of key-value pair arrays from an object.

Use Object.keys() and Array.map() to iterate over the object's keys and produce an array with key-value pairs.

const objectToPairs = obj => Object.keys(obj).map(k => [k, obj[k]]);
+// objectToPairs({a: 1, b: 2}) -> [['a',1],['b',2]])
+

orderBy

Returns a sorted array of objects ordered by properties and orders.

Uses a custom implementation of sort, that reduces the props array argument with a default value of 0, it uses destructuring to swap the properties position depending on the order passed. If no orders array is passed it sort by 'asc' by default.

const orderBy = (arr, props, orders) =>
+  arr.sort((a, b) =>
+    props.reduce((acc, prop, i) => {
       if (acc === 0) {
         const [p1, p2] = orders[i] === 'asc' ? [a[prop], b[prop]] : [b[prop], a[prop]];
-        acc = p1 > p2 ? 1 : p1 < p2 ? -1 : 0;
+        acc = p1 > p2 ? 1 : p1 < p2 ? -1 : 0;
       }
       return acc;
     }, 0)
@@ -984,281 +374,130 @@ If no orders array is passed it sort by 'asc' by default.

/* const users = [{ 'name': 'fred', 'age': 48 },{ 'name': 'barney', 'age': 36 }, { 'name': 'fred', 'age': 40 },{ 'name': 'barney', 'age': 34 }]; -orderby(users, ['name', 'age'], ['asc', 'desc']) -> [{name: 'barney', age: 36}, {name: 'barney', age: 34}, {name: 'fred', age: 48}, {name: 'fred', age: 40}] -orderby(users, ['name', 'age']) -> [{name: 'barney', age: 34}, {name: 'barney', age: 36}, {name: 'fred', age: 40}, {name: 'fred', age: 48}] +orderby(users, ['name', 'age'], ['asc', 'desc']) -> [{name: 'barney', age: 36}, {name: 'barney', age: 34}, {name: 'fred', age: 48}, {name: 'fred', age: 40}] +orderby(users, ['name', 'age']) -> [{name: 'barney', age: 34}, {name: 'barney', age: 36}, {name: 'fred', age: 40}, {name: 'fred', age: 48}] */ -
-

select

-

Retrieve a property that indicated by the selector from object.

-

If property not exists returns undefined.

-
const select = (from, selector) =>
-  selector.split('.').reduce((prev, cur) => prev && prev[cur], from);
+

select

Retrieve a property that indicated by the selector from object.

If property not exists returns undefined.

const select = (from, selector) =>
+  selector.split('.').reduce((prev, cur) => prev && prev[cur], from);
 
 // const obj = {selector: {to: {val: 'val to select'}}};
-// select(obj, 'selector.to.val'); -> 'val to select'
-
-

shallowClone

-

Creates a shallow clone of an object.

-

Use Object.assign() and an empty object ({}) to create a shallow clone of the original.

-
const shallowClone = obj => Object.assign({}, obj);
+// select(obj, 'selector.to.val'); -> 'val to select'
+

shallowClone

Creates a shallow clone of an object.

Use Object.assign() and an empty object ({}) to create a shallow clone of the original.

const shallowClone = obj => Object.assign({}, obj);
 /*
 const a = { x: true, y: 1 };
 const b = shallowClone(a);
-a === b -> false
+a === b -> false
 */
-
-

truthCheckCollection

-

Checks if the predicate (second argument) is truthy on all elements of a collection (first argument).

-

Use Array.every() to check if each passed object has the specified property and if it returns a truthy value.

-
const truthCheckCollection = (collection, pre) => (collection.every(obj => obj[pre]));
-// truthCheckCollection([{"user": "Tinky-Winky", "sex": "male"}, {"user": "Dipsy", "sex": "male"}], "sex") -> true
-
-

String

-

anagrams

-

Generates all anagrams of a string (contains duplicates).

-

Use recursion. -For each letter in the given string, create all the partial anagrams for the rest of its letters. -Use Array.map() to combine the letter with each partial anagram, then Array.reduce() to combine all anagrams in one array. -Base cases are for string length equal to 2 or 1.

-
const anagrams = str => {
+

truthCheckCollection

Checks if the predicate (second argument) is truthy on all elements of a collection (first argument).

Use Array.every() to check if each passed object has the specified property and if it returns a truthy value.

const truthCheckCollection = (collection, pre) => (collection.every(obj => obj[pre]));
+// truthCheckCollection([{"user": "Tinky-Winky", "sex": "male"}, {"user": "Dipsy", "sex": "male"}], "sex") -> true
+

String

anagrams

Generates all anagrams of a string (contains duplicates).

Use recursion. For each letter in the given string, create all the partial anagrams for the rest of its letters. Use Array.map() to combine the letter with each partial anagram, then Array.reduce() to combine all anagrams in one array. Base cases are for string length equal to 2 or 1.

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)), []);
+  return str.split('').reduce((acc, letter, i) =>
+    acc.concat(anagrams(str.slice(0, i) + str.slice(i + 1)).map(val => letter + val)), []);
 };
-// anagrams('abc') -> ['abc','acb','bac','bca','cab','cba']
-
-

Capitalize

-

Capitalizes the first letter of a string.

-

Use destructuring and toUpperCase() to capitalize first letter, ...rest to get array of characters after first letter and then Array.join('') to make it a string again. -Omit the lowerRest parameter to keep the rest of the string intact, or set it to true to convert to lowercase.

-
const capitalize = ([first,...rest], lowerRest = false) =>
+// anagrams('abc') -> ['abc','acb','bac','bca','cab','cba']
+

Capitalize

Capitalizes the first letter of a string.

Use destructuring and toUpperCase() to capitalize first letter, ...rest to get array of characters after first letter and then Array.join('') to make it a string again. Omit the lowerRest parameter to keep the rest of the string intact, or set it to true to convert to lowercase.

const capitalize = ([first,...rest], lowerRest = false) =>
   first.toUpperCase() + (lowerRest ? rest.join('').toLowerCase() : rest.join(''));
-// capitalize('myName') -> 'MyName'
-// capitalize('myName', true) -> 'Myname'
-
-

capitalizeEveryWord

-

Capitalizes the first letter of every word in a string.

-

Use replace() to match the first character of each word and toUpperCase() to capitalize it.

-
const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase());
-// capitalizeEveryWord('hello world!') -> 'Hello World!'
-
-

countVowels

-

Retuns number of vowels in provided string.

-

Use a regular expression to count number of vowels (A, E, I, O, U) in a string.

-
const countVowels = str => (str.match(/[aeiou]/ig) || []).length;
-// countVowels('foobar') -> 3
-// countVowels('gym') -> 0
-
-

escapeRegExp

-

Escapes a string to use in a regular expression.

-

Use replace() to escape special characters.

-
const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
-// escapeRegExp('(test)') -> \\(test\\)
-
-

fromCamelCase

-

Converts a string from camelcase.

-

Use replace() to remove underscores, hyphens and spaces and convert words to camelcase. -Omit the second argument to use a default separator of _.

-
const fromCamelCase = (str, separator = '_') =>
+// capitalize('myName') -> 'MyName'
+// capitalize('myName', true) -> 'Myname'
+

capitalizeEveryWord

Capitalizes the first letter of every word in a string.

Use replace() to match the first character of each word and toUpperCase() to capitalize it.

const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase());
+// capitalizeEveryWord('hello world!') -> 'Hello World!'
+

countVowels

Retuns number of vowels in provided string.

Use a regular expression to count number of vowels (A, E, I, O, U) in a string.

const countVowels = str => (str.match(/[aeiou]/ig) || []).length;
+// countVowels('foobar') -> 3
+// countVowels('gym') -> 0
+

escapeRegExp

Escapes a string to use in a regular expression.

Use replace() to escape special characters.

const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+// escapeRegExp('(test)') -> \\(test\\)
+

fromCamelCase

Converts a string from camelcase.

Use replace() to remove underscores, hyphens and spaces and convert words to camelcase. Omit the second argument to use a default separator of _.

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();
-// fromCamelCase('someDatabaseFieldName', ' ') -> 'some database field name'
-// fromCamelCase('someLabelThatNeedsToBeCamelized', '-') -> 'some-label-that-needs-to-be-camelized'
-// fromCamelCase('someJavascriptProperty', '_') -> 'some_javascript_property'
-
-

reverseString

-

Reverses a string.

-

Use split('') and Array.reverse() to reverse the order of the characters in the string. -Combine characters to get a string using join('').

-
const reverseString = str => str.split('').reverse().join('');
-// reverseString('foobar') -> 'raboof'
-
-

sortCharactersInString

-

Alphabetically sorts the characters in a string.

-

Split the string using split(''), Array.sort() utilizing localeCompare(), recombine using join('').

-
const sortCharactersInString = str =>
-  str.split('').sort((a, b) => a.localeCompare(b)).join('');
-// sortCharactersInString('cabbage') -> 'aabbceg'
-
-

stringToArrayOfWords

-

Converts a given string into an array of words.

-

Use String.split() with a supplied pattern (defaults to non alpha as a regex) to convert to an array of strings. Use Array.filter() to remove any empty strings. -Omit the second argument to use the default regex.

-
const stringToArrayOfWords = (str, pattern = /[^a-zA-Z-]+/) => str.split(pattern).filter(Boolean);
-// stringToArrayOfWords("I love javaScript!!") -> ["I", "love", "javaScript"]
-// stringToArrayOfWords("python, javaScript & coffee") -> ["python", "javaScript", "coffee"]
-
-

toCamelCase

-

Converts a string to camelcase.

-

Use replace() to remove underscores, hyphens and spaces and convert words to camelcase.

-
const toCamelCase = str =>
-  str.replace(/^([A-Z])|[\s-_]+(\w)/g, (match, p1, p2, offset) =>  p2 ? p2.toUpperCase() : p1.toLowerCase());
-// toCamelCase("some_database_field_name") -> 'someDatabaseFieldName'
-// toCamelCase("Some label that needs to be camelized") -> 'someLabelThatNeedsToBeCamelized'
-// toCamelCase("some-javascript-property") -> 'someJavascriptProperty'
-// toCamelCase("some-mixed_string with spaces_underscores-and-hyphens") -> 'someMixedStringWithSpacesUnderscoresAndHyphens'
-
-

truncateString

-

Truncates a string up to a specified length.

-

Determine if the string's length is greater than num. -Return the string truncated to the desired length, with ... appended to the end or the original string.

-
const truncateString = (str, num) =>
-  str.length > num ? str.slice(0, num > 3 ? num - 3 : num) + '...' : str;
-// truncateString('boomerang', 7) -> 'boom...'
-
-

Utility

-

coalesce

-

Returns the first non-null/undefined argument.

-

Use Array.find() to return the first non null/undefined argument.

-
const coalesce = (...args) => args.find(_ => ![undefined, null].includes(_))
-// coalesce(null,undefined,"",NaN, "Waldo") -> ""
-
-

coalesceFactory

-

Returns a customized coalesce function that returns the first argument that returns true from the provided argument validation function.

-

Use Array.find() to return the first argument that returns true from the provided argument validation function.

-
const coalesceFactory = valid => (...args) => args.find(valid);
-// const customCoalesce = coalesceFactory(_ => ![null, undefined, "", NaN].includes(_))
-// customCoalesce(undefined, null, NaN, "", "Waldo") //-> "Waldo"
-
-

extendHex

-

Extends a 3-digit color code to a 6-digit color code.

-

Use Array.map(), split() and Array.join() to join the mapped array for converting a 3-digit RGB notated hexadecimal color-code to the 6-digit form. -Array.slice() is used to remove # from string start since it's added once.

-
const extendHex = shortHex =>
-  '#' + shortHex.slice(shortHex.startsWith('#') ? 1 : 0).split('').map(x => x+x).join('')
-// extendHex('#03f') -> '#0033ff'
-// extendHex('05a') -> '#0055aa'
-
-

getType

-

Returns the native type of a value.

-

Returns lowercased constructor name of value, "undefined" or "null" if value is undefined or null

-
const getType = v =>
+// fromCamelCase('someDatabaseFieldName', ' ') -> 'some database field name'
+// fromCamelCase('someLabelThatNeedsToBeCamelized', '-') -> 'some-label-that-needs-to-be-camelized'
+// fromCamelCase('someJavascriptProperty', '_') -> 'some_javascript_property'
+

reverseString

Reverses a string.

Use split('') and Array.reverse() to reverse the order of the characters in the string. Combine characters to get a string using join('').

const reverseString = str => str.split('').reverse().join('');
+// reverseString('foobar') -> 'raboof'
+

sortCharactersInString

Alphabetically sorts the characters in a string.

Split the string using split(''), Array.sort() utilizing localeCompare(), recombine using join('').

const sortCharactersInString = str =>
+  str.split('').sort((a, b) => a.localeCompare(b)).join('');
+// sortCharactersInString('cabbage') -> 'aabbceg'
+

stringToArrayOfWords

Converts a given string into an array of words.

Use String.split() with a supplied pattern (defaults to non alpha as a regex) to convert to an array of strings. Use Array.filter() to remove any empty strings. Omit the second argument to use the default regex.

const stringToArrayOfWords = (str, pattern = /[^a-zA-Z-]+/) => str.split(pattern).filter(Boolean);
+// stringToArrayOfWords("I love javaScript!!") -> ["I", "love", "javaScript"]
+// stringToArrayOfWords("python, javaScript & coffee") -> ["python", "javaScript", "coffee"]
+

toCamelCase

Converts a string to camelcase.

Use replace() to remove underscores, hyphens and spaces and convert words to camelcase.

const toCamelCase = str =>
+  str.replace(/^([A-Z])|[\s-_]+(\w)/g, (match, p1, p2, offset) =>  p2 ? p2.toUpperCase() : p1.toLowerCase());
+// toCamelCase("some_database_field_name") -> 'someDatabaseFieldName'
+// toCamelCase("Some label that needs to be camelized") -> 'someLabelThatNeedsToBeCamelized'
+// toCamelCase("some-javascript-property") -> 'someJavascriptProperty'
+// toCamelCase("some-mixed_string with spaces_underscores-and-hyphens") -> 'someMixedStringWithSpacesUnderscoresAndHyphens'
+

truncateString

Truncates a string up to a specified length.

Determine if the string's length is greater than num. Return the string truncated to the desired length, with ... appended to the end or the original string.

const truncateString = (str, num) =>
+  str.length > num ? str.slice(0, num > 3 ? num - 3 : num) + '...' : str;
+// truncateString('boomerang', 7) -> 'boom...'
+

Utility

coalesce

Returns the first non-null/undefined argument.

Use Array.find() to return the first non null/undefined argument.

const coalesce = (...args) => args.find(_ => ![undefined, null].includes(_))
+// coalesce(null,undefined,"",NaN, "Waldo") -> ""
+

coalesceFactory

Returns a customized coalesce function that returns the first argument that returns true from the provided argument validation function.

Use Array.find() to return the first argument that returns true from the provided argument validation function.

const coalesceFactory = valid => (...args) => args.find(valid);
+// const customCoalesce = coalesceFactory(_ => ![null, undefined, "", NaN].includes(_))
+// customCoalesce(undefined, null, NaN, "", "Waldo") //-> "Waldo"
+

extendHex

Extends a 3-digit color code to a 6-digit color code.

Use Array.map(), split() and Array.join() to join the mapped array for converting a 3-digit RGB notated hexadecimal color-code to the 6-digit form. Array.slice() is used to remove # from string start since it's added once.

const extendHex = shortHex =>
+  '#' + shortHex.slice(shortHex.startsWith('#') ? 1 : 0).split('').map(x => x+x).join('')
+// extendHex('#03f') -> '#0033ff'
+// extendHex('05a') -> '#0055aa'
+

getType

Returns the native type of a value.

Returns lowercased constructor name of value, "undefined" or "null" if value is undefined or null

const getType = v =>
   v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name.toLowerCase();
-// getType(new Set([1,2,3])) -> "set"
-
-

hexToRGB

-

Converts a color code to a rgb() or rgba() string if alpha value is provided.

-

Use bitwise right-shift operator and mask bits with & (and) operator to convert a hexadecimal color code (with or without prefixed with #) to a string with the RGB values. If it's 3-digit color code, first convert to 6-digit version. If any alpha value is provided alongside 6-digit hex, give rgba() string in return.

-
const hexToRGB = hex => {
+// getType(new Set([1,2,3])) -> "set"
+

hexToRGB

Converts a color code to a rgb() or rgba() string if alpha value is provided.

Use bitwise right-shift operator and mask bits with & (and) operator to convert a hexadecimal color code (with or without prefixed with #) to a string with the RGB values. If it's 3-digit color code, first convert to 6-digit version. If any alpha value is provided alongside 6-digit hex, give rgba() string in return.

const hexToRGB = hex => {
   let alpha = false, h = hex.slice(hex.startsWith('#') ? 1 : 0);
-  if (h.length === 3) h = [...h].map(x => x + x).join('');
+  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)}` : '') + ')';
+    + (h >>> (alpha ? 24 : 16)) + ', '
+    + ((h & (alpha ? 0x00ff0000 : 0x00ff00)) >>> (alpha ? 16 : 8)) + ', '
+    + ((h & (alpha ? 0x0000ff00 : 0x0000ff)) >>> (alpha ? 8 : 0))
+    + (alpha ? `, ${(h & 0x000000ff)}` : '') + ')';
 };
-// hexToRGB('#27ae60ff') -> 'rgba(39, 174, 96, 255)'
-// hexToRGB('27ae60') -> 'rgb(39, 174, 96)'
-// hexToRGB('#fff') -> 'rgb(255, 255, 255)'
+// hexToRGB('#27ae60ff') -> 'rgba(39, 174, 96, 255)'
+// hexToRGB('27ae60') -> 'rgb(39, 174, 96)'
+// hexToRGB('#fff') -> 'rgb(255, 255, 255)'
 
-
-

isArray

-

Checks if the given argument is an array.

-

Use Array.isArray() to check if a value is classified as an array.

-
const isArray = val => !!val && Array.isArray(val);
-// isArray(null) -> false
-// isArray([1]) -> true
-
-

isBoolean

-

Checks if the given argument is a native boolean element.

-

Use typeof to check if a value is classified as a boolean primitive.

-
const isBoolean = val => typeof val === 'boolean';
-// isBoolean(null) -> false
-// isBoolean(false) -> true
-
-

isFunction

-

Checks if the given argument is a function.

-

Use typeof to check if a value is classified as a function primitive.

-
const isFunction = val => val && typeof val === 'function';
-// isFunction('x') -> false
-// isFunction(x => x) -> true
-
-

isNumber

-

Checks if the given argument is a number.

-

Use typeof to check if a value is classified as a number primitive.

-
const isNumber = val => typeof val === 'number';
-// isNumber('1') -> false
-// isNumber(1) -> true
-
-

isString

-

Checks if the given argument is a string.

-

Use typeof to check if a value is classified as a string primitive.

-
const isString = val => typeof val === 'string';
-// isString(10) -> false
-// isString('10') -> true
-
-

isSymbol

-

Checks if the given argument is a symbol.

-

Use typeof to check if a value is classified as a symbol primitive.

-
const isSymbol = val => typeof val === 'symbol';
-// isSymbol('x') -> false
-// isSymbol(Symbol('x')) -> true
-
-

RGBToHex

-

Converts the values of RGB components to a colorcode.

-

Convert given RGB parameters to hexadecimal string using bitwise left-shift operator (<<) and toString(16), then padStart(6,'0') to get a 6-digit hexadecimal value.

-
const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0');
-// RGBToHex(255, 165, 1) -> 'ffa501'
-
-

timeTaken

-

Measures the time taken by a function to execute.

-

Use console.time() and console.timeEnd() to measure the difference between the start and end times to determine how long the callback took to execute.

-
const timeTaken = callback => {
+

isArray

Checks if the given argument is an array.

Use Array.isArray() to check if a value is classified as an array.

const isArray = val => !!val && Array.isArray(val);
+// isArray(null) -> false
+// isArray([1]) -> true
+

isBoolean

Checks if the given argument is a native boolean element.

Use typeof to check if a value is classified as a boolean primitive.

const isBoolean = val => typeof val === 'boolean';
+// isBoolean(null) -> false
+// isBoolean(false) -> true
+

isFunction

Checks if the given argument is a function.

Use typeof to check if a value is classified as a function primitive.

const isFunction = val => val && typeof val === 'function';
+// isFunction('x') -> false
+// isFunction(x => x) -> true
+

isNumber

Checks if the given argument is a number.

Use typeof to check if a value is classified as a number primitive.

const isNumber = val => typeof val === 'number';
+// isNumber('1') -> false
+// isNumber(1) -> true
+

isString

Checks if the given argument is a string.

Use typeof to check if a value is classified as a string primitive.

const isString = val => typeof val === 'string';
+// isString(10) -> false
+// isString('10') -> true
+

isSymbol

Checks if the given argument is a symbol.

Use typeof to check if a value is classified as a symbol primitive.

const isSymbol = val => typeof val === 'symbol';
+// isSymbol('x') -> false
+// isSymbol(Symbol('x')) -> true
+

RGBToHex

Converts the values of RGB components to a colorcode.

Convert given RGB parameters to hexadecimal string using bitwise left-shift operator (<<) and toString(16), then padStart(6,'0') to get a 6-digit hexadecimal value.

const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0');
+// RGBToHex(255, 165, 1) -> 'ffa501'
+

timeTaken

Measures the time taken by a function to execute.

Use console.time() and console.timeEnd() to measure the difference between the start and end times to determine how long the callback took to execute.

const timeTaken = callback => {
   console.time('timeTaken');  const r = callback();
   console.timeEnd('timeTaken');  return r;
 };
-// timeTaken(() => Math.pow(2, 10)) -> 1024
+// timeTaken(() => Math.pow(2, 10)) -> 1024
 // (logged): timeTaken: 0.02099609375ms
-
-

toOrdinalSuffix

-

Adds an ordinal suffix to a number.

-

Use the modulo operator (%) to find values of single and tens digits. -Find which ordinal pattern digits match. -If digit is found in teens pattern, use teens ordinal.

-
const toOrdinalSuffix = num => {
+

toOrdinalSuffix

Adds an ordinal suffix to a number.

Use the modulo operator (%) to find values of single and tens digits. Find which ordinal pattern digits match. If digit is found in teens pattern, use teens ordinal.

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];
+  return oPattern.includes(digits[0]) && !tPattern.includes(digits[1]) ? int + ordinals[digits[0] - 1] : int + ordinals[3];
 };
-// toOrdinalSuffix("123") -> "123rd"
-
-

UUIDGenerator

-

Generates a UUID.

-

Use crypto API to generate a UUID, compliant with RFC4122 version 4.

-
const UUIDGenerator = () =>
-  ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
-    (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
+// toOrdinalSuffix("123") -> "123rd"
+

UUIDGenerator

Generates a UUID.

Use crypto API to generate a UUID, compliant with RFC4122 version 4.

const UUIDGenerator = () =>
+  ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
+    (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
   );
-// UUIDGenerator() -> '7982fcfe-5721-4632-bede-6000885be57d'
-
-

validateEmail

-

Returns true if the given string is a valid email, false otherwise.

-

Use a regular expression to check if the email is valid. -Returns true if email is valid, false if not.

-
const validateEmail = str =>
-  /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(str);
-// validateEmail(mymail@gmail.com) -> true
-
-

validateNumber

-

Returns true if the given value is a number, false otherwise.

-

Use !isNaN in combination with parseFloat() to check if the argument is a number. -Use isFinite() to check if the number is finite. -Use Number() to check if the coercion holds.

-
const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n;
-// validateNumber('10') -> true
-
-

- -
-
- - - - +// UUIDGenerator() -> '7982fcfe-5721-4632-bede-6000885be57d' +

validateEmail

Returns true if the given string is a valid email, false otherwise.

Use a regular expression to check if the email is valid. Returns true if email is valid, false if not.

const validateEmail = str =>
+  /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(str);
+// validateEmail(mymail@gmail.com) -> true
+

validateNumber

Returns true if the given value is a number, false otherwise.

Use !isNaN in combination with parseFloat() to check if the argument is a number. Use isFinite() to check if the number is finite. Use Number() to check if the coercion holds.

const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n;
+// validateNumber('10') -> true
+

\ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 6f628179a..d0fb28b03 100644 --- a/package-lock.json +++ b/package-lock.json @@ -322,6 +322,15 @@ "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=" }, + "camel-case": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", + "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", + "requires": { + "no-case": "2.3.2", + "upper-case": "1.1.3" + } + }, "camelcase": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", @@ -389,6 +398,14 @@ "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==" }, + "clean-css": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.1.9.tgz", + "integrity": "sha1-Nc7ornaHpJuYA09w3gDE7dOCYwE=", + "requires": { + "source-map": "0.5.7" + } + }, "cli-boxes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", @@ -1398,6 +1415,33 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=" }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=" + }, + "html-minifier": { + "version": "3.5.7", + "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.7.tgz", + "integrity": "sha512-GISXn6oKDo7+gVpKOgZJTbHMCUI2TSGfpg/8jgencWhWJsvEmsvp3M8emX7QocsXsYznWloLib3OeSfeyb/ewg==", + "requires": { + "camel-case": "3.0.0", + "clean-css": "4.1.9", + "commander": "2.12.2", + "he": "1.1.1", + "ncname": "1.0.0", + "param-case": "2.1.1", + "relateurl": "0.2.7", + "uglify-js": "3.2.2" + }, + "dependencies": { + "commander": { + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz", + "integrity": "sha512-BFnaq5ZOGcDN7FlrtBT4xxkgIToalIIxwjxLWVJ8bGTpe1LroqMiqQXdA7ygc7CRvaYS+9zfPGFnJqFSayx+AA==" + } + } + }, "http-auth": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/http-auth/-/http-auth-3.1.3.tgz", @@ -1971,6 +2015,11 @@ "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=" }, + "lower-case": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", + "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=" + }, "lowercase-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", @@ -2123,11 +2172,27 @@ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" }, + "ncname": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ncname/-/ncname-1.0.0.tgz", + "integrity": "sha1-W1etGLHKCShk72Kwse2BlPODtxw=", + "requires": { + "xml-char-classes": "1.0.0" + } + }, "negotiator": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" }, + "no-case": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", + "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "requires": { + "lower-case": "1.1.4" + } + }, "nodemon": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-1.12.1.tgz", @@ -2299,6 +2364,14 @@ "semver": "5.4.1" } }, + "param-case": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", + "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", + "requires": { + "no-case": "2.3.2" + } + }, "parse-glob": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", @@ -2601,6 +2674,11 @@ "rc": "1.2.2" } }, + "relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=" + }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -2820,6 +2898,11 @@ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=" }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, "spawn-command": { "version": "0.0.2-1", "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", @@ -3037,6 +3120,27 @@ "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.3.tgz", "integrity": "sha1-ftUNXg+an7ClczeSWfKndFjVAZI=" }, + "uglify-js": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.2.2.tgz", + "integrity": "sha512-++1NO/zZIEdWf6cDIGceSJQPX31SqIpbVAHwFG5+240MtZqPG/NIPoinj8zlXQtAfMBqEt1Jyv2FiLP3n9gVhQ==", + "requires": { + "commander": "2.12.2", + "source-map": "0.6.1" + }, + "dependencies": { + "commander": { + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz", + "integrity": "sha512-BFnaq5ZOGcDN7FlrtBT4xxkgIToalIIxwjxLWVJ8bGTpe1LroqMiqQXdA7ygc7CRvaYS+9zfPGFnJqFSayx+AA==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, "undefsafe": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-0.0.3.tgz", @@ -3124,6 +3228,11 @@ } } }, + "upper-case": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", + "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=" + }, "url-parse-lax": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", @@ -3256,6 +3365,11 @@ "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=" }, + "xml-char-classes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/xml-char-classes/-/xml-char-classes-1.0.0.tgz", + "integrity": "sha1-ZGV4SKIP/F31g6Qq2KJ3tFErvE0=" + }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", diff --git a/package.json b/package.json index ae03a1343..6805118bb 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "dependencies": { "concurrently": "^3.5.1", "fs-extra": "^4.0.2", + "html-minifier": "^3.5.7", "live-server": "^1.2.0", "markdown-it": "^8.4.0", "nodemon": "^1.12.1", diff --git a/scripts/web-script.js b/scripts/web-script.js index bbfb5015f..1a77956da 100644 --- a/scripts/web-script.js +++ b/scripts/web-script.js @@ -3,8 +3,12 @@ Run using `npm run webber`. */ // Load modules -const fs = require('fs-extra'), path = require('path'), chalk = require('chalk'), - md = require('markdown-it')(); +const fs = require('fs-extra'); +const path = require('path'); +const chalk = require('chalk'); +const md = require('markdown-it')(); +const minify = require('html-minifier').minify; + // Set variables for paths const snippetsPath = './snippets', staticPartsPath = './static-parts', docsPath = './docs'; // Set variables for script @@ -70,6 +74,25 @@ try { // Add the ending static part output += `\n${endPart+'\n'}`; // Write to the index.html file + + output = minify(output, { + collapseBooleanAttributes: true, + collapseWhitespace: true, + decodeEntities: true, + minifyCSS: true, + minifyJS: true, + html5: false, + processConditionalComments: true, + removeAttributeQuotes: true, + removeComments: true, + removeEmptyAttributes: true, + removeOptionalTags: true, + removeScriptTypeAttributes: true, + removeStyleLinkTypeAttributes: true, + trimCustomFragments: true, + useShortDoctype: true, + }); + fs.writeFileSync(path.join(docsPath,'index.html'), output); } catch (err){ // Handle errors (hopefully not!) From 6dc1a39bc6cc99fb42f0a318c27529bfc3c52a2f Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Wed, 20 Dec 2017 16:16:52 +0200 Subject: [PATCH 08/61] Build --- README.md | 20 +++++++++++++++++++- docs/index.html | 17 ++++++++++++++--- tag_database | 1 + 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e30f1b5e1..d3cabfac7 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ ## Table of Contents ### Array +* [`arrayGcd`](#arraygcd) * [`arrayMax`](#arraymax) * [`arrayMin`](#arraymin) * [`chunk`](#chunk) @@ -151,6 +152,23 @@ ## Array +### arrayGcd + +Calculates the greatest common denominator (gcd) of an array of numbers. + +Use `Array.reduce()` and the `gcd` formula (uses recursion) to calculate the greatest common denominator of an array of numbers. + +```js +const arrayGcd = arr =>{ + const gcd = (x, y) => !y ? x : gcd(y, x % y); + return arr.reduce((a,b) => gcd(a,b)); +} +// arrayGcd([1,2,3,4,5]) -> 1 +// arrayGcd([4,8,12]) -> 4 +``` + +[⬆ back to top](#table-of-contents) + ### arrayMax Returns the maximum value in an array. @@ -1549,7 +1567,7 @@ const orderBy = (arr, props, orders) => arr.sort((a, b) => props.reduce((acc, prop, i) => { if (acc === 0) { - const [p1, p2] = orders[i] === 'asc' ? [a[prop], b[prop]] : [b[prop], a[prop]]; + 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; diff --git a/docs/index.html b/docs/index.html index 38d633d4f..eb3335d43 100644 --- a/docs/index.html +++ b/docs/index.html @@ -42,7 +42,8 @@

Array -

arrayMax +arrayGcd +arrayMax arrayMin chunk compact @@ -181,7 +182,17 @@ validateNumber
 

Array

-

arrayMax

+

arrayGcd

+

Calculates the greatest common denominator (gcd) of an array of numbers.

+

Use Array.reduce() and the gcd formula (uses recursion) to calculate the greatest common denominator of an array of numbers.

+
const arrayGcd = arr =>{
+  const gcd = (x, y) => !y ? x : gcd(y, x % y);
+  return arr.reduce((a,b) => gcd(a,b));
+}
+// arrayGcd([1,2,3,4,5]) -> 1
+// arrayGcd([4,8,12]) -> 4
+
+

arrayMax

Returns the maximum value in an array.

Use Math.max() combined with the spread operator (...) to get the maximum value in the array.

const arrayMax = arr => Math.max(...arr);
@@ -962,7 +973,7 @@ If no orders array is passed it sort by 'asc' by default.

arr.sort((a, b) => props.reduce((acc, prop, i) => { if (acc === 0) { - const [p1, p2] = orders[i] === 'asc' ? [a[prop], b[prop]] : [b[prop], a[prop]]; + 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; diff --git a/tag_database b/tag_database index a6657b911..f3ad1b365 100644 --- a/tag_database +++ b/tag_database @@ -1,5 +1,6 @@ anagrams:string arrayAverage:math +arrayGcd:array arrayMax:array arrayMin:array arraySum:math From 1a372322ce6cfc5835b772f0153c74e72543a894 Mon Sep 17 00:00:00 2001 From: Arjun Mahishi Date: Wed, 20 Dec 2017 22:03:58 +0530 Subject: [PATCH 09/61] Snippet to implement inRange --- snippets/inRange.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 snippets/inRange.md diff --git a/snippets/inRange.md b/snippets/inRange.md new file mode 100644 index 000000000..025cf42a0 --- /dev/null +++ b/snippets/inRange.md @@ -0,0 +1,14 @@ +### inRange + +Checks if the given number falls in the given range. + +`end` is an optional parameter. If `end` is not given, the range is considered from 0 to start. + +```js +const inRange = (n, start, end=null) => (end == null) ? (n>=0 && n<=start) : (n>=start && n<=end); + +// inRange(3, 2, 5) -> true +// inRange(3, 4) -> true +// inRange(2, 3, 5) -> false +// inrange(3, 2) -> false +``` \ No newline at end of file From a968a3cc284f882c70a944efd718fc11aa87ebb1 Mon Sep 17 00:00:00 2001 From: Arjun Mahishi Date: Wed, 20 Dec 2017 22:07:30 +0530 Subject: [PATCH 10/61] modified description --- snippets/inRange.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snippets/inRange.md b/snippets/inRange.md index 025cf42a0..b970fa8c1 100644 --- a/snippets/inRange.md +++ b/snippets/inRange.md @@ -2,7 +2,7 @@ Checks if the given number falls in the given range. -`end` is an optional parameter. If `end` is not given, the range is considered from 0 to start. +`end` is an optional parameter. If `end` is not given, the range is considered from `0` to `start`. ```js const inRange = (n, start, end=null) => (end == null) ? (n>=0 && n<=start) : (n>=start && n<=end); From 266637ba49cb1ded69197cf6fa8557cc24911146 Mon Sep 17 00:00:00 2001 From: Arjun Mahishi Date: Wed, 20 Dec 2017 22:49:18 +0530 Subject: [PATCH 11/61] Snippet to implement clamping --- snippets/clampNumber.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 snippets/clampNumber.md diff --git a/snippets/clampNumber.md b/snippets/clampNumber.md new file mode 100644 index 000000000..11089a966 --- /dev/null +++ b/snippets/clampNumber.md @@ -0,0 +1,16 @@ +### clampNumber + +Clamps `num` within the inclusive `lower` and `upper` bounds. + +If `lower` is greater than `upper`, swap them. If `num` falls within the range, return `num`. Otherwise return the nearest number in the range. + +```js +const clampNumber = (num, lower, upper) => { + if(lower > upper) upper = [lower, lower = upper][0]; + return (num>=lower && num<=upper) ? num : ((num < lower) ? lower : upper) +} + +// clampNumber(2, 3, 5) -> 3 +// clampNumber(1, -1, -5) -> -1 +// clampNumber(3, 2, 4) -> 3 +``` \ No newline at end of file From 8873c54304cf0e58d5ebca4cdb95fd2924871db9 Mon Sep 17 00:00:00 2001 From: Arjun Mahishi Date: Wed, 20 Dec 2017 23:42:20 +0530 Subject: [PATCH 12/61] Fixed bugs pointed out by @kingdavidmartins --- snippets/inRange.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/snippets/inRange.md b/snippets/inRange.md index b970fa8c1..f98535f86 100644 --- a/snippets/inRange.md +++ b/snippets/inRange.md @@ -5,7 +5,10 @@ Checks if the given number falls in the given range. `end` is an optional parameter. If `end` is not given, the range is considered from `0` to `start`. ```js -const inRange = (n, start, end=null) => (end == null) ? (n>=0 && n<=start) : (n>=start && n<=end); +const inRange = (n, start, end=null) => { + if(end && start > end) end = [start, start=end][0] + return (end == null) ? (n>=0 && n=start && n true // inRange(3, 4) -> true From 13ae7a574b56803b35f6ead6482bf5b525a70bef Mon Sep 17 00:00:00 2001 From: King Date: Wed, 20 Dec 2017 13:50:17 -0500 Subject: [PATCH 13/61] Update PULL_REQUEST_TEMPLATE --- .github/PULL_REQUEST_TEMPLATE.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 310dae48f..240f8953c 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -6,6 +6,9 @@ **Resolves** #(issue number) + +**Lodash[ACTION]** #100 -> https://lodash.com/docs/4.17.4#(method) + ## What does your PR belong to? - [ ] Website - [ ] Snippets @@ -17,6 +20,12 @@ - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) +## [Lodash Backlog](https://github.com/Chalarangelo/30-seconds-of-code/issues/100) + + +- [ ] I added the prefix [UPDATE: `method.md`] or [ADD: `method.md`] +- [ ] I have reference the `method` to issue #100 accordingly. + ## Checklist: - [ ] My code follows the code style of this project. From 1d8eeb26335c43ac0461a886946e47e666a7d121 Mon Sep 17 00:00:00 2001 From: King Date: Wed, 20 Dec 2017 14:01:20 -0500 Subject: [PATCH 14/61] Fix double ref of #100 --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 240f8953c..c3ed31c2e 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -24,7 +24,7 @@ - [ ] I added the prefix [UPDATE: `method.md`] or [ADD: `method.md`] -- [ ] I have reference the `method` to issue #100 accordingly. +- [ ] I have referenced the `method` to the lodash backlog. ## Checklist: From 6c47aae3b055fa892e0d1179edca2b340694a341 Mon Sep 17 00:00:00 2001 From: Robert Mennell Date: Wed, 20 Dec 2017 14:55:18 -0800 Subject: [PATCH 15/61] Create zipObject.md Will also need to add a tag in the tag database --- snippets/zipObject.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 snippets/zipObject.md diff --git a/snippets/zipObject.md b/snippets/zipObject.md new file mode 100644 index 000000000..169cdaeb1 --- /dev/null +++ b/snippets/zipObject.md @@ -0,0 +1,11 @@ +### zipObject + +Given an Array of valid property identifiers and an Array of values, `zipObject` returns an object mapping the properties to the values +Since an object can have undefined values but not undefined property pointers, the Array of properties is used to decide the structure of the resulting object + +```js +const zipObject = (props, values) => props.reduce( ( obj, prop, index ) => (obj[prop] = values[index], obj), {}) +/* +zipObject(['a','b','c'], [1,2]) +*/ +``` From 627e5f422578bb27cc7f6b6c991fe0a8a5c11da1 Mon Sep 17 00:00:00 2001 From: Robert Mennell Date: Wed, 20 Dec 2017 14:56:03 -0800 Subject: [PATCH 16/61] Update tag_database with zipObject --- tag_database | 1 + 1 file changed, 1 insertion(+) diff --git a/tag_database b/tag_database index f3ad1b365..a0a06d2d0 100644 --- a/tag_database +++ b/tag_database @@ -118,3 +118,4 @@ validateEmail:utility validateNumber:utility without:array zip:array +zipObject:array From 8cf6092e141ddfae698e36eaf96ab401ecb212e4 Mon Sep 17 00:00:00 2001 From: Robert Mennell Date: Wed, 20 Dec 2017 14:57:20 -0800 Subject: [PATCH 17/61] Update zipObject.md --- snippets/zipObject.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snippets/zipObject.md b/snippets/zipObject.md index 169cdaeb1..b37e04045 100644 --- a/snippets/zipObject.md +++ b/snippets/zipObject.md @@ -6,6 +6,6 @@ Since an object can have undefined values but not undefined property pointers, t ```js const zipObject = (props, values) => props.reduce( ( obj, prop, index ) => (obj[prop] = values[index], obj), {}) /* -zipObject(['a','b','c'], [1,2]) +zipObject(['a','b','c'], [1,2]) -> {a: 1, b: 2, c: undefined} */ ``` From e194269da924bb196dfbfd5969853d5759191275 Mon Sep 17 00:00:00 2001 From: Robert Mennell Date: Wed, 20 Dec 2017 14:59:23 -0800 Subject: [PATCH 18/61] Update zipObject.md --- snippets/zipObject.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/snippets/zipObject.md b/snippets/zipObject.md index b37e04045..ca1174bee 100644 --- a/snippets/zipObject.md +++ b/snippets/zipObject.md @@ -1,7 +1,8 @@ ### zipObject -Given an Array of valid property identifiers and an Array of values, `zipObject` returns an object mapping the properties to the values -Since an object can have undefined values but not undefined property pointers, the Array of properties is used to decide the structure of the resulting object +Given an Array of valid property identifiers and an Array of values, `zipObject` returns an object associating the properties to the values + +Since an object can have undefined values but not undefined property pointers, the Array of properties is used to decide the structure of the resulting object through a `reduce` ```js const zipObject = (props, values) => props.reduce( ( obj, prop, index ) => (obj[prop] = values[index], obj), {}) From 48c2625e16508dcb405e03dc7c0203ab81a92a3e Mon Sep 17 00:00:00 2001 From: Robert Mennell Date: Wed, 20 Dec 2017 15:02:43 -0800 Subject: [PATCH 19/61] Update zipObject.md --- snippets/zipObject.md | 1 + 1 file changed, 1 insertion(+) diff --git a/snippets/zipObject.md b/snippets/zipObject.md index ca1174bee..bc9ecc010 100644 --- a/snippets/zipObject.md +++ b/snippets/zipObject.md @@ -8,5 +8,6 @@ Since an object can have undefined values but not undefined property pointers, t const zipObject = (props, values) => props.reduce( ( obj, prop, index ) => (obj[prop] = values[index], obj), {}) /* zipObject(['a','b','c'], [1,2]) -> {a: 1, b: 2, c: undefined} +zipObject(['a','b'], [1,2,3]) -> {a: 1, b: 2} */ ``` From 8554fa507a6a76e1df39e6456aba846a18f90300 Mon Sep 17 00:00:00 2001 From: Robert Mennell Date: Wed, 20 Dec 2017 15:03:40 -0800 Subject: [PATCH 20/61] Update zipObject.md --- snippets/zipObject.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snippets/zipObject.md b/snippets/zipObject.md index bc9ecc010..ab8ac6ee5 100644 --- a/snippets/zipObject.md +++ b/snippets/zipObject.md @@ -5,7 +5,7 @@ Given an Array of valid property identifiers and an Array of values, `zipObject` Since an object can have undefined values but not undefined property pointers, the Array of properties is used to decide the structure of the resulting object through a `reduce` ```js -const zipObject = (props, values) => props.reduce( ( obj, prop, index ) => (obj[prop] = values[index], obj), {}) +const zipObject = ( props, values ) => props.reduce( ( obj, prop, index ) => ( obj[prop] = values[index], obj ), {} ) /* zipObject(['a','b','c'], [1,2]) -> {a: 1, b: 2, c: undefined} zipObject(['a','b'], [1,2,3]) -> {a: 1, b: 2} From 2c5f6261ea0275ca885605362a0331d2b8aac0a4 Mon Sep 17 00:00:00 2001 From: Robert Mennell Date: Wed, 20 Dec 2017 15:04:32 -0800 Subject: [PATCH 21/61] Update zipObject.md --- snippets/zipObject.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/snippets/zipObject.md b/snippets/zipObject.md index ab8ac6ee5..3bf6bee60 100644 --- a/snippets/zipObject.md +++ b/snippets/zipObject.md @@ -6,8 +6,7 @@ Since an object can have undefined values but not undefined property pointers, t ```js const zipObject = ( props, values ) => props.reduce( ( obj, prop, index ) => ( obj[prop] = values[index], obj ), {} ) -/* -zipObject(['a','b','c'], [1,2]) -> {a: 1, b: 2, c: undefined} -zipObject(['a','b'], [1,2,3]) -> {a: 1, b: 2} -*/ +// zipObject(['a','b','c'], [1,2]) -> {a: 1, b: 2, c: undefined} +// zipObject(['a','b'], [1,2,3]) -> {a: 1, b: 2} + ``` From 3ae52f466f600894ca2e190cb098478def49f0cd Mon Sep 17 00:00:00 2001 From: Robert Mennell Date: Wed, 20 Dec 2017 16:18:57 -0800 Subject: [PATCH 22/61] Update zipObject.md --- snippets/zipObject.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/snippets/zipObject.md b/snippets/zipObject.md index 3bf6bee60..d1f8b9e32 100644 --- a/snippets/zipObject.md +++ b/snippets/zipObject.md @@ -1,8 +1,8 @@ ### zipObject -Given an Array of valid property identifiers and an Array of values, `zipObject` returns an object associating the properties to the values +Given an array of valid property identifiers and an array of values, `zipObject` returns an object associating the properties to the values -Since an object can have undefined values but not undefined property pointers, the Array of properties is used to decide the structure of the resulting object through a `reduce` +Since an object can have undefined values but not undefined property pointers, the array of properties is used to decide the structure of the resulting object through a `reduce` ```js const zipObject = ( props, values ) => props.reduce( ( obj, prop, index ) => ( obj[prop] = values[index], obj ), {} ) From bbf3fc5fa3cf46fc3e1e870d15d3b191c3a0321f Mon Sep 17 00:00:00 2001 From: Robert Mennell Date: Wed, 20 Dec 2017 16:19:12 -0800 Subject: [PATCH 23/61] Update zipObject.md --- snippets/zipObject.md | 1 - 1 file changed, 1 deletion(-) diff --git a/snippets/zipObject.md b/snippets/zipObject.md index d1f8b9e32..a698038b9 100644 --- a/snippets/zipObject.md +++ b/snippets/zipObject.md @@ -8,5 +8,4 @@ Since an object can have undefined values but not undefined property pointers, t const zipObject = ( props, values ) => props.reduce( ( obj, prop, index ) => ( obj[prop] = values[index], obj ), {} ) // zipObject(['a','b','c'], [1,2]) -> {a: 1, b: 2, c: undefined} // zipObject(['a','b'], [1,2,3]) -> {a: 1, b: 2} - ``` From c8bf4e197d1e07bfd162bb2e7acd2147ce6561d9 Mon Sep 17 00:00:00 2001 From: King Date: Wed, 20 Dec 2017 22:43:33 -0500 Subject: [PATCH 24/61] before hacky -> now elegant --- snippets/pull.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/snippets/pull.md b/snippets/pull.md index 16f0e25c4..41658a545 100644 --- a/snippets/pull.md +++ b/snippets/pull.md @@ -9,8 +9,10 @@ _(For a snippet that does not mutate the original array see [`without`](#without ```js const pull = (arr, ...args) => { - let pulled = arr.filter((v, i) => !args.toString().split(',').includes(v)); - arr.length = 0; pulled.forEach(v => arr.push(v)); + 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)); }; // let myArray1 = ['a', 'b', 'c', 'a', 'b', 'c']; From 86c34262912005081445709290a6b072e0717fe5 Mon Sep 17 00:00:00 2001 From: King Date: Wed, 20 Dec 2017 22:47:54 -0500 Subject: [PATCH 25/61] ran npm run builder --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d3cabfac7..25b7dbfd0 100644 --- a/README.md +++ b/README.md @@ -550,8 +550,10 @@ _(For a snippet that does not mutate the original array see [`without`](#without ```js const pull = (arr, ...args) => { - let pulled = arr.filter((v, i) => !args.toString().split(',').includes(v)); - arr.length = 0; pulled.forEach(v => arr.push(v)); + 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)); }; // let myArray1 = ['a', 'b', 'c', 'a', 'b', 'c']; From 3cd5d1b795720a914d69a16f49d1975b707b5c4b Mon Sep 17 00:00:00 2001 From: King Date: Thu, 21 Dec 2017 01:02:59 -0500 Subject: [PATCH 26/61] Update CONTRIBUTING.md --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ac39ceccc..100d05aca 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,7 +12,7 @@ Here's what you can do to help: ### Snippet submission and Pull request guidelines -- **DO NOT MODIFY THE README.md FILE!** Make changes to individual snippet files. You can optionally run `npm run build-list` to update the README.md file automatically, based on the changes you have made. +- **DO NOT MODIFY THE README.md FILE!** Make changes to individual snippet files. You can optionally run `npm run builder` to update the README.md file automatically, based on the changes you have made. - **Snippet filenames** must correspond to the title of the snippet. For example, if your snippet is titled `### awesomeSnippet` the filename should be `awesomeSnippet.md`. - Use `camelCase`, not `kebab-case` or `snake_case`. - Avoid capitalization of words, except if the whole word is capitalized (e.g. `URL` should be capitalized in the filename and the snippet title). From 24d1ef99eebf10c0c017a1242da536e4f3d70ba5 Mon Sep 17 00:00:00 2001 From: Arjun Mahishi Date: Thu, 21 Dec 2017 12:03:56 +0530 Subject: [PATCH 27/61] Snippet to perform HTTPS redirect --- snippets/httpsRedirect.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 snippets/httpsRedirect.md diff --git a/snippets/httpsRedirect.md b/snippets/httpsRedirect.md new file mode 100644 index 000000000..f60a79610 --- /dev/null +++ b/snippets/httpsRedirect.md @@ -0,0 +1,9 @@ +### httpsRedirect + +Redirects the page to HTTPS if its currently in HTTP. Also, pressing the back button doesn't take it back to the HTTP page as its replaced in the history. + +```js +const httpsRedirect = () => { + if(location.protocol !== "https:") location.replace("https://" + location.href.split("//")[1]); +} +``` \ No newline at end of file From 679c674b3a4eb8cf61879101901f5125ad0b561e Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Thu, 21 Dec 2017 11:05:39 +0200 Subject: [PATCH 28/61] Update inRange.md --- snippets/inRange.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/snippets/inRange.md b/snippets/inRange.md index f98535f86..7162c52d8 100644 --- a/snippets/inRange.md +++ b/snippets/inRange.md @@ -2,16 +2,16 @@ Checks if the given number falls in the given range. -`end` is an optional parameter. If `end` is not given, the range is considered from `0` to `start`. +Use arithmetic comparison to check if the given number is in the specified range. +If the second parameter, `end`, is not specified, the reange is considered to be from `0` to `start`. ```js const inRange = (n, start, end=null) => { - if(end && start > end) end = [start, start=end][0] - return (end == null) ? (n>=0 && n=start && n end) end = [start, start=end][0]; + return (end == null) ? (n>=0 && n=start && n true // inRange(3, 4) -> true // inRange(2, 3, 5) -> false // inrange(3, 2) -> false -``` \ No newline at end of file +``` From cf85040eef45c2ea937b37891b8501430885abc9 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Thu, 21 Dec 2017 11:08:01 +0200 Subject: [PATCH 29/61] Update clampNumber.md --- snippets/clampNumber.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/snippets/clampNumber.md b/snippets/clampNumber.md index 11089a966..526d41af8 100644 --- a/snippets/clampNumber.md +++ b/snippets/clampNumber.md @@ -2,15 +2,17 @@ Clamps `num` within the inclusive `lower` and `upper` bounds. -If `lower` is greater than `upper`, swap them. If `num` falls within the range, return `num`. Otherwise return the nearest number in the range. +If `lower` is greater than `upper`, swap them. +If `num` falls within the range, return `num`. +Otherwise return the nearest number in the range. ```js const clampNumber = (num, lower, upper) => { - if(lower > upper) upper = [lower, lower = upper][0]; - return (num>=lower && num<=upper) ? num : ((num < lower) ? lower : upper) + if(lower > upper) upper = [lower, lower = upper][0]; + return (num>=lower && num<=upper) ? num : ((num < lower) ? lower : upper) } // clampNumber(2, 3, 5) -> 3 // clampNumber(1, -1, -5) -> -1 // clampNumber(3, 2, 4) -> 3 -``` \ No newline at end of file +``` From 396b24cab2e3cd6f7e55703887848f724e041867 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Thu, 21 Dec 2017 11:08:09 +0200 Subject: [PATCH 30/61] Update clampNumber.md --- snippets/clampNumber.md | 1 - 1 file changed, 1 deletion(-) diff --git a/snippets/clampNumber.md b/snippets/clampNumber.md index 526d41af8..ddbb655ff 100644 --- a/snippets/clampNumber.md +++ b/snippets/clampNumber.md @@ -11,7 +11,6 @@ const clampNumber = (num, lower, upper) => { if(lower > upper) upper = [lower, lower = upper][0]; return (num>=lower && num<=upper) ? num : ((num < lower) ? lower : upper) } - // clampNumber(2, 3, 5) -> 3 // clampNumber(1, -1, -5) -> -1 // clampNumber(3, 2, 4) -> 3 From 07c5ee65d8b12faef54c51d065efcf660a6b9dd8 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Thu, 21 Dec 2017 11:13:38 +0200 Subject: [PATCH 31/61] Update zipObject.md --- snippets/zipObject.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/snippets/zipObject.md b/snippets/zipObject.md index a698038b9..f9214e7aa 100644 --- a/snippets/zipObject.md +++ b/snippets/zipObject.md @@ -1,8 +1,8 @@ ### zipObject -Given an array of valid property identifiers and an array of values, `zipObject` returns an object associating the properties to the values +Given an array of valid property identifiers and an array of values, return an object associating the properties to the values. -Since an object can have undefined values but not undefined property pointers, the array of properties is used to decide the structure of the resulting object through a `reduce` +Since an object can have undefined values but not undefined property pointers, the array of properties is used to decide the structure of the resulting object using `Array.reduce()`. ```js const zipObject = ( props, values ) => props.reduce( ( obj, prop, index ) => ( obj[prop] = values[index], obj ), {} ) From 024d9bc6aafbcc8b213cc297a8214d351eb04af2 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Thu, 21 Dec 2017 11:14:58 +0200 Subject: [PATCH 32/61] Build --- README.md | 57 +++++++++++++++++++++++++++++++++++++++++++++++++ docs/index.html | 36 +++++++++++++++++++++++++++++++ tag_database | 2 ++ 3 files changed, 95 insertions(+) diff --git a/README.md b/README.md index d3cabfac7..4e447bf9e 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,7 @@ * [`union`](#union) * [`without`](#without) * [`zip`](#zip) +* [`zipObject`](#zipobject) ### Browser * [`arrayToHtmlList`](#arraytohtmllist) @@ -81,6 +82,7 @@ ### Math * [`arrayAverage`](#arrayaverage) * [`arraySum`](#arraysum) +* [`clampNumber`](#clampnumber) * [`collatz`](#collatz) * [`digitize`](#digitize) * [`distance`](#distance) @@ -88,6 +90,7 @@ * [`fibonacci`](#fibonacci) * [`gcd`](#gcd) * [`hammingDistance`](#hammingdistance) +* [`inRange`](#inrange) * [`isArmstrongNumber`](#isarmstrongnumber) * [`isDivisible`](#isdivisible) * [`isEven`](#iseven) @@ -782,6 +785,20 @@ const zip = (...arrays) => { //zip(['a'], [1, 2], [true, false]); -> [['a', 1, true], [undefined, 2, false]] ``` +[⬆ back to top](#table-of-contents) + +### zipObject + +Given an array of valid property identifiers and an array of values, return an object associating the properties to the values. + +Since an object can have undefined values but not undefined property pointers, the array of properties is used to decide the structure of the resulting object using `Array.reduce()`. + +```js +const zipObject = ( props, values ) => props.reduce( ( obj, prop, index ) => ( obj[prop] = values[index], obj ), {} ) +// zipObject(['a','b','c'], [1,2]) -> {a: 1, b: 2, c: undefined} +// zipObject(['a','b'], [1,2,3]) -> {a: 1, b: 2} +``` + [⬆ back to top](#table-of-contents) ## Browser @@ -1135,6 +1152,26 @@ const arraySum = arr => arr.reduce((acc, val) => acc + val, 0); [⬆ back to top](#table-of-contents) +### clampNumber + +Clamps `num` within the inclusive `lower` and `upper` bounds. + +If `lower` is greater than `upper`, swap them. +If `num` falls within the range, return `num`. +Otherwise return the nearest number in the range. + +```js +const clampNumber = (num, lower, upper) => { + if(lower > upper) upper = [lower, lower = upper][0]; + return (num>=lower && num<=upper) ? num : ((num < lower) ? lower : upper) +} +// clampNumber(2, 3, 5) -> 3 +// clampNumber(1, -1, -5) -> -1 +// clampNumber(3, 2, 4) -> 3 +``` + +[⬆ back to top](#table-of-contents) + ### collatz Applies the Collatz algorithm. @@ -1239,6 +1276,26 @@ const hammingDistance = (num1, num2) => [⬆ back to top](#table-of-contents) +### inRange + +Checks if the given number falls in the given range. + +Use arithmetic comparison to check if the given number is in the specified range. +If the second parameter, `end`, is not specified, the reange is considered to be from `0` to `start`. + +```js +const inRange = (n, start, end=null) => { + if(end && start > end) end = [start, start=end][0]; + return (end == null) ? (n>=0 && n=start && n true +// inRange(3, 4) -> true +// inRange(2, 3, 5) -> false +// inrange(3, 2) -> false +``` + +[⬆ back to top](#table-of-contents) + ### isArmstrongNumber Checks if the given number is an armstrong number or not. diff --git a/docs/index.html b/docs/index.html index eb3335d43..42421208d 100644 --- a/docs/index.html +++ b/docs/index.html @@ -83,6 +83,7 @@ union without zip +zipObject

Browser

arrayToHtmlList @@ -112,6 +113,7 @@

Math

arrayAverage arraySum +clampNumber collatz digitize distance @@ -119,6 +121,7 @@ fibonacci gcd hammingDistance +inRange isArmstrongNumber isDivisible isEven @@ -525,6 +528,13 @@ If lengths of the argument-arrays vary, undefined is used where no //zip(['a', 'b'], [1, 2], [true, false]); -> [['a', 1, true], ['b', 2, false]] //zip(['a'], [1, 2], [true, false]); -> [['a', 1, true], [undefined, 2, false]]
+

zipObject

+

Given an array of valid property identifiers and an array of values, return an object associating the properties to the values.

+

Since an object can have undefined values but not undefined property pointers, the array of properties is used to decide the structure of the resulting object using Array.reduce().

+
const zipObject = ( props, values ) => props.reduce( ( obj, prop, index ) => ( obj[prop] = values[index], obj ), {} )
+// zipObject(['a','b','c'], [1,2]) -> {a: 1, b: 2, c: undefined}
+// zipObject(['a','b'], [1,2,3]) -> {a: 1, b: 2}
+

Browser

arrayToHtmlList

Converts the given array elements into <li> tags and appends them to the list of the given id.

@@ -728,6 +738,19 @@ async function sleepyWork() {
const arraySum = arr => arr.reduce((acc, val) => acc + val, 0);
 // arraySum([1,2,3,4]) -> 10
 
+

clampNumber

+

Clamps num within the inclusive lower and upper bounds.

+

If lower is greater than upper, swap them. +If num falls within the range, return num. +Otherwise return the nearest number in the range.

+
const clampNumber = (num, lower, upper) => {
+  if(lower > upper) upper = [lower, lower = upper][0];
+  return (num>=lower && num<=upper) ? num : ((num < lower) ? lower : upper) 
+}
+// clampNumber(2, 3, 5) -> 3
+// clampNumber(1, -1, -5) -> -1
+// clampNumber(3, 2, 4) -> 3
+

collatz

Applies the Collatz algorithm.

If n is even, return n/2. Otherwise return 3n+1.

@@ -783,6 +806,19 @@ Count and return the number of 1s in the string, using match( ((num1 ^ num2).toString(2).match(/1/g) || '').length; // hammingDistance(2,3) -> 1 +

inRange

+

Checks if the given number falls in the given range.

+

Use arithmetic comparison to check if the given number is in the specified range. +If the second parameter, end, is not specified, the reange is considered to be from 0 to start.

+
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);
+}
+// inRange(3, 2, 5) -> true
+// inRange(3, 4) -> true
+// inRange(2, 3, 5) -> false
+// inrange(3, 2) -> false
+

isArmstrongNumber

Checks if the given number is an armstrong number or not.

Convert the given number into array of digits. Use Math.pow() to get the appropriate power for each digit and sum them up. If the sum is equal to the number itself, return true otherwise false.

diff --git a/tag_database b/tag_database index a0a06d2d0..84063917c 100644 --- a/tag_database +++ b/tag_database @@ -10,6 +10,7 @@ capitalize:string capitalizeEveryWord:string chainAsync:function chunk:array +clampNumber:math cleanObj:object coalesce:utility coalesceFactory:utility @@ -52,6 +53,7 @@ initial:array initialize2DArray:array initializeArrayWithRange:array initializeArrayWithValues:array +inRange:math intersection:array isArmstrongNumber:math isArray:utility From 58514f6564b7c849dd1666c218d31c3e048604d2 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Thu, 21 Dec 2017 11:17:22 +0200 Subject: [PATCH 33/61] Build --- docs/index.html | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/index.html b/docs/index.html index 42421208d..49a3b13df 100644 --- a/docs/index.html +++ b/docs/index.html @@ -389,8 +389,10 @@ Omit the second argument, n, to get the first element of the array. Use Array.length = 0 to mutate the passed in array by resetting it's length to zero and Array.push() to re-populate it with only the pulled values.

(For a snippet that does not mutate the original array see without)

const pull = (arr, ...args) => {
-  let pulled = arr.filter((v, i) => !args.toString().split(',').includes(v));
-  arr.length = 0; pulled.forEach(v => arr.push(v));
+  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));
 };
 
 // let myArray1 = ['a', 'b', 'c', 'a', 'b', 'c'];

From 38011e1a78a060136277f9708f9ca5ce0fc4eea3 Mon Sep 17 00:00:00 2001
From: Angelos Chalaris 
Date: Thu, 21 Dec 2017 11:46:29 +0200
Subject: [PATCH 34/61] Rules for collaborators

---
 COLLABORATING.md | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)
 create mode 100644 COLLABORATING.md

diff --git a/COLLABORATING.md b/COLLABORATING.md
new file mode 100644
index 000000000..3629eba70
--- /dev/null
+++ b/COLLABORATING.md
@@ -0,0 +1,24 @@
+# Collaborator team rules and guidelines for community moderation
+
+**As a contributor/member of the community, remember that you can always open issues about moderation and problems with how community moderation is done. We are always open to constructive criticism and feedback!**
+
+## Responsibilities of a collaborator
+
+As a member of the team that manages **30 seconds of code**, you have the following responsibilities:
+
+- **Be part of the conversation in the issue tracker.** That includes (but is not limited to) helping out new members, discussing new features and explaining decisions to people.
+- **Review pull requests.** You do not have to read through all of the pull requests and review them, but taking the time each day to review a few can help a great deal.
+- **Be civil and polite.** If you are about to lose your temper, take a step back and go do something else. We want our interactions with the community to be polite, so that more people can join the project and contribute in any way they can. Remember to always thank contributors for their help, even if its minor changes or changes that did not make it into the project. This way we can reward and encourage people to keep being part of the community.
+- Contribute when you want, moderate when you can. If you have a lot on your plate outside of this project, it's alright. It's better to take a break for a few days rather than hastily deal with issues and pull requests that might break things.
+
+## Guidelines for merging pull requests and making changes to the project
+
+- **Usual guidelines apply.** Make sure to follow them, like everybody else.
+- **For a pull request to be considered ready to merge, there should be at least 2 (preferrably 3) reviews approving it for merge.** There are, however, certain exceptions:
+  - **If a pull request only fixes typos**, there is no need to wait for a second reviewer (unless you are not absolutely certain these were not typos in the first place).
+  - **If a pull request only clarifies a snippet's description or enforces the styleguide for an existng snippet**, you might be able to merge it without getting a second reviewer to review it, but only if you are absolutely certain about it.
+  - **Changes to build scripts, guidelines and things that might break the processes we have in place need to be reviewed by @Chalarangelo (this is temporary, but we need a baseline to make sure we break as few things as possible in the beginning).**
+- **After merging a pull request, make sure to check for untagged snippets and tag them appropriately.** Try to keep all snippets tagged, so that the list and website are up to date.
+- (*Irrelevant once we set up CI*) **You should rebuild the README and website after merging pull requests.**
+- **If you make changes or additions to existing snippets or if you want to add you own snippets, you will go through the pull request process that everyone else goes.** Exceptions apply similarly to the ones mentioned above about merging pull requests (i.e. typos, description clarification and the way script and build process changes are handled). Pull requests suggested by collaborators should be reviewed by at least two other collaborators to be considered ready to merge.
+- **Pull requests that are inactive for over a week should be closed or put on hold.**

From 82b83fe1b8952c53111c49c2bf0db1f91518e063 Mon Sep 17 00:00:00 2001
From: Angelos Chalaris 
Date: Thu, 21 Dec 2017 11:48:36 +0200
Subject: [PATCH 35/61] Fix markup

---
 COLLABORATING.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/COLLABORATING.md b/COLLABORATING.md
index 3629eba70..e5f17c034 100644
--- a/COLLABORATING.md
+++ b/COLLABORATING.md
@@ -9,7 +9,7 @@ As a member of the team that manages **30 seconds of code**, you have the follow
 - **Be part of the conversation in the issue tracker.** That includes (but is not limited to) helping out new members, discussing new features and explaining decisions to people.
 - **Review pull requests.** You do not have to read through all of the pull requests and review them, but taking the time each day to review a few can help a great deal.
 - **Be civil and polite.** If you are about to lose your temper, take a step back and go do something else. We want our interactions with the community to be polite, so that more people can join the project and contribute in any way they can. Remember to always thank contributors for their help, even if its minor changes or changes that did not make it into the project. This way we can reward and encourage people to keep being part of the community.
-- Contribute when you want, moderate when you can. If you have a lot on your plate outside of this project, it's alright. It's better to take a break for a few days rather than hastily deal with issues and pull requests that might break things.
+- **Contribute when you want, moderate when you can.** If you have a lot on your plate outside of this project, it's alright. It's better to take a break for a few days rather than hastily deal with issues and pull requests that might break things.
 
 ## Guidelines for merging pull requests and making changes to the project
 

From 7866a097724cdf9dcdb109a1ff98407fe31a0d1c Mon Sep 17 00:00:00 2001
From: Angelos Chalaris 
Date: Thu, 21 Dec 2017 11:52:12 +0200
Subject: [PATCH 36/61] Update guidelines for collaborators

---
 COLLABORATING.md | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/COLLABORATING.md b/COLLABORATING.md
index e5f17c034..119870112 100644
--- a/COLLABORATING.md
+++ b/COLLABORATING.md
@@ -8,17 +8,17 @@ As a member of the team that manages **30 seconds of code**, you have the follow
 
 - **Be part of the conversation in the issue tracker.** That includes (but is not limited to) helping out new members, discussing new features and explaining decisions to people.
 - **Review pull requests.** You do not have to read through all of the pull requests and review them, but taking the time each day to review a few can help a great deal.
-- **Be civil and polite.** If you are about to lose your temper, take a step back and go do something else. We want our interactions with the community to be polite, so that more people can join the project and contribute in any way they can. Remember to always thank contributors for their help, even if its minor changes or changes that did not make it into the project. This way we can reward and encourage people to keep being part of the community.
+- **Be civil and polite.** If you are about to lose your temper, take a step back and go do something else. We want our interactions with the community to be polite, so that more people can join the project and contribute in any way they can. Remember to always thank contributors for their help, even if it's minor changes or changes that did not make it into the project. This way we can reward and encourage people to keep being part of the community.
 - **Contribute when you want, moderate when you can.** If you have a lot on your plate outside of this project, it's alright. It's better to take a break for a few days rather than hastily deal with issues and pull requests that might break things.
 
 ## Guidelines for merging pull requests and making changes to the project
 
-- **Usual guidelines apply.** Make sure to follow them, like everybody else.
+- **[Usual guidelines](https://github.com/Chalarangelo/30-seconds-of-code/blob/master/CONTRIBUTING.md) apply.** Make sure to follow them, like everybody else.
 - **For a pull request to be considered ready to merge, there should be at least 2 (preferrably 3) reviews approving it for merge.** There are, however, certain exceptions:
   - **If a pull request only fixes typos**, there is no need to wait for a second reviewer (unless you are not absolutely certain these were not typos in the first place).
   - **If a pull request only clarifies a snippet's description or enforces the styleguide for an existng snippet**, you might be able to merge it without getting a second reviewer to review it, but only if you are absolutely certain about it.
-  - **Changes to build scripts, guidelines and things that might break the processes we have in place need to be reviewed by @Chalarangelo (this is temporary, but we need a baseline to make sure we break as few things as possible in the beginning).**
+  - **Changes to build scripts, guidelines and things that might break the processes we have in place need to be reviewed by [@Chalarangelo](https://github.com/Chalarangelo)** (this is temporary, but we need a baseline to make sure we break as few things as possible in the beginning).
 - **After merging a pull request, make sure to check for untagged snippets and tag them appropriately.** Try to keep all snippets tagged, so that the list and website are up to date.
-- (*Irrelevant once we set up CI*) **You should rebuild the README and website after merging pull requests.**
+- (*Irrelevant once we set up CI*) **You should rebuild the README and website after merging pull requests and push to the repository, so that both files are up to date.**
 - **If you make changes or additions to existing snippets or if you want to add you own snippets, you will go through the pull request process that everyone else goes.** Exceptions apply similarly to the ones mentioned above about merging pull requests (i.e. typos, description clarification and the way script and build process changes are handled). Pull requests suggested by collaborators should be reviewed by at least two other collaborators to be considered ready to merge.
 - **Pull requests that are inactive for over a week should be closed or put on hold.**

From 4b61b994e9d596602cfce022a168bc6e4ae0b8d9 Mon Sep 17 00:00:00 2001
From: Angelos Chalaris 
Date: Thu, 21 Dec 2017 12:21:31 +0200
Subject: [PATCH 37/61] Rebuild website and regenerate package-lock

---
 docs/index.html   | 1513 +++++++++++----------------------------------
 package-lock.json |  217 ++++---
 2 files changed, 492 insertions(+), 1238 deletions(-)

diff --git a/docs/index.html b/docs/index.html
index 49a3b13df..791f0c534 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -1,724 +1,256 @@
-
-
-  
-    
-    
-    30 seconds of code
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-  
-  
-  
-    
-    
-

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

- -
-
- -
 

Array

-

arrayGcd

-

Calculates the greatest common denominator (gcd) of an array of numbers.

-

Use Array.reduce() and the gcd formula (uses recursion) to calculate the greatest common denominator of an array of numbers.

-
const arrayGcd = arr =>{
-  const gcd = (x, y) => !y ? x : gcd(y, x % y);
-  return arr.reduce((a,b) => gcd(a,b));
+    }

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

 

Array

arrayGcd

Calculates the greatest common denominator (gcd) of an array of numbers.

Use Array.reduce() and the gcd formula (uses recursion) to calculate the greatest common denominator of an array of numbers.

const arrayGcd = arr =>{
+  const gcd = (x, y) => !y ? x : gcd(y, x % y);
+  return arr.reduce((a,b) => gcd(a,b));
 }
-// arrayGcd([1,2,3,4,5]) -> 1
-// arrayGcd([4,8,12]) -> 4
-
-

arrayMax

-

Returns the maximum value in an array.

-

Use Math.max() combined with the spread operator (...) to get the maximum value in the array.

-
const arrayMax = arr => Math.max(...arr);
-// arrayMax([10, 1, 5]) -> 10
-
-

arrayMin

-

Returns the minimum value in an array.

-

Use Math.min() combined with the spread operator (...) to get the minimum value in the array.

-
const arrayMin = arr => Math.min(...arr);
-// arrayMin([10, 1, 5]) -> 1
-
-

chunk

-

Chunks an array into smaller arrays of a specified size.

-

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

-
const chunk = (arr, size) =>
-  Array.from({length: Math.ceil(arr.length / size)}, (v, i) => arr.slice(i * size, i * size + size));
-// chunk([1,2,3,4,5], 2) -> [[1,2],[3,4],[5]]
-
-

compact

-

Removes falsey values from an array.

-

Use Array.filter() to filter out falsey values (false, null, 0, "", undefined, and NaN).

-
const compact = (arr) => arr.filter(Boolean);
-// compact([0, 1, false, 2, '', 3, 'a', 'e'*23, NaN, 's', 34]) -> [ 1, 2, 3, 'a', 's', 34 ]
-
-

countOccurrences

-

Counts the occurrences of a value in an array.

-

Use Array.reduce() to increment a counter each time you encounter the specific value inside the array.

-
const countOccurrences = (arr, value) => arr.reduce((a, v) => v === value ? a + 1 : a + 0, 0);
-// countOccurrences([1,1,2,1,2,3], 1) -> 3
-
-

deepFlatten

-

Deep flattens an array.

-

Use recursion. -Use Array.concat() with an empty array ([]) and the spread operator (...) to flatten an array. -Recursively flatten each element that is an array.

-
const deepFlatten = arr => [].concat(...arr.map(v => Array.isArray(v) ? deepFlatten(v) : v));
-// deepFlatten([1,[2],[[3],4],5]) -> [1,2,3,4,5]
-
-

difference

-

Returns the difference between two arrays.

-

Create a Set from b, then use Array.filter() on a to only keep values not contained in b.

-
const difference = (a, b) => { const s = new Set(b); return a.filter(x => !s.has(x)); };
-// difference([1,2,3], [1,2,4]) -> [3]
-
-

differenceWith

-

Filters out all values from an array for which the comparator function does not return true.

-

Use Array.filter() and Array.find() to find the appropriate values.

-
const differenceWith = (arr, val, comp) => arr.filter(a => !val.find(b => comp(a, b)))
-// differenceWith([1, 1.2, 1.5, 3], [1.9, 3], (a,b) => Math.round(a) == Math.round(b)) -> [1, 1.2]
-
-

distinctValuesOfArray

-

Returns all the distinct values of an array.

-

Use ES6 Set and the ...rest operator to discard all duplicated values.

-
const distinctValuesOfArray = arr => [...new Set(arr)];
-// distinctValuesOfArray([1,2,2,3,4,4,5]) -> [1,2,3,4,5]
-
-

dropElements

-

Removes elements in an array until the passed function returns true. Returns the remaining elements in the array.

-

Loop through the array, using Array.slice() to drop the first element of the array until the returned value from the function is true. -Returns the remaining elements.

-
const dropElements = (arr, func) => {
-  while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1);
+// arrayGcd([1,2,3,4,5]) -> 1
+// arrayGcd([4,8,12]) -> 4
+

arrayMax

Returns the maximum value in an array.

Use Math.max() combined with the spread operator (...) to get the maximum value in the array.

const arrayMax = arr => Math.max(...arr);
+// arrayMax([10, 1, 5]) -> 10
+

arrayMin

Returns the minimum value in an array.

Use Math.min() combined with the spread operator (...) to get the minimum value in the array.

const arrayMin = arr => Math.min(...arr);
+// arrayMin([10, 1, 5]) -> 1
+

chunk

Chunks an array into smaller arrays of a specified size.

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

const chunk = (arr, size) =>
+  Array.from({length: Math.ceil(arr.length / size)}, (v, i) => arr.slice(i * size, i * size + size));
+// chunk([1,2,3,4,5], 2) -> [[1,2],[3,4],[5]]
+

compact

Removes falsey values from an array.

Use Array.filter() to filter out falsey values (false, null, 0, "", undefined, and NaN).

const compact = (arr) => arr.filter(Boolean);
+// compact([0, 1, false, 2, '', 3, 'a', 'e'*23, NaN, 's', 34]) -> [ 1, 2, 3, 'a', 's', 34 ]
+

countOccurrences

Counts the occurrences of a value in an array.

Use Array.reduce() to increment a counter each time you encounter the specific value inside the array.

const countOccurrences = (arr, value) => arr.reduce((a, v) => v === value ? a + 1 : a + 0, 0);
+// countOccurrences([1,1,2,1,2,3], 1) -> 3
+

deepFlatten

Deep flattens an array.

Use recursion. Use Array.concat() with an empty array ([]) and the spread operator (...) to flatten an array. Recursively flatten each element that is an array.

const deepFlatten = arr => [].concat(...arr.map(v => Array.isArray(v) ? deepFlatten(v) : v));
+// deepFlatten([1,[2],[[3],4],5]) -> [1,2,3,4,5]
+

difference

Returns the difference between two arrays.

Create a Set from b, then use Array.filter() on a to only keep values not contained in b.

const difference = (a, b) => { const s = new Set(b); return a.filter(x => !s.has(x)); };
+// difference([1,2,3], [1,2,4]) -> [3]
+

differenceWith

Filters out all values from an array for which the comparator function does not return true.

Use Array.filter() and Array.find() to find the appropriate values.

const differenceWith = (arr, val, comp) => arr.filter(a => !val.find(b => comp(a, b)))
+// differenceWith([1, 1.2, 1.5, 3], [1.9, 3], (a,b) => Math.round(a) == Math.round(b)) -> [1, 1.2]
+

distinctValuesOfArray

Returns all the distinct values of an array.

Use ES6 Set and the ...rest operator to discard all duplicated values.

const distinctValuesOfArray = arr => [...new Set(arr)];
+// distinctValuesOfArray([1,2,2,3,4,4,5]) -> [1,2,3,4,5]
+

dropElements

Removes elements in an array until the passed function returns true. Returns the remaining elements in the array.

Loop through the array, using Array.slice() to drop the first element of the array until the returned value from the function is true. Returns the remaining elements.

const dropElements = (arr, func) => {
+  while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1);
   return arr;
 };
-// dropElements([1, 2, 3, 4], n => n >= 3) -> [3,4]
-
-

dropRight

-

Returns a new array with n elements removed from the right

-

Check if n is shorter than the given array and use Array.slice() to slice it accordingly or return an empty array.

-
const dropRight = (arr, n = 1) => n < arr.length ? arr.slice(0, arr.length - n) : []
-//dropRight([1,2,3]) -> [1,2]
-//dropRight([1,2,3], 2) -> [1]
-//dropRight([1,2,3], 42) -> []
-
-

everyNth

-

Returns every nth element in an array.

-

Use Array.filter() to create a new array that contains every nth element of a given array.

-
const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === 0);
-// everyNth([1,2,3,4,5,6], 2) -> [ 1, 3, 5 ]
-
-

filterNonUnique

-

Filters out the non-unique values in an array.

-

Use Array.filter() for an array containing only the unique values.

-
const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i));
-// filterNonUnique([1,2,2,3,4,4,5]) -> [1,3,5]
-
-

flatten

-

Flattens an array.

-

Use Array.reduce() to get all elements inside the array and concat() to flatten them.

-
const flatten = arr => arr.reduce((a, v) => a.concat(v), []);
-// flatten([1,[2],3,4]) -> [1,2,3,4]
-
-

flattenDepth

-

Flattens an array up to the specified depth.

-

Use recursion, decrementing depth by 1 for each level of depth. -Use Array.reduce() and Array.concat() to merge elements or arrays. -Base case, for depth equal to 1 stops recursion. -Omit the second element, depth to flatten only to a depth of 1 (single flatten).

-
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), []);
-// flattenDepth([1,[2],[[[3],4],5]], 2) -> [1,2,[3],4,5]
-
-

groupBy

-

Groups the element of an array based on the given function.

-

Use Array.map() to map the values of an array to a function or property name. -Use Array.reduce() to create an object, where the keys are produced from the mapped results.

-
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; }, {});
-// groupBy([6.1, 4.2, 6.3], Math.floor) -> {4: [4.2], 6: [6.1, 6.3]}
-// groupBy(['one', 'two', 'three'], 'length') -> {3: ['one', 'two'], 5: ['three']}
-
-

-

Returns the head of a list.

-

Use arr[0] to return the first element of the passed array.

-
const head = arr => arr[0];
-// head([1,2,3]) -> 1
-
-

initial

-

Returns all the elements of an array except the last one.

-

Use arr.slice(0,-1)to return all but the last element of the array.

-
const initial = arr => arr.slice(0, -1);
-// initial([1,2,3]) -> [1,2]
-
-

initialize2DArray

-

Initializes an 2D array of given width and height and value.

-

Use Array.map() to generate h rows where each is a new array of size w initialize with value. If value is not provided, default to null.

-
const initialize2DArray = (w, h, val = null) => Array(h).fill().map(() => Array(w).fill(val));
-// initializeArrayWithRange(2, 2, 0) -> [[0,0], [0,0]]
-
-

initializeArrayWithRange

-

Initializes an array containing the numbers in the specified range where start and end are inclusive.

-

Use Array((end + 1) - start) to create an array of the desired length, Array.map() to fill with the desired values in a range. -You can omit start to use a default value of 0.

-
const initializeArrayWithRange = (end, start = 0) => 
-  Array.from({ length: (end + 1) - start }).map((v, i) => i + start);
-// initializeArrayWithRange(5) -> [0,1,2,3,4,5]
-// initializeArrayWithRange(7, 3) -> [3,4,5,6,7]
-
-

initializeArrayWithValues

-

Initializes and fills an array with the specified values.

-

Use Array(n) to create an array of the desired length, fill(v) to fill it with the desired values. -You can omit value to use a default value of 0.

-
const initializeArrayWithValues = (n, value = 0) => Array(n).fill(value);
-// initializeArrayWithValues(5, 2) -> [2,2,2,2,2]
-
-

intersection

-

Returns a list of elements that exist in both arrays.

-

Create a Set from b, then use Array.filter() on a to only keep values contained in b.

-
const intersection = (a, b) => { const s = new Set(b); return a.filter(x => s.has(x)); };
-// intersection([1,2,3], [4,3,2]) -> [2,3]
-
-

last

-

Returns the last element in an array.

-

Use arr.length - 1 to compute index of the last element of the given array and returning it.

-
const last = arr => arr[arr.length - 1];
-// last([1,2,3]) -> 3
-
-

mapObject

-

Maps the values of an array to an object using a function, where the key-value pairs consist of the original value as the key and the mapped value.

-

Use an anonymous inner function scope to declare an undefined memory space, using closures to store a return value. Use a new Array to stor the array with a map of the function over its data set and a comma operator to return a second step, without needing to move from one context to another (due to closures and order of operations).

-
const mapObject = (arr, fn) => 
-  (a => (a = [arr, arr.map(fn)], a[0].reduce( (acc,val,ind) => (acc[val] = a[1][ind], acc), {}) )) ( );
+// dropElements([1, 2, 3, 4], n => n >= 3) -> [3,4]
+

dropRight

Returns a new array with n elements removed from the right

Check if n is shorter than the given array and use Array.slice() to slice it accordingly or return an empty array.

const dropRight = (arr, n = 1) => n < arr.length ? arr.slice(0, arr.length - n) : []
+//dropRight([1,2,3]) -> [1,2]
+//dropRight([1,2,3], 2) -> [1]
+//dropRight([1,2,3], 42) -> []
+

everyNth

Returns every nth element in an array.

Use Array.filter() to create a new array that contains every nth element of a given array.

const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === 0);
+// everyNth([1,2,3,4,5,6], 2) -> [ 1, 3, 5 ]
+

filterNonUnique

Filters out the non-unique values in an array.

Use Array.filter() for an array containing only the unique values.

const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i));
+// filterNonUnique([1,2,2,3,4,4,5]) -> [1,3,5]
+

flatten

Flattens an array.

Use Array.reduce() to get all elements inside the array and concat() to flatten them.

const flatten = arr => arr.reduce((a, v) => a.concat(v), []);
+// flatten([1,[2],3,4]) -> [1,2,3,4]
+

flattenDepth

Flattens an array up to the specified depth.

Use recursion, decrementing depth by 1 for each level of depth. Use Array.reduce() and Array.concat() to merge elements or arrays. Base case, for depth equal to 1 stops recursion. Omit the second element, depth to flatten only to a depth of 1 (single flatten).

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), []);
+// flattenDepth([1,[2],[[[3],4],5]], 2) -> [1,2,[3],4,5]
+

groupBy

Groups the element of an array based on the given function.

Use Array.map() to map the values of an array to a function or property name. Use Array.reduce() to create an object, where the keys are produced from the mapped results.

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; }, {});
+// groupBy([6.1, 4.2, 6.3], Math.floor) -> {4: [4.2], 6: [6.1, 6.3]}
+// groupBy(['one', 'two', 'three'], 'length') -> {3: ['one', 'two'], 5: ['three']}
+

Returns the head of a list.

Use arr[0] to return the first element of the passed array.

const head = arr => arr[0];
+// head([1,2,3]) -> 1
+

initial

Returns all the elements of an array except the last one.

Use arr.slice(0,-1)to return all but the last element of the array.

const initial = arr => arr.slice(0, -1);
+// initial([1,2,3]) -> [1,2]
+

initialize2DArray

Initializes an 2D array of given width and height and value.

Use Array.map() to generate h rows where each is a new array of size w initialize with value. If value is not provided, default to null.

const initialize2DArray = (w, h, val = null) => Array(h).fill().map(() => Array(w).fill(val));
+// initializeArrayWithRange(2, 2, 0) -> [[0,0], [0,0]]
+

initializeArrayWithRange

Initializes an array containing the numbers in the specified range where start and end are inclusive.

Use Array((end + 1) - start) to create an array of the desired length, Array.map() to fill with the desired values in a range. You can omit start to use a default value of 0.

const initializeArrayWithRange = (end, start = 0) => 
+  Array.from({ length: (end + 1) - start }).map((v, i) => i + start);
+// initializeArrayWithRange(5) -> [0,1,2,3,4,5]
+// initializeArrayWithRange(7, 3) -> [3,4,5,6,7]
+

initializeArrayWithValues

Initializes and fills an array with the specified values.

Use Array(n) to create an array of the desired length, fill(v) to fill it with the desired values. You can omit value to use a default value of 0.

const initializeArrayWithValues = (n, value = 0) => Array(n).fill(value);
+// initializeArrayWithValues(5, 2) -> [2,2,2,2,2]
+

intersection

Returns a list of elements that exist in both arrays.

Create a Set from b, then use Array.filter() on a to only keep values contained in b.

const intersection = (a, b) => { const s = new Set(b); return a.filter(x => s.has(x)); };
+// intersection([1,2,3], [4,3,2]) -> [2,3]
+

last

Returns the last element in an array.

Use arr.length - 1 to compute index of the last element of the given array and returning it.

const last = arr => arr[arr.length - 1];
+// last([1,2,3]) -> 3
+

mapObject

Maps the values of an array to an object using a function, where the key-value pairs consist of the original value as the key and the mapped value.

Use an anonymous inner function scope to declare an undefined memory space, using closures to store a return value. Use a new Array to stor the array with a map of the function over its data set and a comma operator to return a second step, without needing to move from one context to another (due to closures and order of operations).

const mapObject = (arr, fn) => 
+  (a => (a = [arr, arr.map(fn)], a[0].reduce( (acc,val,ind) => (acc[val] = a[1][ind], acc), {}) )) ( );
 /*
-const squareIt = arr => mapObject(arr, a => a*a)
+const squareIt = arr => mapObject(arr, a => a*a)
 squareIt([1,2,3]) // { 1: 1, 2: 4, 3: 9 }
 */
-
-

nthElement

-

Returns the nth element of an array.

-

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

-
const nthElement = (arr, n=0) => (n>0? arr.slice(n,n+1) : arr.slice(n))[0];
-// nthElement(['a','b','c'],1) -> 'b'
-// nthElement(['a','b','b'],-3) -> 'a'
-
-

pick

-

Picks the key-value pairs corresponding to the given keys from an object.

-

Use Array.reduce() to convert the filtered/picked keys back to a object with the corresponding key-value pair if the key exist in the obj.

-
const pick = (obj, arr) =>
-  arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {});
-// pick({ 'a': 1, 'b': '2', 'c': 3 }, ['a', 'c']) -> { 'a': 1, 'c': 3 }
-
-

pull

-

Mutates the original array to filter out the values specified.

-

Use Array.filter() and Array.includes() to pull out the values that are not needed. -Use Array.length = 0 to mutate the passed in array by resetting it's length to zero and Array.push() to re-populate it with only the pulled values.

-

(For a snippet that does not mutate the original array see without)

-
const pull = (arr, ...args) => {
+

nthElement

Returns the nth element of an array.

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

const nthElement = (arr, n=0) => (n>0? arr.slice(n,n+1) : arr.slice(n))[0];
+// nthElement(['a','b','c'],1) -> 'b'
+// nthElement(['a','b','b'],-3) -> 'a'
+

pick

Picks the key-value pairs corresponding to the given keys from an object.

Use Array.reduce() to convert the filtered/picked keys back to a object with the corresponding key-value pair if the key exist in the obj.

const pick = (obj, arr) =>
+  arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {});
+// pick({ 'a': 1, 'b': '2', 'c': 3 }, ['a', 'c']) -> { 'a': 1, 'c': 3 }
+

pull

Mutates the original array to filter out the values specified.

Use Array.filter() and Array.includes() to pull out the values that are not needed. Use Array.length = 0 to mutate the passed in array by resetting it's length to zero and Array.push() to re-populate it with only the pulled values.

(For a snippet that does not mutate the original array see without)

const pull = (arr, ...args) => {
   let argState = Array.isArray(args[0]) ? args[0] : args;
-  let pulled = arr.filter((v, i) => !argState.includes(v));
+  let pulled = arr.filter((v, i) => !argState.includes(v));
   arr.length = 0; 
-  pulled.forEach(v => arr.push(v));
+  pulled.forEach(v => arr.push(v));
 };
 
 // let myArray1 = ['a', 'b', 'c', 'a', 'b', 'c'];
 // pull(myArray1, 'a', 'c');
-// console.log(myArray1) -> [ 'b', 'b' ]
+// console.log(myArray1) -> [ 'b', 'b' ]
 
 // let myArray2 = ['a', 'b', 'c', 'a', 'b', 'c'];
 // pull(myArray2, ['a', 'c']);
-// console.log(myArray2) -> [ 'b', 'b' ]
-
-

pullAtIndex

-

Mutates the original array to filter out the values at the specified indexes.

-

Use Array.filter() and Array.includes() to pull out the values that are not needed. -Use Array.length = 0 to mutate the passed in array by resetting it's length to zero and Array.push() to re-populate it with only the pulled values. -Use Array.push() to keep track of pulled values

-
const pullAtIndex = (arr, pullArr) => {
+// console.log(myArray2) -> [ 'b', 'b' ]
+

pullAtIndex

Mutates the original array to filter out the values at the specified indexes.

Use Array.filter() and Array.includes() to pull out the values that are not needed. Use Array.length = 0 to mutate the passed in array by resetting it's length to zero and Array.push() to re-populate it with only the pulled values. Use Array.push() to keep track of pulled values

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))
+  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));
+  pulled.forEach(v => arr.push(v));
   return removed;
 }
 
 // let myArray = ['a', 'b', 'c', 'd'];
 // let pulled = pullAtIndex(myArray, [1, 3]);
 
-// console.log(myArray); -> [ 'a', 'c' ]
-// console.log(pulled); -> [ 'b', 'd' ]
-
-

pullAtValue

-

Mutates the original array to filter out the values specified. Returns the removed elements.

-

Use Array.filter() and Array.includes() to pull out the values that are not needed. -Use Array.length = 0 to mutate the passed in array by resetting it's length to zero and Array.push() to re-populate it with only the pulled values. -Use Array.push() to keep track of pulled values

-
const pullAtValue = (arr, pullArr) => {
+// console.log(myArray); -> [ 'a', 'c' ]
+// console.log(pulled); -> [ 'b', 'd' ]
+

pullAtValue

Mutates the original array to filter out the values specified. Returns the removed elements.

Use Array.filter() and Array.includes() to pull out the values that are not needed. Use Array.length = 0 to mutate the passed in array by resetting it's length to zero and Array.push() to re-populate it with only the pulled values. Use Array.push() to keep track of pulled values

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));
+    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));
+  mutateTo.forEach(v => arr.push(v));
   return removed;
 }
 /*
 let myArray = ['a', 'b', 'c', 'd'];
 let pulled = pullAtValue(myArray, ['b', 'd']);
-console.log(myArray); -> [ 'a', 'c' ]
-console.log(pulled); -> [ 'b', 'd' ]
+console.log(myArray); -> [ 'a', 'c' ]
+console.log(pulled); -> [ 'b', 'd' ]
 */
-
-

remove

-

Removes elements from an array for which the given function returns false.

-

Use Array.filter() to find array elements that return truthy values and Array.reduce() to remove elements using Array.splice(). -The func is invoked with three arguments (value, index, array).

-
const remove = (arr, func) =>
-  Array.isArray(arr) ? arr.filter(func).reduce((acc, val) => {
+

remove

Removes elements from an array for which the given function returns false.

Use Array.filter() to find array elements that return truthy values and Array.reduce() to remove elements using Array.splice(). The func is invoked with three arguments (value, index, array).

const remove = (arr, func) =>
+  Array.isArray(arr) ? arr.filter(func).reduce((acc, val) => {
     arr.splice(arr.indexOf(val), 1); return acc.concat(val);
     }, [])
   : [];
-// remove([1, 2, 3, 4], n => n % 2 == 0) -> [2, 4]
-
-

sample

-

Returns a random element from an array.

-

Use Math.random() to generate a random number, multiply it with length and round it of to the nearest whole number using Math.floor(). -This method also works with strings.

-
const sample = arr => arr[Math.floor(Math.random() * arr.length)];
-// sample([3, 7, 9, 11]) -> 9
-
-

shuffle

-

Randomizes the order of the values of an array.

-

Use Array.sort() to reorder elements, using Math.random() in the comparator.

-
const shuffle = arr => arr.sort(() => Math.random() - 0.5);
-// shuffle([1,2,3]) -> [2,3,1]
-
-

similarity

-

Returns an array of elements that appear in both arrays.

-

Use filter() to remove values that are not part of values, determined using includes().

-
const similarity = (arr, values) => arr.filter(v => values.includes(v));
-// similarity([1,2,3], [1,2,4]) -> [1,2]
-
-

symmetricDifference

-

Returns the symmetric difference between two arrays.

-

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

-
const symmetricDifference = (a, b) => {
+// remove([1, 2, 3, 4], n => n % 2 == 0) -> [2, 4]
+

sample

Returns a random element from an array.

Use Math.random() to generate a random number, multiply it with length and round it of to the nearest whole number using Math.floor(). This method also works with strings.

const sample = arr => arr[Math.floor(Math.random() * arr.length)];
+// sample([3, 7, 9, 11]) -> 9
+

shuffle

Randomizes the order of the values of an array.

Use Array.sort() to reorder elements, using Math.random() in the comparator.

const shuffle = arr => arr.sort(() => Math.random() - 0.5);
+// shuffle([1,2,3]) -> [2,3,1]
+

similarity

Returns an array of elements that appear in both arrays.

Use filter() to remove values that are not part of values, determined using includes().

const similarity = (arr, values) => arr.filter(v => values.includes(v));
+// similarity([1,2,3], [1,2,4]) -> [1,2]
+

symmetricDifference

Returns the symmetric difference between two arrays.

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

const symmetricDifference = (a, b) => {
   const sA = new Set(a), sB = new Set(b);
-  return [...a.filter(x => !sB.has(x)), ...b.filter(x => !sA.has(x))];
+  return [...a.filter(x => !sB.has(x)), ...b.filter(x => !sA.has(x))];
 }
-// symmetricDifference([1,2,3], [1,2,4]) -> [3,4]
-
-

tail

-

Returns all elements in an array except for the first one.

-

Return arr.slice(1) if the array's length is more than 1, otherwise return the whole array.

-
const tail = arr => arr.length > 1 ? arr.slice(1) : arr;
-// tail([1,2,3]) -> [2,3]
-// tail([1]) -> [1]
-
-

take

-

Returns an array with n elements removed from the beginning.

-

Use Array.slice() to create a slice of the array with n elements taken from the beginning.

-
const take = (arr, n = 1) => arr.slice(0, n);
-// take([1, 2, 3], 5) -> [1, 2, 3]
-// take([1, 2, 3], 0) -> []
-
-

takeRight

-

Returns an array with n elements removed from the end.

-

Use Array.slice() to create a slice of the array with n elements taken from the end.

-
const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length);
-// takeRight([1, 2, 3], 2) -> [ 2, 3 ]
-// takeRight([1, 2, 3]) -> [3]
-
-

union

-

Returns every element that exists in any of the two arrays once.

-

Create a Set with all values of a and b and convert to an array.

-
const union = (a, b) => Array.from(new Set([...a, ...b]));
-// union([1,2,3], [4,3,2]) -> [1,2,3,4]
-
-

without

-

Filters out the elements of an array, that have one of the specified values.

-

Use Array.filter() to create an array excluding(using !Array.includes()) all given values.

-

(For a snippet that mutates the original array see pull)

-
const without = (arr, ...args) => arr.filter(v => !args.includes(v));
-// without([2, 1, 2, 3], 1, 2) -> [3]
-
-

zip

-

Creates an array of elements, grouped based on the position in the original arrays.

-

Use Math.max.apply() to get the longest array in the arguments. -Creates an array with that length as return value and use Array.from() with a map-function to create an array of grouped elements. -If lengths of the argument-arrays vary, undefined is used where no value could be found.

-
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]);
+// symmetricDifference([1,2,3], [1,2,4]) -> [3,4]
+

tail

Returns all elements in an array except for the first one.

Return arr.slice(1) if the array's length is more than 1, otherwise return the whole array.

const tail = arr => arr.length > 1 ? arr.slice(1) : arr;
+// tail([1,2,3]) -> [2,3]
+// tail([1]) -> [1]
+

take

Returns an array with n elements removed from the beginning.

Use Array.slice() to create a slice of the array with n elements taken from the beginning.

const take = (arr, n = 1) => arr.slice(0, n);
+// take([1, 2, 3], 5) -> [1, 2, 3]
+// take([1, 2, 3], 0) -> []
+

takeRight

Returns an array with n elements removed from the end.

Use Array.slice() to create a slice of the array with n elements taken from the end.

const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length);
+// takeRight([1, 2, 3], 2) -> [ 2, 3 ]
+// takeRight([1, 2, 3]) -> [3]
+

union

Returns every element that exists in any of the two arrays once.

Create a Set with all values of a and b and convert to an array.

const union = (a, b) => Array.from(new Set([...a, ...b]));
+// union([1,2,3], [4,3,2]) -> [1,2,3,4]
+

without

Filters out the elements of an array, that have one of the specified values.

Use Array.filter() to create an array excluding(using !Array.includes()) all given values.

(For a snippet that mutates the original array see pull)

const without = (arr, ...args) => arr.filter(v => !args.includes(v));
+// without([2, 1, 2, 3], 1, 2) -> [3]
+

zip

Creates an array of elements, grouped based on the position in the original arrays.

Use Math.max.apply() to get the longest array in the arguments. Creates an array with that length as return value and use Array.from() with a map-function to create an array of grouped elements. If lengths of the argument-arrays vary, undefined is used where no value could be found.

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]);
   })
 }
-//zip(['a', 'b'], [1, 2], [true, false]); -> [['a', 1, true], ['b', 2, false]]
-//zip(['a'], [1, 2], [true, false]); -> [['a', 1, true], [undefined, 2, false]]
-
-

zipObject

-

Given an array of valid property identifiers and an array of values, return an object associating the properties to the values.

-

Since an object can have undefined values but not undefined property pointers, the array of properties is used to decide the structure of the resulting object using Array.reduce().

-
const zipObject = ( props, values ) => props.reduce( ( obj, prop, index ) => ( obj[prop] = values[index], obj ), {} )
-// zipObject(['a','b','c'], [1,2]) -> {a: 1, b: 2, c: undefined}
-// zipObject(['a','b'], [1,2,3]) -> {a: 1, b: 2}
-
-

Browser

-

arrayToHtmlList

-

Converts the given array elements into <li> tags and appends them to the list of the given id.

-

Use Array.map() and document.querySelector() to create a list of html tags.

-
const arrayToHtmlList = (arr, listID) => arr.map(item => document.querySelector("#"+listID).innerHTML+=`<li>${item}</li>`);
+//zip(['a', 'b'], [1, 2], [true, false]); -> [['a', 1, true], ['b', 2, false]]
+//zip(['a'], [1, 2], [true, false]); -> [['a', 1, true], [undefined, 2, false]]
+

zipObject

Given an array of valid property identifiers and an array of values, return an object associating the properties to the values.

Since an object can have undefined values but not undefined property pointers, the array of properties is used to decide the structure of the resulting object using Array.reduce().

const zipObject = ( props, values ) => props.reduce( ( obj, prop, index ) => ( obj[prop] = values[index], obj ), {} )
+// zipObject(['a','b','c'], [1,2]) -> {a: 1, b: 2, c: undefined}
+// zipObject(['a','b'], [1,2,3]) -> {a: 1, b: 2}
+

Browser

arrayToHtmlList

Converts the given array elements into <li> tags and appends them to the list of the given id.

Use Array.map() and document.querySelector() to create a list of html tags.

const arrayToHtmlList = (arr, listID) => arr.map(item => document.querySelector("#"+listID).innerHTML+=`<li>${item}</li>`);
 // arrayToHtmlList(['item 1', 'item 2'],'myListID')
-
-

bottomVisible

-

Returns true if the bottom of the page is visible, false otherwise.

-

Use scrollY, scrollHeight and clientHeight to determine if the bottom of the page is visible.

-
const bottomVisible = () =>
-  document.documentElement.clientHeight + window.scrollY >= (document.documentElement.scrollHeight || document.documentElement.clientHeight);
-// bottomVisible() -> true
-
-

currentURL

-

Returns the current URL.

-

Use window.location.href to get current URL.

-
const currentURL = () => window.location.href;
-// currentUrl() -> 'https://google.com'
-
-

elementIsVisibleInViewport

-

Returns true if the element specified is visible in the viewport, false otherwise.

-

Use Element.getBoundingClientRect() and the window.inner(Width|Height) values -to determine if a given element is visible in the viewport. -Omit the second argument to determine if the element is entirely visible, or specify true to determine if -it is partially visible.

-
const elementIsVisibleInViewport = (el, partiallyVisible = false) => {
+

bottomVisible

Returns true if the bottom of the page is visible, false otherwise.

Use scrollY, scrollHeight and clientHeight to determine if the bottom of the page is visible.

const bottomVisible = () =>
+  document.documentElement.clientHeight + window.scrollY >= (document.documentElement.scrollHeight || document.documentElement.clientHeight);
+// bottomVisible() -> true
+

currentURL

Returns the current URL.

Use window.location.href to get current URL.

const currentURL = () => window.location.href;
+// currentUrl() -> 'https://google.com'
+

elementIsVisibleInViewport

Returns true if the element specified is visible in the viewport, false otherwise.

Use Element.getBoundingClientRect() and the window.inner(Width|Height) values to determine if a given element is visible in the viewport. Omit the second argument to determine if the element is entirely visible, or specify true to determine if it is partially visible.

const elementIsVisibleInViewport = (el, partiallyVisible = false) => {
   const { top, left, bottom, right } = el.getBoundingClientRect();
   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;
+    ? ((top > 0 && top < innerHeight) || (bottom > 0 && bottom < innerHeight)) &&
+      ((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth))
+    : top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth;
 };
 // e.g. 100x100 viewport and a 10x10px element at position {top: -1, left: 0, bottom: 9, right: 10}
-// elementIsVisibleInViewport(el) -> false (not fully visible)
-// elementIsVisibleInViewport(el, true) -> true (partially visible)
-
-

getScrollPosition

-

Returns the scroll position of the current page.

-

Use pageXOffset and pageYOffset if they are defined, otherwise scrollLeft and scrollTop. -You can omit el to use a default value of window.

-
const getScrollPosition = (el = window) =>
+// elementIsVisibleInViewport(el) -> false (not fully visible)
+// elementIsVisibleInViewport(el, true) -> true (partially visible)
+

getScrollPosition

Returns the scroll position of the current page.

Use pageXOffset and pageYOffset if they are defined, otherwise scrollLeft and scrollTop. You can omit el to use a default value of window.

const getScrollPosition = (el = window) =>
   ({x: (el.pageXOffset !== undefined) ? el.pageXOffset : el.scrollLeft,
     y: (el.pageYOffset !== undefined) ? el.pageYOffset : el.scrollTop});
-// getScrollPosition() -> {x: 0, y: 200}
-
-

getURLParameters

-

Returns an object containing the parameters of the current URL.

-

Use match() with an appropriate regular expression to get all key-value pairs, Array.reduce() to map and combine them into a single object. -Pass location.search as the argument to apply to the current url.

-
const getURLParameters = url =>
-  url.match(/([^?=&]+)(=([^&]*))/g).reduce(
-    (a, v) => (a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1), a), {}
+// getScrollPosition() -> {x: 0, y: 200}
+

getURLParameters

Returns an object containing the parameters of the current URL.

Use match() with an appropriate regular expression to get all key-value pairs, Array.reduce() to map and combine them into a single object. Pass location.search as the argument to apply to the current url.

const getURLParameters = url =>
+  url.match(/([^?=&]+)(=([^&]*))/g).reduce(
+    (a, v) => (a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1), a), {}
   );
-// getURLParameters('http://url.com/page?name=Adam&surname=Smith') -> {name: 'Adam', surname: 'Smith'}
-
-

redirect

-

Redirects to a specified URL.

-

Use window.location.href or window.location.replace() to redirect to url. -Pass a second argument to simulate a link click (true - default) or an HTTP redirect (false).

-
const redirect = (url, asLink = true) =>
+// getURLParameters('http://url.com/page?name=Adam&surname=Smith') -> {name: 'Adam', surname: 'Smith'}
+

redirect

Redirects to a specified URL.

Use window.location.href or window.location.replace() to redirect to url. Pass a second argument to simulate a link click (true - default) or an HTTP redirect (false).

const redirect = (url, asLink = true) =>
   asLink ? window.location.href = url : window.location.replace(url);
 // redirect('https://google.com')
-
-

scrollToTop

-

Smooth-scrolls to the top of the page.

-

Get distance from top using document.documentElement.scrollTop or document.body.scrollTop. -Scroll by a fraction of the distance from top. Use window.requestAnimationFrame() to animate the scrolling.

-
const scrollToTop = () => {
+

scrollToTop

Smooth-scrolls to the top of the page.

Get distance from top using document.documentElement.scrollTop or document.body.scrollTop. Scroll by a fraction of the distance from top. Use window.requestAnimationFrame() to animate the scrolling.

const scrollToTop = () => {
   const c = document.documentElement.scrollTop || document.body.scrollTop;
-  if (c > 0) {
+  if (c > 0) {
     window.requestAnimationFrame(scrollToTop);
     window.scrollTo(0, c - c / 8);
   }
 };
 // scrollToTop()
-
-

Date

-

getDaysDiffBetweenDates

-

Returns the difference (in days) between two dates.

-

Calculate the difference (in days) between to Date objects.

-
const getDaysDiffBetweenDates = (dateInitial, dateFinal) => (dateFinal - dateInitial) / (1000 * 3600 * 24);
-// getDaysDiffBetweenDates(new Date("2017-12-13"), new Date("2017-12-22")) -> 9
-
-

JSONToDate

-

Converts a JSON object to a date.

-

Use Date(), to convert dates in JSON format to readable format (dd/mm/yyyy).

-
const JSONToDate = arr => {
+

Date

getDaysDiffBetweenDates

Returns the difference (in days) between two dates.

Calculate the difference (in days) between to Date objects.

const getDaysDiffBetweenDates = (dateInitial, dateFinal) => (dateFinal - dateInitial) / (1000 * 3600 * 24);
+// getDaysDiffBetweenDates(new Date("2017-12-13"), new Date("2017-12-22")) -> 9
+

JSONToDate

Converts a JSON object to a date.

Use Date(), to convert dates in JSON format to readable format (dd/mm/yyyy).

const JSONToDate = arr => {
   const dt = new Date(parseInt(arr.toString().substr(6)));
   return `${ dt.getDate() }/${ dt.getMonth() + 1 }/${ dt.getFullYear() }`
 };
-// JSONToDate(/Date(1489525200000)/) -> "14/3/2017"
-
-

toEnglishDate

-

Converts a date from American format to English format.

-

Use Date.toISOString(), split('T') and replace() to convert a date from American format to English format. -Throws an error if the passed time cannot be converted to a date.

-
const toEnglishDate  = (time) =>
+// JSONToDate(/Date(1489525200000)/) -> "14/3/2017"
+

toEnglishDate

Converts a date from American format to English format.

Use Date.toISOString(), split('T') and replace() to convert a date from American format to English format. Throws an error if the passed time cannot be converted to a date.

const toEnglishDate  = (time) =>
   {try{return new Date(time).toISOString().split('T')[0].replace(/-/g, '/')}catch(e){return}};
-// toEnglishDate('09/21/2010') -> '21/09/2010'
-
-

Function

-

chainAsync

-

Chains asynchronous functions.

-

Loop through an array of functions containing asynchronous events, calling next when each asynchronous event has completed.

-
const chainAsync = fns => { let curr = 0; const next = () => fns[curr++](next); next(); };
+// toEnglishDate('09/21/2010') -> '21/09/2010'
+

Function

chainAsync

Chains asynchronous functions.

Loop through an array of functions containing asynchronous events, calling next when each asynchronous event has completed.

const chainAsync = fns => { let curr = 0; const next = () => fns[curr++](next); next(); };
 /*
 chainAsync([
-  next => { console.log('0 seconds'); setTimeout(next, 1000); },
-  next => { console.log('1 second');  setTimeout(next, 1000); },
-  next => { console.log('2 seconds'); }
+  next => { console.log('0 seconds'); setTimeout(next, 1000); },
+  next => { console.log('1 second');  setTimeout(next, 1000); },
+  next => { console.log('2 seconds'); }
 ])
 */
-
-

compose

-

Performs right-to-left function composition.

-

Use Array.reduce() to perform right-to-left function composition. -The last (rightmost) function can accept one or more arguments; the remaining functions must be unary.

-
const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)));
+

compose

Performs right-to-left function composition.

Use Array.reduce() to perform right-to-left function composition. The last (rightmost) function can accept one or more arguments; the remaining functions must be unary.

const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)));
 /*
-const add5 = x => x + 5
-const multiply = (x, y) => x * y
+const add5 = x => x + 5
+const multiply = (x, y) => x * y
 const multiplyAndAdd5 = compose(add5, multiply)
-multiplyAndAdd5(5, 2) -> 15
+multiplyAndAdd5(5, 2) -> 15
 */
-
-

curry

-

Curries a function.

-

Use recursion. -If the number of provided arguments (args) is sufficient, call the passed function f. -Otherwise return a curried function f that expects the rest of the arguments. -If you want to curry a function that accepts a variable number of arguments (a variadic function, e.g. Math.min()), you can optionally pass the number of arguments to the second parameter arity.

-
const curry = (fn, arity = fn.length, ...args) =>
+

curry

Curries a function.

Use recursion. If the number of provided arguments (args) is sufficient, call the passed function f. Otherwise return a curried function f that expects the rest of the arguments. If you want to curry a function that accepts a variable number of arguments (a variadic function, e.g. Math.min()), you can optionally pass the number of arguments to the second parameter arity.

const curry = (fn, arity = fn.length, ...args) =>
   arity <= args.length
     ? fn(...args)
     : curry.bind(null, fn, arity, ...args);
-// curry(Math.pow)(2)(10) -> 1024
-// curry(Math.min, 3)(10)(50)(2) -> 2
-
-

functionName

-

Logs the name of a function.

-

Use console.debug() and the name property of the passed method to log the method's name to the debug channel of the console.

-
const functionName = fn => (console.debug(fn.name), fn);
-// functionName(Math.max) -> max (logged in debug channel of console)
-
-

pipe

-

Performs left-to-right function composition.

-

Use Array.reduce() with the spread operator (...) to perform left-to-right function composition. -The first (leftmost) function can accept one or more arguments; the remaining functions must be unary.

-
const pipeFunctions = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args)));
+// curry(Math.pow)(2)(10) -> 1024
+// curry(Math.min, 3)(10)(50)(2) -> 2
+

functionName

Logs the name of a function.

Use console.debug() and the name property of the passed method to log the method's name to the debug channel of the console.

const functionName = fn => (console.debug(fn.name), fn);
+// functionName(Math.max) -> max (logged in debug channel of console)
+

pipe

Performs left-to-right function composition.

Use Array.reduce() with the spread operator (...) to perform left-to-right function composition. The first (leftmost) function can accept one or more arguments; the remaining functions must be unary.

const pipeFunctions = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args)));
 /*
-const add5 = x => x + 5
-const multiply = (x, y) => x * y
+const add5 = x => x + 5
+const multiply = (x, y) => x * y
 const multiplyAndAdd5 = pipeFunctions(multiply, add5)
-multiplyAndAdd5(5, 2) -> 15
+multiplyAndAdd5(5, 2) -> 15
 */
-
-

promisify

-

Converts an asynchronous function to return a promise.

-

Use currying to return a function returning a Promise that calls the original function. -Use the ...rest operator to pass in all the parameters.

-

In Node 8+, you can use util.promisify

-
const promisify = func =>
-  (...args) =>
-    new Promise((resolve, reject) =>
-      func(...args, (err, result) =>
+

promisify

Converts an asynchronous function to return a promise.

Use currying to return a function returning a Promise that calls the original function. Use the ...rest operator to pass in all the parameters.

In Node 8+, you can use util.promisify

const promisify = func =>
+  (...args) =>
+    new Promise((resolve, reject) =>
+      func(...args, (err, result) =>
         err ? reject(err) : resolve(result))
     );
-// const delay = promisify((d, cb) => setTimeout(cb, d))
-// delay(2000).then(() => console.log('Hi!')) -> Promise resolves after 2s
-
-

runPromisesInSeries

-

Runs an array of promises in series.

-

Use Array.reduce() to create a promise chain, where each promise returns the next promise when resolved.

-
const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve());
-// const delay = (d) => new Promise(r => setTimeout(r, d))
-// runPromisesInSeries([() => delay(1000), () => delay(2000)]) -> executes each promise sequentially, taking a total of 3 seconds to complete
-
-

sleep

-

Delays the execution of an asynchronous function.

-

Delay executing part of an async function, by putting it to sleep, returning a Promise.

-
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
+// const delay = promisify((d, cb) => setTimeout(cb, d))
+// delay(2000).then(() => console.log('Hi!')) -> Promise resolves after 2s
+

runPromisesInSeries

Runs an array of promises in series.

Use Array.reduce() to create a promise chain, where each promise returns the next promise when resolved.

const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve());
+// const delay = (d) => new Promise(r => setTimeout(r, d))
+// runPromisesInSeries([() => delay(1000), () => delay(2000)]) -> executes each promise sequentially, taking a total of 3 seconds to complete
+

sleep

Delays the execution of an asynchronous function.

Delay executing part of an async function, by putting it to sleep, returning a Promise.

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
 /*
 async function sleepyWork() {
   console.log('I\'m going to sleep for 1 second.');
@@ -726,241 +258,108 @@ async function sleepyWork() {
   console.log('I woke up after 1 second.');
 }
 */
-
-

Math

-

arrayAverage

-

Returns the average of an array of numbers.

-

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

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

arraySum

-

Returns the sum of an array of numbers.

-

Use Array.reduce() to add each value to an accumulator, initialized with a value of 0.

-
const arraySum = arr => arr.reduce((acc, val) => acc + val, 0);
-// arraySum([1,2,3,4]) -> 10
-
-

clampNumber

-

Clamps num within the inclusive lower and upper bounds.

-

If lower is greater than upper, swap them. -If num falls within the range, return num. -Otherwise return the nearest number in the range.

-
const clampNumber = (num, lower, upper) => {
-  if(lower > upper) upper = [lower, lower = upper][0];
-  return (num>=lower && num<=upper) ? num : ((num < lower) ? lower : upper) 
+

Math

arrayAverage

Returns the average of an array of numbers.

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

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

arraySum

Returns the sum of an array of numbers.

Use Array.reduce() to add each value to an accumulator, initialized with a value of 0.

const arraySum = arr => arr.reduce((acc, val) => acc + val, 0);
+// arraySum([1,2,3,4]) -> 10
+

clampNumber

Clamps num within the inclusive lower and upper bounds.

If lower is greater than upper, swap them. If num falls within the range, return num. Otherwise return the nearest number in the range.

const clampNumber = (num, lower, upper) => {
+  if(lower > upper) upper = [lower, lower = upper][0];
+  return (num>=lower && num<=upper) ? num : ((num < lower) ? lower : upper) 
 }
-// clampNumber(2, 3, 5) -> 3
-// clampNumber(1, -1, -5) -> -1
-// clampNumber(3, 2, 4) -> 3
-
-

collatz

-

Applies the Collatz algorithm.

-

If n is even, return n/2. Otherwise return 3n+1.

-
const collatz = n => (n % 2 == 0) ? (n / 2) : (3 * n + 1);
-// collatz(8) --> 4
-// collatz(5) --> 16
-
-

digitize

-

Converts a number to an array of digits.

-

Convert the number to a string, using spread operators in ES6([...string]) build an array. -Use Array.map() and parseInt() to transform each value to an integer.

-
const digitize = n => [...''+n].map(i => parseInt(i));
-// digitize(2334) -> [2, 3, 3, 4]
-
-

distance

-

Returns the distance between two points.

-

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

-
const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0);
-// distance(1,1, 2,3) -> 2.23606797749979
-
-

factorial

-

Calculates the factorial of a number.

-

Use recursion. -If n is less than or equal to 1, return 1. -Otherwise, return the product of n and the factorial of n - 1. -Throws an exception if n is a negative number.

-
const factorial = n =>
-  n < 0 ? (() => { throw new TypeError('Negative numbers are not allowed!') })()
+// clampNumber(2, 3, 5) -> 3
+// clampNumber(1, -1, -5) -> -1
+// clampNumber(3, 2, 4) -> 3
+

collatz

Applies the Collatz algorithm.

If n is even, return n/2. Otherwise return 3n+1.

const collatz = n => (n % 2 == 0) ? (n / 2) : (3 * n + 1);
+// collatz(8) --> 4
+// collatz(5) --> 16
+

digitize

Converts a number to an array of digits.

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

const digitize = n => [...''+n].map(i => parseInt(i));
+// digitize(2334) -> [2, 3, 3, 4]
+

distance

Returns the distance between two points.

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

const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0);
+// distance(1,1, 2,3) -> 2.23606797749979
+

factorial

Calculates the factorial of a number.

Use recursion. If n is less than or equal to 1, return 1. Otherwise, return the product of n and the factorial of n - 1. Throws an exception if n is a negative number.

const factorial = n =>
+  n < 0 ? (() => { throw new TypeError('Negative numbers are not allowed!') })()
   : n <= 1 ? 1 : n * factorial(n - 1);
-// factorial(6) -> 720
-
-

fibonacci

-

Generates an array, containing the Fibonacci sequence, up until the nth term.

-

Create an empty array of the specific length, initializing the first two values (0 and 1). -Use Array.reduce() to add values into the array, using the sum of the last two values, except for the first two.

-
const fibonacci = n =>
-  Array(n).fill(0).reduce((acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), []);
-// fibonacci(5) -> [0,1,1,2,3]
-
-

gcd

-

Calculates the greatest common divisor between two numbers.

-

Use recursion. -Base case is when y equals 0. In this case, return x. -Otherwise, return the GCD of y and the remainder of the division x/y.

-
const gcd = (x, y) => !y ? x : gcd(y, x % y);
-// gcd (8, 36) -> 4
-
-

hammingDistance

-

Calculates the Hamming distance between two values.

-

Use XOR operator (^) to find the bit difference between the two numbers, convert to binary string using toString(2). -Count and return the number of 1s in the string, using match(/1/g).

-
const hammingDistance = (num1, num2) =>
+// factorial(6) -> 720
+

fibonacci

Generates an array, containing the Fibonacci sequence, up until the nth term.

Create an empty array of the specific length, initializing the first two values (0 and 1). Use Array.reduce() to add values into the array, using the sum of the last two values, except for the first two.

const fibonacci = n =>
+  Array(n).fill(0).reduce((acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), []);
+// fibonacci(5) -> [0,1,1,2,3]
+

gcd

Calculates the greatest common divisor between two numbers.

Use recursion. Base case is when y equals 0. In this case, return x. Otherwise, return the GCD of y and the remainder of the division x/y.

const gcd = (x, y) => !y ? x : gcd(y, x % y);
+// gcd (8, 36) -> 4
+

hammingDistance

Calculates the Hamming distance between two values.

Use XOR operator (^) to find the bit difference between the two numbers, convert to binary string using toString(2). Count and return the number of 1s in the string, using match(/1/g).

const hammingDistance = (num1, num2) =>
   ((num1 ^ num2).toString(2).match(/1/g) || '').length;
-// hammingDistance(2,3) -> 1
-
-

inRange

-

Checks if the given number falls in the given range.

-

Use arithmetic comparison to check if the given number is in the specified range. -If the second parameter, end, is not specified, the reange is considered to be from 0 to start.

-
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);
+// hammingDistance(2,3) -> 1
+

inRange

Checks if the given number falls in the given range.

Use arithmetic comparison to check if the given number is in the specified range. If the second parameter, end, is not specified, the reange is considered to be from 0 to start.

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);
 }
-// inRange(3, 2, 5) -> true
-// inRange(3, 4) -> true
-// inRange(2, 3, 5) -> false
-// inrange(3, 2) -> false
-
-

isArmstrongNumber

-

Checks if the given number is an armstrong number or not.

-

Convert the given number into array of digits. Use Math.pow() to get the appropriate power for each digit and sum them up. If the sum is equal to the number itself, return true otherwise false.

-
const isArmstrongNumber = digits => 
-  ( arr => arr.reduce( ( a, d ) => a + Math.pow( parseInt( d ), arr.length ), 0 ) == digits ? true : false )( ( digits+'' ).split( '' ) );
-// isArmstrongNumber(1634) -> true
-// isArmstrongNumber(371) -> true
-// isArmstrongNumber(56) -> false
-
-

isDivisible

-

Checks if the first numeric argument is divisible by the second one.

-

Use the modulo operator (%) to check if the remainder is equal to 0.

-
const isDivisible = (dividend, divisor) => dividend % divisor === 0;
-// isDivisible(6,3) -> true
-
-

isEven

-

Returns true if the given number is even, false otherwise.

-

Checks whether a number is odd or even using the modulo (%) operator. -Returns true if the number is even, false if the number is odd.

-
const isEven = num => num % 2 === 0;
-// isEven(3) -> false
-
-

isPrime

-

Checks if the provided integer is a prime number.

-

Returns false if the provided number has positive divisors other than 1 and itself or if the number itself is less than 2.

-
const isPrime = num => {
+// inRange(3, 2, 5) -> true
+// inRange(3, 4) -> true
+// inRange(2, 3, 5) -> false
+// inrange(3, 2) -> false
+

isArmstrongNumber

Checks if the given number is an armstrong number or not.

Convert the given number into array of digits. Use Math.pow() to get the appropriate power for each digit and sum them up. If the sum is equal to the number itself, return true otherwise false.

const isArmstrongNumber = digits => 
+  ( arr => arr.reduce( ( a, d ) => a + Math.pow( parseInt( d ), arr.length ), 0 ) == digits ? true : false )( ( digits+'' ).split( '' ) );
+// isArmstrongNumber(1634) -> true
+// isArmstrongNumber(371) -> true
+// isArmstrongNumber(56) -> false
+

isDivisible

Checks if the first numeric argument is divisible by the second one.

Use the modulo operator (%) to check if the remainder is equal to 0.

const isDivisible = (dividend, divisor) => dividend % divisor === 0;
+// isDivisible(6,3) -> true
+

isEven

Returns true if the given number is even, false otherwise.

Checks whether a number is odd or even using the modulo (%) operator. Returns true if the number is even, false if the number is odd.

const isEven = num => num % 2 === 0;
+// isEven(3) -> false
+

isPrime

Checks if the provided integer is a prime number.

Returns false if the provided number has positive divisors other than 1 and itself or if the number itself is less than 2.

const isPrime = num => {
   for (var i = 2; i < num; i++) if (num % i == 0) return false;
-  return num >= 2;
+  return num >= 2;
 }
-// isPrime(11) -> true
-// isPrime(12) -> false
-// isPrime(1) -> false
-
-

lcm

-

Returns the least common multiple of two numbers.

-

Use the greatest common divisor (GCD) formula and Math.abs() to determine the least common multiple. -The GCD formula uses recursion.

-
const lcm = (x,y) => {
-  const gcd = (x, y) => !y ? x : gcd(y, x % y);
+// isPrime(11) -> true
+// isPrime(12) -> false
+// isPrime(1) -> false
+

lcm

Returns the least common multiple of two numbers.

Use the greatest common divisor (GCD) formula and Math.abs() to determine the least common multiple. The GCD formula uses recursion.

const lcm = (x,y) => {
+  const gcd = (x, y) => !y ? x : gcd(y, x % y);
   return Math.abs(x*y)/(gcd(x,y));
 };
-// lcm(12,7) -> 84
-
-

median

-

Returns the median of an array of numbers.

-

Find the middle of the array, use Array.sort() to sort the values. -Return the number at the midpoint if length is odd, otherwise the average of the two middle numbers.

-
const median = arr => {
-  const mid = Math.floor(arr.length / 2), nums = [...arr].sort((a, b) => a - b);
+// lcm(12,7) -> 84
+

median

Returns the median of an array of numbers.

Find the middle of the array, use Array.sort() to sort the values. Return the number at the midpoint if length is odd, otherwise the average of the two middle numbers.

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;
 };
-// median([5,6,50,1,-5]) -> 5
-// median([0,10,-2,7]) -> 3.5
-
-

palindrome

-

Returns true if the given string is a palindrome, false otherwise.

-

Convert string toLowerCase() and use replace() to remove non-alphanumeric characters from it. -Then, split('') into individual characters, reverse(), join('') and compare to the original, unreversed string, after converting it tolowerCase().

-
const palindrome = str => {
+// median([5,6,50,1,-5]) -> 5
+// median([0,10,-2,7]) -> 3.5
+

palindrome

Returns true if the given string is a palindrome, false otherwise.

Convert string toLowerCase() and use replace() to remove non-alphanumeric characters from it. Then, split('') into individual characters, reverse(), join('') and compare to the original, unreversed string, after converting it tolowerCase().

const palindrome = str => {
   const s = str.toLowerCase().replace(/[\W_]/g,'');
   return s === s.split('').reverse().join('');
 }
-// palindrome('taco cat') -> true
-
-

percentile

-

Uses the percentile formula to calculate how many numbers in the given array are less or equal to the given value.

-

Use Array.reduce() to calculate how many numbers are below the value and how many are the same value and apply the percentile formula.

-
const percentile = (arr, val) =>
-  100 * arr.reduce((acc,v) => acc + (v < val ? 1 : 0) + (v === val ? 0.5 : 0), 0) / arr.length;
-// percentile([1,2,3,4,5,6,7,8,9,10], 6) -> 55
-
-

powerset

-

Returns the powerset of a given array of numbers.

-

Use Array.reduce() combined with Array.map() to iterate over elements and combine into an array containing all combinations.

-
const powerset = arr =>
-  arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]);
-// powerset([1,2]) -> [[], [1], [2], [2,1]]
-
-

randomIntegerInRange

-

Returns a random integer in the specified range.

-

Use Math.random() to generate a random number and map it to the desired range, using Math.floor() to make it an integer.

-
const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
-// randomIntegerInRange(0, 5) -> 2
-
-

randomNumberInRange

-

Returns a random number in the specified range.

-

Use Math.random() to generate a random value, map it to the desired range using multiplication.

-
const randomNumberInRange = (min, max) => Math.random() * (max - min) + min;
-// randomNumberInRange(2,10) -> 6.0211363285087005
-
-

round

-

Rounds a number to a specified amount of digits.

-

Use Math.round() and template literals to round the number to the specified number of digits. -Omit the second argument, decimals to round to an integer.

-
const round = (n, decimals=0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`);
-// round(1.005, 2) -> 1.01
-
-

standardDeviation

-

Returns the standard deviation of an array of numbers.

-

Use Array.reduce() to calculate the mean, variance and the sum of the variance of the values, the variance of the values, then -determine the standard deviation. -You can omit the second argument to get the sample standard deviation or set it to true to get the population standard deviation.

-
const standardDeviation = (arr, usePopulation = false) => {
-  const mean = arr.reduce((acc, val) => acc + val, 0) / arr.length;
+// palindrome('taco cat') -> true
+

percentile

Uses the percentile formula to calculate how many numbers in the given array are less or equal to the given value.

Use Array.reduce() to calculate how many numbers are below the value and how many are the same value and apply the percentile formula.

const percentile = (arr, val) =>
+  100 * arr.reduce((acc,v) => acc + (v < val ? 1 : 0) + (v === val ? 0.5 : 0), 0) / arr.length;
+// percentile([1,2,3,4,5,6,7,8,9,10], 6) -> 55
+

powerset

Returns the powerset of a given array of numbers.

Use Array.reduce() combined with Array.map() to iterate over elements and combine into an array containing all combinations.

const powerset = arr =>
+  arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]);
+// powerset([1,2]) -> [[], [1], [2], [2,1]]
+

randomIntegerInRange

Returns a random integer in the specified range.

Use Math.random() to generate a random number and map it to the desired range, using Math.floor() to make it an integer.

const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
+// randomIntegerInRange(0, 5) -> 2
+

randomNumberInRange

Returns a random number in the specified range.

Use Math.random() to generate a random value, map it to the desired range using multiplication.

const randomNumberInRange = (min, max) => Math.random() * (max - min) + min;
+// randomNumberInRange(2,10) -> 6.0211363285087005
+

round

Rounds a number to a specified amount of digits.

Use Math.round() and template literals to round the number to the specified number of digits. Omit the second argument, decimals to round to an integer.

const round = (n, decimals=0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`);
+// round(1.005, 2) -> 1.01
+

standardDeviation

Returns the standard deviation of an array of numbers.

Use Array.reduce() to calculate the mean, variance and the sum of the variance of the values, the variance of the values, then determine the standard deviation. You can omit the second argument to get the sample standard deviation or set it to true to get the population standard deviation.

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))
+    arr.reduce((acc, val) => acc.concat(Math.pow(val - mean, 2)), [])
+       .reduce((acc, val) => acc + val, 0) / (arr.length - (usePopulation ? 0 : 1))
   );
 };
-// standardDeviation([10,2,38,23,38,23,21]) -> 13.284434142114991 (sample)
-// standardDeviation([10,2,38,23,38,23,21], true) -> 12.29899614287479 (population)
-
-

Media

-

speechSynthesis

-

Performs speech synthesis (experimental).

-

Use SpeechSynthesisUtterance.voice and window.speechSynthesis.getVoices() to convert a message to speech. -Use window.speechSynthesis.speak() to play the message.

-

Learn more about the SpeechSynthesisUtterance interface of the Web Speech API.

-
const speechSynthesis = message => {
+// standardDeviation([10,2,38,23,38,23,21]) -> 13.284434142114991 (sample)
+// standardDeviation([10,2,38,23,38,23,21], true) -> 12.29899614287479 (population)
+

Media

speechSynthesis

Performs speech synthesis (experimental).

Use SpeechSynthesisUtterance.voice and window.speechSynthesis.getVoices() to convert a message to speech. Use window.speechSynthesis.speak() to play the message.

Learn more about the SpeechSynthesisUtterance interface of the Web Speech API.

const speechSynthesis = message => {
   const msg = new SpeechSynthesisUtterance(message);
   msg.voice = window.speechSynthesis.getVoices()[0];
   window.speechSynthesis.speak(msg);
 };
-// speechSynthesis('Hello, World') -> plays the message
-
-

Node

-

JSONToFile

-

Writes a JSON object to a file.

-

Use fs.writeFile(), template literals and JSON.stringify() to write a json object to a .json file.

-
const fs = require('fs');
-const JSONToFile = (obj, filename) => fs.writeFile(`${filename}.json`, JSON.stringify(obj, null, 2))
-// JSONToFile({test: "is passed"}, 'testJsonFile') -> writes the object to 'testJsonFile.json'
-
-

readFileLines

-

Returns an array of lines from the specified file.

-

Use readFileSync function in fs node package to create a Buffer from a file. -convert buffer to string using toString(encoding) function. -creating an array from contents of file by spliting file content line by line (each \n).

-
const fs = require('fs');
-const readFileLines = filename => fs.readFileSync(filename).toString('UTF8').split('\n');
+// speechSynthesis('Hello, World') -> plays the message
+

Node

JSONToFile

Writes a JSON object to a file.

Use fs.writeFile(), template literals and JSON.stringify() to write a json object to a .json file.

const fs = require('fs');
+const JSONToFile = (obj, filename) => fs.writeFile(`${filename}.json`, JSON.stringify(obj, null, 2))
+// JSONToFile({test: "is passed"}, 'testJsonFile') -> writes the object to 'testJsonFile.json'
+

readFileLines

Returns an array of lines from the specified file.

Use readFileSync function in fs node package to create a Buffer from a file. convert buffer to string using toString(encoding) function. creating an array from contents of file by spliting file content line by line (each \n).

const fs = require('fs');
+const readFileLines = filename => fs.readFileSync(filename).toString('UTF8').split('\n');
 /*
 contents of test.txt :
   line1
@@ -968,16 +367,10 @@ contents of test.txt :
   line3
   ___________________________
 let arr = readFileLines('test.txt')
-console.log(arr) // -> ['line1', 'line2', 'line3']
+console.log(arr) // -> ['line1', 'line2', 'line3']
 */
-
-

Object

-

cleanObj

-

Removes any properties except the ones specified from a JSON object.

-

Use Object.keys() method to loop over given json object and deleting keys that are not included in given array. -Also if you give it a special key (childIndicator) it will search deeply inside it to apply function to inner objects too.

-
const cleanObj = (obj, keysToKeep = [], childIndicator) => {
-  Object.keys(obj).forEach(key => {
+

Object

cleanObj

Removes any properties except the ones specified from a JSON object.

Use Object.keys() method to loop over given json object and deleting keys that are not included in given array. Also if you give it a special key (childIndicator) it will search deeply inside it to apply function to inner objects too.

const cleanObj = (obj, keysToKeep = [], childIndicator) => {
+  Object.keys(obj).forEach(key => {
     if (key === childIndicator) {
       cleanObj(obj[key], keysToKeep, childIndicator);
     } else if (!keysToKeep.includes(key)) {
@@ -987,32 +380,19 @@ Also if you give it a special key (childIndicator) it will search d
 }
 /*
   const testObj = {a: 1, b: 2, children: {a: 1, b: 2}}
-  cleanObj(testObj, ["a"],"children")
+  cleanObj(testObj, ["a"],"children")
   console.log(testObj)// { a: 1, children : { a: 1}}
 */
-
-

objectFromPairs

-

Creates an object from the given key-value pairs.

-

Use Array.reduce() to create and combine key-value pairs.

-
const objectFromPairs = arr => arr.reduce((a, v) => (a[v[0]] = v[1], a), {});
-// objectFromPairs([['a',1],['b',2]]) -> {a: 1, b: 2}
-
-

objectToPairs

-

Creates an array of key-value pair arrays from an object.

-

Use Object.keys() and Array.map() to iterate over the object's keys and produce an array with key-value pairs.

-
const objectToPairs = obj => Object.keys(obj).map(k => [k, obj[k]]);
-// objectToPairs({a: 1, b: 2}) -> [['a',1],['b',2]])
-
-

orderBy

-

Returns a sorted array of objects ordered by properties and orders.

-

Uses a custom implementation of sort, that reduces the props array argument with a default value of 0, it uses destructuring to swap the properties position depending on the order passed. -If no orders array is passed it sort by 'asc' by default.

-
const orderBy = (arr, props, orders) =>
-  arr.sort((a, b) =>
-    props.reduce((acc, prop, i) => {
+

objectFromPairs

Creates an object from the given key-value pairs.

Use Array.reduce() to create and combine key-value pairs.

const objectFromPairs = arr => arr.reduce((a, v) => (a[v[0]] = v[1], a), {});
+// objectFromPairs([['a',1],['b',2]]) -> {a: 1, b: 2}
+

objectToPairs

Creates an array of key-value pair arrays from an object.

Use Object.keys() and Array.map() to iterate over the object's keys and produce an array with key-value pairs.

const objectToPairs = obj => Object.keys(obj).map(k => [k, obj[k]]);
+// objectToPairs({a: 1, b: 2}) -> [['a',1],['b',2]])
+

orderBy

Returns a sorted array of objects ordered by properties and orders.

Uses a custom implementation of sort, that reduces the props array argument with a default value of 0, it uses destructuring to swap the properties position depending on the order passed. If no orders array is passed it sort by 'asc' by default.

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;
+        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)
@@ -1020,281 +400,130 @@ If no orders array is passed it sort by 'asc' by default.

/* const users = [{ 'name': 'fred', 'age': 48 },{ 'name': 'barney', 'age': 36 }, { 'name': 'fred', 'age': 40 },{ 'name': 'barney', 'age': 34 }]; -orderby(users, ['name', 'age'], ['asc', 'desc']) -> [{name: 'barney', age: 36}, {name: 'barney', age: 34}, {name: 'fred', age: 48}, {name: 'fred', age: 40}] -orderby(users, ['name', 'age']) -> [{name: 'barney', age: 34}, {name: 'barney', age: 36}, {name: 'fred', age: 40}, {name: 'fred', age: 48}] +orderby(users, ['name', 'age'], ['asc', 'desc']) -> [{name: 'barney', age: 36}, {name: 'barney', age: 34}, {name: 'fred', age: 48}, {name: 'fred', age: 40}] +orderby(users, ['name', 'age']) -> [{name: 'barney', age: 34}, {name: 'barney', age: 36}, {name: 'fred', age: 40}, {name: 'fred', age: 48}] */ -
-

select

-

Retrieve a property that indicated by the selector from object.

-

If property not exists returns undefined.

-
const select = (from, selector) =>
-  selector.split('.').reduce((prev, cur) => prev && prev[cur], from);
+

select

Retrieve a property that indicated by the selector from object.

If property not exists returns undefined.

const select = (from, selector) =>
+  selector.split('.').reduce((prev, cur) => prev && prev[cur], from);
 
 // const obj = {selector: {to: {val: 'val to select'}}};
-// select(obj, 'selector.to.val'); -> 'val to select'
-
-

shallowClone

-

Creates a shallow clone of an object.

-

Use Object.assign() and an empty object ({}) to create a shallow clone of the original.

-
const shallowClone = obj => Object.assign({}, obj);
+// select(obj, 'selector.to.val'); -> 'val to select'
+

shallowClone

Creates a shallow clone of an object.

Use Object.assign() and an empty object ({}) to create a shallow clone of the original.

const shallowClone = obj => Object.assign({}, obj);
 /*
 const a = { x: true, y: 1 };
 const b = shallowClone(a);
-a === b -> false
+a === b -> false
 */
-
-

truthCheckCollection

-

Checks if the predicate (second argument) is truthy on all elements of a collection (first argument).

-

Use Array.every() to check if each passed object has the specified property and if it returns a truthy value.

-
const truthCheckCollection = (collection, pre) => (collection.every(obj => obj[pre]));
-// truthCheckCollection([{"user": "Tinky-Winky", "sex": "male"}, {"user": "Dipsy", "sex": "male"}], "sex") -> true
-
-

String

-

anagrams

-

Generates all anagrams of a string (contains duplicates).

-

Use recursion. -For each letter in the given string, create all the partial anagrams for the rest of its letters. -Use Array.map() to combine the letter with each partial anagram, then Array.reduce() to combine all anagrams in one array. -Base cases are for string length equal to 2 or 1.

-
const anagrams = str => {
+

truthCheckCollection

Checks if the predicate (second argument) is truthy on all elements of a collection (first argument).

Use Array.every() to check if each passed object has the specified property and if it returns a truthy value.

const truthCheckCollection = (collection, pre) => (collection.every(obj => obj[pre]));
+// truthCheckCollection([{"user": "Tinky-Winky", "sex": "male"}, {"user": "Dipsy", "sex": "male"}], "sex") -> true
+

String

anagrams

Generates all anagrams of a string (contains duplicates).

Use recursion. For each letter in the given string, create all the partial anagrams for the rest of its letters. Use Array.map() to combine the letter with each partial anagram, then Array.reduce() to combine all anagrams in one array. Base cases are for string length equal to 2 or 1.

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)), []);
+  return str.split('').reduce((acc, letter, i) =>
+    acc.concat(anagrams(str.slice(0, i) + str.slice(i + 1)).map(val => letter + val)), []);
 };
-// anagrams('abc') -> ['abc','acb','bac','bca','cab','cba']
-
-

Capitalize

-

Capitalizes the first letter of a string.

-

Use destructuring and toUpperCase() to capitalize first letter, ...rest to get array of characters after first letter and then Array.join('') to make it a string again. -Omit the lowerRest parameter to keep the rest of the string intact, or set it to true to convert to lowercase.

-
const capitalize = ([first,...rest], lowerRest = false) =>
+// anagrams('abc') -> ['abc','acb','bac','bca','cab','cba']
+

Capitalize

Capitalizes the first letter of a string.

Use destructuring and toUpperCase() to capitalize first letter, ...rest to get array of characters after first letter and then Array.join('') to make it a string again. Omit the lowerRest parameter to keep the rest of the string intact, or set it to true to convert to lowercase.

const capitalize = ([first,...rest], lowerRest = false) =>
   first.toUpperCase() + (lowerRest ? rest.join('').toLowerCase() : rest.join(''));
-// capitalize('myName') -> 'MyName'
-// capitalize('myName', true) -> 'Myname'
-
-

capitalizeEveryWord

-

Capitalizes the first letter of every word in a string.

-

Use replace() to match the first character of each word and toUpperCase() to capitalize it.

-
const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase());
-// capitalizeEveryWord('hello world!') -> 'Hello World!'
-
-

countVowels

-

Retuns number of vowels in provided string.

-

Use a regular expression to count number of vowels (A, E, I, O, U) in a string.

-
const countVowels = str => (str.match(/[aeiou]/ig) || []).length;
-// countVowels('foobar') -> 3
-// countVowels('gym') -> 0
-
-

escapeRegExp

-

Escapes a string to use in a regular expression.

-

Use replace() to escape special characters.

-
const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
-// escapeRegExp('(test)') -> \\(test\\)
-
-

fromCamelCase

-

Converts a string from camelcase.

-

Use replace() to remove underscores, hyphens and spaces and convert words to camelcase. -Omit the second argument to use a default separator of _.

-
const fromCamelCase = (str, separator = '_') =>
+// capitalize('myName') -> 'MyName'
+// capitalize('myName', true) -> 'Myname'
+

capitalizeEveryWord

Capitalizes the first letter of every word in a string.

Use replace() to match the first character of each word and toUpperCase() to capitalize it.

const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase());
+// capitalizeEveryWord('hello world!') -> 'Hello World!'
+

countVowels

Retuns number of vowels in provided string.

Use a regular expression to count number of vowels (A, E, I, O, U) in a string.

const countVowels = str => (str.match(/[aeiou]/ig) || []).length;
+// countVowels('foobar') -> 3
+// countVowels('gym') -> 0
+

escapeRegExp

Escapes a string to use in a regular expression.

Use replace() to escape special characters.

const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+// escapeRegExp('(test)') -> \\(test\\)
+

fromCamelCase

Converts a string from camelcase.

Use replace() to remove underscores, hyphens and spaces and convert words to camelcase. Omit the second argument to use a default separator of _.

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();
-// fromCamelCase('someDatabaseFieldName', ' ') -> 'some database field name'
-// fromCamelCase('someLabelThatNeedsToBeCamelized', '-') -> 'some-label-that-needs-to-be-camelized'
-// fromCamelCase('someJavascriptProperty', '_') -> 'some_javascript_property'
-
-

reverseString

-

Reverses a string.

-

Use split('') and Array.reverse() to reverse the order of the characters in the string. -Combine characters to get a string using join('').

-
const reverseString = str => str.split('').reverse().join('');
-// reverseString('foobar') -> 'raboof'
-
-

sortCharactersInString

-

Alphabetically sorts the characters in a string.

-

Split the string using split(''), Array.sort() utilizing localeCompare(), recombine using join('').

-
const sortCharactersInString = str =>
-  str.split('').sort((a, b) => a.localeCompare(b)).join('');
-// sortCharactersInString('cabbage') -> 'aabbceg'
-
-

stringToArrayOfWords

-

Converts a given string into an array of words.

-

Use String.split() with a supplied pattern (defaults to non alpha as a regex) to convert to an array of strings. Use Array.filter() to remove any empty strings. -Omit the second argument to use the default regex.

-
const stringToArrayOfWords = (str, pattern = /[^a-zA-Z-]+/) => str.split(pattern).filter(Boolean);
-// stringToArrayOfWords("I love javaScript!!") -> ["I", "love", "javaScript"]
-// stringToArrayOfWords("python, javaScript & coffee") -> ["python", "javaScript", "coffee"]
-
-

toCamelCase

-

Converts a string to camelcase.

-

Use replace() to remove underscores, hyphens and spaces and convert words to camelcase.

-
const toCamelCase = str =>
-  str.replace(/^([A-Z])|[\s-_]+(\w)/g, (match, p1, p2, offset) =>  p2 ? p2.toUpperCase() : p1.toLowerCase());
-// toCamelCase("some_database_field_name") -> 'someDatabaseFieldName'
-// toCamelCase("Some label that needs to be camelized") -> 'someLabelThatNeedsToBeCamelized'
-// toCamelCase("some-javascript-property") -> 'someJavascriptProperty'
-// toCamelCase("some-mixed_string with spaces_underscores-and-hyphens") -> 'someMixedStringWithSpacesUnderscoresAndHyphens'
-
-

truncateString

-

Truncates a string up to a specified length.

-

Determine if the string's length is greater than num. -Return the string truncated to the desired length, with ... appended to the end or the original string.

-
const truncateString = (str, num) =>
-  str.length > num ? str.slice(0, num > 3 ? num - 3 : num) + '...' : str;
-// truncateString('boomerang', 7) -> 'boom...'
-
-

Utility

-

coalesce

-

Returns the first non-null/undefined argument.

-

Use Array.find() to return the first non null/undefined argument.

-
const coalesce = (...args) => args.find(_ => ![undefined, null].includes(_))
-// coalesce(null,undefined,"",NaN, "Waldo") -> ""
-
-

coalesceFactory

-

Returns a customized coalesce function that returns the first argument that returns true from the provided argument validation function.

-

Use Array.find() to return the first argument that returns true from the provided argument validation function.

-
const coalesceFactory = valid => (...args) => args.find(valid);
-// const customCoalesce = coalesceFactory(_ => ![null, undefined, "", NaN].includes(_))
-// customCoalesce(undefined, null, NaN, "", "Waldo") //-> "Waldo"
-
-

extendHex

-

Extends a 3-digit color code to a 6-digit color code.

-

Use Array.map(), split() and Array.join() to join the mapped array for converting a 3-digit RGB notated hexadecimal color-code to the 6-digit form. -Array.slice() is used to remove # from string start since it's added once.

-
const extendHex = shortHex =>
-  '#' + shortHex.slice(shortHex.startsWith('#') ? 1 : 0).split('').map(x => x+x).join('')
-// extendHex('#03f') -> '#0033ff'
-// extendHex('05a') -> '#0055aa'
-
-

getType

-

Returns the native type of a value.

-

Returns lowercased constructor name of value, "undefined" or "null" if value is undefined or null

-
const getType = v =>
+// fromCamelCase('someDatabaseFieldName', ' ') -> 'some database field name'
+// fromCamelCase('someLabelThatNeedsToBeCamelized', '-') -> 'some-label-that-needs-to-be-camelized'
+// fromCamelCase('someJavascriptProperty', '_') -> 'some_javascript_property'
+

reverseString

Reverses a string.

Use split('') and Array.reverse() to reverse the order of the characters in the string. Combine characters to get a string using join('').

const reverseString = str => str.split('').reverse().join('');
+// reverseString('foobar') -> 'raboof'
+

sortCharactersInString

Alphabetically sorts the characters in a string.

Split the string using split(''), Array.sort() utilizing localeCompare(), recombine using join('').

const sortCharactersInString = str =>
+  str.split('').sort((a, b) => a.localeCompare(b)).join('');
+// sortCharactersInString('cabbage') -> 'aabbceg'
+

stringToArrayOfWords

Converts a given string into an array of words.

Use String.split() with a supplied pattern (defaults to non alpha as a regex) to convert to an array of strings. Use Array.filter() to remove any empty strings. Omit the second argument to use the default regex.

const stringToArrayOfWords = (str, pattern = /[^a-zA-Z-]+/) => str.split(pattern).filter(Boolean);
+// stringToArrayOfWords("I love javaScript!!") -> ["I", "love", "javaScript"]
+// stringToArrayOfWords("python, javaScript & coffee") -> ["python", "javaScript", "coffee"]
+

toCamelCase

Converts a string to camelcase.

Use replace() to remove underscores, hyphens and spaces and convert words to camelcase.

const toCamelCase = str =>
+  str.replace(/^([A-Z])|[\s-_]+(\w)/g, (match, p1, p2, offset) =>  p2 ? p2.toUpperCase() : p1.toLowerCase());
+// toCamelCase("some_database_field_name") -> 'someDatabaseFieldName'
+// toCamelCase("Some label that needs to be camelized") -> 'someLabelThatNeedsToBeCamelized'
+// toCamelCase("some-javascript-property") -> 'someJavascriptProperty'
+// toCamelCase("some-mixed_string with spaces_underscores-and-hyphens") -> 'someMixedStringWithSpacesUnderscoresAndHyphens'
+

truncateString

Truncates a string up to a specified length.

Determine if the string's length is greater than num. Return the string truncated to the desired length, with ... appended to the end or the original string.

const truncateString = (str, num) =>
+  str.length > num ? str.slice(0, num > 3 ? num - 3 : num) + '...' : str;
+// truncateString('boomerang', 7) -> 'boom...'
+

Utility

coalesce

Returns the first non-null/undefined argument.

Use Array.find() to return the first non null/undefined argument.

const coalesce = (...args) => args.find(_ => ![undefined, null].includes(_))
+// coalesce(null,undefined,"",NaN, "Waldo") -> ""
+

coalesceFactory

Returns a customized coalesce function that returns the first argument that returns true from the provided argument validation function.

Use Array.find() to return the first argument that returns true from the provided argument validation function.

const coalesceFactory = valid => (...args) => args.find(valid);
+// const customCoalesce = coalesceFactory(_ => ![null, undefined, "", NaN].includes(_))
+// customCoalesce(undefined, null, NaN, "", "Waldo") //-> "Waldo"
+

extendHex

Extends a 3-digit color code to a 6-digit color code.

Use Array.map(), split() and Array.join() to join the mapped array for converting a 3-digit RGB notated hexadecimal color-code to the 6-digit form. Array.slice() is used to remove # from string start since it's added once.

const extendHex = shortHex =>
+  '#' + shortHex.slice(shortHex.startsWith('#') ? 1 : 0).split('').map(x => x+x).join('')
+// extendHex('#03f') -> '#0033ff'
+// extendHex('05a') -> '#0055aa'
+

getType

Returns the native type of a value.

Returns lowercased constructor name of value, "undefined" or "null" if value is undefined or null

const getType = v =>
   v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name.toLowerCase();
-// getType(new Set([1,2,3])) -> "set"
-
-

hexToRGB

-

Converts a color code to a rgb() or rgba() string if alpha value is provided.

-

Use bitwise right-shift operator and mask bits with & (and) operator to convert a hexadecimal color code (with or without prefixed with #) to a string with the RGB values. If it's 3-digit color code, first convert to 6-digit version. If any alpha value is provided alongside 6-digit hex, give rgba() string in return.

-
const hexToRGB = hex => {
+// getType(new Set([1,2,3])) -> "set"
+

hexToRGB

Converts a color code to a rgb() or rgba() string if alpha value is provided.

Use bitwise right-shift operator and mask bits with & (and) operator to convert a hexadecimal color code (with or without prefixed with #) to a string with the RGB values. If it's 3-digit color code, first convert to 6-digit version. If any alpha value is provided alongside 6-digit hex, give rgba() string in return.

const hexToRGB = hex => {
   let alpha = false, h = hex.slice(hex.startsWith('#') ? 1 : 0);
-  if (h.length === 3) h = [...h].map(x => x + x).join('');
+  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)}` : '') + ')';
+    + (h >>> (alpha ? 24 : 16)) + ', '
+    + ((h & (alpha ? 0x00ff0000 : 0x00ff00)) >>> (alpha ? 16 : 8)) + ', '
+    + ((h & (alpha ? 0x0000ff00 : 0x0000ff)) >>> (alpha ? 8 : 0))
+    + (alpha ? `, ${(h & 0x000000ff)}` : '') + ')';
 };
-// hexToRGB('#27ae60ff') -> 'rgba(39, 174, 96, 255)'
-// hexToRGB('27ae60') -> 'rgb(39, 174, 96)'
-// hexToRGB('#fff') -> 'rgb(255, 255, 255)'
+// hexToRGB('#27ae60ff') -> 'rgba(39, 174, 96, 255)'
+// hexToRGB('27ae60') -> 'rgb(39, 174, 96)'
+// hexToRGB('#fff') -> 'rgb(255, 255, 255)'
 
-
-

isArray

-

Checks if the given argument is an array.

-

Use Array.isArray() to check if a value is classified as an array.

-
const isArray = val => !!val && Array.isArray(val);
-// isArray(null) -> false
-// isArray([1]) -> true
-
-

isBoolean

-

Checks if the given argument is a native boolean element.

-

Use typeof to check if a value is classified as a boolean primitive.

-
const isBoolean = val => typeof val === 'boolean';
-// isBoolean(null) -> false
-// isBoolean(false) -> true
-
-

isFunction

-

Checks if the given argument is a function.

-

Use typeof to check if a value is classified as a function primitive.

-
const isFunction = val => val && typeof val === 'function';
-// isFunction('x') -> false
-// isFunction(x => x) -> true
-
-

isNumber

-

Checks if the given argument is a number.

-

Use typeof to check if a value is classified as a number primitive.

-
const isNumber = val => typeof val === 'number';
-// isNumber('1') -> false
-// isNumber(1) -> true
-
-

isString

-

Checks if the given argument is a string.

-

Use typeof to check if a value is classified as a string primitive.

-
const isString = val => typeof val === 'string';
-// isString(10) -> false
-// isString('10') -> true
-
-

isSymbol

-

Checks if the given argument is a symbol.

-

Use typeof to check if a value is classified as a symbol primitive.

-
const isSymbol = val => typeof val === 'symbol';
-// isSymbol('x') -> false
-// isSymbol(Symbol('x')) -> true
-
-

RGBToHex

-

Converts the values of RGB components to a colorcode.

-

Convert given RGB parameters to hexadecimal string using bitwise left-shift operator (<<) and toString(16), then padStart(6,'0') to get a 6-digit hexadecimal value.

-
const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0');
-// RGBToHex(255, 165, 1) -> 'ffa501'
-
-

timeTaken

-

Measures the time taken by a function to execute.

-

Use console.time() and console.timeEnd() to measure the difference between the start and end times to determine how long the callback took to execute.

-
const timeTaken = callback => {
+

isArray

Checks if the given argument is an array.

Use Array.isArray() to check if a value is classified as an array.

const isArray = val => !!val && Array.isArray(val);
+// isArray(null) -> false
+// isArray([1]) -> true
+

isBoolean

Checks if the given argument is a native boolean element.

Use typeof to check if a value is classified as a boolean primitive.

const isBoolean = val => typeof val === 'boolean';
+// isBoolean(null) -> false
+// isBoolean(false) -> true
+

isFunction

Checks if the given argument is a function.

Use typeof to check if a value is classified as a function primitive.

const isFunction = val => val && typeof val === 'function';
+// isFunction('x') -> false
+// isFunction(x => x) -> true
+

isNumber

Checks if the given argument is a number.

Use typeof to check if a value is classified as a number primitive.

const isNumber = val => typeof val === 'number';
+// isNumber('1') -> false
+// isNumber(1) -> true
+

isString

Checks if the given argument is a string.

Use typeof to check if a value is classified as a string primitive.

const isString = val => typeof val === 'string';
+// isString(10) -> false
+// isString('10') -> true
+

isSymbol

Checks if the given argument is a symbol.

Use typeof to check if a value is classified as a symbol primitive.

const isSymbol = val => typeof val === 'symbol';
+// isSymbol('x') -> false
+// isSymbol(Symbol('x')) -> true
+

RGBToHex

Converts the values of RGB components to a colorcode.

Convert given RGB parameters to hexadecimal string using bitwise left-shift operator (<<) and toString(16), then padStart(6,'0') to get a 6-digit hexadecimal value.

const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0');
+// RGBToHex(255, 165, 1) -> 'ffa501'
+

timeTaken

Measures the time taken by a function to execute.

Use console.time() and console.timeEnd() to measure the difference between the start and end times to determine how long the callback took to execute.

const timeTaken = callback => {
   console.time('timeTaken');  const r = callback();
   console.timeEnd('timeTaken');  return r;
 };
-// timeTaken(() => Math.pow(2, 10)) -> 1024
+// timeTaken(() => Math.pow(2, 10)) -> 1024
 // (logged): timeTaken: 0.02099609375ms
-
-

toOrdinalSuffix

-

Adds an ordinal suffix to a number.

-

Use the modulo operator (%) to find values of single and tens digits. -Find which ordinal pattern digits match. -If digit is found in teens pattern, use teens ordinal.

-
const toOrdinalSuffix = num => {
+

toOrdinalSuffix

Adds an ordinal suffix to a number.

Use the modulo operator (%) to find values of single and tens digits. Find which ordinal pattern digits match. If digit is found in teens pattern, use teens ordinal.

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];
+  return oPattern.includes(digits[0]) && !tPattern.includes(digits[1]) ? int + ordinals[digits[0] - 1] : int + ordinals[3];
 };
-// toOrdinalSuffix("123") -> "123rd"
-
-

UUIDGenerator

-

Generates a UUID.

-

Use crypto API to generate a UUID, compliant with RFC4122 version 4.

-
const UUIDGenerator = () =>
-  ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
-    (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
+// toOrdinalSuffix("123") -> "123rd"
+

UUIDGenerator

Generates a UUID.

Use crypto API to generate a UUID, compliant with RFC4122 version 4.

const UUIDGenerator = () =>
+  ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
+    (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
   );
-// UUIDGenerator() -> '7982fcfe-5721-4632-bede-6000885be57d'
-
-

validateEmail

-

Returns true if the given string is a valid email, false otherwise.

-

Use a regular expression to check if the email is valid. -Returns true if email is valid, false if not.

-
const validateEmail = str =>
-  /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(str);
-// validateEmail(mymail@gmail.com) -> true
-
-

validateNumber

-

Returns true if the given value is a number, false otherwise.

-

Use !isNaN in combination with parseFloat() to check if the argument is a number. -Use isFinite() to check if the number is finite. -Use Number() to check if the coercion holds.

-
const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n;
-// validateNumber('10') -> true
-
-

- -
-
- - - - +// UUIDGenerator() -> '7982fcfe-5721-4632-bede-6000885be57d' +

validateEmail

Returns true if the given string is a valid email, false otherwise.

Use a regular expression to check if the email is valid. Returns true if email is valid, false if not.

const validateEmail = str =>
+  /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(str);
+// validateEmail(mymail@gmail.com) -> true
+

validateNumber

Returns true if the given value is a number, false otherwise.

Use !isNaN in combination with parseFloat() to check if the argument is a number. Use isFinite() to check if the number is finite. Use Number() to check if the coercion holds.

const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n;
+// validateNumber('10') -> true
+

\ No newline at end of file diff --git a/package-lock.json b/package-lock.json index ca776f670..cce28f14f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -504,6 +504,13 @@ "integrity": "sha1-Nc7ornaHpJuYA09w3gDE7dOCYwE=", "requires": { "source-map": "0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } } }, "cli-boxes": { @@ -590,11 +597,6 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, - "colors": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", - "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=" - }, "combined-stream": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", @@ -698,15 +700,6 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, - "cors": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.4.tgz", - "integrity": "sha1-K9OB8usgECAQXNUOpZ2mMJBpRoY=", - "requires": { - "object-assign": "4.1.1", - "vary": "1.1.2" - } - }, "create-error-class": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", @@ -1809,11 +1802,37 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=" }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, "he": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=" }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" + }, + "hosted-git-info": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==" + }, "html-minifier": { "version": "3.5.7", "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.7.tgz", @@ -1836,32 +1855,6 @@ } } }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" - }, - "hawk": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", - "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" - } - }, - "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" - }, - "hosted-git-info": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", - "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==" - }, "http-auth": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/http-auth/-/http-auth-3.1.3.tgz", @@ -2412,6 +2405,87 @@ "proxy-middleware": "0.15.0", "send": "0.16.1", "serve-index": "1.9.1" + }, + "dependencies": { + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=" + }, + "cors": { + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.4.tgz", + "integrity": "sha1-K9OB8usgECAQXNUOpZ2mMJBpRoY=", + "requires": { + "object-assign": "4.1.1", + "vary": "1.1.2" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "event-stream": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", + "requires": { + "duplexer": "0.1.1", + "from": "0.1.7", + "map-stream": "0.1.0", + "pause-stream": "0.0.11", + "split": "0.3.3", + "stream-combiner": "0.0.4", + "through": "2.3.8" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "opn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.1.0.tgz", + "integrity": "sha512-iPNl7SyM8L30Rm1sjGdLLheyHVw5YXVfi3SKWJzBI7efxRwHojfRFjwE/OLM6qp9xJYMgab8WicTU1cPoY+Hpg==", + "requires": { + "is-wsl": "1.1.0" + } + }, + "proxy-middleware": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/proxy-middleware/-/proxy-middleware-0.15.0.tgz", + "integrity": "sha1-o/3xvvtzD5UZZYcqwvYHTGFHelY=" + }, + "send": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.1.tgz", + "integrity": "sha512-ElCLJdJIKPk6ux/Hocwhk7NFHpI3pVm/IZOYWqUmoxcgeyM+MpxHHKhb8QmlJDX1pU6WrgaHBkVNm73Sv7uc2A==", + "requires": { + "debug": "2.6.9", + "depd": "1.1.1", + "destroy": "1.0.4", + "encodeurl": "1.0.1", + "escape-html": "1.0.3", + "etag": "1.8.1", + "fresh": "0.5.2", + "http-errors": "1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "2.3.0", + "range-parser": "1.2.0", + "statuses": "1.3.1" + } + } } }, "load-json-file": { @@ -2551,10 +2625,6 @@ "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=" }, - "lower-case": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", - "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=" "loud-rejection": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", @@ -2564,6 +2634,11 @@ "signal-exit": "3.0.2" } }, + "lower-case": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", + "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=" + }, "lowercase-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", @@ -2762,6 +2837,8 @@ "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", "requires": { "lower-case": "1.1.4" + } + }, "node-gyp": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.6.2.tgz", @@ -3030,14 +3107,6 @@ "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" }, - "opn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.1.0.tgz", - "integrity": "sha512-iPNl7SyM8L30Rm1sjGdLLheyHVw5YXVfi3SKWJzBI7efxRwHojfRFjwE/OLM6qp9xJYMgab8WicTU1cPoY+Hpg==", - "requires": { - "is-wsl": "1.1.0" - } - }, "optionator": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", @@ -3285,11 +3354,6 @@ "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=" }, - "proxy-middleware": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/proxy-middleware/-/proxy-middleware-0.15.0.tgz", - "integrity": "sha1-o/3xvvtzD5UZZYcqwvYHTGFHelY=" - }, "ps-tree": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.1.0.tgz", @@ -3681,41 +3745,6 @@ "semver": "5.4.1" } }, - "send": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.16.1.tgz", - "integrity": "sha512-ElCLJdJIKPk6ux/Hocwhk7NFHpI3pVm/IZOYWqUmoxcgeyM+MpxHHKhb8QmlJDX1pU6WrgaHBkVNm73Sv7uc2A==", - "requires": { - "debug": "2.6.9", - "depd": "1.1.1", - "destroy": "1.0.4", - "encodeurl": "1.0.1", - "escape-html": "1.0.3", - "etag": "1.8.1", - "fresh": "0.5.2", - "http-errors": "1.6.2", - "mime": "1.4.1", - "ms": "2.0.0", - "on-finished": "2.3.0", - "range-parser": "1.2.0", - "statuses": "1.3.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, "serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", @@ -3793,10 +3822,6 @@ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=" }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" "sntp": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", From f8e1357cbb185fc55a96089ba5b9740008a07382 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Thu, 21 Dec 2017 12:31:47 +0200 Subject: [PATCH 38/61] Updated web script to deal with bugs --- docs/index.html | 1513 ++++++++++++++++++++++++++--------- docs/mini/flavor.scss | 4 + scripts/web-script.js | 17 +- static-parts/index-end.html | 2 +- 4 files changed, 1155 insertions(+), 381 deletions(-) diff --git a/docs/index.html b/docs/index.html index 791f0c534..2a083f30b 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,256 +1,724 @@ -30 seconds of code

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

 

Array

arrayGcd

Calculates the greatest common denominator (gcd) of an array of numbers.

Use Array.reduce() and the gcd formula (uses recursion) to calculate the greatest common denominator of an array of numbers.

const arrayGcd = arr =>{
-  const gcd = (x, y) => !y ? x : gcd(y, x % y);
-  return arr.reduce((a,b) => gcd(a,b));
+    }
+  
+  
+    
+    
+

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

+ +
+
+ +
 

Array

+

arrayGcd

+

Calculates the greatest common denominator (gcd) of an array of numbers.

+

Use Array.reduce() and the gcd formula (uses recursion) to calculate the greatest common denominator of an array of numbers.

+
const arrayGcd = arr =>{
+  const gcd = (x, y) => !y ? x : gcd(y, x % y);
+  return arr.reduce((a,b) => gcd(a,b));
 }
-// arrayGcd([1,2,3,4,5]) -> 1
-// arrayGcd([4,8,12]) -> 4
-

arrayMax

Returns the maximum value in an array.

Use Math.max() combined with the spread operator (...) to get the maximum value in the array.

const arrayMax = arr => Math.max(...arr);
-// arrayMax([10, 1, 5]) -> 10
-

arrayMin

Returns the minimum value in an array.

Use Math.min() combined with the spread operator (...) to get the minimum value in the array.

const arrayMin = arr => Math.min(...arr);
-// arrayMin([10, 1, 5]) -> 1
-

chunk

Chunks an array into smaller arrays of a specified size.

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

const chunk = (arr, size) =>
-  Array.from({length: Math.ceil(arr.length / size)}, (v, i) => arr.slice(i * size, i * size + size));
-// chunk([1,2,3,4,5], 2) -> [[1,2],[3,4],[5]]
-

compact

Removes falsey values from an array.

Use Array.filter() to filter out falsey values (false, null, 0, "", undefined, and NaN).

const compact = (arr) => arr.filter(Boolean);
-// compact([0, 1, false, 2, '', 3, 'a', 'e'*23, NaN, 's', 34]) -> [ 1, 2, 3, 'a', 's', 34 ]
-

countOccurrences

Counts the occurrences of a value in an array.

Use Array.reduce() to increment a counter each time you encounter the specific value inside the array.

const countOccurrences = (arr, value) => arr.reduce((a, v) => v === value ? a + 1 : a + 0, 0);
-// countOccurrences([1,1,2,1,2,3], 1) -> 3
-

deepFlatten

Deep flattens an array.

Use recursion. Use Array.concat() with an empty array ([]) and the spread operator (...) to flatten an array. Recursively flatten each element that is an array.

const deepFlatten = arr => [].concat(...arr.map(v => Array.isArray(v) ? deepFlatten(v) : v));
-// deepFlatten([1,[2],[[3],4],5]) -> [1,2,3,4,5]
-

difference

Returns the difference between two arrays.

Create a Set from b, then use Array.filter() on a to only keep values not contained in b.

const difference = (a, b) => { const s = new Set(b); return a.filter(x => !s.has(x)); };
-// difference([1,2,3], [1,2,4]) -> [3]
-

differenceWith

Filters out all values from an array for which the comparator function does not return true.

Use Array.filter() and Array.find() to find the appropriate values.

const differenceWith = (arr, val, comp) => arr.filter(a => !val.find(b => comp(a, b)))
-// differenceWith([1, 1.2, 1.5, 3], [1.9, 3], (a,b) => Math.round(a) == Math.round(b)) -> [1, 1.2]
-

distinctValuesOfArray

Returns all the distinct values of an array.

Use ES6 Set and the ...rest operator to discard all duplicated values.

const distinctValuesOfArray = arr => [...new Set(arr)];
-// distinctValuesOfArray([1,2,2,3,4,4,5]) -> [1,2,3,4,5]
-

dropElements

Removes elements in an array until the passed function returns true. Returns the remaining elements in the array.

Loop through the array, using Array.slice() to drop the first element of the array until the returned value from the function is true. Returns the remaining elements.

const dropElements = (arr, func) => {
-  while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1);
+// arrayGcd([1,2,3,4,5]) -> 1
+// arrayGcd([4,8,12]) -> 4
+
+

arrayMax

+

Returns the maximum value in an array.

+

Use Math.max() combined with the spread operator (...) to get the maximum value in the array.

+
const arrayMax = arr => Math.max(...arr);
+// arrayMax([10, 1, 5]) -> 10
+
+

arrayMin

+

Returns the minimum value in an array.

+

Use Math.min() combined with the spread operator (...) to get the minimum value in the array.

+
const arrayMin = arr => Math.min(...arr);
+// arrayMin([10, 1, 5]) -> 1
+
+

chunk

+

Chunks an array into smaller arrays of a specified size.

+

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

+
const chunk = (arr, size) =>
+  Array.from({length: Math.ceil(arr.length / size)}, (v, i) => arr.slice(i * size, i * size + size));
+// chunk([1,2,3,4,5], 2) -> [[1,2],[3,4],[5]]
+
+

compact

+

Removes falsey values from an array.

+

Use Array.filter() to filter out falsey values (false, null, 0, "", undefined, and NaN).

+
const compact = (arr) => arr.filter(Boolean);
+// compact([0, 1, false, 2, '', 3, 'a', 'e'*23, NaN, 's', 34]) -> [ 1, 2, 3, 'a', 's', 34 ]
+
+

countOccurrences

+

Counts the occurrences of a value in an array.

+

Use Array.reduce() to increment a counter each time you encounter the specific value inside the array.

+
const countOccurrences = (arr, value) => arr.reduce((a, v) => v === value ? a + 1 : a + 0, 0);
+// countOccurrences([1,1,2,1,2,3], 1) -> 3
+
+

deepFlatten

+

Deep flattens an array.

+

Use recursion. +Use Array.concat() with an empty array ([]) and the spread operator (...) to flatten an array. +Recursively flatten each element that is an array.

+
const deepFlatten = arr => [].concat(...arr.map(v => Array.isArray(v) ? deepFlatten(v) : v));
+// deepFlatten([1,[2],[[3],4],5]) -> [1,2,3,4,5]
+
+

difference

+

Returns the difference between two arrays.

+

Create a Set from b, then use Array.filter() on a to only keep values not contained in b.

+
const difference = (a, b) => { const s = new Set(b); return a.filter(x => !s.has(x)); };
+// difference([1,2,3], [1,2,4]) -> [3]
+
+

differenceWith

+

Filters out all values from an array for which the comparator function does not return true.

+

Use Array.filter() and Array.find() to find the appropriate values.

+
const differenceWith = (arr, val, comp) => arr.filter(a => !val.find(b => comp(a, b)))
+// differenceWith([1, 1.2, 1.5, 3], [1.9, 3], (a,b) => Math.round(a) == Math.round(b)) -> [1, 1.2]
+
+

distinctValuesOfArray

+

Returns all the distinct values of an array.

+

Use ES6 Set and the ...rest operator to discard all duplicated values.

+
const distinctValuesOfArray = arr => [...new Set(arr)];
+// distinctValuesOfArray([1,2,2,3,4,4,5]) -> [1,2,3,4,5]
+
+

dropElements

+

Removes elements in an array until the passed function returns true. Returns the remaining elements in the array.

+

Loop through the array, using Array.slice() to drop the first element of the array until the returned value from the function is true. +Returns the remaining elements.

+
const dropElements = (arr, func) => {
+  while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1);
   return arr;
 };
-// dropElements([1, 2, 3, 4], n => n >= 3) -> [3,4]
-

dropRight

Returns a new array with n elements removed from the right

Check if n is shorter than the given array and use Array.slice() to slice it accordingly or return an empty array.

const dropRight = (arr, n = 1) => n < arr.length ? arr.slice(0, arr.length - n) : []
-//dropRight([1,2,3]) -> [1,2]
-//dropRight([1,2,3], 2) -> [1]
-//dropRight([1,2,3], 42) -> []
-

everyNth

Returns every nth element in an array.

Use Array.filter() to create a new array that contains every nth element of a given array.

const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === 0);
-// everyNth([1,2,3,4,5,6], 2) -> [ 1, 3, 5 ]
-

filterNonUnique

Filters out the non-unique values in an array.

Use Array.filter() for an array containing only the unique values.

const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i));
-// filterNonUnique([1,2,2,3,4,4,5]) -> [1,3,5]
-

flatten

Flattens an array.

Use Array.reduce() to get all elements inside the array and concat() to flatten them.

const flatten = arr => arr.reduce((a, v) => a.concat(v), []);
-// flatten([1,[2],3,4]) -> [1,2,3,4]
-

flattenDepth

Flattens an array up to the specified depth.

Use recursion, decrementing depth by 1 for each level of depth. Use Array.reduce() and Array.concat() to merge elements or arrays. Base case, for depth equal to 1 stops recursion. Omit the second element, depth to flatten only to a depth of 1 (single flatten).

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), []);
-// flattenDepth([1,[2],[[[3],4],5]], 2) -> [1,2,[3],4,5]
-

groupBy

Groups the element of an array based on the given function.

Use Array.map() to map the values of an array to a function or property name. Use Array.reduce() to create an object, where the keys are produced from the mapped results.

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; }, {});
-// groupBy([6.1, 4.2, 6.3], Math.floor) -> {4: [4.2], 6: [6.1, 6.3]}
-// groupBy(['one', 'two', 'three'], 'length') -> {3: ['one', 'two'], 5: ['three']}
-

Returns the head of a list.

Use arr[0] to return the first element of the passed array.

const head = arr => arr[0];
-// head([1,2,3]) -> 1
-

initial

Returns all the elements of an array except the last one.

Use arr.slice(0,-1)to return all but the last element of the array.

const initial = arr => arr.slice(0, -1);
-// initial([1,2,3]) -> [1,2]
-

initialize2DArray

Initializes an 2D array of given width and height and value.

Use Array.map() to generate h rows where each is a new array of size w initialize with value. If value is not provided, default to null.

const initialize2DArray = (w, h, val = null) => Array(h).fill().map(() => Array(w).fill(val));
-// initializeArrayWithRange(2, 2, 0) -> [[0,0], [0,0]]
-

initializeArrayWithRange

Initializes an array containing the numbers in the specified range where start and end are inclusive.

Use Array((end + 1) - start) to create an array of the desired length, Array.map() to fill with the desired values in a range. You can omit start to use a default value of 0.

const initializeArrayWithRange = (end, start = 0) => 
-  Array.from({ length: (end + 1) - start }).map((v, i) => i + start);
-// initializeArrayWithRange(5) -> [0,1,2,3,4,5]
-// initializeArrayWithRange(7, 3) -> [3,4,5,6,7]
-

initializeArrayWithValues

Initializes and fills an array with the specified values.

Use Array(n) to create an array of the desired length, fill(v) to fill it with the desired values. You can omit value to use a default value of 0.

const initializeArrayWithValues = (n, value = 0) => Array(n).fill(value);
-// initializeArrayWithValues(5, 2) -> [2,2,2,2,2]
-

intersection

Returns a list of elements that exist in both arrays.

Create a Set from b, then use Array.filter() on a to only keep values contained in b.

const intersection = (a, b) => { const s = new Set(b); return a.filter(x => s.has(x)); };
-// intersection([1,2,3], [4,3,2]) -> [2,3]
-

last

Returns the last element in an array.

Use arr.length - 1 to compute index of the last element of the given array and returning it.

const last = arr => arr[arr.length - 1];
-// last([1,2,3]) -> 3
-

mapObject

Maps the values of an array to an object using a function, where the key-value pairs consist of the original value as the key and the mapped value.

Use an anonymous inner function scope to declare an undefined memory space, using closures to store a return value. Use a new Array to stor the array with a map of the function over its data set and a comma operator to return a second step, without needing to move from one context to another (due to closures and order of operations).

const mapObject = (arr, fn) => 
-  (a => (a = [arr, arr.map(fn)], a[0].reduce( (acc,val,ind) => (acc[val] = a[1][ind], acc), {}) )) ( );
+// dropElements([1, 2, 3, 4], n => n >= 3) -> [3,4]
+
+

dropRight

+

Returns a new array with n elements removed from the right

+

Check if n is shorter than the given array and use Array.slice() to slice it accordingly or return an empty array.

+
const dropRight = (arr, n = 1) => n < arr.length ? arr.slice(0, arr.length - n) : []
+//dropRight([1,2,3]) -> [1,2]
+//dropRight([1,2,3], 2) -> [1]
+//dropRight([1,2,3], 42) -> []
+
+

everyNth

+

Returns every nth element in an array.

+

Use Array.filter() to create a new array that contains every nth element of a given array.

+
const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === 0);
+// everyNth([1,2,3,4,5,6], 2) -> [ 1, 3, 5 ]
+
+

filterNonUnique

+

Filters out the non-unique values in an array.

+

Use Array.filter() for an array containing only the unique values.

+
const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i));
+// filterNonUnique([1,2,2,3,4,4,5]) -> [1,3,5]
+
+

flatten

+

Flattens an array.

+

Use Array.reduce() to get all elements inside the array and concat() to flatten them.

+
const flatten = arr => arr.reduce((a, v) => a.concat(v), []);
+// flatten([1,[2],3,4]) -> [1,2,3,4]
+
+

flattenDepth

+

Flattens an array up to the specified depth.

+

Use recursion, decrementing depth by 1 for each level of depth. +Use Array.reduce() and Array.concat() to merge elements or arrays. +Base case, for depth equal to 1 stops recursion. +Omit the second element, depth to flatten only to a depth of 1 (single flatten).

+
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), []);
+// flattenDepth([1,[2],[[[3],4],5]], 2) -> [1,2,[3],4,5]
+
+

groupBy

+

Groups the element of an array based on the given function.

+

Use Array.map() to map the values of an array to a function or property name. +Use Array.reduce() to create an object, where the keys are produced from the mapped results.

+
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; }, {});
+// groupBy([6.1, 4.2, 6.3], Math.floor) -> {4: [4.2], 6: [6.1, 6.3]}
+// groupBy(['one', 'two', 'three'], 'length') -> {3: ['one', 'two'], 5: ['three']}
+
+

+

Returns the head of a list.

+

Use arr[0] to return the first element of the passed array.

+
const head = arr => arr[0];
+// head([1,2,3]) -> 1
+
+

initial

+

Returns all the elements of an array except the last one.

+

Use arr.slice(0,-1)to return all but the last element of the array.

+
const initial = arr => arr.slice(0, -1);
+// initial([1,2,3]) -> [1,2]
+
+

initialize2DArray

+

Initializes an 2D array of given width and height and value.

+

Use Array.map() to generate h rows where each is a new array of size w initialize with value. If value is not provided, default to null.

+
const initialize2DArray = (w, h, val = null) => Array(h).fill().map(() => Array(w).fill(val));
+// initializeArrayWithRange(2, 2, 0) -> [[0,0], [0,0]]
+
+

initializeArrayWithRange

+

Initializes an array containing the numbers in the specified range where start and end are inclusive.

+

Use Array((end + 1) - start) to create an array of the desired length, Array.map() to fill with the desired values in a range. +You can omit start to use a default value of 0.

+
const initializeArrayWithRange = (end, start = 0) => 
+  Array.from({ length: (end + 1) - start }).map((v, i) => i + start);
+// initializeArrayWithRange(5) -> [0,1,2,3,4,5]
+// initializeArrayWithRange(7, 3) -> [3,4,5,6,7]
+
+

initializeArrayWithValues

+

Initializes and fills an array with the specified values.

+

Use Array(n) to create an array of the desired length, fill(v) to fill it with the desired values. +You can omit value to use a default value of 0.

+
const initializeArrayWithValues = (n, value = 0) => Array(n).fill(value);
+// initializeArrayWithValues(5, 2) -> [2,2,2,2,2]
+
+

intersection

+

Returns a list of elements that exist in both arrays.

+

Create a Set from b, then use Array.filter() on a to only keep values contained in b.

+
const intersection = (a, b) => { const s = new Set(b); return a.filter(x => s.has(x)); };
+// intersection([1,2,3], [4,3,2]) -> [2,3]
+
+

last

+

Returns the last element in an array.

+

Use arr.length - 1 to compute index of the last element of the given array and returning it.

+
const last = arr => arr[arr.length - 1];
+// last([1,2,3]) -> 3
+
+

mapObject

+

Maps the values of an array to an object using a function, where the key-value pairs consist of the original value as the key and the mapped value.

+

Use an anonymous inner function scope to declare an undefined memory space, using closures to store a return value. Use a new Array to stor the array with a map of the function over its data set and a comma operator to return a second step, without needing to move from one context to another (due to closures and order of operations).

+
const mapObject = (arr, fn) => 
+  (a => (a = [arr, arr.map(fn)], a[0].reduce( (acc,val,ind) => (acc[val] = a[1][ind], acc), {}) )) ( );
 /*
-const squareIt = arr => mapObject(arr, a => a*a)
+const squareIt = arr => mapObject(arr, a => a*a)
 squareIt([1,2,3]) // { 1: 1, 2: 4, 3: 9 }
 */
-

nthElement

Returns the nth element of an array.

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

const nthElement = (arr, n=0) => (n>0? arr.slice(n,n+1) : arr.slice(n))[0];
-// nthElement(['a','b','c'],1) -> 'b'
-// nthElement(['a','b','b'],-3) -> 'a'
-

pick

Picks the key-value pairs corresponding to the given keys from an object.

Use Array.reduce() to convert the filtered/picked keys back to a object with the corresponding key-value pair if the key exist in the obj.

const pick = (obj, arr) =>
-  arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {});
-// pick({ 'a': 1, 'b': '2', 'c': 3 }, ['a', 'c']) -> { 'a': 1, 'c': 3 }
-

pull

Mutates the original array to filter out the values specified.

Use Array.filter() and Array.includes() to pull out the values that are not needed. Use Array.length = 0 to mutate the passed in array by resetting it's length to zero and Array.push() to re-populate it with only the pulled values.

(For a snippet that does not mutate the original array see without)

const pull = (arr, ...args) => {
+
+

nthElement

+

Returns the nth element of an array.

+

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

+
const nthElement = (arr, n=0) => (n>0? arr.slice(n,n+1) : arr.slice(n))[0];
+// nthElement(['a','b','c'],1) -> 'b'
+// nthElement(['a','b','b'],-3) -> 'a'
+
+

pick

+

Picks the key-value pairs corresponding to the given keys from an object.

+

Use Array.reduce() to convert the filtered/picked keys back to a object with the corresponding key-value pair if the key exist in the obj.

+
const pick = (obj, arr) =>
+  arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {});
+// pick({ 'a': 1, 'b': '2', 'c': 3 }, ['a', 'c']) -> { 'a': 1, 'c': 3 }
+
+

pull

+

Mutates the original array to filter out the values specified.

+

Use Array.filter() and Array.includes() to pull out the values that are not needed. +Use Array.length = 0 to mutate the passed in array by resetting it's length to zero and Array.push() to re-populate it with only the pulled values.

+

(For a snippet that does not mutate the original array see without)

+
const pull = (arr, ...args) => {
   let argState = Array.isArray(args[0]) ? args[0] : args;
-  let pulled = arr.filter((v, i) => !argState.includes(v));
+  let pulled = arr.filter((v, i) => !argState.includes(v));
   arr.length = 0; 
-  pulled.forEach(v => arr.push(v));
+  pulled.forEach(v => arr.push(v));
 };
 
 // let myArray1 = ['a', 'b', 'c', 'a', 'b', 'c'];
 // pull(myArray1, 'a', 'c');
-// console.log(myArray1) -> [ 'b', 'b' ]
+// console.log(myArray1) -> [ 'b', 'b' ]
 
 // let myArray2 = ['a', 'b', 'c', 'a', 'b', 'c'];
 // pull(myArray2, ['a', 'c']);
-// console.log(myArray2) -> [ 'b', 'b' ]
-

pullAtIndex

Mutates the original array to filter out the values at the specified indexes.

Use Array.filter() and Array.includes() to pull out the values that are not needed. Use Array.length = 0 to mutate the passed in array by resetting it's length to zero and Array.push() to re-populate it with only the pulled values. Use Array.push() to keep track of pulled values

const pullAtIndex = (arr, pullArr) => {
+// console.log(myArray2) -> [ 'b', 'b' ]
+
+

pullAtIndex

+

Mutates the original array to filter out the values at the specified indexes.

+

Use Array.filter() and Array.includes() to pull out the values that are not needed. +Use Array.length = 0 to mutate the passed in array by resetting it's length to zero and Array.push() to re-populate it with only the pulled values. +Use Array.push() to keep track of pulled values

+
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))
+  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));
+  pulled.forEach(v => arr.push(v));
   return removed;
 }
 
 // let myArray = ['a', 'b', 'c', 'd'];
 // let pulled = pullAtIndex(myArray, [1, 3]);
 
-// console.log(myArray); -> [ 'a', 'c' ]
-// console.log(pulled); -> [ 'b', 'd' ]
-

pullAtValue

Mutates the original array to filter out the values specified. Returns the removed elements.

Use Array.filter() and Array.includes() to pull out the values that are not needed. Use Array.length = 0 to mutate the passed in array by resetting it's length to zero and Array.push() to re-populate it with only the pulled values. Use Array.push() to keep track of pulled values

const pullAtValue = (arr, pullArr) => {
+// console.log(myArray); -> [ 'a', 'c' ]
+// console.log(pulled); -> [ 'b', 'd' ]
+
+

pullAtValue

+

Mutates the original array to filter out the values specified. Returns the removed elements.

+

Use Array.filter() and Array.includes() to pull out the values that are not needed. +Use Array.length = 0 to mutate the passed in array by resetting it's length to zero and Array.push() to re-populate it with only the pulled values. +Use Array.push() to keep track of pulled values

+
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));
+    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));
+  mutateTo.forEach(v => arr.push(v));
   return removed;
 }
 /*
 let myArray = ['a', 'b', 'c', 'd'];
 let pulled = pullAtValue(myArray, ['b', 'd']);
-console.log(myArray); -> [ 'a', 'c' ]
-console.log(pulled); -> [ 'b', 'd' ]
+console.log(myArray); -> [ 'a', 'c' ]
+console.log(pulled); -> [ 'b', 'd' ]
 */
-

remove

Removes elements from an array for which the given function returns false.

Use Array.filter() to find array elements that return truthy values and Array.reduce() to remove elements using Array.splice(). The func is invoked with three arguments (value, index, array).

const remove = (arr, func) =>
-  Array.isArray(arr) ? arr.filter(func).reduce((acc, val) => {
+
+

remove

+

Removes elements from an array for which the given function returns false.

+

Use Array.filter() to find array elements that return truthy values and Array.reduce() to remove elements using Array.splice(). +The func is invoked with three arguments (value, index, array).

+
const remove = (arr, func) =>
+  Array.isArray(arr) ? arr.filter(func).reduce((acc, val) => {
     arr.splice(arr.indexOf(val), 1); return acc.concat(val);
     }, [])
   : [];
-// remove([1, 2, 3, 4], n => n % 2 == 0) -> [2, 4]
-

sample

Returns a random element from an array.

Use Math.random() to generate a random number, multiply it with length and round it of to the nearest whole number using Math.floor(). This method also works with strings.

const sample = arr => arr[Math.floor(Math.random() * arr.length)];
-// sample([3, 7, 9, 11]) -> 9
-

shuffle

Randomizes the order of the values of an array.

Use Array.sort() to reorder elements, using Math.random() in the comparator.

const shuffle = arr => arr.sort(() => Math.random() - 0.5);
-// shuffle([1,2,3]) -> [2,3,1]
-

similarity

Returns an array of elements that appear in both arrays.

Use filter() to remove values that are not part of values, determined using includes().

const similarity = (arr, values) => arr.filter(v => values.includes(v));
-// similarity([1,2,3], [1,2,4]) -> [1,2]
-

symmetricDifference

Returns the symmetric difference between two arrays.

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

const symmetricDifference = (a, b) => {
+// remove([1, 2, 3, 4], n => n % 2 == 0) -> [2, 4]
+
+

sample

+

Returns a random element from an array.

+

Use Math.random() to generate a random number, multiply it with length and round it of to the nearest whole number using Math.floor(). +This method also works with strings.

+
const sample = arr => arr[Math.floor(Math.random() * arr.length)];
+// sample([3, 7, 9, 11]) -> 9
+
+

shuffle

+

Randomizes the order of the values of an array.

+

Use Array.sort() to reorder elements, using Math.random() in the comparator.

+
const shuffle = arr => arr.sort(() => Math.random() - 0.5);
+// shuffle([1,2,3]) -> [2,3,1]
+
+

similarity

+

Returns an array of elements that appear in both arrays.

+

Use filter() to remove values that are not part of values, determined using includes().

+
const similarity = (arr, values) => arr.filter(v => values.includes(v));
+// similarity([1,2,3], [1,2,4]) -> [1,2]
+
+

symmetricDifference

+

Returns the symmetric difference between two arrays.

+

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

+
const symmetricDifference = (a, b) => {
   const sA = new Set(a), sB = new Set(b);
-  return [...a.filter(x => !sB.has(x)), ...b.filter(x => !sA.has(x))];
+  return [...a.filter(x => !sB.has(x)), ...b.filter(x => !sA.has(x))];
 }
-// symmetricDifference([1,2,3], [1,2,4]) -> [3,4]
-

tail

Returns all elements in an array except for the first one.

Return arr.slice(1) if the array's length is more than 1, otherwise return the whole array.

const tail = arr => arr.length > 1 ? arr.slice(1) : arr;
-// tail([1,2,3]) -> [2,3]
-// tail([1]) -> [1]
-

take

Returns an array with n elements removed from the beginning.

Use Array.slice() to create a slice of the array with n elements taken from the beginning.

const take = (arr, n = 1) => arr.slice(0, n);
-// take([1, 2, 3], 5) -> [1, 2, 3]
-// take([1, 2, 3], 0) -> []
-

takeRight

Returns an array with n elements removed from the end.

Use Array.slice() to create a slice of the array with n elements taken from the end.

const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length);
-// takeRight([1, 2, 3], 2) -> [ 2, 3 ]
-// takeRight([1, 2, 3]) -> [3]
-

union

Returns every element that exists in any of the two arrays once.

Create a Set with all values of a and b and convert to an array.

const union = (a, b) => Array.from(new Set([...a, ...b]));
-// union([1,2,3], [4,3,2]) -> [1,2,3,4]
-

without

Filters out the elements of an array, that have one of the specified values.

Use Array.filter() to create an array excluding(using !Array.includes()) all given values.

(For a snippet that mutates the original array see pull)

const without = (arr, ...args) => arr.filter(v => !args.includes(v));
-// without([2, 1, 2, 3], 1, 2) -> [3]
-

zip

Creates an array of elements, grouped based on the position in the original arrays.

Use Math.max.apply() to get the longest array in the arguments. Creates an array with that length as return value and use Array.from() with a map-function to create an array of grouped elements. If lengths of the argument-arrays vary, undefined is used where no value could be found.

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]);
+// symmetricDifference([1,2,3], [1,2,4]) -> [3,4]
+
+

tail

+

Returns all elements in an array except for the first one.

+

Return arr.slice(1) if the array's length is more than 1, otherwise return the whole array.

+
const tail = arr => arr.length > 1 ? arr.slice(1) : arr;
+// tail([1,2,3]) -> [2,3]
+// tail([1]) -> [1]
+
+

take

+

Returns an array with n elements removed from the beginning.

+

Use Array.slice() to create a slice of the array with n elements taken from the beginning.

+
const take = (arr, n = 1) => arr.slice(0, n);
+// take([1, 2, 3], 5) -> [1, 2, 3]
+// take([1, 2, 3], 0) -> []
+
+

takeRight

+

Returns an array with n elements removed from the end.

+

Use Array.slice() to create a slice of the array with n elements taken from the end.

+
const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length);
+// takeRight([1, 2, 3], 2) -> [ 2, 3 ]
+// takeRight([1, 2, 3]) -> [3]
+
+

union

+

Returns every element that exists in any of the two arrays once.

+

Create a Set with all values of a and b and convert to an array.

+
const union = (a, b) => Array.from(new Set([...a, ...b]));
+// union([1,2,3], [4,3,2]) -> [1,2,3,4]
+
+

without

+

Filters out the elements of an array, that have one of the specified values.

+

Use Array.filter() to create an array excluding(using !Array.includes()) all given values.

+

(For a snippet that mutates the original array see pull)

+
const without = (arr, ...args) => arr.filter(v => !args.includes(v));
+// without([2, 1, 2, 3], 1, 2) -> [3]
+
+

zip

+

Creates an array of elements, grouped based on the position in the original arrays.

+

Use Math.max.apply() to get the longest array in the arguments. +Creates an array with that length as return value and use Array.from() with a map-function to create an array of grouped elements. +If lengths of the argument-arrays vary, undefined is used where no value could be found.

+
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]);
   })
 }
-//zip(['a', 'b'], [1, 2], [true, false]); -> [['a', 1, true], ['b', 2, false]]
-//zip(['a'], [1, 2], [true, false]); -> [['a', 1, true], [undefined, 2, false]]
-

zipObject

Given an array of valid property identifiers and an array of values, return an object associating the properties to the values.

Since an object can have undefined values but not undefined property pointers, the array of properties is used to decide the structure of the resulting object using Array.reduce().

const zipObject = ( props, values ) => props.reduce( ( obj, prop, index ) => ( obj[prop] = values[index], obj ), {} )
-// zipObject(['a','b','c'], [1,2]) -> {a: 1, b: 2, c: undefined}
-// zipObject(['a','b'], [1,2,3]) -> {a: 1, b: 2}
-

Browser

arrayToHtmlList

Converts the given array elements into <li> tags and appends them to the list of the given id.

Use Array.map() and document.querySelector() to create a list of html tags.

const arrayToHtmlList = (arr, listID) => arr.map(item => document.querySelector("#"+listID).innerHTML+=`<li>${item}</li>`);
+//zip(['a', 'b'], [1, 2], [true, false]); -> [['a', 1, true], ['b', 2, false]]
+//zip(['a'], [1, 2], [true, false]); -> [['a', 1, true], [undefined, 2, false]]
+
+

zipObject

+

Given an array of valid property identifiers and an array of values, return an object associating the properties to the values.

+

Since an object can have undefined values but not undefined property pointers, the array of properties is used to decide the structure of the resulting object using Array.reduce().

+
const zipObject = ( props, values ) => props.reduce( ( obj, prop, index ) => ( obj[prop] = values[index], obj ), {} )
+// zipObject(['a','b','c'], [1,2]) -> {a: 1, b: 2, c: undefined}
+// zipObject(['a','b'], [1,2,3]) -> {a: 1, b: 2}
+
+

Browser

+

arrayToHtmlList

+

Converts the given array elements into <li> tags and appends them to the list of the given id.

+

Use Array.map() and document.querySelector() to create a list of html tags.

+
const arrayToHtmlList = (arr, listID) => arr.map(item => document.querySelector("#"+listID).innerHTML+=`<li>${item}</li>`);
 // arrayToHtmlList(['item 1', 'item 2'],'myListID')
-

bottomVisible

Returns true if the bottom of the page is visible, false otherwise.

Use scrollY, scrollHeight and clientHeight to determine if the bottom of the page is visible.

const bottomVisible = () =>
-  document.documentElement.clientHeight + window.scrollY >= (document.documentElement.scrollHeight || document.documentElement.clientHeight);
-// bottomVisible() -> true
-

currentURL

Returns the current URL.

Use window.location.href to get current URL.

const currentURL = () => window.location.href;
-// currentUrl() -> 'https://google.com'
-

elementIsVisibleInViewport

Returns true if the element specified is visible in the viewport, false otherwise.

Use Element.getBoundingClientRect() and the window.inner(Width|Height) values to determine if a given element is visible in the viewport. Omit the second argument to determine if the element is entirely visible, or specify true to determine if it is partially visible.

const elementIsVisibleInViewport = (el, partiallyVisible = false) => {
+
+

bottomVisible

+

Returns true if the bottom of the page is visible, false otherwise.

+

Use scrollY, scrollHeight and clientHeight to determine if the bottom of the page is visible.

+
const bottomVisible = () =>
+  document.documentElement.clientHeight + window.scrollY >= (document.documentElement.scrollHeight || document.documentElement.clientHeight);
+// bottomVisible() -> true
+
+

currentURL

+

Returns the current URL.

+

Use window.location.href to get current URL.

+
const currentURL = () => window.location.href;
+// currentUrl() -> 'https://google.com'
+
+

elementIsVisibleInViewport

+

Returns true if the element specified is visible in the viewport, false otherwise.

+

Use Element.getBoundingClientRect() and the window.inner(Width|Height) values +to determine if a given element is visible in the viewport. +Omit the second argument to determine if the element is entirely visible, or specify true to determine if +it is partially visible.

+
const elementIsVisibleInViewport = (el, partiallyVisible = false) => {
   const { top, left, bottom, right } = el.getBoundingClientRect();
   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;
+    ? ((top > 0 && top < innerHeight) || (bottom > 0 && bottom < innerHeight)) &&
+      ((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth))
+    : top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth;
 };
 // e.g. 100x100 viewport and a 10x10px element at position {top: -1, left: 0, bottom: 9, right: 10}
-// elementIsVisibleInViewport(el) -> false (not fully visible)
-// elementIsVisibleInViewport(el, true) -> true (partially visible)
-

getScrollPosition

Returns the scroll position of the current page.

Use pageXOffset and pageYOffset if they are defined, otherwise scrollLeft and scrollTop. You can omit el to use a default value of window.

const getScrollPosition = (el = window) =>
+// elementIsVisibleInViewport(el) -> false (not fully visible)
+// elementIsVisibleInViewport(el, true) -> true (partially visible)
+
+

getScrollPosition

+

Returns the scroll position of the current page.

+

Use pageXOffset and pageYOffset if they are defined, otherwise scrollLeft and scrollTop. +You can omit el to use a default value of window.

+
const getScrollPosition = (el = window) =>
   ({x: (el.pageXOffset !== undefined) ? el.pageXOffset : el.scrollLeft,
     y: (el.pageYOffset !== undefined) ? el.pageYOffset : el.scrollTop});
-// getScrollPosition() -> {x: 0, y: 200}
-

getURLParameters

Returns an object containing the parameters of the current URL.

Use match() with an appropriate regular expression to get all key-value pairs, Array.reduce() to map and combine them into a single object. Pass location.search as the argument to apply to the current url.

const getURLParameters = url =>
-  url.match(/([^?=&]+)(=([^&]*))/g).reduce(
-    (a, v) => (a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1), a), {}
+// getScrollPosition() -> {x: 0, y: 200}
+
+

getURLParameters

+

Returns an object containing the parameters of the current URL.

+

Use match() with an appropriate regular expression to get all key-value pairs, Array.reduce() to map and combine them into a single object. +Pass location.search as the argument to apply to the current url.

+
const getURLParameters = url =>
+  url.match(/([^?=&]+)(=([^&]*))/g).reduce(
+    (a, v) => (a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1), a), {}
   );
-// getURLParameters('http://url.com/page?name=Adam&surname=Smith') -> {name: 'Adam', surname: 'Smith'}
-

redirect

Redirects to a specified URL.

Use window.location.href or window.location.replace() to redirect to url. Pass a second argument to simulate a link click (true - default) or an HTTP redirect (false).

const redirect = (url, asLink = true) =>
+// getURLParameters('http://url.com/page?name=Adam&surname=Smith') -> {name: 'Adam', surname: 'Smith'}
+
+

redirect

+

Redirects to a specified URL.

+

Use window.location.href or window.location.replace() to redirect to url. +Pass a second argument to simulate a link click (true - default) or an HTTP redirect (false).

+
const redirect = (url, asLink = true) =>
   asLink ? window.location.href = url : window.location.replace(url);
 // redirect('https://google.com')
-

scrollToTop

Smooth-scrolls to the top of the page.

Get distance from top using document.documentElement.scrollTop or document.body.scrollTop. Scroll by a fraction of the distance from top. Use window.requestAnimationFrame() to animate the scrolling.

const scrollToTop = () => {
+
+

scrollToTop

+

Smooth-scrolls to the top of the page.

+

Get distance from top using document.documentElement.scrollTop or document.body.scrollTop. +Scroll by a fraction of the distance from top. Use window.requestAnimationFrame() to animate the scrolling.

+
const scrollToTop = () => {
   const c = document.documentElement.scrollTop || document.body.scrollTop;
-  if (c > 0) {
+  if (c > 0) {
     window.requestAnimationFrame(scrollToTop);
     window.scrollTo(0, c - c / 8);
   }
 };
 // scrollToTop()
-

Date

getDaysDiffBetweenDates

Returns the difference (in days) between two dates.

Calculate the difference (in days) between to Date objects.

const getDaysDiffBetweenDates = (dateInitial, dateFinal) => (dateFinal - dateInitial) / (1000 * 3600 * 24);
-// getDaysDiffBetweenDates(new Date("2017-12-13"), new Date("2017-12-22")) -> 9
-

JSONToDate

Converts a JSON object to a date.

Use Date(), to convert dates in JSON format to readable format (dd/mm/yyyy).

const JSONToDate = arr => {
+
+

Date

+

getDaysDiffBetweenDates

+

Returns the difference (in days) between two dates.

+

Calculate the difference (in days) between to Date objects.

+
const getDaysDiffBetweenDates = (dateInitial, dateFinal) => (dateFinal - dateInitial) / (1000 * 3600 * 24);
+// getDaysDiffBetweenDates(new Date("2017-12-13"), new Date("2017-12-22")) -> 9
+
+

JSONToDate

+

Converts a JSON object to a date.

+

Use Date(), to convert dates in JSON format to readable format (dd/mm/yyyy).

+
const JSONToDate = arr => {
   const dt = new Date(parseInt(arr.toString().substr(6)));
   return `${ dt.getDate() }/${ dt.getMonth() + 1 }/${ dt.getFullYear() }`
 };
-// JSONToDate(/Date(1489525200000)/) -> "14/3/2017"
-

toEnglishDate

Converts a date from American format to English format.

Use Date.toISOString(), split('T') and replace() to convert a date from American format to English format. Throws an error if the passed time cannot be converted to a date.

const toEnglishDate  = (time) =>
+// JSONToDate(/Date(1489525200000)/) -> "14/3/2017"
+
+

toEnglishDate

+

Converts a date from American format to English format.

+

Use Date.toISOString(), split('T') and replace() to convert a date from American format to English format. +Throws an error if the passed time cannot be converted to a date.

+
const toEnglishDate  = (time) =>
   {try{return new Date(time).toISOString().split('T')[0].replace(/-/g, '/')}catch(e){return}};
-// toEnglishDate('09/21/2010') -> '21/09/2010'
-

Function

chainAsync

Chains asynchronous functions.

Loop through an array of functions containing asynchronous events, calling next when each asynchronous event has completed.

const chainAsync = fns => { let curr = 0; const next = () => fns[curr++](next); next(); };
+// toEnglishDate('09/21/2010') -> '21/09/2010'
+
+

Function

+

chainAsync

+

Chains asynchronous functions.

+

Loop through an array of functions containing asynchronous events, calling next when each asynchronous event has completed.

+
const chainAsync = fns => { let curr = 0; const next = () => fns[curr++](next); next(); };
 /*
 chainAsync([
-  next => { console.log('0 seconds'); setTimeout(next, 1000); },
-  next => { console.log('1 second');  setTimeout(next, 1000); },
-  next => { console.log('2 seconds'); }
+  next => { console.log('0 seconds'); setTimeout(next, 1000); },
+  next => { console.log('1 second');  setTimeout(next, 1000); },
+  next => { console.log('2 seconds'); }
 ])
 */
-

compose

Performs right-to-left function composition.

Use Array.reduce() to perform right-to-left function composition. The last (rightmost) function can accept one or more arguments; the remaining functions must be unary.

const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)));
+
+

compose

+

Performs right-to-left function composition.

+

Use Array.reduce() to perform right-to-left function composition. +The last (rightmost) function can accept one or more arguments; the remaining functions must be unary.

+
const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)));
 /*
-const add5 = x => x + 5
-const multiply = (x, y) => x * y
+const add5 = x => x + 5
+const multiply = (x, y) => x * y
 const multiplyAndAdd5 = compose(add5, multiply)
-multiplyAndAdd5(5, 2) -> 15
+multiplyAndAdd5(5, 2) -> 15
 */
-

curry

Curries a function.

Use recursion. If the number of provided arguments (args) is sufficient, call the passed function f. Otherwise return a curried function f that expects the rest of the arguments. If you want to curry a function that accepts a variable number of arguments (a variadic function, e.g. Math.min()), you can optionally pass the number of arguments to the second parameter arity.

const curry = (fn, arity = fn.length, ...args) =>
+
+

curry

+

Curries a function.

+

Use recursion. +If the number of provided arguments (args) is sufficient, call the passed function f. +Otherwise return a curried function f that expects the rest of the arguments. +If you want to curry a function that accepts a variable number of arguments (a variadic function, e.g. Math.min()), you can optionally pass the number of arguments to the second parameter arity.

+
const curry = (fn, arity = fn.length, ...args) =>
   arity <= args.length
     ? fn(...args)
     : curry.bind(null, fn, arity, ...args);
-// curry(Math.pow)(2)(10) -> 1024
-// curry(Math.min, 3)(10)(50)(2) -> 2
-

functionName

Logs the name of a function.

Use console.debug() and the name property of the passed method to log the method's name to the debug channel of the console.

const functionName = fn => (console.debug(fn.name), fn);
-// functionName(Math.max) -> max (logged in debug channel of console)
-

pipe

Performs left-to-right function composition.

Use Array.reduce() with the spread operator (...) to perform left-to-right function composition. The first (leftmost) function can accept one or more arguments; the remaining functions must be unary.

const pipeFunctions = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args)));
+// curry(Math.pow)(2)(10) -> 1024
+// curry(Math.min, 3)(10)(50)(2) -> 2
+
+

functionName

+

Logs the name of a function.

+

Use console.debug() and the name property of the passed method to log the method's name to the debug channel of the console.

+
const functionName = fn => (console.debug(fn.name), fn);
+// functionName(Math.max) -> max (logged in debug channel of console)
+
+

pipe

+

Performs left-to-right function composition.

+

Use Array.reduce() with the spread operator (...) to perform left-to-right function composition. +The first (leftmost) function can accept one or more arguments; the remaining functions must be unary.

+
const pipeFunctions = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args)));
 /*
-const add5 = x => x + 5
-const multiply = (x, y) => x * y
+const add5 = x => x + 5
+const multiply = (x, y) => x * y
 const multiplyAndAdd5 = pipeFunctions(multiply, add5)
-multiplyAndAdd5(5, 2) -> 15
+multiplyAndAdd5(5, 2) -> 15
 */
-

promisify

Converts an asynchronous function to return a promise.

Use currying to return a function returning a Promise that calls the original function. Use the ...rest operator to pass in all the parameters.

In Node 8+, you can use util.promisify

const promisify = func =>
-  (...args) =>
-    new Promise((resolve, reject) =>
-      func(...args, (err, result) =>
+
+

promisify

+

Converts an asynchronous function to return a promise.

+

Use currying to return a function returning a Promise that calls the original function. +Use the ...rest operator to pass in all the parameters.

+

In Node 8+, you can use util.promisify

+
const promisify = func =>
+  (...args) =>
+    new Promise((resolve, reject) =>
+      func(...args, (err, result) =>
         err ? reject(err) : resolve(result))
     );
-// const delay = promisify((d, cb) => setTimeout(cb, d))
-// delay(2000).then(() => console.log('Hi!')) -> Promise resolves after 2s
-

runPromisesInSeries

Runs an array of promises in series.

Use Array.reduce() to create a promise chain, where each promise returns the next promise when resolved.

const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve());
-// const delay = (d) => new Promise(r => setTimeout(r, d))
-// runPromisesInSeries([() => delay(1000), () => delay(2000)]) -> executes each promise sequentially, taking a total of 3 seconds to complete
-

sleep

Delays the execution of an asynchronous function.

Delay executing part of an async function, by putting it to sleep, returning a Promise.

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
+// const delay = promisify((d, cb) => setTimeout(cb, d))
+// delay(2000).then(() => console.log('Hi!')) -> Promise resolves after 2s
+
+

runPromisesInSeries

+

Runs an array of promises in series.

+

Use Array.reduce() to create a promise chain, where each promise returns the next promise when resolved.

+
const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve());
+// const delay = (d) => new Promise(r => setTimeout(r, d))
+// runPromisesInSeries([() => delay(1000), () => delay(2000)]) -> executes each promise sequentially, taking a total of 3 seconds to complete
+
+

sleep

+

Delays the execution of an asynchronous function.

+

Delay executing part of an async function, by putting it to sleep, returning a Promise.

+
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
 /*
 async function sleepyWork() {
   console.log('I\'m going to sleep for 1 second.');
@@ -258,108 +726,241 @@ async function sleepyWork() {
   console.log('I woke up after 1 second.');
 }
 */
-

Math

arrayAverage

Returns the average of an array of numbers.

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

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

arraySum

Returns the sum of an array of numbers.

Use Array.reduce() to add each value to an accumulator, initialized with a value of 0.

const arraySum = arr => arr.reduce((acc, val) => acc + val, 0);
-// arraySum([1,2,3,4]) -> 10
-

clampNumber

Clamps num within the inclusive lower and upper bounds.

If lower is greater than upper, swap them. If num falls within the range, return num. Otherwise return the nearest number in the range.

const clampNumber = (num, lower, upper) => {
-  if(lower > upper) upper = [lower, lower = upper][0];
-  return (num>=lower && num<=upper) ? num : ((num < lower) ? lower : upper) 
+
+

Math

+

arrayAverage

+

Returns the average of an array of numbers.

+

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

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

arraySum

+

Returns the sum of an array of numbers.

+

Use Array.reduce() to add each value to an accumulator, initialized with a value of 0.

+
const arraySum = arr => arr.reduce((acc, val) => acc + val, 0);
+// arraySum([1,2,3,4]) -> 10
+
+

clampNumber

+

Clamps num within the inclusive lower and upper bounds.

+

If lower is greater than upper, swap them. +If num falls within the range, return num. +Otherwise return the nearest number in the range.

+
const clampNumber = (num, lower, upper) => {
+  if(lower > upper) upper = [lower, lower = upper][0];
+  return (num>=lower && num<=upper) ? num : ((num < lower) ? lower : upper) 
 }
-// clampNumber(2, 3, 5) -> 3
-// clampNumber(1, -1, -5) -> -1
-// clampNumber(3, 2, 4) -> 3
-

collatz

Applies the Collatz algorithm.

If n is even, return n/2. Otherwise return 3n+1.

const collatz = n => (n % 2 == 0) ? (n / 2) : (3 * n + 1);
-// collatz(8) --> 4
-// collatz(5) --> 16
-

digitize

Converts a number to an array of digits.

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

const digitize = n => [...''+n].map(i => parseInt(i));
-// digitize(2334) -> [2, 3, 3, 4]
-

distance

Returns the distance between two points.

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

const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0);
-// distance(1,1, 2,3) -> 2.23606797749979
-

factorial

Calculates the factorial of a number.

Use recursion. If n is less than or equal to 1, return 1. Otherwise, return the product of n and the factorial of n - 1. Throws an exception if n is a negative number.

const factorial = n =>
-  n < 0 ? (() => { throw new TypeError('Negative numbers are not allowed!') })()
+// clampNumber(2, 3, 5) -> 3
+// clampNumber(1, -1, -5) -> -1
+// clampNumber(3, 2, 4) -> 3
+
+

collatz

+

Applies the Collatz algorithm.

+

If n is even, return n/2. Otherwise return 3n+1.

+
const collatz = n => (n % 2 == 0) ? (n / 2) : (3 * n + 1);
+// collatz(8) --> 4
+// collatz(5) --> 16
+
+

digitize

+

Converts a number to an array of digits.

+

Convert the number to a string, using spread operators in ES6([...string]) build an array. +Use Array.map() and parseInt() to transform each value to an integer.

+
const digitize = n => [...''+n].map(i => parseInt(i));
+// digitize(2334) -> [2, 3, 3, 4]
+
+

distance

+

Returns the distance between two points.

+

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

+
const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0);
+// distance(1,1, 2,3) -> 2.23606797749979
+
+

factorial

+

Calculates the factorial of a number.

+

Use recursion. +If n is less than or equal to 1, return 1. +Otherwise, return the product of n and the factorial of n - 1. +Throws an exception if n is a negative number.

+
const factorial = n =>
+  n < 0 ? (() => { throw new TypeError('Negative numbers are not allowed!') })()
   : n <= 1 ? 1 : n * factorial(n - 1);
-// factorial(6) -> 720
-

fibonacci

Generates an array, containing the Fibonacci sequence, up until the nth term.

Create an empty array of the specific length, initializing the first two values (0 and 1). Use Array.reduce() to add values into the array, using the sum of the last two values, except for the first two.

const fibonacci = n =>
-  Array(n).fill(0).reduce((acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), []);
-// fibonacci(5) -> [0,1,1,2,3]
-

gcd

Calculates the greatest common divisor between two numbers.

Use recursion. Base case is when y equals 0. In this case, return x. Otherwise, return the GCD of y and the remainder of the division x/y.

const gcd = (x, y) => !y ? x : gcd(y, x % y);
-// gcd (8, 36) -> 4
-

hammingDistance

Calculates the Hamming distance between two values.

Use XOR operator (^) to find the bit difference between the two numbers, convert to binary string using toString(2). Count and return the number of 1s in the string, using match(/1/g).

const hammingDistance = (num1, num2) =>
+// factorial(6) -> 720
+
+

fibonacci

+

Generates an array, containing the Fibonacci sequence, up until the nth term.

+

Create an empty array of the specific length, initializing the first two values (0 and 1). +Use Array.reduce() to add values into the array, using the sum of the last two values, except for the first two.

+
const fibonacci = n =>
+  Array(n).fill(0).reduce((acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), []);
+// fibonacci(5) -> [0,1,1,2,3]
+
+

gcd

+

Calculates the greatest common divisor between two numbers.

+

Use recursion. +Base case is when y equals 0. In this case, return x. +Otherwise, return the GCD of y and the remainder of the division x/y.

+
const gcd = (x, y) => !y ? x : gcd(y, x % y);
+// gcd (8, 36) -> 4
+
+

hammingDistance

+

Calculates the Hamming distance between two values.

+

Use XOR operator (^) to find the bit difference between the two numbers, convert to binary string using toString(2). +Count and return the number of 1s in the string, using match(/1/g).

+
const hammingDistance = (num1, num2) =>
   ((num1 ^ num2).toString(2).match(/1/g) || '').length;
-// hammingDistance(2,3) -> 1
-

inRange

Checks if the given number falls in the given range.

Use arithmetic comparison to check if the given number is in the specified range. If the second parameter, end, is not specified, the reange is considered to be from 0 to start.

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);
+// hammingDistance(2,3) -> 1
+
+

inRange

+

Checks if the given number falls in the given range.

+

Use arithmetic comparison to check if the given number is in the specified range. +If the second parameter, end, is not specified, the reange is considered to be from 0 to start.

+
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);
 }
-// inRange(3, 2, 5) -> true
-// inRange(3, 4) -> true
-// inRange(2, 3, 5) -> false
-// inrange(3, 2) -> false
-

isArmstrongNumber

Checks if the given number is an armstrong number or not.

Convert the given number into array of digits. Use Math.pow() to get the appropriate power for each digit and sum them up. If the sum is equal to the number itself, return true otherwise false.

const isArmstrongNumber = digits => 
-  ( arr => arr.reduce( ( a, d ) => a + Math.pow( parseInt( d ), arr.length ), 0 ) == digits ? true : false )( ( digits+'' ).split( '' ) );
-// isArmstrongNumber(1634) -> true
-// isArmstrongNumber(371) -> true
-// isArmstrongNumber(56) -> false
-

isDivisible

Checks if the first numeric argument is divisible by the second one.

Use the modulo operator (%) to check if the remainder is equal to 0.

const isDivisible = (dividend, divisor) => dividend % divisor === 0;
-// isDivisible(6,3) -> true
-

isEven

Returns true if the given number is even, false otherwise.

Checks whether a number is odd or even using the modulo (%) operator. Returns true if the number is even, false if the number is odd.

const isEven = num => num % 2 === 0;
-// isEven(3) -> false
-

isPrime

Checks if the provided integer is a prime number.

Returns false if the provided number has positive divisors other than 1 and itself or if the number itself is less than 2.

const isPrime = num => {
+// inRange(3, 2, 5) -> true
+// inRange(3, 4) -> true
+// inRange(2, 3, 5) -> false
+// inrange(3, 2) -> false
+
+

isArmstrongNumber

+

Checks if the given number is an armstrong number or not.

+

Convert the given number into array of digits. Use Math.pow() to get the appropriate power for each digit and sum them up. If the sum is equal to the number itself, return true otherwise false.

+
const isArmstrongNumber = digits => 
+  ( arr => arr.reduce( ( a, d ) => a + Math.pow( parseInt( d ), arr.length ), 0 ) == digits ? true : false )( ( digits+'' ).split( '' ) );
+// isArmstrongNumber(1634) -> true
+// isArmstrongNumber(371) -> true
+// isArmstrongNumber(56) -> false
+
+

isDivisible

+

Checks if the first numeric argument is divisible by the second one.

+

Use the modulo operator (%) to check if the remainder is equal to 0.

+
const isDivisible = (dividend, divisor) => dividend % divisor === 0;
+// isDivisible(6,3) -> true
+
+

isEven

+

Returns true if the given number is even, false otherwise.

+

Checks whether a number is odd or even using the modulo (%) operator. +Returns true if the number is even, false if the number is odd.

+
const isEven = num => num % 2 === 0;
+// isEven(3) -> false
+
+

isPrime

+

Checks if the provided integer is a prime number.

+

Returns false if the provided number has positive divisors other than 1 and itself or if the number itself is less than 2.

+
const isPrime = num => {
   for (var i = 2; i < num; i++) if (num % i == 0) return false;
-  return num >= 2;
+  return num >= 2;
 }
-// isPrime(11) -> true
-// isPrime(12) -> false
-// isPrime(1) -> false
-

lcm

Returns the least common multiple of two numbers.

Use the greatest common divisor (GCD) formula and Math.abs() to determine the least common multiple. The GCD formula uses recursion.

const lcm = (x,y) => {
-  const gcd = (x, y) => !y ? x : gcd(y, x % y);
+// isPrime(11) -> true
+// isPrime(12) -> false
+// isPrime(1) -> false
+
+

lcm

+

Returns the least common multiple of two numbers.

+

Use the greatest common divisor (GCD) formula and Math.abs() to determine the least common multiple. +The GCD formula uses recursion.

+
const lcm = (x,y) => {
+  const gcd = (x, y) => !y ? x : gcd(y, x % y);
   return Math.abs(x*y)/(gcd(x,y));
 };
-// lcm(12,7) -> 84
-

median

Returns the median of an array of numbers.

Find the middle of the array, use Array.sort() to sort the values. Return the number at the midpoint if length is odd, otherwise the average of the two middle numbers.

const median = arr => {
-  const mid = Math.floor(arr.length / 2), nums = [...arr].sort((a, b) => a - b);
+// lcm(12,7) -> 84
+
+

median

+

Returns the median of an array of numbers.

+

Find the middle of the array, use Array.sort() to sort the values. +Return the number at the midpoint if length is odd, otherwise the average of the two middle numbers.

+
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;
 };
-// median([5,6,50,1,-5]) -> 5
-// median([0,10,-2,7]) -> 3.5
-

palindrome

Returns true if the given string is a palindrome, false otherwise.

Convert string toLowerCase() and use replace() to remove non-alphanumeric characters from it. Then, split('') into individual characters, reverse(), join('') and compare to the original, unreversed string, after converting it tolowerCase().

const palindrome = str => {
+// median([5,6,50,1,-5]) -> 5
+// median([0,10,-2,7]) -> 3.5
+
+

palindrome

+

Returns true if the given string is a palindrome, false otherwise.

+

Convert string toLowerCase() and use replace() to remove non-alphanumeric characters from it. +Then, split('') into individual characters, reverse(), join('') and compare to the original, unreversed string, after converting it tolowerCase().

+
const palindrome = str => {
   const s = str.toLowerCase().replace(/[\W_]/g,'');
   return s === s.split('').reverse().join('');
 }
-// palindrome('taco cat') -> true
-

percentile

Uses the percentile formula to calculate how many numbers in the given array are less or equal to the given value.

Use Array.reduce() to calculate how many numbers are below the value and how many are the same value and apply the percentile formula.

const percentile = (arr, val) =>
-  100 * arr.reduce((acc,v) => acc + (v < val ? 1 : 0) + (v === val ? 0.5 : 0), 0) / arr.length;
-// percentile([1,2,3,4,5,6,7,8,9,10], 6) -> 55
-

powerset

Returns the powerset of a given array of numbers.

Use Array.reduce() combined with Array.map() to iterate over elements and combine into an array containing all combinations.

const powerset = arr =>
-  arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]);
-// powerset([1,2]) -> [[], [1], [2], [2,1]]
-

randomIntegerInRange

Returns a random integer in the specified range.

Use Math.random() to generate a random number and map it to the desired range, using Math.floor() to make it an integer.

const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
-// randomIntegerInRange(0, 5) -> 2
-

randomNumberInRange

Returns a random number in the specified range.

Use Math.random() to generate a random value, map it to the desired range using multiplication.

const randomNumberInRange = (min, max) => Math.random() * (max - min) + min;
-// randomNumberInRange(2,10) -> 6.0211363285087005
-

round

Rounds a number to a specified amount of digits.

Use Math.round() and template literals to round the number to the specified number of digits. Omit the second argument, decimals to round to an integer.

const round = (n, decimals=0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`);
-// round(1.005, 2) -> 1.01
-

standardDeviation

Returns the standard deviation of an array of numbers.

Use Array.reduce() to calculate the mean, variance and the sum of the variance of the values, the variance of the values, then determine the standard deviation. You can omit the second argument to get the sample standard deviation or set it to true to get the population standard deviation.

const standardDeviation = (arr, usePopulation = false) => {
-  const mean = arr.reduce((acc, val) => acc + val, 0) / arr.length;
+// palindrome('taco cat') -> true
+
+

percentile

+

Uses the percentile formula to calculate how many numbers in the given array are less or equal to the given value.

+

Use Array.reduce() to calculate how many numbers are below the value and how many are the same value and apply the percentile formula.

+
const percentile = (arr, val) =>
+  100 * arr.reduce((acc,v) => acc + (v < val ? 1 : 0) + (v === val ? 0.5 : 0), 0) / arr.length;
+// percentile([1,2,3,4,5,6,7,8,9,10], 6) -> 55
+
+

powerset

+

Returns the powerset of a given array of numbers.

+

Use Array.reduce() combined with Array.map() to iterate over elements and combine into an array containing all combinations.

+
const powerset = arr =>
+  arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]);
+// powerset([1,2]) -> [[], [1], [2], [2,1]]
+
+

randomIntegerInRange

+

Returns a random integer in the specified range.

+

Use Math.random() to generate a random number and map it to the desired range, using Math.floor() to make it an integer.

+
const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
+// randomIntegerInRange(0, 5) -> 2
+
+

randomNumberInRange

+

Returns a random number in the specified range.

+

Use Math.random() to generate a random value, map it to the desired range using multiplication.

+
const randomNumberInRange = (min, max) => Math.random() * (max - min) + min;
+// randomNumberInRange(2,10) -> 6.0211363285087005
+
+

round

+

Rounds a number to a specified amount of digits.

+

Use Math.round() and template literals to round the number to the specified number of digits. +Omit the second argument, decimals to round to an integer.

+
const round = (n, decimals=0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`);
+// round(1.005, 2) -> 1.01
+
+

standardDeviation

+

Returns the standard deviation of an array of numbers.

+

Use Array.reduce() to calculate the mean, variance and the sum of the variance of the values, the variance of the values, then +determine the standard deviation. +You can omit the second argument to get the sample standard deviation or set it to true to get the population standard deviation.

+
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))
+    arr.reduce((acc, val) => acc.concat(Math.pow(val - mean, 2)), [])
+       .reduce((acc, val) => acc + val, 0) / (arr.length - (usePopulation ? 0 : 1))
   );
 };
-// standardDeviation([10,2,38,23,38,23,21]) -> 13.284434142114991 (sample)
-// standardDeviation([10,2,38,23,38,23,21], true) -> 12.29899614287479 (population)
-

Media

speechSynthesis

Performs speech synthesis (experimental).

Use SpeechSynthesisUtterance.voice and window.speechSynthesis.getVoices() to convert a message to speech. Use window.speechSynthesis.speak() to play the message.

Learn more about the SpeechSynthesisUtterance interface of the Web Speech API.

const speechSynthesis = message => {
+// standardDeviation([10,2,38,23,38,23,21]) -> 13.284434142114991 (sample)
+// standardDeviation([10,2,38,23,38,23,21], true) -> 12.29899614287479 (population)
+
+

Media

+

speechSynthesis

+

Performs speech synthesis (experimental).

+

Use SpeechSynthesisUtterance.voice and window.speechSynthesis.getVoices() to convert a message to speech. +Use window.speechSynthesis.speak() to play the message.

+

Learn more about the SpeechSynthesisUtterance interface of the Web Speech API.

+
const speechSynthesis = message => {
   const msg = new SpeechSynthesisUtterance(message);
   msg.voice = window.speechSynthesis.getVoices()[0];
   window.speechSynthesis.speak(msg);
 };
-// speechSynthesis('Hello, World') -> plays the message
-

Node

JSONToFile

Writes a JSON object to a file.

Use fs.writeFile(), template literals and JSON.stringify() to write a json object to a .json file.

const fs = require('fs');
-const JSONToFile = (obj, filename) => fs.writeFile(`${filename}.json`, JSON.stringify(obj, null, 2))
-// JSONToFile({test: "is passed"}, 'testJsonFile') -> writes the object to 'testJsonFile.json'
-

readFileLines

Returns an array of lines from the specified file.

Use readFileSync function in fs node package to create a Buffer from a file. convert buffer to string using toString(encoding) function. creating an array from contents of file by spliting file content line by line (each \n).

const fs = require('fs');
-const readFileLines = filename => fs.readFileSync(filename).toString('UTF8').split('\n');
+// speechSynthesis('Hello, World') -> plays the message
+
+

Node

+

JSONToFile

+

Writes a JSON object to a file.

+

Use fs.writeFile(), template literals and JSON.stringify() to write a json object to a .json file.

+
const fs = require('fs');
+const JSONToFile = (obj, filename) => fs.writeFile(`${filename}.json`, JSON.stringify(obj, null, 2))
+// JSONToFile({test: "is passed"}, 'testJsonFile') -> writes the object to 'testJsonFile.json'
+
+

readFileLines

+

Returns an array of lines from the specified file.

+

Use readFileSync function in fs node package to create a Buffer from a file. +convert buffer to string using toString(encoding) function. +creating an array from contents of file by spliting file content line by line (each \n).

+
const fs = require('fs');
+const readFileLines = filename => fs.readFileSync(filename).toString('UTF8').split('\n');
 /*
 contents of test.txt :
   line1
@@ -367,10 +968,16 @@ contents of test.txt :
   line3
   ___________________________
 let arr = readFileLines('test.txt')
-console.log(arr) // -> ['line1', 'line2', 'line3']
+console.log(arr) // -> ['line1', 'line2', 'line3']
 */
-

Object

cleanObj

Removes any properties except the ones specified from a JSON object.

Use Object.keys() method to loop over given json object and deleting keys that are not included in given array. Also if you give it a special key (childIndicator) it will search deeply inside it to apply function to inner objects too.

const cleanObj = (obj, keysToKeep = [], childIndicator) => {
-  Object.keys(obj).forEach(key => {
+
+

Object

+

cleanObj

+

Removes any properties except the ones specified from a JSON object.

+

Use Object.keys() method to loop over given json object and deleting keys that are not included in given array. +Also if you give it a special key (childIndicator) it will search deeply inside it to apply function to inner objects too.

+
const cleanObj = (obj, keysToKeep = [], childIndicator) => {
+  Object.keys(obj).forEach(key => {
     if (key === childIndicator) {
       cleanObj(obj[key], keysToKeep, childIndicator);
     } else if (!keysToKeep.includes(key)) {
@@ -380,19 +987,32 @@ console.log(arr) // -> ['line1', 'line2', 'line3']
 }
 /*
   const testObj = {a: 1, b: 2, children: {a: 1, b: 2}}
-  cleanObj(testObj, ["a"],"children")
+  cleanObj(testObj, ["a"],"children")
   console.log(testObj)// { a: 1, children : { a: 1}}
 */
-

objectFromPairs

Creates an object from the given key-value pairs.

Use Array.reduce() to create and combine key-value pairs.

const objectFromPairs = arr => arr.reduce((a, v) => (a[v[0]] = v[1], a), {});
-// objectFromPairs([['a',1],['b',2]]) -> {a: 1, b: 2}
-

objectToPairs

Creates an array of key-value pair arrays from an object.

Use Object.keys() and Array.map() to iterate over the object's keys and produce an array with key-value pairs.

const objectToPairs = obj => Object.keys(obj).map(k => [k, obj[k]]);
-// objectToPairs({a: 1, b: 2}) -> [['a',1],['b',2]])
-

orderBy

Returns a sorted array of objects ordered by properties and orders.

Uses a custom implementation of sort, that reduces the props array argument with a default value of 0, it uses destructuring to swap the properties position depending on the order passed. If no orders array is passed it sort by 'asc' by default.

const orderBy = (arr, props, orders) =>
-  arr.sort((a, b) =>
-    props.reduce((acc, prop, i) => {
+
+

objectFromPairs

+

Creates an object from the given key-value pairs.

+

Use Array.reduce() to create and combine key-value pairs.

+
const objectFromPairs = arr => arr.reduce((a, v) => (a[v[0]] = v[1], a), {});
+// objectFromPairs([['a',1],['b',2]]) -> {a: 1, b: 2}
+
+

objectToPairs

+

Creates an array of key-value pair arrays from an object.

+

Use Object.keys() and Array.map() to iterate over the object's keys and produce an array with key-value pairs.

+
const objectToPairs = obj => Object.keys(obj).map(k => [k, obj[k]]);
+// objectToPairs({a: 1, b: 2}) -> [['a',1],['b',2]])
+
+

orderBy

+

Returns a sorted array of objects ordered by properties and orders.

+

Uses a custom implementation of sort, that reduces the props array argument with a default value of 0, it uses destructuring to swap the properties position depending on the order passed. +If no orders array is passed it sort by 'asc' by default.

+
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;
+        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)
@@ -400,130 +1020,281 @@ console.log(arr) // -> ['line1', 'line2', 'line3']
 /*
 const users = [{ 'name': 'fred',   'age': 48 },{ 'name': 'barney', 'age': 36 },
   { 'name': 'fred',   'age': 40 },{ 'name': 'barney', 'age': 34 }];
-orderby(users, ['name', 'age'], ['asc', 'desc']) -> [{name: 'barney', age: 36}, {name: 'barney', age: 34}, {name: 'fred', age: 48}, {name: 'fred', age: 40}]
-orderby(users, ['name', 'age']) -> [{name: 'barney', age: 34}, {name: 'barney', age: 36}, {name: 'fred', age: 40}, {name: 'fred', age: 48}]
+orderby(users, ['name', 'age'], ['asc', 'desc']) -> [{name: 'barney', age: 36}, {name: 'barney', age: 34}, {name: 'fred', age: 48}, {name: 'fred', age: 40}]
+orderby(users, ['name', 'age']) -> [{name: 'barney', age: 34}, {name: 'barney', age: 36}, {name: 'fred', age: 40}, {name: 'fred', age: 48}]
 */
-

select

Retrieve a property that indicated by the selector from object.

If property not exists returns undefined.

const select = (from, selector) =>
-  selector.split('.').reduce((prev, cur) => prev && prev[cur], from);
+
+

select

+

Retrieve a property that indicated by the selector from object.

+

If property not exists returns undefined.

+
const select = (from, selector) =>
+  selector.split('.').reduce((prev, cur) => prev && prev[cur], from);
 
 // const obj = {selector: {to: {val: 'val to select'}}};
-// select(obj, 'selector.to.val'); -> 'val to select'
-

shallowClone

Creates a shallow clone of an object.

Use Object.assign() and an empty object ({}) to create a shallow clone of the original.

const shallowClone = obj => Object.assign({}, obj);
+// select(obj, 'selector.to.val'); -> 'val to select'
+
+

shallowClone

+

Creates a shallow clone of an object.

+

Use Object.assign() and an empty object ({}) to create a shallow clone of the original.

+
const shallowClone = obj => Object.assign({}, obj);
 /*
 const a = { x: true, y: 1 };
 const b = shallowClone(a);
-a === b -> false
+a === b -> false
 */
-

truthCheckCollection

Checks if the predicate (second argument) is truthy on all elements of a collection (first argument).

Use Array.every() to check if each passed object has the specified property and if it returns a truthy value.

const truthCheckCollection = (collection, pre) => (collection.every(obj => obj[pre]));
-// truthCheckCollection([{"user": "Tinky-Winky", "sex": "male"}, {"user": "Dipsy", "sex": "male"}], "sex") -> true
-

String

anagrams

Generates all anagrams of a string (contains duplicates).

Use recursion. For each letter in the given string, create all the partial anagrams for the rest of its letters. Use Array.map() to combine the letter with each partial anagram, then Array.reduce() to combine all anagrams in one array. Base cases are for string length equal to 2 or 1.

const anagrams = str => {
+
+

truthCheckCollection

+

Checks if the predicate (second argument) is truthy on all elements of a collection (first argument).

+

Use Array.every() to check if each passed object has the specified property and if it returns a truthy value.

+
const truthCheckCollection = (collection, pre) => (collection.every(obj => obj[pre]));
+// truthCheckCollection([{"user": "Tinky-Winky", "sex": "male"}, {"user": "Dipsy", "sex": "male"}], "sex") -> true
+
+

String

+

anagrams

+

Generates all anagrams of a string (contains duplicates).

+

Use recursion. +For each letter in the given string, create all the partial anagrams for the rest of its letters. +Use Array.map() to combine the letter with each partial anagram, then Array.reduce() to combine all anagrams in one array. +Base cases are for string length equal to 2 or 1.

+
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)), []);
+  return str.split('').reduce((acc, letter, i) =>
+    acc.concat(anagrams(str.slice(0, i) + str.slice(i + 1)).map(val => letter + val)), []);
 };
-// anagrams('abc') -> ['abc','acb','bac','bca','cab','cba']
-

Capitalize

Capitalizes the first letter of a string.

Use destructuring and toUpperCase() to capitalize first letter, ...rest to get array of characters after first letter and then Array.join('') to make it a string again. Omit the lowerRest parameter to keep the rest of the string intact, or set it to true to convert to lowercase.

const capitalize = ([first,...rest], lowerRest = false) =>
+// anagrams('abc') -> ['abc','acb','bac','bca','cab','cba']
+
+

Capitalize

+

Capitalizes the first letter of a string.

+

Use destructuring and toUpperCase() to capitalize first letter, ...rest to get array of characters after first letter and then Array.join('') to make it a string again. +Omit the lowerRest parameter to keep the rest of the string intact, or set it to true to convert to lowercase.

+
const capitalize = ([first,...rest], lowerRest = false) =>
   first.toUpperCase() + (lowerRest ? rest.join('').toLowerCase() : rest.join(''));
-// capitalize('myName') -> 'MyName'
-// capitalize('myName', true) -> 'Myname'
-

capitalizeEveryWord

Capitalizes the first letter of every word in a string.

Use replace() to match the first character of each word and toUpperCase() to capitalize it.

const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase());
-// capitalizeEveryWord('hello world!') -> 'Hello World!'
-

countVowels

Retuns number of vowels in provided string.

Use a regular expression to count number of vowels (A, E, I, O, U) in a string.

const countVowels = str => (str.match(/[aeiou]/ig) || []).length;
-// countVowels('foobar') -> 3
-// countVowels('gym') -> 0
-

escapeRegExp

Escapes a string to use in a regular expression.

Use replace() to escape special characters.

const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
-// escapeRegExp('(test)') -> \\(test\\)
-

fromCamelCase

Converts a string from camelcase.

Use replace() to remove underscores, hyphens and spaces and convert words to camelcase. Omit the second argument to use a default separator of _.

const fromCamelCase = (str, separator = '_') =>
+// capitalize('myName') -> 'MyName'
+// capitalize('myName', true) -> 'Myname'
+
+

capitalizeEveryWord

+

Capitalizes the first letter of every word in a string.

+

Use replace() to match the first character of each word and toUpperCase() to capitalize it.

+
const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase());
+// capitalizeEveryWord('hello world!') -> 'Hello World!'
+
+

countVowels

+

Retuns number of vowels in provided string.

+

Use a regular expression to count number of vowels (A, E, I, O, U) in a string.

+
const countVowels = str => (str.match(/[aeiou]/ig) || []).length;
+// countVowels('foobar') -> 3
+// countVowels('gym') -> 0
+
+

escapeRegExp

+

Escapes a string to use in a regular expression.

+

Use replace() to escape special characters.

+
const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+// escapeRegExp('(test)') -> \\(test\\)
+
+

fromCamelCase

+

Converts a string from camelcase.

+

Use replace() to remove underscores, hyphens and spaces and convert words to camelcase. +Omit the second argument to use a default separator of _.

+
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();
-// fromCamelCase('someDatabaseFieldName', ' ') -> 'some database field name'
-// fromCamelCase('someLabelThatNeedsToBeCamelized', '-') -> 'some-label-that-needs-to-be-camelized'
-// fromCamelCase('someJavascriptProperty', '_') -> 'some_javascript_property'
-

reverseString

Reverses a string.

Use split('') and Array.reverse() to reverse the order of the characters in the string. Combine characters to get a string using join('').

const reverseString = str => str.split('').reverse().join('');
-// reverseString('foobar') -> 'raboof'
-

sortCharactersInString

Alphabetically sorts the characters in a string.

Split the string using split(''), Array.sort() utilizing localeCompare(), recombine using join('').

const sortCharactersInString = str =>
-  str.split('').sort((a, b) => a.localeCompare(b)).join('');
-// sortCharactersInString('cabbage') -> 'aabbceg'
-

stringToArrayOfWords

Converts a given string into an array of words.

Use String.split() with a supplied pattern (defaults to non alpha as a regex) to convert to an array of strings. Use Array.filter() to remove any empty strings. Omit the second argument to use the default regex.

const stringToArrayOfWords = (str, pattern = /[^a-zA-Z-]+/) => str.split(pattern).filter(Boolean);
-// stringToArrayOfWords("I love javaScript!!") -> ["I", "love", "javaScript"]
-// stringToArrayOfWords("python, javaScript & coffee") -> ["python", "javaScript", "coffee"]
-

toCamelCase

Converts a string to camelcase.

Use replace() to remove underscores, hyphens and spaces and convert words to camelcase.

const toCamelCase = str =>
-  str.replace(/^([A-Z])|[\s-_]+(\w)/g, (match, p1, p2, offset) =>  p2 ? p2.toUpperCase() : p1.toLowerCase());
-// toCamelCase("some_database_field_name") -> 'someDatabaseFieldName'
-// toCamelCase("Some label that needs to be camelized") -> 'someLabelThatNeedsToBeCamelized'
-// toCamelCase("some-javascript-property") -> 'someJavascriptProperty'
-// toCamelCase("some-mixed_string with spaces_underscores-and-hyphens") -> 'someMixedStringWithSpacesUnderscoresAndHyphens'
-

truncateString

Truncates a string up to a specified length.

Determine if the string's length is greater than num. Return the string truncated to the desired length, with ... appended to the end or the original string.

const truncateString = (str, num) =>
-  str.length > num ? str.slice(0, num > 3 ? num - 3 : num) + '...' : str;
-// truncateString('boomerang', 7) -> 'boom...'
-

Utility

coalesce

Returns the first non-null/undefined argument.

Use Array.find() to return the first non null/undefined argument.

const coalesce = (...args) => args.find(_ => ![undefined, null].includes(_))
-// coalesce(null,undefined,"",NaN, "Waldo") -> ""
-

coalesceFactory

Returns a customized coalesce function that returns the first argument that returns true from the provided argument validation function.

Use Array.find() to return the first argument that returns true from the provided argument validation function.

const coalesceFactory = valid => (...args) => args.find(valid);
-// const customCoalesce = coalesceFactory(_ => ![null, undefined, "", NaN].includes(_))
-// customCoalesce(undefined, null, NaN, "", "Waldo") //-> "Waldo"
-

extendHex

Extends a 3-digit color code to a 6-digit color code.

Use Array.map(), split() and Array.join() to join the mapped array for converting a 3-digit RGB notated hexadecimal color-code to the 6-digit form. Array.slice() is used to remove # from string start since it's added once.

const extendHex = shortHex =>
-  '#' + shortHex.slice(shortHex.startsWith('#') ? 1 : 0).split('').map(x => x+x).join('')
-// extendHex('#03f') -> '#0033ff'
-// extendHex('05a') -> '#0055aa'
-

getType

Returns the native type of a value.

Returns lowercased constructor name of value, "undefined" or "null" if value is undefined or null

const getType = v =>
+// fromCamelCase('someDatabaseFieldName', ' ') -> 'some database field name'
+// fromCamelCase('someLabelThatNeedsToBeCamelized', '-') -> 'some-label-that-needs-to-be-camelized'
+// fromCamelCase('someJavascriptProperty', '_') -> 'some_javascript_property'
+
+

reverseString

+

Reverses a string.

+

Use split('') and Array.reverse() to reverse the order of the characters in the string. +Combine characters to get a string using join('').

+
const reverseString = str => str.split('').reverse().join('');
+// reverseString('foobar') -> 'raboof'
+
+

sortCharactersInString

+

Alphabetically sorts the characters in a string.

+

Split the string using split(''), Array.sort() utilizing localeCompare(), recombine using join('').

+
const sortCharactersInString = str =>
+  str.split('').sort((a, b) => a.localeCompare(b)).join('');
+// sortCharactersInString('cabbage') -> 'aabbceg'
+
+

stringToArrayOfWords

+

Converts a given string into an array of words.

+

Use String.split() with a supplied pattern (defaults to non alpha as a regex) to convert to an array of strings. Use Array.filter() to remove any empty strings. +Omit the second argument to use the default regex.

+
const stringToArrayOfWords = (str, pattern = /[^a-zA-Z-]+/) => str.split(pattern).filter(Boolean);
+// stringToArrayOfWords("I love javaScript!!") -> ["I", "love", "javaScript"]
+// stringToArrayOfWords("python, javaScript & coffee") -> ["python", "javaScript", "coffee"]
+
+

toCamelCase

+

Converts a string to camelcase.

+

Use replace() to remove underscores, hyphens and spaces and convert words to camelcase.

+
const toCamelCase = str =>
+  str.replace(/^([A-Z])|[\s-_]+(\w)/g, (match, p1, p2, offset) =>  p2 ? p2.toUpperCase() : p1.toLowerCase());
+// toCamelCase("some_database_field_name") -> 'someDatabaseFieldName'
+// toCamelCase("Some label that needs to be camelized") -> 'someLabelThatNeedsToBeCamelized'
+// toCamelCase("some-javascript-property") -> 'someJavascriptProperty'
+// toCamelCase("some-mixed_string with spaces_underscores-and-hyphens") -> 'someMixedStringWithSpacesUnderscoresAndHyphens'
+
+

truncateString

+

Truncates a string up to a specified length.

+

Determine if the string's length is greater than num. +Return the string truncated to the desired length, with ... appended to the end or the original string.

+
const truncateString = (str, num) =>
+  str.length > num ? str.slice(0, num > 3 ? num - 3 : num) + '...' : str;
+// truncateString('boomerang', 7) -> 'boom...'
+
+

Utility

+

coalesce

+

Returns the first non-null/undefined argument.

+

Use Array.find() to return the first non null/undefined argument.

+
const coalesce = (...args) => args.find(_ => ![undefined, null].includes(_))
+// coalesce(null,undefined,"",NaN, "Waldo") -> ""
+
+

coalesceFactory

+

Returns a customized coalesce function that returns the first argument that returns true from the provided argument validation function.

+

Use Array.find() to return the first argument that returns true from the provided argument validation function.

+
const coalesceFactory = valid => (...args) => args.find(valid);
+// const customCoalesce = coalesceFactory(_ => ![null, undefined, "", NaN].includes(_))
+// customCoalesce(undefined, null, NaN, "", "Waldo") //-> "Waldo"
+
+

extendHex

+

Extends a 3-digit color code to a 6-digit color code.

+

Use Array.map(), split() and Array.join() to join the mapped array for converting a 3-digit RGB notated hexadecimal color-code to the 6-digit form. +Array.slice() is used to remove # from string start since it's added once.

+
const extendHex = shortHex =>
+  '#' + shortHex.slice(shortHex.startsWith('#') ? 1 : 0).split('').map(x => x+x).join('')
+// extendHex('#03f') -> '#0033ff'
+// extendHex('05a') -> '#0055aa'
+
+

getType

+

Returns the native type of a value.

+

Returns lowercased constructor name of value, "undefined" or "null" if value is undefined or null

+
const getType = v =>
   v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name.toLowerCase();
-// getType(new Set([1,2,3])) -> "set"
-

hexToRGB

Converts a color code to a rgb() or rgba() string if alpha value is provided.

Use bitwise right-shift operator and mask bits with & (and) operator to convert a hexadecimal color code (with or without prefixed with #) to a string with the RGB values. If it's 3-digit color code, first convert to 6-digit version. If any alpha value is provided alongside 6-digit hex, give rgba() string in return.

const hexToRGB = hex => {
+// getType(new Set([1,2,3])) -> "set"
+
+

hexToRGB

+

Converts a color code to a rgb() or rgba() string if alpha value is provided.

+

Use bitwise right-shift operator and mask bits with & (and) operator to convert a hexadecimal color code (with or without prefixed with #) to a string with the RGB values. If it's 3-digit color code, first convert to 6-digit version. If any alpha value is provided alongside 6-digit hex, give rgba() string in return.

+
const hexToRGB = hex => {
   let alpha = false, h = hex.slice(hex.startsWith('#') ? 1 : 0);
-  if (h.length === 3) h = [...h].map(x => x + x).join('');
+  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)}` : '') + ')';
+    + (h >>> (alpha ? 24 : 16)) + ', '
+    + ((h & (alpha ? 0x00ff0000 : 0x00ff00)) >>> (alpha ? 16 : 8)) + ', '
+    + ((h & (alpha ? 0x0000ff00 : 0x0000ff)) >>> (alpha ? 8 : 0))
+    + (alpha ? `, ${(h & 0x000000ff)}` : '') + ')';
 };
-// hexToRGB('#27ae60ff') -> 'rgba(39, 174, 96, 255)'
-// hexToRGB('27ae60') -> 'rgb(39, 174, 96)'
-// hexToRGB('#fff') -> 'rgb(255, 255, 255)'
+// hexToRGB('#27ae60ff') -> 'rgba(39, 174, 96, 255)'
+// hexToRGB('27ae60') -> 'rgb(39, 174, 96)'
+// hexToRGB('#fff') -> 'rgb(255, 255, 255)'
 
-

isArray

Checks if the given argument is an array.

Use Array.isArray() to check if a value is classified as an array.

const isArray = val => !!val && Array.isArray(val);
-// isArray(null) -> false
-// isArray([1]) -> true
-

isBoolean

Checks if the given argument is a native boolean element.

Use typeof to check if a value is classified as a boolean primitive.

const isBoolean = val => typeof val === 'boolean';
-// isBoolean(null) -> false
-// isBoolean(false) -> true
-

isFunction

Checks if the given argument is a function.

Use typeof to check if a value is classified as a function primitive.

const isFunction = val => val && typeof val === 'function';
-// isFunction('x') -> false
-// isFunction(x => x) -> true
-

isNumber

Checks if the given argument is a number.

Use typeof to check if a value is classified as a number primitive.

const isNumber = val => typeof val === 'number';
-// isNumber('1') -> false
-// isNumber(1) -> true
-

isString

Checks if the given argument is a string.

Use typeof to check if a value is classified as a string primitive.

const isString = val => typeof val === 'string';
-// isString(10) -> false
-// isString('10') -> true
-

isSymbol

Checks if the given argument is a symbol.

Use typeof to check if a value is classified as a symbol primitive.

const isSymbol = val => typeof val === 'symbol';
-// isSymbol('x') -> false
-// isSymbol(Symbol('x')) -> true
-

RGBToHex

Converts the values of RGB components to a colorcode.

Convert given RGB parameters to hexadecimal string using bitwise left-shift operator (<<) and toString(16), then padStart(6,'0') to get a 6-digit hexadecimal value.

const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0');
-// RGBToHex(255, 165, 1) -> 'ffa501'
-

timeTaken

Measures the time taken by a function to execute.

Use console.time() and console.timeEnd() to measure the difference between the start and end times to determine how long the callback took to execute.

const timeTaken = callback => {
+
+

isArray

+

Checks if the given argument is an array.

+

Use Array.isArray() to check if a value is classified as an array.

+
const isArray = val => !!val && Array.isArray(val);
+// isArray(null) -> false
+// isArray([1]) -> true
+
+

isBoolean

+

Checks if the given argument is a native boolean element.

+

Use typeof to check if a value is classified as a boolean primitive.

+
const isBoolean = val => typeof val === 'boolean';
+// isBoolean(null) -> false
+// isBoolean(false) -> true
+
+

isFunction

+

Checks if the given argument is a function.

+

Use typeof to check if a value is classified as a function primitive.

+
const isFunction = val => val && typeof val === 'function';
+// isFunction('x') -> false
+// isFunction(x => x) -> true
+
+

isNumber

+

Checks if the given argument is a number.

+

Use typeof to check if a value is classified as a number primitive.

+
const isNumber = val => typeof val === 'number';
+// isNumber('1') -> false
+// isNumber(1) -> true
+
+

isString

+

Checks if the given argument is a string.

+

Use typeof to check if a value is classified as a string primitive.

+
const isString = val => typeof val === 'string';
+// isString(10) -> false
+// isString('10') -> true
+
+

isSymbol

+

Checks if the given argument is a symbol.

+

Use typeof to check if a value is classified as a symbol primitive.

+
const isSymbol = val => typeof val === 'symbol';
+// isSymbol('x') -> false
+// isSymbol(Symbol('x')) -> true
+
+

RGBToHex

+

Converts the values of RGB components to a colorcode.

+

Convert given RGB parameters to hexadecimal string using bitwise left-shift operator (<<) and toString(16), then padStart(6,'0') to get a 6-digit hexadecimal value.

+
const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0');
+// RGBToHex(255, 165, 1) -> 'ffa501'
+
+

timeTaken

+

Measures the time taken by a function to execute.

+

Use console.time() and console.timeEnd() to measure the difference between the start and end times to determine how long the callback took to execute.

+
const timeTaken = callback => {
   console.time('timeTaken');  const r = callback();
   console.timeEnd('timeTaken');  return r;
 };
-// timeTaken(() => Math.pow(2, 10)) -> 1024
+// timeTaken(() => Math.pow(2, 10)) -> 1024
 // (logged): timeTaken: 0.02099609375ms
-

toOrdinalSuffix

Adds an ordinal suffix to a number.

Use the modulo operator (%) to find values of single and tens digits. Find which ordinal pattern digits match. If digit is found in teens pattern, use teens ordinal.

const toOrdinalSuffix = num => {
+
+

toOrdinalSuffix

+

Adds an ordinal suffix to a number.

+

Use the modulo operator (%) to find values of single and tens digits. +Find which ordinal pattern digits match. +If digit is found in teens pattern, use teens ordinal.

+
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];
+  return oPattern.includes(digits[0]) && !tPattern.includes(digits[1]) ? int + ordinals[digits[0] - 1] : int + ordinals[3];
 };
-// toOrdinalSuffix("123") -> "123rd"
-

UUIDGenerator

Generates a UUID.

Use crypto API to generate a UUID, compliant with RFC4122 version 4.

const UUIDGenerator = () =>
-  ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
-    (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
+// toOrdinalSuffix("123") -> "123rd"
+
+

UUIDGenerator

+

Generates a UUID.

+

Use crypto API to generate a UUID, compliant with RFC4122 version 4.

+
const UUIDGenerator = () =>
+  ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
+    (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
   );
-// UUIDGenerator() -> '7982fcfe-5721-4632-bede-6000885be57d'
-

validateEmail

Returns true if the given string is a valid email, false otherwise.

Use a regular expression to check if the email is valid. Returns true if email is valid, false if not.

const validateEmail = str =>
-  /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(str);
-// validateEmail(mymail@gmail.com) -> true
-

validateNumber

Returns true if the given value is a number, false otherwise.

Use !isNaN in combination with parseFloat() to check if the argument is a number. Use isFinite() to check if the number is finite. Use Number() to check if the coercion holds.

const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n;
-// validateNumber('10') -> true
-

\ No newline at end of file +// UUIDGenerator() -> '7982fcfe-5721-4632-bede-6000885be57d' +
+

validateEmail

+

Returns true if the given string is a valid email, false otherwise.

+

Use a regular expression to check if the email is valid. +Returns true if email is valid, false if not.

+
const validateEmail = str =>
+  /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(str);
+// validateEmail(mymail@gmail.com) -> true
+
+

validateNumber

+

Returns true if the given value is a number, false otherwise.

+

Use !isNaN in combination with parseFloat() to check if the argument is a number. +Use isFinite() to check if the number is finite. +Use Number() to check if the coercion holds.

+
const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n;
+// validateNumber('10') -> true
+
+

+ +
+
+ + + + diff --git a/docs/mini/flavor.scss b/docs/mini/flavor.scss index 88d0f91c2..e0ab1e425 100644 --- a/docs/mini/flavor.scss +++ b/docs/mini/flavor.scss @@ -157,3 +157,7 @@ label#menu-toggle { .card { box-shadow: 0 0.25rem 0.25rem 0 rgba(0, 0, 0, 0.125), 0 0.125rem 0.125rem -0.125rem rgba(0, 0, 0, 0.25); } + +main { + padding: 0; +} diff --git a/scripts/web-script.js b/scripts/web-script.js index 52dd2ddc4..d51a39d28 100644 --- a/scripts/web-script.js +++ b/scripts/web-script.js @@ -89,20 +89,19 @@ try { // Minify output output = minify(output, { collapseBooleanAttributes: true, - collapseWhitespace: true, - decodeEntities: true, + collapseWhitespace: false, + decodeEntities: false, minifyCSS: true, minifyJS: true, - html5: false, + keepClosingSlash: true, processConditionalComments: true, - removeAttributeQuotes: true, + removeAttributeQuotes: false, removeComments: true, - removeEmptyAttributes: true, - removeOptionalTags: true, - removeScriptTypeAttributes: true, - removeStyleLinkTypeAttributes: true, + removeEmptyAttributes: false, + removeOptionalTags: false, + removeScriptTypeAttributes: false, + removeStyleLinkTypeAttributes: false, trimCustomFragments: true, - useShortDoctype: true, }); // Write to the index.html file fs.writeFileSync(path.join(docsPath,'index.html'), output); diff --git a/static-parts/index-end.html b/static-parts/index-end.html index 6831f6995..2dd2aae7e 100644 --- a/static-parts/index-end.html +++ b/static-parts/index-end.html @@ -1,6 +1,6 @@
From 5c4a7f5bffcc1d600ec93ebe79a3b62cd8b0f1a4 Mon Sep 17 00:00:00 2001 From: Arjun Mahishi Date: Thu, 21 Dec 2017 16:10:50 +0530 Subject: [PATCH 39/61] Update httpsRedirect.md --- snippets/httpsRedirect.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/snippets/httpsRedirect.md b/snippets/httpsRedirect.md index f60a79610..26f8ec2c9 100644 --- a/snippets/httpsRedirect.md +++ b/snippets/httpsRedirect.md @@ -2,8 +2,10 @@ Redirects the page to HTTPS if its currently in HTTP. Also, pressing the back button doesn't take it back to the HTTP page as its replaced in the history. +Use `location.protocol` to get the protocol currently being used. If it's not HTTPS, use `location.replace()` to replace the existing page with the HTTPS version of the page. Use `location.href` to get the full address, split it with `String.split()` and remove the protocol part of the URL. + ```js const httpsRedirect = () => { if(location.protocol !== "https:") location.replace("https://" + location.href.split("//")[1]); } -``` \ No newline at end of file +``` From c5ddde438c2b07c22ab2881563ce1f79b7930b80 Mon Sep 17 00:00:00 2001 From: David Wu Date: Thu, 21 Dec 2017 12:11:43 +0100 Subject: [PATCH 40/61] Travis config --- travis.log | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 travis.log diff --git a/travis.log b/travis.log new file mode 100644 index 000000000..727b5c674 --- /dev/null +++ b/travis.log @@ -0,0 +1,87 @@ +Command line: +"travis encrypt --add" + + + ________ __ + / | / | + ########/ ______ ______ __ __ ##/ _______ + ## | / \ / \ / \ / | / | / | + ## | /###### | ###### | ## \ /##/ ## | /#######/ + ## | ## | ##/ / ## | ## /##/ ## | ## \ + ## | ## | /####### | ## ##/ ## | ###### | + ## | ## | ## ## | ###/ ## | / ##/ + ##/ ##/ #######/ #/ ##/ #######/ + + TRajectory Analyzer and VISualizer - Open-source freeware under GNU GPL v3 + + Copyright (c) Martin Brehm (2009-2015) + Martin Thomas (2012-2015) + Barbara Kirchner (2009-2015) + University of Leipzig / University of Bonn. + + http://www.travis-analyzer.de + + Please cite: + M. Brehm and B. Kirchner, J. Chem. Inf. Model. 2011, 51 (8), pp 2007-2023. + + There is absolutely no warranty on any results obtained from TRAVIS. + + # Running on pl4gue at Thu Dec 21 11:44:39 2017 (PID 25714). + # Running in /home/pl4gue/Programming/30-seconds-of-code + # Source code version: Nov 07 2015. + # Compiled at Nov 17 2015 23:12:21. + # Compiler version: 5.2.1 20151028 + # Target platform: Linux + # Compile flags: DEBUG_ARRAYS + # Machine: int=4b, long=8b, addr=8b, 0xA0B0C0D0=D0,C0,B0,A0. + # User home: /home/pl4gue + # Exe path: /usr/bin/travis + # Input is redirected, Output to terminal + + >>> Please use a color scheme with dark background or specify "-nocolor"! <<< + + No configuration file found. + Writing default configuration to /home/pl4gue/.travis.conf ... + +Unknown parameter: "encrypt". + + List of supported command line options: + + -p Loads position data from the specified trajectory file. + The file format may be *.xyz, *.pdb, *.lmp (Lammps), HISTORY (DLPOLY), or *.prmtop/*.mdcrd (Amber). + -i Reads input from the specified text file. + + -config Load the specified configuration file. + -stream Treats input trajectory as a stream (e.g. named pipe): No fseek, etc. + -showconf Shows a tree structure of the configuration file. + -writeconf Writes the default configuration file, including all defines values. + + -verbose Show detailed information about what's going on. + -nocolor Executes TRAVIS in monochrome mode. + -dimcolor Uses dim instead of bright colors. + + -credits Display a list of persons who contributed to TRAVIS. + -help, -? Shows this help. + + If only one argument is specified, it is assumed to be the name of a trajectory file. + If argument is specified at all, TRAVIS asks for the trajectory file to open. + + + Note: To show a list of all persons who contributed to TRAVIS, + please add "-credits" to your command line arguments, or set the + variable "SHOWCREDITS" to "TRUE" in your travis.conf file. + + Source code from other projects used in TRAVIS: + - lmfit from Joachim Wuttke + - kiss_fft from Mark Borgerding + - voro++ from Chris Rycroft + + http://www.travis-analyzer.de + + Please cite: + + * "TRAVIS - A Free Analyzer and Visualizer for Monte Carlo and Molecular Dynamics Trajectories", + M. Brehm, B. Kirchner; J. Chem. Inf. Model. 2011, 51 (8), pp 2007-2023. + +*** The End *** + From 0c99e499f64856d1fadd2a56d86f244369394535 Mon Sep 17 00:00:00 2001 From: David Wu Date: Thu, 21 Dec 2017 12:13:18 +0100 Subject: [PATCH 41/61] TravisCi config and build script --- .travis.yml | 16 ++++++++++++++++ .travis/push.sh | 21 +++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 .travis.yml create mode 100644 .travis/push.sh diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..945419827 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,16 @@ +language: node_js +node_js: + - node +before_install: + - npm install webber + - npm install builder + - npm install tagger +script: + - npm run tagger + - npm run builder + - npm run webber +after_success: + - .travis/push.sh +env: + global: + - secure: nwLmj3XjcE4+AQRlph+UWLXItNmPOdh7oVuXEO/rJYIXf9VOiWj6QK3VXX2BLLuDTmzgwvUz+kOB2rtFStoyD70oP255fD/54DhIXrW1br4XlYYHk5mXWF+tiW6iEh7xk7CpY9Tj1x1Y/DOKu5PmZ1CbGGlp5lgPsdBb/QQrkJk36yl/6tES0CBOxuSInde7Xs5sgpQyRa/4VIz0suTmNuGhAZKhdpaXQlPvi8uNr2JGACV7OAHLhySwGCqhuhzdnRXkB2nGhnnwxbY/OYzKDCHoBsA8KWqqyq3ptV3tWzJ2tZDusDG2kXz0DeQquFT5ysDsInSm41Q+7Pw92RPa7+Qjvx0tvjB7YqK0hXpDmgO/DVzbgzW6Wx+X/tUOqkM88CEKqoSisdLiOsCoABuhMojAnZ+TghfIYQ3cm/a5gmMiidbiVm96JPw/ghC5n2K0UlzGK3iBXFn+8+F8XFzGuJ16+z91Nz8ny7SvsCN3EVWRwGTuU9SmxbwpEcIx8c7bkQBElGA/MnzWOOBcJQ3sKeXKYD01Cc6CXXbOb0qckPwU4AM4/qa9pgs2m2xhIM0tHb/cVYOqsD3pIjbgiAG+ySyVJ7QJ5xLZh2zYqXTb1/VRyAXmRHSklEhnHDY8JRTaV4mUk3gEo+8jZJ2GMQxQVY+QwxN2uahPk8wa6nGEKl4= diff --git a/.travis/push.sh b/.travis/push.sh new file mode 100644 index 000000000..425167c0d --- /dev/null +++ b/.travis/push.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +setup_git() { + git config --global user.email "david10608@gmail.com" + git config --global user.name "Pl4gue" +} + +commit_website_files() { + git checkout master + git add * + git commit --message "Travis build: $TRAVIS_BUILD_NUMBER" +} + +upload_files() { + git remote add origin https://${GH_TOKEN}@github.com/Chalarangelo/30-seconds-of-code.git > /dev/null 2>&1 + git push --quiet --set-upstream origin master +} + +setup_git +commit_website_files +upload_files From aa2634669922d87445d1bee062224c223ac340e2 Mon Sep 17 00:00:00 2001 From: David Wu Date: Thu, 21 Dec 2017 12:21:34 +0100 Subject: [PATCH 42/61] add travis badge --- static-parts/README-start.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static-parts/README-start.md b/static-parts/README-start.md index 92eb9fe8a..f1e937dff 100644 --- a/static-parts/README-start.md +++ b/static-parts/README-start.md @@ -1,6 +1,6 @@ ![Logo](/logo.png) -# 30 seconds of code [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/30-seconds-of-code/Lobby) +# 30 seconds of code [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/30-seconds-of-code/Lobby) ![Travis Build](https://travis-ci.org/Chalarangelo/30-seconds-of-code.svg?branch=master) > Curated collection of useful Javascript snippets that you can understand in 30 seconds or less. - Use Ctrl + F or command + F to search for a snippet. From a9537e4153345ba977fb952b0308873d8e141cd8 Mon Sep 17 00:00:00 2001 From: David Wu Date: Thu, 21 Dec 2017 12:25:51 +0100 Subject: [PATCH 43/61] fix permission denied issue --- .travis.yml | 2 +- .travis/push.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 945419827..a5d5a9dca 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ script: - npm run builder - npm run webber after_success: - - .travis/push.sh + - sudo .travis/push.sh env: global: - secure: nwLmj3XjcE4+AQRlph+UWLXItNmPOdh7oVuXEO/rJYIXf9VOiWj6QK3VXX2BLLuDTmzgwvUz+kOB2rtFStoyD70oP255fD/54DhIXrW1br4XlYYHk5mXWF+tiW6iEh7xk7CpY9Tj1x1Y/DOKu5PmZ1CbGGlp5lgPsdBb/QQrkJk36yl/6tES0CBOxuSInde7Xs5sgpQyRa/4VIz0suTmNuGhAZKhdpaXQlPvi8uNr2JGACV7OAHLhySwGCqhuhzdnRXkB2nGhnnwxbY/OYzKDCHoBsA8KWqqyq3ptV3tWzJ2tZDusDG2kXz0DeQquFT5ysDsInSm41Q+7Pw92RPa7+Qjvx0tvjB7YqK0hXpDmgO/DVzbgzW6Wx+X/tUOqkM88CEKqoSisdLiOsCoABuhMojAnZ+TghfIYQ3cm/a5gmMiidbiVm96JPw/ghC5n2K0UlzGK3iBXFn+8+F8XFzGuJ16+z91Nz8ny7SvsCN3EVWRwGTuU9SmxbwpEcIx8c7bkQBElGA/MnzWOOBcJQ3sKeXKYD01Cc6CXXbOb0qckPwU4AM4/qa9pgs2m2xhIM0tHb/cVYOqsD3pIjbgiAG+ySyVJ7QJ5xLZh2zYqXTb1/VRyAXmRHSklEhnHDY8JRTaV4mUk3gEo+8jZJ2GMQxQVY+QwxN2uahPk8wa6nGEKl4= diff --git a/.travis/push.sh b/.travis/push.sh index 425167c0d..4e577890f 100644 --- a/.travis/push.sh +++ b/.travis/push.sh @@ -12,7 +12,7 @@ commit_website_files() { } upload_files() { - git remote add origin https://${GH_TOKEN}@github.com/Chalarangelo/30-seconds-of-code.git > /dev/null 2>&1 + sudo git remote add origin https://${GH_TOKEN}@github.com/Chalarangelo/30-seconds-of-code.git > /dev/null 2>&1 git push --quiet --set-upstream origin master } From 906200821053594687cd1faff893c3075faf0df6 Mon Sep 17 00:00:00 2001 From: Pl4gue Date: Thu, 21 Dec 2017 12:29:25 +0100 Subject: [PATCH 44/61] Travis build: --- .travis/push.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 .travis/push.sh diff --git a/.travis/push.sh b/.travis/push.sh old mode 100644 new mode 100755 From 23cebf3cc212affec5ebf6ae944191eb3cbcf243 Mon Sep 17 00:00:00 2001 From: Pl4gue Date: Thu, 21 Dec 2017 12:30:04 +0100 Subject: [PATCH 45/61] update push script permissions --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index a5d5a9dca..2f767b547 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,7 @@ script: - npm run builder - npm run webber after_success: + - chmod +x .travis/push.sh - sudo .travis/push.sh env: global: From 09b75542cc3d499a75dd0b8eb21e1a671ec37d92 Mon Sep 17 00:00:00 2001 From: Pl4gue Date: Thu, 21 Dec 2017 12:36:39 +0100 Subject: [PATCH 46/61] test --- .travis/push.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis/push.sh b/.travis/push.sh index 4e577890f..96d1fa2a5 100755 --- a/.travis/push.sh +++ b/.travis/push.sh @@ -12,7 +12,7 @@ commit_website_files() { } upload_files() { - sudo git remote add origin https://${GH_TOKEN}@github.com/Chalarangelo/30-seconds-of-code.git > /dev/null 2>&1 + sudo git remote add origin https://${GH_TOKEN}@github.com/Pl4gue/30-seconds-of-code.git > /dev/null 2>&1 git push --quiet --set-upstream origin master } From dc98127d66c03ec902f606c0d6bb2ff2d32db3bd Mon Sep 17 00:00:00 2001 From: Pl4gue Date: Thu, 21 Dec 2017 12:40:35 +0100 Subject: [PATCH 47/61] update secure PAT --- .travis.yml | 2 +- .travis/push.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2f767b547..7afe5f05b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,4 +14,4 @@ after_success: - sudo .travis/push.sh env: global: - - secure: nwLmj3XjcE4+AQRlph+UWLXItNmPOdh7oVuXEO/rJYIXf9VOiWj6QK3VXX2BLLuDTmzgwvUz+kOB2rtFStoyD70oP255fD/54DhIXrW1br4XlYYHk5mXWF+tiW6iEh7xk7CpY9Tj1x1Y/DOKu5PmZ1CbGGlp5lgPsdBb/QQrkJk36yl/6tES0CBOxuSInde7Xs5sgpQyRa/4VIz0suTmNuGhAZKhdpaXQlPvi8uNr2JGACV7OAHLhySwGCqhuhzdnRXkB2nGhnnwxbY/OYzKDCHoBsA8KWqqyq3ptV3tWzJ2tZDusDG2kXz0DeQquFT5ysDsInSm41Q+7Pw92RPa7+Qjvx0tvjB7YqK0hXpDmgO/DVzbgzW6Wx+X/tUOqkM88CEKqoSisdLiOsCoABuhMojAnZ+TghfIYQ3cm/a5gmMiidbiVm96JPw/ghC5n2K0UlzGK3iBXFn+8+F8XFzGuJ16+z91Nz8ny7SvsCN3EVWRwGTuU9SmxbwpEcIx8c7bkQBElGA/MnzWOOBcJQ3sKeXKYD01Cc6CXXbOb0qckPwU4AM4/qa9pgs2m2xhIM0tHb/cVYOqsD3pIjbgiAG+ySyVJ7QJ5xLZh2zYqXTb1/VRyAXmRHSklEhnHDY8JRTaV4mUk3gEo+8jZJ2GMQxQVY+QwxN2uahPk8wa6nGEKl4= + - secure: E+2E3M4ubbMPgZLlO3uR+2ojE8+5V8vWvh+U3tK6DmLMegGgR14lIYMK7v0RhZ5Oj0stF1lRDLTUrioZwygw4H5D/1bE4H7f92KffopRz8KL/zpvweNcxrAbLpD40WfzCgVlq8A8kM1U9LOVYVNF5s9WUomH6c64bVda72bX0W0lILjoMEroLzFDE4sQ7NFyLnX+S/3xF0b60bvDRLUvdnoDVfNODsXaBwYCFfC2BwdI1tw62KkNG17QM/bL1Gb8OG7vE37OwE9l7NUM3+R1o+YKIGRvIMkyq1msKGfj/pVS8McbA61dYvpuYf9sxvXOgQcbdNn6Gzofs48g2QguNfJuBEv2kohzQ7yQIgBfdzBxBiAPfROJjwzs0PoVZjmCicBMAlZL/unJC3MBKIkawz1vENlnYgM601slR+5od+6IhoVNXA2wlz89+RHQ/Gn9iLlX/611nzgjaObpl6P/8NbwJfUnG5vYcN1MDXpEbsBbb5rUeC0J1FChWV7O5VcgT2/p7Xgc7i9T2H8bSZYjXEhOJ6vWToRTSl0MNUa/PY5+KmNF8HxstTSwhPHF0Eh/tFpprTrBjp0nRNa6wdPhPI8XdnDjqNFw/VTNilutF4RAfwUEBRhZeuK1bNwpuakzwMWGUUazOm+nfxND5i6TYT4haP1iuyv3kVqvgDXgNbY= diff --git a/.travis/push.sh b/.travis/push.sh index 96d1fa2a5..d36981d5e 100755 --- a/.travis/push.sh +++ b/.travis/push.sh @@ -12,7 +12,7 @@ commit_website_files() { } upload_files() { - sudo git remote add origin https://${GH_TOKEN}@github.com/Pl4gue/30-seconds-of-code.git > /dev/null 2>&1 + git remote add origin https://${GH_TOKEN}@github.com/Pl4gue/30-seconds-of-code.git > /dev/null 2>&1 git push --quiet --set-upstream origin master } From 86b3d5a70f57f85dde763433a9330d27ec8f9e80 Mon Sep 17 00:00:00 2001 From: Pl4gue Date: Thu, 21 Dec 2017 12:41:16 +0100 Subject: [PATCH 48/61] force push --- .travis/push.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis/push.sh b/.travis/push.sh index d36981d5e..541f705bd 100755 --- a/.travis/push.sh +++ b/.travis/push.sh @@ -13,7 +13,7 @@ commit_website_files() { upload_files() { git remote add origin https://${GH_TOKEN}@github.com/Pl4gue/30-seconds-of-code.git > /dev/null 2>&1 - git push --quiet --set-upstream origin master + git push --force --quiet --set-upstream origin master } setup_git From 8cc365ee69e9f30087f44e7d10320a5db31f3d04 Mon Sep 17 00:00:00 2001 From: Pl4gue Date: Thu, 21 Dec 2017 12:51:53 +0100 Subject: [PATCH 49/61] fix auth issue(1) --- .travis.yml | 2 +- .travis/push.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7afe5f05b..1a4e59cd1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,4 +14,4 @@ after_success: - sudo .travis/push.sh env: global: - - secure: E+2E3M4ubbMPgZLlO3uR+2ojE8+5V8vWvh+U3tK6DmLMegGgR14lIYMK7v0RhZ5Oj0stF1lRDLTUrioZwygw4H5D/1bE4H7f92KffopRz8KL/zpvweNcxrAbLpD40WfzCgVlq8A8kM1U9LOVYVNF5s9WUomH6c64bVda72bX0W0lILjoMEroLzFDE4sQ7NFyLnX+S/3xF0b60bvDRLUvdnoDVfNODsXaBwYCFfC2BwdI1tw62KkNG17QM/bL1Gb8OG7vE37OwE9l7NUM3+R1o+YKIGRvIMkyq1msKGfj/pVS8McbA61dYvpuYf9sxvXOgQcbdNn6Gzofs48g2QguNfJuBEv2kohzQ7yQIgBfdzBxBiAPfROJjwzs0PoVZjmCicBMAlZL/unJC3MBKIkawz1vENlnYgM601slR+5od+6IhoVNXA2wlz89+RHQ/Gn9iLlX/611nzgjaObpl6P/8NbwJfUnG5vYcN1MDXpEbsBbb5rUeC0J1FChWV7O5VcgT2/p7Xgc7i9T2H8bSZYjXEhOJ6vWToRTSl0MNUa/PY5+KmNF8HxstTSwhPHF0Eh/tFpprTrBjp0nRNa6wdPhPI8XdnDjqNFw/VTNilutF4RAfwUEBRhZeuK1bNwpuakzwMWGUUazOm+nfxND5i6TYT4haP1iuyv3kVqvgDXgNbY= + - secure: "dgdJT6owa/NdtXb+41vDsQPNbNAlela/CyoHrTtJqMZjH3UzoYdqUeMd+qJ+T3+yneUZ3ZPdvdrkGhFX3cHwqFFcShT/9abpXVFMvExE6BHhx7Z/ZSfNRfEsA7uowMd6FrI5QXwRMefP74eUlA2pc0Ky3miwwX1GYLWO0zrGTzwzamjHfLxOOgiln++iqRH1IEejuAnhBK+8WjL8OxP6g0VG6U0ofApf96tnf8Z/4OUDsHlKzUjSuPszJsD1xCXUjx+J/C8fOuGif8b+oXWQPqJVi5E3FKMCoN0wS0XBSch7HNDwq7PhSK7TS6PKP6kn9NtaHo8HAEfzl6w41ilBBZgY6FYjC6qQDVIYjndNxRa5EiHOZUeFG7Ejg+jlSQSaCuvzXHKMtSZoHHboG652IWeXFWEvc+d4fFKWbexAE7k6CuQayPRUzWy1FPqRnTkkKfwCgUW0DHhltQPh3sski1iBOqeNE0vjn4f2nSS36R9jpkVmc+j2YZU6jqGrjavdtXQQmppPEU9O6k6ZNCB5yzPvnM3e9191ujhqC9RJphiEXWMDZ7zmACn1vEp3Py6vRqOu2HBhYbtgd10DGgTtXfvu4GBY7l/AZqoIC+EeFxqFJyryV0cnsEeo19NycnknBD1uK8zbeYPWmjeySVBCyy3gliq/dsxxDMTPBUUSSow=" diff --git a/.travis/push.sh b/.travis/push.sh index 541f705bd..74c171849 100755 --- a/.travis/push.sh +++ b/.travis/push.sh @@ -12,7 +12,7 @@ commit_website_files() { } upload_files() { - git remote add origin https://${GH_TOKEN}@github.com/Pl4gue/30-seconds-of-code.git > /dev/null 2>&1 + git remote add origin https://${GH_TOKEN}@$github.com/Pl4gue/30-seconds-of-code.git > /dev/null 2>&1 git push --force --quiet --set-upstream origin master } From 07ab0267775ec3481a240a2ebd5d9ab6457750eb Mon Sep 17 00:00:00 2001 From: Pl4gue Date: Thu, 21 Dec 2017 12:57:35 +0100 Subject: [PATCH 50/61] Env Key --- .travis.yml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1a4e59cd1..8b83fb40f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,17 +1,17 @@ language: node_js node_js: - - node + - node before_install: - - npm install webber - - npm install builder - - npm install tagger + - npm install webber + - npm install builder + - npm install tagger script: - - npm run tagger - - npm run builder - - npm run webber + - npm run tagger + - npm run builder + - npm run webber after_success: - - chmod +x .travis/push.sh - - sudo .travis/push.sh + - chmod +x .travis/push.sh + - sudo .travis/push.sh env: - global: - - secure: "dgdJT6owa/NdtXb+41vDsQPNbNAlela/CyoHrTtJqMZjH3UzoYdqUeMd+qJ+T3+yneUZ3ZPdvdrkGhFX3cHwqFFcShT/9abpXVFMvExE6BHhx7Z/ZSfNRfEsA7uowMd6FrI5QXwRMefP74eUlA2pc0Ky3miwwX1GYLWO0zrGTzwzamjHfLxOOgiln++iqRH1IEejuAnhBK+8WjL8OxP6g0VG6U0ofApf96tnf8Z/4OUDsHlKzUjSuPszJsD1xCXUjx+J/C8fOuGif8b+oXWQPqJVi5E3FKMCoN0wS0XBSch7HNDwq7PhSK7TS6PKP6kn9NtaHo8HAEfzl6w41ilBBZgY6FYjC6qQDVIYjndNxRa5EiHOZUeFG7Ejg+jlSQSaCuvzXHKMtSZoHHboG652IWeXFWEvc+d4fFKWbexAE7k6CuQayPRUzWy1FPqRnTkkKfwCgUW0DHhltQPh3sski1iBOqeNE0vjn4f2nSS36R9jpkVmc+j2YZU6jqGrjavdtXQQmppPEU9O6k6ZNCB5yzPvnM3e9191ujhqC9RJphiEXWMDZ7zmACn1vEp3Py6vRqOu2HBhYbtgd10DGgTtXfvu4GBY7l/AZqoIC+EeFxqFJyryV0cnsEeo19NycnknBD1uK8zbeYPWmjeySVBCyy3gliq/dsxxDMTPBUUSSow=" + global: + - secure: Zqx82XiLeEuyZXNn3Dzv9Ll+UyldEpE1TjMO+BsUWcw3ZXkJDtROYpaH1reGKoHErCtS4SM0pzuRyLwehl3uFizKrvrC1g/SRdrKFr5YiUDeIssKrGtsHsfwHalkgQAw9OEkzKDKknWF++mPrMdQI8kF0wDKxSAaxqbZNKmXnNgEiToDh0cRE+B5mu5+0k/Lk0hZkSJszcK69xF+03ggq3Xx1uwf6u2L1QQApJyNKcCwp/cc3dCo0bXCtAsPdBO/78PphkNE9e9Mnz7+E3brr8foo70aAUrUoLb7+OAqhvRQl1icjMdSFsXpVCQdajqRA1AT3MBenD/7+JORx5Gt+VRSa8dvuvjuV1PFEBy8AEi8jH7XTtnfMCxYJwyr5m3rkkcMG+qqiGr/EDxrF07sM93QTqN8jcSA9shLaxhIEwujBUInGLLUEDo1mtDQYKF0sa0OrL4vzbcQf0FiANwzZ8Qh++p7WJ0eBgNMtWf33PZDuFOouN+vBxsIYeyh4WE+DMLw9+khKM5CsKpUm8CAPnCDhgBw3tC6G9H5aIhhmysDIlqai6rPS5OjzSyQf/JV8rI0tMS/swE4ydbeUixCTYhJF4puEjlfWAsi3raBSsWSde2IOj3hZ2mwruLc/fT2TY11BeqyOZ4jO/laR3g7oejrY+/cck/9weKrA8XWq3k= From 5dc76515fcf88058d75ca56ee22ead6b85ee232b Mon Sep 17 00:00:00 2001 From: Pl4gue Date: Thu, 21 Dec 2017 12:59:45 +0100 Subject: [PATCH 51/61] update gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 22010c5cb..f30159a31 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ node_modules/ currentSnippet\.js *.md.temp.js .idea +test.sh From 2aa0c8e05382f5be23b5dcd928507b779d03a2ce Mon Sep 17 00:00:00 2001 From: Pl4gue Date: Thu, 21 Dec 2017 13:00:35 +0100 Subject: [PATCH 52/61] Travis build: --- test | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test diff --git a/test b/test new file mode 100644 index 000000000..e69de29bb From 2d20ed7c23909641c9c2e938a319342ef5077438 Mon Sep 17 00:00:00 2001 From: Pl4gue Date: Thu, 21 Dec 2017 13:07:51 +0100 Subject: [PATCH 53/61] update push script --- .travis/push.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis/push.sh b/.travis/push.sh index 74c171849..ae0c2cf53 100755 --- a/.travis/push.sh +++ b/.travis/push.sh @@ -12,8 +12,7 @@ commit_website_files() { } upload_files() { - git remote add origin https://${GH_TOKEN}@$github.com/Pl4gue/30-seconds-of-code.git > /dev/null 2>&1 - git push --force --quiet --set-upstream origin master + git push --force --quiet "https://${GH_TOKEN}@github.com/Chalarangelo/30-seconds-of-code.git" master > /dev/null 2>&1 } setup_git From adee86dc6ac749f1c500704c2d847de8c4a76513 Mon Sep 17 00:00:00 2001 From: Pl4gue Date: Thu, 21 Dec 2017 12:10:08 +0000 Subject: [PATCH 54/61] Travis build: 11 --- README.md | 2 +- docs/mini.css | 2 +- package-lock.json | 86 ++++++ package.json | 5 +- yarn.lock | 734 ++++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 800 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index d48327a92..7f7d9a56d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![Logo](/logo.png) -# 30 seconds of code [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/30-seconds-of-code/Lobby) +# 30 seconds of code [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/30-seconds-of-code/Lobby) ![Travis Build](https://travis-ci.org/Chalarangelo/30-seconds-of-code.svg?branch=master) > Curated collection of useful Javascript snippets that you can understand in 30 seconds or less. - Use Ctrl + F or command + F to search for a snippet. diff --git a/docs/mini.css b/docs/mini.css index bf798f86c..8d909e24c 100644 --- a/docs/mini.css +++ b/docs/mini.css @@ -1 +1 @@ -:root{--fore-color:#111;--secondary-fore-color:#444;--back-color:#f8f8f8;--secondary-back-color:#f0f0f0;--blockquote-color:#f57c00;--pre-color:#1565c0;--border-color:#aaa;--secondary-border-color:#ddd;--heading-ratio:1.19;--universal-margin:.5rem;--universal-padding:.5rem;--universal-border-radius:.125rem;--a-link-color:#0277bd;--a-visited-color:#01579b}html{font-size:16px}a,b,del,em,i,ins,q,span,strong,u{font-size:1em}html,*{font-family:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, "Helvetica Neue", Helvetica, sans-serif;line-height:1.5;-webkit-text-size-adjust:100%}*{font-size:1rem}body{margin:0;color:var(--fore-color);background:var(--back-color)}details{display:block}summary{display:list-item}abbr[title]{border-bottom:none;text-decoration:underline dotted}input{overflow:visible}img{max-width:100%;height:auto}h1,h2,h3,h4,h5,h6{line-height:1.2;margin:calc(1.5 * var(--universal-margin)) var(--universal-margin);font-weight:500}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{color:var(--secondary-fore-color);display:block;margin-top:-.25rem}h1{font-size:calc(1rem * var(--heading-ratio) * var(--heading-ratio) * var(--heading-ratio) * var(--heading-ratio))}h2{font-size:calc(1rem * var(--heading-ratio) * var(--heading-ratio) * var(--heading-ratio))}h3{font-size:calc(1rem * var(--heading-ratio) * var(--heading-ratio))}h4{font-size:calc(1rem * var(--heading-ratio))}h5{font-size:1rem}h6{font-size:calc(1rem / var(--heading-ratio))}p{margin:var(--universal-margin)}ol,ul{margin:var(--universal-margin);padding-left:calc(2 * var(--universal-margin))}b,strong{font-weight:700}hr{box-sizing:content-box;border:0;line-height:1.25em;margin:var(--universal-margin);height:.0625rem;background:linear-gradient(to right, transparent, var(--border-color) 20%, var(--border-color) 80%, transparent)}blockquote{display:block;position:relative;font-style:italic;color:var(--secondary-fore-color);margin:var(--universal-margin);padding:calc(3 * var(--universal-padding));border:.0625rem solid var(--secondary-border-color);border-left:.375rem solid var(--blockquote-color);border-radius:0 var(--universal-border-radius) var(--universal-border-radius) 0}blockquote:before{position:absolute;top:calc(0rem - var(--universal-padding));left:0;font-family:sans-serif;font-size:3rem;font-weight:700;content:"\201c";color:var(--blockquote-color)}blockquote[cite]:after{font-style:normal;font-size:.75em;font-weight:700;content:"\a— " attr(cite);white-space:pre}code,kbd,pre,samp{font-family:Menlo, Consolas, monospace;font-size:.85em}code{background:var(--secondary-back-color);border-radius:var(--universal-border-radius);padding:calc(var(--universal-padding) / 4) calc(var(--universal-padding) / 2)}kbd{background:var(--fore-color);color:var(--back-color);border-radius:var(--universal-border-radius);padding:calc(var(--universal-padding) / 4) calc(var(--universal-padding) / 2)}pre{overflow:auto;background:var(--secondary-back-color);padding:calc(1.5 * var(--universal-padding));margin:var(--universal-margin);border:.0625rem solid var(--secondary-border-color);border-left:.25rem solid var(--pre-color);border-radius:0 var(--universal-border-radius) var(--universal-border-radius) 0}sup,sub,code,kbd{line-height:0;position:relative;vertical-align:baseline}small,sup,sub,figcaption{font-size:.75em}sup{top:-.5em}sub{bottom:-.25em}figure{margin:var(--universal-margin)}figcaption{color:var(--secondary-fore-color)}a{text-decoration:none}a:link{color:var(--a-link-color)}a:visited{color:var(--a-visited-color)}a:hover,a:focus{text-decoration:underline}.container{margin:0 auto;padding:0 calc(1.5 * var(--universal-padding))}.row{box-sizing:border-box;display:flex;flex:0 1 auto;flex-flow:row wrap}.col-sm,[class^='col-sm-'],[class^='col-sm-offset-'],.row[class*='cols-sm-']>*{box-sizing:border-box;flex:0 0 auto;padding:0 calc(var(--universal-padding) / 2)}.col-sm,.row.cols-sm>*{max-width:100%;flex-grow:1;flex-basis:0}.col-sm-1,.row.cols-sm-1>*{max-width:8.33333%;flex-basis:8.33333%}.col-sm-offset-0{margin-left:0}.col-sm-2,.row.cols-sm-2>*{max-width:16.66667%;flex-basis:16.66667%}.col-sm-offset-1{margin-left:8.33333%}.col-sm-3,.row.cols-sm-3>*{max-width:25%;flex-basis:25%}.col-sm-offset-2{margin-left:16.66667%}.col-sm-4,.row.cols-sm-4>*{max-width:33.33333%;flex-basis:33.33333%}.col-sm-offset-3{margin-left:25%}.col-sm-5,.row.cols-sm-5>*{max-width:41.66667%;flex-basis:41.66667%}.col-sm-offset-4{margin-left:33.33333%}.col-sm-6,.row.cols-sm-6>*{max-width:50%;flex-basis:50%}.col-sm-offset-5{margin-left:41.66667%}.col-sm-7,.row.cols-sm-7>*{max-width:58.33333%;flex-basis:58.33333%}.col-sm-offset-6{margin-left:50%}.col-sm-8,.row.cols-sm-8>*{max-width:66.66667%;flex-basis:66.66667%}.col-sm-offset-7{margin-left:58.33333%}.col-sm-9,.row.cols-sm-9>*{max-width:75%;flex-basis:75%}.col-sm-offset-8{margin-left:66.66667%}.col-sm-10,.row.cols-sm-10>*{max-width:83.33333%;flex-basis:83.33333%}.col-sm-offset-9{margin-left:75%}.col-sm-11,.row.cols-sm-11>*{max-width:91.66667%;flex-basis:91.66667%}.col-sm-offset-10{margin-left:83.33333%}.col-sm-12,.row.cols-sm-12>*{max-width:100%;flex-basis:100%}.col-sm-offset-11{margin-left:91.66667%}.col-sm-normal{order:initial}.col-sm-first{order:-999}.col-sm-last{order:999}@media screen and (min-width: 768px){.col-md,[class^='col-md-'],[class^='col-md-offset-'],.row[class*='cols-md-']>*{box-sizing:border-box;flex:0 0 auto;padding:0 calc(var(--universal-padding) / 2)}.col-md,.row.cols-md>*{max-width:100%;flex-grow:1;flex-basis:0}.col-md-1,.row.cols-md-1>*{max-width:8.33333%;flex-basis:8.33333%}.col-md-offset-0{margin-left:0}.col-md-2,.row.cols-md-2>*{max-width:16.66667%;flex-basis:16.66667%}.col-md-offset-1{margin-left:8.33333%}.col-md-3,.row.cols-md-3>*{max-width:25%;flex-basis:25%}.col-md-offset-2{margin-left:16.66667%}.col-md-4,.row.cols-md-4>*{max-width:33.33333%;flex-basis:33.33333%}.col-md-offset-3{margin-left:25%}.col-md-5,.row.cols-md-5>*{max-width:41.66667%;flex-basis:41.66667%}.col-md-offset-4{margin-left:33.33333%}.col-md-6,.row.cols-md-6>*{max-width:50%;flex-basis:50%}.col-md-offset-5{margin-left:41.66667%}.col-md-7,.row.cols-md-7>*{max-width:58.33333%;flex-basis:58.33333%}.col-md-offset-6{margin-left:50%}.col-md-8,.row.cols-md-8>*{max-width:66.66667%;flex-basis:66.66667%}.col-md-offset-7{margin-left:58.33333%}.col-md-9,.row.cols-md-9>*{max-width:75%;flex-basis:75%}.col-md-offset-8{margin-left:66.66667%}.col-md-10,.row.cols-md-10>*{max-width:83.33333%;flex-basis:83.33333%}.col-md-offset-9{margin-left:75%}.col-md-11,.row.cols-md-11>*{max-width:91.66667%;flex-basis:91.66667%}.col-md-offset-10{margin-left:83.33333%}.col-md-12,.row.cols-md-12>*{max-width:100%;flex-basis:100%}.col-md-offset-11{margin-left:91.66667%}.col-md-normal{order:initial}.col-md-first{order:-999}.col-md-last{order:999}}@media screen and (min-width: 1280px){.col-lg,[class^='col-lg-'],[class^='col-lg-offset-'],.row[class*='cols-lg-']>*{box-sizing:border-box;flex:0 0 auto;padding:0 calc(var(--universal-padding) / 2)}.col-lg,.row.cols-lg>*{max-width:100%;flex-grow:1;flex-basis:0}.col-lg-1,.row.cols-lg-1>*{max-width:8.33333%;flex-basis:8.33333%}.col-lg-offset-0{margin-left:0}.col-lg-2,.row.cols-lg-2>*{max-width:16.66667%;flex-basis:16.66667%}.col-lg-offset-1{margin-left:8.33333%}.col-lg-3,.row.cols-lg-3>*{max-width:25%;flex-basis:25%}.col-lg-offset-2{margin-left:16.66667%}.col-lg-4,.row.cols-lg-4>*{max-width:33.33333%;flex-basis:33.33333%}.col-lg-offset-3{margin-left:25%}.col-lg-5,.row.cols-lg-5>*{max-width:41.66667%;flex-basis:41.66667%}.col-lg-offset-4{margin-left:33.33333%}.col-lg-6,.row.cols-lg-6>*{max-width:50%;flex-basis:50%}.col-lg-offset-5{margin-left:41.66667%}.col-lg-7,.row.cols-lg-7>*{max-width:58.33333%;flex-basis:58.33333%}.col-lg-offset-6{margin-left:50%}.col-lg-8,.row.cols-lg-8>*{max-width:66.66667%;flex-basis:66.66667%}.col-lg-offset-7{margin-left:58.33333%}.col-lg-9,.row.cols-lg-9>*{max-width:75%;flex-basis:75%}.col-lg-offset-8{margin-left:66.66667%}.col-lg-10,.row.cols-lg-10>*{max-width:83.33333%;flex-basis:83.33333%}.col-lg-offset-9{margin-left:75%}.col-lg-11,.row.cols-lg-11>*{max-width:91.66667%;flex-basis:91.66667%}.col-lg-offset-10{margin-left:83.33333%}.col-lg-12,.row.cols-lg-12>*{max-width:100%;flex-basis:100%}.col-lg-offset-11{margin-left:91.66667%}.col-lg-normal{order:initial}.col-lg-first{order:-999}.col-lg-last{order:999}}:root{--card-back-color:#f8f8f8;--card-fore-color:#111;--card-border-color:#ddd}.card{display:flex;flex-direction:column;justify-content:space-between;align-self:center;position:relative;width:100%;background:var(--card-back-color);color:var(--card-fore-color);border:.0625rem solid var(--card-border-color);border-radius:var(--universal-border-radius);margin:var(--universal-margin);overflow:hidden}@media screen and (min-width: 320px){.card{max-width:320px}}.card>.section{background:var(--card-back-color);color:var(--card-fore-color);box-sizing:border-box;margin:0;border:0;border-radius:0;border-bottom:.0625rem solid var(--card-border-color);padding:var(--universal-padding);width:100%}.card>.section.media{height:200px;padding:0;-o-object-fit:cover;object-fit:cover}.card>.section:last-child{border-bottom:0}@media screen and (min-width: 240px){.card.small{max-width:240px}}@media screen and (min-width: 480px){.card.large{max-width:480px}}.card.fluid{max-width:100%;width:auto}.card.warning{--card-back-color:#ffca28;--card-border-color:#e8b825}.card.error{--card-back-color:#b71c1c;--card-fore-color:#f8f8f8;--card-border-color:#a71a1a}.card>.section.dark{--card-back-color:#e0e0e0}.card>.section.double-padded{padding:calc(1.5 * var(--universal-padding))}:root{--form-back-color:#f0f0f0;--form-fore-color:#111;--form-border-color:#ddd;--input-back-color:#f8f8f8;--input-fore-color:#111;--input-border-color:#ddd;--input-focus-color:#0288d1;--input-invalid-color:#d32f2f;--button-back-color:#e2e2e2;--button-hover-back-color:#dcdcdc;--button-fore-color:#212121;--button-border-color:transparent;--button-hover-border-color:transparent;--button-group-border-color:rgba(124,124,124,0.54)}form{background:var(--form-back-color);color:var(--form-fore-color);border:.0625rem solid var(--form-border-color);border-radius:var(--universal-border-radius);margin:var(--universal-margin);padding:calc(2 * var(--universal-padding)) var(--universal-padding)}fieldset{border:.0625rem solid var(--form-border-color);border-radius:var(--universal-border-radius);margin:calc(var(--universal-margin) / 4);padding:var(--universal-padding)}legend{box-sizing:border-box;display:table;max-width:100%;white-space:normal;font-weight:700;padding:calc(var(--universal-padding) / 2)}label{padding:calc(var(--universal-padding) / 2) var(--universal-padding)}.input-group{display:inline-block}.input-group.fluid{display:flex;align-items:center;justify-content:center}.input-group.fluid>input{max-width:100%;flex-grow:1;flex-basis:0px}@media screen and (max-width: 767px){.input-group.fluid{align-items:stretch;flex-direction:column}}.input-group.vertical{display:flex;align-items:stretch;flex-direction:column}.input-group.vertical>input{max-width:100%;flex-grow:1;flex-basis:0px}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{-webkit-appearance:textfield;outline-offset:-2px}[type="search"]::-webkit-search-cancel-button,[type="search"]::-webkit-search-decoration{-webkit-appearance:none}input:not([type]),[type="text"],[type="email"],[type="number"],[type="search"],[type="password"],[type="url"],[type="tel"],[type="checkbox"],[type="radio"],textarea,select{box-sizing:border-box;background:var(--input-back-color);color:var(--input-fore-color);border:.0625rem solid var(--input-border-color);border-radius:var(--universal-border-radius);margin:calc(var(--universal-margin) / 2);padding:var(--universal-padding) calc(1.5 * var(--universal-padding))}input:not([type="button"]):not([type="submit"]):not([type="reset"]):hover,input:not([type="button"]):not([type="submit"]):not([type="reset"]):focus,textarea:hover,textarea:focus,select:hover,select:focus{border-color:var(--input-focus-color);box-shadow:none}input:not([type="button"]):not([type="submit"]):not([type="reset"]):invalid,input:not([type="button"]):not([type="submit"]):not([type="reset"]):focus:invalid,textarea:invalid,textarea:focus:invalid,select:invalid,select:focus:invalid{border-color:var(--input-invalid-color);box-shadow:none}input:not([type="button"]):not([type="submit"]):not([type="reset"])[readonly],textarea[readonly],select[readonly]{background:var(--secondary-back-color)}select{max-width:100%}option{overflow:hidden;text-overflow:ellipsis}[type="checkbox"],[type="radio"]{-webkit-appearance:none;-moz-appearance:none;appearance:none;position:relative;height:calc(1rem + var(--universal-padding) / 2);width:calc(1rem + var(--universal-padding) / 2);vertical-align:text-bottom;padding:0;flex-basis:calc(1rem + var(--universal-padding) / 2) !important;flex-grow:0 !important}[type="checkbox"]:checked:before,[type="radio"]:checked:before{position:absolute}[type="checkbox"]:checked:before{content:'\2713';font-family:sans-serif;font-size:calc(1rem + var(--universal-padding) / 2);top:calc(0rem - var(--universal-padding));left:calc(var(--universal-padding) / 4)}[type="radio"]{border-radius:100%}[type="radio"]:checked:before{border-radius:100%;content:'';top:calc(.0625rem + var(--universal-padding) / 2);left:calc(.0625rem + var(--universal-padding) / 2);background:var(--input-fore-color);width:0.5rem;height:0.5rem}:placeholder-shown{color:var(--input-fore-color)}::-ms-placeholder{color:var(--input-fore-color);opacity:0.54}button::-moz-focus-inner,[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner{border-style:none;padding:0}button,html [type="button"],[type="reset"],[type="submit"]{-webkit-appearance:button}button{overflow:visible;text-transform:none}button,[type="button"],[type="submit"],[type="reset"],a.button,label.button,.button,a[role="button"],label[role="button"],[role="button"]{display:inline-block;background:var(--button-back-color);color:var(--button-fore-color);border:.0625rem solid var(--button-border-color);border-radius:var(--universal-border-radius);padding:var(--universal-padding) calc(1.5 * var(--universal-padding));margin:var(--universal-margin);text-decoration:none;cursor:pointer;transition:background 0.3s}button:hover,button:focus,[type="button"]:hover,[type="button"]:focus,[type="submit"]:hover,[type="submit"]:focus,[type="reset"]:hover,[type="reset"]:focus,a.button:hover,a.button:focus,label.button:hover,label.button:focus,.button:hover,.button:focus,a[role="button"]:hover,a[role="button"]:focus,label[role="button"]:hover,label[role="button"]:focus,[role="button"]:hover,[role="button"]:focus{background:var(--button-hover-back-color);border-color:var(--button-hover-border-color)}input:disabled,input[disabled],textarea:disabled,textarea[disabled],select:disabled,select[disabled],button:disabled,button[disabled],.button:disabled,.button[disabled],[role="button"]:disabled,[role="button"][disabled]{cursor:not-allowed;opacity:.75}.button-group{display:flex;border:.0625rem solid var(--button-group-border-color);border-radius:var(--universal-border-radius);margin:var(--universal-margin)}.button-group>button,.button-group [type="button"],.button-group>[type="submit"],.button-group>[type="reset"],.button-group>.button,.button-group>[role="button"]{margin:0;max-width:100%;flex:1 1 auto;text-align:center;border:0;border-radius:0;box-shadow:none}.button-group>:not(:first-child){border-left:.0625rem solid var(--button-group-border-color)}@media screen and (max-width: 767px){.button-group{flex-direction:column}.button-group>:not(:first-child){border:0;border-top:.0625rem solid var(--button-group-border-color)}}button.primary,[type="button"].primary,[type="submit"].primary,[type="reset"].primary,.button.primary,[role="button"].primary{--button-back-color:#1976d2;--button-fore-color:#f8f8f8}button.primary:hover,button.primary:focus,[type="button"].primary:hover,[type="button"].primary:focus,[type="submit"].primary:hover,[type="submit"].primary:focus,[type="reset"].primary:hover,[type="reset"].primary:focus,.button.primary:hover,.button.primary:focus,[role="button"].primary:hover,[role="button"].primary:focus{--button-hover-back-color:#1565c0}button.secondary,[type="button"].secondary,[type="submit"].secondary,[type="reset"].secondary,.button.secondary,[role="button"].secondary{--button-back-color:#d32f2f;--button-fore-color:#f8f8f8}button.secondary:hover,button.secondary:focus,[type="button"].secondary:hover,[type="button"].secondary:focus,[type="submit"].secondary:hover,[type="submit"].secondary:focus,[type="reset"].secondary:hover,[type="reset"].secondary:focus,.button.secondary:hover,.button.secondary:focus,[role="button"].secondary:hover,[role="button"].secondary:focus{--button-hover-back-color:#c62828}button.tertiary,[type="button"].tertiary,[type="submit"].tertiary,[type="reset"].tertiary,.button.tertiary,[role="button"].tertiary{--button-back-color:#308732;--button-fore-color:#f8f8f8}button.tertiary:hover,button.tertiary:focus,[type="button"].tertiary:hover,[type="button"].tertiary:focus,[type="submit"].tertiary:hover,[type="submit"].tertiary:focus,[type="reset"].tertiary:hover,[type="reset"].tertiary:focus,.button.tertiary:hover,.button.tertiary:focus,[role="button"].tertiary:hover,[role="button"].tertiary:focus{--button-hover-back-color:#277529}button.inverse,[type="button"].inverse,[type="submit"].inverse,[type="reset"].inverse,.button.inverse,[role="button"].inverse{--button-back-color:#212121;--button-fore-color:#f8f8f8}button.inverse:hover,button.inverse:focus,[type="button"].inverse:hover,[type="button"].inverse:focus,[type="submit"].inverse:hover,[type="submit"].inverse:focus,[type="reset"].inverse:hover,[type="reset"].inverse:focus,.button.inverse:hover,.button.inverse:focus,[role="button"].inverse:hover,[role="button"].inverse:focus{--button-hover-back-color:#111}button.small,[type="button"].small,[type="submit"].small,[type="reset"].small,.button.small,[role="button"].small{padding:calc(0.5 * var(--universal-padding)) calc(0.75 * var(--universal-padding));margin:var(--universal-margin)}button.large,[type="button"].large,[type="submit"].large,[type="reset"].large,.button.large,[role="button"].large{padding:calc(1.5 * var(--universal-padding)) calc(2 * var(--universal-padding));margin:var(--universal-margin)}:root{--header-back-color:#f8f8f8;--header-hover-back-color:#f0f0f0;--header-fore-color:#444;--header-border-color:#ddd;--nav-back-color:#f8f8f8;--nav-hover-back-color:#f0f0f0;--nav-fore-color:#444;--nav-border-color:#ddd;--nav-link-color:#0277bd;--footer-fore-color:#444;--footer-back-color:#f8f8f8;--footer-border-color:#ddd;--footer-link-color:#0277bd;--drawer-back-color:#f8f8f8;--drawer-hover-back-color:#f0f0f0;--drawer-border-color:#ddd;--drawer-close-color:#444}header{height:3.1875rem;background:var(--header-back-color);color:var(--header-fore-color);border-bottom:.0625rem solid var(--header-border-color);padding:calc(var(--universal-padding) / 4) 0;white-space:nowrap;overflow-x:auto;overflow-y:hidden}header.row{box-sizing:content-box}header .logo{color:var(--header-fore-color);font-size:1.75rem;padding:var(--universal-padding) calc(2 * var(--universal-padding));text-decoration:none}header button,header [type="button"],header .button,header [role="button"]{box-sizing:border-box;position:relative;top:calc(0rem - var(--universal-padding) / 4);height:calc(3.1875rem + var(--universal-padding) / 2);background:var(--header-back-color);line-height:calc(3.1875rem - var(--universal-padding) * 1.5);text-align:center;color:var(--header-fore-color);border:0;border-radius:0;margin:0;text-transform:uppercase}header button:hover,header button:focus,header [type="button"]:hover,header [type="button"]:focus,header .button:hover,header .button:focus,header [role="button"]:hover,header [role="button"]:focus{background:var(--header-hover-back-color)}nav{background:var(--nav-back-color);color:var(--nav-fore-color);border:.0625rem solid var(--nav-border-color);border-radius:var(--universal-border-radius);margin:var(--universal-margin)}nav *{padding:var(--universal-padding) calc(1.5 * var(--universal-padding))}nav a,nav a:visited{display:block;color:var(--nav-link-color);border-radius:var(--universal-border-radius);transition:background 0.3s}nav a:hover,nav a:focus,nav a:visited:hover,nav a:visited:focus{text-decoration:none;background:var(--nav-hover-back-color)}nav .sublink-1{position:relative;margin-left:calc(2 * var(--universal-padding))}nav .sublink-1:before{position:absolute;left:calc(var(--universal-padding) - 1 * var(--universal-padding));top:-.0625rem;content:'';height:100%;border:.0625rem solid var(--nav-border-color);border-left:0}nav .sublink-2{position:relative;margin-left:calc(4 * var(--universal-padding))}nav .sublink-2:before{position:absolute;left:calc(var(--universal-padding) - 3 * var(--universal-padding));top:-.0625rem;content:'';height:100%;border:.0625rem solid var(--nav-border-color);border-left:0}footer{background:var(--footer-back-color);color:var(--footer-fore-color);border-top:.0625rem solid var(--footer-border-color);padding:calc(2 * var(--universal-padding)) var(--universal-padding);font-size:.875rem}footer a,footer a:visited{color:var(--footer-link-color)}header.sticky{position:-webkit-sticky;position:sticky;z-index:1101;top:0}footer.sticky{position:-webkit-sticky;position:sticky;z-index:1101;bottom:0}.drawer-toggle:before{display:inline-block;position:relative;vertical-align:bottom;content:'\00a0\2261\00a0';font-family:sans-serif;font-size:1.5em}@media screen and (min-width: 768px){.drawer-toggle:not(.persistent){display:none}}[type="checkbox"].drawer{height:1px;width:1px;margin:-1px;overflow:hidden;position:absolute;clip:rect(0 0 0 0);-webkit-clip-path:inset(100%);clip-path:inset(100%)}[type="checkbox"].drawer+*{display:block;box-sizing:border-box;position:fixed;top:0;width:320px;height:100vh;overflow-y:auto;background:var(--drawer-back-color);border:.0625rem solid var(--drawer-border-color);border-radius:0;margin:0;z-index:1110;left:-320px;transition:left 0.3s}[type="checkbox"].drawer+* .drawer-close{position:absolute;top:var(--universal-margin);right:var(--universal-margin);z-index:1111;width:2rem;height:2rem;border-radius:var(--universal-border-radius);padding:var(--universal-padding);margin:0;cursor:pointer;transition:background 0.3s}[type="checkbox"].drawer+* .drawer-close:before{display:block;content:'\00D7';color:var(--drawer-close-color);position:relative;font-family:sans-serif;font-size:2rem;line-height:1;text-align:center}[type="checkbox"].drawer+* .drawer-close:hover,[type="checkbox"].drawer+* .drawer-close:focus{background:var(--drawer-hover-back-color)}@media screen and (max-width: 320px){[type="checkbox"].drawer+*{width:100%}}[type="checkbox"].drawer:checked+*{left:0}@media screen and (min-width: 768px){[type="checkbox"].drawer:not(.persistent)+*{position:static;height:100%;z-index:1100}[type="checkbox"].drawer:not(.persistent)+* .drawer-close{display:none}}:root{--mark-back-color:#0277bd;--mark-fore-color:#fafafa}mark{background:var(--mark-back-color);color:var(--mark-fore-color);font-size:.95em;line-height:1em;border-radius:var(--universal-border-radius);padding:calc(var(--universal-padding) / 4) calc(var(--universal-padding) / 2)}mark.inline-block{display:inline-block;font-size:1em;line-height:1.5;padding:calc(var(--universal-padding) / 2) var(--universal-padding)}:root{--toast-back-color:#424242;--toast-fore-color:#fafafa}.toast{position:fixed;bottom:calc(var(--universal-margin) * 3);left:50%;transform:translate(-50%, -50%);z-index:1111;color:var(--toast-fore-color);background:var(--toast-back-color);border-radius:calc(var(--universal-border-radius) * 16);padding:var(--universal-padding) calc(var(--universal-padding) * 3)}:root{--tooltip-back-color:#212121;--tooltip-fore-color:#fafafa}.tooltip{position:relative;display:inline-block}.tooltip:before,.tooltip:after{position:absolute;opacity:0;clip:rect(0 0 0 0);-webkit-clip-path:inset(100%);clip-path:inset(100%);transition:all 0.3s;z-index:1010;left:50%}.tooltip:not(.bottom):before,.tooltip:not(.bottom):after{bottom:75%}.tooltip.bottom:before,.tooltip.bottom:after{top:75%}.tooltip:hover:before,.tooltip:hover:after,.tooltip:focus:before,.tooltip:focus:after{opacity:1;clip:auto;-webkit-clip-path:inset(0%);clip-path:inset(0%)}.tooltip:before{content:'';background:transparent;border:var(--universal-margin) solid transparent;left:calc(50% - var(--universal-margin))}.tooltip:not(.bottom):before{border-top-color:#212121}.tooltip.bottom:before{border-bottom-color:#212121}.tooltip:after{content:attr(aria-label);color:var(--tooltip-fore-color);background:var(--tooltip-back-color);border-radius:var(--universal-border-radius);padding:var(--universal-padding);white-space:nowrap;transform:translateX(-50%)}.tooltip:not(.bottom):after{margin-bottom:calc(2 * var(--universal-margin))}.tooltip.bottom:after{margin-top:calc(2 * var(--universal-margin))}:root{--modal-overlay-color:rgba(0,0,0,0.45);--modal-close-color:#444;--modal-close-hover-color:#f0f0f0}[type="checkbox"].modal{height:1px;width:1px;margin:-1px;overflow:hidden;position:absolute;clip:rect(0 0 0 0);-webkit-clip-path:inset(100%);clip-path:inset(100%)}[type="checkbox"].modal+div{position:fixed;top:0;left:0;display:none;width:100vw;height:100vh;background:var(--modal-overlay-color)}[type="checkbox"].modal+div .card{margin:0 auto;max-height:50vh;overflow:auto}[type="checkbox"].modal+div .card .modal-close{position:absolute;top:0;right:0;width:1.75rem;height:1.75rem;border-radius:var(--universal-border-radius);padding:var(--universal-padding);margin:0;cursor:pointer;transition:background 0.3s}[type="checkbox"].modal+div .card .modal-close:before{display:block;content:'\00D7';color:var(--modal-close-color);position:relative;font-family:sans-serif;font-size:1.75rem;line-height:1;text-align:center}[type="checkbox"].modal+div .card .modal-close:hover,[type="checkbox"].modal+div .card .modal-close:focus{background:var(--modal-close-hover-color)}[type="checkbox"].modal:checked+div{display:flex;flex:0 1 auto;z-index:1200}[type="checkbox"].modal:checked+div .card .modal-close{z-index:1211}:root{--collapse-label-back-color:#e8e8e8;--collapse-label-fore-color:#212121;--collapse-label-hover-back-color:#f0f0f0;--collapse-selected-label-back-color:#ececec;--collapse-border-color:#ddd;--collapse-content-back-color:#fafafa;--collapse-selected-label-border-color:#0277bd}.collapse{width:calc(100% - 2 * var(--universal-margin));opacity:1;display:flex;flex-direction:column;margin:var(--universal-margin);border-radius:var(--universal-border-radius)}.collapse>[type="radio"],.collapse>[type="checkbox"]{height:1px;width:1px;margin:-1px;overflow:hidden;position:absolute;clip:rect(0 0 0 0);-webkit-clip-path:inset(100%);clip-path:inset(100%)}.collapse>label{flex-grow:1;display:inline-block;height:1.5rem;cursor:pointer;transition:background 0.3s;color:var(--collapse-label-fore-color);background:var(--collapse-label-back-color);border:.0625rem solid var(--collapse-border-color);padding:calc(1.5 * var(--universal-padding))}.collapse>label:hover,.collapse>label:focus{background:var(--collapse-label-hover-back-color)}.collapse>label+div{flex-basis:auto;height:1px;width:1px;margin:-1px;overflow:hidden;position:absolute;clip:rect(0 0 0 0);-webkit-clip-path:inset(100%);clip-path:inset(100%);transition:max-height 0.3s;max-height:1px}.collapse>:checked+label{background:var(--collapse-selected-label-back-color);border-bottom-color:var(--collapse-selected-label-border-color)}.collapse>:checked+label+div{box-sizing:border-box;position:relative;width:100%;height:auto;overflow:auto;margin:0;background:var(--collapse-content-back-color);border:.0625rem solid var(--collapse-border-color);border-top:0;padding:var(--universal-padding);clip:auto;-webkit-clip-path:inset(0%);clip-path:inset(0%);max-height:400px}.collapse>label:not(:first-of-type){border-top:0}.collapse>label:first-of-type{border-radius:var(--universal-border-radius) var(--universal-border-radius) 0 0}.collapse>label:last-of-type{border-radius:0 0 var(--universal-border-radius) var(--universal-border-radius)}.collapse>:checked:last-of-type+label{border-radius:0}.collapse>:checked:last-of-type+label+div{border-radius:0 0 var(--universal-border-radius) var(--universal-border-radius)}mark.secondary{--mark-back-color:#d32f2f}mark.tertiary{--mark-back-color:#308732}mark.tag{padding:calc(var(--universal-padding)/2) var(--universal-padding);border-radius:1em}html,*{font-family:'Poppins', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, "Helvetica Neue", Helvetica, sans-serif}code,pre,kbd,code *,pre *,kbd *{font-family:'Inconsolata', Menlo, Consolas, monospace}code,kbd{font-size:1em}code{transform:scale(1)}pre{font-size:1rem;border:0.0625rem solid var(--secondary-border-color);border-radius:var(--universal-border-radius)}.group{position:relative;margin-top:2em;margin-bottom:-1em}.search{font-size:14px;margin-top:-.1em;display:block;width:100%;border:none;border-bottom:1px solid var(--nav-link-color)}.search:focus{outline:none}label#search-label{color:var(--nav-link-color);font-size:18px;font-weight:400;position:absolute;left:5px;top:10px}.search:focus ~ label#search-label,.search:valid ~ label#search-label{top:-20px;font-size:14px;color:var(--nav-link-color)}label#menu-toggle{width:3.4375rem}header h1.logo{margin-top:-0.8rem;text-align:center}header h1.logo a{text-decoration:none;color:#111}header #title{position:relative;top:-1rem}@media screen and (max-width: 500px){header #title{font-size:1rem;display:block}}header h1 small{display:block;font-size:0.875rem;font-style:italic;color:#888;margin-top:-0.8rem}@media screen and (max-width: 768px){header h1 small{font-size:0.75rem}}@media screen and (max-width: 600px){header h1 small{font-size:0.625rem}}@media screen and (max-width: 500px){header h1 small{font-size:0.5rem;margin-top:-1.2rem}}label#menu-toggle{position:absolute;left:0.5rem;top:0.5rem;width:3.4375rem}.card{box-shadow:0 0.25rem 0.25rem 0 rgba(0,0,0,0.125),0 0.125rem 0.125rem -0.125rem rgba(0,0,0,0.25)} +:root{--fore-color:#111;--secondary-fore-color:#444;--back-color:#f8f8f8;--secondary-back-color:#f0f0f0;--blockquote-color:#f57c00;--pre-color:#1565c0;--border-color:#aaa;--secondary-border-color:#ddd;--heading-ratio:1.19;--universal-margin:.5rem;--universal-padding:.5rem;--universal-border-radius:.125rem;--a-link-color:#0277bd;--a-visited-color:#01579b}html{font-size:16px}a,b,del,em,i,ins,q,span,strong,u{font-size:1em}html,*{font-family:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, "Helvetica Neue", Helvetica, sans-serif;line-height:1.5;-webkit-text-size-adjust:100%}*{font-size:1rem}body{margin:0;color:var(--fore-color);background:var(--back-color)}details{display:block}summary{display:list-item}abbr[title]{border-bottom:none;text-decoration:underline dotted}input{overflow:visible}img{max-width:100%;height:auto}h1,h2,h3,h4,h5,h6{line-height:1.2;margin:calc(1.5 * var(--universal-margin)) var(--universal-margin);font-weight:500}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{color:var(--secondary-fore-color);display:block;margin-top:-.25rem}h1{font-size:calc(1rem * var(--heading-ratio) * var(--heading-ratio) * var(--heading-ratio) * var(--heading-ratio))}h2{font-size:calc(1rem * var(--heading-ratio) * var(--heading-ratio) * var(--heading-ratio))}h3{font-size:calc(1rem * var(--heading-ratio) * var(--heading-ratio))}h4{font-size:calc(1rem * var(--heading-ratio))}h5{font-size:1rem}h6{font-size:calc(1rem / var(--heading-ratio))}p{margin:var(--universal-margin)}ol,ul{margin:var(--universal-margin);padding-left:calc(2 * var(--universal-margin))}b,strong{font-weight:700}hr{box-sizing:content-box;border:0;line-height:1.25em;margin:var(--universal-margin);height:.0625rem;background:linear-gradient(to right, transparent, var(--border-color) 20%, var(--border-color) 80%, transparent)}blockquote{display:block;position:relative;font-style:italic;color:var(--secondary-fore-color);margin:var(--universal-margin);padding:calc(3 * var(--universal-padding));border:.0625rem solid var(--secondary-border-color);border-left:.375rem solid var(--blockquote-color);border-radius:0 var(--universal-border-radius) var(--universal-border-radius) 0}blockquote:before{position:absolute;top:calc(0rem - var(--universal-padding));left:0;font-family:sans-serif;font-size:3rem;font-weight:700;content:"\201c";color:var(--blockquote-color)}blockquote[cite]:after{font-style:normal;font-size:.75em;font-weight:700;content:"\a— " attr(cite);white-space:pre}code,kbd,pre,samp{font-family:Menlo, Consolas, monospace;font-size:.85em}code{background:var(--secondary-back-color);border-radius:var(--universal-border-radius);padding:calc(var(--universal-padding) / 4) calc(var(--universal-padding) / 2)}kbd{background:var(--fore-color);color:var(--back-color);border-radius:var(--universal-border-radius);padding:calc(var(--universal-padding) / 4) calc(var(--universal-padding) / 2)}pre{overflow:auto;background:var(--secondary-back-color);padding:calc(1.5 * var(--universal-padding));margin:var(--universal-margin);border:.0625rem solid var(--secondary-border-color);border-left:.25rem solid var(--pre-color);border-radius:0 var(--universal-border-radius) var(--universal-border-radius) 0}sup,sub,code,kbd{line-height:0;position:relative;vertical-align:baseline}small,sup,sub,figcaption{font-size:.75em}sup{top:-.5em}sub{bottom:-.25em}figure{margin:var(--universal-margin)}figcaption{color:var(--secondary-fore-color)}a{text-decoration:none}a:link{color:var(--a-link-color)}a:visited{color:var(--a-visited-color)}a:hover,a:focus{text-decoration:underline}.container{margin:0 auto;padding:0 calc(1.5 * var(--universal-padding))}.row{box-sizing:border-box;display:flex;flex:0 1 auto;flex-flow:row wrap}.col-sm,[class^='col-sm-'],[class^='col-sm-offset-'],.row[class*='cols-sm-']>*{box-sizing:border-box;flex:0 0 auto;padding:0 calc(var(--universal-padding) / 2)}.col-sm,.row.cols-sm>*{max-width:100%;flex-grow:1;flex-basis:0}.col-sm-1,.row.cols-sm-1>*{max-width:8.33333%;flex-basis:8.33333%}.col-sm-offset-0{margin-left:0}.col-sm-2,.row.cols-sm-2>*{max-width:16.66667%;flex-basis:16.66667%}.col-sm-offset-1{margin-left:8.33333%}.col-sm-3,.row.cols-sm-3>*{max-width:25%;flex-basis:25%}.col-sm-offset-2{margin-left:16.66667%}.col-sm-4,.row.cols-sm-4>*{max-width:33.33333%;flex-basis:33.33333%}.col-sm-offset-3{margin-left:25%}.col-sm-5,.row.cols-sm-5>*{max-width:41.66667%;flex-basis:41.66667%}.col-sm-offset-4{margin-left:33.33333%}.col-sm-6,.row.cols-sm-6>*{max-width:50%;flex-basis:50%}.col-sm-offset-5{margin-left:41.66667%}.col-sm-7,.row.cols-sm-7>*{max-width:58.33333%;flex-basis:58.33333%}.col-sm-offset-6{margin-left:50%}.col-sm-8,.row.cols-sm-8>*{max-width:66.66667%;flex-basis:66.66667%}.col-sm-offset-7{margin-left:58.33333%}.col-sm-9,.row.cols-sm-9>*{max-width:75%;flex-basis:75%}.col-sm-offset-8{margin-left:66.66667%}.col-sm-10,.row.cols-sm-10>*{max-width:83.33333%;flex-basis:83.33333%}.col-sm-offset-9{margin-left:75%}.col-sm-11,.row.cols-sm-11>*{max-width:91.66667%;flex-basis:91.66667%}.col-sm-offset-10{margin-left:83.33333%}.col-sm-12,.row.cols-sm-12>*{max-width:100%;flex-basis:100%}.col-sm-offset-11{margin-left:91.66667%}.col-sm-normal{order:initial}.col-sm-first{order:-999}.col-sm-last{order:999}@media screen and (min-width: 768px){.col-md,[class^='col-md-'],[class^='col-md-offset-'],.row[class*='cols-md-']>*{box-sizing:border-box;flex:0 0 auto;padding:0 calc(var(--universal-padding) / 2)}.col-md,.row.cols-md>*{max-width:100%;flex-grow:1;flex-basis:0}.col-md-1,.row.cols-md-1>*{max-width:8.33333%;flex-basis:8.33333%}.col-md-offset-0{margin-left:0}.col-md-2,.row.cols-md-2>*{max-width:16.66667%;flex-basis:16.66667%}.col-md-offset-1{margin-left:8.33333%}.col-md-3,.row.cols-md-3>*{max-width:25%;flex-basis:25%}.col-md-offset-2{margin-left:16.66667%}.col-md-4,.row.cols-md-4>*{max-width:33.33333%;flex-basis:33.33333%}.col-md-offset-3{margin-left:25%}.col-md-5,.row.cols-md-5>*{max-width:41.66667%;flex-basis:41.66667%}.col-md-offset-4{margin-left:33.33333%}.col-md-6,.row.cols-md-6>*{max-width:50%;flex-basis:50%}.col-md-offset-5{margin-left:41.66667%}.col-md-7,.row.cols-md-7>*{max-width:58.33333%;flex-basis:58.33333%}.col-md-offset-6{margin-left:50%}.col-md-8,.row.cols-md-8>*{max-width:66.66667%;flex-basis:66.66667%}.col-md-offset-7{margin-left:58.33333%}.col-md-9,.row.cols-md-9>*{max-width:75%;flex-basis:75%}.col-md-offset-8{margin-left:66.66667%}.col-md-10,.row.cols-md-10>*{max-width:83.33333%;flex-basis:83.33333%}.col-md-offset-9{margin-left:75%}.col-md-11,.row.cols-md-11>*{max-width:91.66667%;flex-basis:91.66667%}.col-md-offset-10{margin-left:83.33333%}.col-md-12,.row.cols-md-12>*{max-width:100%;flex-basis:100%}.col-md-offset-11{margin-left:91.66667%}.col-md-normal{order:initial}.col-md-first{order:-999}.col-md-last{order:999}}@media screen and (min-width: 1280px){.col-lg,[class^='col-lg-'],[class^='col-lg-offset-'],.row[class*='cols-lg-']>*{box-sizing:border-box;flex:0 0 auto;padding:0 calc(var(--universal-padding) / 2)}.col-lg,.row.cols-lg>*{max-width:100%;flex-grow:1;flex-basis:0}.col-lg-1,.row.cols-lg-1>*{max-width:8.33333%;flex-basis:8.33333%}.col-lg-offset-0{margin-left:0}.col-lg-2,.row.cols-lg-2>*{max-width:16.66667%;flex-basis:16.66667%}.col-lg-offset-1{margin-left:8.33333%}.col-lg-3,.row.cols-lg-3>*{max-width:25%;flex-basis:25%}.col-lg-offset-2{margin-left:16.66667%}.col-lg-4,.row.cols-lg-4>*{max-width:33.33333%;flex-basis:33.33333%}.col-lg-offset-3{margin-left:25%}.col-lg-5,.row.cols-lg-5>*{max-width:41.66667%;flex-basis:41.66667%}.col-lg-offset-4{margin-left:33.33333%}.col-lg-6,.row.cols-lg-6>*{max-width:50%;flex-basis:50%}.col-lg-offset-5{margin-left:41.66667%}.col-lg-7,.row.cols-lg-7>*{max-width:58.33333%;flex-basis:58.33333%}.col-lg-offset-6{margin-left:50%}.col-lg-8,.row.cols-lg-8>*{max-width:66.66667%;flex-basis:66.66667%}.col-lg-offset-7{margin-left:58.33333%}.col-lg-9,.row.cols-lg-9>*{max-width:75%;flex-basis:75%}.col-lg-offset-8{margin-left:66.66667%}.col-lg-10,.row.cols-lg-10>*{max-width:83.33333%;flex-basis:83.33333%}.col-lg-offset-9{margin-left:75%}.col-lg-11,.row.cols-lg-11>*{max-width:91.66667%;flex-basis:91.66667%}.col-lg-offset-10{margin-left:83.33333%}.col-lg-12,.row.cols-lg-12>*{max-width:100%;flex-basis:100%}.col-lg-offset-11{margin-left:91.66667%}.col-lg-normal{order:initial}.col-lg-first{order:-999}.col-lg-last{order:999}}:root{--card-back-color:#f8f8f8;--card-fore-color:#111;--card-border-color:#ddd}.card{display:flex;flex-direction:column;justify-content:space-between;align-self:center;position:relative;width:100%;background:var(--card-back-color);color:var(--card-fore-color);border:.0625rem solid var(--card-border-color);border-radius:var(--universal-border-radius);margin:var(--universal-margin);overflow:hidden}@media screen and (min-width: 320px){.card{max-width:320px}}.card>.section{background:var(--card-back-color);color:var(--card-fore-color);box-sizing:border-box;margin:0;border:0;border-radius:0;border-bottom:.0625rem solid var(--card-border-color);padding:var(--universal-padding);width:100%}.card>.section.media{height:200px;padding:0;-o-object-fit:cover;object-fit:cover}.card>.section:last-child{border-bottom:0}@media screen and (min-width: 240px){.card.small{max-width:240px}}@media screen and (min-width: 480px){.card.large{max-width:480px}}.card.fluid{max-width:100%;width:auto}.card.warning{--card-back-color:#ffca28;--card-border-color:#e8b825}.card.error{--card-back-color:#b71c1c;--card-fore-color:#f8f8f8;--card-border-color:#a71a1a}.card>.section.dark{--card-back-color:#e0e0e0}.card>.section.double-padded{padding:calc(1.5 * var(--universal-padding))}:root{--form-back-color:#f0f0f0;--form-fore-color:#111;--form-border-color:#ddd;--input-back-color:#f8f8f8;--input-fore-color:#111;--input-border-color:#ddd;--input-focus-color:#0288d1;--input-invalid-color:#d32f2f;--button-back-color:#e2e2e2;--button-hover-back-color:#dcdcdc;--button-fore-color:#212121;--button-border-color:transparent;--button-hover-border-color:transparent;--button-group-border-color:rgba(124,124,124,0.54)}form{background:var(--form-back-color);color:var(--form-fore-color);border:.0625rem solid var(--form-border-color);border-radius:var(--universal-border-radius);margin:var(--universal-margin);padding:calc(2 * var(--universal-padding)) var(--universal-padding)}fieldset{border:.0625rem solid var(--form-border-color);border-radius:var(--universal-border-radius);margin:calc(var(--universal-margin) / 4);padding:var(--universal-padding)}legend{box-sizing:border-box;display:table;max-width:100%;white-space:normal;font-weight:700;padding:calc(var(--universal-padding) / 2)}label{padding:calc(var(--universal-padding) / 2) var(--universal-padding)}.input-group{display:inline-block}.input-group.fluid{display:flex;align-items:center;justify-content:center}.input-group.fluid>input{max-width:100%;flex-grow:1;flex-basis:0px}@media screen and (max-width: 767px){.input-group.fluid{align-items:stretch;flex-direction:column}}.input-group.vertical{display:flex;align-items:stretch;flex-direction:column}.input-group.vertical>input{max-width:100%;flex-grow:1;flex-basis:0px}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{-webkit-appearance:textfield;outline-offset:-2px}[type="search"]::-webkit-search-cancel-button,[type="search"]::-webkit-search-decoration{-webkit-appearance:none}input:not([type]),[type="text"],[type="email"],[type="number"],[type="search"],[type="password"],[type="url"],[type="tel"],[type="checkbox"],[type="radio"],textarea,select{box-sizing:border-box;background:var(--input-back-color);color:var(--input-fore-color);border:.0625rem solid var(--input-border-color);border-radius:var(--universal-border-radius);margin:calc(var(--universal-margin) / 2);padding:var(--universal-padding) calc(1.5 * var(--universal-padding))}input:not([type="button"]):not([type="submit"]):not([type="reset"]):hover,input:not([type="button"]):not([type="submit"]):not([type="reset"]):focus,textarea:hover,textarea:focus,select:hover,select:focus{border-color:var(--input-focus-color);box-shadow:none}input:not([type="button"]):not([type="submit"]):not([type="reset"]):invalid,input:not([type="button"]):not([type="submit"]):not([type="reset"]):focus:invalid,textarea:invalid,textarea:focus:invalid,select:invalid,select:focus:invalid{border-color:var(--input-invalid-color);box-shadow:none}input:not([type="button"]):not([type="submit"]):not([type="reset"])[readonly],textarea[readonly],select[readonly]{background:var(--secondary-back-color)}select{max-width:100%}option{overflow:hidden;text-overflow:ellipsis}[type="checkbox"],[type="radio"]{-webkit-appearance:none;-moz-appearance:none;appearance:none;position:relative;height:calc(1rem + var(--universal-padding) / 2);width:calc(1rem + var(--universal-padding) / 2);vertical-align:text-bottom;padding:0;flex-basis:calc(1rem + var(--universal-padding) / 2) !important;flex-grow:0 !important}[type="checkbox"]:checked:before,[type="radio"]:checked:before{position:absolute}[type="checkbox"]:checked:before{content:'\2713';font-family:sans-serif;font-size:calc(1rem + var(--universal-padding) / 2);top:calc(0rem - var(--universal-padding));left:calc(var(--universal-padding) / 4)}[type="radio"]{border-radius:100%}[type="radio"]:checked:before{border-radius:100%;content:'';top:calc(.0625rem + var(--universal-padding) / 2);left:calc(.0625rem + var(--universal-padding) / 2);background:var(--input-fore-color);width:0.5rem;height:0.5rem}:placeholder-shown{color:var(--input-fore-color)}::-ms-placeholder{color:var(--input-fore-color);opacity:0.54}button::-moz-focus-inner,[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner{border-style:none;padding:0}button,html [type="button"],[type="reset"],[type="submit"]{-webkit-appearance:button}button{overflow:visible;text-transform:none}button,[type="button"],[type="submit"],[type="reset"],a.button,label.button,.button,a[role="button"],label[role="button"],[role="button"]{display:inline-block;background:var(--button-back-color);color:var(--button-fore-color);border:.0625rem solid var(--button-border-color);border-radius:var(--universal-border-radius);padding:var(--universal-padding) calc(1.5 * var(--universal-padding));margin:var(--universal-margin);text-decoration:none;cursor:pointer;transition:background 0.3s}button:hover,button:focus,[type="button"]:hover,[type="button"]:focus,[type="submit"]:hover,[type="submit"]:focus,[type="reset"]:hover,[type="reset"]:focus,a.button:hover,a.button:focus,label.button:hover,label.button:focus,.button:hover,.button:focus,a[role="button"]:hover,a[role="button"]:focus,label[role="button"]:hover,label[role="button"]:focus,[role="button"]:hover,[role="button"]:focus{background:var(--button-hover-back-color);border-color:var(--button-hover-border-color)}input:disabled,input[disabled],textarea:disabled,textarea[disabled],select:disabled,select[disabled],button:disabled,button[disabled],.button:disabled,.button[disabled],[role="button"]:disabled,[role="button"][disabled]{cursor:not-allowed;opacity:.75}.button-group{display:flex;border:.0625rem solid var(--button-group-border-color);border-radius:var(--universal-border-radius);margin:var(--universal-margin)}.button-group>button,.button-group [type="button"],.button-group>[type="submit"],.button-group>[type="reset"],.button-group>.button,.button-group>[role="button"]{margin:0;max-width:100%;flex:1 1 auto;text-align:center;border:0;border-radius:0;box-shadow:none}.button-group>:not(:first-child){border-left:.0625rem solid var(--button-group-border-color)}@media screen and (max-width: 767px){.button-group{flex-direction:column}.button-group>:not(:first-child){border:0;border-top:.0625rem solid var(--button-group-border-color)}}button.primary,[type="button"].primary,[type="submit"].primary,[type="reset"].primary,.button.primary,[role="button"].primary{--button-back-color:#1976d2;--button-fore-color:#f8f8f8}button.primary:hover,button.primary:focus,[type="button"].primary:hover,[type="button"].primary:focus,[type="submit"].primary:hover,[type="submit"].primary:focus,[type="reset"].primary:hover,[type="reset"].primary:focus,.button.primary:hover,.button.primary:focus,[role="button"].primary:hover,[role="button"].primary:focus{--button-hover-back-color:#1565c0}button.secondary,[type="button"].secondary,[type="submit"].secondary,[type="reset"].secondary,.button.secondary,[role="button"].secondary{--button-back-color:#d32f2f;--button-fore-color:#f8f8f8}button.secondary:hover,button.secondary:focus,[type="button"].secondary:hover,[type="button"].secondary:focus,[type="submit"].secondary:hover,[type="submit"].secondary:focus,[type="reset"].secondary:hover,[type="reset"].secondary:focus,.button.secondary:hover,.button.secondary:focus,[role="button"].secondary:hover,[role="button"].secondary:focus{--button-hover-back-color:#c62828}button.tertiary,[type="button"].tertiary,[type="submit"].tertiary,[type="reset"].tertiary,.button.tertiary,[role="button"].tertiary{--button-back-color:#308732;--button-fore-color:#f8f8f8}button.tertiary:hover,button.tertiary:focus,[type="button"].tertiary:hover,[type="button"].tertiary:focus,[type="submit"].tertiary:hover,[type="submit"].tertiary:focus,[type="reset"].tertiary:hover,[type="reset"].tertiary:focus,.button.tertiary:hover,.button.tertiary:focus,[role="button"].tertiary:hover,[role="button"].tertiary:focus{--button-hover-back-color:#277529}button.inverse,[type="button"].inverse,[type="submit"].inverse,[type="reset"].inverse,.button.inverse,[role="button"].inverse{--button-back-color:#212121;--button-fore-color:#f8f8f8}button.inverse:hover,button.inverse:focus,[type="button"].inverse:hover,[type="button"].inverse:focus,[type="submit"].inverse:hover,[type="submit"].inverse:focus,[type="reset"].inverse:hover,[type="reset"].inverse:focus,.button.inverse:hover,.button.inverse:focus,[role="button"].inverse:hover,[role="button"].inverse:focus{--button-hover-back-color:#111}button.small,[type="button"].small,[type="submit"].small,[type="reset"].small,.button.small,[role="button"].small{padding:calc(0.5 * var(--universal-padding)) calc(0.75 * var(--universal-padding));margin:var(--universal-margin)}button.large,[type="button"].large,[type="submit"].large,[type="reset"].large,.button.large,[role="button"].large{padding:calc(1.5 * var(--universal-padding)) calc(2 * var(--universal-padding));margin:var(--universal-margin)}:root{--header-back-color:#f8f8f8;--header-hover-back-color:#f0f0f0;--header-fore-color:#444;--header-border-color:#ddd;--nav-back-color:#f8f8f8;--nav-hover-back-color:#f0f0f0;--nav-fore-color:#444;--nav-border-color:#ddd;--nav-link-color:#0277bd;--footer-fore-color:#444;--footer-back-color:#f8f8f8;--footer-border-color:#ddd;--footer-link-color:#0277bd;--drawer-back-color:#f8f8f8;--drawer-hover-back-color:#f0f0f0;--drawer-border-color:#ddd;--drawer-close-color:#444}header{height:3.1875rem;background:var(--header-back-color);color:var(--header-fore-color);border-bottom:.0625rem solid var(--header-border-color);padding:calc(var(--universal-padding) / 4) 0;white-space:nowrap;overflow-x:auto;overflow-y:hidden}header.row{box-sizing:content-box}header .logo{color:var(--header-fore-color);font-size:1.75rem;padding:var(--universal-padding) calc(2 * var(--universal-padding));text-decoration:none}header button,header [type="button"],header .button,header [role="button"]{box-sizing:border-box;position:relative;top:calc(0rem - var(--universal-padding) / 4);height:calc(3.1875rem + var(--universal-padding) / 2);background:var(--header-back-color);line-height:calc(3.1875rem - var(--universal-padding) * 1.5);text-align:center;color:var(--header-fore-color);border:0;border-radius:0;margin:0;text-transform:uppercase}header button:hover,header button:focus,header [type="button"]:hover,header [type="button"]:focus,header .button:hover,header .button:focus,header [role="button"]:hover,header [role="button"]:focus{background:var(--header-hover-back-color)}nav{background:var(--nav-back-color);color:var(--nav-fore-color);border:.0625rem solid var(--nav-border-color);border-radius:var(--universal-border-radius);margin:var(--universal-margin)}nav *{padding:var(--universal-padding) calc(1.5 * var(--universal-padding))}nav a,nav a:visited{display:block;color:var(--nav-link-color);border-radius:var(--universal-border-radius);transition:background 0.3s}nav a:hover,nav a:focus,nav a:visited:hover,nav a:visited:focus{text-decoration:none;background:var(--nav-hover-back-color)}nav .sublink-1{position:relative;margin-left:calc(2 * var(--universal-padding))}nav .sublink-1:before{position:absolute;left:calc(var(--universal-padding) - 1 * var(--universal-padding));top:-.0625rem;content:'';height:100%;border:.0625rem solid var(--nav-border-color);border-left:0}nav .sublink-2{position:relative;margin-left:calc(4 * var(--universal-padding))}nav .sublink-2:before{position:absolute;left:calc(var(--universal-padding) - 3 * var(--universal-padding));top:-.0625rem;content:'';height:100%;border:.0625rem solid var(--nav-border-color);border-left:0}footer{background:var(--footer-back-color);color:var(--footer-fore-color);border-top:.0625rem solid var(--footer-border-color);padding:calc(2 * var(--universal-padding)) var(--universal-padding);font-size:.875rem}footer a,footer a:visited{color:var(--footer-link-color)}header.sticky{position:-webkit-sticky;position:sticky;z-index:1101;top:0}footer.sticky{position:-webkit-sticky;position:sticky;z-index:1101;bottom:0}.drawer-toggle:before{display:inline-block;position:relative;vertical-align:bottom;content:'\00a0\2261\00a0';font-family:sans-serif;font-size:1.5em}@media screen and (min-width: 768px){.drawer-toggle:not(.persistent){display:none}}[type="checkbox"].drawer{height:1px;width:1px;margin:-1px;overflow:hidden;position:absolute;clip:rect(0 0 0 0);-webkit-clip-path:inset(100%);clip-path:inset(100%)}[type="checkbox"].drawer+*{display:block;box-sizing:border-box;position:fixed;top:0;width:320px;height:100vh;overflow-y:auto;background:var(--drawer-back-color);border:.0625rem solid var(--drawer-border-color);border-radius:0;margin:0;z-index:1110;left:-320px;transition:left 0.3s}[type="checkbox"].drawer+* .drawer-close{position:absolute;top:var(--universal-margin);right:var(--universal-margin);z-index:1111;width:2rem;height:2rem;border-radius:var(--universal-border-radius);padding:var(--universal-padding);margin:0;cursor:pointer;transition:background 0.3s}[type="checkbox"].drawer+* .drawer-close:before{display:block;content:'\00D7';color:var(--drawer-close-color);position:relative;font-family:sans-serif;font-size:2rem;line-height:1;text-align:center}[type="checkbox"].drawer+* .drawer-close:hover,[type="checkbox"].drawer+* .drawer-close:focus{background:var(--drawer-hover-back-color)}@media screen and (max-width: 320px){[type="checkbox"].drawer+*{width:100%}}[type="checkbox"].drawer:checked+*{left:0}@media screen and (min-width: 768px){[type="checkbox"].drawer:not(.persistent)+*{position:static;height:100%;z-index:1100}[type="checkbox"].drawer:not(.persistent)+* .drawer-close{display:none}}:root{--mark-back-color:#0277bd;--mark-fore-color:#fafafa}mark{background:var(--mark-back-color);color:var(--mark-fore-color);font-size:.95em;line-height:1em;border-radius:var(--universal-border-radius);padding:calc(var(--universal-padding) / 4) calc(var(--universal-padding) / 2)}mark.inline-block{display:inline-block;font-size:1em;line-height:1.5;padding:calc(var(--universal-padding) / 2) var(--universal-padding)}:root{--toast-back-color:#424242;--toast-fore-color:#fafafa}.toast{position:fixed;bottom:calc(var(--universal-margin) * 3);left:50%;transform:translate(-50%, -50%);z-index:1111;color:var(--toast-fore-color);background:var(--toast-back-color);border-radius:calc(var(--universal-border-radius) * 16);padding:var(--universal-padding) calc(var(--universal-padding) * 3)}:root{--tooltip-back-color:#212121;--tooltip-fore-color:#fafafa}.tooltip{position:relative;display:inline-block}.tooltip:before,.tooltip:after{position:absolute;opacity:0;clip:rect(0 0 0 0);-webkit-clip-path:inset(100%);clip-path:inset(100%);transition:all 0.3s;z-index:1010;left:50%}.tooltip:not(.bottom):before,.tooltip:not(.bottom):after{bottom:75%}.tooltip.bottom:before,.tooltip.bottom:after{top:75%}.tooltip:hover:before,.tooltip:hover:after,.tooltip:focus:before,.tooltip:focus:after{opacity:1;clip:auto;-webkit-clip-path:inset(0%);clip-path:inset(0%)}.tooltip:before{content:'';background:transparent;border:var(--universal-margin) solid transparent;left:calc(50% - var(--universal-margin))}.tooltip:not(.bottom):before{border-top-color:#212121}.tooltip.bottom:before{border-bottom-color:#212121}.tooltip:after{content:attr(aria-label);color:var(--tooltip-fore-color);background:var(--tooltip-back-color);border-radius:var(--universal-border-radius);padding:var(--universal-padding);white-space:nowrap;transform:translateX(-50%)}.tooltip:not(.bottom):after{margin-bottom:calc(2 * var(--universal-margin))}.tooltip.bottom:after{margin-top:calc(2 * var(--universal-margin))}:root{--modal-overlay-color:rgba(0,0,0,0.45);--modal-close-color:#444;--modal-close-hover-color:#f0f0f0}[type="checkbox"].modal{height:1px;width:1px;margin:-1px;overflow:hidden;position:absolute;clip:rect(0 0 0 0);-webkit-clip-path:inset(100%);clip-path:inset(100%)}[type="checkbox"].modal+div{position:fixed;top:0;left:0;display:none;width:100vw;height:100vh;background:var(--modal-overlay-color)}[type="checkbox"].modal+div .card{margin:0 auto;max-height:50vh;overflow:auto}[type="checkbox"].modal+div .card .modal-close{position:absolute;top:0;right:0;width:1.75rem;height:1.75rem;border-radius:var(--universal-border-radius);padding:var(--universal-padding);margin:0;cursor:pointer;transition:background 0.3s}[type="checkbox"].modal+div .card .modal-close:before{display:block;content:'\00D7';color:var(--modal-close-color);position:relative;font-family:sans-serif;font-size:1.75rem;line-height:1;text-align:center}[type="checkbox"].modal+div .card .modal-close:hover,[type="checkbox"].modal+div .card .modal-close:focus{background:var(--modal-close-hover-color)}[type="checkbox"].modal:checked+div{display:flex;flex:0 1 auto;z-index:1200}[type="checkbox"].modal:checked+div .card .modal-close{z-index:1211}:root{--collapse-label-back-color:#e8e8e8;--collapse-label-fore-color:#212121;--collapse-label-hover-back-color:#f0f0f0;--collapse-selected-label-back-color:#ececec;--collapse-border-color:#ddd;--collapse-content-back-color:#fafafa;--collapse-selected-label-border-color:#0277bd}.collapse{width:calc(100% - 2 * var(--universal-margin));opacity:1;display:flex;flex-direction:column;margin:var(--universal-margin);border-radius:var(--universal-border-radius)}.collapse>[type="radio"],.collapse>[type="checkbox"]{height:1px;width:1px;margin:-1px;overflow:hidden;position:absolute;clip:rect(0 0 0 0);-webkit-clip-path:inset(100%);clip-path:inset(100%)}.collapse>label{flex-grow:1;display:inline-block;height:1.5rem;cursor:pointer;transition:background 0.3s;color:var(--collapse-label-fore-color);background:var(--collapse-label-back-color);border:.0625rem solid var(--collapse-border-color);padding:calc(1.5 * var(--universal-padding))}.collapse>label:hover,.collapse>label:focus{background:var(--collapse-label-hover-back-color)}.collapse>label+div{flex-basis:auto;height:1px;width:1px;margin:-1px;overflow:hidden;position:absolute;clip:rect(0 0 0 0);-webkit-clip-path:inset(100%);clip-path:inset(100%);transition:max-height 0.3s;max-height:1px}.collapse>:checked+label{background:var(--collapse-selected-label-back-color);border-bottom-color:var(--collapse-selected-label-border-color)}.collapse>:checked+label+div{box-sizing:border-box;position:relative;width:100%;height:auto;overflow:auto;margin:0;background:var(--collapse-content-back-color);border:.0625rem solid var(--collapse-border-color);border-top:0;padding:var(--universal-padding);clip:auto;-webkit-clip-path:inset(0%);clip-path:inset(0%);max-height:400px}.collapse>label:not(:first-of-type){border-top:0}.collapse>label:first-of-type{border-radius:var(--universal-border-radius) var(--universal-border-radius) 0 0}.collapse>label:last-of-type{border-radius:0 0 var(--universal-border-radius) var(--universal-border-radius)}.collapse>:checked:last-of-type+label{border-radius:0}.collapse>:checked:last-of-type+label+div{border-radius:0 0 var(--universal-border-radius) var(--universal-border-radius)}mark.secondary{--mark-back-color:#d32f2f}mark.tertiary{--mark-back-color:#308732}mark.tag{padding:calc(var(--universal-padding)/2) var(--universal-padding);border-radius:1em}html,*{font-family:'Poppins', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, "Helvetica Neue", Helvetica, sans-serif}code,pre,kbd,code *,pre *,kbd *{font-family:'Inconsolata', Menlo, Consolas, monospace}code,kbd{font-size:1em}code{transform:scale(1)}pre{font-size:1rem;border:0.0625rem solid var(--secondary-border-color);border-radius:var(--universal-border-radius)}.group{position:relative;margin-top:2em;margin-bottom:-1em}.search{font-size:14px;margin-top:-.1em;display:block;width:100%;border:none;border-bottom:1px solid var(--nav-link-color)}.search:focus{outline:none}label#search-label{color:var(--nav-link-color);font-size:18px;font-weight:400;position:absolute;left:5px;top:10px}.search:focus ~ label#search-label,.search:valid ~ label#search-label{top:-20px;font-size:14px;color:var(--nav-link-color)}label#menu-toggle{width:3.4375rem}header h1.logo{margin-top:-0.8rem;text-align:center}header h1.logo a{text-decoration:none;color:#111}header #title{position:relative;top:-1rem}@media screen and (max-width: 500px){header #title{font-size:1rem;display:block}}header h1 small{display:block;font-size:0.875rem;font-style:italic;color:#888;margin-top:-0.8rem}@media screen and (max-width: 768px){header h1 small{font-size:0.75rem}}@media screen and (max-width: 600px){header h1 small{font-size:0.625rem}}@media screen and (max-width: 500px){header h1 small{font-size:0.5rem;margin-top:-1.2rem}}label#menu-toggle{position:absolute;left:0.5rem;top:0.5rem;width:3.4375rem}.card{box-shadow:0 0.25rem 0.25rem 0 rgba(0,0,0,0.125),0 0.125rem 0.125rem -0.125rem rgba(0,0,0,0.25)}main{padding:0} diff --git a/package-lock.json b/package-lock.json index cce28f14f..82dcfac8a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -184,6 +184,11 @@ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=" }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, "async-each": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", @@ -383,6 +388,77 @@ "repeat-element": "1.1.2" } }, + "builder": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/builder/-/builder-3.2.3.tgz", + "integrity": "sha512-DXkZ27RHCw4uCn08SEx7hhgXbtamZOBKa8FEuHjsooyMfNfZXNn7YYqpfWrBNigwX2sMgKYWY8Jupxp6waofSg==", + "requires": { + "async": "1.5.2", + "chalk": "1.1.3", + "js-yaml": "3.10.0", + "lodash": "3.10.1", + "nopt": "3.0.6", + "tree-kill": "1.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "requires": { + "abbrev": "1.1.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, "builtin-modules": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", @@ -4069,6 +4145,11 @@ } } }, + "tagger": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/tagger/-/tagger-0.1.2.tgz", + "integrity": "sha1-K0ZDWgdvEn359ZglN/PX9K5AH/k=" + }, "tar": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", @@ -4354,6 +4435,11 @@ } } }, + "webber": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/webber/-/webber-0.0.1.tgz", + "integrity": "sha1-u1Nt4g0OmS6Noj7KM/5O3/LEZHY=" + }, "websocket-driver": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", diff --git a/package.json b/package.json index 59ade407a..09024b301 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,6 @@ { "dependencies": { + "builder": "^3.2.3", "concurrently": "^3.5.1", "fs-extra": "^4.0.2", "html-minifier": "^3.5.7", @@ -7,7 +8,9 @@ "markdown-it": "^8.4.0", "node-sass": "^4.7.2", "nodemon": "^1.12.1", - "semistandard": "^11.0.0" + "semistandard": "^11.0.0", + "tagger": "^0.1.2", + "webber": "0.0.1" }, "name": "30-seconds-of-code", "description": "A collection of useful Javascript snippets.", diff --git a/yarn.lock b/yarn.lock index 9dc4ac57e..6e263d4ae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -38,6 +38,19 @@ ajv@^4.7.0, ajv@^4.9.1: co "^4.6.0" json-stable-stringify "^1.0.1" +ajv@^5.1.0: + version "5.5.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" + dependencies: + co "^4.6.0" + fast-deep-equal "^1.0.0" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.3.0" + +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + ansi-align@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f" @@ -118,6 +131,10 @@ arr-flatten@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" +array-find-index@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" + array-union@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" @@ -159,6 +176,14 @@ async-each@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" +async-foreach@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542" + +async@^1.4.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -167,7 +192,11 @@ aws-sign2@~0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" -aws4@^1.2.1: +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + +aws4@^1.2.1, aws4@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" @@ -219,6 +248,18 @@ boom@2.x.x: dependencies: hoek "2.x.x" +boom@4.x.x: + version "4.3.1" + resolved "https://registry.yarnpkg.com/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31" + dependencies: + hoek "4.x.x" + +boom@5.x.x: + version "5.2.0" + resolved "https://registry.yarnpkg.com/boom/-/boom-5.2.0.tgz#5dd9da6ee3a5f302077436290cb717d3f4a54e02" + dependencies: + hoek "4.x.x" + boxen@^1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.2.2.tgz#3f1d4032c30ffea9d4b02c322eaf2ea741dcbce5" @@ -246,7 +287,18 @@ braces@^1.8.2: preserve "^0.2.0" repeat-element "^1.1.2" -builtin-modules@^1.1.1: +builder@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/builder/-/builder-3.2.3.tgz#33b239fa62d2432802164eb72e5f49639b0ae115" + dependencies: + async "^1.4.2" + chalk "^1.1.1" + js-yaml "^3.4.3" + lodash "^3.10.1" + nopt "^3.0.6" + tree-kill "^1.0.0" + +builtin-modules@^1.0.0, builtin-modules@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" @@ -260,6 +312,28 @@ callsites@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" +camel-case@3.0.x: + version "3.0.0" + resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73" + dependencies: + no-case "^2.2.0" + upper-case "^1.1.1" + +camelcase-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" + dependencies: + camelcase "^2.0.0" + map-obj "^1.0.0" + +camelcase@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" + +camelcase@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" + camelcase@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" @@ -268,6 +342,10 @@ capture-stack-trace@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz#4a6fa07399c26bba47f0b2496b4d0fb408c5550d" +caseless@~0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7" + caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" @@ -319,6 +397,12 @@ circular-json@^0.3.1: version "0.3.3" resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" +clean-css@4.1.x: + version "4.1.9" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.1.9.tgz#35cee8ae7687a49b98034f70de00c4edd3826301" + dependencies: + source-map "0.5.x" + cli-boxes@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143" @@ -333,6 +417,14 @@ cli-width@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" +cliui@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi "^2.0.0" + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -361,6 +453,10 @@ combined-stream@^1.0.5, combined-stream@~1.0.5: dependencies: delayed-stream "~1.0.0" +commander@2.12.x, commander@^2.9.0, commander@~2.12.1: + version "2.12.2" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.12.2.tgz#0f5946c427ed9ec0d91a46bb9def53e54650e555" + commander@2.6.0: version "2.6.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.6.0.tgz#9df7e52fb2a0cb0fb89058ee80c3104225f37e1d" @@ -435,6 +531,13 @@ create-error-class@^3.0.0: dependencies: capture-stack-trace "^1.0.0" +cross-spawn@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982" + dependencies: + lru-cache "^4.0.1" + which "^1.2.9" + cross-spawn@^5.0.1: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" @@ -449,10 +552,22 @@ cryptiles@2.x.x: dependencies: boom "2.x.x" +cryptiles@3.x.x: + version "3.1.2" + resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-3.1.2.tgz#a89fbb220f5ce25ec56e8c4aa8a4fd7b5b0d29fe" + dependencies: + boom "5.x.x" + crypto-random-string@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" +currently-unhandled@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" + dependencies: + array-find-index "^1.0.1" + d@1: version "1.0.0" resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" @@ -485,6 +600,10 @@ debug@~2.2.0: dependencies: ms "0.7.1" +decamelize@^1.1.1, decamelize@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + deep-extend@~0.4.0: version "0.4.2" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" @@ -878,7 +997,7 @@ expand-range@^1.8.1: dependencies: fill-range "^2.1.0" -extend@~3.0.0: +extend@~3.0.0, extend@~3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" @@ -892,6 +1011,14 @@ extsprintf@1.3.0, extsprintf@^1.2.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" +fast-deep-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" + +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" @@ -992,6 +1119,14 @@ form-data@~2.1.1: combined-stream "^1.0.5" mime-types "^2.1.12" +form-data@~2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.1.tgz#6fb94fbd71885306d73d15cc497fe4cc4ecd44bf" + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.5" + mime-types "^2.1.12" + fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" @@ -1053,6 +1188,12 @@ gauge@~2.7.3: strip-ansi "^3.0.1" wide-align "^1.1.0" +gaze@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.2.tgz#847224677adb8870d679257ed3388fdb61e40105" + dependencies: + globule "^1.0.0" + generate-function@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" @@ -1063,6 +1204,14 @@ generate-object-property@^1.1.0: dependencies: is-property "^1.0.0" +get-caller-file@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" + +get-stdin@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" + get-stdin@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398" @@ -1090,7 +1239,17 @@ glob-parent@^2.0.0: dependencies: is-glob "^2.0.0" -glob@^7.0.0, glob@^7.0.3, glob@^7.0.5: +glob@^6.0.4: + version "6.0.4" + resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@~7.1.1: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" dependencies: @@ -1122,6 +1281,14 @@ globby@^5.0.0: pify "^2.0.0" pinkie-promise "^2.0.0" +globule@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/globule/-/globule-1.2.0.tgz#1dc49c6822dd9e8a2fa00ba2a295006e8664bd09" + dependencies: + glob "~7.1.1" + lodash "~4.17.4" + minimatch "~3.0.2" + got@^6.7.1: version "6.7.1" resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" @@ -1146,6 +1313,19 @@ har-schema@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + +har-validator@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d" + dependencies: + chalk "^1.1.1" + commander "^2.9.0" + is-my-json-valid "^2.12.4" + pinkie-promise "^2.0.0" + har-validator@~4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a" @@ -1153,6 +1333,13 @@ har-validator@~4.2.1: ajv "^4.9.1" har-schema "^1.0.5" +har-validator@~5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" + dependencies: + ajv "^5.1.0" + har-schema "^2.0.0" + has-ansi@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-0.1.0.tgz#84f265aae8c0e6a88a12d7022894b7568894c62e" @@ -1192,10 +1379,44 @@ hawk@3.1.3, hawk@~3.1.3: hoek "2.x.x" sntp "1.x.x" +hawk@~6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/hawk/-/hawk-6.0.2.tgz#af4d914eb065f9b5ce4d9d11c1cb2126eecc3038" + dependencies: + boom "4.x.x" + cryptiles "3.x.x" + hoek "4.x.x" + sntp "2.x.x" + +he@1.1.x: + version "1.1.1" + resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" + hoek@2.x.x: version "2.16.3" resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" +hoek@4.x.x: + version "4.2.0" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d" + +hosted-git-info@^2.1.4: + version "2.5.0" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c" + +html-minifier@^3.5.7: + version "3.5.7" + resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-3.5.7.tgz#511e69bb5a8e7677d1012ebe03819aa02ca06208" + dependencies: + camel-case "3.0.x" + clean-css "4.1.x" + commander "2.12.x" + he "1.1.x" + ncname "1.0.x" + param-case "2.1.x" + relateurl "0.2.x" + uglify-js "3.2.x" + http-auth@3.1.x: version "3.1.3" resolved "https://registry.yarnpkg.com/http-auth/-/http-auth-3.1.3.tgz#945cfadd66521eaf8f7c84913d377d7b15f24e31" @@ -1226,6 +1447,14 @@ http-signature@~1.1.0: jsprim "^1.2.2" sshpk "^1.7.0" +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + ignore-by-default@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" @@ -1242,6 +1471,16 @@ imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" +in-publish@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/in-publish/-/in-publish-2.0.0.tgz#e20ff5e3a2afc2690320b6dc552682a9c7fadf51" + +indent-string@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" + dependencies: + repeating "^2.0.0" + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -1279,6 +1518,10 @@ interpret@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -1293,6 +1536,12 @@ is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" +is-builtin-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" + dependencies: + builtin-modules "^1.0.0" + is-callable@^1.1.1, is-callable@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.3.tgz#86eb75392805ddc33af71c92a0eedf74ee7604b2" @@ -1319,6 +1568,12 @@ is-extglob@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" +is-finite@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" + dependencies: + number-is-nan "^1.0.0" + is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" @@ -1351,6 +1606,15 @@ is-my-json-valid@^2.10.0: jsonpointer "^4.0.0" xtend "^4.0.0" +is-my-json-valid@^2.12.4: + version "2.17.1" + resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz#3da98914a70a22f0a8563ef1511a246c6fc55471" + dependencies: + generate-function "^2.0.0" + generate-object-property "^1.1.0" + jsonpointer "^4.0.0" + xtend "^4.0.0" + is-npm@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" @@ -1429,6 +1693,10 @@ is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + is-wsl@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" @@ -1451,11 +1719,15 @@ isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" +js-base64@^2.1.8: + version "2.4.0" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.0.tgz#9e566fee624751a1d720c966cd6226d29d4025aa" + js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" -js-yaml@^3.5.1: +js-yaml@^3.4.3, js-yaml@^3.5.1: version "3.10.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc" dependencies: @@ -1466,6 +1738,10 @@ jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" +json-schema-traverse@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" + json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" @@ -1525,6 +1801,12 @@ latest-version@^3.0.0: dependencies: package-json "^4.0.0" +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + dependencies: + invert-kv "^1.0.0" + levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" @@ -1556,6 +1838,16 @@ live-server@^1.2.0: send latest serve-index "^1.7.2" +load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + pinkie-promise "^2.0.0" + strip-bom "^2.0.0" + load-json-file@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" @@ -1611,6 +1903,14 @@ lodash.assign@^3.0.0: lodash._createassigner "^3.0.0" lodash.keys "^3.0.0" +lodash.assign@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" + +lodash.clonedeep@^4.3.2: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + lodash.cond@^4.3.0: version "4.5.2" resolved "https://registry.yarnpkg.com/lodash.cond/-/lodash.cond-4.5.2.tgz#f471a1da486be60f6ab955d17115523dd1d255d5" @@ -1638,14 +1938,33 @@ lodash.keys@^3.0.0: lodash.isarguments "^3.0.0" lodash.isarray "^3.0.0" +lodash.mergewith@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.0.tgz#150cf0a16791f5903b8891eab154609274bdea55" + lodash.restparam@^3.0.0: version "3.6.1" resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" -lodash@^4.0.0, lodash@^4.3.0, lodash@^4.5.1: +lodash@^3.10.1: + version "3.10.1" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" + +lodash@^4.0.0, lodash@^4.3.0, lodash@^4.5.1, lodash@~4.17.4: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" +loud-rejection@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" + dependencies: + currently-unhandled "^0.4.1" + signal-exit "^3.0.0" + +lower-case@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" + lowercase-keys@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" @@ -1663,6 +1982,10 @@ make-dir@^1.0.0: dependencies: pify "^3.0.0" +map-obj@^1.0.0, map-obj@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + map-stream@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" @@ -1681,6 +2004,21 @@ mdurl@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" +meow@^3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" + dependencies: + camelcase-keys "^2.0.0" + decamelize "^1.1.2" + loud-rejection "^1.0.0" + map-obj "^1.0.1" + minimist "^1.1.3" + normalize-package-data "^2.3.4" + object-assign "^4.0.1" + read-pkg-up "^1.0.1" + redent "^1.0.0" + trim-newlines "^1.0.0" + micromatch@^2.1.5: version "2.3.11" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" @@ -1713,7 +2051,7 @@ mime@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" -minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: +"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@~3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: @@ -1723,7 +2061,7 @@ minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" -minimist@^1.1.0, minimist@^1.2.0: +minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" @@ -1755,7 +2093,7 @@ mute-stream@0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0" -nan@^2.3.0: +nan@^2.3.0, nan@^2.3.2: version "2.8.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.8.0.tgz#ed715f3fe9de02b57a5e6252d90a96675e1f085a" @@ -1763,10 +2101,40 @@ natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" +ncname@1.0.x: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ncname/-/ncname-1.0.0.tgz#5b57ad18b1ca092864ef62b0b1ed8194f383b71c" + dependencies: + xml-char-classes "^1.0.0" + negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" +no-case@^2.2.0: + version "2.3.2" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac" + dependencies: + lower-case "^1.1.1" + +node-gyp@^3.3.1: + version "3.6.2" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.6.2.tgz#9bfbe54562286284838e750eac05295853fa1c60" + dependencies: + fstream "^1.0.0" + glob "^7.0.3" + graceful-fs "^4.1.2" + minimatch "^3.0.2" + mkdirp "^0.5.0" + nopt "2 || 3" + npmlog "0 || 1 || 2 || 3 || 4" + osenv "0" + request "2" + rimraf "2" + semver "~5.3.0" + tar "^2.0.0" + which "1" + node-pre-gyp@^0.6.39: version "0.6.39" resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz#c00e96860b23c0e1420ac7befc5044e1d78d8649" @@ -1783,6 +2151,30 @@ node-pre-gyp@^0.6.39: tar "^2.2.1" tar-pack "^3.4.0" +node-sass@^4.7.2: + version "4.7.2" + resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.7.2.tgz#9366778ba1469eb01438a9e8592f4262bcb6794e" + dependencies: + async-foreach "^0.1.3" + chalk "^1.1.1" + cross-spawn "^3.0.0" + gaze "^1.0.0" + get-stdin "^4.0.1" + glob "^7.0.3" + in-publish "^2.0.0" + lodash.assign "^4.2.0" + lodash.clonedeep "^4.3.2" + lodash.mergewith "^4.6.0" + meow "^3.7.0" + mkdirp "^0.5.1" + nan "^2.3.2" + node-gyp "^3.3.1" + npmlog "^4.0.0" + request "~2.79.0" + sass-graph "^2.2.4" + stdout-stream "^1.4.0" + "true-case-path" "^1.0.2" + nodemon@^1.12.1: version "1.12.1" resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.12.1.tgz#996a56dc49d9f16bbf1b78a4de08f13634b3878d" @@ -1798,6 +2190,12 @@ nodemon@^1.12.1: undefsafe "0.0.3" update-notifier "^2.2.0" +"nopt@2 || 3", nopt@^3.0.6: + version "3.0.6" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + dependencies: + abbrev "1" + nopt@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" @@ -1811,6 +2209,15 @@ nopt@~1.0.10: dependencies: abbrev "1" +normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: + version "2.4.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" + dependencies: + hosted-git-info "^2.1.4" + is-builtin-module "^1.0.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + normalize-path@^2.0.0, normalize-path@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" @@ -1823,7 +2230,7 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" -npmlog@^4.0.2: +"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" dependencies: @@ -1836,7 +2243,7 @@ number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" -oauth-sign@~0.8.1: +oauth-sign@~0.8.1, oauth-sign@~0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" @@ -1904,11 +2311,17 @@ os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" +os-locale@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" + dependencies: + lcid "^1.0.0" + os-tmpdir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" -osenv@^0.1.4: +osenv@0, osenv@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.4.tgz#42fe6d5953df06c8064be6f176c3d05aaaa34644" dependencies: @@ -1938,6 +2351,12 @@ package-json@^4.0.0: registry-url "^3.0.3" semver "^5.1.0" +param-case@2.1.x: + version "2.1.1" + resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247" + dependencies: + no-case "^2.2.0" + parse-glob@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" @@ -1983,6 +2402,14 @@ path-parse@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" +path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" + pause-stream@0.0.11: version "0.0.11" resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" @@ -1993,6 +2420,10 @@ performance-now@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + pify@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -2080,10 +2511,18 @@ punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" +qs@~6.3.0: + version "6.3.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c" + qs@~6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" +qs@~6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" + randomatic@^1.1.3: version "1.1.7" resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" @@ -2104,7 +2543,22 @@ rc@^1.0.1, rc@^1.1.6, rc@^1.1.7: minimist "^1.2.0" strip-json-comments "~2.0.1" -readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.2.2: +read-pkg-up@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + dependencies: + find-up "^1.0.0" + read-pkg "^1.0.0" + +read-pkg@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + dependencies: + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" + +readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.2.2: version "2.3.3" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" dependencies: @@ -2139,6 +2593,13 @@ rechoir@^0.6.2: dependencies: resolve "^1.1.6" +redent@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" + dependencies: + indent-string "^2.1.0" + strip-indent "^1.0.1" + regex-cache@^0.4.2: version "0.4.4" resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" @@ -2158,6 +2619,10 @@ registry-url@^3.0.3: dependencies: rc "^1.0.1" +relateurl@0.2.x: + version "0.2.7" + resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" + remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" @@ -2170,6 +2635,39 @@ repeat-string@^1.5.2: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + dependencies: + is-finite "^1.0.0" + +request@2: + version "2.83.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.6.0" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.1" + forever-agent "~0.6.1" + form-data "~2.3.1" + har-validator "~5.0.3" + hawk "~6.0.2" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.17" + oauth-sign "~0.8.2" + performance-now "^2.1.0" + qs "~6.5.1" + safe-buffer "^5.1.1" + stringstream "~0.0.5" + tough-cookie "~2.3.3" + tunnel-agent "^0.6.0" + uuid "^3.1.0" + request@2.81.0: version "2.81.0" resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" @@ -2197,6 +2695,39 @@ request@2.81.0: tunnel-agent "^0.6.0" uuid "^3.0.0" +request@~2.79.0: + version "2.79.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" + dependencies: + aws-sign2 "~0.6.0" + aws4 "^1.2.1" + caseless "~0.11.0" + combined-stream "~1.0.5" + extend "~3.0.0" + forever-agent "~0.6.1" + form-data "~2.1.1" + har-validator "~2.0.6" + hawk "~3.1.3" + http-signature "~1.1.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.7" + oauth-sign "~0.8.1" + qs "~6.3.0" + stringstream "~0.0.4" + tough-cookie "~2.3.0" + tunnel-agent "~0.4.1" + uuid "^3.0.0" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + require-uncached@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" @@ -2245,10 +2776,26 @@ rx@2.3.24: version "2.3.24" resolved "https://registry.yarnpkg.com/rx/-/rx-2.3.24.tgz#14f950a4217d7e35daa71bbcbe58eff68ea4b2b7" -safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" +sass-graph@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49" + dependencies: + glob "^7.0.0" + lodash "^4.0.0" + scss-tokenizer "^0.2.3" + yargs "^7.0.0" + +scss-tokenizer@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1" + dependencies: + js-base64 "^2.1.8" + source-map "^0.4.2" + semistandard@^11.0.0: version "11.0.0" resolved "https://registry.yarnpkg.com/semistandard/-/semistandard-11.0.0.tgz#d2d9fc8ac393de21312195e006e50c8861391c47" @@ -2270,14 +2817,14 @@ semver-diff@^2.0.0: dependencies: semver "^5.0.3" -semver@5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" - -semver@^5.0.3, semver@^5.1.0, semver@^5.3.0: +"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0: version "5.4.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" +semver@5.3.0, semver@~5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" + send@latest: version "0.16.1" resolved "https://registry.yarnpkg.com/send/-/send-0.16.1.tgz#a70e1ca21d1382c11d0d9f6231deb281080d7ab3" @@ -2308,7 +2855,7 @@ serve-index@^1.7.2: mime-types "~2.1.17" parseurl "~1.3.2" -set-blocking@~2.0.0: +set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" @@ -2352,10 +2899,44 @@ sntp@1.x.x: dependencies: hoek "2.x.x" +sntp@2.x.x: + version "2.1.0" + resolved "https://registry.yarnpkg.com/sntp/-/sntp-2.1.0.tgz#2c6cec14fedc2222739caf9b5c3d85d1cc5a2cc8" + dependencies: + hoek "4.x.x" + +source-map@0.5.x: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + +source-map@^0.4.2: + version "0.4.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" + dependencies: + amdefine ">=0.0.4" + +source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + spawn-command@^0.0.2-1: version "0.0.2-1" resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0" +spdx-correct@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40" + dependencies: + spdx-license-ids "^1.0.2" + +spdx-expression-parse@~1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c" + +spdx-license-ids@^1.0.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" + split@0.3: version "0.3.3" resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" @@ -2397,6 +2978,12 @@ statuses@~1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" +stdout-stream@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.0.tgz#a2c7c8587e54d9427ea9edb3ac3f2cd522df378b" + dependencies: + readable-stream "^2.0.1" + stream-combiner@~0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" @@ -2424,7 +3011,7 @@ string_decoder@~1.0.3: dependencies: safe-buffer "~5.1.0" -stringstream@~0.0.4: +stringstream@~0.0.4, stringstream@~0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" @@ -2446,6 +3033,12 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + dependencies: + is-utf8 "^0.2.0" + strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" @@ -2454,6 +3047,12 @@ strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" +strip-indent@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" + dependencies: + get-stdin "^4.0.1" + strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" @@ -2489,6 +3088,10 @@ table@^3.7.8: slice-ansi "0.0.4" string-width "^2.0.0" +tagger@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/tagger/-/tagger-0.1.2.tgz#2b46435a076f127df9f5982537f3d7f4ae401ff9" + tar-pack@^3.4.0: version "3.4.1" resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.1.tgz#e1dbc03a9b9d3ba07e896ad027317eb679a10a1f" @@ -2502,7 +3105,7 @@ tar-pack@^3.4.0: tar "^2.2.1" uid-number "^0.0.6" -tar@^2.2.1: +tar@^2.0.0, tar@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" dependencies: @@ -2534,22 +3137,36 @@ touch@^3.1.0: dependencies: nopt "~1.0.10" -tough-cookie@~2.3.0: +tough-cookie@~2.3.0, tough-cookie@~2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" dependencies: punycode "^1.4.1" -tree-kill@^1.1.0: +tree-kill@^1.0.0, tree-kill@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.0.tgz#5846786237b4239014f05db156b643212d4c6f36" +trim-newlines@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" + +"true-case-path@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-1.0.2.tgz#7ec91130924766c7f573be3020c34f8fdfd00d62" + dependencies: + glob "^6.0.4" + tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" dependencies: safe-buffer "^5.0.1" +tunnel-agent@~0.4.1: + version "0.4.3" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb" + tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" @@ -2568,6 +3185,13 @@ uc.micro@^1.0.1, uc.micro@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.3.tgz#7ed50d5e0f9a9fb0a573379259f2a77458d50192" +uglify-js@3.2.x: + version "3.2.2" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.2.2.tgz#870e4b34ed733d179284f9998efd3293f7fd73f6" + dependencies: + commander "~2.12.1" + source-map "~0.6.1" + uid-number@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" @@ -2616,6 +3240,10 @@ update-notifier@^2.2.0: semver-diff "^2.0.0" xdg-basedir "^3.0.0" +upper-case@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" + url-parse-lax@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" @@ -2636,10 +3264,17 @@ utils-merge@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.0.tgz#0294fb922bb9375153541c4f7096231f287c8af8" -uuid@^3.0.0: +uuid@^3.0.0, uuid@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" +validate-npm-package-license@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc" + dependencies: + spdx-correct "~1.0.0" + spdx-expression-parse "~1.0.0" + vary@^1: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" @@ -2652,6 +3287,10 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" +webber@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/webber/-/webber-0.0.1.tgz#bb536de20d0e992e8da23eca33fe4edff2c46476" + websocket-driver@>=0.5.1: version "0.7.0" resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.0.tgz#0caf9d2d755d93aee049d4bdd0d3fe2cca2a24eb" @@ -2663,7 +3302,11 @@ websocket-extensions@>=0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29" -which@^1.2.9: +which-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" + +which@1, which@^1.2.9: version "1.3.0" resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" dependencies: @@ -2685,6 +3328,13 @@ wordwrap@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -2707,10 +3357,42 @@ xdg-basedir@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" +xml-char-classes@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/xml-char-classes/-/xml-char-classes-1.0.0.tgz#64657848a20ffc5df583a42ad8a277b4512bbc4d" + xtend@^4.0.0, xtend@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" +y18n@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" + yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + +yargs-parser@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" + dependencies: + camelcase "^3.0.0" + +yargs@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" + dependencies: + camelcase "^3.0.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^1.4.0" + read-pkg-up "^1.0.1" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^1.0.2" + which-module "^1.0.0" + y18n "^3.2.1" + yargs-parser "^5.0.0" From 56f0176d92d5d1587f234e9480fe8c6f81f90d14 Mon Sep 17 00:00:00 2001 From: Pl4gue Date: Thu, 21 Dec 2017 13:17:42 +0100 Subject: [PATCH 55/61] travis badge --- static-parts/README-start.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static-parts/README-start.md b/static-parts/README-start.md index f1e937dff..ae6f9909a 100644 --- a/static-parts/README-start.md +++ b/static-parts/README-start.md @@ -1,6 +1,6 @@ ![Logo](/logo.png) -# 30 seconds of code [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/30-seconds-of-code/Lobby) ![Travis Build](https://travis-ci.org/Chalarangelo/30-seconds-of-code.svg?branch=master) +# 30 seconds of code [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/30-seconds-of-code/Lobby) [![Travis Build](https://travis-ci.org/Chalarangelo/30-seconds-of-code.svg?branch=master)](https://travis-ci.org/Chalarangelo/30-seconds-of-code) > Curated collection of useful Javascript snippets that you can understand in 30 seconds or less. - Use Ctrl + F or command + F to search for a snippet. From 651dd073b34394cef98f821f88e8c142d7d009c6 Mon Sep 17 00:00:00 2001 From: Pl4gue Date: Thu, 21 Dec 2017 12:19:59 +0000 Subject: [PATCH 56/61] Travis build: 13 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7f7d9a56d..8729cc6c9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![Logo](/logo.png) -# 30 seconds of code [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/30-seconds-of-code/Lobby) ![Travis Build](https://travis-ci.org/Chalarangelo/30-seconds-of-code.svg?branch=master) +# 30 seconds of code [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/30-seconds-of-code/Lobby) [![Travis Build](https://travis-ci.org/Chalarangelo/30-seconds-of-code.svg?branch=master)](https://travis-ci.org/Chalarangelo/30-seconds-of-code) > Curated collection of useful Javascript snippets that you can understand in 30 seconds or less. - Use Ctrl + F or command + F to search for a snippet. From 2ba9279b8cd996b7e771a38a954c7e217364992f Mon Sep 17 00:00:00 2001 From: King Date: Thu, 21 Dec 2017 07:24:10 -0500 Subject: [PATCH 57/61] update fibonacci Array() -> Array.from() --- snippets/fibonacci.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snippets/fibonacci.md b/snippets/fibonacci.md index a669c344d..1c15dc352 100644 --- a/snippets/fibonacci.md +++ b/snippets/fibonacci.md @@ -7,6 +7,6 @@ Use `Array.reduce()` to add values into the array, using the sum of the last two ```js const fibonacci = n => - Array(n).fill(0).reduce((acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), []); + Array.from({ length: n}).map(v => 0).reduce((acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), []); // fibonacci(5) -> [0,1,1,2,3] ``` From 257efc2a00972bf421a2d983b02c960a8c53a39a Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Thu, 21 Dec 2017 14:26:15 +0200 Subject: [PATCH 58/61] Update httpsRedirect.md --- snippets/httpsRedirect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snippets/httpsRedirect.md b/snippets/httpsRedirect.md index 26f8ec2c9..b1b851320 100644 --- a/snippets/httpsRedirect.md +++ b/snippets/httpsRedirect.md @@ -6,6 +6,6 @@ Use `location.protocol` to get the protocol currently being used. If it's not HT ```js const httpsRedirect = () => { - if(location.protocol !== "https:") location.replace("https://" + location.href.split("//")[1]); + if(location.protocol !== "https:") location.replace("https://" + location.href.split("//")[1]); } ``` From 4ff3f4f5fda112d3d22f2026e2f8d5abd5e1cf95 Mon Sep 17 00:00:00 2001 From: King Date: Thu, 21 Dec 2017 07:26:40 -0500 Subject: [PATCH 59/61] ran npm run builder --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d48327a92..2aabd659e 100644 --- a/README.md +++ b/README.md @@ -1242,7 +1242,7 @@ Use `Array.reduce()` to add values into the array, using the sum of the last two ```js const fibonacci = n => - Array(n).fill(0).reduce((acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), []); + Array.from({ length: n}).map(v => 0).reduce((acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), []); // fibonacci(5) -> [0,1,1,2,3] ``` From 2522e489c5ad64f3082e1fd97c52ce8435829688 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Thu, 21 Dec 2017 14:30:57 +0200 Subject: [PATCH 60/61] Updating guidelines and a tag --- COLLABORATING.md | 2 +- tag_database | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/COLLABORATING.md b/COLLABORATING.md index 119870112..fdf6ab673 100644 --- a/COLLABORATING.md +++ b/COLLABORATING.md @@ -17,8 +17,8 @@ As a member of the team that manages **30 seconds of code**, you have the follow - **For a pull request to be considered ready to merge, there should be at least 2 (preferrably 3) reviews approving it for merge.** There are, however, certain exceptions: - **If a pull request only fixes typos**, there is no need to wait for a second reviewer (unless you are not absolutely certain these were not typos in the first place). - **If a pull request only clarifies a snippet's description or enforces the styleguide for an existng snippet**, you might be able to merge it without getting a second reviewer to review it, but only if you are absolutely certain about it. + - **Make sure pull requests pass the Travis CI build**, otherwise try and find out what's wrong and inform the author of the pull request. - **Changes to build scripts, guidelines and things that might break the processes we have in place need to be reviewed by [@Chalarangelo](https://github.com/Chalarangelo)** (this is temporary, but we need a baseline to make sure we break as few things as possible in the beginning). - **After merging a pull request, make sure to check for untagged snippets and tag them appropriately.** Try to keep all snippets tagged, so that the list and website are up to date. -- (*Irrelevant once we set up CI*) **You should rebuild the README and website after merging pull requests and push to the repository, so that both files are up to date.** - **If you make changes or additions to existing snippets or if you want to add you own snippets, you will go through the pull request process that everyone else goes.** Exceptions apply similarly to the ones mentioned above about merging pull requests (i.e. typos, description clarification and the way script and build process changes are handled). Pull requests suggested by collaborators should be reviewed by at least two other collaborators to be considered ready to merge. - **Pull requests that are inactive for over a week should be closed or put on hold.** diff --git a/tag_database b/tag_database index 84063917c..fa488eabf 100644 --- a/tag_database +++ b/tag_database @@ -49,6 +49,7 @@ groupBy:array hammingDistance:math head:array hexToRGB:utility +httpsRedirect:browser initial:array initialize2DArray:array initializeArrayWithRange:array From af7275dd75f001f410c8e16a0a392574313788ca Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Thu, 21 Dec 2017 14:48:27 +0200 Subject: [PATCH 61/61] Tag --- README.md | 35 +++++++++++++++++++++++++++++++++++ docs/index.html | 23 ++++++++++++++++++++++- tag_database | 1 + 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ba24c7d61..895d8fc38 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,7 @@ * [`elementIsVisibleInViewport`](#elementisvisibleinviewport) * [`getScrollPosition`](#getscrollposition) * [`getURLParameters`](#geturlparameters) +* [`httpsRedirect`](#httpsredirect) * [`redirect`](#redirect) * [`scrollToTop`](#scrolltotop) @@ -100,6 +101,7 @@ * [`palindrome`](#palindrome) * [`percentile`](#percentile) * [`powerset`](#powerset) +* [`primes`](#primes) * [`randomIntegerInRange`](#randomintegerinrange) * [`randomNumberInRange`](#randomnumberinrange) * [`round`](#round) @@ -901,6 +903,20 @@ const getURLParameters = url => [⬆ back to top](#table-of-contents) +### httpsRedirect + +Redirects the page to HTTPS if its currently in HTTP. Also, pressing the back button doesn't take it back to the HTTP page as its replaced in the history. + +Use `location.protocol` to get the protocol currently being used. If it's not HTTPS, use `location.replace()` to replace the existing page with the HTTPS version of the page. Use `location.href` to get the full address, split it with `String.split()` and remove the protocol part of the URL. + +```js +const httpsRedirect = () => { + if(location.protocol !== "https:") location.replace("https://" + location.href.split("//")[1]); +} +``` + +[⬆ back to top](#table-of-contents) + ### redirect Redirects to a specified URL. @@ -1439,6 +1455,25 @@ const powerset = arr => [⬆ back to top](#table-of-contents) +### primes + +Generates primes up to a given number, using the Sieve of Eratosthenes. + +Generate an array from `2` to the given number. Use `Array.filter()` to filter out the values divisible by any number from `2` to the square root of the provided number. + +```js +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; +} +// primes(10) -> [2,3,5,7] +``` + +[⬆ back to top](#table-of-contents) + ### randomIntegerInRange Returns a random integer in the specified range. diff --git a/docs/index.html b/docs/index.html index 2a083f30b..bad72481f 100644 --- a/docs/index.html +++ b/docs/index.html @@ -92,6 +92,7 @@ elementIsVisibleInViewport getScrollPosition getURLParameters +httpsRedirect redirect scrollToTop @@ -131,6 +132,7 @@ palindrome percentile powerset +primes randomIntegerInRange randomNumberInRange round @@ -593,6 +595,13 @@ Pass location.search as the argument to apply to the current ); // getURLParameters('http://url.com/page?name=Adam&surname=Smith') -> {name: 'Adam', surname: 'Smith'} +

httpsRedirect

+

Redirects the page to HTTPS if its currently in HTTP. Also, pressing the back button doesn't take it back to the HTTP page as its replaced in the history.

+

Use location.protocol to get the protocol currently being used. If it's not HTTPS, use location.replace() to replace the existing page with the HTTPS version of the page. Use location.href to get the full address, split it with String.split() and remove the protocol part of the URL.

+
const httpsRedirect = () => {
+  if(location.protocol !== "https:") location.replace("https://" + location.href.split("//")[1]);
+}
+

redirect

Redirects to a specified URL.

Use window.location.href or window.location.replace() to redirect to url. @@ -789,7 +798,7 @@ Throws an exception if n is a negative number.

Create an empty array of the specific length, initializing the first two values (0 and 1). Use Array.reduce() to add values into the array, using the sum of the last two values, except for the first two.

const fibonacci = n =>
-  Array(n).fill(0).reduce((acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), []);
+  Array.from({ length: n}).map(v => 0).reduce((acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), []);
 // fibonacci(5) -> [0,1,1,2,3]
 

gcd

@@ -899,6 +908,18 @@ Then, split('') into individual characters, reverse(), arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]); // powerset([1,2]) -> [[], [1], [2], [2,1]] +

primes

+

Generates primes up to a given number, using the Sieve of Eratosthenes.

+

Generate an array from 2 to the given number. Use Array.filter() to filter out the values divisible by any number from 2 to the square root of the provided number.

+
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; 
+}
+// primes(10) -> [2,3,5,7] 
+

randomIntegerInRange

Returns a random integer in the specified range.

Use Math.random() to generate a random number and map it to the desired range, using Math.floor() to make it an integer.

diff --git a/tag_database b/tag_database index fa488eabf..4c19589ef 100644 --- a/tag_database +++ b/tag_database @@ -81,6 +81,7 @@ percentile:math pick:array pipe:function powerset:math +primes:math promisify:function pull:array pullAtIndex:array