eslint-plugin-pet-peeves 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +43 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/rules/max-operands.d.ts +4 -0
- package/dist/rules/max-operands.d.ts.map +1 -0
- package/dist/rules/max-operands.js +41 -0
- package/dist/rules/max-operands.js.map +1 -0
- package/dist/rules/max-same-operator-operands.d.ts +4 -0
- package/dist/rules/max-same-operator-operands.d.ts.map +1 -0
- package/dist/rules/max-same-operator-operands.js +45 -0
- package/dist/rules/max-same-operator-operands.js.map +1 -0
- package/dist/rules/shared.d.ts +26 -0
- package/dist/rules/shared.d.ts.map +1 -0
- package/dist/rules/shared.js +22 -0
- package/dist/rules/shared.js.map +1 -0
- package/docs/rules/max-operands.md +33 -0
- package/docs/rules/max-same-operator-operands.md +40 -0
- package/package.json +58 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Joona Kettunen
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# eslint-plugin-pet-peeves
|
|
2
|
+
|
|
3
|
+
A small ESLint plugin for opinionated readability rules.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install --save-dev eslint-plugin-pet-peeves
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Add the plugin and whichever rules you want to an ESLint flat configuration:
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
import petPeeves from "eslint-plugin-pet-peeves";
|
|
15
|
+
|
|
16
|
+
export default [
|
|
17
|
+
{
|
|
18
|
+
plugins: {
|
|
19
|
+
"pet-peeves": petPeeves,
|
|
20
|
+
},
|
|
21
|
+
rules: {
|
|
22
|
+
"pet-peeves/max-operands": ["error", { max: 8 }],
|
|
23
|
+
"pet-peeves/max-same-operator-operands": ["error", { max: 4 }],
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
];
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Rules
|
|
30
|
+
|
|
31
|
+
- [`max-operands`](docs/rules/max-operands.md) limits all operands in a connected logical expression.
|
|
32
|
+
- [`max-same-operator-operands`](docs/rules/max-same-operator-operands.md) limits operands in each same-operator logical chain.
|
|
33
|
+
|
|
34
|
+
Both rules support `&&`, `||`, and `??`.
|
|
35
|
+
|
|
36
|
+
## Development
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
npm install
|
|
40
|
+
npm test
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`npm run build` compiles the TypeScript source to JavaScript and declarations in `dist`.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const rules: {
|
|
2
|
+
"max-operands": import("eslint").Rule.RuleModule;
|
|
3
|
+
"max-same-operator-operands": import("eslint").Rule.RuleModule;
|
|
4
|
+
};
|
|
5
|
+
declare const plugin: {
|
|
6
|
+
meta: {
|
|
7
|
+
name: string;
|
|
8
|
+
version: string;
|
|
9
|
+
};
|
|
10
|
+
rules: {
|
|
11
|
+
"max-operands": import("eslint").Rule.RuleModule;
|
|
12
|
+
"max-same-operator-operands": import("eslint").Rule.RuleModule;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
export default plugin;
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,KAAK;;;CAGjB,CAAC;AAEF,QAAA,MAAM,MAAM;;;;;;;;;CAMX,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import maxOperands from "./rules/max-operands.js";
|
|
2
|
+
import maxSameOperatorOperands from "./rules/max-same-operator-operands.js";
|
|
3
|
+
export const rules = {
|
|
4
|
+
"max-operands": maxOperands,
|
|
5
|
+
"max-same-operator-operands": maxSameOperatorOperands,
|
|
6
|
+
};
|
|
7
|
+
const plugin = {
|
|
8
|
+
meta: {
|
|
9
|
+
name: "eslint-plugin-pet-peeves",
|
|
10
|
+
version: "0.1.0",
|
|
11
|
+
},
|
|
12
|
+
rules,
|
|
13
|
+
};
|
|
14
|
+
export default plugin;
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,yBAAyB,CAAC;AAClD,OAAO,uBAAuB,MAAM,uCAAuC,CAAC;AAE5E,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,cAAc,EAAE,WAAW;IAC3B,4BAA4B,EAAE,uBAAuB;CACtD,CAAC;AAEF,MAAM,MAAM,GAAG;IACb,IAAI,EAAE;QACJ,IAAI,EAAE,0BAA0B;QAChC,OAAO,EAAE,OAAO;KACjB;IACD,KAAK;CACN,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"max-operands.d.ts","sourceRoot":"","sources":["../../src/rules/max-operands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAiBnC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UAqChB,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { getMax, isLogicalExpression, maxOptionSchema, } from "./shared.js";
|
|
2
|
+
function countOperands(node) {
|
|
3
|
+
if (!isLogicalExpression(node)) {
|
|
4
|
+
return 1;
|
|
5
|
+
}
|
|
6
|
+
return countOperands(node.left) + countOperands(node.right);
|
|
7
|
+
}
|
|
8
|
+
const rule = {
|
|
9
|
+
meta: {
|
|
10
|
+
type: "suggestion",
|
|
11
|
+
docs: {
|
|
12
|
+
description: "Limit the total number of operands in a logical expression.",
|
|
13
|
+
recommended: false,
|
|
14
|
+
url: "https://github.com/joonarafael/eslint-plugin-pet-peeves/blob/master/docs/rules/max-operands.md",
|
|
15
|
+
},
|
|
16
|
+
schema: maxOptionSchema,
|
|
17
|
+
messages: {
|
|
18
|
+
tooManyOperands: "This logical expression has {{count}} operands. The maximum allowed is {{max}}.",
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
create(context) {
|
|
22
|
+
const max = getMax(context.options);
|
|
23
|
+
return {
|
|
24
|
+
LogicalExpression(node) {
|
|
25
|
+
if (isLogicalExpression(node.parent)) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const count = countOperands(node);
|
|
29
|
+
if (count > max) {
|
|
30
|
+
context.report({
|
|
31
|
+
node,
|
|
32
|
+
messageId: "tooManyOperands",
|
|
33
|
+
data: { count, max },
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
export default rule;
|
|
41
|
+
//# sourceMappingURL=max-operands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"max-operands.js","sourceRoot":"","sources":["../../src/rules/max-operands.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,MAAM,EACN,mBAAmB,EACnB,eAAe,GAEhB,MAAM,aAAa,CAAC;AAErB,SAAS,aAAa,CAAC,IAAe;IACpC,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,CAAC;IACX,CAAC;IAED,OAAO,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,IAAI,GAAoB;IAC5B,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE;YACJ,WAAW,EACT,6DAA6D;YAC/D,WAAW,EAAE,KAAK;YAClB,GAAG,EAAE,gGAAgG;SACtG;QACD,MAAM,EAAE,eAAe;QACvB,QAAQ,EAAE;YACR,eAAe,EACb,iFAAiF;SACpF;KACF;IAED,MAAM,CAAC,OAAO;QACZ,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,OAAkB,CAAC,CAAC;QAE/C,OAAO;YACL,iBAAiB,CAAC,IAAI;gBACpB,IAAI,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;oBACrC,OAAO;gBACT,CAAC;gBAED,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;gBAElC,IAAI,KAAK,GAAG,GAAG,EAAE,CAAC;oBAChB,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI;wBACJ,SAAS,EAAE,iBAAiB;wBAC5B,IAAI,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE;qBACrB,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"max-same-operator-operands.d.ts","sourceRoot":"","sources":["../../src/rules/max-same-operator-operands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAwBnC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UA8ChB,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { getMax, isLogicalExpression, maxOptionSchema, } from "./shared.js";
|
|
2
|
+
function countSameOperatorOperands(node, operator) {
|
|
3
|
+
if (!isLogicalExpression(node) || node.operator !== operator) {
|
|
4
|
+
return 1;
|
|
5
|
+
}
|
|
6
|
+
return (countSameOperatorOperands(node.left, operator) +
|
|
7
|
+
countSameOperatorOperands(node.right, operator));
|
|
8
|
+
}
|
|
9
|
+
const rule = {
|
|
10
|
+
meta: {
|
|
11
|
+
type: "suggestion",
|
|
12
|
+
docs: {
|
|
13
|
+
description: "Limit the number of operands in a same-operator logical chain.",
|
|
14
|
+
recommended: false,
|
|
15
|
+
url: "https://github.com/joonarafael/eslint-plugin-pet-peeves/blob/master/docs/rules/max-same-operator-operands.md",
|
|
16
|
+
},
|
|
17
|
+
schema: maxOptionSchema,
|
|
18
|
+
messages: {
|
|
19
|
+
tooManyOperands: "This '{{operator}}' chain has {{count}} operands. The maximum allowed is {{max}}.",
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
create(context) {
|
|
23
|
+
const max = getMax(context.options);
|
|
24
|
+
return {
|
|
25
|
+
LogicalExpression(node) {
|
|
26
|
+
const expression = node;
|
|
27
|
+
const parent = expression.parent;
|
|
28
|
+
if (isLogicalExpression(parent) &&
|
|
29
|
+
parent.operator === expression.operator) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const count = countSameOperatorOperands(expression, expression.operator);
|
|
33
|
+
if (count > max) {
|
|
34
|
+
context.report({
|
|
35
|
+
node: expression,
|
|
36
|
+
messageId: "tooManyOperands",
|
|
37
|
+
data: { count, max, operator: expression.operator },
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
export default rule;
|
|
45
|
+
//# sourceMappingURL=max-same-operator-operands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"max-same-operator-operands.js","sourceRoot":"","sources":["../../src/rules/max-same-operator-operands.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,MAAM,EACN,mBAAmB,EACnB,eAAe,GAGhB,MAAM,aAAa,CAAC;AAErB,SAAS,yBAAyB,CAChC,IAAe,EACf,QAAuC;IAEvC,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC7D,OAAO,CAAC,CAAC;IACX,CAAC;IAED,OAAO,CACL,yBAAyB,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC;QAC9C,yBAAyB,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,CAChD,CAAC;AACJ,CAAC;AAED,MAAM,IAAI,GAAoB;IAC5B,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE;YACJ,WAAW,EACT,gEAAgE;YAClE,WAAW,EAAE,KAAK;YAClB,GAAG,EAAE,8GAA8G;SACpH;QACD,MAAM,EAAE,eAAe;QACvB,QAAQ,EAAE;YACR,eAAe,EACb,mFAAmF;SACtF;KACF;IAED,MAAM,CAAC,OAAO;QACZ,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,OAAkB,CAAC,CAAC;QAE/C,OAAO;YACL,iBAAiB,CAAC,IAAI;gBACpB,MAAM,UAAU,GAAG,IAAyB,CAAC;gBAC7C,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;gBAEjC,IACE,mBAAmB,CAAC,MAAM,CAAC;oBAC3B,MAAM,CAAC,QAAQ,KAAK,UAAU,CAAC,QAAQ,EACvC,CAAC;oBACD,OAAO;gBACT,CAAC;gBAED,MAAM,KAAK,GAAG,yBAAyB,CACrC,UAAU,EACV,UAAU,CAAC,QAAQ,CACpB,CAAC;gBAEF,IAAI,KAAK,GAAG,GAAG,EAAE,CAAC;oBAChB,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI,EAAE,UAAU;wBAChB,SAAS,EAAE,iBAAiB;wBAC5B,IAAI,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,UAAU,CAAC,QAAQ,EAAE;qBACpD,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Rule } from "eslint";
|
|
2
|
+
export declare const DEFAULT_MAX = 4;
|
|
3
|
+
export type Options = [{
|
|
4
|
+
max: number;
|
|
5
|
+
}?];
|
|
6
|
+
export type LogicalExpression = Rule.Node & {
|
|
7
|
+
type: "LogicalExpression";
|
|
8
|
+
operator: "&&" | "||" | "??";
|
|
9
|
+
left: Rule.Node;
|
|
10
|
+
right: Rule.Node;
|
|
11
|
+
};
|
|
12
|
+
export declare const maxOptionSchema: readonly [{
|
|
13
|
+
readonly type: "object";
|
|
14
|
+
readonly properties: {
|
|
15
|
+
readonly max: {
|
|
16
|
+
readonly type: "integer";
|
|
17
|
+
readonly minimum: 0;
|
|
18
|
+
readonly maximum: 100;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
readonly required: readonly ["max"];
|
|
22
|
+
readonly additionalProperties: false;
|
|
23
|
+
}];
|
|
24
|
+
export declare function isLogicalExpression(node: Rule.Node | null | undefined): node is LogicalExpression;
|
|
25
|
+
export declare function getMax(options: Options): number;
|
|
26
|
+
//# sourceMappingURL=shared.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/rules/shared.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAEnC,eAAO,MAAM,WAAW,IAAI,CAAC;AAE7B,MAAM,MAAM,OAAO,GAAG,CAAC;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAAC;AAEzC,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,GAAG;IAC1C,IAAI,EAAE,mBAAmB,CAAC;IAC1B,QAAQ,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC7B,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC;IAChB,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC;CAClB,CAAC;AAEF,eAAO,MAAM,eAAe;;;;;;;;;;;EAalB,CAAC;AAEX,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,IAAI,CAAC,IAAI,GAAG,IAAI,GAAG,SAAS,GACjC,IAAI,IAAI,iBAAiB,CAE3B;AAED,wBAAgB,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAE/C"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export const DEFAULT_MAX = 4;
|
|
2
|
+
export const maxOptionSchema = [
|
|
3
|
+
{
|
|
4
|
+
type: "object",
|
|
5
|
+
properties: {
|
|
6
|
+
max: {
|
|
7
|
+
type: "integer",
|
|
8
|
+
minimum: 0,
|
|
9
|
+
maximum: 100,
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
required: ["max"],
|
|
13
|
+
additionalProperties: false,
|
|
14
|
+
},
|
|
15
|
+
];
|
|
16
|
+
export function isLogicalExpression(node) {
|
|
17
|
+
return node?.type === "LogicalExpression";
|
|
18
|
+
}
|
|
19
|
+
export function getMax(options) {
|
|
20
|
+
return options[0]?.max ?? DEFAULT_MAX;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=shared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/rules/shared.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC;AAW7B,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B;QACE,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,GAAG,EAAE;gBACH,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,CAAC;gBACV,OAAO,EAAE,GAAG;aACb;SACF;QACD,QAAQ,EAAE,CAAC,KAAK,CAAC;QACjB,oBAAoB,EAAE,KAAK;KAC5B;CACO,CAAC;AAEX,MAAM,UAAU,mBAAmB,CACjC,IAAkC;IAElC,OAAO,IAAI,EAAE,IAAI,KAAK,mBAAmB,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,OAAgB;IACrC,OAAO,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,WAAW,CAAC;AACxC,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Limit total logical operands (`max-operands`)
|
|
2
|
+
|
|
3
|
+
Limits the total number of operands in a connected logical expression. The rule counts operands joined by `&&`, `||`, and `??`, including expressions that mix those operators.
|
|
4
|
+
|
|
5
|
+
Parentheses do not reset the count. Logical expressions nested inside a non-logical operand, such as a function call, are checked separately.
|
|
6
|
+
|
|
7
|
+
## Options
|
|
8
|
+
|
|
9
|
+
The rule accepts an object with a `max` property:
|
|
10
|
+
|
|
11
|
+
```js
|
|
12
|
+
{
|
|
13
|
+
"pet-peeves/max-operands": ["error", { max: 4 }]
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`max` must be an integer from `0` through `100`. It defaults to `4` when the option is omitted.
|
|
18
|
+
|
|
19
|
+
With `{ max: 4 }`, these examples are valid:
|
|
20
|
+
|
|
21
|
+
```js
|
|
22
|
+
a && b && c && d;
|
|
23
|
+
(a && b) || (c ?? d);
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
These examples are invalid:
|
|
27
|
+
|
|
28
|
+
```js
|
|
29
|
+
a && b && c && d && e;
|
|
30
|
+
(a && b && c) || (d && e) || f;
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The rule reports the complete offending logical expression and does not provide an automatic fix.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Limit same-operator logical operands (`max-same-operator-operands`)
|
|
2
|
+
|
|
3
|
+
Limits the number of operands in each maximal `&&`, `||`, or `??` chain. Different logical operators begin separate chains, while the expression using them can still be an operand in the surrounding chain.
|
|
4
|
+
|
|
5
|
+
For example, this expression has a three-operand `||` chain, a three-operand `&&` chain, and a two-operand `&&` chain:
|
|
6
|
+
|
|
7
|
+
```js
|
|
8
|
+
(a && b && c) || (d && e) || f;
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Parentheses do not break a same-operator chain.
|
|
12
|
+
|
|
13
|
+
## Options
|
|
14
|
+
|
|
15
|
+
The rule accepts an object with a `max` property:
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
{
|
|
19
|
+
"pet-peeves/max-same-operator-operands": ["error", { max: 4 }]
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`max` must be an integer from `0` through `100`. It defaults to `4` when the option is omitted.
|
|
24
|
+
|
|
25
|
+
With `{ max: 3 }`, these examples are valid:
|
|
26
|
+
|
|
27
|
+
```js
|
|
28
|
+
a && b && c;
|
|
29
|
+
(a && b) || (c && d);
|
|
30
|
+
(a ?? b) || (c ?? d);
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
These examples are invalid:
|
|
34
|
+
|
|
35
|
+
```js
|
|
36
|
+
a && b && c && d;
|
|
37
|
+
a || b || c || d;
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The rule reports each complete offending chain and does not provide an automatic fix.
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "eslint-plugin-pet-peeves",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Opinionated ESLint rules for keeping JavaScript expressions readable.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"docs"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsc -p tsconfig.json",
|
|
20
|
+
"typecheck": "tsc -p tsconfig.tests.json",
|
|
21
|
+
"test": "npm run build && npm run typecheck && tsx --test tests/*.test.ts",
|
|
22
|
+
"lint": "eslint .",
|
|
23
|
+
"lint:fix": "eslint . --fix",
|
|
24
|
+
"format": "prettier --write .",
|
|
25
|
+
"format:check": "prettier --check .",
|
|
26
|
+
"prepack": "npm test"
|
|
27
|
+
},
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"eslint": "^9.0.0 || ^10.0.0"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/node": "24.13.3",
|
|
33
|
+
"eslint": "10.10.0",
|
|
34
|
+
"eslint-config-prettier": "10.1.8",
|
|
35
|
+
"eslint-plugin-prettier": "5.5.6",
|
|
36
|
+
"prettier": "3.9.6",
|
|
37
|
+
"tsx": "4.23.13",
|
|
38
|
+
"typescript": "6.0.3",
|
|
39
|
+
"typescript-eslint": "8.69.0"
|
|
40
|
+
},
|
|
41
|
+
"keywords": [
|
|
42
|
+
"eslint",
|
|
43
|
+
"eslintplugin",
|
|
44
|
+
"eslint-plugin"
|
|
45
|
+
],
|
|
46
|
+
"repository": {
|
|
47
|
+
"type": "git",
|
|
48
|
+
"url": "git+https://github.com/joonarafael/eslint-plugin-pet-peeves.git"
|
|
49
|
+
},
|
|
50
|
+
"bugs": {
|
|
51
|
+
"url": "https://github.com/joonarafael/eslint-plugin-pet-peeves/issues"
|
|
52
|
+
},
|
|
53
|
+
"homepage": "https://github.com/joonarafael/eslint-plugin-pet-peeves#readme",
|
|
54
|
+
"license": "MIT",
|
|
55
|
+
"allowScripts": {
|
|
56
|
+
"esbuild@0.28.2": true
|
|
57
|
+
}
|
|
58
|
+
}
|