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.
npm i regex-but-with-words
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:
/(\d-)?\d{3}-\d{3}-\d{4}/g
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")
npm install regex-but-with-words
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}
)
- (ex.
- If
min
andmax
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}
)
- (ex.
- the string
"*"
can be passed asmax
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,}
)
- (ex.
- Methods marked with a
+
can accept the above parameters, but only if a single character is provided
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.
Groups can accept two types of arguments: string
and subExpressionCallback
. subExpressionCallback
returns a RegexButWithWords object to allow for chaining inside a group:
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:
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
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 | (?!=) |
Look around can accept two types of arguments: string
and subExpressionCallback
. subExpressionCallback
returns a RegexButWithWords object to allow for chaining inside a group:
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:
exp
.litral("hello")
.look
.ahead(exp => {
exp.literal("frog")
}, 2, 3)
.done("g)
// matches
/(hello(?=frog){2,3})/g
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) |
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.
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")
This module uses mocha and chai to run automated tests.
To run the unit tests, use the command
npm run test
This module uses nyc for unit test coverage.
To get test coverage, run the command
npm run 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 | π |
- 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
If you have any questions or issues you can create a new [issue here][issues]. See the full contribution guidelines here.
This repo uses Prettier JS for formatting. We recommend using the VS Code extension.
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:
- Fork the repo
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Added some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request