From b2e12335f8e7b321403bb6a73e79742f8a0c39d9 Mon Sep 17 00:00:00 2001 From: Wojciech Maj Date: Mon, 18 Dec 2017 00:41:26 +0100 Subject: [PATCH 01/33] Replace spread operator with split() for increased performance and compatibility --- snippets/reverseString.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/snippets/reverseString.md b/snippets/reverseString.md index a76c506db..5564a5897 100644 --- a/snippets/reverseString.md +++ b/snippets/reverseString.md @@ -2,10 +2,10 @@ Reverses a string. -Use array destructuring and `Array.reverse()` to reverse the order of the characters in the string. +Use `split('')` and `Array.reverse()` to reverse the order of the characters in the string. Combine characters to get a string using `join('')`. ```js -const reverseString = str => [...str].reverse().join(''); +const reverseString = str => str.split('').reverse().join(''); // reverseString('foobar') -> 'raboof' ``` From a26c70864bfac8c8634a486164dd91c5e57c0c0a Mon Sep 17 00:00:00 2001 From: Simon Legg Date: Mon, 18 Dec 2017 14:11:16 +0000 Subject: [PATCH 02/33] add reference to #without --- snippets/pull.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/snippets/pull.md b/snippets/pull.md index 4913c5082..42efe6c1b 100644 --- a/snippets/pull.md +++ b/snippets/pull.md @@ -5,6 +5,8 @@ Mutates the original array to filter out the values specified. Use `Array.filter()` and `Array.includes()` to pull out the values that are not needed. Use `Array.length = 0` to mutate the passed in array by resetting it's length to zero and `Array.push()` to re-populate it with only the pulled values. +_(For a snippet that does not mutate the original array see [`without`](#without))_ + ```js const pull = (arr, ...args) => { let pulled = arr.filter((v, i) => !args.includes(v)); From b4196993df2319c847d85e36ab5f176045175cd5 Mon Sep 17 00:00:00 2001 From: Simon Legg Date: Mon, 18 Dec 2017 14:14:46 +0000 Subject: [PATCH 03/33] Add reference to #pull --- snippets/without.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/snippets/without.md b/snippets/without.md index 70f2a20aa..532ec26d9 100644 --- a/snippets/without.md +++ b/snippets/without.md @@ -4,6 +4,8 @@ Filters out the elements of an array, that have one of the specified values. Use `Array.filter()` to create an array excluding(using `!Array.includes()`) all given values. +_(For a snippet that mutates the original array see [`pull`](#pull))_ + ```js const without = (arr, ...args) => arr.filter(v => !args.includes(v)); // without([2, 1, 2, 3], 1, 2) -> [3] From 8c5af9af49b4082fcd154ed0f81d3e6925a2f585 Mon Sep 17 00:00:00 2001 From: David Wu Date: Mon, 18 Dec 2017 18:11:24 +0100 Subject: [PATCH 04/33] Back to top link in footer --- static-parts/index-end.html | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/static-parts/index-end.html b/static-parts/index-end.html index 1dd086328..6ea0075e4 100644 --- a/static-parts/index-end.html +++ b/static-parts/index-end.html @@ -1,6 +1,9 @@ - + - + From 170c7381767065fa0956a964aaf933828fd9f590 Mon Sep 17 00:00:00 2001 From: David Wu Date: Mon, 18 Dec 2017 18:11:32 +0100 Subject: [PATCH 05/33] top anchor --- scripts/web-script.js | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/web-script.js b/scripts/web-script.js index edc221de3..27e84fcc4 100644 --- a/scripts/web-script.js +++ b/scripts/web-script.js @@ -60,6 +60,7 @@ try { output += '\n'; } output += `
`; + output += ` `; // Loop over tags and snippets to create the list of snippets for(let tag of [...new Set(Object.entries(tagDbData).map(t => t[1]))].filter(v => v).sort((a,b) => a.localeCompare(b))){ output +=md.render(`## ${capitalize(tag, true)}\n`).replace(/

/g,'

'); From 890cf6c22109b78f0a4163972c82772b9f017bf0 Mon Sep 17 00:00:00 2001 From: David Wu Date: Mon, 18 Dec 2017 18:12:11 +0100 Subject: [PATCH 06/33] Build website --- docs/index.html | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/index.html b/docs/index.html index 7c2e08821..55dd98227 100644 --- a/docs/index.html +++ b/docs/index.html @@ -159,7 +159,7 @@ validateEmail validateNumber -

Array

+
 

Array

arrayMax

Returns the maximum value in an array.

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

@@ -1072,9 +1072,12 @@ Use Number() to check if the coercion holds.

// validateNumber('10') -> true

- +
- + From 758f8547d4e215855e094c9a5b2cb00402e1f666 Mon Sep 17 00:00:00 2001 From: taltmann42 Date: Mon, 18 Dec 2017 19:00:24 +0100 Subject: [PATCH 07/33] Create difference-with.md --- snippets/difference-with.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 snippets/difference-with.md diff --git a/snippets/difference-with.md b/snippets/difference-with.md new file mode 100644 index 000000000..70f43a5c5 --- /dev/null +++ b/snippets/difference-with.md @@ -0,0 +1,9 @@ +### Array differenceWith + +`filter`s out all values from `arr` for which the comparator `comp(a,b)` function never returns `true` + +```js +const differenceWith = (arr, val, comp) => arr.filter(a => !val.find(b => comp(a, b))) + +//differenceWith([1, 1.2, 1.5, 3], [1.9, 3], (a,b) => Math.round(a) == Math.round(b)) -> [1, 1.2] +``` From f6933702475cd3aa6ce0187d806a5d16f77552c3 Mon Sep 17 00:00:00 2001 From: taltmann42 Date: Mon, 18 Dec 2017 19:12:51 +0100 Subject: [PATCH 08/33] Create drop-right.md --- snippets/drop-right.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 snippets/drop-right.md diff --git a/snippets/drop-right.md b/snippets/drop-right.md new file mode 100644 index 000000000..9c162327a --- /dev/null +++ b/snippets/drop-right.md @@ -0,0 +1,13 @@ +### Array dropRight + +Returns a new array with `n` elements removed from the right + +Checks if `n` is shorter than the given array and slices it accordingly or returns an empty array + +```js +const dropRight = (arr, n = 1) => (arr.length - n ) > 0 ? arr.slice(0, arr.length - n) : [] + +//dropRight([1,2,3]) -> [1,2] +//dropRight([1,2,3], 2) -> [1] +//dropRight([1,2,3], 42) -> [] +``` From 911bf0a4dc01627e043eac4e532edcf8431a98a7 Mon Sep 17 00:00:00 2001 From: taltmann42 Date: Mon, 18 Dec 2017 19:15:51 +0100 Subject: [PATCH 09/33] Update drop-right.md shorter comparison of `n` and `arr.length` --- snippets/drop-right.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snippets/drop-right.md b/snippets/drop-right.md index 9c162327a..b1f7e02ed 100644 --- a/snippets/drop-right.md +++ b/snippets/drop-right.md @@ -5,7 +5,7 @@ Returns a new array with `n` elements removed from the right Checks if `n` is shorter than the given array and slices it accordingly or returns an empty array ```js -const dropRight = (arr, n = 1) => (arr.length - n ) > 0 ? arr.slice(0, arr.length - n) : [] +const (arr, n = 1) => n < arr.length ? arr.slice(0, arr.length - n) : [] //dropRight([1,2,3]) -> [1,2] //dropRight([1,2,3], 2) -> [1] From d8c41260da61e6a5804f69cd1007dbce20ea7800 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Feje=C5=A1?= Date: Mon, 18 Dec 2017 20:07:44 +0100 Subject: [PATCH 10/33] Add countVowels --- snippets/countVowels.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 snippets/countVowels.md diff --git a/snippets/countVowels.md b/snippets/countVowels.md new file mode 100644 index 000000000..d7d98248b --- /dev/null +++ b/snippets/countVowels.md @@ -0,0 +1,12 @@ +### countVowels + +Retuns `number` of vowels in provided string. + +Use a regular expression to count number of vowels `(A, E, I, O, U)` in a `string`. + +```js +const countVowels = str => + return (str.match(/[aeiou]/ig) || []).length; +// countVowels('foobar') -> 3 +// countVowels('gym') -> 0 +``` From 93096b8bdc84d32216db797d2b1bab4e58de12ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Feje=C5=A1?= Date: Mon, 18 Dec 2017 20:20:24 +0100 Subject: [PATCH 11/33] Generated readme, index and tag_database for countVowels --- README.md | 16 ++++++++++++++++ docs/index.html | 9 +++++++++ tag_database | 1 + 3 files changed, 26 insertions(+) diff --git a/README.md b/README.md index c4a6765d3..3ba0a832b 100644 --- a/README.md +++ b/README.md @@ -110,6 +110,7 @@ * [`anagrams`](#anagrams) * [`capitalize`](#capitalize) * [`capitalizeEveryWord`](#capitalizeeveryword) +* [`countVowels`](#countvowels) * [`escapeRegExp`](#escaperegexp) * [`fromCamelCase`](#fromcamelcase) * [`reverseString`](#reversestring) @@ -1452,6 +1453,21 @@ const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperC [⬆ back to top](#table-of-contents) +### countVowels + +Retuns `number` of vowels in provided string. + +Use a regular expression to count number of vowels `(A, E, I, O, U)` in a `string`. + +```js +const countVowels = str => + return (str.match(/[aeiou]/ig) || []).length; +// countVowels('foobar') -> 3 +// countVowels('gym') -> 0 +``` + +[⬆ back to top](#table-of-contents) + ### escapeRegExp Escapes a string to use in a regular expression. diff --git a/docs/index.html b/docs/index.html index 7c2e08821..cabdd7c23 100644 --- a/docs/index.html +++ b/docs/index.html @@ -133,6 +133,7 @@

anagrams capitalize capitalizeEveryWord +countVowels escapeRegExp fromCamelCase reverseString @@ -884,6 +885,14 @@ Omit the lowerRest parameter to keep the rest of the string intact,
const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase());
 // capitalizeEveryWord('hello world!') -> 'Hello World!'
 
+

countVowels

+

Retuns number of vowels in provided string.

+

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

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

escapeRegExp

Escapes a string to use in a regular expression.

Use replace() to escape special characters.

diff --git a/tag_database b/tag_database index f48f069b3..9f48d15cb 100644 --- a/tag_database +++ b/tag_database @@ -15,6 +15,7 @@ collatz:math compact:array compose:function countOccurrences:array +countVowels:string currentURL:browser curry:function deepFlatten:array From c30e245830233dfc3fcbcdb14554130ec152f5ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Feje=C5=A1?= Date: Mon, 18 Dec 2017 20:26:37 +0100 Subject: [PATCH 12/33] Fix small syntax typo --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4b1164232..ac39ceccc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -24,7 +24,7 @@ Here's what you can do to help: - 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 => { }`. + - 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. @@ -57,7 +57,7 @@ Here's what you can do to help: - Use `()` if your function takes no arguments. - Use `_` 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'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. From 21c7e06f7fe87872e47d9cd524da220b2977da56 Mon Sep 17 00:00:00 2001 From: King Date: Mon, 18 Dec 2017 14:32:05 -0500 Subject: [PATCH 13/33] add pullAll --- snippets/pullAll.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 snippets/pullAll.md diff --git a/snippets/pullAll.md b/snippets/pullAll.md new file mode 100644 index 000000000..d630aab99 --- /dev/null +++ b/snippets/pullAll.md @@ -0,0 +1,18 @@ +### pullAll + +This method is like pull except that it accepts an array of values to filter out before Mutating and pulling all the values from the original array. + +Use `Array.filter()` and `Array.includes()` to pull out the values that are not needed. +Use `Array.length = 0` to mutate the passed in array by resetting it's length to zero and `Array.push()` to re-populate it with only the pulled values. + +```js +const pullAll = (arr, pullArr) => { + let pulled = arr.filter((v, i) => !pullArr.includes(v)); + arr.length = 0; + pulled.forEach(v => arr.push(v)); +} + +// let myArray = ['a', 'b', 'c', 'a', 'b', 'c']; +// pullAll(myArray, ['a', 'c']); +// console.log(myArray) -> [ 'b', 'b' ] +``` \ No newline at end of file From 1053a662831c40316eb0b87ab65c64f88c6dc0c7 Mon Sep 17 00:00:00 2001 From: King Date: Mon, 18 Dec 2017 14:40:26 -0500 Subject: [PATCH 14/33] ran npm tagger & updated pullAll:array -> tag_database --- tag_database | 1 + 1 file changed, 1 insertion(+) diff --git a/tag_database b/tag_database index f48f069b3..d1f687a4b 100644 --- a/tag_database +++ b/tag_database @@ -71,6 +71,7 @@ pipe:function powerset:math promisify:function pull:array +pullAll:array randomIntegerInRange:math randomNumberInRange:math readFileLines:node From 0128cc2a10ff0a7dfce3e4f11c04a926bd14fd42 Mon Sep 17 00:00:00 2001 From: atomiks Date: Tue, 19 Dec 2017 10:58:11 +1100 Subject: [PATCH 15/33] Make median.md immutable `.sort()` mutates the original array --- snippets/median.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snippets/median.md b/snippets/median.md index fd8ca3d7c..c7eea609c 100644 --- a/snippets/median.md +++ b/snippets/median.md @@ -7,7 +7,7 @@ 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 From 60226545406e6eafc8dcef895294f117a888a5fe Mon Sep 17 00:00:00 2001 From: Larry Botha Date: Tue, 19 Dec 2017 08:52:26 +0200 Subject: [PATCH 16/33] use Array.slice instead of Array.shift --- snippets/dropElements.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/snippets/dropElements.md b/snippets/dropElements.md index 34138eb93..adc81d79d 100644 --- a/snippets/dropElements.md +++ b/snippets/dropElements.md @@ -2,12 +2,12 @@ Removes elements in an array until the passed function returns `true`. Returns the remaining elements in the array. -Loop through the array, using `Array.shift()` to drop the first element of the array until the returned value from the function is `true`. +Loop through the array, using `Array.slice()` to drop the first element of the array until the returned value from the function is `true`. Returns the remaining elements. ```js const dropElements = (arr, func) => { - while (arr.length > 0 && !func(arr[0])) arr.shift(); + while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1); return arr; }; // dropElements([1, 2, 3, 4], n => n >= 3) -> [3,4] From ddcd2787f8f4b1c0c0d3cab6d3d65fd1b40f576e Mon Sep 17 00:00:00 2001 From: Larry Botha Date: Tue, 19 Dec 2017 08:53:18 +0200 Subject: [PATCH 17/33] build updated readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c4a6765d3..57328c55a 100644 --- a/README.md +++ b/README.md @@ -251,12 +251,12 @@ const distinctValuesOfArray = arr => [...new Set(arr)]; Removes elements in an array until the passed function returns `true`. Returns the remaining elements in the array. -Loop through the array, using `Array.shift()` to drop the first element of the array until the returned value from the function is `true`. +Loop through the array, using `Array.slice()` to drop the first element of the array until the returned value from the function is `true`. Returns the remaining elements. ```js const dropElements = (arr, func) => { - while (arr.length > 0 && !func(arr[0])) arr.shift(); + while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1); return arr; }; // dropElements([1, 2, 3, 4], n => n >= 3) -> [3,4] From 88bf2d6cf455200087c6ee276d74b70fb4382d5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=84=9A=E4=BA=BA=E7=A0=81=E5=A4=B4?= Date: Tue, 19 Dec 2017 14:58:08 +0800 Subject: [PATCH 18/33] code error ```js const bottomVisible = () => document.documentElement.clientHeight + window.scrollY >= (document.documentElement.scrollHeight || document.documentElement.clientHeight); // bottomVisible() -> true ``` --- snippets/bottomVisible.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snippets/bottomVisible.md b/snippets/bottomVisible.md index 8e655db45..adac44881 100644 --- a/snippets/bottomVisible.md +++ b/snippets/bottomVisible.md @@ -6,6 +6,6 @@ Use `scrollY`, `scrollHeight` and `clientHeight` to determine if the bottom of t ```js const bottomVisible = () => - document.documentElement.clientHeight + window.scrollY >= document.documentElement.scrollHeight || document.documentElement.clientHeight; + document.documentElement.clientHeight + window.scrollY >= (document.documentElement.scrollHeight || document.documentElement.clientHeight); // bottomVisible() -> true ``` From 7cd73ff2d851ad17c49d86af56c93c3fad247cc3 Mon Sep 17 00:00:00 2001 From: David Wu Date: Tue, 19 Dec 2017 10:23:25 +0100 Subject: [PATCH 19/33] Add subtitle to header --- static-parts/index-start.html | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/static-parts/index-start.html b/static-parts/index-start.html index 0aeee1e31..cc270b31f 100644 --- a/static-parts/index-start.html +++ b/static-parts/index-start.html @@ -22,8 +22,10 @@ -
-

 30 seconds of code

+
+

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

From 8217f400b8a3fd64933575cbd0614eb47dc7796e Mon Sep 17 00:00:00 2001 From: David Wu Date: Tue, 19 Dec 2017 10:23:38 +0100 Subject: [PATCH 20/33] Build site --- docs/index.html | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/index.html b/docs/index.html index 7c2e08821..2cead4570 100644 --- a/docs/index.html +++ b/docs/index.html @@ -22,8 +22,10 @@ -
-

 30 seconds of code

+
+

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

From a80a62c56da7f00908ada432ab4e8d402065a1ee Mon Sep 17 00:00:00 2001 From: King Date: Tue, 19 Dec 2017 04:52:44 -0500 Subject: [PATCH 21/33] fix/update intializeArrayWithRange.md --- snippets/initializeArrayWithRange.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/snippets/initializeArrayWithRange.md b/snippets/initializeArrayWithRange.md index 75dbc8adf..8a58c1bbb 100644 --- a/snippets/initializeArrayWithRange.md +++ b/snippets/initializeArrayWithRange.md @@ -1,12 +1,13 @@ ### initializeArrayWithRange -Initializes an array containing the numbers in the specified range. +Initializes an array containing the numbers in the specified range where `start` and `end` are inclusive. Use `Array(end-start)` to create an array of the desired length, `Array.map()` to fill with the desired values in a range. You can omit `start` to use a default value of `0`. ```js -const initializeArrayWithRange = (end, start = 0) => - Array.from({ length: end - start }).map((v, i) => i + start); -// initializeArrayWithRange(5) -> [0,1,2,3,4] +const initializeArrayWithRange = (end, start = 0) => + Array.from({ length: (end + 1) - start }).map((v, i) => i + start); +// initializeArrayWithRange(5) -> [0,1,2,3,4,5] +// initializeArrayWithRange(7, 3) -> [3,4,5,6,7] ``` From 8f69f4432fb373d3f3be075d47bf657749b0d2b0 Mon Sep 17 00:00:00 2001 From: King Date: Tue, 19 Dec 2017 05:00:49 -0500 Subject: [PATCH 22/33] fix up description --- snippets/initializeArrayWithRange.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snippets/initializeArrayWithRange.md b/snippets/initializeArrayWithRange.md index 8a58c1bbb..c3ef5a0a0 100644 --- a/snippets/initializeArrayWithRange.md +++ b/snippets/initializeArrayWithRange.md @@ -2,7 +2,7 @@ Initializes an array containing the numbers in the specified range where `start` and `end` are inclusive. -Use `Array(end-start)` to create an array of the desired length, `Array.map()` to fill with the desired values in a range. +Use `Array((end + 1) - start)` to create an array of the desired length, `Array.map()` to fill with the desired values in a range. You can omit `start` to use a default value of `0`. ```js From ab971e7f4d7b71c4c9207b32ca103b68bd3e2898 Mon Sep 17 00:00:00 2001 From: Angelos Chalaris Date: Tue, 19 Dec 2017 12:01:29 +0200 Subject: [PATCH 23/33] Rebuild website --- docs/index.html | 2 +- static-parts/index-start.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/index.html b/docs/index.html index d95229aa1..3e4e53b93 100644 --- a/docs/index.html +++ b/docs/index.html @@ -28,7 +28,7 @@
-
+
-
+