diff --git a/.gitignore b/.gitignore index c2658d7d1..9fe5cb489 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ node_modules/ +currentSnippet\.js +*.md.temp.js diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7e90497d5..618a99b1a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,13 +1,77 @@ ## Contributing -You can contribute to **30 seconds of code** by sending pull requests for snippets that you find useful, reporting issues with current snippets or suggesting changes and/or additions. +**30 seconds of code** is a community effort, so feel free to contribute in any way you can. Every contribution helps! -### Guidelines for new snippets +Here's what you can do to help: -- Snippets must be short. Usually anything above 10 lines would be considered too long, but you can still submit it as it might be possible to shorten it or it might still prove useful regardless of its length. -- Snippets must be explained to a certain extent in the description above them. Make sure to include what functions you are using and why. -- Snippets must solve real-world problems and should be abstract enough to use in different scenarios. This is highly subjective, so send them in anyways. -- Snippets *should* be written in ES6 if possible. -- Snippet files must follow the anchor name conventions of [GitHub Flavored Markdown](https://github.github.com/gfm/), so that the `builder.js` can build the links for the list. -- Use the [template](snippet-template.md) to format your snippets. -- If possible, provide test cases in your Pull Request (link or comment), so that it's easier to verify that each snippet is working. +- [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). +- 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 + +- **DO NOT MODIFY THE README.md FILE!** Make changes to individual snippet files. You can optionally run `npm run build-list` to update the README.md file automatically, based on the changes you have made. +- **Snippet filenames** must correspond to the title of the snippet. For example, if your snippet is titled `### Awesome snippet` the filename should be `awesome-snippet.md`. + - Use `kebab-case`, not `snake_case`. + - Avoid capitalization of words, except if the whole word is capitalized (e.g. `URL` should be capitalized in the filename and the snippet title). + - If there are parentheses in the title, add them to the filename (e.g. `awesome-snippet-(extra-awesome).md` if your snippet's title is `Awesome snippet (extra awesome)`). +- **Snippet titles** should have only the first letter of the first word capitalized. Certain words can be in capitals (e.g. `URL`, `RGB`), but this is on a per-snippet basis. + - All snippet titles must be prefixed with `###` and be at the very first line of your snippet. + - Snippet titles must be unique (although if you cannot find a better title, just add some placeholder at the end of the filename and title and we will figure it out). + - Follow snippet titles with an empty line. +- **Snippet descriptions** must be short and to the point. Try to explain *how* the snippet works and what Javascript features are used. Remember to include what functions you are using and why. + - Follow snippet descriptions with an empty line. +- **Snippet code** must be enclosed inside ` ```js ` and ` ``` `. + - Remember to start your snippet's code on a new line below the opening backticks. + - Use ES6 notation to define your function. For example `const myFunction = arg1, arg2 => { }`. + - Try to keep your snippets' code short and to the point. Use modern techniques and features. Make sure to test your code before submitting. + - All snippets must be followed by one (more if necessary) test case after the code, on a new line, in the form of a comment, along with the expected output. The syntax for this is `myFunction('testInput') -> 'testOutput'`. Use multiline comments only if necessary. + - Try to make your function name unique, so that it does not conflict with existing snippets. +- Snippets should be short (usually below 10 lines). If your snippet is longer than that, you can still submit it, and we can help you shorten it or figure out ways to improve it. +- Snippets *should* solve real-world problems, no matter how simple. +- Snippets *should* be abstract enough to be applied to different scenarios. +- It is not mandatory but highly appreciated if you provide **test cases** and/or performance tests (we recommend using [jsPerf](https://jsperf.com/)). +- You can start creating a new snippet, by using the [snippet template](snippet-template.md) to format your snippets. + +### Additional guidelines and conventions regarding snippets + +- When describing snippets, refer to methods, using their full name. For example, use `Array.reduce()`, instead of `reduce()`. +- If your snippet contains argument with default parameters, explain what happens if they are omitted when calling the function and what the default case is. +- If your snippet uses recursion, explain the base cases. +- Always use `const functionName` for function definitions. +- Use variables only when necessary. Prefer `const` when the values are not altered after assignment, otherwise, use `let`. Avoid using `var`. +- Use `camelCase` for function and variable names if they consist of more than one word. +- Try to give meaningful names to variables. For example use `letter`, instead of `lt`. Some exceptions to convention are: + - `arr` for arrays (usually as the snippet function's argument). + - `str` for strings. + - `n` for a numeric value (usually as the snippet function's argument). + - `el` for DOM elements (usually as the snippet function's argument). + - `val` or `v` for value (usually when iterating a list, mapping, sorting etc.). + - `acc` for accumulators in `Array.reduce()`. + - `(a,b)` for the two values compared when using `Array.sort()`. + - `i` for indexes. + - `func` for function arguments. + - `nums` for arrays of numbers. +- Use `_` if your function takes no arguments or if an argument inside some function (e.g. `Array.reduce()`) is not used anywhere in your code. +- Specify default parameters for arguments, if necessary. It is preferred to put default parameters last unless you have pretty good reason not to. +- If your snippet's function takes variadic arguments, use `..args` (although in certain cases, it might be needed to use a different name). +- If your snippet function's body is a single statement, omit the `return` keyword and use an expression instead. +- Always use soft tabs (2 spaces), never hard tabs. +- Omit curly braces (`{` and `}`) whenever possible. +- Always use single quotes for string literals. Use template literals, instead, if necessary. +- If your snippet's code is short enough (around 80 characters), you can make it a single-line function (although not mandatory). Otherwise, use multiple lines. +- Prefer using `Array` methods whenever possible. +- Prefer `Array.concat()` instead of `Array.push()` when working with `Array.reduce()`. +- Use strict equality checking (`===` and `!==` instead of `==` and `!=`), unless you specificly have reason not to. +- Prefer using the ternary operator (`condition ? trueResult : falseResult`) instead of `if else` statements whenever possible. +- Avoid nesting ternary operators (but you can do it if you feel like you should). +- You should define multiple variables on the same line (e.g. `const x = 0, y = 0`) on the same line whenever possible. +- Do not use trailing or leading underscores in variable names. +- Use dot notation (`object.property`) for object properties, when possible. Use bracket notation (`object[variable]`) when accessing object properties using a variable. +- Use arrow functions as much as possible, except when you can't. +- Use semicolons whenever necessary. If your snippet function's body is a single statement, return an expression and add a semicolon at the end. +- Leave a single space after a comma (`,`) character. +- Try to strike a balance between readability, brevity, and performance. +- Never use `eval()`. Your snippet will be disqualified immediately. diff --git a/LICENSE b/LICENSE index 9eea76289..670154e35 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,116 @@ -30 seconds of code is licensed under Creative Commons CC0 1.0 Universal license. -https://creativecommons.org/publicdomain/zero/1.0/ -The license states, "You can copy, modify, distribute and perform the work, even for commercial purposes, -all without asking permission." Additionally, we ask that groups utilizing this ontology reference this project. +CC0 1.0 Universal + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator and +subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the +purpose of contributing to a commons of creative, cultural and scientific +works ("Commons") that the public can reliably and without fear of later +claims of infringement build upon, modify, incorporate in other works, reuse +and redistribute as freely as possible in any form whatsoever and for any +purposes, including without limitation commercial purposes. These owners may +contribute to the Commons to promote the ideal of a free culture and the +further production of creative, cultural and scientific works, or to gain +reputation or greater distribution for their Work in part through the use and +efforts of others. + +For these and/or other purposes and motivations, and without any expectation +of additional consideration or compensation, the person associating CC0 with a +Work (the "Affirmer"), to the extent that he or she is an owner of Copyright +and Related Rights in the Work, voluntarily elects to apply CC0 to the Work +and publicly distribute the Work under its terms, with knowledge of his or her +Copyright and Related Rights in the Work and the meaning and intended legal +effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not limited +to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + + ii. moral rights retained by the original author(s) and/or performer(s); + + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, +applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and +unconditionally waives, abandons, and surrenders all of Affirmer's Copyright +and Related Rights and associated claims and causes of action, whether now +known or unknown (including existing as well as future claims and causes of +action), in the Work (i) in all territories worldwide, (ii) for the maximum +duration provided by applicable law or treaty (including future time +extensions), (iii) in any current or future medium and for any number of +copies, and (iv) for any purpose whatsoever, including without limitation +commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes +the Waiver for the benefit of each member of the public at large and to the +detriment of Affirmer's heirs and successors, fully intending that such Waiver +shall not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of the Work +by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be +judged legally invalid or ineffective under applicable law, then the Waiver +shall be preserved to the maximum extent permitted taking into account +Affirmer's express Statement of Purpose. In addition, to the extent the Waiver +is so judged Affirmer hereby grants to each affected person a royalty-free, +non transferable, non sublicensable, non exclusive, irrevocable and +unconditional license to exercise Affirmer's Copyright and Related Rights in +the Work (i) in all territories worldwide, (ii) for the maximum duration +provided by applicable law or treaty (including future time extensions), (iii) +in any current or future medium and for any number of copies, and (iv) for any +purpose whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed effective as +of the date CC0 was applied by Affirmer to the Work. Should any part of the +License for any reason be judged legally invalid or ineffective under +applicable law, such partial invalidity or ineffectiveness shall not +invalidate the remainder of the License, and in such case Affirmer hereby +affirms that he or she will not (i) exercise any of his or her remaining +Copyright and Related Rights in the Work or (ii) assert any associated claims +and causes of action with respect to the Work, in either case contrary to +Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +For more information, please see + diff --git a/README.md b/README.md index 640da6cd9..7160b9afb 100644 --- a/README.md +++ b/README.md @@ -1,257 +1,302 @@ ![Logo](/logo.png) -# 30 seconds of code +# 30 seconds of code [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/30-seconds-of-code/Lobby) > Curated collection of useful Javascript snippets that you can understand in 30 seconds or less. - Use Ctrl + F or command + F to search for a snippet. -- Contributions welcome, please read [contribution guide](CONTRIBUTING.md). +- Contributions welcome, please read the [contribution guide](CONTRIBUTING.md). +- Snippets are written in ES6, use the [Babel transpiler](https://babeljs.io/) to ensure backwards-compatibility. -## Contents +## 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) -* [Capitalize first letter of every word](#capitalize-first-letter-of-every-word) -* [Capitalize first letter](#capitalize-first-letter) -* [Check for palindrome](#check-for-palindrome) +* [Chunk array](#chunk-array) +* [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) -* [Difference between arrays](#difference-between-arrays) -* [Distance between two points](#distance-between-two-points) -* [Divisible by number](#divisible-by-number) -* [Escape regular expression](#escape-regular-expression) -* [Even or odd number](#even-or-odd-number) -* [Factorial](#factorial) -* [Fibonacci array generator](#fibonacci-array-generator) -* [Filter out non uniqe values in an array](#filter-out-non-uniqe-values-in-an-array) +* [Drop elements in array](#drop-elements-in-array) +* [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 scroll position](#get-scroll-position) -* [Greatest common divisor (GCD)](#greatest-common-divisor-gcd) +* [Group by](#group-by) * [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) -* [Measure time taken by function](#measure-time-taken-by-function) -* [Object from key value pairs](#object-from-key-value-pairs) -* [Pipe](#pipe) -* [Powerset](#powerset) -* [Random number in range](#random-number-in-range) -* [Randomize order of array](#randomize-order-of-array) -* [Redirect to url](#redirect-to-url) -* [Reverse a string](#reverse-a-string) -* [RGB to hexadecimal](#rgb-to-hexadecimal) -* [Scroll to top](#scroll-to-top) -* [Shuffle array values](#shuffle-array-values) +* [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) -* [Sort characters in string (alphabetical)](#sort-characters-in-string-alphabetical) * [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) * [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) +* [Measure time taken by function](#measure-time-taken-by-function) +* [Number to array of digits](#number-to-array-of-digits) +* [Ordinal suffix of number](#ordinal-suffix-of-number) +* [Random integer in range](#random-integer-in-range) +* [Random number in range](#random-number-in-range) +* [RGB to hexadecimal](#rgb-to-hexadecimal) +* [Swap values of two variables](#swap-values-of-two-variables) * [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 `map()` to combine the letter with each partial anagram, then `reduce()` to combine all anagrams in one array. -Base cases are for string `length` equal to `2` or `1`. +### Array concatenation + +Use `Array.concat()` to concatenate an array with any additional arrays and/or values, specified in `args`. ```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) => { - anagrams(str.slice(0, i) + str.slice(i + 1)).map( val => acc.push(letter + val) ); - return acc; - }, []); -} -// anagrams('abc') -> ['abc','acb','bac','bca','cab','cba'] +const arrayConcat = (arr, ...args) => arr.concat(...args); +// arrayConcat([1], 2, [3], [[4]]) -> [1,2,3,[4]] ``` +[⬆ 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)); }; +// 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)); }; +// 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])); +// union([1,2,3], [4,3,2]) -> [1,2,3,4] +``` + +[⬆ back to top](#table-of-contents) + ### Average of array of numbers -Use `reduce()` to add each value to an accumulator, initialized with a value of `0`, divide by the `length` of the array. +Use `Array.reduce()` to add each value to an accumulator, initialized with a value of `0`, divide by the `length` of the array. ```js -const average = arr => - arr.reduce( (acc , val) => acc + val, 0) / arr.length; +const average = arr => arr.reduce((acc, val) => acc + val, 0) / arr.length; // average([1,2,3]) -> 2 ``` -### Capitalize first letter of every word +[⬆ back to top](#table-of-contents) -Use `replace()` to match the first character of each word and `toUpperCase()` to capitalize it. +### 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 capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase()); -// capitalizeEveryWord('hello world!') -> 'Hello World!' +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] ``` -### Capitalize first letter +[⬆ back to top](#table-of-contents) -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. +### Compact + +Use `Array.filter()` to filter out falsey values (`false`, `null`, `0`, `""`, `undefined`, and `NaN`). ```js -const capitalize = (str, lowerRest = false) => - str.slice(0, 1).toUpperCase() + (lowerRest? str.slice(1).toLowerCase() : str.slice(1)); -// capitalize('myName', true) -> 'Myname' +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 ] ``` -### 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 => - str.toLowerCase().replace(/[\W_]/g,'').split('').reverse().join('') === str.toLowerCase().replace(/[\W_]/g,''); -// palindrome('taco cat') -> true - ``` +[⬆ back to top](#table-of-contents) ### Count occurrences of a value in array -Use `reduce()` to increment a counter each time you encounter the specific value inside the 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 ``` -### Current URL - -Use `window.location.href` to get current URL. - -```js -const currentUrl = _ => window.location.href; -// currentUrl() -> 'https://google.com' -``` - -### Curry - -Use recursion. -If the number of provided arguments (`args`) is sufficient, call the passed function `f`. -Otherwise return a curried function `f` that expects the rest of the arguments. - -```js -const curry = f => - (...args) => - args.length >= f.length ? f(...args) : (...otherArgs) => curry(f)(...args, ...otherArgs); -// curry(Math.pow)(2)(10) -> 1024 -``` +[⬆ back to top](#table-of-contents) ### Deep flatten array Use recursion. -Use `reduce()` to get all elements that are not arrays, flatten each element that is an array. +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) ? flatten(v) : v ), []); + arr.reduce((a, v) => a.concat(Array.isArray(v) ? deepFlatten(v) : v), []); // deepFlatten([1,[2],[[3],4],5]) -> [1,2,3,4,5] ``` -### Difference between arrays +[⬆ back to top](#table-of-contents) -Use `filter()` to remove values that are part of `values`, determined using `includes()`. +### 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 difference = (arr, values) => arr.filter(v => !values.includes(v)); -// difference([1,2,3], [1,2]) -> [3] +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] ``` -### Distance between two points +[⬆ back to top](#table-of-contents) -Use `Math.hypot()` to calculate the Euclidean distance between two points. +### 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 distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0); -// distance(1,1, 2,3) -> 2.23606797749979 +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] ``` -### 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 -``` - -### Escape regular expression - -Use `replace()` to escape special characters. - -```js -const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); -// escapeRegExp('(test)') -> \\(test\\) -``` - -### Even or odd number - -Use `Math.abs()` to extend logic to negative numbers, check using the modulo (`%`) operator. -Return `true` if the number is even, `false` if the number is odd. - -```js -const isEven = num => Math.abs(num) % 2 === 0; -// isEven(3) -> false -``` - -### 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 -``` - -### 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) ### Filter out non-unique values in an array Use `Array.filter()` for an array containing only the unique values. ```js -const unique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i)); -// unique([1,2,2,3,4,4,5]) -> [1,3,5] +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 `reduce()` to get all elements inside the array and `concat()` to flatten them. +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] +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 minimum value in the 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. @@ -261,58 +306,58 @@ const arrayMin = arr => Math.min(...arr); // arrayMin([10, 1, 5]) -> 1 ``` -### Get scroll position +[⬆ back to top](#table-of-contents) -Use `pageXOffset` and `pageYOffset` if they are defined, otherwise `scrollLeft` and `scrollTop`. -You can omit `el` to use a default value of `window`. +### 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 getScrollPos = (el = window) => - ( {x: (el.pageXOffset !== undefined) ? el.pageXOffset : el.scrollLeft, - y: (el.pageYOffset !== undefined) ? el.pageYOffset : el.scrollTop} ); -// getScrollPos() -> {x: 0, y: 200} +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']} ``` -### 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) ### Head of list -Return `arr[0]`. +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 -Return `arr.slice(0,-1)`. +Use `arr.slice(0,-1)`to return all but the last element of the array. ```js -const initial = arr => arr.slice(0,-1); +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, `map()` to fill with the desired values in a 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 ); + 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. @@ -323,75 +368,190 @@ 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 -Return `arr.slice(-1)[0]`. +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 ``` -### Measure time taken by function +[⬆ back to top](#table-of-contents) -Use `performance.now()` to get start and end time for the function, `console.log()` the time taken. -First argument is the function name, subsequent arguments are passed to the function. +### 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 timeTaken = (func,...args) => { - var t0 = performance.now(), r = func(...args); - console.log(performance.now() - t0); - return r; -} -// timeTaken(Math.pow, 2, 10) -> 1024 (0.010000000009313226 logged in console) +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 ``` -### Object from key-value pairs +[⬆ back to top](#table-of-contents) -Use `Array.reduce()` to create and combine key-value pairs. +### 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 objectFromPairs = arr => arr.reduce((a,v) => (a[v[0]] = v[1], a), {}); -// objectFromPairs([['a',1],['b',2]]) -> {a: 1, b: 2} +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' ``` -### Pipe +[⬆ back to top](#table-of-contents) -Use `Array.reduce()` to pass value through functions. +### 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 pipe = (...funcs) => arg => funcs.reduce((acc, func) => func(acc), arg); -// pipe(btoa, x => x.toUpperCase())("Test") -> "VGVZDA==" +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 ``` -### Powerset +[⬆ back to top](#table-of-contents) -Use `reduce()` combined with `map()` to iterate over elements and combine into an array containing all combinations. +### Shuffle array + +Use `Array.sort()` to reorder elements, using `Math.random()` in the comparator. ```js -const powerset = arr => - arr.reduce( (a,v) => a.concat(a.map( r => [v].concat(r) )), [[]]); -// powerset([1,2]) -> [[], [1], [2], [2,1]] +const shuffle = arr => arr.sort(() => Math.random() - 0.5); +// shuffle([1,2,3]) -> [2,3,1] ``` -### Random number in range +[⬆ back to top](#table-of-contents) -Use `Math.random()` to generate a random value, map it to the desired range using multiplication. +### Similarity between arrays + +Use `filter()` to remove values that are not part of `values`, determined using `includes()`. ```js -const randomInRange = (min, max) => Math.random() * (max - min) + min; -// randomInRange(2,10) -> 6.0211363285087005 +const similarity = (arr, values) => arr.filter(v => values.includes(v)); +// similarity([1,2,3], [1,2,4]) -> [1,2] ``` -### Randomize order of array +[⬆ back to top](#table-of-contents) -Use `sort()` to reorder elements, utilizing `Math.random()` to randomize the sorting. +### Sum of array of numbers + +Use `Array.reduce()` to add each value to an accumulator, initialized with a value of `0`. ```js -const randomizeOrder = arr => arr.sort( (a,b) => Math.random() >= 0.5 ? -1 : 1); -// randomizeOrder([1,2,3]) -> [1,3,2] +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. + +```js +const bottomVisible = _ => + document.documentElement.clientHeight + window.scrollY >= document.documentElement.scrollHeight || document.documentElement.clientHeight; +// bottomVisible() -> true +``` + +[⬆ 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) + +### 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) + +### 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`. @@ -403,6 +563,405 @@ const redirect = (url, asLink = true) => // 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. + +```js +const chainAsync = fns => { let curr = 0; const next = () => fns[curr++](next); next(); }; +/* +chainAsync([ + next => { console.log('0 seconds'); setTimeout(next, 1000); }, + next => { console.log('1 second'); setTimeout(next, 1000); }, + next => { console.log('2 seconds'); } +]) +*/ +``` + +[⬆ back to top](#table-of-contents) + +### Curry + +Use recursion. +If the number of provided arguments (`args`) is sufficient, call the passed function `f`. +Otherwise return a curried function `f` that expects the rest of the arguments. +If you want to curry a function that accepts a variable number of arguments (a variadic function, e.g. `Math.min()`), you can optionally pass the number of arguments to the second parameter `arity`. + +```js +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) + +### Pipe + +Use `Array.reduce()` to pass value through functions. + +```js +const pipe = (...funcs) => arg => funcs.reduce((acc, func) => func(acc), arg); +// pipe(btoa, x => x.toUpperCase())("Test") -> "VGVZDA==" +``` + +[⬆ back to top](#table-of-contents) + +### Promisify + +Use currying to return a function returning a `Promise` that calls the original function. +Use the `...rest` operator to pass in all the parameters. + +*In Node 8+, you can use [`util.promisify`](https://nodejs.org/api/util.html#util_util_promisify_original)* + +```js +const promisify = func => + (...args) => + new Promise((resolve, reject) => + func(...args, (err, result) => + err ? reject(err) : resolve(result)) + ); +// const delay = promisify((d, cb) => setTimeout(cb, d)) +// delay(2000).then(() => console.log('Hi!')) -> Promise resolves after 2s +``` + +[⬆ 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. + +```js +const series = ps => ps.reduce((p, next) => p.then(next), Promise.resolve()); +// const delay = (d) => new Promise(r => setTimeout(r, d)) +// series([() => delay(1000), () => delay(2000)]) -> executes each promise sequentially, taking a total of 3 seconds to complete +``` + +[⬆ back to top](#table-of-contents) + +### Sleep + +Delay executing part of an `async` function, by putting it to sleep, returning a `Promise`. + +```js +const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); +/* +async function sleepyWork() { + console.log('I\'m going to sleep for 1 second.'); + await sleep(1000); + console.log('I woke up after 1 second.'); +} +*/ +``` + +[⬆ back to top](#table-of-contents) +## Math + +### 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) + +### 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 +determine the standard deviation. +You can omit the second argument to get the sample standard deviation or set it to `true` to get the population standard deviation. + +```js +const standardDeviation = (arr, usePopulation = false) => { + const mean = arr.reduce((acc, val) => acc + val, 0) / arr.length; + return Math.sqrt( + arr.reduce((acc, val) => acc.concat(Math.pow(val - mean, 2)), []) + .reduce((acc, val) => acc + val, 0) / (arr.length - (usePopulation ? 0 : 1)) + ); +}; +// 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) +## Media + +### 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 +``` + +[⬆ back to top](#table-of-contents) +## Object + +### 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) + +### 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 +*/ +``` + +[⬆ 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. @@ -413,6 +972,198 @@ 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`. +Return the string truncated to the desired length, with `...` appended to the end or the original string. + +```js +const truncate = (str, num) => + str.length > num ? str.slice(0, num > 3 ? num - 3 : num) + '...' : str; +// truncate('boomerang', 7) -> 'boom...' +``` + +[⬆ back to top](#table-of-contents) +## Utility + +### 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) + +### 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. @@ -422,62 +1173,7 @@ const rgbToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6 // rgbToHex(255, 165, 1) -> 'ffa501' ``` -### 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() -``` - -### Shuffle array values - -Create an array of random values by using `Array.map()` and `Math.random()`. -Use `Array.sort()` to sort the elements of the original array based on the random values. - -```js -const shuffle = arr => { - let r = arr.map(Math.random); - return arr.sort((a,b) => r[a] - r[b]); -} -// shuffle([1,2,3]) -> [2, 1, 3] -``` - -### 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] -``` - -### Sort characters in string (alphabetical) - -Split the string using `split('')`, `sort()` utilizing `localeCompare()`, recombine using `join('')`. - -```js -const sortCharactersInString = str => - str.split('').sort( (a,b) => a.localeCompare(b) ).join(''); -// sortCharactersInString('cabbage') -> 'aabbceg' -``` - -### Sum of array of numbers - -Use `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) ### Swap values of two variables @@ -488,58 +1184,74 @@ Use array destructuring to swap values between two variables. // [x, y] = [y, x] ``` -### Tail of list - -Return `arr.slice(1)`. - -```js -const tail = arr => arr.slice(1); -// tail([1,2,3]) -> [2,3] -``` - -### 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) ### URL parameters -Use `match()` with an appropriate regular expression to get all key-value pairs, `map()` them appropriately. -Combine all key-value pairs into a single object using `Object.assign()` and the spread operator (`...`). +Use `match()` with an appropriate regular expression to get all key-value pairs, `Array.reduce()` to map and combine them into a single object. Pass `location.search` as the argument to apply to the current `url`. ```js const getUrlParameters = url => - Object.assign(...url.match(/([^?=&]+)(=([^&]*))?/g).map(m => {[f,v] = m.split('='); return {[f]:v}})); + url.match(/([^?=&]+)(=([^&]*))/g).reduce( + (a, v) => (a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1), a), {} + ); // getUrlParameters('http://url.com/page?name=Adam&surname=Smith') -> {name: 'Adam', surname: 'Smith'} ``` +[⬆ 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. ```js const uuid = _ => - ( [1e7]+-1e3+-4e3+-8e3+-1e11 ).replace( /[018]/g, c => + ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16) ); // uuid() -> '7982fcfe-5721-4632-bede-6000885be57d' ``` +[⬆ back to top](#table-of-contents) + +### Validate email + +Use a regular experssion to check if the email is valid. +Returns `true` if email is valid, `false` if not. + +```js +const validateEmail = str => + /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(str); +// validateEmail(mymail@gmail.com) -> true +``` + +[⬆ back to top](#table-of-contents) + ### Validate number Use `!isNaN` in combination with `parseFloat()` to check if the argument is a number. Use `isFinite()` to check if the number is finite. +Use `Number()` to check if the coercion holds. ```js -const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n); +const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n; // validateNumber('10') -> true ``` +[⬆ back to top](#table-of-contents) + +### Value or default + +Returns value, or default value if passed value is `falsy`. + +```js +const valueOrDefault = (value, d) => value || d; +// valueOrDefault(NaN, 30) -> 30 +``` + +[⬆ 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 50c9abf8a..4344c4b9b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,40 @@ "negotiator": "0.6.1" } }, + "acorn": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.2.1.tgz", + "integrity": "sha512-jG0u7c4Ly+3QkkW18V+NRDN+4bWHdln30NL1ZL2AvFZZmQe/BfopYCtghCKKVBUSetZ4QKcyA0pY6/4Gw8Pv8w==" + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "requires": { + "acorn": "3.3.0" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=" + } + } + }, + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ajv-keywords": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", + "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=" + }, "ansi-align": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", @@ -26,15 +60,10 @@ "string-width": "2.1.1" } }, - "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=" + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=" }, "anymatch": { "version": "1.3.2", @@ -79,16 +108,98 @@ "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "requires": { + "array-uniq": "1.0.3" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" + }, "array-unique": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" }, + "array.prototype.find": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.0.4.tgz", + "integrity": "sha1-VWpcU2LAhkgyPdrrnenRS8GGTJA=", + "requires": { + "define-properties": "1.1.2", + "es-abstract": "1.10.0" + } + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" + }, "async-each": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=" }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -183,6 +294,24 @@ "repeat-element": "1.1.2" } }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "requires": { + "callsites": "0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=" + }, "camelcase": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", @@ -194,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" + } } } }, @@ -227,11 +374,34 @@ "readdirp": "2.1.0" } }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==" + }, "cli-boxes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=" }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "requires": { + "restore-cursor": "1.0.1" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -265,12 +435,21 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, + "concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "typedarray": "0.0.6" + } + }, "concurrently": { "version": "3.5.1", "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", @@ -304,6 +483,11 @@ "utils-merge": "1.0.0" } }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=" + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -341,6 +525,14 @@ "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=" }, + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "requires": { + "es5-ext": "0.10.37" + } + }, "date-fns": { "version": "1.29.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.29.0.tgz", @@ -354,11 +546,64 @@ "ms": "0.7.1" } }, + "debug-log": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/debug-log/-/debug-log-1.0.1.tgz", + "integrity": "sha1-IwdjLUwEOCuN+KMvcLiVBG1SdF8=" + }, "deep-extend": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=" }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + }, + "define-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "requires": { + "foreach": "2.0.5", + "object-keys": "1.0.11" + } + }, + "deglob": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/deglob/-/deglob-2.1.0.tgz", + "integrity": "sha1-TUSr4W7zLHebSXK9FBqAMlApoUo=", + "requires": { + "find-root": "1.1.0", + "glob": "7.1.2", + "ignore": "3.3.7", + "pkg-config": "1.1.1", + "run-parallel": "1.1.6", + "uniq": "1.0.1" + } + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "requires": { + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.0", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.6.2" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, "depd": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", @@ -369,6 +614,14 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, + "doctrine": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.2.tgz", + "integrity": "sha512-y0tm5Pq6ywp3qSTZ1vPgVdAnbDEoeoc5wlOHXoY1c4Wug/a7JvqHIl7BTvwodaHmejWkK/9dSb3sCYfyo/om8A==", + "requires": { + "esutils": "2.0.2" + } + }, "dot-prop": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", @@ -402,11 +655,105 @@ "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=" }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "requires": { + "is-arrayish": "0.2.1" + } + }, + "es-abstract": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.10.0.tgz", + "integrity": "sha512-/uh/DhdqIOSkAWifU+8nG78vlQxdLckUdI/sPgy0VhuXi2qJ7T8czBmqIYtLQVpCIFYafChnsRsB5pyb1JdmCQ==", + "requires": { + "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": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", + "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", + "requires": { + "is-callable": "1.1.3", + "is-date-object": "1.0.1", + "is-symbol": "1.0.1" + } + }, + "es5-ext": { + "version": "0.10.37", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.37.tgz", + "integrity": "sha1-DudB0Ui4AGm6J9AgOTdWryV978M=", + "requires": { + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37", + "es6-symbol": "3.1.1" + } + }, + "es6-map": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37", + "es6-iterator": "2.0.3", + "es6-set": "0.1.5", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, "es6-promise": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=" }, + "es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37", + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37" + } + }, + "es6-weak-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37", + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1" + } + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -417,11 +764,288 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, + "escope": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "requires": { + "es6-map": "0.1.5", + "es6-weak-map": "2.0.2", + "esrecurse": "4.2.0", + "estraverse": "4.2.0" + } + }, + "eslint": { + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz", + "integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw=", + "requires": { + "babel-code-frame": "6.26.0", + "chalk": "1.1.3", + "concat-stream": "1.6.0", + "debug": "2.2.0", + "doctrine": "2.0.2", + "escope": "3.6.0", + "espree": "3.5.2", + "esquery": "1.0.0", + "estraverse": "4.2.0", + "esutils": "2.0.2", + "file-entry-cache": "2.0.0", + "glob": "7.1.2", + "globals": "9.18.0", + "ignore": "3.3.7", + "imurmurhash": "0.1.4", + "inquirer": "0.12.0", + "is-my-json-valid": "2.16.1", + "is-resolvable": "1.0.1", + "js-yaml": "3.10.0", + "json-stable-stringify": "1.0.1", + "levn": "0.3.0", + "lodash": "4.17.4", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "optionator": "0.8.2", + "path-is-inside": "1.0.2", + "pluralize": "1.2.1", + "progress": "1.1.8", + "require-uncached": "1.0.3", + "shelljs": "0.7.8", + "strip-bom": "3.0.0", + "strip-json-comments": "2.0.1", + "table": "3.8.3", + "text-table": "0.2.0", + "user-home": "2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "eslint-config-semistandard": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-semistandard/-/eslint-config-semistandard-11.0.0.tgz", + "integrity": "sha1-RO73z9/Uchnjp7gbkbVA6IC7JhU=" + }, + "eslint-config-standard": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz", + "integrity": "sha1-wGHk0GbzedwXzVYsZOgZtN1FRZE=" + }, + "eslint-config-standard-jsx": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-4.0.1.tgz", + "integrity": "sha1-zU5GPQJo4tnnB/YfQvc/WzMzxkI=" + }, + "eslint-import-resolver-node": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.2.3.tgz", + "integrity": "sha1-Wt2BBujJKNssuiMrzZ76hG49oWw=", + "requires": { + "debug": "2.2.0", + "object-assign": "4.1.1", + "resolve": "1.5.0" + } + }, + "eslint-module-utils": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz", + "integrity": "sha512-jDI/X5l/6D1rRD/3T43q8Qgbls2nq5km5KSqiwlyUbGo5+04fXhMKdCPhjwbqAa6HXWaMxj8Q4hQDIh7IadJQw==", + "requires": { + "debug": "2.6.9", + "pkg-dir": "1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "eslint-plugin-import": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.2.0.tgz", + "integrity": "sha1-crowb60wXWfEgWNIpGmaQimsi04=", + "requires": { + "builtin-modules": "1.1.1", + "contains-path": "0.1.0", + "debug": "2.2.0", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "0.2.3", + "eslint-module-utils": "2.1.1", + "has": "1.0.1", + "lodash.cond": "4.5.2", + "minimatch": "3.0.4", + "pkg-up": "1.0.0" + }, + "dependencies": { + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "requires": { + "esutils": "2.0.2", + "isarray": "1.0.0" + } + } + } + }, + "eslint-plugin-node": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-4.2.3.tgz", + "integrity": "sha512-vIUQPuwbVYdz/CYnlTLsJrRy7iXHQjdEe5wz0XhhdTym3IInM/zZLlPf9nZ2mThsH0QcsieCOWs2vOeCy/22LQ==", + "requires": { + "ignore": "3.3.7", + "minimatch": "3.0.4", + "object-assign": "4.1.1", + "resolve": "1.5.0", + "semver": "5.3.0" + }, + "dependencies": { + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" + } + } + }, + "eslint-plugin-promise": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.5.0.tgz", + "integrity": "sha1-ePu2/+BHIBYnVp6FpsU3OvKmj8o=" + }, + "eslint-plugin-react": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-6.10.3.tgz", + "integrity": "sha1-xUNb6wZ3ThLH2y9qut3L+QDNP3g=", + "requires": { + "array.prototype.find": "2.0.4", + "doctrine": "1.5.0", + "has": "1.0.1", + "jsx-ast-utils": "1.4.1", + "object.assign": "4.0.4" + }, + "dependencies": { + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "requires": { + "esutils": "2.0.2", + "isarray": "1.0.0" + } + } + } + }, + "eslint-plugin-standard": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz", + "integrity": "sha1-NNDJFbRe3G8BA5PH7vOCOwhWXPI=" + }, + "espree": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.2.tgz", + "integrity": "sha512-sadKeYwaR/aJ3stC2CdvgXu1T16TdYN+qwCpcWbMnGJ8s0zNWemzrvb2GbD4OhmJ/fwpJjudThAlLobGbWZbCQ==", + "requires": { + "acorn": "5.2.1", + "acorn-jsx": "3.0.1" + } + }, + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" + }, + "esquery": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", + "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", + "requires": { + "estraverse": "4.2.0" + } + }, + "esrecurse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", + "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", + "requires": { + "estraverse": "4.2.0", + "object-assign": "4.1.1" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + }, "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37" + } + }, "event-stream": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", @@ -450,6 +1074,11 @@ "strip-eof": "1.0.0" } }, + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=" + }, "expand-brackets": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", @@ -474,6 +1103,11 @@ "is-extglob": "1.0.0" } }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, "faye-websocket": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz", @@ -482,6 +1116,24 @@ "websocket-driver": "0.7.0" } }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "requires": { + "flat-cache": "1.3.0", + "object-assign": "4.1.1" + } + }, "filename-regex": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", @@ -511,6 +1163,31 @@ "unpipe": "1.0.0" } }, + "find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "requires": { + "circular-json": "0.3.3", + "del": "2.2.2", + "graceful-fs": "4.1.11", + "write": "0.2.1" + } + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -524,6 +1201,11 @@ "for-in": "1.0.2" } }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" + }, "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -544,11 +1226,52 @@ "universalify": "0.1.1" } }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "generate-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=" + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "requires": { + "is-property": "1.0.2" + } + }, + "get-stdin": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", + "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=" + }, "get-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, "glob-base": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", @@ -574,6 +1297,31 @@ "ini": "1.3.5" } }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==" + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, "got": { "version": "6.7.1", "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", @@ -597,12 +1345,12 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" }, - "has-ansi": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", - "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", + "has": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", "requires": { - "ansi-regex": "0.2.1" + "function-bind": "1.1.1" } }, "has-flag": { @@ -637,6 +1385,11 @@ "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.9.tgz", "integrity": "sha1-6hoE+2St/wJC6ZdPKX3Uw8rSceE=" }, + "ignore": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", + "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==" + }, "ignore-by-default": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", @@ -652,6 +1405,15 @@ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", @@ -662,6 +1424,99 @@ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" }, + "inquirer": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", + "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", + "requires": { + "ansi-escapes": "1.4.0", + "ansi-regex": "2.1.1", + "chalk": "1.1.3", + "cli-cursor": "1.0.2", + "cli-width": "2.2.0", + "figures": "1.7.0", + "lodash": "4.17.4", + "readline2": "1.0.1", + "run-async": "0.1.0", + "rx-lite": "3.1.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "through": "2.3.8" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "1.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=" + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, "is-binary-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", @@ -675,6 +1530,16 @@ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, + "is-callable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", + "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=" + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" + }, "is-dotfile": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", @@ -720,6 +1585,17 @@ "is-path-inside": "1.0.1" } }, + "is-my-json-valid": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz", + "integrity": "sha512-ochPsqWS1WXj8ZnMIV0vnNXooaMhp7cyL4FMSIPKTtnV0Ha/T19G2b9kkhcNsabV9bxYkze7/aLZJb/bYuFduQ==", + "requires": { + "generate-function": "2.0.0", + "generate-object-property": "1.2.0", + "jsonpointer": "4.0.1", + "xtend": "4.0.1" + } + }, "is-npm": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", @@ -738,6 +1614,19 @@ "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=" + }, + "is-path-in-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "requires": { + "is-path-inside": "1.0.1" + } + }, "is-path-inside": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", @@ -756,11 +1645,29 @@ "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" + }, "is-redirect": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=" }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "requires": { + "has": "1.0.1" + } + }, + "is-resolvable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.1.tgz", + "integrity": "sha512-y5CXYbzvB3jTnWAZH1Nl7ykUWb6T3BcTs56HUruwBf8MhF56n1HWqhDWnVFo8GHrUPDgvUUNVhrc2U8W7iqz5g==" + }, "is-retry-allowed": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", @@ -771,6 +1678,11 @@ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, + "is-symbol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", + "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=" + }, "is-wsl": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", @@ -794,6 +1706,28 @@ "isarray": "1.0.0" } }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" + }, + "js-yaml": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "requires": { + "argparse": "1.0.9", + "esprima": "4.0.0" + } + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "requires": { + "jsonify": "0.0.0" + } + }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -802,6 +1736,21 @@ "graceful-fs": "4.1.11" } }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" + }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=" + }, + "jsx-ast-utils": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz", + "integrity": "sha1-OGchPo3Xm/Ho8jAMDPwe+xgsDfE=" + }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -818,6 +1767,15 @@ "package-json": "4.0.1" } }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, "linkify-it": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.0.3.tgz", @@ -846,6 +1804,40 @@ "serve-index": "1.9.1" } }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "strip-bom": "3.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + }, + "dependencies": { + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + } + } + }, "lodash": { "version": "4.17.4", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", @@ -900,6 +1892,11 @@ "lodash.keys": "3.1.2" } }, + "lodash.cond": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/lodash.cond/-/lodash.cond-4.5.2.tgz", + "integrity": "sha1-9HGh2khr5g9quVXRcRVSPdHSVdU=" + }, "lodash.defaults": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-3.1.2.tgz", @@ -1029,6 +2026,21 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + } + } + }, "morgan": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.0.tgz", @@ -1061,6 +2073,16 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" }, + "mute-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", + "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=" + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" + }, "negotiator": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", @@ -1132,6 +2154,21 @@ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=" + }, + "object.assign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.0.4.tgz", + "integrity": "sha1-scnMBE7xuf5jYG/BQau7MuFHMMw=", + "requires": { + "define-properties": "1.1.2", + "function-bind": "1.1.1", + "object-keys": "1.0.11" + } + }, "object.omit": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", @@ -1154,6 +2191,19 @@ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=" }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" + }, "opn": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/opn/-/opn-5.1.0.tgz", @@ -1162,11 +2212,42 @@ "is-wsl": "1.1.0" } }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" }, + "p-limit": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz", + "integrity": "sha1-sH/y2aXYi+yAYDWJWiurZqJ5iLw=" + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "requires": { + "p-limit": "1.1.0" + } + }, "package-json": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", @@ -1189,11 +2270,27 @@ "is-glob": "2.0.1" } }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "1.3.1" + } + }, "parseurl": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "requires": { + "pinkie-promise": "2.0.1" + } + }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -1209,6 +2306,11 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" + }, "pause-stream": { "version": "0.0.11", "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", @@ -1222,6 +2324,74 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "2.0.4" + } + }, + "pkg-conf": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-2.0.0.tgz", + "integrity": "sha1-BxyHZQQDvM+5xif1h1G/5HwGcnk=", + "requires": { + "find-up": "2.1.0", + "load-json-file": "2.0.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "requires": { + "locate-path": "2.0.0" + } + } + } + }, + "pkg-config": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pkg-config/-/pkg-config-1.1.1.tgz", + "integrity": "sha1-VX7yLXPaPIg3EHdmxS6tq94pj+Q=", + "requires": { + "debug-log": "1.0.1", + "find-root": "1.1.0", + "xtend": "4.0.1" + } + }, + "pkg-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", + "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", + "requires": { + "find-up": "1.1.2" + } + }, + "pkg-up": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-1.0.0.tgz", + "integrity": "sha1-Pgj7RhUlxEIWJKM7n35tCvWwWiY=", + "requires": { + "find-up": "1.1.2" + } + }, + "pluralize": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", + "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=" + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, "prepend-http": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", @@ -1237,6 +2407,11 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" }, + "progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=" + }, "proxy-middleware": { "version": "0.15.0", "resolved": "https://registry.npmjs.org/proxy-middleware/-/proxy-middleware-0.15.0.tgz", @@ -1333,6 +2508,34 @@ "set-immediate-shim": "1.0.1" } }, + "readline2": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", + "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "mute-stream": "0.0.5" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "1.0.1" + } + } + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "requires": { + "resolve": "1.5.0" + } + }, "regex-cache": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", @@ -1373,16 +2576,90 @@ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "requires": { + "caller-path": "0.1.0", + "resolve-from": "1.0.1" + } + }, + "resolve": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", + "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", + "requires": { + "path-parse": "1.0.5" + } + }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=" + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "requires": { + "exit-hook": "1.1.1", + "onetime": "1.1.0" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "requires": { + "glob": "7.1.2" + } + }, + "run-async": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", + "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", + "requires": { + "once": "1.4.0" + } + }, + "run-parallel": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.6.tgz", + "integrity": "sha1-KQA8miFj4B4tLfyQV18sbB1hoDk=" + }, "rx": { "version": "2.3.24", "resolved": "https://registry.npmjs.org/rx/-/rx-2.3.24.tgz", "integrity": "sha1-FPlQpCF9fjXapxu8vljv9o6ksrc=" }, + "rx-lite": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", + "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=" + }, "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" }, + "semistandard": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/semistandard/-/semistandard-11.0.0.tgz", + "integrity": "sha1-0tn8isOT3iExIZXgBuUMiGE5HEc=", + "requires": { + "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.3", + "eslint-plugin-promise": "3.5.0", + "eslint-plugin-react": "6.10.3", + "eslint-plugin-standard": "3.0.1", + "standard-engine": "7.0.0" + } + }, "semver": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", @@ -1483,11 +2760,26 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" }, + "shelljs": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", + "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", + "requires": { + "glob": "7.1.2", + "interpret": "1.1.0", + "rechoir": "0.6.2" + } + }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=" + }, "spawn-command": { "version": "0.0.2-1", "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", @@ -1506,6 +2798,17 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, + "standard-engine": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-7.0.0.tgz", + "integrity": "sha1-67d7nI/CyBZf+jU72Rug3/Qa9pA=", + "requires": { + "deglob": "2.1.0", + "get-stdin": "5.0.1", + "minimist": "1.2.0", + "pkg-conf": "2.0.0" + } + }, "statuses": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", @@ -1551,13 +2854,10 @@ "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", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" }, "strip-eof": { "version": "1.0.0", @@ -1577,6 +2877,64 @@ "has-flag": "1.0.0" } }, + "table": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", + "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", + "requires": { + "ajv": "4.11.8", + "ajv-keywords": "1.5.1", + "chalk": "1.1.3", + "lodash": "4.17.4", + "slice-ansi": "0.0.4", + "string-width": "2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, "term-size": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", @@ -1585,6 +2943,11 @@ "execa": "0.7.0" } }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -1608,6 +2971,19 @@ "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.0.tgz", "integrity": "sha512-DlX6dR0lOIRDFxI0mjL9IYg6OTncLm/Zt+JiBhE5OlFcAR8yc9S7FFXU9so0oda47frdM/JFsk7UjNt9vscKcg==" }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "requires": { + "prelude-ls": "1.1.2" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, "uc.micro": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.3.tgz", @@ -1618,6 +2994,11 @@ "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-0.0.3.tgz", "integrity": "sha1-7Mo6A+VrmvFzhbqsgSrIO5lKli8=" }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=" + }, "unique-string": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", @@ -1703,6 +3084,14 @@ "prepend-http": "1.0.4" } }, + "user-home": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", + "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", + "requires": { + "os-homedir": "1.0.2" + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -1786,6 +3175,24 @@ } } }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "requires": { + "mkdirp": "0.5.1" + } + }, "write-file-atomic": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", @@ -1801,6 +3208,11 @@ "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=" }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", diff --git a/package.json b/package.json index d4e46f083..4c6d5f82e 100644 --- a/package.json +++ b/package.json @@ -4,15 +4,20 @@ "fs-extra": "^4.0.2", "live-server": "^1.2.0", "markdown-it": "^8.4.0", - "nodemon": "^1.12.1" + "nodemon": "^1.12.1", + "semistandard": "^11.0.0" }, "name": "30-seconds-of-code", "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", + "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 b3305147a..000000000 --- a/scripts/builder.js +++ /dev/null @@ -1,53 +0,0 @@ -var fs = require('fs-extra'); -var path = require('path'); - -var snippetsPath = './snippets'; -var staticPartsPath = './static-parts'; - -var snippets = {}, startPart = '', endPart = '', output = ''; - -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'}`; - output += `${endPart+'\n'}`; - fs.writeFileSync('README.md', output); -} -catch (err){ - console.log('Error during README generation: '+err); - process.exit(1); -} 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/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/snippet-template.md b/snippet-template.md index 02148e458..83e820965 100644 --- a/snippet-template.md +++ b/snippet-template.md @@ -1,9 +1,9 @@ ### Snippet title -Explain briefly how the snippet works +Explain briefly how the snippet works. ```js -var functionName = arguments => +const functionName = arguments => {functionBody} // functionName(sampleInput) -> sampleOutput ``` diff --git a/snippets/URL-parameters.md b/snippets/URL-parameters.md index 4620513dc..f78c774d8 100644 --- a/snippets/URL-parameters.md +++ b/snippets/URL-parameters.md @@ -1,11 +1,12 @@ ### URL parameters -Use `match()` with an appropriate regular expression to get all key-value pairs, `map()` them appropriately. -Combine all key-value pairs into a single object using `Object.assign()` and the spread operator (`...`). +Use `match()` with an appropriate regular expression to get all key-value pairs, `Array.reduce()` to map and combine them into a single object. Pass `location.search` as the argument to apply to the current `url`. ```js const getUrlParameters = url => - Object.assign(...url.match(/([^?=&]+)(=([^&]*))?/g).map(m => {[f,v] = m.split('='); return {[f]:v}})); + url.match(/([^?=&]+)(=([^&]*))/g).reduce( + (a, v) => (a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1), a), {} + ); // getUrlParameters('http://url.com/page?name=Adam&surname=Smith') -> {name: 'Adam', surname: 'Smith'} ``` diff --git a/snippets/UUID-generator.md b/snippets/UUID-generator.md index b7860cf64..01d4e27ac 100644 --- a/snippets/UUID-generator.md +++ b/snippets/UUID-generator.md @@ -4,7 +4,7 @@ Use `crypto` API to generate a UUID, compliant with [RFC4122](https://www.ietf.o ```js const uuid = _ => - ( [1e7]+-1e3+-4e3+-8e3+-1e11 ).replace( /[018]/g, c => + ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16) ); // uuid() -> '7982fcfe-5721-4632-bede-6000885be57d' diff --git a/snippets/anagrams-of-string-(with-duplicates).md b/snippets/anagrams-of-string-(with-duplicates).md index 0d24e51cb..bbc2e3dfb 100644 --- a/snippets/anagrams-of-string-(with-duplicates).md +++ b/snippets/anagrams-of-string-(with-duplicates).md @@ -2,16 +2,14 @@ Use recursion. For each letter in the given string, create all the partial anagrams for the rest of its letters. -Use `map()` to combine the letter with each partial anagram, then `reduce()` to combine all anagrams in one array. +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) => { - anagrams(str.slice(0, i) + str.slice(i + 1)).map( val => acc.push(letter + val) ); - return acc; - }, []); -} + 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'] ``` diff --git a/snippets/array-concatenation.md b/snippets/array-concatenation.md new file mode 100644 index 000000000..992036905 --- /dev/null +++ b/snippets/array-concatenation.md @@ -0,0 +1,8 @@ +### Array concatenation + +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); +// arrayConcat([1], 2, [3], [[4]]) -> [1,2,3,[4]] +``` diff --git a/snippets/array-difference.md b/snippets/array-difference.md new file mode 100644 index 000000000..208cb811e --- /dev/null +++ b/snippets/array-difference.md @@ -0,0 +1,8 @@ +### 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)); }; +// difference([1,2,3], [1,2]) -> [3] +``` diff --git a/snippets/array-intersection.md b/snippets/array-intersection.md new file mode 100644 index 000000000..780ab1d85 --- /dev/null +++ b/snippets/array-intersection.md @@ -0,0 +1,8 @@ +### 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)); }; +// intersection([1,2,3], [4,3,2]) -> [2,3] +``` diff --git a/snippets/array-union.md b/snippets/array-union.md new file mode 100644 index 000000000..6224227d1 --- /dev/null +++ b/snippets/array-union.md @@ -0,0 +1,8 @@ +### 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])); +// union([1,2,3], [4,3,2]) -> [1,2,3,4] +``` diff --git a/snippets/average-of-array-of-numbers.md b/snippets/average-of-array-of-numbers.md index 615e183b8..73ae7bc39 100644 --- a/snippets/average-of-array-of-numbers.md +++ b/snippets/average-of-array-of-numbers.md @@ -1,9 +1,8 @@ ### Average of array of numbers -Use `reduce()` to add each value to an accumulator, initialized with a value of `0`, divide by the `length` of the array. +Use `Array.reduce()` to add each value to an accumulator, initialized with a value of `0`, divide by the `length` of the array. ```js -const average = arr => - arr.reduce( (acc , val) => acc + val, 0) / arr.length; +const average = arr => arr.reduce((acc, val) => acc + val, 0) / arr.length; // average([1,2,3]) -> 2 ``` diff --git a/snippets/bottom-visible.md b/snippets/bottom-visible.md new file mode 100644 index 000000000..b94ac773a --- /dev/null +++ b/snippets/bottom-visible.md @@ -0,0 +1,9 @@ +### Bottom visible + +Use `scrollY`, `scrollHeight` and `clientHeight` to determine if the bottom of the page is visible. + +```js +const bottomVisible = _ => + document.documentElement.clientHeight + window.scrollY >= document.documentElement.scrollHeight || document.documentElement.clientHeight; +// bottomVisible() -> true +``` diff --git a/snippets/capitalize-first-letter.md b/snippets/capitalize-first-letter.md index 99be77927..61f73b6a7 100644 --- a/snippets/capitalize-first-letter.md +++ b/snippets/capitalize-first-letter.md @@ -5,6 +5,6 @@ Omit the `lowerRest` parameter to keep the rest of the string intact, or set it ```js const capitalize = (str, lowerRest = false) => - str.slice(0, 1).toUpperCase() + (lowerRest? str.slice(1).toLowerCase() : str.slice(1)); + str.slice(0, 1).toUpperCase() + (lowerRest ? str.slice(1).toLowerCase() : str.slice(1)); // capitalize('myName', true) -> 'Myname' ``` diff --git a/snippets/chain-asynchronous-functions.md b/snippets/chain-asynchronous-functions.md new file mode 100644 index 000000000..8aec5d186 --- /dev/null +++ b/snippets/chain-asynchronous-functions.md @@ -0,0 +1,14 @@ +### Chain asynchronous functions + +Loop through an array of functions containing asynchronous events, calling `next` when each asynchronous event has completed. + +```js +const chainAsync = fns => { let curr = 0; const next = () => fns[curr++](next); next(); }; +/* +chainAsync([ + next => { console.log('0 seconds'); setTimeout(next, 1000); }, + next => { console.log('1 second'); setTimeout(next, 1000); }, + next => { console.log('2 seconds'); } +]) +*/ +``` diff --git a/snippets/check-for-palindrome.md b/snippets/check-for-palindrome.md index bd0452cf8..a22007688 100644 --- a/snippets/check-for-palindrome.md +++ b/snippets/check-for-palindrome.md @@ -4,7 +4,9 @@ Convert string `toLowerCase()` and use `replace()` to remove non-alphanumeric ch Then, `split('')` into individual characters, `reverse()`, `join('')` and compare to the original, unreversed string, after converting it `tolowerCase()`. ```js -const palindrome = str => - str.toLowerCase().replace(/[\W_]/g,'').split('').reverse().join('') === str.toLowerCase().replace(/[\W_]/g,''); +const palindrome = str => { + const s = str.toLowerCase().replace(/[\W_]/g,''); + return s === s.split('').reverse().join(''); +} // palindrome('taco cat') -> true ``` diff --git a/snippets/chunk-array.md b/snippets/chunk-array.md new file mode 100644 index 000000000..c14bf269d --- /dev/null +++ b/snippets/chunk-array.md @@ -0,0 +1,11 @@ +### 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] +``` diff --git a/snippets/collatz-algorithm.md b/snippets/collatz-algorithm.md new file mode 100644 index 000000000..61614e5e0 --- /dev/null +++ b/snippets/collatz-algorithm.md @@ -0,0 +1,9 @@ +### 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 +``` diff --git a/snippets/compact.md b/snippets/compact.md new file mode 100644 index 000000000..607634b4a --- /dev/null +++ b/snippets/compact.md @@ -0,0 +1,8 @@ +### 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 ] +``` diff --git a/snippets/count-occurrences-of-a-value-in-array.md b/snippets/count-occurrences-of-a-value-in-array.md index 89e3b5b6d..f4a0dc210 100644 --- a/snippets/count-occurrences-of-a-value-in-array.md +++ b/snippets/count-occurrences-of-a-value-in-array.md @@ -1,6 +1,6 @@ ### Count occurrences of a value in array -Use `reduce()` to increment a counter each time you encounter the specific value inside the 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); diff --git a/snippets/curry.md b/snippets/curry.md index a700ac776..bbee4086c 100644 --- a/snippets/curry.md +++ b/snippets/curry.md @@ -3,10 +3,13 @@ Use recursion. If the number of provided arguments (`args`) is sufficient, call the passed function `f`. Otherwise return a curried function `f` that expects the rest of the arguments. +If you want to curry a function that accepts a variable number of arguments (a variadic function, e.g. `Math.min()`), you can optionally pass the number of arguments to the second parameter `arity`. ```js -const curry = f => - (...args) => - args.length >= f.length ? f(...args) : (...otherArgs) => curry(f)(...args, ...otherArgs); +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 545c4c8d4..c350d848c 100644 --- a/snippets/deep-flatten-array.md +++ b/snippets/deep-flatten-array.md @@ -1,10 +1,10 @@ ### Deep flatten array Use recursion. -Use `reduce()` to get all elements that are not arrays, flatten each element that is an array. +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) ? flatten(v) : v ), []); + arr.reduce((a, v) => a.concat(Array.isArray(v) ? deepFlatten(v) : v), []); // deepFlatten([1,[2],[[3],4],5]) -> [1,2,3,4,5] ``` diff --git a/snippets/difference-between-arrays.md b/snippets/difference-between-arrays.md deleted file mode 100644 index 1fb172dab..000000000 --- a/snippets/difference-between-arrays.md +++ /dev/null @@ -1,8 +0,0 @@ -### Difference between arrays - -Use `filter()` to remove values that are part of `values`, determined using `includes()`. - -```js -const difference = (arr, values) => arr.filter(v => !values.includes(v)); -// difference([1,2,3], [1,2]) -> [3] -``` diff --git a/snippets/drop-elements-in-array.md b/snippets/drop-elements-in-array.md new file mode 100644 index 000000000..236c5ab56 --- /dev/null +++ b/snippets/drop-elements-in-array.md @@ -0,0 +1,12 @@ +### 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] +``` diff --git a/snippets/element-is-visible-in-viewport.md b/snippets/element-is-visible-in-viewport.md new file mode 100644 index 000000000..514aea5e6 --- /dev/null +++ b/snippets/element-is-visible-in-viewport.md @@ -0,0 +1,19 @@ +### 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) +``` diff --git a/snippets/even-or-odd-number.md b/snippets/even-or-odd-number.md index 605108429..24eb312e6 100644 --- a/snippets/even-or-odd-number.md +++ b/snippets/even-or-odd-number.md @@ -1,9 +1,9 @@ ### Even or odd number -Use `Math.abs()` to extend logic to negative numbers, check using the modulo (`%`) operator. -Return `true` if the number is even, `false` if the number is odd. +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 => Math.abs(num) % 2 === 0; +const isEven = num => num % 2 === 0; // isEven(3) -> false ``` diff --git a/snippets/fibonacci-array-generator.md b/snippets/fibonacci-array-generator.md index 0255e8875..7f0d4c7d2 100644 --- a/snippets/fibonacci-array-generator.md +++ b/snippets/fibonacci-array-generator.md @@ -4,7 +4,7 @@ Create an empty array of the specific length, initializing the first two values 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),[]); +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] ``` diff --git a/snippets/fill-array.md b/snippets/fill-array.md new file mode 100644 index 000000000..a5da15483 --- /dev/null +++ b/snippets/fill-array.md @@ -0,0 +1,10 @@ +### 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] +``` diff --git a/snippets/filter-out-non-uniqe-values-in-an-array.md b/snippets/filter-out-non-uniqe-values-in-an-array.md deleted file mode 100644 index 622026234..000000000 --- a/snippets/filter-out-non-uniqe-values-in-an-array.md +++ /dev/null @@ -1,8 +0,0 @@ -### Filter out non-unique values in an array - -Use `Array.filter()` for an array containing only the unique values. - -```js -const unique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i)); -// unique([1,2,2,3,4,4,5]) -> [1,3,5] -``` diff --git a/snippets/filter-out-non-unique-values-in-an-array.md b/snippets/filter-out-non-unique-values-in-an-array.md new file mode 100644 index 000000000..86562feb4 --- /dev/null +++ b/snippets/filter-out-non-unique-values-in-an-array.md @@ -0,0 +1,8 @@ +### 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] +``` diff --git a/snippets/flatten-array-up-to-depth.md b/snippets/flatten-array-up-to-depth.md new file mode 100644 index 000000000..b6e3805b6 --- /dev/null +++ b/snippets/flatten-array-up-to-depth.md @@ -0,0 +1,13 @@ +### 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] +``` diff --git a/snippets/flatten-array.md b/snippets/flatten-array.md index a677fa4ea..d23f24611 100644 --- a/snippets/flatten-array.md +++ b/snippets/flatten-array.md @@ -1,8 +1,8 @@ ### Flatten array -Use `reduce()` to get all elements inside the array and `concat()` to flatten them. +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), []); +const flatten = arr => arr.reduce((a, v) => a.concat(v), []); // flatten([1,[2],3,4]) -> [1,2,3,4] ``` 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/get-max-value-from-array.md b/snippets/get-max-value-from-array.md index 55d90f1a7..2e724a3e2 100644 --- a/snippets/get-max-value-from-array.md +++ b/snippets/get-max-value-from-array.md @@ -1,6 +1,6 @@ ### Get max value from array -Use `Math.max()` combined with the spread operator (`...`) to get the minimum value in the array. +Use `Math.max()` combined with the spread operator (`...`) to get the maximum value in the array. ```js const arrayMax = arr => Math.max(...arr); diff --git a/snippets/get-native-type-of-value.md b/snippets/get-native-type-of-value.md new file mode 100644 index 000000000..9e043a83e --- /dev/null +++ b/snippets/get-native-type-of-value.md @@ -0,0 +1,9 @@ +### 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" +``` diff --git a/snippets/get-scroll-position.md b/snippets/get-scroll-position.md index 7e367168f..4f134a9fb 100644 --- a/snippets/get-scroll-position.md +++ b/snippets/get-scroll-position.md @@ -5,7 +5,7 @@ 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} ); + ({x: (el.pageXOffset !== undefined) ? el.pageXOffset : el.scrollLeft, + y: (el.pageYOffset !== undefined) ? el.pageYOffset : el.scrollTop}); // getScrollPos() -> {x: 0, y: 200} ``` diff --git a/snippets/greatest-common-divisor-(GCD).md b/snippets/greatest-common-divisor-(GCD).md index 38b5603ca..d1025a029 100644 --- a/snippets/greatest-common-divisor-(GCD).md +++ b/snippets/greatest-common-divisor-(GCD).md @@ -5,6 +5,6 @@ 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); +const gcd = (x, y) => !y ? x : gcd(y, x % y); // gcd (8, 36) -> 4 ``` diff --git a/snippets/group-by.md b/snippets/group-by.md new file mode 100644 index 000000000..ec8074ea2 --- /dev/null +++ b/snippets/group-by.md @@ -0,0 +1,12 @@ +### 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']} +``` diff --git a/snippets/hamming-distance.md b/snippets/hamming-distance.md new file mode 100644 index 000000000..e524408a8 --- /dev/null +++ b/snippets/hamming-distance.md @@ -0,0 +1,10 @@ +### 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 +``` diff --git a/snippets/head-of-list.md b/snippets/head-of-list.md index 31dc5fbaf..c2e0d5a3a 100644 --- a/snippets/head-of-list.md +++ b/snippets/head-of-list.md @@ -1,6 +1,6 @@ ### Head of list -Return `arr[0]`. +Use `arr[0]` to return the first element of the passed array. ```js const head = arr => arr[0]; diff --git a/snippets/initial-of-list.md b/snippets/initial-of-list.md index 77ea3e8f7..1f967f804 100644 --- a/snippets/initial-of-list.md +++ b/snippets/initial-of-list.md @@ -1,8 +1,8 @@ ### Initial of list -Return `arr.slice(0,-1)`. +Use `arr.slice(0,-1)`to return all but the last element of the array. ```js -const initial = arr => arr.slice(0,-1); +const initial = arr => arr.slice(0, -1); // initial([1,2,3]) -> [1,2] ``` diff --git a/snippets/initialize-array-with-range.md b/snippets/initialize-array-with-range.md index c974f2786..def23fb9c 100644 --- a/snippets/initialize-array-with-range.md +++ b/snippets/initialize-array-with-range.md @@ -1,10 +1,10 @@ ### Initialize array with range -Use `Array(end-start)` to create an array of the desired length, `map()` to fill with the desired values in a 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 ); + Array.apply(null, Array(end - start)).map((v, i) => i + start); // initializeArrayRange(5) -> [0,1,2,3,4] ``` diff --git a/snippets/is-array.md b/snippets/is-array.md new file mode 100644 index 000000000..939cb086d --- /dev/null +++ b/snippets/is-array.md @@ -0,0 +1,9 @@ +### 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 +``` diff --git a/snippets/is-boolean.md b/snippets/is-boolean.md new file mode 100644 index 000000000..8625add35 --- /dev/null +++ b/snippets/is-boolean.md @@ -0,0 +1,9 @@ +### 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 +``` diff --git a/snippets/is-function.md b/snippets/is-function.md new file mode 100644 index 000000000..d4247a512 --- /dev/null +++ b/snippets/is-function.md @@ -0,0 +1,9 @@ +### 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 +``` diff --git a/snippets/is-number.md b/snippets/is-number.md new file mode 100644 index 000000000..a647b39ed --- /dev/null +++ b/snippets/is-number.md @@ -0,0 +1,9 @@ +### 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 +``` diff --git a/snippets/is-string.md b/snippets/is-string.md new file mode 100644 index 000000000..6721c59c6 --- /dev/null +++ b/snippets/is-string.md @@ -0,0 +1,9 @@ +### 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 +``` diff --git a/snippets/is-symbol.md b/snippets/is-symbol.md new file mode 100644 index 000000000..53d4ce67c --- /dev/null +++ b/snippets/is-symbol.md @@ -0,0 +1,9 @@ +### 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 +``` diff --git a/snippets/last-of-list.md b/snippets/last-of-list.md index 16955f201..d27b0b35e 100644 --- a/snippets/last-of-list.md +++ b/snippets/last-of-list.md @@ -1,6 +1,6 @@ ### Last of list -Return `arr.slice(-1)[0]`. +Use `arr.slice(-1)[0]` to get the last element of the given array. ```js const last = arr => arr.slice(-1)[0]; diff --git a/snippets/measure-time-taken-by-function.md b/snippets/measure-time-taken-by-function.md index 8586f59d1..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. -First argument is the function name, subsequent arguments are passed to the 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 = (func,...args) => { - var t0 = performance.now(), r = func(...args); - console.log(performance.now() - t0); +const timeTaken = callback => { + 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/median-of-array-of-numbers.md b/snippets/median-of-array-of-numbers.md new file mode 100644 index 000000000..8113d51c6 --- /dev/null +++ b/snippets/median-of-array-of-numbers.md @@ -0,0 +1,13 @@ +### 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 +``` 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/object-from-key-value-pairs.md b/snippets/object-from-key-value-pairs.md index df01da0ba..cbb545c06 100644 --- a/snippets/object-from-key-value-pairs.md +++ b/snippets/object-from-key-value-pairs.md @@ -3,6 +3,6 @@ Use `Array.reduce()` to create and combine key-value pairs. ```js -const objectFromPairs = arr => arr.reduce((a,v) => (a[v[0]] = v[1], a), {}); +const objectFromPairs = arr => arr.reduce((a, v) => (a[v[0]] = v[1], a), {}); // objectFromPairs([['a',1],['b',2]]) -> {a: 1, b: 2} ``` diff --git a/snippets/object-to-key-value-pairs.md b/snippets/object-to-key-value-pairs.md new file mode 100644 index 000000000..fb639e432 --- /dev/null +++ b/snippets/object-to-key-value-pairs.md @@ -0,0 +1,8 @@ +### 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]]) +``` diff --git a/snippets/ordinal-suffix-of-number.md b/snippets/ordinal-suffix-of-number.md new file mode 100644 index 000000000..d3166928b --- /dev/null +++ b/snippets/ordinal-suffix-of-number.md @@ -0,0 +1,15 @@ +### 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" +``` diff --git a/snippets/percentile.md b/snippets/percentile.md new file mode 100644 index 000000000..eb72b711c --- /dev/null +++ b/snippets/percentile.md @@ -0,0 +1,10 @@ +### 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 + ``` diff --git a/snippets/pick.md b/snippets/pick.md new file mode 100644 index 000000000..3689e4a28 --- /dev/null +++ b/snippets/pick.md @@ -0,0 +1,10 @@ +### 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 +``` diff --git a/snippets/powerset.md b/snippets/powerset.md index 2908c78b2..73b71b645 100644 --- a/snippets/powerset.md +++ b/snippets/powerset.md @@ -1,9 +1,9 @@ ### Powerset -Use `reduce()` combined with `map()` to iterate over elements and combine into an array containing all combinations. +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) )), [[]]); + arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]); // powerset([1,2]) -> [[], [1], [2], [2,1]] ``` diff --git a/snippets/promisify.md b/snippets/promisify.md new file mode 100644 index 000000000..bdedec054 --- /dev/null +++ b/snippets/promisify.md @@ -0,0 +1,17 @@ +### Promisify + +Use currying to return a function returning a `Promise` that calls the original function. +Use the `...rest` operator to pass in all the parameters. + +*In Node 8+, you can use [`util.promisify`](https://nodejs.org/api/util.html#util_util_promisify_original)* + +```js +const promisify = func => + (...args) => + new Promise((resolve, reject) => + func(...args, (err, result) => + err ? reject(err) : resolve(result)) + ); +// const delay = promisify((d, cb) => setTimeout(cb, d)) +// delay(2000).then(() => console.log('Hi!')) -> Promise resolves after 2s +``` diff --git a/snippets/random-integer-in-range.md b/snippets/random-integer-in-range.md new file mode 100644 index 000000000..78bb85ab0 --- /dev/null +++ b/snippets/random-integer-in-range.md @@ -0,0 +1,8 @@ +### 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 +``` diff --git a/snippets/randomize-order-of-array.md b/snippets/randomize-order-of-array.md deleted file mode 100644 index fe9093843..000000000 --- a/snippets/randomize-order-of-array.md +++ /dev/null @@ -1,8 +0,0 @@ -### Randomize order of array - -Use `sort()` to reorder elements, utilizing `Math.random()` to randomize the sorting. - -```js -const randomizeOrder = arr => arr.sort( (a,b) => Math.random() >= 0.5 ? -1 : 1); -// randomizeOrder([1,2,3]) -> [1,3,2] -``` 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/run-promises-in-series.md b/snippets/run-promises-in-series.md new file mode 100644 index 000000000..2193e8df4 --- /dev/null +++ b/snippets/run-promises-in-series.md @@ -0,0 +1,9 @@ +### 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. + +```js +const series = ps => ps.reduce((p, next) => p.then(next), Promise.resolve()); +// const delay = (d) => new Promise(r => setTimeout(r, d)) +// series([() => delay(1000), () => delay(2000)]) -> executes each promise sequentially, taking a total of 3 seconds to complete +``` diff --git a/snippets/scroll-to-top.md b/snippets/scroll-to-top.md index 7a813429a..6c82190a4 100644 --- a/snippets/scroll-to-top.md +++ b/snippets/scroll-to-top.md @@ -6,10 +6,10 @@ Scroll by a fraction of the distance from top. Use `window.requestAnimationFrame ```js const scrollToTop = _ => { const c = document.documentElement.scrollTop || document.body.scrollTop; - if(c > 0) { + if (c > 0) { window.requestAnimationFrame(scrollToTop); - window.scrollTo(0, c - c/8); + window.scrollTo(0, c - c / 8); } -} +}; // scrollToTop() ``` 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/shuffle-array-values.md b/snippets/shuffle-array-values.md deleted file mode 100644 index a140bd647..000000000 --- a/snippets/shuffle-array-values.md +++ /dev/null @@ -1,12 +0,0 @@ -### Shuffle array values - -Create an array of random values by using `Array.map()` and `Math.random()`. -Use `Array.sort()` to sort the elements of the original array based on the random values. - -```js -const shuffle = arr => { - let r = arr.map(Math.random); - return arr.sort((a,b) => r[a] - r[b]); -} -// shuffle([1,2,3]) -> [2, 1, 3] -``` diff --git a/snippets/shuffle-array.md b/snippets/shuffle-array.md new file mode 100644 index 000000000..6266f9ecf --- /dev/null +++ b/snippets/shuffle-array.md @@ -0,0 +1,8 @@ +### 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] +``` diff --git a/snippets/sleep.md b/snippets/sleep.md index c64ed3917..e2a58d0bd 100644 --- a/snippets/sleep.md +++ b/snippets/sleep.md @@ -4,9 +4,11 @@ Delay executing part of an `async` function, by putting it to sleep, returning a ```js const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); -// async function sleepyWork() { -// console.log('I\'m going to sleep for 1 second.'); -// await sleep(1000); -// console.log('I woke up after 1 second.'); -// } +/* +async function sleepyWork() { + console.log('I\'m going to sleep for 1 second.'); + await sleep(1000); + console.log('I woke up after 1 second.'); +} +*/ ``` diff --git a/snippets/sort-characters-in-string-(alphabetical).md b/snippets/sort-characters-in-string-(alphabetical).md index c283ca17c..9cf37ad77 100644 --- a/snippets/sort-characters-in-string-(alphabetical).md +++ b/snippets/sort-characters-in-string-(alphabetical).md @@ -1,9 +1,9 @@ ### Sort characters in string (alphabetical) -Split the string using `split('')`, `sort()` utilizing `localeCompare()`, recombine using `join('')`. +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(''); + str.split('').sort((a, b) => a.localeCompare(b)).join(''); // sortCharactersInString('cabbage') -> 'aabbceg' ``` 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 new file mode 100644 index 000000000..5819579ad --- /dev/null +++ b/snippets/standard-deviation.md @@ -0,0 +1,17 @@ +### 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 +determine the standard deviation. +You can omit the second argument to get the sample standard deviation or set it to `true` to get the population standard deviation. + +```js +const standardDeviation = (arr, usePopulation = false) => { + const mean = arr.reduce((acc, val) => acc + val, 0) / arr.length; + return Math.sqrt( + arr.reduce((acc, val) => acc.concat(Math.pow(val - mean, 2)), []) + .reduce((acc, val) => acc + val, 0) / (arr.length - (usePopulation ? 0 : 1)) + ); +}; +// 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/sum-of-array-of-numbers.md b/snippets/sum-of-array-of-numbers.md index fcf01949c..9729eb474 100644 --- a/snippets/sum-of-array-of-numbers.md +++ b/snippets/sum-of-array-of-numbers.md @@ -1,8 +1,8 @@ ### Sum of array of numbers -Use `reduce()` to add each value to an accumulator, initialized with a value of `0`. +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); +const sum = arr => arr.reduce((acc, val) => acc + val, 0); // sum([1,2,3,4]) -> 10 ``` diff --git a/snippets/tail-of-list.md b/snippets/tail-of-list.md index 9a9513262..d0c9681c3 100644 --- a/snippets/tail-of-list.md +++ b/snippets/tail-of-list.md @@ -1,8 +1,9 @@ ### Tail of list -Return `arr.slice(1)`. +Return `arr.slice(1)` if the array's `length` is more than `1`, otherwise return the whole array. ```js -const tail = arr => arr.slice(1); +const tail = arr => arr.length > 1 ? arr.slice(1) : arr; // tail([1,2,3]) -> [2,3] +// tail([1]) -> [1] ``` diff --git a/snippets/take.md b/snippets/take.md new file mode 100644 index 000000000..44d6ff0bc --- /dev/null +++ b/snippets/take.md @@ -0,0 +1,9 @@ +### 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) -> [] +``` diff --git a/snippets/truncate-a-string.md b/snippets/truncate-a-string.md new file mode 100644 index 000000000..a33ac6367 --- /dev/null +++ b/snippets/truncate-a-string.md @@ -0,0 +1,10 @@ +### Truncate a String + +Determine if the string's `length` is greater than `num`. +Return the string truncated to the desired length, with `...` appended to the end or the original string. + +```js +const truncate = (str, num) => + str.length > num ? str.slice(0, num > 3 ? num - 3 : num) + '...' : str; +// truncate('boomerang', 7) -> 'boom...' +``` diff --git a/snippets/validate-email.md b/snippets/validate-email.md new file mode 100644 index 000000000..d83a41904 --- /dev/null +++ b/snippets/validate-email.md @@ -0,0 +1,10 @@ +### Validate email + +Use a regular experssion to check if the email is valid. +Returns `true` if email is valid, `false` if not. + +```js +const validateEmail = str => + /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(str); +// validateEmail(mymail@gmail.com) -> true +``` diff --git a/snippets/validate-number.md b/snippets/validate-number.md index a26eca627..60a037e3e 100644 --- a/snippets/validate-number.md +++ b/snippets/validate-number.md @@ -2,8 +2,9 @@ Use `!isNaN` in combination with `parseFloat()` to check if the argument is a number. Use `isFinite()` to check if the number is finite. +Use `Number()` to check if the coercion holds. ```js -const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n); +const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n; // validateNumber('10') -> true ``` diff --git a/snippets/value-or-default.md b/snippets/value-or-default.md new file mode 100644 index 000000000..0af9529e8 --- /dev/null +++ b/snippets/value-or-default.md @@ -0,0 +1,8 @@ +### Value or default + +Returns value, or default value if passed value is `falsy`. + +```js +const valueOrDefault = (value, d) => value || d; +// valueOrDefault(NaN, 30) -> 30 +``` diff --git a/static-parts/README-start.md b/static-parts/README-start.md index 424b14964..6a6504483 100644 --- a/static-parts/README-start.md +++ b/static-parts/README-start.md @@ -1,9 +1,10 @@ ![Logo](/logo.png) -# 30 seconds of code +# 30 seconds of code [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/30-seconds-of-code/Lobby) > Curated collection of useful Javascript snippets that you can understand in 30 seconds or less. - Use Ctrl + F or command + F to search for a snippet. -- Contributions welcome, please read [contribution guide](CONTRIBUTING.md). +- Contributions welcome, please read the [contribution guide](CONTRIBUTING.md). +- Snippets are written in ES6, use the [Babel transpiler](https://babeljs.io/) to ensure backwards-compatibility. -## Contents +## Table of Contents diff --git a/tag_database b/tag_database new file mode 100644 index 000000000..b2535a484 --- /dev/null +++ b/tag_database @@ -0,0 +1,87 @@ +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 +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 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"