diff --git a/.gitignore b/.gitignore index c2658d7d1..bc23f6a88 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ node_modules/ + +currentSnippet\.js diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7e90497d5..09e28829b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,13 +1,74 @@ ## 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). +- Fix typos in existing snippets or run `npm run lint "snippet-name.md"` on unlinted snippets (yes, this is something we actually want help with). + +### 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 ommited 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 by convention are: + - `arr` for arrays (usually as the snippet function's argument). + - `str` for strings. + - `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/README.md b/README.md index 7317a259d..efc81a9de 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,9 @@ ## Contents * [Anagrams of string (with duplicates)](#anagrams-of-string-with-duplicates) +* [Array difference](#array-difference) +* [Array intersection](#array-intersection) +* [Array union](#array-union) * [Average of array of numbers](#average-of-array-of-numbers) * [Bottom visible](#bottom-visible) * [Capitalize first letter of every word](#capitalize-first-letter-of-every-word) @@ -17,11 +20,11 @@ * [Chain asynchronous functions](#chain-asynchronous-functions) * [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) @@ -35,6 +38,7 @@ * [Get native type of value](#get-native-type-of-value) * [Get scroll position](#get-scroll-position) * [Greatest common divisor (GCD)](#greatest-common-divisor-gcd) +* [Group by](#group-by) * [Hamming distance](#hamming-distance) * [Head of list](#head-of-list) * [Initial of list](#initial-of-list) @@ -44,19 +48,24 @@ * [Measure time taken by function](#measure-time-taken-by-function) * [Median of array of numbers](#median-of-array-of-numbers) * [Object from key value pairs](#object-from-key-value-pairs) +* [Object to key value pairs](#object-to-key-value-pairs) +* [Ordinal suffix of number](#ordinal-suffix-of-number) * [Percentile](#percentile) +* [Pick](#pick) * [Pipe](#pipe) * [Powerset](#powerset) * [Promisify](#promisify) * [Random integer in range](#random-integer-in-range) * [Random number in range](#random-number-in-range) -* [Redirect to url](#redirect-to-url) +* [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) * [Run promises in series](#run-promises-in-series) * [Scroll to top](#scroll-to-top) * [Shuffle array](#shuffle-array) * [Similarity between arrays](#similarity-between-arrays) +* [Sleep](#sleep) * [Sort characters in string (alphabetical)](#sort-characters-in-string-alphabetical) * [Sum of array of numbers](#sum-of-array-of-numbers) * [Swap values of two variables](#swap-values-of-two-variables) @@ -77,20 +86,46 @@ 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 )), []); -} + 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'] ``` +### 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] +``` + +### 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] +``` + +### 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] +``` + ### Average of array of numbers Use `Array.reduce()` to add each value to an accumulator, initialized with a value of `0`, divide by the `length` of the array. ```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 ``` @@ -99,7 +134,7 @@ const average = arr => Use `scrollY`, `scrollHeight` and `clientHeight` to determine if the bottom of the page is visible. ```js -const bottomVisible = _ => +const bottomVisible = _ => document.documentElement.clientHeight + window.scrollY >= document.documentElement.scrollHeight || document.documentElement.clientHeight; // bottomVisible() -> true ``` @@ -120,7 +155,7 @@ 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' ``` @@ -129,7 +164,7 @@ const capitalize = (str, lowerRest = false) => 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(); } +const chainAsync = fns => { let curr = 0; const next = () => fns[curr++](next); next(); }; /* chainAsync([ next => { console.log('0 seconds'); setTimeout(next, 1000); }, @@ -145,23 +180,34 @@ 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 ``` ### Chunk array -Use `Array.apply()` to create a new array, that fits the number of chunks that will be produced. -Use `Array.map()` to map each element of the new array to a chunk the length of `size`. +Use `Array.from()` to create a new array, that fits the number of chunks that will be produced. +Use `Array.slice()` to map each element of the new array to a chunk the length of `size`. If the original array can't be split evenly, the final chunk will contain the remaining elements. ```js const chunk = (arr, size) => - Array.apply(null, {length: Math.ceil(arr.length/size)}).map((v, i) => arr.slice(i*size, i*size+size)); + Array.from({length: Math.ceil(arr.length / size)}, (v, i) => arr.slice(i * size, i * size + size)); // chunk([1,2,3,4,5], 2) -> [[1,2],[3,4],5] ``` +### Compact + +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 ] +``` + ### Count occurrences of a value in array Use `Array.reduce()` to increment a counter each time you encounter the specific value inside the array. @@ -206,19 +252,10 @@ Use `Array.reduce()` to get all elements that are not arrays, flatten each eleme ```js const deepFlatten = arr => - arr.reduce( (a, v) => a.concat( Array.isArray(v) ? deepFlatten(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 - -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] -``` - ### Distance between two points Use `Math.hypot()` to calculate the Euclidean distance between two points. @@ -248,11 +285,11 @@ const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); ### 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 ``` @@ -273,8 +310,8 @@ 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] ``` @@ -292,7 +329,7 @@ const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexO 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] ``` @@ -320,7 +357,7 @@ Returns lower-cased constructor name of value, "undefined" or "null" if value is ```js const getType = v => - v === undefined ? "undefined" : v === null ? "null" : v.constructor.name.toLowerCase(); + v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name.toLowerCase(); // getType(new Set([1,2,3])) -> "set" ``` @@ -331,8 +368,8 @@ 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} ``` @@ -343,10 +380,25 @@ 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 ``` +### 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) => + (typeof func === 'function' ? arr.map(func) : arr.map(val => val[func])) + .reduce((acc, val, i) => { + acc[val] = acc[val] === undefined ? [arr[i]] : 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']} +``` + ### Hamming distance Use XOR operator (`^`) to find the bit difference between the two numbers, convert to binary string using `toString(2)`. @@ -354,13 +406,13 @@ 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; + ((num1 ^ num2).toString(2).match(/1/g) || '').length; // hammingDistance(2,3) -> 1 ``` ### Head of list -Return `arr[0]`. +Use `arr[0]` to return the first element of the passed array. ```js const head = arr => arr[0]; @@ -369,10 +421,10 @@ const head = arr => arr[0]; ### 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] ``` @@ -383,7 +435,7 @@ 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] ``` @@ -399,7 +451,7 @@ const initializeArray = (n, value = 0) => Array(n).fill(value); ### 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]; @@ -416,7 +468,7 @@ const timeTaken = callback => { const t0 = performance.now(), r = callback(); console.log(performance.now() - t0); return r; -} +}; // timeTaken(() => Math.pow(2, 10)) -> 1024 (0.010000000009313226 logged in console) ``` @@ -427,9 +479,9 @@ Return the number at the midpoint if `length` is odd, otherwise the average of t ```js const median = arr => { - const mid = Math.floor(arr.length / 2), nums = arr.sort((a,b) => a - b); + 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 ``` @@ -439,10 +491,35 @@ const median = arr => { 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} ``` +### 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]]) +``` + +### 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" +``` + ### Percentile Use `Array.reduce()` to calculate how many numbers are below the value and how many are the same value and @@ -454,6 +531,17 @@ const percentile = (arr, val) => // percentile([1,2,3,4,5,6,7,8,9,10], 6) -> 55 ``` +### 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 +``` + ### Pipe Use `Array.reduce()` to pass value through functions. @@ -469,7 +557,7 @@ Use `Array.reduce()` combined with `Array.map()` to iterate over elements and co ```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]] ``` @@ -509,6 +597,15 @@ const randomInRange = (min, max) => Math.random() * (max - min) + min; // randomInRange(2,10) -> 6.0211363285087005 ``` +### Randomize order of array + +Use `Array.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] +``` + ### Redirect to URL Use `window.location.href` or `window.location.replace()` to redirect to `url`. @@ -557,11 +654,11 @@ 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() ``` @@ -570,8 +667,11 @@ const scrollToTop = _ => { 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] +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 @@ -583,13 +683,28 @@ const similarity = (arr, values) => arr.filter(v => values.includes(v)); // similarity([1,2,3], [1,2,4]) -> [1,2] ``` +### 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.'); +} +*/ +``` + ### 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(''); + str.split('').sort((a, b) => a.localeCompare(b)).join(''); // sortCharactersInString('cabbage') -> 'aabbceg' ``` @@ -598,7 +713,7 @@ const sortCharactersInString = str => 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 ``` @@ -628,7 +743,7 @@ Return the string truncated to the desired length, with `...` appended to the en ```js const truncate = (str, num) => - str.length > num ? str.slice(0, num > 3 ? num-3 : num) + '...' : str; + str.length > num ? str.slice(0, num > 3 ? num - 3 : num) + '...' : str; // truncate('boomerang', 7) -> 'boom...' ``` @@ -648,8 +763,8 @@ Pass `location.search` as the argument to apply to the current `url`. ```js const getUrlParameters = url => - url.match(/([^?=&]+)(=([^&]*))?/g).reduce( - (a,v) => (a[v.slice(0,v.indexOf('='))] = v.slice(v.indexOf('=')+1), a), {} + 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'} ``` @@ -660,7 +775,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' @@ -670,9 +785,10 @@ const uuid = _ => 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/package-lock.json b/package-lock.json index 50c9abf8a..be8bcab8d 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,6 +60,11 @@ "string-width": "2.1.1" } }, + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=" + }, "ansi-regex": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", @@ -79,16 +118,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 +304,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", @@ -227,11 +366,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,6 +427,16 @@ "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", @@ -304,6 +476,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 +518,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 +539,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 +607,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 +648,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 +757,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 +1067,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 +1096,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 +1109,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 +1156,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 +1194,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 +1219,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 +1290,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,6 +1338,14 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" }, + "has": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "requires": { + "function-bind": "1.1.1" + } + }, "has-ansi": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", @@ -637,6 +1386,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 +1406,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 +1425,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 +1531,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 +1586,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 +1615,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 +1646,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 +1679,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 +1707,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 +1737,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 +1768,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 +1805,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 +1893,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 +2027,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 +2074,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 +2155,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 +2192,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 +2213,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 +2271,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 +2307,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 +2325,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 +2408,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 +2509,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 +2577,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 +2761,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 +2799,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", @@ -1559,6 +2863,11 @@ "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", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", @@ -1577,6 +2886,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 +2952,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 +2980,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 +3003,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 +3093,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 +3184,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 +3217,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..a616c02d0 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "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.", @@ -13,6 +14,7 @@ "devDependencies": {}, "scripts": { "build-list": "node ./scripts/builder.js", + "lint": "node ./scripts/lintSnippet.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/builder.js b/scripts/builder.js index b3305147a..b9a5d5bc8 100644 --- a/scripts/builder.js +++ b/scripts/builder.js @@ -6,6 +6,8 @@ var staticPartsPath = './static-parts'; var snippets = {}, startPart = '', endPart = '', output = ''; +console.time('Builder'); + try { var snippetFilenames = fs.readdirSync(snippetsPath); snippetFilenames.sort((a, b) => { @@ -51,3 +53,5 @@ catch (err){ console.log('Error during README generation: '+err); process.exit(1); } + +console.timeEnd('Builder'); diff --git a/scripts/lintSnippet.js b/scripts/lintSnippet.js new file mode 100644 index 000000000..a53686ee5 --- /dev/null +++ b/scripts/lintSnippet.js @@ -0,0 +1,31 @@ +var fs = require('fs-extra'); +var cp = require('child_process'); +var path = require('path'); + +var snippetsPath = './snippets'; +var snippetFilename = ''; + +console.time('Linter'); + +if(process.argv.length < 3){ + console.log('Please specify the filename of a snippet to be linted.'); + console.log('Example usage: npm run lint "snippet-file.md"'); + process.exit(0); +} +else { + snippetFilename = process.argv[2]; + let snippetData = fs.readFileSync(path.join(snippetsPath,snippetFilename),'utf8'); + try { + let originalCode = snippetData.slice(snippetData.indexOf('```js')+5,snippetData.lastIndexOf('```')); + fs.writeFileSync('currentSnippet.js',`${originalCode}`); + cp.exec('semistandard "currentSnippet.js" --fix',{},(error, stdOut, stdErr) => { + let lintedCode = fs.readFileSync('currentSnippet.js','utf8'); + fs.writeFile(path.join(snippetsPath,snippetFilename), `${snippetData.slice(0, snippetData.indexOf('```js')+5)+lintedCode+'```\n'}`); + console.timeEnd('Linter'); + }); + } + catch (err){ + console.log('Error during snippet loading: '+err); + process.exit(1); + } +} diff --git a/snippet-template.md b/snippet-template.md index e258fe079..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 -const functionName = arguments => +const functionName = arguments => {functionBody} // functionName(sampleInput) -> sampleOutput ``` diff --git a/snippets/URL-parameters.md b/snippets/URL-parameters.md index c5a316b76..f78c774d8 100644 --- a/snippets/URL-parameters.md +++ b/snippets/URL-parameters.md @@ -5,8 +5,8 @@ Pass `location.search` as the argument to apply to the current `url`. ```js const getUrlParameters = url => - url.match(/([^?=&]+)(=([^&]*))?/g).reduce( - (a,v) => (a[v.slice(0,v.indexOf('='))] = v.slice(v.indexOf('=')+1), a), {} + 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 7e1d613b6..bbc2e3dfb 100644 --- a/snippets/anagrams-of-string-(with-duplicates).md +++ b/snippets/anagrams-of-string-(with-duplicates).md @@ -7,9 +7,9 @@ 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 )), []); -} + 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-difference.md b/snippets/array-difference.md new file mode 100644 index 000000000..46469b1d6 --- /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..87c42378b --- /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..b417dcce7 --- /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 8d9aaf1cd..73ae7bc39 100644 --- a/snippets/average-of-array-of-numbers.md +++ b/snippets/average-of-array-of-numbers.md @@ -3,7 +3,6 @@ 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 index 9045c6bff..b94ac773a 100644 --- a/snippets/bottom-visible.md +++ b/snippets/bottom-visible.md @@ -3,7 +3,7 @@ Use `scrollY`, `scrollHeight` and `clientHeight` to determine if the bottom of the page is visible. ```js -const bottomVisible = _ => +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 index 6c6118b3c..8aec5d186 100644 --- a/snippets/chain-asynchronous-functions.md +++ b/snippets/chain-asynchronous-functions.md @@ -3,7 +3,7 @@ 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(); } +const chainAsync = fns => { let curr = 0; const next = () => fns[curr++](next); next(); }; /* chainAsync([ next => { console.log('0 seconds'); setTimeout(next, 1000); }, 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 index 8f92499a2..c14bf269d 100644 --- a/snippets/chunk-array.md +++ b/snippets/chunk-array.md @@ -1,11 +1,11 @@ ### Chunk array -Use `Array.apply()` to create a new array, that fits the number of chunks that will be produced. -Use `Array.map()` to map each element of the new array to a chunk the length of `size`. +Use `Array.from()` to create a new array, that fits the number of chunks that will be produced. +Use `Array.slice()` to map each element of the new array to a chunk the length of `size`. If the original array can't be split evenly, the final chunk will contain the remaining elements. ```js const chunk = (arr, size) => - Array.apply(null, {length: Math.ceil(arr.length/size)}).map((v, i) => arr.slice(i*size, i*size+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/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/deep-flatten-array.md b/snippets/deep-flatten-array.md index 397d62241..c350d848c 100644 --- a/snippets/deep-flatten-array.md +++ b/snippets/deep-flatten-array.md @@ -5,6 +5,6 @@ Use `Array.reduce()` to get all elements that are not arrays, flatten each eleme ```js const deepFlatten = arr => - arr.reduce( (a, v) => a.concat( Array.isArray(v) ? deepFlatten(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/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/flatten-array.md b/snippets/flatten-array.md index 224060d02..d23f24611 100644 --- a/snippets/flatten-array.md +++ b/snippets/flatten-array.md @@ -3,6 +3,6 @@ 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-native-type-of-value.md b/snippets/get-native-type-of-value.md index d2ded3f83..9e043a83e 100644 --- a/snippets/get-native-type-of-value.md +++ b/snippets/get-native-type-of-value.md @@ -4,6 +4,6 @@ Returns lower-cased constructor name of value, "undefined" or "null" if value is ```js const getType = v => - v === undefined ? "undefined" : v === null ? "null" : v.constructor.name.toLowerCase(); + 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..ab833c9d2 --- /dev/null +++ b/snippets/group-by.md @@ -0,0 +1,14 @@ +### 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) => + (typeof func === 'function' ? arr.map(func) : arr.map(val => val[func])) + .reduce((acc, val, i) => { + acc[val] = acc[val] === undefined ? [arr[i]] : 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 index 5b47db022..e524408a8 100644 --- a/snippets/hamming-distance.md +++ b/snippets/hamming-distance.md @@ -5,6 +5,6 @@ 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; + ((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 03de99eb2..def23fb9c 100644 --- a/snippets/initialize-array-with-range.md +++ b/snippets/initialize-array-with-range.md @@ -5,6 +5,6 @@ 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/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 73d32141e..44e099d7e 100644 --- a/snippets/measure-time-taken-by-function.md +++ b/snippets/measure-time-taken-by-function.md @@ -8,6 +8,6 @@ const timeTaken = callback => { const t0 = performance.now(), r = callback(); console.log(performance.now() - t0); return r; -} +}; // timeTaken(() => Math.pow(2, 10)) -> 1024 (0.010000000009313226 logged in console) ``` diff --git a/snippets/median-of-array-of-numbers.md b/snippets/median-of-array-of-numbers.md index 3a675a545..8113d51c6 100644 --- a/snippets/median-of-array-of-numbers.md +++ b/snippets/median-of-array-of-numbers.md @@ -5,9 +5,9 @@ Return the number at the midpoint if `length` is odd, otherwise the average of t ```js const median = arr => { - const mid = Math.floor(arr.length / 2), nums = arr.sort((a,b) => a - b); + 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/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..4e849eff7 --- /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/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 62ec96655..73b71b645 100644 --- a/snippets/powerset.md +++ b/snippets/powerset.md @@ -4,6 +4,6 @@ Use `Array.reduce()` combined with `Array.map()` to iterate over elements and co ```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/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/sleep.md b/snippets/sleep.md new file mode 100644 index 000000000..e2a58d0bd --- /dev/null +++ b/snippets/sleep.md @@ -0,0 +1,14 @@ +### 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.'); +} +*/ +``` diff --git a/snippets/sort-characters-in-string-(alphabetical).md b/snippets/sort-characters-in-string-(alphabetical).md index 7ed73cb14..9cf37ad77 100644 --- a/snippets/sort-characters-in-string-(alphabetical).md +++ b/snippets/sort-characters-in-string-(alphabetical).md @@ -4,6 +4,6 @@ Split the string using `split('')`, `Array.sort()` utilizing `localeCompare()`, ```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/sum-of-array-of-numbers.md b/snippets/sum-of-array-of-numbers.md index 939106cc1..9729eb474 100644 --- a/snippets/sum-of-array-of-numbers.md +++ b/snippets/sum-of-array-of-numbers.md @@ -3,6 +3,6 @@ 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/truncate-a-string.md b/snippets/truncate-a-string.md index 556667781..a33ac6367 100644 --- a/snippets/truncate-a-string.md +++ b/snippets/truncate-a-string.md @@ -5,6 +5,6 @@ Return the string truncated to the desired length, with `...` appended to the en ```js const truncate = (str, num) => - str.length > num ? str.slice(0, num > 3 ? num-3 : num) + '...' : str; + str.length > num ? str.slice(0, num > 3 ? num - 3 : num) + '...' : str; // truncate('boomerang', 7) -> 'boom...' ``` 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 ```