Repository: plexis-js/plexis
Pull request #97 (2019-10-28 22:05:47)

Feature: count 
Fix for #94


AngelGzS: Someone knows how to fix it?
theashraf: Try running `yarn bootstrap` before running `yarn test` again.
codecov[bot]: # [Codecov](https://codecov.io/gh/plexis-js/plexis/pull/97?src=pr&el=h1) Report
> Merging [#97](https://codecov.io/gh/plexis-js/plexis/pull/97?src=pr&el=desc) into [master](https://codecov.io/gh/plexis-js/plexis/commit/6e51bfb92a4d8c9a0ef3bc090a43c09b7da14cf7?src=pr&el=desc) will **not change** coverage.
> The diff coverage is `100%`.


[![Impacted file tree graph](https://codecov.io/gh/plexis-js/plexis/pull/97/graphs/tree.svg?width=650&token=DdDVC9ByG1&height=150&src=pr)](https://codecov.io/gh/plexis-js/plexis/pull/97?src=pr&el=tree)

```diff
@@          Coverage Diff          @@
##           master    #97   +/-   ##
=====================================
  Coverage     100%   100%           
=====================================
  Files          26     27    +1     
  Lines         130    137    +7     
=====================================
+ Hits          130    137    +7
```


| [Impacted Files](https://codecov.io/gh/plexis-js/plexis/pull/97?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [packages/count/src/index.js](https://codecov.io/gh/plexis-js/plexis/pull/97/diff?src=pr&el=tree#diff-cGFja2FnZXMvY291bnQvc3JjL2luZGV4Lmpz) | `100% <100%> (ø)` | |

AngelGzS: > Try running `yarn bootstrap` before running `yarn test` again.

Thank you!

Patch:
diff --git a/README.md b/README.md
index d903ed7..ba2ab0c 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@
 
 </div>
 
-This is the main monorepo codebase of Plexis.js a production-ready string manipulation libray that's community driven.
+This is the main monorepo codebase of Plexis.js a production-ready string manipulation library that's community-driven.
 
 [![npm version](https://badge.fury.io/js/plexis.svg)](https://www.npmjs.com/package/plexis)
 [![bundle size](https://badgen.net/bundlephobia/minzip/plexis)](https://bundlephobia.com/result?p=plexis)
@@ -19,7 +19,7 @@ This is the main monorepo codebase of Plexis.js a production-ready string manipu
 
 For the past few years managing, contributing or even starting an open-source project could be hard, especially for newcomers. Plexis was born and driven by the JavaScript community. Our initial goal is to provide a production-ready set of utilities and help people understand how an open-source project is maintained. Plexis is driven by our contributors and it should always stay that way.
 
-You may have noticed that there are some functions missing and there are [lots of open issues](https://github.com/plexis-js/plexis/issues) in our repo. That's because we want to allow people to create through the process of learning. Plexis grows with the community and we want to provide a friendly environment for people to get creative, have fun and expand their expertise into JavaScript.
+You may have noticed that some functions are missing and there are [lots of open issues](https://github.com/plexis-js/plexis/issues) in our repo. That's because we want to allow people to create through the process of learning. Plexis grows with the community and we want to provide a friendly environment for people to get creative, have fun and expand their expertise into JavaScript.
 
 **Plexis aims to be the best and most flexible library for string operations in the JavaScript and also encourage everyone to learn.**
 
@@ -56,7 +56,7 @@ npm install @plexis/without-diacritics @plexis/toPred
 
 ## Using
 
-Plexis utilities can be directly been used, Plexis is production-ready and made for Node.js as well as the web. You can directly include and use any module from Plexis inside your project.
+Plexis utilities can be directly used, Plexis is production-ready and made for Node.js as well as the web. You can directly include and use any module from Plexis inside your project.
 
 ```javascript
 import {toPred} from 'plexis';
@@ -79,7 +79,7 @@ The basic idea behind Plexis is to help people understand and learn how to use t
 
 - Working with pull requests, forks, GIT and the whole workflow of an open-source project.
 - Learning how unit testing works.
-- Taking a look how a CI/CD workflow works along with the NPM registry.
+- Taking a look at how a CI/CD workflow works along with the NPM registry.
 
 ## Codebase and technologies
 
@@ -110,7 +110,7 @@ plexis/
 
 ## Contributing
 
-**We welcome any and all contributions from the community!** Plexis is made, driven and maintained by the community. We want to offer everyone a fair chance to make their first steps into open-source and learn through the journey.
+**We welcome any contributions from the community!** Plexis is made, driven and maintained by the community. We want to offer everyone a fair chance to make their first steps into open-source and learn through the journey.
 
 ## Great, how do I get started?
 
@@ -120,12 +120,12 @@ Plexis has a [Code of Conduct](CODE-OF-CONDUCT.md). Please review and help enfor
 
 First things first, thanks so much! Feel free to contribute by opening and commenting on issues, helping answer questions, updating or improving our documentation, or opening a pull request. For quick bug fixes or PRs that address an open issue, feel free to open a PR. You can suggest API changes or dig through your codebase and make us a gift with that precious function of yours.
 
-Even the a tiny piece of code, knowledge or even a few minutes you can spare for Plexis are really important for us.
+Even the tiniest piece of code, knowledge or even a few minutes you can spare for Plexis are really important for us.
 [Code of Conduct](CODE-OF-CONDUCT.md)
 
 ### Creating a new issue
 
-We have setup proper GitHub issue templates with guidelines about asking for features, fixing a bug or even questions. We are waiting for your ideas to start flowing.
+We have set up proper GitHub issue templates with guidelines about asking for features, fixing a bug or even questions. We are waiting for your ideas to start flowing.
 
 ### Setup your environment
 
@@ -140,7 +140,7 @@ Now you can locally clone the project as: `git clone git@github.com:plexis-js/pl
 
 ### Pick an open issue
 
-Plexis is all about teaching people. You can found lots of open issues with different types of difficulty. Usually there are labels that they can help you find the best open issue for you. Find the best issue for you and let's get started.
+Plexis is all about teaching people. You can found lots of open issues with different types of difficulty. Usually, there are labels that they can help you find the best open issue for you. Find the best issue for you and let's get started.
 
 Usually, you will find yourself creating a new package or as it is said "a feature request", thus we are trying to provide as much information, test cases or examples as possible.
 
@@ -162,7 +162,7 @@ You need to take a few additional steps. Let's assume that you need to create a
 
 First thing first we need to create a new `@plexis` packages using `lerna create @plexis/came-case`. \_Note: NPM does not allows uppercase characters for packages`.
 
-You can use `lerna create` for creating a new package, more infos can be found [here](https://github.com/lerna/lerna/tree/master/commands/create). You should include all the available information for the new package like `name`, `version`, Alternatively, we are providing [a template for new packages](/..package-template). Keep in mind that the name of package folders should be in camelCase and package.json details should be aligned with the other packages and `lerna.json`. For packages with dependencies to other `@plexis` packages, you can use `yarn bootstrap` which under the hood uses `lerna bootstrap`, learn more about bootstaping [here](https://github.com/lerna/lerna/tree/master/commands/bootstrap).
+You can use `lerna create` for creating a new package, more info can be found [here](https://github.com/lerna/lerna/tree/master/commands/create). You should include all the available information for the new package like `name`, `version`, Alternatively, we are providing [a template for new packages](/..package-template). Keep in mind that the name of package folders should be in camelCase and package.json details should be aligned with the other packages and `lerna.json`. For packages with dependencies to other `@plexis` packages, you can use `yarn bootstrap` which under the hood uses `lerna bootstrap`, learn more about bootstrapping [here](https://github.com/lerna/lerna/tree/master/commands/bootstrap).
 
 Afterward, create an `src` and a `test` folder, place your files and write the appropriate test cases for unit testing.
 
@@ -182,9 +182,9 @@ packages/
 
 Finally, you should create a JSDoc comment block for your package, providing a proper description, some code examples and documenting the parameters passed through the function. You shall also create or update the `README.md` or any related documentation files.
 
-Last but not least you shall update the main `plexis` package with exports all the submodules. Since the main `plexis` module uses snapshots for testing, you need to run `yarn test -u` in order to update the snapshot testing.
+Last but not least you shall update the main `plexis` package with exports all the submodules. Since the main `plexis` module uses snapshots for testing, you need to run `yarn test -u` to update the snapshot testing.
 
-:bulb: Tip: If your pull request resolves an open issue, don't forget to use [GitHub keywords](https://help.github.com/en/github/managing-your-work-on-github/closing-issues-using-keywords) in the description of your commit message, for example **closes #1**, in order to automatically close the equivalent issue upon merge.
+:bulb: Tip: If your pull request resolves an open issue, don't forget to use [GitHub keywords](https://help.github.com/en/github/managing-your-work-on-github/closing-issues-using-keywords) in the description of your commit message, e.g., **closes #1**, to automatically close the equivalent issue upon merge.
 
 ### Pull requests
 
@@ -194,10 +194,10 @@ In a nutshell, to submit a pull request, follow these steps:
 2. Create a branch for your changes.
 3. Install dependencies with `yarn`.
 4. Ensure tests are passing by running `yarn test`. Update any snapshots using `yarn test -u`.
-5. Update the docs or `README.md` file if required. .
+5. Update the docs or `README.md` file if required.
 6. If you're fixing a bug, it's recommended to write a failing test before writing any code.
 7. Make changes locally and commit them.
-8. Try to make sure tests still pass and that there's great coverage and clear test cases.
+8. Try to make sure tests still pass and that there's a great coverage and clear test cases.
 9. Push your branch to origin.
 10. Open a pull request in this repository with a clear title and description and link to any relevant issues
 11. Wait for a maintainer to review your pull request.
@@ -208,13 +208,13 @@ In a nutshell, to submit a pull request, follow these steps:
 
 - Lerna is a powerful tool, try to get through the documentation, make yourself familiar with the commands and follow the appropriate steps as described above.
 - Yarn can be a lifesaver for dependency management, try to avoid mixing `npm` and `yarn`.
-- Commitlint can be frustating. Please use it all consciously as it provides a consistent `git` history.
+- Commitlint can be frustrating. Please use it all consciously as it provides a consistent `git` history.
 
 - If you don't know how to do something, just ask for help. We got your back!
 
 ### Learning resources
 
-Here are some learning resources, free tutorials and books:
+Here are some learning resources, free tutorials, and books:
 
 #### ES6
 
diff --git a/docs/pages/api.md b/docs/pages/api.md
index 56c357b..c848381 100644
--- a/docs/pages/api.md
+++ b/docs/pages/api.md
@@ -27,9 +27,11 @@
 - [toPred](/packages/toPred)
 - [toSnakeCase](/packages/toSnakeCase)
 - [toSucc](/packages/toSucc)
+- [toSwapCase](/packages/toSwapCase)
 - [toTitle](/packages/toTitle)
 - [when](/packages/when)
 - [withoutDiacritics](/packages/withoutDiacritics)
 - [withoutHTML](/packages/withoutHTML)
 - [withoutIndent](/packages/withoutIndent)
 - [tail](/packages/tail)
+- [toSwap](/packages/toSwap)
diff --git a/packages/count/README.md b/packages/count/README.md
new file mode 100644
index 0000000..6c24c44
--- /dev/null
+++ b/packages/count/README.md
@@ -0,0 +1,24 @@
+## `@plexis/count`
+
+Return the number of characters in the input text.
+
+`npm i @plexis/count`
+
+**Usage**
+
+```javascript
+import count from '@plexis/count';
+
+count(); // returns 0
+count(''); // returns 0
+count('Hello'); // returns 5
+count('Hello   '); // returns 8
+count('Hello   ', char => char !== ' '); // returns 5
+```
+
+**Aliases**
+
+```javascript
+import count from '@plexis/count';
+import {count} from 'plexis';
+```
diff --git a/packages/count/package.json b/packages/count/package.json
new file mode 100644
index 0000000..ed12749
--- /dev/null
+++ b/packages/count/package.json
@@ -0,0 +1,31 @@
+{
+  "name": "@plexis/count",
+  "version": "0.0.21",
+  "main": "dist/index.js",
+  "module": "dist/index.esm.js",
+  "jsnext:main": "./src/index.js",
+  "description": "Return the number of characters in the input text.",
+  "keywords": [
+    "utility",
+    "string",
+    "parse",
+    "format",
+    "validate"
+  ],
+  "author": "Angel Gonzalez <angelbroz@gmail.com>",
+  "homepage": "https://github.com/plexis-js/plexis#readme",
+  "license": "MIT",
+  "files": [
+    "lib"
+  ],
+  "publishConfig": {
+    "access": "public"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/plexis-js/plexis.git"
+  },
+  "bugs": {
+    "url": "https://github.com/plexis-js/plexis/issues"
+  }
+}
diff --git a/packages/count/src/index.js b/packages/count/src/index.js
new file mode 100644
index 0000000..6351761
--- /dev/null
+++ b/packages/count/src/index.js
@@ -0,0 +1,24 @@
+/**
+ * @description This is a sample description
+ * @param {String} text
+ * @param (Function) validator, validates if a character should be count or not
+ * @example
+ * count('b') // returns 1
+ * count('Foo') // returns 3
+ * count('Foo bar') // returns 7
+ * count('Foo bar  ', char => char != ' ') //returns 6
+ *
+ */
+const count = (text = '', validator = () => true) => {
+  let strLen = text ? text.length : 0;
+
+  strLen = 0;
+
+  text.split('').map(letter => {
+    strLen += validator(letter) ? 1 : 0;
+  });
+
+  return strLen;
+};
+
+export default count;
diff --git a/packages/plexis/package.json b/packages/plexis/package.json
index b5e53ef..ee15846 100644
--- a/packages/plexis/package.json
+++ b/packages/plexis/package.json
@@ -15,6 +15,7 @@
   "dependencies": {
     "@plexis/compare": "^0.0.21",
     "@plexis/compose": "^0.0.21",
+    "@plexis/count": "^0.0.21",
     "@plexis/distance": "^0.0.21",
     "@plexis/ends-with": "^0.0.21",
     "@plexis/escape-html": "^0.0.21",
@@ -31,6 +32,7 @@
     "@plexis/to-capitals": "^0.0.21",
     "@plexis/to-chicago": "^0.0.21",
     "@plexis/to-chunks": "^0.0.21",
+    "@plexis/to-swap-case": "^0.0.20",
     "@plexis/to-human": "^0.0.21",
     "@plexis/to-lower": "^0.0.21",
     "@plexis/to-pascal-case": "^0.0.21",
@@ -41,6 +43,7 @@
     "@plexis/to-title": "^0.0.21",
     "@plexis/when": "^0.0.21",
     "@plexis/without-diacritics": "^0.0.21",
+    "@plexis/to-swap": "^0.0.21",
     "@plexis/without-html": "^0.0.21",
     "@plexis/without-indent": "^0.0.21",
     "@plexis/tail": "^0.0.21"
diff --git a/packages/plexis/src/index.js b/packages/plexis/src/index.js
index 604cc1e..5a4df13 100644
--- a/packages/plexis/src/index.js
+++ b/packages/plexis/src/index.js
@@ -4,6 +4,7 @@ export {
   default as naturalCompare
 } from '@plexis/compare';
 export {default as compose, default as _do} from '@plexis/compose';
+export {default as count} from '@plexis/count';
 export {
   default as calcLevenshtein,
   default as distance,
@@ -35,6 +36,7 @@ export {
   default as toChicagoTitle,
   default as toTurabian
 } from '@plexis/to-chicago';
+export {default as toSwapCase, default as swapCase} from '@plexis/to-swap-case';
 export {default as toChunks} from '@plexis/to-chunks';
 export {
   default as decapitalize,
@@ -66,3 +68,4 @@ export {
 } from '@plexis/is-alphanumeric';
 export {default as withoutHTML, default as removeHTML} from '@plexis/without-html';
 export {default as tail, default as rest, default as last, default as pop} from '@plexis/tail';
+export {default as toSwap, default as swap} from '@plexis/to-swap';
diff --git a/packages/toSwap/README.md b/packages/toSwap/README.md
new file mode 100644
index 0000000..537f228
--- /dev/null
+++ b/packages/toSwap/README.md
@@ -0,0 +1,23 @@
+## `@plexis/toSwap`
+
+Swaps every character with the next one in a given string.
+
+`npm i @plexis/to-swap`
+
+**Usage**
+
+```javascript
+import toSwap from '@plexis/to-swap';
+
+toSwap('ab'); // returns 'ba'
+toSwap('abc'); // returns 'bac'
+toSwap('abcd'); // returns 'badc'
+toSwap('a b'); // returns ' ab'
+```
+
+**Aliases**
+
+```javascript
+import {toSwap} from 'plexis';
+import {swap} from 'plexis';
+```
diff --git a/packages/toSwap/package.json b/packages/toSwap/package.json
new file mode 100644
index 0000000..cdc57af
--- /dev/null
+++ b/packages/toSwap/package.json
@@ -0,0 +1,29 @@
+{
+  "name": "@plexis/to-swap",
+  "version": "0.0.21",
+  "main": "dist/index.js",
+  "module": "dist/index.esm.js",
+  "jsnext:main": "./src/index.js",
+  "files": [
+    "dist",
+    "src"
+  ],
+  "authors": [
+    "David Medeiros <david.medeiros@live.com>"
+  ],
+  "license": "MIT",
+  "keywords": [
+    "utility",
+    "string",
+    "parse",
+    "format",
+    "validate"
+  ],
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/plexis-js/plexis.git"
+  },
+  "publishConfig": {
+    "access": "public"
+  }
+}
diff --git a/packages/toSwap/src/index.js b/packages/toSwap/src/index.js
new file mode 100644
index 0000000..b6679c8
--- /dev/null
+++ b/packages/toSwap/src/index.js
@@ -0,0 +1,21 @@
+/**
+ * @description Swaps every character in a string, until the end of the string
+ * @param {String} string
+ * @example
+ * toSwap('ab') // returns 'ab'
+ * toSwap('a b') // returns ' ab'
+ * toSwap('abcd') // returns 'badc'
+ * @returns {String} reordered letters
+ */
+const toSwap = string => {
+  var arr = string.split('');
+  arr.forEach((current, index, array) => {
+    if (index % 2 == 0) {
+      array[index] = array[index + 1];
+      array[index + 1] = current;
+    }
+  });
+  return arr.join('');
+};
+
+export default toSwap;
diff --git a/packages/toSwapCase/README.md b/packages/toSwapCase/README.md
new file mode 100644
index 0000000..be25969
--- /dev/null
+++ b/packages/toSwapCase/README.md
@@ -0,0 +1,22 @@
+# `@plexis/to-swap-case`
+
+Swaps lowercase to uppercase and vice versa for the input text.
+
+**Installation**
+`npm i @plexis/to-swap-case`
+
+**Usage**
+
+```javascript
+import toSwapCase from '@plexis/to-swap-case';
+
+toSwapCase('Hello WORLD'); // => 'hELLO world'
+toSwapCase('123 toys'); // => '123 TOYS'
+```
+
+**Aliases**
+
+```javascript
+import toSwapCase from '@plexis/to-swap-case';
+import {toSwapCase, swapCase} from 'plexis';
+```
diff --git a/packages/toSwapCase/package.json b/packages/toSwapCase/package.json
new file mode 100644
index 0000000..247952b
--- /dev/null
+++ b/packages/toSwapCase/package.json
@@ -0,0 +1,29 @@
+{
+  "name": "@plexis/to-swap-case",
+  "version": "0.0.20",
+  "main": "dist/index.js",
+  "module": "dist/index.esm.js",
+  "jsnext:main": "./src/index.js",
+  "files": [
+    "dist",
+    "src"
+  ],
+  "authors": [
+    "Nowtryz <damien.djmb@gmail.com> (https://nowtryz.net)"
+  ],
+  "license": "MIT",
+  "keywords": [
+    "utility",
+    "string",
+    "parse",
+    "format",
+    "validate"
+  ],
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/plexis-js/plexis.git"
+  },
+  "publishConfig": {
+    "access": "public"
+  }
+}
diff --git a/packages/toSwapCase/src/index.js b/packages/toSwapCase/src/index.js
new file mode 100644
index 0000000..73eb2cd
--- /dev/null
+++ b/packages/toSwapCase/src/index.js
@@ -0,0 +1,19 @@
+'use strict';
+
+/**
+ * Swaps lowercase to uppercase and vice versa for the input text.
+ * @param {String} input
+ * @returns {String} swaped text
+ * @example
+ * toSwapCase('Hello WORLD'); // => 'hELLO world'
+ * toSwapCase('123 toys'); // => '123 TOYS'
+ */
+export default input =>
+  input
+    .toString()
+    .split('')
+    .map(c => {
+      const lower = c.toLocaleLowerCase();
+      return lower === c ? c.toLocaleUpperCase() : lower;
+    })
+    .join('');


Test patch:
diff --git a/packages/count/test/index.js b/packages/count/test/index.js
new file mode 100644
index 0000000..4134fa3
--- /dev/null
+++ b/packages/count/test/index.js
@@ -0,0 +1,19 @@
+import count from '../src';
+
+describe('@plexis/count', () => {
+  it('no first or second parameter given', () => {
+    expect(count()).toBe(0);
+  });
+
+  it('empty string given and no validator for second parameter', () => {
+    expect(count('')).toBe(0);
+  });
+
+  it('no empty string given for first and no validator for second parameter ', () => {
+    expect(count('Foo bar')).toBe(7);
+  });
+
+  it('no empty string given for first and  validator for no spaces as second parameter', () => {
+    expect(count('Foo bar   ', char => char !== ' ')).toBe(6);
+  });
+});
diff --git a/packages/plexis/test/__snapshots__/index.js.snap b/packages/plexis/test/__snapshots__/index.js.snap
index dc1e65d..315297f 100644
--- a/packages/plexis/test/__snapshots__/index.js.snap
+++ b/packages/plexis/test/__snapshots__/index.js.snap
@@ -8,6 +8,7 @@ Array [
   "naturalCompare",
   "compose",
   "_do",
+  "count",
   "calcLevenshtein",
   "distance",
   "levenshtein",
@@ -37,6 +38,8 @@ Array [
   "toChicagoStyle",
   "toChicagoTitle",
   "toTurabian",
+  "toSwapCase",
+  "swapCase",
   "toChunks",
   "decapitalize",
   "toFirstLower",
@@ -71,5 +74,7 @@ Array [
   "rest",
   "last",
   "pop",
+  "toSwap",
+  "swap",
 ]
 `;
diff --git a/packages/toSwap/test/index.js b/packages/toSwap/test/index.js
new file mode 100644
index 0000000..bc6ab57
--- /dev/null
+++ b/packages/toSwap/test/index.js
@@ -0,0 +1,21 @@
+import toSwap from '../src';
+
+it('Swap only small strings', () => {
+  expect(toSwap('ab')).toBe('ba');
+  expect(toSwap('a')).toBe('a');
+});
+it('Swap an odd number of letters', () => {
+  expect(toSwap('abc')).toBe('bac');
+  expect(toSwap('abcd')).toBe('badc');
+});
+it('Swap with spaces', () => {
+  expect(toSwap('a b')).toBe(' ab');
+  expect(toSwap('ab cd')).toBe('bac d');
+});
+it('Swap Random Characters', () => {
+  expect(toSwap('1;3')).toBe(';13');
+  expect(toSwap('.,][')).toBe(',.[]');
+});
+it('Empty string case', () => {
+  expect(toSwap('')).toBe('');
+});
diff --git a/packages/toSwapCase/test/swap-case.test.js b/packages/toSwapCase/test/swap-case.test.js
new file mode 100644
index 0000000..5cf41a5
--- /dev/null
+++ b/packages/toSwapCase/test/swap-case.test.js
@@ -0,0 +1,15 @@
+import swapCase from '../src';
+
+describe('@plexis/to-swap-case', () => {
+  it('Swap single char', () => {
+    expect(swapCase('a')).toBe('A');
+    expect(swapCase('B')).toBe('b');
+    expect(swapCase('5')).toBe('5');
+  });
+
+  it('Swap charters of a sentence', () => {
+    expect(swapCase('Hello WORLD')).toBe('hELLO world');
+    expect(swapCase('123 toys')).toBe('123 TOYS');
+    expect(swapCase('654 À Á Â Ã Ä Å Æ Ç È É Ê ę')).toBe('654 à á â ã ä å æ ç è é ê Ę');
+  });
+});