diff --git a/.gitignore b/.gitignore index bc23f6a88..9fe5cb489 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ node_modules/ - currentSnippet\.js +*.md.temp.js diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d2bdbf7e1..618a99b1a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,7 +7,8 @@ Here's what you can do to help: - [Open issues](https://github.com/Chalarangelo/30-seconds-of-code/issues/new) for things you want to see added or modified. - Be part of the discussion by helping out with [existing issues](https://github.com/Chalarangelo/30-seconds-of-code/issues) or talking on our [gitter channel](https://gitter.im/30-seconds-of-code/Lobby). - Submit [pull requests](https://github.com/Chalarangelo/30-seconds-of-code/pulls) with snippets you have created (see below for guidelines). -- Fix typos in existing snippets or run `npm run lint "snippet-name.md"` on unlinted snippets (yes, this is something we actually want help with). +- Tag untagged snippets by running `npm run tagger` and adding the appropriate tag next to the script name in `tag_database`. +- Fix typos in existing snippets or run `npm run linter` to lint unlinted snippets (yes, this is something we actually want help with, as this can take quite a while to run). ### Snippet submission and Pull request guidelines diff --git a/README.md b/README.md index 65a72b1a0..7160b9afb 100644 --- a/README.md +++ b/README.md @@ -9,108 +9,116 @@ ## Table of Contents -* [Anagrams of string (with duplicates)](#anagrams-of-string-with-duplicates) +### Array * [Array concatenation](#array-concatenation) * [Array difference](#array-difference) * [Array intersection](#array-intersection) * [Array union](#array-union) * [Average of array of numbers](#average-of-array-of-numbers) -* [Bottom visible](#bottom-visible) -* [Capitalize first letter of every word](#capitalize-first-letter-of-every-word) -* [Capitalize first letter](#capitalize-first-letter) -* [Chain asynchronous functions](#chain-asynchronous-functions) -* [Check for palindrome](#check-for-palindrome) * [Chunk array](#chunk-array) -* [Collatz algorithm](#collatz-algorithm) * [Compact](#compact) * [Count occurrences of a value in array](#count-occurrences-of-a-value-in-array) -* [Current URL](#current-url) -* [Curry](#curry) * [Deep flatten array](#deep-flatten-array) -* [Distance between two points](#distance-between-two-points) -* [Divisible by number](#divisible-by-number) * [Drop elements in array](#drop-elements-in-array) -* [Element is visible in viewport](#element-is-visible-in-viewport) -* [Escape regular expression](#escape-regular-expression) -* [Even or odd number](#even-or-odd-number) -* [Factorial](#factorial) -* [Fibonacci array generator](#fibonacci-array-generator) * [Fill array](#fill-array) * [Filter out non unique values in an array](#filter-out-non-unique-values-in-an-array) * [Flatten array up to depth](#flatten-array-up-to-depth) * [Flatten array](#flatten-array) * [Get max value from array](#get-max-value-from-array) * [Get min value from array](#get-min-value-from-array) -* [Get native type of value](#get-native-type-of-value) -* [Get scroll position](#get-scroll-position) -* [Greatest common divisor (GCD)](#greatest-common-divisor-gcd) * [Group by](#group-by) -* [Hamming distance](#hamming-distance) * [Head of list](#head-of-list) * [Initial of list](#initial-of-list) * [Initialize array with range](#initialize-array-with-range) * [Initialize array with values](#initialize-array-with-values) +* [Last of list](#last-of-list) +* [Median of array of numbers](#median-of-array-of-numbers) +* [Nth element of array](#nth-element-of-array) +* [Pick](#pick) +* [Shuffle array](#shuffle-array) +* [Similarity between arrays](#similarity-between-arrays) +* [Sum of array of numbers](#sum-of-array-of-numbers) +* [Tail of list](#tail-of-list) +* [Take](#take) +* [Unique values of array](#unique-values-of-array) + +### Browser +* [Bottom visible](#bottom-visible) +* [Current URL](#current-url) +* [Element is visible in viewport](#element-is-visible-in-viewport) +* [Get scroll position](#get-scroll-position) +* [Redirect to URL](#redirect-to-url) +* [Scroll to top](#scroll-to-top) + +### Date +* [Get days difference between dates](#get-days-difference-between-dates) + +### Function +* [Chain asynchronous functions](#chain-asynchronous-functions) +* [Curry](#curry) +* [Pipe](#pipe) +* [Promisify](#promisify) +* [Run promises in series](#run-promises-in-series) +* [Sleep](#sleep) + +### Math +* [Collatz algorithm](#collatz-algorithm) +* [Distance between two points](#distance-between-two-points) +* [Divisible by number](#divisible-by-number) +* [Even or odd number](#even-or-odd-number) +* [Factorial](#factorial) +* [Fibonacci array generator](#fibonacci-array-generator) +* [Greatest common divisor (GCD)](#greatest-common-divisor-gcd) +* [Hamming distance](#hamming-distance) +* [Percentile](#percentile) +* [Powerset](#powerset) +* [Round number to n digits](#round-number-to-n-digits) +* [Standard deviation](#standard-deviation) + +### Media +* [Speech synthesis (experimental)](#speech-synthesis-experimental) + +### Object +* [Object from key value pairs](#object-from-key-value-pairs) +* [Object to key value pairs](#object-to-key-value-pairs) +* [Shallow clone object](#shallow-clone-object) + +### String +* [Anagrams of string (with duplicates)](#anagrams-of-string-with-duplicates) +* [Capitalize first letter of every word](#capitalize-first-letter-of-every-word) +* [Capitalize first letter](#capitalize-first-letter) +* [Check for palindrome](#check-for-palindrome) +* [Reverse a string](#reverse-a-string) +* [Sort characters in string (alphabetical)](#sort-characters-in-string-alphabetical) +* [Truncate a string](#truncate-a-string) + +### Utility +* [Escape regular expression](#escape-regular-expression) +* [Get native type of value](#get-native-type-of-value) * [Is array](#is-array) * [Is boolean](#is-boolean) * [Is function](#is-function) * [Is number](#is-number) * [Is string](#is-string) * [Is symbol](#is-symbol) -* [Last of list](#last-of-list) * [Measure time taken by function](#measure-time-taken-by-function) -* [Median of array of numbers](#median-of-array-of-numbers) -* [Object from key value pairs](#object-from-key-value-pairs) -* [Object to key value pairs](#object-to-key-value-pairs) +* [Number to array of digits](#number-to-array-of-digits) * [Ordinal suffix of number](#ordinal-suffix-of-number) -* [Percentile](#percentile) -* [Pick](#pick) -* [Pipe](#pipe) -* [Powerset](#powerset) -* [Promisify](#promisify) * [Random integer in range](#random-integer-in-range) * [Random number in range](#random-number-in-range) -* [Redirect to URL](#redirect-to-url) -* [Reverse a string](#reverse-a-string) * [RGB to hexadecimal](#rgb-to-hexadecimal) -* [Run promises in series](#run-promises-in-series) -* [Scroll to top](#scroll-to-top) -* [Shuffle array](#shuffle-array) -* [Similarity between arrays](#similarity-between-arrays) -* [Sleep](#sleep) -* [Sort characters in string (alphabetical)](#sort-characters-in-string-alphabetical) -* [Standard deviation](#standard-deviation) -* [Sum of array of numbers](#sum-of-array-of-numbers) * [Swap values of two variables](#swap-values-of-two-variables) -* [Tail of list](#tail-of-list) -* [Take](#take) -* [Truncate a string](#truncate-a-string) -* [Unique values of array](#unique-values-of-array) * [URL parameters](#url-parameters) * [UUID generator](#uuid-generator) * [Validate email](#validate-email) * [Validate number](#validate-number) * [Value or default](#value-or-default) -### Anagrams of string (with duplicates) +## Array -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`. - -```js -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)), []); -}; -// anagrams('abc') -> ['abc','acb','bac','bca','cab','cba'] -``` - -[⬆ back to top](#table-of-contents) ### Array concatenation -Use `Array.concat()` to concatenate and array with any additional arrays and/or values, specified in `args`. +Use `Array.concat()` to concatenate an array with any additional arrays and/or values, specified in `args`. ```js const arrayConcat = (arr, ...args) => arr.concat(...args); @@ -118,36 +126,40 @@ const arrayConcat = (arr, ...args) => arr.concat(...args); ``` [⬆ back to top](#table-of-contents) + ### Array difference Create a `Set` from `b`, then use `Array.filter()` on `a` to only keep values not contained in `b`. ```js -const difference = (a, b) => { const s = new Set(b); return a.filter(x => !s.has(x)); } +const difference = (a, b) => { const s = new Set(b); return a.filter(x => !s.has(x)); }; // difference([1,2,3], [1,2]) -> [3] ``` [⬆ back to top](#table-of-contents) + ### Array intersection Create a `Set` from `b`, then use `Array.filter()` on `a` to only keep values contained in `b`. ```js -const intersection = (a, b) => { const s = new Set(b); return a.filter(x => s.has(x)); } +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] ``` [⬆ back to top](#table-of-contents) + ### Array union Create a `Set` with all values of `a` and `b` and convert to an array. ```js -const union = (a, b) => Array.from(new Set([...a, ...b])) +const union = (a, b) => Array.from(new Set([...a, ...b])); // union([1,2,3], [4,3,2]) -> [1,2,3,4] ``` [⬆ back to top](#table-of-contents) + ### Average of 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. @@ -158,6 +170,329 @@ const average = arr => arr.reduce((acc, val) => acc + val, 0) / arr.length; ``` [⬆ back to top](#table-of-contents) + +### Chunk array + +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. + +```js +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] +``` + +[⬆ back to top](#table-of-contents) + +### Compact + +Use `Array.filter()` to filter out falsey values (`false`, `null`, `0`, `""`, `undefined`, and `NaN`). + +```js +const compact = (arr) => arr.filter(v => v); +// compact([0, 1, false, 2, '', 3, 'a', 'e'*23, NaN, 's', 34]) -> [ 1, 2, 3, 'a', 's', 34 ] +``` + +[⬆ back to top](#table-of-contents) + +### Count occurrences of a value in array + +Use `Array.reduce()` to increment a counter each time you encounter the specific value inside the array. + +```js +const countOccurrences = (arr, value) => arr.reduce((a, v) => v === value ? a + 1 : a + 0, 0); +// countOccurrences([1,1,2,1,2,3], 1) -> 3 +``` + +[⬆ back to top](#table-of-contents) + +### Deep flatten array + +Use recursion. +Use `Array.reduce()` to get all elements that are not arrays, flatten each element that is an array. + +```js +const deepFlatten = arr => + arr.reduce((a, v) => a.concat(Array.isArray(v) ? deepFlatten(v) : v), []); +// deepFlatten([1,[2],[[3],4],5]) -> [1,2,3,4,5] +``` + +[⬆ back to top](#table-of-contents) + +### Drop elements in array + +Loop through the array, using `Array.shift()` to drop the first element of the array until the returned value from the function is `true`. +Returns the remaining elements. + +```js +const dropElements = (arr, func) => { + while (arr.length > 0 && !func(arr[0])) arr.shift(); + return arr; +}; +// dropElements([1, 2, 3, 4], n => n >= 3) -> [3,4] +``` + +[⬆ back to top](#table-of-contents) + +### Fill array + +Use `Array.map()` to map values between `start` (inclusive) and `end` (exclusive) to `value`. +Omit `start` to start at the first element and/or `end` to finish at the last. + +```js +const fillArray = (arr, value, start = 0, end = arr.length) => + arr.map((v, i) => i >= start && i < end ? value : v); +// fillArray([1,2,3,4],'8',1,3) -> [1,'8','8',4] +``` + +[⬆ back to top](#table-of-contents) + +### Filter out non-unique values in an array + +Use `Array.filter()` for an array containing only the unique values. + +```js +const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i)); +// filterNonUnique([1,2,2,3,4,4,5]) -> [1,3,5] +``` + +[⬆ back to top](#table-of-contents) + +### Flatten array up to 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). + +```js +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] +``` + +[⬆ back to top](#table-of-contents) + +### Flatten array + +Use `Array.reduce()` to get all elements inside the array and `concat()` to flatten them. + +```js +const flatten = arr => arr.reduce((a, v) => a.concat(v), []); +// flatten([1,[2],3,4]) -> [1,2,3,4] +``` + +[⬆ back to top](#table-of-contents) + +### Get max value from array + +Use `Math.max()` combined with the spread operator (`...`) to get the maximum value in the array. + +```js +const arrayMax = arr => Math.max(...arr); +// arrayMax([10, 1, 5]) -> 10 +``` + +[⬆ back to top](#table-of-contents) + +### Get min value from array + +Use `Math.min()` combined with the spread operator (`...`) to get the minimum value in the array. + +```js +const arrayMin = arr => Math.min(...arr); +// arrayMin([10, 1, 5]) -> 1 +``` + +[⬆ back to top](#table-of-contents) + +### Group by + +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. + +```js +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']} +``` + +[⬆ back to top](#table-of-contents) + +### Head of list + +Use `arr[0]` to return the first element of the passed array. + +```js +const head = arr => arr[0]; +// head([1,2,3]) -> 1 +``` + +[⬆ back to top](#table-of-contents) + +### Initial of list + +Use `arr.slice(0,-1)`to return all but the last element of the array. + +```js +const initial = arr => arr.slice(0, -1); +// initial([1,2,3]) -> [1,2] +``` + +[⬆ back to top](#table-of-contents) + +### Initialize array with range + +Use `Array(end-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`. + +```js +const initializeArrayRange = (end, start = 0) => + Array.apply(null, Array(end - start)).map((v, i) => i + start); +// initializeArrayRange(5) -> [0,1,2,3,4] +``` + +[⬆ back to top](#table-of-contents) + +### Initialize array with 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`. + +```js +const initializeArray = (n, value = 0) => Array(n).fill(value); +// initializeArray(5, 2) -> [2,2,2,2,2] +``` + +[⬆ back to top](#table-of-contents) + +### Last of list + +Use `arr.slice(-1)[0]` to get the last element of the given array. + +```js +const last = arr => arr.slice(-1)[0]; +// last([1,2,3]) -> 3 +``` + +[⬆ back to top](#table-of-contents) + +### Median of 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. + +```js +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 +``` + +[⬆ back to top](#table-of-contents) + +### Nth element of 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. + +```js +const nth = (arr, n=0) => (n>0? arr.slice(n,n+1) : arr.slice(n))[0]; +// nth(['a','b','c'],1) -> 'b' +// nth(['a','b','b']-2) -> 'a' +``` + +[⬆ back to top](#table-of-contents) + +### Pick + +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. + +```js +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 } +// pick(object, ['a', 'c'])['a'] -> 1 +``` + +[⬆ back to top](#table-of-contents) + +### Shuffle array + +Use `Array.sort()` to reorder elements, using `Math.random()` in the comparator. + +```js +const shuffle = arr => arr.sort(() => Math.random() - 0.5); +// shuffle([1,2,3]) -> [2,3,1] +``` + +[⬆ back to top](#table-of-contents) + +### Similarity between arrays + +Use `filter()` to remove values that are not part of `values`, determined using `includes()`. + +```js +const similarity = (arr, values) => arr.filter(v => values.includes(v)); +// similarity([1,2,3], [1,2,4]) -> [1,2] +``` + +[⬆ back to top](#table-of-contents) + +### Sum of array of numbers + +Use `Array.reduce()` to add each value to an accumulator, initialized with a value of `0`. + +```js +const sum = arr => arr.reduce((acc, val) => acc + val, 0); +// sum([1,2,3,4]) -> 10 +``` + +[⬆ back to top](#table-of-contents) + +### Tail of list + +Return `arr.slice(1)` if the array's `length` is more than `1`, otherwise return the whole array. + +```js +const tail = arr => arr.length > 1 ? arr.slice(1) : arr; +// tail([1,2,3]) -> [2,3] +// tail([1]) -> [1] +``` + +[⬆ back to top](#table-of-contents) + +### Take + +Use `Array.slice()` to create a slice of the array with `n` elements taken from the beginning. + +```js +const take = (arr, n = 1) => arr.slice(0, n); +// take([1, 2, 3], 5) -> [1, 2, 3] +// take([1, 2, 3], 0) -> [] +``` + +[⬆ back to top](#table-of-contents) + +### Unique values of array + +Use ES6 `Set` and the `...rest` operator to discard all duplicated values. + +```js +const unique = arr => [...new Set(arr)]; +// unique([1,2,2,3,4,4,5]) -> [1,2,3,4,5] +``` + +[⬆ back to top](#table-of-contents) +## Browser + ### Bottom visible Use `scrollY`, `scrollHeight` and `clientHeight` to determine if the bottom of the page is visible. @@ -169,28 +504,98 @@ const bottomVisible = _ => ``` [⬆ back to top](#table-of-contents) -### Capitalize first letter of every word -Use `replace()` to match the first character of each word and `toUpperCase()` to capitalize it. +### Current URL + +Use `window.location.href` to get current URL. ```js -const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase()); -// capitalizeEveryWord('hello world!') -> 'Hello World!' +const currentUrl = _ => window.location.href; +// currentUrl() -> 'https://google.com' ``` [⬆ back to top](#table-of-contents) -### Capitalize first letter -Use `slice(0,1)` and `toUpperCase()` to capitalize first letter, `slice(1)` to get the rest of the string. -Omit the `lowerRest` parameter to keep the rest of the string intact, or set it to `true` to convert to lower case. +### Element is visible in viewport + +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. ```js -const capitalize = (str, lowerRest = false) => - str.slice(0, 1).toUpperCase() + (lowerRest ? str.slice(1).toLowerCase() : str.slice(1)); -// capitalize('myName', true) -> 'Myname' +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; +}; +// 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) ``` [⬆ back to top](#table-of-contents) + +### Get scroll position + +Use `pageXOffset` and `pageYOffset` if they are defined, otherwise `scrollLeft` and `scrollTop`. +You can omit `el` to use a default value of `window`. + +```js +const getScrollPos = (el = window) => + ({x: (el.pageXOffset !== undefined) ? el.pageXOffset : el.scrollLeft, + y: (el.pageYOffset !== undefined) ? el.pageYOffset : el.scrollTop}); +// getScrollPos() -> {x: 0, y: 200} +``` + +[⬆ back to top](#table-of-contents) + +### Redirect to 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`). + +```js +const redirect = (url, asLink = true) => + asLink ? window.location.href = url : window.location.replace(url); +// redirect('https://google.com') +``` + +[⬆ back to top](#table-of-contents) + +### Scroll to top + +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. + +```js +const scrollToTop = _ => { + const c = document.documentElement.scrollTop || document.body.scrollTop; + if (c > 0) { + window.requestAnimationFrame(scrollToTop); + window.scrollTo(0, c - c / 8); + } +}; +// scrollToTop() +``` + +[⬆ back to top](#table-of-contents) +## Date + +### Get days difference between dates + +Calculate the difference (in days) between to `Date` objects. + +```js +const getDaysDiffBetweenDates = (dateInitial, dateFinal) => (dateFinal - dateInitial) / (1000 * 3600 * 24); +// getDaysDiffBetweenDates(new Date("2017-12-13"), new Date("2017-12-22")) -> 9 +``` + +[⬆ back to top](#table-of-contents) +## Function + ### Chain asynchronous functions Loop through an array of functions containing asynchronous events, calling `next` when each asynchronous event has completed. @@ -207,74 +612,7 @@ chainAsync([ ``` [⬆ back to top](#table-of-contents) -### Check for palindrome -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()`. - -```js -const palindrome = str => { - const s = str.toLowerCase().replace(/[\W_]/g,''); - return s === s.split('').reverse().join(''); -} -// palindrome('taco cat') -> true - ``` - -[⬆ back to top](#table-of-contents) -### Chunk array - -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. - -```js -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] -``` - -[⬆ back to top](#table-of-contents) -### Collatz algorithm - -If `n` is even, return `n/2`. Otherwise return `3n+1`. - -```js -const collatz = n => (n % 2 == 0) ? (n/2) : (3*n+1); -// collatz(8) --> 4 -// collatz(5) --> 16 -``` - -[⬆ back to top](#table-of-contents) -### Compact - -Use `Array.filter()` to filter out falsey values (`false`, `null`, `0`, `""`, `undefined`, and `NaN`). - -```js -const compact = (arr) => arr.filter(v => v); -// compact([0, 1, false, 2, '', 3, 'a', 'e'*23, NaN, 's', 34]) -> [ 1, 2, 3, 'a', 's', 34 ] -``` - -[⬆ back to top](#table-of-contents) -### Count occurrences of a value in array - -Use `Array.reduce()` to increment a counter each time you encounter the specific value inside the array. - -```js -const countOccurrences = (arr, value) => arr.reduce((a, v) => v === value ? a + 1 : a + 0, 0); -// countOccurrences([1,1,2,1,2,3], 1) -> 3 -``` - -[⬆ back to top](#table-of-contents) -### Current URL - -Use `window.location.href` to get current URL. - -```js -const currentUrl = _ => window.location.href; -// currentUrl() -> 'https://google.com' -``` - -[⬆ back to top](#table-of-contents) ### Curry Use recursion. @@ -283,469 +621,16 @@ 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`. ```js -const curry = (f, arity = f.length, next) => - (next = prevArgs => - nextArg => { - const args = [ ...prevArgs, nextArg ]; - return args.length >= arity ? f(...args) : next(args); - } - )([]); +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 ``` [⬆ back to top](#table-of-contents) -### Deep flatten array -Use recursion. -Use `Array.reduce()` to get all elements that are not arrays, flatten each element that is an array. - -```js -const deepFlatten = arr => - arr.reduce((a, v) => a.concat(Array.isArray(v) ? deepFlatten(v) : v), []); -// deepFlatten([1,[2],[[3],4],5]) -> [1,2,3,4,5] -``` - -[⬆ back to top](#table-of-contents) -### Distance between two points - -Use `Math.hypot()` to calculate the Euclidean distance between two points. - -```js -const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0); -// distance(1,1, 2,3) -> 2.23606797749979 -``` - -[⬆ back to top](#table-of-contents) -### Divisible by number - -Use the modulo operator (`%`) to check if the remainder is equal to `0`. - -```js -const isDivisible = (dividend, divisor) => dividend % divisor === 0; -// isDivisible(6,3) -> true -``` - -[⬆ back to top](#table-of-contents) -### Drop elements in array - -Loop through the array, using `Array.shift()` to drop the first element of the array until the returned value from the function is `true`. -Returns the remaining elements. - -```js -const dropElements = (arr,func) => { - while(arr.length > 0 && !func(arr[0])) arr.shift(); - return arr; -} -// dropElements([1, 2, 3, 4], n => n >= 3) -> [3,4] -``` - -[⬆ back to top](#table-of-contents) -### Element is visible in viewport - -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. - -```js -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; -} -// 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) -``` - -[⬆ back to top](#table-of-contents) -### Escape regular expression - -Use `replace()` to escape special characters. - -```js -const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); -// escapeRegExp('(test)') -> \\(test\\) -``` - -[⬆ back to top](#table-of-contents) -### Even or odd number - -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. - -```js -const isEven = num => num % 2 === 0; -// isEven(3) -> false -``` - -[⬆ back to top](#table-of-contents) -### Factorial - -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`. - -```js -const factorial = n => n <= 1 ? 1 : n * factorial(n - 1); -// factorial(6) -> 720 -``` - -[⬆ back to top](#table-of-contents) -### Fibonacci array generator - -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. - -```js -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] -``` - -[⬆ back to top](#table-of-contents) -### Fill array - -Use `Array.map()` to map values between `start` (inclusive) and `end` (exclusive) to `value`. -Omit `start` to start at the first element and/or `end` to finish at the last. - -```js -const fillArray = (arr, value, start = 0, end = arr.length) => - arr.map((v,i) => i>=start && i [1,'8','8',4] -``` - -[⬆ back to top](#table-of-contents) -### Filter out non-unique values in an array - -Use `Array.filter()` for an array containing only the unique values. - -```js -const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i)); -// filterNonUnique([1,2,2,3,4,4,5]) -> [1,3,5] -``` - -[⬆ back to top](#table-of-contents) -### Flatten array up to 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). - -```js -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] -``` - -[⬆ back to top](#table-of-contents) -### Flatten array - -Use `Array.reduce()` to get all elements inside the array and `concat()` to flatten them. - -```js -const flatten = arr => arr.reduce((a, v) => a.concat(v), []); -// flatten([1,[2],3,4]) -> [1,2,3,4] -``` - -[⬆ back to top](#table-of-contents) -### Get max value from array - -Use `Math.max()` combined with the spread operator (`...`) to get the maximum value in the array. - -```js -const arrayMax = arr => Math.max(...arr); -// arrayMax([10, 1, 5]) -> 10 -``` - -[⬆ back to top](#table-of-contents) -### Get min value from array - -Use `Math.min()` combined with the spread operator (`...`) to get the minimum value in the array. - -```js -const arrayMin = arr => Math.min(...arr); -// arrayMin([10, 1, 5]) -> 1 -``` - -[⬆ back to top](#table-of-contents) -### Get native type of value - -Returns lower-cased constructor name of value, "undefined" or "null" if value is undefined or null - -```js -const getType = v => - v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name.toLowerCase(); -// getType(new Set([1,2,3])) -> "set" -``` - -[⬆ back to top](#table-of-contents) -### Get scroll position - -Use `pageXOffset` and `pageYOffset` if they are defined, otherwise `scrollLeft` and `scrollTop`. -You can omit `el` to use a default value of `window`. - -```js -const getScrollPos = (el = window) => - ({x: (el.pageXOffset !== undefined) ? el.pageXOffset : el.scrollLeft, - y: (el.pageYOffset !== undefined) ? el.pageYOffset : el.scrollTop}); -// getScrollPos() -> {x: 0, y: 200} -``` - -[⬆ back to top](#table-of-contents) -### Greatest common divisor (GCD) - -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`. - -```js -const gcd = (x, y) => !y ? x : gcd(y, x % y); -// gcd (8, 36) -> 4 -``` - -[⬆ back to top](#table-of-contents) -### Group by - -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. - -```js -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']} -``` - -[⬆ back to top](#table-of-contents) -### Hamming distance - -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 `1`s in the string, using `match(/1/g)`. - -```js -const hammingDistance = (num1, num2) => - ((num1 ^ num2).toString(2).match(/1/g) || '').length; -// hammingDistance(2,3) -> 1 -``` - -[⬆ back to top](#table-of-contents) -### Head of list - -Use `arr[0]` to return the first element of the passed array. - -```js -const head = arr => arr[0]; -// head([1,2,3]) -> 1 -``` - -[⬆ back to top](#table-of-contents) -### Initial of list - -Use `arr.slice(0,-1)`to return all but the last element of the array. - -```js -const initial = arr => arr.slice(0, -1); -// initial([1,2,3]) -> [1,2] -``` - -[⬆ back to top](#table-of-contents) -### Initialize array with range - -Use `Array(end-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`. - -```js -const initializeArrayRange = (end, start = 0) => - Array.apply(null, Array(end - start)).map((v, i) => i + start); -// initializeArrayRange(5) -> [0,1,2,3,4] -``` - -[⬆ back to top](#table-of-contents) -### Initialize array with 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`. - -```js -const initializeArray = (n, value = 0) => Array(n).fill(value); -// initializeArray(5, 2) -> [2,2,2,2,2] -``` - -[⬆ back to top](#table-of-contents) -### Is array - -Use `Array.isArray()` to check if a value is classified as an array. - -```js -const isArray = val => val && Array.isArray(val); -// isArray(null) -> false -// isArray([1]) -> true -``` - -[⬆ back to top](#table-of-contents) -### Is boolean - -Use `typeof` to check if a value is classified as a boolean primitive. - -```js -const isBoolean = val => typeof val === 'boolean'; -// isBoolean(null) -> false -// isBoolean(false) -> true -``` - -[⬆ back to top](#table-of-contents) -### Is function - -Use `typeof` to check if a value is classified as a function primitive. - -```js -const isFunction = val => val && typeof val === 'function'; -// isFunction('x') -> false -// isFunction(x => x) -> true -``` - -[⬆ back to top](#table-of-contents) -### Is number - -Use `typeof` to check if a value is classified as a number primitive. - -```js -const isNumber = val => typeof val === 'number'; -// isNumber('1') -> false -// isNumber(1) -> true -``` - -[⬆ back to top](#table-of-contents) -### Is string - -Use `typeof` to check if a value is classified as a string primitive. - -```js -const isString = val => typeof val === 'string'; -// isString(10) -> false -// isString('10') -> true -``` - -[⬆ back to top](#table-of-contents) -### Is symbol - -Use `typeof` to check if a value is classified as a symbol primitive. - -```js -const isSymbol = val => typeof val === 'symbol'; -// isSymbol('x') -> false -// isSymbol(Symbol('x')) -> true -``` - -[⬆ back to top](#table-of-contents) -### Last of list - -Use `arr.slice(-1)[0]` to get the last element of the given array. - -```js -const last = arr => arr.slice(-1)[0]; -// last([1,2,3]) -> 3 -``` - -[⬆ back to top](#table-of-contents) -### Measure time taken by function - -Use `performance.now()` to get start and end time for the function, `console.log()` the time taken. -Pass a callback function as the argument. - -```js -const timeTaken = callback => { - const t0 = performance.now(), r = callback(); - console.log(performance.now() - t0); - return r; -}; -// timeTaken(() => Math.pow(2, 10)) -> 1024 (0.010000000009313226 logged in console) -``` - -[⬆ back to top](#table-of-contents) -### Median of 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. - -```js -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 -``` - -[⬆ back to top](#table-of-contents) -### Object from key-value pairs - -Use `Array.reduce()` to create and combine key-value pairs. - -```js -const objectFromPairs = arr => arr.reduce((a, v) => (a[v[0]] = v[1], a), {}); -// objectFromPairs([['a',1],['b',2]]) -> {a: 1, b: 2} -``` - -[⬆ back to top](#table-of-contents) -### Object to key-value pairs - -Use `Object.keys()` and `Array.map()` to iterate over the object's keys and produce an array with key-value pairs. - -```js -const objectToPairs = obj => Object.keys(obj).map(k => [k, obj[k]]); -// objectToPairs({a: 1, b: 2}) -> [['a',1],['b',2]]) -``` - -[⬆ back to top](#table-of-contents) -### Ordinal suffix of 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. - -```js -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]; -} -// toOrdinalSuffix("123") -> "123rd" -``` - -[⬆ back to top](#table-of-contents) -### Percentile - -Use `Array.reduce()` to calculate how many numbers are below the value and how many are the same value and -apply the percentile formula. - -```js -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 - ``` - -[⬆ back to top](#table-of-contents) -### Pick - -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. - -```js -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 } -// pick(object, ['a', 'c'])['a'] -> 1 -``` - -[⬆ back to top](#table-of-contents) ### Pipe Use `Array.reduce()` to pass value through functions. @@ -756,17 +641,7 @@ const pipe = (...funcs) => arg => funcs.reduce((acc, func) => func(acc), arg); ``` [⬆ back to top](#table-of-contents) -### Powerset -Use `Array.reduce()` combined with `Array.map()` to iterate over elements and combine into an array containing all combinations. - -```js -const powerset = arr => - arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]); -// powerset([1,2]) -> [[], [1], [2], [2,1]] -``` - -[⬆ back to top](#table-of-contents) ### Promisify Use currying to return a function returning a `Promise` that calls the original function. @@ -786,59 +661,7 @@ const promisify = func => ``` [⬆ back to top](#table-of-contents) -### Random integer in range -Use `Math.random()` to generate a random number and map it to the desired range, using `Math.floor()` to make it an integer. - -```js -const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min; -// randomIntegerInRange(0, 5) -> 2 -``` - -[⬆ back to top](#table-of-contents) -### Random number in range - -Use `Math.random()` to generate a random value, map it to the desired range using multiplication. - -```js -const randomInRange = (min, max) => Math.random() * (max - min) + min; -// randomInRange(2,10) -> 6.0211363285087005 -``` - -[⬆ back to top](#table-of-contents) -### Redirect to 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`). - -```js -const redirect = (url, asLink = true) => - asLink ? window.location.href = url : window.location.replace(url); -// redirect('https://google.com') -``` - -[⬆ back to top](#table-of-contents) -### Reverse a string - -Use array destructuring and `Array.reverse()` to reverse the order of the characters in the string. -Combine characters to get a string using `join('')`. - -```js -const reverseString = str => [...str].reverse().join(''); -// reverseString('foobar') -> 'raboof' -``` - -[⬆ back to top](#table-of-contents) -### RGB to hexadecimal - -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. - -```js -const rgbToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0'); -// rgbToHex(255, 165, 1) -> 'ffa501' -``` - -[⬆ back to top](#table-of-contents) ### Run promises in series Run an array of promises in series using `Array.reduce()` by creating a promise chain, where each promise returns the next promise when resolved. @@ -850,43 +673,7 @@ const series = ps => ps.reduce((p, next) => p.then(next), Promise.resolve()); ``` [⬆ back to top](#table-of-contents) -### Scroll to top -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. - -```js -const scrollToTop = _ => { - const c = document.documentElement.scrollTop || document.body.scrollTop; - if (c > 0) { - window.requestAnimationFrame(scrollToTop); - window.scrollTo(0, c - c / 8); - } -}; -// scrollToTop() -``` - -[⬆ back to top](#table-of-contents) -### Shuffle array - -Use `Array.sort()` to reorder elements, using `Math.random()` in the comparator. - -```js -const shuffle = arr => arr.sort(() => Math.random() - 0.5); -// shuffle([1,2,3]) -> [2,3,1] -``` - -[⬆ back to top](#table-of-contents) -### Similarity between arrays - -Use `filter()` to remove values that are not part of `values`, determined using `includes()`. - -```js -const similarity = (arr, values) => arr.filter(v => values.includes(v)); -// similarity([1,2,3], [1,2,4]) -> [1,2] -``` - -[⬆ back to top](#table-of-contents) ### Sleep Delay executing part of an `async` function, by putting it to sleep, returning a `Promise`. @@ -903,17 +690,143 @@ async function sleepyWork() { ``` [⬆ back to top](#table-of-contents) -### Sort characters in string (alphabetical) +## Math -Split the string using `split('')`, `Array.sort()` utilizing `localeCompare()`, recombine using `join('')`. +### Collatz algorithm + +If `n` is even, return `n/2`. Otherwise return `3n+1`. ```js -const sortCharactersInString = str => - str.split('').sort((a, b) => a.localeCompare(b)).join(''); -// sortCharactersInString('cabbage') -> 'aabbceg' +const collatz = n => (n % 2 == 0) ? (n / 2) : (3 * n + 1); +// collatz(8) --> 4 +// collatz(5) --> 16 ``` [⬆ back to top](#table-of-contents) + +### Distance between two points + +Use `Math.hypot()` to calculate the Euclidean distance between two points. + +```js +const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0); +// distance(1,1, 2,3) -> 2.23606797749979 +``` + +[⬆ back to top](#table-of-contents) + +### Divisible by number + +Use the modulo operator (`%`) to check if the remainder is equal to `0`. + +```js +const isDivisible = (dividend, divisor) => dividend % divisor === 0; +// isDivisible(6,3) -> true +``` + +[⬆ back to top](#table-of-contents) + +### Even or odd number + +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. + +```js +const isEven = num => num % 2 === 0; +// isEven(3) -> false +``` + +[⬆ back to top](#table-of-contents) + +### Factorial + +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`. + +```js +const factorial = n => n <= 1 ? 1 : n * factorial(n - 1); +// factorial(6) -> 720 +``` + +[⬆ back to top](#table-of-contents) + +### Fibonacci array generator + +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. + +```js +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] +``` + +[⬆ back to top](#table-of-contents) + +### Greatest common divisor (GCD) + +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`. + +```js +const gcd = (x, y) => !y ? x : gcd(y, x % y); +// gcd (8, 36) -> 4 +``` + +[⬆ back to top](#table-of-contents) + +### Hamming distance + +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 `1`s in the string, using `match(/1/g)`. + +```js +const hammingDistance = (num1, num2) => + ((num1 ^ num2).toString(2).match(/1/g) || '').length; +// hammingDistance(2,3) -> 1 +``` + +[⬆ back to top](#table-of-contents) + +### Percentile + +Use `Array.reduce()` to calculate how many numbers are below the value and how many are the same value and +apply the percentile formula. + +```js +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 + ``` + +[⬆ back to top](#table-of-contents) + +### Powerset + +Use `Array.reduce()` combined with `Array.map()` to iterate over elements and combine into an array containing all combinations. + +```js +const powerset = arr => + arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]); +// powerset([1,2]) -> [[], [1], [2], [2,1]] +``` + +[⬆ back to top](#table-of-contents) + +### Round number to n 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. + +```js +const round = (n, decimals=0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`); +// round(1.005, 2) -> 1.01 +``` + +[⬆ back to top](#table-of-contents) + ### Standard deviation Use `Array.reduce()` to calculate the mean, variance and the sum of the variance of the values, the variance of the values, then @@ -927,55 +840,152 @@ const standardDeviation = (arr, usePopulation = false) => { 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) ``` [⬆ back to top](#table-of-contents) -### Sum of array of numbers +## Media -Use `Array.reduce()` to add each value to an accumulator, initialized with a value of `0`. +### Speech synthesis (experimental) + +Use `SpeechSynthesisUtterance.voice` and `indow.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](https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesisUtterance). ```js -const sum = arr => arr.reduce((acc, val) => acc + val, 0); -// sum([1,2,3,4]) -> 10 +const speak = message => { + const msg = new SpeechSynthesisUtterance(message); + msg.voice = window.speechSynthesis.getVoices()[0]; + window.speechSynthesis.speak(msg); +}; +// speak('Hello, World') -> plays the message ``` [⬆ back to top](#table-of-contents) -### Swap values of two variables +## Object -Use array destructuring to swap values between two variables. +### Object from key-value pairs + +Use `Array.reduce()` to create and combine key-value pairs. ```js -[varA, varB] = [varB, varA]; -// [x, y] = [y, x] +const objectFromPairs = arr => arr.reduce((a, v) => (a[v[0]] = v[1], a), {}); +// objectFromPairs([['a',1],['b',2]]) -> {a: 1, b: 2} ``` [⬆ back to top](#table-of-contents) -### Tail of list -Return `arr.slice(1)` if the array's `length` is more than `1`, otherwise return the whole array. +### Object to key-value pairs + +Use `Object.keys()` and `Array.map()` to iterate over the object's keys and produce an array with key-value pairs. ```js -const tail = arr => arr.length > 1 ? arr.slice(1) : arr; -// tail([1,2,3]) -> [2,3] -// tail([1]) -> [1] +const objectToPairs = obj => Object.keys(obj).map(k => [k, obj[k]]); +// objectToPairs({a: 1, b: 2}) -> [['a',1],['b',2]]) ``` [⬆ back to top](#table-of-contents) -### Take -Use `Array.slice()` to create a slice of the array with `n` elements taken from the beginning. +### Shallow clone object + +Use the object `...spread` operator to spread the properties of the target object into the clone. ```js -const take = (arr, n = 1) => arr.slice(0, n); - -// take([1, 2, 3], 5) -> [1, 2, 3] -// take([1, 2, 3], 0) -> [] +const shallowClone = obj => ({ ...obj }); +/* +const a = { x: true, y: 1 }; +const b = shallowClone(a); +a === b -> false +*/ ``` [⬆ back to top](#table-of-contents) +## String + +### Anagrams of string (with 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`. + +```js +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)), []); +}; +// anagrams('abc') -> ['abc','acb','bac','bca','cab','cba'] +``` + +[⬆ back to top](#table-of-contents) + +### Capitalize first letter of every word + +Use `replace()` to match the first character of each word and `toUpperCase()` to capitalize it. + +```js +const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase()); +// capitalizeEveryWord('hello world!') -> 'Hello World!' +``` + +[⬆ back to top](#table-of-contents) + +### Capitalize first letter + +Use `slice(0,1)` and `toUpperCase()` to capitalize first letter, `slice(1)` to get the rest of the string. +Omit the `lowerRest` parameter to keep the rest of the string intact, or set it to `true` to convert to lower case. + +```js +const capitalize = (str, lowerRest = false) => + str.slice(0, 1).toUpperCase() + (lowerRest ? str.slice(1).toLowerCase() : str.slice(1)); +// capitalize('myName', true) -> 'Myname' +``` + +[⬆ back to top](#table-of-contents) + +### Check for palindrome + +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()`. + +```js +const palindrome = str => { + const s = str.toLowerCase().replace(/[\W_]/g,''); + return s === s.split('').reverse().join(''); +} +// palindrome('taco cat') -> true + ``` + +[⬆ back to top](#table-of-contents) + +### Reverse a string + +Use array destructuring and `Array.reverse()` to reverse the order of the characters in the string. +Combine characters to get a string using `join('')`. + +```js +const reverseString = str => [...str].reverse().join(''); +// reverseString('foobar') -> 'raboof' +``` + +[⬆ back to top](#table-of-contents) + +### Sort characters in string (alphabetical) + +Split the string using `split('')`, `Array.sort()` utilizing `localeCompare()`, recombine using `join('')`. + +```js +const sortCharactersInString = str => + str.split('').sort((a, b) => a.localeCompare(b)).join(''); +// sortCharactersInString('cabbage') -> 'aabbceg' +``` + +[⬆ back to top](#table-of-contents) + ### Truncate a String Determine if the string's `length` is greater than `num`. @@ -988,16 +998,194 @@ const truncate = (str, num) => ``` [⬆ back to top](#table-of-contents) -### Unique values of array +## Utility -Use ES6 `Set` and the `...rest` operator to discard all duplicated values. +### Escape regular expression + +Use `replace()` to escape special characters. ```js -const unique = arr => [...new Set(arr)]; -// unique([1,2,2,3,4,4,5]) -> [1,2,3,4,5] +const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); +// escapeRegExp('(test)') -> \\(test\\) ``` [⬆ back to top](#table-of-contents) + +### Get native type of value + +Returns lower-cased constructor name of value, "undefined" or "null" if value is undefined or null + +```js +const getType = v => + v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name.toLowerCase(); +// getType(new Set([1,2,3])) -> "set" +``` + +[⬆ back to top](#table-of-contents) + +### Is array + +Use `Array.isArray()` to check if a value is classified as an array. + +```js +const isArray = val => !!val && Array.isArray(val); +// isArray(null) -> false +// isArray([1]) -> true +``` + +[⬆ back to top](#table-of-contents) + +### Is boolean + +Use `typeof` to check if a value is classified as a boolean primitive. + +```js +const isBoolean = val => typeof val === 'boolean'; +// isBoolean(null) -> false +// isBoolean(false) -> true +``` + +[⬆ back to top](#table-of-contents) + +### Is function + +Use `typeof` to check if a value is classified as a function primitive. + +```js +const isFunction = val => val && typeof val === 'function'; +// isFunction('x') -> false +// isFunction(x => x) -> true +``` + +[⬆ back to top](#table-of-contents) + +### Is number + +Use `typeof` to check if a value is classified as a number primitive. + +```js +const isNumber = val => typeof val === 'number'; +// isNumber('1') -> false +// isNumber(1) -> true +``` + +[⬆ back to top](#table-of-contents) + +### Is string + +Use `typeof` to check if a value is classified as a string primitive. + +```js +const isString = val => typeof val === 'string'; +// isString(10) -> false +// isString('10') -> true +``` + +[⬆ back to top](#table-of-contents) + +### Is symbol + +Use `typeof` to check if a value is classified as a symbol primitive. + +```js +const isSymbol = val => typeof val === 'symbol'; +// isSymbol('x') -> false +// isSymbol(Symbol('x')) -> true +``` + +[⬆ back to top](#table-of-contents) + +### Measure time taken by function + +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. + +```js +const timeTaken = callback => { + console.time('timeTaken'); + const r = callback(); + console.timeEnd('timeTaken'); + return r; +}; +// timeTaken(() => Math.pow(2, 10)) -> 1024 +// (logged): timeTaken: 0.02099609375ms +``` + +[⬆ back to top](#table-of-contents) + +### Number to array of digits + +Convert the number to a string, use `split()` to convert build an array. +Use `Array.map()` and `parseInt()` to transform each value to an integer. + +```js +const digitize = n => (''+n).split('').map(i => parseInt(i)); +// digitize(2334) -> [2, 3, 3, 4] +``` + +[⬆ back to top](#table-of-contents) + +### Ordinal suffix of 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. + +```js +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]; +}; +// toOrdinalSuffix("123") -> "123rd" +``` + +[⬆ back to top](#table-of-contents) + +### Random integer in range + +Use `Math.random()` to generate a random number and map it to the desired range, using `Math.floor()` to make it an integer. + +```js +const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min; +// randomIntegerInRange(0, 5) -> 2 +``` + +[⬆ back to top](#table-of-contents) + +### Random number in range + +Use `Math.random()` to generate a random value, map it to the desired range using multiplication. + +```js +const randomInRange = (min, max) => Math.random() * (max - min) + min; +// randomInRange(2,10) -> 6.0211363285087005 +``` + +[⬆ back to top](#table-of-contents) + +### RGB to hexadecimal + +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. + +```js +const rgbToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0'); +// rgbToHex(255, 165, 1) -> 'ffa501' +``` + +[⬆ back to top](#table-of-contents) + +### Swap values of two variables + +Use array destructuring to swap values between two variables. + +```js +[varA, varB] = [varB, varA]; +// [x, y] = [y, x] +``` + +[⬆ back to top](#table-of-contents) + ### URL parameters Use `match()` with an appropriate regular expression to get all key-value pairs, `Array.reduce()` to map and combine them into a single object. @@ -1012,6 +1200,7 @@ const getUrlParameters = url => ``` [⬆ back to top](#table-of-contents) + ### UUID generator Use `crypto` API to generate a UUID, compliant with [RFC4122](https://www.ietf.org/rfc/rfc4122.txt) version 4. @@ -1025,6 +1214,7 @@ const uuid = _ => ``` [⬆ back to top](#table-of-contents) + ### Validate email Use a regular experssion to check if the email is valid. @@ -1037,6 +1227,7 @@ const validateEmail = str => ``` [⬆ back to top](#table-of-contents) + ### Validate number Use `!isNaN` in combination with `parseFloat()` to check if the argument is a number. @@ -1049,6 +1240,7 @@ const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == ``` [⬆ back to top](#table-of-contents) + ### Value or default Returns value, or default value if passed value is `falsy`. @@ -1059,6 +1251,7 @@ const valueOrDefault = (value, d) => value || d; ``` [⬆ back to top](#table-of-contents) + ## Credits *Icons made by [Smashicons](https://www.flaticon.com/authors/smashicons) from [www.flaticon.com](https://www.flaticon.com/) is licensed by [CC 3.0 BY](http://creativecommons.org/licenses/by/3.0/).* diff --git a/package-lock.json b/package-lock.json index be8bcab8d..4344c4b9b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -65,16 +65,6 @@ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=" }, - "ansi-regex": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", - "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=" - }, - "ansi-styles": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", - "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=" - }, "anymatch": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", @@ -333,21 +323,39 @@ "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=" }, "chalk": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", - "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, "requires": { - "ansi-styles": "1.1.0", + "ansi-styles": "3.2.0", "escape-string-regexp": "1.0.5", - "has-ansi": "0.1.0", - "strip-ansi": "0.3.0", - "supports-color": "0.2.0" + "supports-color": "4.5.0" }, "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, "supports-color": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", - "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=" + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } } } }, @@ -442,7 +450,6 @@ "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-3.5.1.tgz", "integrity": "sha512-689HrwGw8Rbk1xtV9C4dY6TPJAvIYZbRbnKSAtfJ7tHqICFGoZ0PCWYjxfmerRyxBG0o3sbG3pe7N8vqPwIHuQ==", "requires": { - "chalk": "0.5.1", "commander": "2.6.0", "date-fns": "1.29.0", "lodash": "4.17.4", @@ -1346,14 +1353,6 @@ "function-bind": "1.1.1" } }, - "has-ansi": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", - "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", - "requires": { - "ansi-regex": "0.2.1" - } - }, "has-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", @@ -2855,14 +2854,6 @@ "safe-buffer": "5.1.1" } }, - "strip-ansi": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", - "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", - "requires": { - "ansi-regex": "0.2.1" - } - }, "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", diff --git a/package.json b/package.json index a616c02d0..4c6d5f82e 100644 --- a/package.json +++ b/package.json @@ -11,10 +11,13 @@ "description": "A collection of useful Javascript snippets.", "version": "1.0.0", "main": "index.js", - "devDependencies": {}, + "devDependencies": { + "chalk": "^2.3.0" + }, "scripts": { - "build-list": "node ./scripts/builder.js", - "lint": "node ./scripts/lintSnippet.js", + "builder": "node ./scripts/build-script.js", + "linter": "node ./scripts/lint-script.js", + "tagger": "node ./scripts/tag-script.js", "start": "concurrently --kill-others \"nodemon -e js,md -i README.md -x \\\"npm run build-list\\\"\" \"live-server ./build\"" }, "repository": { diff --git a/scripts/build-script.js b/scripts/build-script.js new file mode 100644 index 000000000..05514ae78 --- /dev/null +++ b/scripts/build-script.js @@ -0,0 +1,79 @@ +/* + This is the builder script that generates the README file. + Run using `npm run builder`. +*/ +// Load modules +const fs = require('fs-extra'), path = require('path'), chalk = require('chalk'); +// Set variables for paths +const snippetsPath = './snippets', staticPartsPath = './static-parts'; +// Set variables for script +let snippets = {}, startPart = '', endPart = '', output = '', tagDbData = {}; +// Load helper functions (these are from existing snippets in 30 seconds of code!) +const objectFromPairs = arr => arr.reduce((a, v) => (a[v[0]] = v[1], a), {}); +const capitalize = (str, lowerRest = false) => str.slice(0, 1).toUpperCase() + (lowerRest ? str.slice(1).toLowerCase() : str.slice(1)); +// Start the timer of the script +console.time('Builder'); +// Synchronously read all snippets and sort them as necessary (case-insensitive) +try { + let snippetFilenames = fs.readdirSync(snippetsPath); + snippetFilenames.sort((a, b) => { + a = a.toLowerCase(); + b = b.toLowerCase(); + if (a < b) return -1; + if (a > b) return 1; + return 0; + }); + // Store the data read from each snippet in the appropriate object + for(let snippet of snippetFilenames) snippets[snippet] = fs.readFileSync(path.join(snippetsPath,snippet),'utf8'); +} +catch (err){ // Handle errors (hopefully not!) + console.log(`${chalk.red('ERROR!')} During snippet loading: ${err}`); + process.exit(1); +} +// Load static parts for the README file +try { + startPart = fs.readFileSync(path.join(staticPartsPath,'README-start.md'),'utf8'); + endPart = fs.readFileSync(path.join(staticPartsPath,'README-end.md'),'utf8'); +} +catch (err){ // Handle errors (hopefully not!) + console.log(`${chalk.red('ERROR!')} During static part loading: ${err}`); + process.exit(1); +} +// Load tag data from the database +try { + tagDbData = objectFromPairs(fs.readFileSync('tag_database','utf8').split('\n').slice(0,-1).map(v => v.split(':').slice(0,2))); +} +catch (err){ // Handle errors (hopefully not!) + console.log(`${chalk.red('ERROR!')} During tag database loading: ${err}`); + process.exit(1); +} +// Create the output for the README file +try { + // Add the start static part + output += `${startPart+'\n'}`; + // Loop over tags and snippets to create the table of contents + for(let tag of [...new Set(Object.entries(tagDbData).map(t => t[1]))].filter(v => v).sort((a,b) => a.localeCompare(b))){ + output +=`### ${capitalize(tag, true)}\n`; + for(let taggedSnippet of Object.entries(tagDbData).filter(v => v[1] === tag)) + output += `* [${taggedSnippet[0][0].toUpperCase() + taggedSnippet[0].replace(/-/g,' ').slice(1)}](#${taggedSnippet[0].replace(/\(/g,'').replace(/\)/g,'').toLowerCase()})\n` + output += '\n'; + } + // Loop over tags and snippets to create the list of snippets + for(let tag of [...new Set(Object.entries(tagDbData).map(t => t[1]))].filter(v => v).sort((a,b) => a.localeCompare(b))){ + output +=`## ${capitalize(tag, true)}\n`; + for(let taggedSnippet of Object.entries(tagDbData).filter(v => v[1] === tag)) + output += `\n${snippets[taggedSnippet[0]+'.md']+'\n[⬆ back to top](#table-of-contents)\n'}`; + } + // Add the ending static part + output += `\n${endPart+'\n'}`; + // Write to the README file + fs.writeFileSync('README.md', output); +} +catch (err){ // Handle errors (hopefully not!) + console.log(`${chalk.red('ERROR!')} During README generation: ${err}`); + process.exit(1); +} +// Log a success message +console.log(`${chalk.green('SUCCESS!')} README file generated!`); +// Log the time taken +console.timeEnd('Builder'); diff --git a/scripts/builder.js b/scripts/builder.js deleted file mode 100644 index 220469705..000000000 --- a/scripts/builder.js +++ /dev/null @@ -1,57 +0,0 @@ -var fs = require('fs-extra'); -var path = require('path'); - -var snippetsPath = './snippets'; -var staticPartsPath = './static-parts'; - -var snippets = {}, startPart = '', endPart = '', output = ''; - -console.time('Builder'); - -try { - var snippetFilenames = fs.readdirSync(snippetsPath); - snippetFilenames.sort((a, b) => { - a = a.toLowerCase(); - b = b.toLowerCase(); - if (a < b) { - return -1; - } - if (a > b) { - return 1; - } - return 0; - }); - for(var snippet of snippetFilenames){ - snippets[snippet] = fs.readFileSync(path.join(snippetsPath,snippet),'utf8'); - } -} -catch (err){ - console.log('Error during snippet loading: '+err); - process.exit(1); -} - -try { - startPart = fs.readFileSync(path.join(staticPartsPath,'README-start.md'),'utf8'); - endPart = fs.readFileSync(path.join(staticPartsPath,'README-end.md'),'utf8'); -} -catch (err){ - console.log('Error during static part loading: '+err); - process.exit(1); -} - -try { - output += `${startPart+'\n'}`; - for(var snippet of Object.entries(snippets)) - output += `* [${snippet[0][0].toUpperCase() + snippet[0].replace(/-/g,' ').slice(1,snippet[0].length-3)}](#${snippet[0].slice(0,snippet[0].length-3).replace(/\(/g,'').replace(/\)/g,'').toLowerCase()})\n` - output += '\n'; - for(var snippet of Object.entries(snippets)) - output += `${snippet[1]+'\n[⬆ back to top](#table-of-contents)\n'}`; - output += `${endPart+'\n'}`; - fs.writeFileSync('README.md', output); -} -catch (err){ - console.log('Error during README generation: '+err); - process.exit(1); -} - -console.timeEnd('Builder'); diff --git a/scripts/lint-script.js b/scripts/lint-script.js new file mode 100644 index 000000000..5d6d8721e --- /dev/null +++ b/scripts/lint-script.js @@ -0,0 +1,44 @@ +/* + This is the linter script that lints snippets. + Run using `npm run linter`. +*/ +// Load modules +const fs = require('fs-extra'), cp = require('child_process'), path = require('path'), chalk = require('chalk'); +// Set variables for paths +var snippetsPath = './snippets'; +// Read files, lint each one individually and update +try { + let snippetFilenames = fs.readdirSync(snippetsPath); + snippetFilenames.sort((a, b) => { + a = a.toLowerCase(); + b = b.toLowerCase(); + if (a < b) return -1; + if (a > b) return 1; + return 0; + }); + // Read each file, get its code, write it to a temporary file, pass it through + // semistandard, get the output from the file, update the original file. + for(let snippet of snippetFilenames){ + // Start a timer for the file + console.time(`Linter (${snippet})`); + // Synchronously read data from the snippet, get the code, write it to a temporary file + let snippetData = fs.readFileSync(path.join(snippetsPath,snippet),'utf8'); + let originalCode = snippetData.slice(snippetData.indexOf('```js')+5,snippetData.lastIndexOf('```')); + fs.writeFileSync(`${snippet}.temp.js`,`${originalCode}`); + // Run semistandard asynchronously (only way this manages to run), get linted code + // and write back to the original snippet file. Remove temporary file + cp.exec(`semistandard "${snippet}.temp.js" --fix`,{},(error, stdOut, stdErr) => { + let lintedCode = fs.readFileSync(`${snippet}.temp.js`,'utf8'); + fs.writeFile(path.join(snippetsPath,snippet), `${snippetData.slice(0, snippetData.indexOf('```js')+5)+lintedCode+'```\n'}`); + fs.unlink(`${snippet}.temp.js`); + // Log a success message + console.log(`${chalk.green('SUCCESS!')} Linted snippet: ${snippet}`); + // Log the time taken for the file + console.timeEnd(`Linter (${snippet})`); + }); + } +} +catch (err){ // Handle errors (hopefully not!) + console.log(`${chalk.red('ERROR!')} During linting: ${err}`); + process.exit(1); +} diff --git a/scripts/lintSnippet.js b/scripts/lintSnippet.js deleted file mode 100644 index a53686ee5..000000000 --- a/scripts/lintSnippet.js +++ /dev/null @@ -1,31 +0,0 @@ -var fs = require('fs-extra'); -var cp = require('child_process'); -var path = require('path'); - -var snippetsPath = './snippets'; -var snippetFilename = ''; - -console.time('Linter'); - -if(process.argv.length < 3){ - console.log('Please specify the filename of a snippet to be linted.'); - console.log('Example usage: npm run lint "snippet-file.md"'); - process.exit(0); -} -else { - snippetFilename = process.argv[2]; - let snippetData = fs.readFileSync(path.join(snippetsPath,snippetFilename),'utf8'); - try { - let originalCode = snippetData.slice(snippetData.indexOf('```js')+5,snippetData.lastIndexOf('```')); - fs.writeFileSync('currentSnippet.js',`${originalCode}`); - cp.exec('semistandard "currentSnippet.js" --fix',{},(error, stdOut, stdErr) => { - let lintedCode = fs.readFileSync('currentSnippet.js','utf8'); - fs.writeFile(path.join(snippetsPath,snippetFilename), `${snippetData.slice(0, snippetData.indexOf('```js')+5)+lintedCode+'```\n'}`); - console.timeEnd('Linter'); - }); - } - catch (err){ - console.log('Error during snippet loading: '+err); - process.exit(1); - } -} diff --git a/scripts/tag-script.js b/scripts/tag-script.js new file mode 100644 index 000000000..8537b3009 --- /dev/null +++ b/scripts/tag-script.js @@ -0,0 +1,67 @@ +/* + This is the tagger script that updates the tag_databse file and logs stats for snippet tags. + Run using `npm run tagger`. +*/ +// Load modules +const fs = require('fs-extra'), path = require('path'), chalk = require('chalk'); +// Set variables for paths +const snippetsPath = './snippets'; +// Set variables for script +let snippets = {}, output = '', tagDbData = {}, missingTags = 0, tagDbStats = {}; +// Load helper functions (these are from existing snippets in 30 seconds of code!) +const objectFromPairs = arr => arr.reduce((a, v) => (a[v[0]] = v[1], a), {}); +const countOccurrences = (arr, value) => arr.reduce((a, v) => v === value ? a + 1 : a + 0, 0); +// Start the timer of the script +console.time('Tagger'); +// Synchronously read all snippets and sort them as necessary (case-insensitive) +try { + let snippetFilenames = fs.readdirSync(snippetsPath); + snippetFilenames.sort((a, b) => { + a = a.toLowerCase(); + b = b.toLowerCase(); + if (a < b) return -1; + if (a > b) return 1; + return 0; + }); + // Store the data read from each snippet in the appropriate object + for(let snippet of snippetFilenames) snippets[snippet] = fs.readFileSync(path.join(snippetsPath,snippet),'utf8'); +} +catch (err){ // Handle errors (hopefully not!) + console.log(`${chalk.red('ERROR!')} During snippet loading: ${err}`); + process.exit(1); +} +// Load tag data from the database +try { + tagDbData = objectFromPairs(fs.readFileSync('tag_database','utf8').split('\n').slice(0,-1).map(v => v.split(':').slice(0,2))); + tagDbStats = Object.entries(tagDbData).sort((a,b) => a[1].localeCompare(b[1])).reduce((acc, val) => {acc.hasOwnProperty(val[1]) ? acc[val[1]]++ : acc[val[1]] = 1; return acc;}, {}); +} +catch (err){ // Handle errors (hopefully not!) + console.log(`${chalk.red('ERROR!')} During tag database loading: ${err}`); + process.exit(1); +} +// Update the listing of snippets in tag_database and log the statistics, along with missing scripts +try { + for(let snippet of Object.entries(snippets)) + if(tagDbData.hasOwnProperty(snippet[0].slice(0,-3)) && tagDbData[snippet[0].slice(0,-3)].trim()) + output += `${snippet[0].slice(0,-3)}:${tagDbData[snippet[0].slice(0,-3)].trim()}\n`; + else { + output += `${snippet[0].slice(0,-3)}:\n`; + missingTags++; + console.log(`${chalk.yellow('Tag missing:')} ${snippet[0].slice(0,-3)}`); + } + // Write to tag_database + fs.writeFileSync('tag_database', output); +} +catch (err){ // Handle errors (hopefully not!) + console.log(`${chalk.red('ERROR!')} During tag_database generation: ${err}`); + process.exit(1); +} +// Log statistics for the tag_database file +console.log(`\n${chalk.bgWhite(chalk.black('=== TAG STATS ==='))}`) +for(let tagData of Object.entries(tagDbStats).filter(v => v[0] !== 'undefined')) + console.log(`${chalk.green(tagData[0])}: ${tagData[1]} snippets`); +console.log(`${chalk.blue('Untagged snippets:')} ${missingTags}\n`); +// Log a success message +console.log(`${chalk.green('SUCCESS!')} tag_database file updated!`); +// Log the time taken +console.timeEnd('Tagger'); diff --git a/snippets/array-concatenation.md b/snippets/array-concatenation.md index b4e2fa205..992036905 100644 --- a/snippets/array-concatenation.md +++ b/snippets/array-concatenation.md @@ -1,6 +1,6 @@ ### Array concatenation -Use `Array.concat()` to concatenate and array with any additional arrays and/or values, specified in `args`. +Use `Array.concat()` to concatenate an array with any additional arrays and/or values, specified in `args`. ```js const arrayConcat = (arr, ...args) => arr.concat(...args); diff --git a/snippets/array-difference.md b/snippets/array-difference.md index 46469b1d6..208cb811e 100644 --- a/snippets/array-difference.md +++ b/snippets/array-difference.md @@ -3,6 +3,6 @@ Create a `Set` from `b`, then use `Array.filter()` on `a` to only keep values not contained in `b`. ```js -const difference = (a, b) => { const s = new Set(b); return a.filter(x => !s.has(x)); } +const difference = (a, b) => { const s = new Set(b); return a.filter(x => !s.has(x)); }; // difference([1,2,3], [1,2]) -> [3] ``` diff --git a/snippets/array-intersection.md b/snippets/array-intersection.md index 87c42378b..780ab1d85 100644 --- a/snippets/array-intersection.md +++ b/snippets/array-intersection.md @@ -3,6 +3,6 @@ Create a `Set` from `b`, then use `Array.filter()` on `a` to only keep values contained in `b`. ```js -const intersection = (a, b) => { const s = new Set(b); return a.filter(x => s.has(x)); } +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] ``` diff --git a/snippets/array-sample.md b/snippets/array-sample.md new file mode 100644 index 000000000..d48f13840 --- /dev/null +++ b/snippets/array-sample.md @@ -0,0 +1,9 @@ +### Array sample + +Use `Math.random()` to generate a random number, multiply it with `Array.length` and round it of to the nearest whole number using `Math.floor()`. Works with strings too. + +```js +const sample = arr => arr[Math.floor(Math.random() * arr.length)]; + +// sample([3, 7, 9, 11]) -> 9 +``` \ No newline at end of file diff --git a/snippets/array-union.md b/snippets/array-union.md index b417dcce7..6224227d1 100644 --- a/snippets/array-union.md +++ b/snippets/array-union.md @@ -3,6 +3,6 @@ Create a `Set` with all values of `a` and `b` and convert to an array. ```js -const union = (a, b) => Array.from(new Set([...a, ...b])) +const union = (a, b) => Array.from(new Set([...a, ...b])); // union([1,2,3], [4,3,2]) -> [1,2,3,4] ``` diff --git a/snippets/array-zip.md b/snippets/array-zip.md new file mode 100644 index 000000000..08c40ed68 --- /dev/null +++ b/snippets/array-zip.md @@ -0,0 +1,17 @@ +### Array zip + +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. + +```js +const zip = (...arrays) => { + const maxLength = Math.max.apply(null, arrays.map(a => a.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]] +``` diff --git a/snippets/chunk-array.md b/snippets/chunk-array.md index c14bf269d..ba3e5e42e 100644 --- a/snippets/chunk-array.md +++ b/snippets/chunk-array.md @@ -7,5 +7,5 @@ If the original array can't be split evenly, the final chunk will contain the re ```js 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] +// chunk([1,2,3,4,5], 2) -> [[1,2],[3,4],[5]] ``` diff --git a/snippets/collatz-algorithm.md b/snippets/collatz-algorithm.md index 730bdd9e3..61614e5e0 100644 --- a/snippets/collatz-algorithm.md +++ b/snippets/collatz-algorithm.md @@ -3,7 +3,7 @@ If `n` is even, return `n/2`. Otherwise return `3n+1`. ```js -const collatz = n => (n % 2 == 0) ? (n/2) : (3*n+1); +const collatz = n => (n % 2 == 0) ? (n / 2) : (3 * n + 1); // collatz(8) --> 4 // collatz(5) --> 16 ``` diff --git a/snippets/curry.md b/snippets/curry.md index edb95461f..bbee4086c 100644 --- a/snippets/curry.md +++ b/snippets/curry.md @@ -6,13 +6,10 @@ 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`. ```js -const curry = (f, arity = f.length, next) => - (next = prevArgs => - nextArg => { - const args = [ ...prevArgs, nextArg ]; - return args.length >= arity ? f(...args) : next(args); - } - )([]); +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 ``` diff --git a/snippets/deep-flatten-array.md b/snippets/deep-flatten-array.md index c350d848c..1dffe860f 100644 --- a/snippets/deep-flatten-array.md +++ b/snippets/deep-flatten-array.md @@ -1,10 +1,9 @@ ### Deep flatten array Use recursion. -Use `Array.reduce()` to get all elements that are not arrays, flatten each element that is an array. +Use `[].concat()` and the spread operator `...` to flatten an array, and recursively flatten each element that is an array. ```js -const deepFlatten = arr => - arr.reduce((a, v) => a.concat(Array.isArray(v) ? deepFlatten(v) : v), []); +const deepFlatten = arr => [].concat(...arr.map(v => Array.isArray(v) ? deepFlatten(v) : v)); // deepFlatten([1,[2],[[3],4],5]) -> [1,2,3,4,5] ``` diff --git a/snippets/drop-elements-in-array.md b/snippets/drop-elements-in-array.md index 0ad2ab5e9..236c5ab56 100644 --- a/snippets/drop-elements-in-array.md +++ b/snippets/drop-elements-in-array.md @@ -4,9 +4,9 @@ Loop through the array, using `Array.shift()` to drop the first element of the a Returns the remaining elements. ```js -const dropElements = (arr,func) => { - while(arr.length > 0 && !func(arr[0])) arr.shift(); +const dropElements = (arr, func) => { + while (arr.length > 0 && !func(arr[0])) arr.shift(); return arr; -} +}; // dropElements([1, 2, 3, 4], n => n >= 3) -> [3,4] ``` diff --git a/snippets/element-is-visible-in-viewport.md b/snippets/element-is-visible-in-viewport.md index 70ff83134..514aea5e6 100644 --- a/snippets/element-is-visible-in-viewport.md +++ b/snippets/element-is-visible-in-viewport.md @@ -12,7 +12,7 @@ const elementIsVisibleInViewport = (el, partiallyVisible = false) => { ? ((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) diff --git a/snippets/fill-array.md b/snippets/fill-array.md index a08c4362e..a5da15483 100644 --- a/snippets/fill-array.md +++ b/snippets/fill-array.md @@ -4,7 +4,7 @@ Use `Array.map()` to map values between `start` (inclusive) and `end` (exclusive Omit `start` to start at the first element and/or `end` to finish at the last. ```js -const fillArray = (arr, value, start = 0, end = arr.length) => - arr.map((v,i) => i>=start && i + arr.map((v, i) => i >= start && i < end ? value : v); // fillArray([1,2,3,4],'8',1,3) -> [1,'8','8',4] ``` diff --git a/snippets/flatten-array-up-to-depth.md b/snippets/flatten-array-up-to-depth.md index d28af98fb..b6e3805b6 100644 --- a/snippets/flatten-array-up-to-depth.md +++ b/snippets/flatten-array-up-to-depth.md @@ -7,7 +7,7 @@ Omit the second element, `depth` to flatten only to a depth of `1` (single flatt ```js 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),[]); + 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] ``` diff --git a/snippets/get-days-difference-between-dates.md b/snippets/get-days-difference-between-dates.md new file mode 100644 index 000000000..ae93ce79d --- /dev/null +++ b/snippets/get-days-difference-between-dates.md @@ -0,0 +1,8 @@ +### Get days difference between dates + +Calculate the difference (in days) between to `Date` objects. + +```js +const getDaysDiffBetweenDates = (dateInitial, dateFinal) => (dateFinal - dateInitial) / (1000 * 3600 * 24); +// getDaysDiffBetweenDates(new Date("2017-12-13"), new Date("2017-12-22")) -> 9 +``` diff --git a/snippets/is-array.md b/snippets/is-array.md index 7652f74c9..939cb086d 100644 --- a/snippets/is-array.md +++ b/snippets/is-array.md @@ -3,7 +3,7 @@ Use `Array.isArray()` to check if a value is classified as an array. ```js -const isArray = val => val && Array.isArray(val); +const isArray = val => !!val && Array.isArray(val); // isArray(null) -> false // isArray([1]) -> true ``` diff --git a/snippets/measure-time-taken-by-function.md b/snippets/measure-time-taken-by-function.md index 44e099d7e..ca476ac71 100644 --- a/snippets/measure-time-taken-by-function.md +++ b/snippets/measure-time-taken-by-function.md @@ -1,13 +1,14 @@ ### Measure time taken by function -Use `performance.now()` to get start and end time for the function, `console.log()` the time taken. -Pass a callback function as the argument. +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. ```js const timeTaken = callback => { - const t0 = performance.now(), r = callback(); - console.log(performance.now() - t0); + console.time('timeTaken'); + const r = callback(); + console.timeEnd('timeTaken'); return r; }; -// timeTaken(() => Math.pow(2, 10)) -> 1024 (0.010000000009313226 logged in console) +// timeTaken(() => Math.pow(2, 10)) -> 1024 +// (logged): timeTaken: 0.02099609375ms ``` diff --git a/snippets/nth-element-of-array.md b/snippets/nth-element-of-array.md new file mode 100644 index 000000000..15552d071 --- /dev/null +++ b/snippets/nth-element-of-array.md @@ -0,0 +1,11 @@ +### Nth element of 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. + +```js +const nth = (arr, n=0) => (n>0? arr.slice(n,n+1) : arr.slice(n))[0]; +// nth(['a','b','c'],1) -> 'b' +// nth(['a','b','b']-2) -> 'a' +``` diff --git a/snippets/number-to-array-of-digits.md b/snippets/number-to-array-of-digits.md new file mode 100644 index 000000000..f00a62b75 --- /dev/null +++ b/snippets/number-to-array-of-digits.md @@ -0,0 +1,9 @@ +### Number to array of digits + +Convert the number to a string, use `split()` to convert build an array. +Use `Array.map()` and `parseInt()` to transform each value to an integer. + +```js +const digitize = n => (''+n).split('').map(i => parseInt(i)); +// digitize(2334) -> [2, 3, 3, 4] +``` diff --git a/snippets/ordinal-suffix-of-number.md b/snippets/ordinal-suffix-of-number.md index 4e849eff7..d3166928b 100644 --- a/snippets/ordinal-suffix-of-number.md +++ b/snippets/ordinal-suffix-of-number.md @@ -7,9 +7,9 @@ If digit is found in teens pattern, use teens ordinal. ```js 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]; -} + 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]; +}; // toOrdinalSuffix("123") -> "123rd" ``` diff --git a/snippets/pipe.md b/snippets/pipe.md index c61ec042c..f46a32148 100644 --- a/snippets/pipe.md +++ b/snippets/pipe.md @@ -1,8 +1,15 @@ ### Pipe -Use `Array.reduce()` to pass value through functions. +Use `Array.reduce()` to perform left-to-right function composition. The first (leftmost) function can accept one or more arguments; the remaining functions must be unary. ```js -const pipe = (...funcs) => arg => funcs.reduce((acc, func) => func(acc), arg); -// pipe(btoa, x => x.toUpperCase())("Test") -> "VGVZDA==" +const pipe = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args))) +/* +const add5 = x => x + 5 +const multiply = (x, y) => x * y + +const multiplyAndAdd5 = pipe(multiply, add5) + +multiplyAndAdd5(5, 2) -> 15 +*/ ``` diff --git a/snippets/redirect-to-url.md b/snippets/redirect-to-URL.md similarity index 100% rename from snippets/redirect-to-url.md rename to snippets/redirect-to-URL.md diff --git a/snippets/round-number-to-n-digits.md b/snippets/round-number-to-n-digits.md new file mode 100644 index 000000000..a35308ce0 --- /dev/null +++ b/snippets/round-number-to-n-digits.md @@ -0,0 +1,9 @@ +### Round number to n 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. + +```js +const round = (n, decimals=0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`); +// round(1.005, 2) -> 1.01 +``` diff --git a/snippets/shallow-clone-object.md b/snippets/shallow-clone-object.md new file mode 100644 index 000000000..c6873c0d8 --- /dev/null +++ b/snippets/shallow-clone-object.md @@ -0,0 +1,12 @@ +### Shallow clone object + +Use the object `...spread` operator to spread the properties of the target object into the clone. + +```js +const shallowClone = obj => ({ ...obj }); +/* +const a = { x: true, y: 1 }; +const b = shallowClone(a); +a === b -> false +*/ +``` diff --git a/snippets/speech-synthesis-(experimental).md b/snippets/speech-synthesis-(experimental).md new file mode 100644 index 000000000..c9e6a288c --- /dev/null +++ b/snippets/speech-synthesis-(experimental).md @@ -0,0 +1,15 @@ +### Speech synthesis (experimental) + +Use `SpeechSynthesisUtterance.voice` and `indow.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](https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesisUtterance). + +```js +const speak = message => { + const msg = new SpeechSynthesisUtterance(message); + msg.voice = window.speechSynthesis.getVoices()[0]; + window.speechSynthesis.speak(msg); +}; +// speak('Hello, World') -> plays the message +``` diff --git a/snippets/standard-deviation.md b/snippets/standard-deviation.md index e559972bb..5819579ad 100644 --- a/snippets/standard-deviation.md +++ b/snippets/standard-deviation.md @@ -11,7 +11,7 @@ const standardDeviation = (arr, usePopulation = false) => { 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) ``` diff --git a/snippets/take.md b/snippets/take.md index 80142031d..44d6ff0bc 100644 --- a/snippets/take.md +++ b/snippets/take.md @@ -4,7 +4,6 @@ Use `Array.slice()` to create a slice of the array with `n` elements taken from ```js const take = (arr, n = 1) => arr.slice(0, n); - // take([1, 2, 3], 5) -> [1, 2, 3] // take([1, 2, 3], 0) -> [] ``` diff --git a/snippets/takeRight.md b/snippets/takeRight.md new file mode 100644 index 000000000..03fc634fa --- /dev/null +++ b/snippets/takeRight.md @@ -0,0 +1,10 @@ +### takeRight + +Use `Array.slice()` to create a slice of the array with `n` elements taken from the end. + +```js +const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length); +// takeRight([1, 2, 3], 2) -> [ 2, 3 ] +// takeRight([1, 2, 3]) -> [3] +// takeRight([1, 2, 3]) -> [] +``` \ No newline at end of file diff --git a/snippets/without.md b/snippets/without.md new file mode 100644 index 000000000..00876b5c9 --- /dev/null +++ b/snippets/without.md @@ -0,0 +1,12 @@ +### Without + +Use `Array.filter()` to create an array excluding all given values + +```js + +const without = (arr, ...args) => arr.filter(v => args.indexOf(v) === -1) + +// without[2, 1, 2, 3], 1, 2) -> [3] +// without([2, 1, 2, 3, 4, 5, 5, 5, 3, 2, 7, 7], 3, 1, 5, 2) -> [ 4, 7, 7 ] + +``` diff --git a/tag_database b/tag_database new file mode 100644 index 000000000..d1733c293 --- /dev/null +++ b/tag_database @@ -0,0 +1,89 @@ +anagrams-of-string-(with-duplicates):string +array-concatenation:array +array-difference:array +array-intersection:array +array-union:array +average-of-array-of-numbers:array +bottom-visible:browser +capitalize-first-letter-of-every-word:string +capitalize-first-letter:string +chain-asynchronous-functions:function +check-for-palindrome:string +chunk-array:array +collatz-algorithm:math +compact:array +count-occurrences-of-a-value-in-array:array +current-URL:browser +curry:function +deep-flatten-array:array +distance-between-two-points:math +divisible-by-number:math +drop-elements-in-array:array +element-is-visible-in-viewport:browser +escape-regular-expression:utility +even-or-odd-number:math +factorial:math +fibonacci-array-generator:math +fill-array:array +filter-out-non-unique-values-in-an-array:array +flatten-array-up-to-depth:array +flatten-array:array +get-days-difference-between-dates:date +get-max-value-from-array:array +get-min-value-from-array:array +get-native-type-of-value:utility +get-scroll-position:browser +greatest-common-divisor-(GCD):math +group-by:array +hamming-distance:math +head-of-list:array +initial-of-list:array +initialize-array-with-range:array +initialize-array-with-values:array +is-array:utility +is-boolean:utility +is-function:utility +is-number:utility +is-string:utility +is-symbol:utility +last-of-list:array +measure-time-taken-by-function:utility +median-of-array-of-numbers:array +nth-element-of-array:array +number-to-array-of-digits:utility +object-from-key-value-pairs:object +object-to-key-value-pairs:object +ordinal-suffix-of-number:utility +percentile:math +pick:array +pipe:function +powerset:math +promisify:function +random-integer-in-range:utility +random-number-in-range:utility +redirect-to-URL:browser +reverse-a-string:string +RGB-to-hexadecimal:utility +round-number-to-n-digits:math +run-promises-in-series:function +scroll-to-top:browser +shallow-clone-object:object +shuffle-array:array +similarity-between-arrays:array +sleep:function +sort-characters-in-string-(alphabetical):string +speech-synthesis-(experimental):media +standard-deviation:math +sum-of-array-of-numbers:array +swap-values-of-two-variables:utility +tail-of-list:array +take:array +takeRight:array +truncate-a-string:string +unique-values-of-array:array +URL-parameters:utility +UUID-generator:utility +validate-email:utility +validate-number:utility +value-or-default:utility +without:array diff --git a/yarn.lock b/yarn.lock index b5f1f6579..9dc4ac57e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13,7 +13,25 @@ accepts@~1.3.4: mime-types "~2.1.16" negotiator "0.6.1" -ajv@^4.9.1: +acorn-jsx@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" + dependencies: + acorn "^3.0.4" + +acorn@^3.0.4: + version "3.3.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" + +acorn@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.2.1.tgz#317ac7821826c22c702d66189ab8359675f135d7" + +ajv-keywords@^1.0.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" + +ajv@^4.7.0, ajv@^4.9.1: version "4.11.8" resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" dependencies: @@ -26,6 +44,10 @@ ansi-align@^2.0.0: dependencies: string-width "^2.0.0" +ansi-escapes@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" + ansi-regex@^0.2.0, ansi-regex@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-0.2.1.tgz#0d8e946967a3d8143f93e24e298525fc1b2235f9" @@ -42,6 +64,10 @@ ansi-styles@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.1.0.tgz#eaecbf66cd706882760b2f4691582b8f55d7a7de" +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + ansi-styles@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88" @@ -92,10 +118,31 @@ arr-flatten@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" +array-union@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + dependencies: + array-uniq "^1.0.1" + +array-uniq@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + array-unique@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" +array.prototype.find@^2.0.1: + version "2.0.4" + resolved "https://registry.yarnpkg.com/array.prototype.find/-/array.prototype.find-2.0.4.tgz#556a5c5362c08648323ddaeb9de9d14bc1864c90" + dependencies: + define-properties "^1.1.2" + es-abstract "^1.7.0" + +arrify@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + asn1@~0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" @@ -124,6 +171,14 @@ aws4@^1.2.1: version "1.6.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" +babel-code-frame@^6.16.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" @@ -191,6 +246,20 @@ braces@^1.8.2: preserve "^0.2.0" repeat-element "^1.1.2" +builtin-modules@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" + +caller-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" + dependencies: + callsites "^0.2.0" + +callsites@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" + camelcase@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" @@ -213,7 +282,17 @@ chalk@0.5.1: strip-ansi "^0.3.0" supports-color "^0.2.0" -chalk@^2.0.1: +chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.0.1, chalk@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" dependencies: @@ -236,10 +315,24 @@ chokidar@^1.6.0, chokidar@^1.7.0: optionalDependencies: fsevents "^1.0.0" +circular-json@^0.3.1: + version "0.3.3" + resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" + cli-boxes@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143" +cli-cursor@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" + dependencies: + restore-cursor "^1.0.1" + +cli-width@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -276,6 +369,14 @@ concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" +concat-stream@^1.5.2: + version "1.6.0" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" + dependencies: + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + concurrently@^3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-3.5.1.tgz#ee8b60018bbe86b02df13e5249453c6ececd2521" @@ -313,6 +414,10 @@ console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" +contains-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" + core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -348,6 +453,12 @@ 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" +d@1: + version "1.0.0" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" + dependencies: + es5-ext "^0.10.9" + dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" @@ -358,7 +469,11 @@ date-fns@^1.23.0: version "1.29.0" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.29.0.tgz#12e609cdcb935127311d04d33334e2960a2a54e6" -debug@2.6.9, debug@^2.2.0, debug@^2.6.8: +debug-log@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/debug-log/-/debug-log-1.0.1.tgz#2307632d4c04382b8df8a32f70b895046d52745f" + +debug@2.6.9, debug@^2.1.1, debug@^2.2.0, debug@^2.6.8: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" dependencies: @@ -374,6 +489,40 @@ deep-extend@~0.4.0: version "0.4.2" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" +deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + +define-properties@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94" + dependencies: + foreach "^2.0.5" + object-keys "^1.0.8" + +deglob@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/deglob/-/deglob-2.1.0.tgz#4d44abe16ef32c779b4972bd141a80325029a14a" + dependencies: + find-root "^1.0.0" + glob "^7.0.5" + ignore "^3.0.9" + pkg-config "^1.1.0" + run-parallel "^1.1.2" + uniq "^1.0.1" + +del@^2.0.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" + dependencies: + globby "^5.0.0" + is-path-cwd "^1.0.0" + is-path-in-cwd "^1.0.0" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + rimraf "^2.2.8" + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -394,6 +543,19 @@ detect-libc@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" +doctrine@1.5.0, doctrine@^1.2.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" + dependencies: + esutils "^2.0.2" + isarray "^1.0.0" + +doctrine@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.0.2.tgz#68f96ce8efc56cc42651f1faadb4f175273b0075" + dependencies: + esutils "^2.0.2" + dot-prop@^4.1.0: version "4.2.0" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" @@ -426,22 +588,256 @@ entities@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" +error-ex@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.7.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.10.0.tgz#1ecb36c197842a00d8ee4c2dfd8646bb97d60864" + dependencies: + es-to-primitive "^1.1.1" + function-bind "^1.1.1" + has "^1.0.1" + is-callable "^1.1.3" + is-regex "^1.0.4" + +es-to-primitive@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d" + dependencies: + is-callable "^1.1.1" + is-date-object "^1.0.1" + is-symbol "^1.0.1" + +es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14: + version "0.10.37" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.37.tgz#0ee741d148b80069ba27d020393756af257defc3" + dependencies: + es6-iterator "~2.0.1" + es6-symbol "~3.1.1" + +es6-iterator@^2.0.1, es6-iterator@~2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-map@^0.1.3: + version "0.1.5" + resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" + dependencies: + d "1" + es5-ext "~0.10.14" + es6-iterator "~2.0.1" + es6-set "~0.1.5" + es6-symbol "~3.1.1" + event-emitter "~0.3.5" + es6-promise@^3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613" +es6-set@~0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" + dependencies: + d "1" + es5-ext "~0.10.14" + es6-iterator "~2.0.1" + es6-symbol "3.1.1" + event-emitter "~0.3.5" + +es6-symbol@3.1.1, es6-symbol@^3.1.1, es6-symbol@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" + dependencies: + d "1" + es5-ext "~0.10.14" + +es6-weak-map@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f" + dependencies: + d "1" + es5-ext "^0.10.14" + es6-iterator "^2.0.1" + es6-symbol "^3.1.1" + escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" -escape-string-regexp@^1.0.0, escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.0, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" +escope@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" + dependencies: + es6-map "^0.1.3" + es6-weak-map "^2.0.1" + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint-config-semistandard@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/eslint-config-semistandard/-/eslint-config-semistandard-11.0.0.tgz#44eef7cfdfd47219e3a7b81b91b540e880bb2615" + +eslint-config-standard-jsx@4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/eslint-config-standard-jsx/-/eslint-config-standard-jsx-4.0.1.tgz#cd4e463d0268e2d9e707f61f42f73f5b3333c642" + +eslint-config-standard@^10.2.1: + version "10.2.1" + resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz#c061e4d066f379dc17cd562c64e819b4dd454591" + +eslint-import-resolver-node@^0.2.0: + version "0.2.3" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.2.3.tgz#5add8106e8c928db2cba232bcd9efa846e3da16c" + dependencies: + debug "^2.2.0" + object-assign "^4.0.1" + resolve "^1.1.6" + +eslint-module-utils@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz#abaec824177613b8a95b299639e1b6facf473449" + dependencies: + debug "^2.6.8" + pkg-dir "^1.0.0" + +eslint-plugin-import@~2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.2.0.tgz#72ba306fad305d67c4816348a4699a4229ac8b4e" + dependencies: + builtin-modules "^1.1.1" + contains-path "^0.1.0" + debug "^2.2.0" + doctrine "1.5.0" + eslint-import-resolver-node "^0.2.0" + eslint-module-utils "^2.0.0" + has "^1.0.1" + lodash.cond "^4.3.0" + minimatch "^3.0.3" + pkg-up "^1.0.0" + +eslint-plugin-node@~4.2.2: + version "4.2.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-4.2.3.tgz#c04390ab8dbcbb6887174023d6f3a72769e63b97" + dependencies: + ignore "^3.0.11" + minimatch "^3.0.2" + object-assign "^4.0.1" + resolve "^1.1.7" + semver "5.3.0" + +eslint-plugin-promise@~3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.5.0.tgz#78fbb6ffe047201627569e85a6c5373af2a68fca" + +eslint-plugin-react@~6.10.0: + version "6.10.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-6.10.3.tgz#c5435beb06774e12c7db2f6abaddcbf900cd3f78" + dependencies: + array.prototype.find "^2.0.1" + doctrine "^1.2.2" + has "^1.0.1" + jsx-ast-utils "^1.3.4" + object.assign "^4.0.4" + +eslint-plugin-standard@~3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz#34d0c915b45edc6f010393c7eef3823b08565cf2" + +eslint@~3.19.0: + version "3.19.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.19.0.tgz#c8fc6201c7f40dd08941b87c085767386a679acc" + dependencies: + babel-code-frame "^6.16.0" + chalk "^1.1.3" + concat-stream "^1.5.2" + debug "^2.1.1" + doctrine "^2.0.0" + escope "^3.6.0" + espree "^3.4.0" + esquery "^1.0.0" + estraverse "^4.2.0" + esutils "^2.0.2" + file-entry-cache "^2.0.0" + glob "^7.0.3" + globals "^9.14.0" + ignore "^3.2.0" + imurmurhash "^0.1.4" + inquirer "^0.12.0" + is-my-json-valid "^2.10.0" + is-resolvable "^1.0.0" + js-yaml "^3.5.1" + json-stable-stringify "^1.0.0" + levn "^0.3.0" + lodash "^4.0.0" + mkdirp "^0.5.0" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.1" + pluralize "^1.2.1" + progress "^1.1.8" + require-uncached "^1.0.2" + shelljs "^0.7.5" + strip-bom "^3.0.0" + strip-json-comments "~2.0.1" + table "^3.7.8" + text-table "~0.2.0" + user-home "^2.0.0" + +espree@^3.4.0: + version "3.5.2" + resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.2.tgz#756ada8b979e9dcfcdb30aad8d1a9304a905e1ca" + dependencies: + acorn "^5.2.1" + acorn-jsx "^3.0.0" + +esprima@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" + +esquery@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.0.tgz#cfba8b57d7fba93f17298a8a006a04cda13d80fa" + dependencies: + estraverse "^4.0.0" + +esrecurse@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.0.tgz#fa9568d98d3823f9a41d91e902dcab9ea6e5b163" + dependencies: + estraverse "^4.1.0" + object-assign "^4.0.1" + +estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" + +esutils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" +event-emitter@~0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + dependencies: + d "1" + es5-ext "~0.10.14" + event-stream@latest, event-stream@~3.3.0: version "3.3.4" resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" @@ -466,6 +862,10 @@ execa@^0.7.0: signal-exit "^3.0.0" strip-eof "^1.0.0" +exit-hook@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" + expand-brackets@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" @@ -492,12 +892,30 @@ 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-levenshtein@~2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + faye-websocket@0.11.x: version "0.11.1" resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.1.tgz#f0efe18c4f56e4f40afc7e06c719fd5ee6188f38" dependencies: websocket-driver ">=0.5.1" +figures@^1.3.5: + version "1.7.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" + dependencies: + escape-string-regexp "^1.0.5" + object-assign "^4.1.0" + +file-entry-cache@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" + dependencies: + flat-cache "^1.2.1" + object-assign "^4.0.1" + filename-regex@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" @@ -522,6 +940,32 @@ finalhandler@0.5.1: statuses "~1.3.1" unpipe "~1.0.0" +find-root@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" + +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + +find-up@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + dependencies: + locate-path "^2.0.0" + +flat-cache@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481" + dependencies: + circular-json "^0.3.1" + del "^2.0.2" + graceful-fs "^4.1.2" + write "^0.2.1" + for-in@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -532,6 +976,10 @@ for-own@^0.1.4: dependencies: for-in "^1.0.1" +foreach@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" + forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -588,6 +1036,10 @@ fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2: mkdirp ">=0.5 0" rimraf "2" +function-bind@^1.0.2, function-bind@^1.1.0, function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" @@ -601,6 +1053,20 @@ gauge@~2.7.3: strip-ansi "^3.0.1" wide-align "^1.1.0" +generate-function@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" + +generate-object-property@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" + dependencies: + is-property "^1.0.0" + +get-stdin@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398" + get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" @@ -624,7 +1090,7 @@ glob-parent@^2.0.0: dependencies: is-glob "^2.0.0" -glob@^7.0.5: +glob@^7.0.0, glob@^7.0.3, glob@^7.0.5: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" dependencies: @@ -641,6 +1107,21 @@ global-dirs@^0.1.0: dependencies: ini "^1.3.4" +globals@^9.14.0: + version "9.18.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" + +globby@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" + dependencies: + array-union "^1.0.1" + arrify "^1.0.0" + glob "^7.0.3" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + got@^6.7.1: version "6.7.1" resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" @@ -678,6 +1159,12 @@ has-ansi@^0.1.0: dependencies: ansi-regex "^0.2.0" +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + dependencies: + ansi-regex "^2.0.0" + has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" @@ -690,6 +1177,12 @@ has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" +has@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" + dependencies: + function-bind "^1.0.2" + hawk@3.1.3, hawk@~3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" @@ -737,6 +1230,10 @@ 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" +ignore@^3.0.11, ignore@^3.0.9, ignore@^3.2.0: + version "3.3.7" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021" + import-lazy@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" @@ -752,7 +1249,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@~2.0.0, inherits@~2.0.3: +inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" @@ -760,6 +1257,32 @@ ini@^1.3.4, ini@~1.3.0: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" +inquirer@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" + dependencies: + ansi-escapes "^1.1.0" + ansi-regex "^2.0.0" + chalk "^1.0.0" + cli-cursor "^1.0.1" + cli-width "^2.0.0" + figures "^1.3.5" + lodash "^4.3.0" + readline2 "^1.0.1" + run-async "^0.1.0" + rx-lite "^3.1.2" + string-width "^1.0.1" + strip-ansi "^3.0.0" + through "^2.3.6" + +interpret@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + is-binary-path@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" @@ -770,6 +1293,14 @@ is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" +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" + +is-date-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" + is-dotfile@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" @@ -811,6 +1342,15 @@ is-installed-globally@^0.1.0: global-dirs "^0.1.0" is-path-inside "^1.0.0" +is-my-json-valid@^2.10.0: + version "2.16.1" + resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz#5a846777e2c2620d1e69104e5d3a03b1f6088f11" + 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" @@ -831,6 +1371,16 @@ is-obj@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" +is-path-cwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" + +is-path-in-cwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc" + dependencies: + is-path-inside "^1.0.0" + is-path-inside@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.0.tgz#fc06e5a1683fbda13de667aff717bbc10a48f37f" @@ -845,10 +1395,24 @@ is-primitive@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" +is-property@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" + is-redirect@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" +is-regex@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" + dependencies: + has "^1.0.1" + +is-resolvable@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.0.1.tgz#acca1cd36dbe44b974b924321555a70ba03b1cf4" + is-retry-allowed@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" @@ -857,6 +1421,10 @@ is-stream@^1.0.0, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" +is-symbol@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572" + is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" @@ -865,7 +1433,7 @@ is-wsl@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" -isarray@1.0.0, isarray@~1.0.0: +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -883,6 +1451,17 @@ isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" +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: + version "3.10.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc" + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" @@ -891,7 +1470,7 @@ json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" -json-stable-stringify@^1.0.1: +json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" dependencies: @@ -911,6 +1490,10 @@ jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" +jsonpointer@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" + jsprim@^1.2.2: version "1.4.1" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" @@ -920,6 +1503,10 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" +jsx-ast-utils@^1.3.4: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz#3867213e8dd79bf1e8f2300c0cfc1efb182c0df1" + kind-of@^3.0.2: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" @@ -938,6 +1525,13 @@ latest-version@^3.0.0: dependencies: package-json "^4.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" + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + linkify-it@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.0.3.tgz#d94a4648f9b1c179d64fa97291268bdb6ce9434f" @@ -962,6 +1556,22 @@ live-server@^1.2.0: send latest serve-index "^1.7.2" +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" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + strip-bom "^3.0.0" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + lodash._baseassign@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" @@ -1001,6 +1611,10 @@ lodash.assign@^3.0.0: lodash._createassigner "^3.0.0" lodash.keys "^3.0.0" +lodash.cond@^4.3.0: + version "4.5.2" + resolved "https://registry.yarnpkg.com/lodash.cond/-/lodash.cond-4.5.2.tgz#f471a1da486be60f6ab955d17115523dd1d255d5" + lodash.defaults@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-3.1.2.tgz#c7308b18dbf8bc9372d701a73493c61192bd2e2c" @@ -1028,7 +1642,7 @@ 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.5.1: +lodash@^4.0.0, lodash@^4.3.0, lodash@^4.5.1: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" @@ -1099,7 +1713,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.4: +minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: @@ -1109,11 +1723,11 @@ minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" -minimist@^1.2.0: +minimist@^1.1.0, minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" -"mkdirp@>=0.5 0", mkdirp@^0.5.1: +"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" dependencies: @@ -1137,10 +1751,18 @@ ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" +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: version "2.8.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.8.0.tgz#ed715f3fe9de02b57a5e6252d90a96675e1f085a" +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" @@ -1218,10 +1840,22 @@ oauth-sign@~0.8.1: version "0.8.2" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" -object-assign@^4, object-assign@^4.1.0, object-assign@latest: +object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@latest: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" +object-keys@^1.0.10, object-keys@^1.0.8: + version "1.0.11" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d" + +object.assign@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.0.4.tgz#b1c9cc044ef1b9fe63606fc141abbb32e14730cc" + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.0" + object-keys "^1.0.10" + object.omit@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" @@ -1245,12 +1879,27 @@ once@^1.3.0, once@^1.3.3: dependencies: wrappy "1" +onetime@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" + opn@latest: version "5.1.0" resolved "https://registry.yarnpkg.com/opn/-/opn-5.1.0.tgz#72ce2306a17dbea58ff1041853352b4a8fc77519" dependencies: is-wsl "^1.1.0" +optionator@^0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.4" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + wordwrap "~1.0.0" + os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" @@ -1270,6 +1919,16 @@ p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" +p-limit@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.1.0.tgz#b07ff2d9a5d88bec806035895a2bab66a27988bc" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + dependencies: + p-limit "^1.1.0" + package-json@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed" @@ -1288,10 +1947,26 @@ parse-glob@^3.0.4: is-extglob "^1.0.0" is-glob "^2.0.0" +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + dependencies: + error-ex "^1.2.0" + parseurl@~1.3.1, parseurl@~1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" +path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + dependencies: + pinkie-promise "^2.0.0" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -1304,6 +1979,10 @@ path-key@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" +path-parse@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" + pause-stream@0.0.11: version "0.0.11" resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" @@ -1314,10 +1993,59 @@ performance-now@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + pify@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + +pkg-conf@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pkg-conf/-/pkg-conf-2.0.0.tgz#071c87650403bccfb9c627f58751bfe47c067279" + dependencies: + find-up "^2.0.0" + load-json-file "^2.0.0" + +pkg-config@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pkg-config/-/pkg-config-1.1.1.tgz#557ef22d73da3c8837107766c52eadabde298fe4" + dependencies: + debug-log "^1.0.0" + find-root "^1.0.0" + xtend "^4.0.1" + +pkg-dir@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" + dependencies: + find-up "^1.0.0" + +pkg-up@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-1.0.0.tgz#3e08fb461525c4421624a33b9f7e6d0af5b05a26" + dependencies: + find-up "^1.0.0" + +pluralize@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + prepend-http@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" @@ -1330,6 +2058,10 @@ process-nextick-args@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" +progress@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" + proxy-middleware@latest: version "0.15.0" resolved "https://registry.yarnpkg.com/proxy-middleware/-/proxy-middleware-0.15.0.tgz#a3fdf1befb730f951965872ac2f6074c61477a56" @@ -1372,7 +2104,7 @@ 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.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: @@ -1393,6 +2125,20 @@ readdirp@^2.0.0: readable-stream "^2.0.2" set-immediate-shim "^1.0.1" +readline2@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + mute-stream "0.0.5" + +rechoir@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + dependencies: + resolve "^1.1.6" + regex-cache@^0.4.2: version "0.4.4" resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" @@ -1451,12 +2197,50 @@ request@2.81.0: tunnel-agent "^0.6.0" uuid "^3.0.0" -rimraf@2, rimraf@^2.5.1, rimraf@^2.6.1: +require-uncached@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" + dependencies: + caller-path "^0.1.0" + resolve-from "^1.0.0" + +resolve-from@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" + +resolve@^1.1.6, resolve@^1.1.7: + version "1.5.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36" + dependencies: + path-parse "^1.0.5" + +restore-cursor@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" + dependencies: + exit-hook "^1.0.0" + onetime "^1.0.0" + +rimraf@2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.6.1: version "2.6.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" dependencies: glob "^7.0.5" +run-async@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389" + dependencies: + once "^1.3.0" + +run-parallel@^1.1.2: + version "1.1.6" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.6.tgz#29003c9a2163e01e2d2dfc90575f2c6c1d61a039" + +rx-lite@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" + rx@2.3.24: version "2.3.24" resolved "https://registry.yarnpkg.com/rx/-/rx-2.3.24.tgz#14f950a4217d7e35daa71bbcbe58eff68ea4b2b7" @@ -1465,12 +2249,31 @@ safe-buffer@5.1.1, safe-buffer@^5.0.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" +semistandard@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/semistandard/-/semistandard-11.0.0.tgz#d2d9fc8ac393de21312195e006e50c8861391c47" + dependencies: + eslint "~3.19.0" + eslint-config-semistandard "^11.0.0" + eslint-config-standard "^10.2.1" + eslint-config-standard-jsx "4.0.1" + eslint-plugin-import "~2.2.0" + eslint-plugin-node "~4.2.2" + eslint-plugin-promise "~3.5.0" + eslint-plugin-react "~6.10.0" + eslint-plugin-standard "~3.0.1" + standard-engine "~7.0.0" + semver-diff@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" 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: version "5.4.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" @@ -1527,10 +2330,22 @@ shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" +shelljs@^0.7.5: + version "0.7.8" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" + dependencies: + glob "^7.0.0" + interpret "^1.0.0" + rechoir "^0.6.2" + signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" +slice-ansi@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" + sntp@1.x.x: version "1.0.9" resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" @@ -1565,6 +2380,15 @@ sshpk@^1.7.0: jsbn "~0.1.0" tweetnacl "~0.14.0" +standard-engine@~7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/standard-engine/-/standard-engine-7.0.0.tgz#ebb77b9c8fc2c8165ffa353bd91ba0dff41af690" + dependencies: + deglob "^2.1.0" + get-stdin "^5.0.1" + minimist "^1.1.0" + pkg-conf "^2.0.0" + "statuses@>= 1.3.1 < 2": version "1.4.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" @@ -1622,6 +2446,10 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" @@ -1634,6 +2462,10 @@ supports-color@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-0.2.0.tgz#d92de2694eb3f67323973d7ae3d8b55b4c22190a" +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + supports-color@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" @@ -1646,6 +2478,17 @@ supports-color@^4.0.0: dependencies: has-flag "^2.0.0" +table@^3.7.8: + version "3.8.3" + resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f" + dependencies: + ajv "^4.7.0" + ajv-keywords "^1.0.0" + chalk "^1.1.1" + lodash "^4.0.0" + slice-ansi "0.0.4" + string-width "^2.0.0" + tar-pack@^3.4.0: version "3.4.1" resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.1.tgz#e1dbc03a9b9d3ba07e896ad027317eb679a10a1f" @@ -1673,7 +2516,11 @@ term-size@^1.2.0: dependencies: execa "^0.7.0" -through@2, through@~2.3, through@~2.3.1: +text-table@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + +through@2, through@^2.3.6, through@~2.3, through@~2.3.1: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" @@ -1707,6 +2554,16 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + dependencies: + prelude-ls "~1.1.2" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + 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" @@ -1719,6 +2576,10 @@ undefsafe@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-0.0.3.tgz#ecca3a03e56b9af17385baac812ac83b994a962f" +uniq@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" + unique-string@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" @@ -1761,6 +2622,12 @@ url-parse-lax@^1.0.0: dependencies: prepend-http "^1.0.1" +user-home@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f" + dependencies: + os-homedir "^1.0.0" + util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -1814,6 +2681,10 @@ widest-line@^1.0.0: dependencies: string-width "^1.0.1" +wordwrap@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -1826,10 +2697,20 @@ write-file-atomic@^2.0.0: imurmurhash "^0.1.4" signal-exit "^3.0.2" +write@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" + dependencies: + mkdirp "^0.5.1" + xdg-basedir@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" +xtend@^4.0.0, xtend@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"