README
ESLint rules using Regular Expressions
Quick Start
1 . Add dependencies:
package.json
:
..
"devDependencies": {
"eslint": ">=4.0.0",
"eslint-plugin-regex": "1.8.0",
..
2 . Configure eslint:
Short configuration:
.eslintrc.json
:
{
"plugins": [
"regex"
],
"rules": {
"regex/invalid": [
"error", [
"invalidRegex1",
"invalidRegexN"
]
],
"regex/required": [
"error", [
"requiredRegex1",
"requiredRegexN"
],
"ignoreFilesRegex"
]
}
}
Detailed configuration:
.eslintrc.json
:
{
"plugins": [
"regex"
],
"rules": {
"regex/invalid": [
"error", [{
"regex": "invalidRegex1",
"message": "errorMessage1",
"replacement": "newValue"
}, {
"id": "regexIdN",
"regex": "invalidRegexN",
"files": {
"ignore": "ignoreFilesRegexN"
}
}
]
],
"regex/required": [
"error", [{
"id": "regexId1",
"regex": "requiredRegex1",
"files": {
"inspect": "inspectFilesRegex1"
}
}, {
"regex": "requiredRegexN",
"message": "errorMessageN",
"files": {
"ignore": "ignoreFilesRegexN",
"inspect": "inspectFilesRegexN"
}
}
]
]
}
}
Goals
The idea is to allow to create different eslint rules based on Regular Expressions in order to have some "freedom" to create quick ESLint custom rules.
Rules
Name | Fixable | Description |
---|---|---|
regex/invalid |
Yes | checks that specified patterns are not found |
regex/required |
No | checks that specified patterns are found |
regex/invalid
This rule checks that specified patterns are not found in files, i.e. Invalid patterns.
Example of incorrect code for this rule:
/* eslint regex/invalid: ['error', ['"']] */
const text = 'Hello "My Friend"'
Example of correct code for this rule:
/* eslint regex/invalid: ['error', ['"']] */
const text = 'Hello \'My Friend\''
When the pattern is found, the error message will reflect the exact location, e.g.:
34:25 error Invalid regular expression /invalidRegex1/gm found regex/invalid
regex/required
This rule looks for specific patterns that must be present in each file, i.e. Required patterns.
Example of incorrect code for this rule:
/* eslint regex/required: ["error", ["^// Copyright My Friend"]] */
const text = 'Hello "My Friend"'
Example of correct code for this rule:
/* eslint regex/required: ["error", ["^// Copyright My Friend"]] */
// Copyright My Friend
const text = 'Hello "My Friend"'
Options
Both rule has two options:
- array of patterns definitions to analyze. [REQUIRED]
- Each pattern definition can be 'Short' and/or 'Detailed'.
- a string representing the regular expression for ignoring files for all patterns. [OPTIONAL]
- Slashes (
/
) are not required in the string, e.g. To get the following regex/.*test\.js/
define the following string".*test\.js"
when using.eslintrc.js
or".*test\\.js"
when using.eslintrc.json
(backslash needs to de double in a json file).
- Slashes (
[
"error",
[
"regex1",
"regexN"
],
"ignoreFilesRegex"
]
Short pattern definition
It is specified by just a regular expression string
, i.e. "regex"
- Slashes (
/
) are not required in the string, e.g. To get the following regex/\bhttp:/
define the following string"\bhttp:"
when using.eslintrc.js
or"\\bhttp:"
when using.eslintrc.json
(backslash needs to de double in a json file).
{
"regex/invalid": [
"error",
[
"invalidRegex1",
"invalidRegexN"
]
],
"regex/required": [
"error",
[
"requiredRegex1",
"requiredRegexN"
]
]
}
Detailed pattern definition
It is specified by an object
, with the following fields:
regex
: A requiredstring
representing the Regular expression to look for.replacement
[1]:- An optional
string
used to replace the invalid found pattern, or - An optional
object
that establish how the invalid found pattern will be replaced:function
: used to replace the invalid found pattern.- It will receive 3 parameters:
text
,captured
and$
, that can be used as desired. - It must return a
string
value, if not, return value will be ignored. - Its definition must be only the body of the function.
- More Information.
- It will receive 3 parameters:
- An optional
id
: An optionalstring
representing the Pattern Id.message
: An optionalstring
specifying the Message to be shown when an error happens (invalidregex
is found or requiredregex
is not found).files
: An optionalobject
specifying which files to analyze:ignore
: Astring
representing Regular expression of the files to be ignored when validating this specific pattern.inspect
: Astring
representing Regular expression of the files to be inspected when validating this specific pattern.
{
"id": "regexId",
"regex": "regex",
"message": "errorMessage",
"files": {
"ignore": "ignoreFilesRegex",
"inspect": "inspectFilesRegex"
}
}
regex
is the only Required field. Slashes (/
) are not required in the string, e.g. To get the following regex/\bhttp:/
:
- when using
.eslintrc.js
, define the following string"\bhttp:"
, or- when using
.eslintrc.json
, define"\\bhttp:"
(backslash needs to de double in a json file).- When
ignore
andinspect
are present,ignore
takes precedence.- Global ignore file pattern, takes precedence over
files
patterns.
[1] In order to fix issues
eslint
must be run with--fix
option.
Definition of the Function used to replace the invalid found pattern
Definition of the function must be done as a string
in 1 line, and the following rules apply:
- It must return a
string
value, if not, return value will be ignored, i.e. it will silently fail. - Its definition must be only the body of the function.
- For "simple" functions where the
return
is found at the beginning of the body of the function and the exact word return is not present,return
can be omitted.
- For "simple" functions where the
- If the function has invalid Javascript code, the function will be ignored, i.e. it will silently fail.
Function will receive 3 parameters, to be used as desired:
text
: astring
with the value of the invalid text found.captured
: anarray
of strings with the values of the captured groups for the regex.$
: anarray
of strings, with the value of the invalid text found plus the values of the captured groups for the regex.$[0]
=text
: astring
with the value of the invalid text found.$[1..]
=captured
: anarray
of strings with the values of the captured groups for the regex.$[1]
=captured[0]
and so on.
- It allows smaller definitions.
e.g. Using parameter text
"return text.trim()"
=> only the body of the function + returns a string
value based on text
Having the following rule in .eslintrc.json
:
{
"id": "regexIdN",
"regex": "\\serror\\w*\\s",
"replacement": {
"function": "return text.trim()"
}
}
or using $
:
{
"id": "regexIdN",
"regex": "\\serror\\w*\\s",
"replacement": {
"function": "return $[0].trim()"
}
}
then, given:
example.js
const exception = " error19 "
when linting with fix, the result will be:
const exception = "error19"
As the body of the function is "simple", i.e. the return
is found at the beginning of the body of the function, and besides, the word return is not present, then the definition could be done as:
{
"id": "regexIdN",
"regex": "\\serror\\w*\\s",
"replacement": {
"function": "text.trim()"
}
}
or
{
"id": "regexIdN",
"regex": "\\serror\\w*\\s",
"replacement": {
"function": "$[0].trim()"
}
}
e.g. Using parameter captured
"return captured[0]"
=> only the body of the function + returns a string
value based on captured
Having the following rule in .eslintrc.json
:
{
"id": "regexIdN",
"regex": "\\serror(\\w*)\\s",
"replacement": {
"function": "return captured[0]"
}
}
or using $
:
{
"id": "regexIdN",
"regex": "\\serror(\\w*)\\s",
"replacement": {
"function": "return $[1]"
}
}
then, given:
example.js
const exception = " error19 "
when linting with fix, the result will be:
const exception = "19"
As the body of the function is "simple", i.e. the return
is found at the beginning of the body of the function, and besides, the word return is not present, then the definition could be done as:
{
"id": "regexIdN",
"regex": "\\serror(\\w*)\\s",
"replacement": {
"function": "captured[0]"
}
}
or
{
"id": "regexIdN",
"regex": "\\serror(\\w*)\\s",
"replacement": {
"function": "$[1]"
}
}
e.g. Using parameters text
and captured
"return text + ' = ' + captured[0] + ' + ' + captured[1] + ' = ' + (parseInt(captured[0]) + parseInt(captured[1]))"
=> only the body of the function + returns a string
value based on text
and captured
Having the following rule in .eslintrc.json
:
{
"id": "regexIdN",
"regex": "(\\d+)\\+(\\d+)",
"replacement": {
"function": "return text + ' = ' + captured[0] + ' + ' + captured[1] + ' = ' + (parseInt(captured[0]) + parseInt(captured[1]))"
}
}
or using $
:
{
"id": "regexIdN",
"regex": "(\\d+)\\+(\\d+)",
"replacement": {
"function": "return $[0] + ' = ' + $[1] + ' + ' + $[2] + ' = ' + (parseInt($[1]) + parseInt($[2]))"
}
}
or :
{
"id": "regexIdN",
"regex": "(\\d+)\\+(\\d+)",
"replacement": {
"function": "return text + ' = ' + $[1] + ' + ' + $[2] + ' = ' + (parseInt($[1]) + parseInt($[2]))"
}
}
or :
{
"id": "regexIdN",
"regex": "(\\d+)\\+(\\d+)",
"replacement": {
"function": "return `${text} = ${captured[0]} + ${captured[1]} = ${parseInt($[1]) + parseInt($[2])}`"
}
}
then, given:
example.js
const sum = "4+5"
when linting with fix, the result will be:
const sum = "4+5 = 4 + 5 = 9"
As the body of the function is "simple", i.e. the return
is found at the beginning of the body of the function, and besides, the word return is not present, then the definition could be done as:
{
"id": "regexIdN",
"regex": "(\\d+)\\+(\\d+)",
"replacement": {
"function": "text + ' = ' + $[1] + ' + ' + $[2] + ' = ' + (parseInt($[1]) + parseInt($[2]))"
}
}
or :
{
"id": "regexIdN",
"regex": "(\\d+)\\+(\\d+)",
"replacement": {
"function": "`${text} = ${captured[0]} + ${captured[1]} = ${parseInt($[1]) + parseInt($[2])}`"
}
}
e.g. return
required
e.g. const result = text === 'superb' ? 'Superb' : text; return result
=> only the body of the function + returns a string
value based on text
.
Since the return
is not found at the beginning of the body of the function, return
cannot be omitted, then rule definition will be as usual:
{
"id": "regexIdN",
"regex": "\\w+",
"replacement": {
"function": "const result = text === 'superb' ? 'Superb' : text; return result"
}
}
Some cases may use Comma operator, e.g.
"function": "result = text === 'superb' ? 'Superb' : text, result"
e.g. return text === 'return' ? 'Return' : text
=> only the body of the function + returns a string
value based on text
.
Since the exact word return is present, this will required return
, then rule definition will be as usual:
{
"id": "regexIdN",
"regex": "\\w+",
"replacement": {
"function": "return text === 'return' ? 'Return' : text"
}
}
Following case does not required return
:
e.g. return text === 'Return' ? 'RETURN' : text
=> only the body of the function + returns a string
value based on text
.
Since the exact word return is not present, this will allow the following rule definition to be:
{
"id": "regexIdN",
"regex": "\\w+",
"replacement": {
"function": "text === 'Return' ? 'RETURN' : text"
}
}
Debugging of the Replacement Function for invalid found pattern
- It is possible to add
console
statements to print some information in the Replacement Function.
{
regex: '\\serror(\\w*)\\s',
replacement: {
function: 'const extract = captured[0]; console.log(extract); return extract'
}
}
Mixing definitions
It is possible to use both type of definitions, 'Short pattern definition' with 'Detailed pattern definition', in the array of patterns.
.eslintrc.json
:
{
"plugins": [
"regex"
],
"rules": {
"regex/invalid": [
"error", [
"invalidRegex1",
"invalidRegex2",
{
"regex": "invalidRegex3",
"message": "errorMessage1",
"files": {
"inspect": "inspectFilesRegex1"
}
},
{
"id": "regexIdN",
"regex": "invalidRegexN",
"files": {
"ignore": "ignoreFilesRegexN"
}
}
]
]
}
}
invalidRegex1
andinvalidRegex2
are 'Short pattern definition'.invalidRegex3
andinvalidRegexN
are 'Detailed pattern definition'.
String to Regular expression conversion
Internally, each string from the array will be converted into a Regular Expression with global
and multiline
options, e.g.:
"someRegex"
will be transformed into /someRegex/gm
Remember that backslash needs to be double in strings of a json file, e.g. To get the following regex
/\bhttp:/
define the following string"\\bhttp:"
.
Error report
The 'Short pattern definition' errors are reported with the following structure:
Given someRegex
, the following message will be shown on error:
Invalid regular expression /someRegex/gm found
or
Required regular expression /someRegex/gm not found in file
The 'Detailed pattern definition' errors are reported with the following rules:
A . If message
is present then that exact message is reported.
B . If id
is present then:
Given "id": "someRegexId"
, the following message will be shown on error:
Invalid regular expression 'someRegexId' found
or
Required regular expression 'someRegexId' not found in file
C . If neither message
nor id
is present then the 'Short pattern definition' error message is shown.
message
takes precedence overid
.- Although
id
is a quick solution (and useful when creating and testing a rule), usingmessage
will give more information to the team about the issue.
vs regex/invalidregex/required
Both rule were design with binary approach:
regex/invalid
: pattern is not present => any presence of the specific pattern in a file is invalid.regex/required
: pattern is present => only 1 presence of the specific pattern in a file is required.
Array of patterns represent different logical operation for each rule:
regex/invalid
: OR => the presence in a file of any of the patterns defined in the array is invalid.regex/required
: AND => the presence in file of all of the patterns defined in the array is required.
Examples
Check:
- invalid-regex Basic rule tests
- invalid-regex Detailed rule tests
- required-regex Basic rule tests
- required-regex Detailed rule tests
- The set of Regex Rules of
eslint-plugin-base-style-config
Prerequisites
Extending/Developing
Contributing
- Use it.
- Share it.
- Give it a Star.
- Propose changes or improvements.
- Report bugs.
Documentation
CHANGELOG.md
: contains the information about changes in each version, chronologically ordered (Keep a Changelog).
License
Remember
- Use code style verification tools => Encourages Best Practices, Efficiency, Readability and Learnability.
- Code Review everything => Encourages Functional suitability, Performance Efficiency and Teamwork.
- If viable, Start testing early => Encourages Reliability and Maintainability.
Additional words
Don't forget:
- Love what you do.
- Learn everyday.
- Learn yourself.
- Share your knowledge.
- Think different!.
- Learn from the past, dream on the future, live and enjoy the present to the max!.
- Enjoy and Value the Quest (It's where you learn and grow).
At life:
- Let's act, not complain.
- Be flexible.
At work:
- Let's give solutions, not questions.
- Aim to simplicity not intellectualism.