Skip to content

Commit d320e11

Browse files
committed
## 1.3.0 - January 2021
* Adds replacements for invalid patterns. * Improves code coverage. * Improves documentation. * Improves project configuration.
1 parent 0f724d0 commit d320e11

13 files changed

+175
-50
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# ESLint Plugin Regex Change Log
22

3+
## 1.3.0 - January 2021
4+
5+
* Adds replacements for invalid patterns.
6+
* Improves code coverage.
7+
* Improves documentation.
8+
* Improves project configuration.
9+
310
## 1.2.1 - August 2020
411

512
* Fixes #4 peerDependencies.

README.md

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ Detailed configuration:
7070
"error", [{
7171
"regex": "invalidRegex1",
7272
"message": "errorMessage1",
73+
"replacement": "newValue"
7374
}, {
7475
"id": "regexIdN",
7576
"regex": "invalidRegexN",
@@ -108,10 +109,10 @@ The idea is to allow to create different eslint rules based on Regular Expressio
108109

109110
## Rules
110111

111-
Two rules are defined:
112-
113-
* [`regex/invalid`](docs/rules/invalid-regex-rule.md).
114-
* [`regex/required`](docs/rules/required-regex-rule.md).
112+
Name | Fixable | Description
113+
----------------------------------------------------- | ------- | -----------
114+
[`regex/invalid`](docs/rules/invalid-regex-rule.md) | Yes | checks that specified patterns are not found
115+
[`regex/required`](docs/rules/required-regex-rule.md) | No | checks that specified patterns are found
115116

116117
### `regex/invalid`
117118

@@ -209,10 +210,11 @@ It is specified by just a regular expression `string`, i.e. `"regex"`
209210

210211
It is specified by an `object`, with the following fields:
211212

212-
* `id`: A `string` representing the **Pattern Id**.
213-
* `regex`: A `string` representing the **Regular expression to look for**.
214-
* `message`: A `string` specifying the **Message to be shown when an error happens** (invalid `regex` is found or required `regex` is not found).
215-
* `files`: An `object` specifying which files to analyze:
213+
* `regex`: A **required** `string` representing the **Regular expression to look for**.
214+
* `replacement`: If present this `string` will use to replace **invalid** found pattern.
215+
* `id`: An optional `string` representing the **Pattern Id**.
216+
* `message`: An optional `string` specifying the **Message to be shown when an error happens** (invalid `regex` is found or required `regex` is not found).
217+
* `files`: An optional `object` specifying which files to analyze:
216218
* `ignore`: A `string` representing **Regular expression of the files to be ignored** when validating this specific pattern.
217219
* `inspect`: A `string` representing **Regular expression of the files to be inspected** when validating this specific pattern.
218220

@@ -228,8 +230,10 @@ It is specified by an `object`, with the following fields:
228230
}
229231
```
230232

231-
> * `regex` is the only Required field. 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).
232-
> * When `ignore` and `inspect` are present, `ignore` takes precedence.
233+
> * `regex` is the only Required field. Slashes (`/`) are not required in the string, e.g. To get the following regex `/\bhttp:/`:
234+
> * when using `.eslintrc.js`, define the following string `"\bhttp:"`, or
235+
> * when using `.eslintrc.json`, define `"\\bhttp:"` (backslash needs to de double in a json file).
236+
> * When `ignore` and `inspect` are present, `ignore` takes precedence.
233237
> * Global ignore file pattern, takes precedence over `files` patterns.
234238

235239
#### Mixing definitions
@@ -329,6 +333,16 @@ Array of patterns represent different logical operation for each rule:
329333
* `regex/invalid`: **OR** => the presence in a file of *any* of the patterns defined in the *array* is invalid.
330334
* `regex/required`: **AND** => the presence in file of *all* of the patterns defined in the *array* is required.
331335

336+
### Examples
337+
338+
[For a set of Regex Rules examples check `eslint-plugin-base-style-config`](https://github.com/gmullerb/base-style-config/tree/master/js#regex-rules)
339+
340+
__________________
341+
342+
## Prerequisites
343+
344+
* [`"eslint": ">=4.0.0"`](https://www.npmjs.com/package/eslint).
345+
332346
__________________
333347

334348
## Extending/Developing

docs/rules/invalid-regex-rule.md

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,18 @@ It is specified by just a regular expression `string`, i.e. `"regex"`
5656

5757
It is specified by an `object`, with the following fields:
5858

59-
* `id`: A `string` representing the **Pattern Id**.
60-
* `regex`: A `string` representing the **Regular expression to look for**.
61-
* `message`: A `string` specifying the **Message to be shown when an error happens** (invalid `regex` is found or required `regex` is not found).
62-
* `files`: An `object` specifying which files to analyze:
59+
* `regex`: A **required** `string` representing the **Regular expression to look for**.
60+
* `replacement`: An optional `string` used to replace invalid found pattern.
61+
* `id`: An optional `string` representing the **Pattern Id**.
62+
* `message`: An optional `string` specifying the **Message to be shown when an invalid `regex` is found**.
63+
* `files`: An optional `object` specifying which files to analyze:
6364
* `ignore`: A `string` representing **Regular expression of the files to be ignored** when validating this specific pattern.
6465
* `inspect`: A `string` representing **Regular expression of the files to be inspected** when validating this specific pattern.
6566

66-
> * `regex` is the only Required field. 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).
67-
> * When `ignore` and `inspect` are present, `ignore` takes precedence.
67+
> * `regex` is the only Required field. Slashes (`/`) are not required in the string, e.g. To get the following regex `/\bhttp:/`:
68+
> * when using `.eslintrc.js`, define the following string `"\bhttp:"`, or
69+
> * when using `.eslintrc.json`, define `"\\bhttp:"` (backslash needs to de double in a json file).
70+
> * When `ignore` and `inspect` are present, `ignore` takes precedence.
6871
> * Global ignore file pattern, takes precedence over `files` patterns.
6972
7073
`.eslintrc.json`:
@@ -79,6 +82,7 @@ It is specified by an `object`, with the following fields:
7982
"error", [{
8083
"regex": "invalidRegex1",
8184
"message": "errorMessage1",
85+
"replacement": "newValue"
8286
}, {
8387
"id": "regexIdN",
8488
"regex": "invalidRegexN",
@@ -98,13 +102,7 @@ Internally, each string from the array will be converted into a Regular Expressi
98102

99103
`"invalidRegex1"` will be transformed into `/invalidRegex1/gm`
100104

101-
When the pattern is found splitting in more the one line the error message will not reflect the location (i.e. `1:1` will be shown), e.g.:
102-
103-
```bash
104-
1:1 error Invalid regular expression /invalidRegex1/gm found in file regex/invalid
105-
```
106-
107-
When the pattern is found inside an specific line the error message will reflect the exact location, e.g.:
105+
When the pattern is found, the error message will reflect the exact location, e.g.:
108106

109107
```bash
110108
34:25 error Invalid regular expression /invalidRegex1/gm found regex/invalid
@@ -116,4 +114,5 @@ When the pattern is found inside an specific line the error message will reflect
116114

117115
## More information
118116

119-
[Back](../README.md)
117+
* [`eslint-plugin-regex`](../README.md)
118+
* [For a set of Regex Rules examples check `eslint-plugin-base-style-config`](https://github.com/gmullerb/base-style-config/tree/master/js#regex-rules)

docs/rules/required-regex-rule.md

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,17 @@ It is specified by just a regular expression `string`, i.e. `"regex"`
5757

5858
It is specified by an `object`, with the following fields:
5959

60-
* `id`: A `string` representing the **Pattern Id**.
61-
* `regex`: A `string` representing the **Regular expression to look for**.
62-
* `message`: A `string` specifying the **Message to be shown when an error happens** (invalid `regex` is found or required `regex` is not found).
63-
* `files`: An `object` specifying which files to analyze:
60+
* `regex`: A **required** `string` representing the **Regular expression to look for**.
61+
* `id`: An optional `string` representing the **Pattern Id**.
62+
* `message`: An optional `string` specifying the **Message to be shown when a required `regex` is not found**.
63+
* `files`: An optional `object` specifying which files to analyze:
6464
* `ignore`: A `string` representing **Regular expression of the files to be ignored** when validating this specific pattern.
6565
* `inspect`: A `string` representing **Regular expression of the files to be inspected** when validating this specific pattern.
6666

67-
> * `regex` is the only Required field. 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).
68-
> * When `ignore` and `inspect` are present, `ignore` takes precedence.
67+
> * `regex` is the only Required field. Slashes (`/`) are not required in the string, e.g. To get the following regex `/\bhttp:/`:
68+
> * when using `.eslintrc.js`, define the following string `"\bhttp:"`, or
69+
> * when using `.eslintrc.json`, define `"\\bhttp:"` (backslash needs to de double in a json file).
70+
> * When `ignore` and `inspect` are present, `ignore` takes precedence.
6971
> * Global ignore file pattern, takes precedence over `files` patterns.
7072
7173
`.eslintrc.json`:
@@ -109,4 +111,5 @@ Internally, each string from the array will be converted into a Regular Expressi
109111

110112
## More information
111113

112-
[Back](../README.md)
114+
* [`eslint-plugin-regex`](../README.md)
115+
* [For a set of Regex Rules examples check `eslint-plugin-base-style-config`](https://github.com/gmullerb/base-style-config/tree/master/js#regex-rules)

lib/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
module.exports = {
66
rules: {
7-
invalid: require('../lib/rules/invalid-regex-rule.js'),
8-
required: require('../lib/rules/required-regex-rule.js')
7+
invalid: require('./rules/invalid-regex-rule.js'),
8+
required: require('./rules/required-regex-rule.js')
99
}
1010
}

lib/rules/invalid-regex-rule.js

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,20 @@ function checkRegexInLines(sourceLines, nextLine, nextChar, regex) {
3131
}
3232
}
3333

34+
function checkRegexInSource(source, regex) {
35+
regex.test('')
36+
const foundDetail = regex.exec(source)
37+
return !!foundDetail
38+
? {
39+
patternIndex: foundDetail.index,
40+
nextChar: regex.lastIndex
41+
}
42+
: {
43+
patternIndex: -1,
44+
nextChar: -1
45+
}
46+
}
47+
3448
function foundStart(source, nextLine, foundAt) {
3549
return Array.from(source.substring(0, foundAt))
3650
.reduce((result, char) => char === '\n'
@@ -39,11 +53,12 @@ function foundStart(source, nextLine, foundAt) {
3953
{ line: nextLine, column: 0 })
4054
}
4155

42-
function checkRegex(source, sourceLines, nextLine, nextChar, pattern, report, node) {
56+
function checkRegex(source, sourceLines, nextLine, nextChar, rootChar, pattern, replace, report) {
4357
if (source.length !== 0) {
44-
const patternIndex = source.search(pattern.regex)
45-
if (patternIndex !== -1) {
46-
const remainingSource = source.slice(patternIndex + 1)
58+
const sourceDetail = checkRegexInSource(source, pattern.regex)
59+
if (sourceDetail.patternIndex !== -1) {
60+
const remainingSourceStart = sourceDetail.patternIndex + 1
61+
const remainingSource = source.slice(remainingSourceStart)
4762
let foundDetail = checkRegexInLines(sourceLines, nextLine, nextChar, pattern.regex)
4863
if (foundDetail.nextLine !== -1) {
4964
report({
@@ -56,43 +71,51 @@ function checkRegex(source, sourceLines, nextLine, nextChar, pattern, report, no
5671
message: formatReportMessage(
5772
pattern,
5873
from => `Invalid regular expression ${from} found`
59-
)
74+
),
75+
fix: replace(rootChar, sourceDetail.patternIndex, sourceDetail.nextChar)
6076
})
61-
checkRegex(remainingSource, sourceLines, foundDetail.nextLine, foundDetail.nextChar, pattern, report, node)
77+
checkRegex(remainingSource, sourceLines, foundDetail.nextLine, foundDetail.nextChar, rootChar + remainingSourceStart,
78+
pattern, replace, report)
6279
}
6380
else {
6481
report({
65-
loc: { start: foundStart(source, nextLine + 1, patternIndex) },
82+
loc: { start: foundStart(source, nextLine + 1, sourceDetail.patternIndex) },
6683
message: formatReportMessage(
6784
pattern,
6885
from => `Invalid regular expression ${from} found`
69-
)
86+
),
87+
fix: replace(rootChar, sourceDetail.patternIndex, sourceDetail.nextChar)
7088
})
71-
checkRegex(remainingSource, sourceLines, nextLine + 1, nextChar, pattern, report, node)
89+
checkRegex(remainingSource, sourceLines, nextLine + 1, nextChar, rootChar + remainingSourceStart, pattern, replace, report)
7290
}
7391
}
7492
}
7593
}
7694

77-
function checkPatterns(fileName, source, patterns, report, node) {
95+
function checkPatterns(fileName, source, patterns, report) {
7896
const sourceLines = source.split('\n')
7997
patterns.forEach(pattern => shouldCheck(pattern.details, fileName) && checkRegex(
8098
source,
8199
sourceLines,
82100
0,
83101
0,
102+
0,
84103
pattern,
85-
report,
86-
node
104+
typeof pattern.details.replacement === 'string'
105+
? (from, deltaStart, deltaEnd) => fixer => fixer.replaceTextRange([from + deltaStart, from + deltaEnd], pattern.details.replacement)
106+
: () => undefined,
107+
report
87108
))
88109
}
89110

90111
module.exports = {
91112
meta: {
92113
type: 'suggestion',
114+
fixable: 'code',
93115
docs: {
94116
description: 'Invalid regular expressions to be reported',
95117
category: 'Stylistic Issues',
118+
url: 'https://github.com/gmullerb/eslint-plugin-regex/blob/master/docs/rules/invalid-regex-rule.md'
96119
},
97120
schema: [{
98121
title: 'Invalid regular expressions',
@@ -121,6 +144,11 @@ module.exports = {
121144
type: 'string',
122145
minLength: 1
123146
},
147+
replacement: {
148+
title: 'Replacement',
149+
description: 'Replacement for invalid pattern',
150+
type: 'string'
151+
},
124152
message: {
125153
title: 'Invalid message',
126154
description: 'Message to be shown when Invalid pattern is found',

lib/rules/required-regex-rule.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ module.exports = {
2424
docs: {
2525
description: 'Required regular expressions to be looked',
2626
category: 'Stylistic Issues',
27+
url: 'https://github.com/gmullerb/eslint-plugin-regex/blob/master/docs/rules/required-regex-rule.md'
2728
},
2829
schema: [{
2930
title: 'Required regular expressions',

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "eslint-plugin-regex",
33
"description": "ESLint rules using Regular Expression",
4-
"version": "1.2.1",
4+
"version": "1.3.0",
55
"license": "MIT",
66
"author": "Gonzalo Müller Bravo",
77
"main": "lib/index.js",
@@ -73,7 +73,8 @@
7373
"test": "echo ==== Test With Coverage ==== && mkdir -p build && nyc npm run test.only",
7474
"prepack": "echo ==== Build Package ====",
7575
"check": "npm install && npm run lint && npm test && mkdir -p build && cd build && npm pack ../",
76-
"check.all": "npm run check && npm audit"
76+
"check.all": "npm run check && npm audit",
77+
"prepublishOnly": "npm run check"
7778
},
7879
"peerDependencies": {
7980
"eslint": ">=4.0.0"

tests/lib/rules/e2e-tests.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// Copyright (c) 2020 Gonzalo Müller Bravo.
2+
// Licensed under the MIT License (MIT), see LICENSE.txt
13
require('./invalid-regex-rule.e2e-test')
24
require('./required-regex-rule.e2e-test')
35
require('./invalid-regex-detailed-rule.e2e-test')

0 commit comments

Comments
 (0)