# regex-but-with-words

> a lightweight package with no user dependecies that allows users to chain a verbose function to create a Regular Expression. It can also be used to create a verbose version of an existing regular expression for reference

Latest version **1.5.5** (published 2023-05-09) · Apache-2.0 license · 0 weekly downloads

## Install

```sh
npm install regex-but-with-words
pnpm add regex-but-with-words
yarn add regex-but-with-words
bun add regex-but-with-words
```

## Health

**Score 15/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.5.5 |
| Published | 2023-05-09 |
| First published | 2022-06-20 |
| Weekly downloads | 0 |
| License | Apache-2.0 |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 0 |
| Unpacked size | 110.4 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 6 |
| Author | Jennifer Valle |
| Maintainers | jvallexm |
| Keywords | regex, regexp, regular expressions, visualization, browser |

## Links

- npm: https://www.npmjs.com/package/regex-but-with-words
- Repository: https://github.com/IBM/regex-but-with-words
- Homepage: https://github.com/IBM/regex-but-with-words#readme
- Issues: https://github.com/IBM/regex-but-with-words/issues
- npm.io page: https://npm.io/package/regex-but-with-words

## Alternatives

- [@opentelemetry/exporter-zipkin](https://npm.io/package/@opentelemetry/exporter-zipkin.md) — 14.8M weekly downloads
- [pusher-js](https://npm.io/package/pusher-js.md) — 2.0M weekly downloads
- [browserify](https://npm.io/package/browserify.md) — 1.7M weekly downloads
- [sqs-consumer](https://npm.io/package/sqs-consumer.md) — 1.7M weekly downloads
- [@sanity/eventsource](https://npm.io/package/@sanity/eventsource.md) — 930.8K weekly downloads

## Recent versions

- 1.5.5 (latest) — 2023-05-09
- 1.5.4 — 2023-05-09
- 1.5.3 — 2023-05-09
- 1.5.1 — 2022-12-13
- 1.5.0 — 2022-10-19
- 1.4.1 — 2022-10-07
- 1.4.0 — 2022-10-06
- 1.3.0 — 2022-10-04
- 1.2.0 — 2022-09-08
- 1.0.5 — 2022-07-27
- 1.0.4 — 2022-06-23
- 1.0.3 — 2022-06-23
- 1.0.2 — 2022-06-21
- 1.0.1 — 2022-06-21
- 1.0.0 — 2022-06-20

## README

# RegEx But With Words

`regex-but-with-words` is a lightweight Regular Expression visualization package with no user dependecies that allows users to chain a verbose function to create a Regular Expression. It can also be used to create a verbose version of an existing regular expression for reference.

[![OpenSSF Best Practices](https://bestpractices.coreinfrastructure.org/projects/7349/badge)](https://bestpractices.coreinfrastructure.org/projects/7349)

## Installing 

```shell
npm i regex-but-with-words
```

## Usage

### Regex But With Words

```js
const { RegexButWithWords } = require("regex-but-with-words");

let exp = new RegexButWithWords();

let phoneNumberExpression = exp
  .group(exp => exp.digit().literal("-"))
  .lazy()
  .digit(3)
  .literal("-")
  .digit(3)
  .literal("-")
  .digit(4)
  .done("g")
```

Returns the composed regular expression:
```js
/(\d-)?\d{3}-\d{3}-\d{4}/g
```

###  Regex To Words

```js
const { RegexToWords } = require("regex-but-with-words")
let wordifedEmailRegex = RegexToWords(/[A-z0-9][A-z0-9\-.]+[A-z0-9]@[\w\-]+\.\w+/g);

// Returns the following as a string

exp
  .set("A-z0-9")
  .set("A-z0-9-.")
  .oneOrMore()
  .set("A-z0-9")
  .literal("@")
  .set((exp) => {
    exp
      .word()
      .literal("-")
  })
  .oneOrMore()
  .literal(".")
  .word()
  .oneOrMore()
  .done("g")
```

---

## Table of Contents

1. [Installation](#Installation)
2. [Expressions](#expressions)
    - [Groups](#groups)
    - [Other Regex But With Words Methods](#other-regex-but-with-words-methods)
3. [RegexToWords](#RegexToWords)
4. [Developer Dependencies](#developer-dependencies)
5. [Code Test Coverage](#code-test-coverage)
6. [Contributing](#contributing)

---

## Installation

```shell
npm install regex-but-with-words
```

---

## Expressions

### Character and Quantifier Methods

The following methods can be used with the `RegexButWithWords` constructor. Each method can be chained with any method other than `done()`

Name                 | Matches                                                                                                                | Regex 
---------------------|------------------------------------------------------------------------------------------------------------------------|-------
`.word()`*           | Any letter A-z, digits 0-9, and underscores                                                                            | `\w` 
`.notWord()`*        | Any character other than A-z, digits 0-9, and underscores                                                              | `\W` 
`.digit()`*          | digits 0-9                                                                                                             | `\d` 
`.notWord()`*        | Any character other digits 0-9                                                                                         | `\D` 
`.any()`*            | Any character                                                                                                          | `.`
`.whitespace()`*     | Any whitespace character (spaces, tabs, newlines)                                                                      | `\s`
`.notWhitespace()`*  | Any non-whitespace character (spaces, tabs, newlines)                                                                  | `\S`
`.wordBoundary()`    | Position between word character and a non-word character                                                               | `\b`
`.notWordBoundary()` | Any character not between a word and a non-word character                                                              | `\b`
`.tab()` *           | Tab character                                                                                                          | `\t`
`.newline()` *       | Newline character                                                                                                      | `\n`
`.literal()` +       | A string literal of the composed characters                                                                            | native characters
`.stringBegin()`     | The beginning of a string or line                                                                                      | `^`
`.stringEnd()`       | The end of a string or line                                                                                            | `$`
`.oneOrMore()`       | Matches one or more of the preceding function call (ex. `.digit().oneOrMore()` will match one or more digits)          | `+`
`.anyNumber()`       | Matches any number of the preceding function call including 0 (ex. `.digit().anyNumber()` will match 0 or more digits) | `*`
`.lazy()`            | Matches 0 or one of the preceding function (ex. `.word().lazy()` will match 0 or 1 word character)                     | `?`
`.or()`              | Logical or between two values (ex. `.word().or().digit()` will match one word or digit character)                      | `|`
`.backslash()` *     | Matches a literal backslash, this function is here due to inconsitancies in string literal `\` requiring an escape sequence | `\\`

**Methods marked with a `*` can accept up to two parameters `min`, and `max`.**
- If only `min` is provided, it will match exactly that number of the preceding call
    - (*ex. `.word(4)` will match exactly 4 word characters. Regex equivilant is `\w{4}`*)
- If `min` and `max` are provided it will match any number of tokens within a range
    - (*ex. `.word(4,6)` will match four, five, or 6 word characters. Regex equivilant is `\w{4,6}`*)
- the string `"*"` can be passed as `max` to match any number of the preceding token after the minimum is met
    - (*ex. `.word(4, "*"` will match four or more word characters. Regex equivilant is `\w{4,}`*)
- Methods marked with a `+` can accept the above parameters, but only if a single character is provided

---

### Groups

Capturing groups. Each method can be chained with any method other than `done()`

Name                             | Matches                                                                                                                        | Regex
---------------------------------|--------------------------------------------------------------------------------------------------------------------------------|-------
`.group(regexGroup)`             | A group of characters. `.group("abc")` will match `abc` anywhere in a string                                                   | `()`
`.nonCapturingGroup(regexGroup)` | Match a group of characters without capturing `.nonCapturingGroup("abc").word()` will match a word character preceded by `abc` | `(?:)`
`.set(regexGroup)`               | Match any one character from a set. `[abc]` will match `a` `b` or `c`                                                          | `[]`
`.negatedSet(regexGroup)`        | Match any one character not in a set. `[^abc]` will match any character that is not `a` `b` or `c`                             | `[^]`

**Groups now support `min` and `max` quantifiers.**

#### Group Callback Functions

Groups can accept two types of arguments: `string` and `subExpressionCallback`. `subExpressionCallback` returns a RegexButWithWords object to allow for chaining inside a group:

```js
exp
  .group(exp => {
    exp.whitespace().or().literal("space")
  })
  .done("g")

// Matches

/(\s|space)/g

exp.group("\sfrog\s").done("g")

// Matches
/(\sfrog\s)/g
```

Groups can also be quantified by passing in a `min` value or a `min` and `max` value:

```js
exp
  .group(exp => {
    exp.whitespace().or().literal("space")
  }, 2)
  .done("g")

// Matches

/(\s|space){2}/g

exp.group("\sfrog\s", 2, 3).done("g")

// Matches
/(\sfrog\s){2,3}/g
```

---

### Look Around

Non-capturing lookaround groups. Each method can be chained with any method other than `done()`

Name                              | Matches                                                    | Regex
----------------------------------|------------------------------------------------------------|-------
`look.ahead(regexGroup)`          | A group after the expression without including the result  | `(?=)`
`look.behind(regexGroup)`         | A group before the expression without including the result | `(?:)`
`negativeLook.ahead(regexGroup)`  | A group that cannot match after the main expression        | `(?!=)`

#### Non-capturing Group Callback Functions

Look around can accept two types of arguments: `string` and `subExpressionCallback`. `subExpressionCallback` returns a RegexButWithWords object to allow for chaining inside a group:


```js
exp
  .look
  .behind(exp => {
    exp.stringBegin().group("behind")
  })
  .literal("matching")
  .look
  .ahead(exp => {
    exp.group("ahead").stringEnd()
  })
  .done("g")

// Matches

/(?:^behind)matching(?=ahead$)/g

exp
  .look
  .behind("egg")
  .literal("plant")
  .done("g")

// Matches

/(?:egg)plant/g

```

Lookaround groups can also be quantified by passing in a `min` value or a `min` and `max` value:

```js
exp
  .litral("hello")
  .look
  .ahead(exp => {
    exp.literal("frog")
  }, 2, 3)
  .done("g)

// matches

/(hello(?=frog){2,3})/g
```


---

### Other Regex But With Words Methods

Name           | Usage
---------------|--------
`.done(flags)` | Terminates a regex but with words chain and returns the resulting regex with flags. ("g" is used for global and "i" for ignore case)

---

## RegexToWords

This module also includes a function that allows the creation of valid `RegexButWithWords` function chain from existing Regular Expressions as a string. This allows for experienced users to store regular expressions in a readable format.

### Example Usage

```js
const { RegexToWords } = require("regex-but-with-words")

let wordifedRegex = RegexToWords(/^--?[a-z-]+\s\S+(\s--?[a-z-]+\s\S+)*$/g);

// Returns the following as a string

exp
  .stringBegin()
  .literal("-")
  .literal("-")
  .lazy()
  .set("a-z-")
  .oneOrMore()
  .whitespace()
  .notWhitespace()
  .oneOrMore()
  .group((exp) => { 
    exp
      .whitespace()
      .literal("-")
      .literal("-")
      .lazy()
      .set("a-z-")
      .oneOrMore()
      .whitespace()
      .notWhitespace()
      .oneOrMore() 
  })
  .anyNumber()
  .stringEnd()
  .done("g")

```

---

## Developer Dependencies

- [nyc](https://www.npmjs.com/package/nyc)
- [mocha](https://mochajs.org/)
- [chai](https://www.chaijs.com/)

---

## Automated Testing

This module uses [mocha](https://mochajs.org/) and [chai](https://www.chaijs.com/) to run automated tests. 

To run the unit tests, use the command
```shell
npm run test
```

## Code Test Coverage

This module uses [nyc](https://www.npmjs.com/package/nyc) for unit test coverage.

To get test coverage, run the command 
```shell
npm run coverage
```

### Current Test Coverage

File            | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------------|---------|----------|---------|---------|-------------------
All files       |     100 |      100 |     100 |     100 | 🏆
 expressions.js |     100 |      100 |     100 |     100 | 🏆
 utils.js       |     100 |      100 |     100 |     100 | 🏆
 verbose.js     |     100 |      100 |     100 |     100 | 🏆

---

### Bugs

- A detailed title describing the issue beginning with `[BUG]` and the current release. For sprint one, filing a bug would have the title `[BUG][0.1.0] <issue title>`
- Steps to recreate said bug (including non-sensitive variables)
- (optional) Corresponding output logs **as text or as part of a code block**
- Tag the issue with the `bug` label 

---

## Contributing

If you have any questions or issues you can create a new [issue here][issues]. See the full contribution guidelines [here](./CONTRIBUTING.md). 

This repo uses [Prettier JS](https://prettier.io/) for formatting. We recommend using the [VS Code extension](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode).

Pull requests are very welcome! Make sure your patches are well tested.
Ideally create a topic branch for every separate change you make. For
example:

1. Fork the repo
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Added some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request

---
_Source: https://npm.io/package/regex-but-with-words · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
