eslint-plugin-code-style 2.0.0 → 2.0.2

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.
@@ -1,448 +0,0 @@
1
- # Control Flow Rules
2
-
3
- ### `block-statement-newlines`
4
-
5
- **What it does:** Enforces newlines after the opening brace `{` and before the closing brace `}` in block statements (if, for, while, etc.).
6
-
7
- **Why use it:** Consistent block formatting improves readability. Single-line blocks are harder to scan and edit.
8
-
9
- ```javascript
10
- // Good — proper block formatting
11
- if (condition) {
12
- doSomething();
13
- }
14
-
15
- for (const item of items) {
16
- process(item);
17
- }
18
-
19
- while (running) {
20
- tick();
21
- }
22
-
23
- // Bad — everything on one line
24
- if (condition) { doSomething(); }
25
-
26
- // Bad — no space after brace
27
- if (condition) {doSomething();}
28
-
29
- // Bad — inconsistent formatting
30
- for (const item of items) { process(item);
31
- }
32
- ```
33
-
34
- ---
35
-
36
- ### `empty-line-after-block`
37
-
38
- **What it does:** Requires an empty line between a closing brace `}` of a block statement (if, try, for, while, etc.) and the next statement, unless the next statement is part of the same construct (else, catch, finally).
39
-
40
- **Why use it:** Visual separation between logical blocks improves code readability and makes the structure clearer.
41
-
42
- > **Note:** Consecutive if statements are handled by `if-else-spacing` rule.
43
-
44
- ```javascript
45
- // Good — empty line after block
46
- if (condition) {
47
- doSomething();
48
- }
49
-
50
- const x = 1;
51
-
52
- // Good — else is part of same construct (no empty line needed)
53
- if (condition) {
54
- doSomething();
55
- } else {
56
- doOther();
57
- }
58
-
59
- // Bad — no empty line after block
60
- if (condition) {
61
- doSomething();
62
- }
63
- const x = 1;
64
- ```
65
-
66
- ---
67
-
68
- ### `if-else-spacing`
69
-
70
- **What it does:** Enforces proper spacing between if statements and if-else chains:
71
- - Consecutive if statements with block bodies must have an empty line between them
72
- - Single-line if and else should NOT have empty lines between them
73
-
74
- **Why use it:** Maintains visual separation between distinct conditional blocks while keeping related single-line if-else pairs compact.
75
-
76
- ```javascript
77
- // Good — empty line between consecutive if blocks
78
- if (!hasValidParams) return null;
79
-
80
- if (status === "loading") {
81
- return <Loading />;
82
- }
83
-
84
- if (status === "error") {
85
- return <Error />;
86
- }
87
-
88
- // Good — no empty line between single-line if-else
89
- if (error) prom.reject(error);
90
- else prom.resolve(token);
91
-
92
- // Bad — no empty line between if blocks
93
- if (!hasValidParams) return null;
94
- if (status === "loading") {
95
- return <Loading />;
96
- }
97
- if (status === "error") {
98
- return <Error />;
99
- }
100
-
101
- // Bad — empty line between single-line if-else
102
- if (error) prom.reject(error);
103
-
104
- else prom.resolve(token);
105
- ```
106
-
107
- ---
108
-
109
- ### `if-statement-format`
110
-
111
- **What it does:** Enforces consistent if/else formatting:
112
- - Opening `{` on the same line as `if`/`else if`/`else`
113
- - `else` on the same line as the closing `}`
114
- - Proper spacing around keywords
115
-
116
- **Why use it:** Consistent brace placement reduces visual noise and follows the most common JavaScript style (K&R / "one true brace style").
117
-
118
- ```javascript
119
- // Good — consistent formatting
120
- if (condition) {
121
- doSomething();
122
-
123
- doMore();
124
- }
125
-
126
- if (condition) {
127
- doSomething();
128
-
129
- doMore();
130
- } else {
131
- doOther();
132
-
133
- doAnother();
134
- }
135
-
136
- if (conditionA) {
137
- handleA();
138
-
139
- processA();
140
- } else if (conditionB) {
141
- handleB();
142
-
143
- processB();
144
- } else {
145
- handleDefault();
146
-
147
- processDefault();
148
- }
149
-
150
- // Bad — brace on new line
151
- if (condition)
152
- {
153
- doSomething();
154
-
155
- doMore();
156
- }
157
-
158
- // Bad — else on new line
159
- if (condition) {
160
- doSomething();
161
-
162
- doMore();
163
- }
164
- else {
165
- doOther();
166
-
167
- doAnother();
168
- }
169
-
170
- // Bad — inconsistent formatting
171
- if (condition)
172
- {
173
- doSomething();
174
-
175
- doMore();
176
- }
177
- else
178
- {
179
- doOther();
180
-
181
- doAnother();
182
- }
183
- ```
184
-
185
- ---
186
-
187
- ### `logical-expression-multiline`
188
-
189
- **What it does:** When a logical expression (`&&`, `||`) has more operands than the threshold (default: 3), each operand goes on its own line with the operator at the start.
190
-
191
- **Why use it:** Long logical expressions are hard to read on one line. One operand per line makes each part clear and easy to modify.
192
-
193
- ```javascript
194
- // Good — 3 or fewer operands stay inline
195
- const isValid = a && b && c;
196
- const result = x || y;
197
-
198
- // Good — 4+ operands get one per line
199
- const err = data.error
200
- || data.message
201
- || data.status
202
- || data.fallback;
203
-
204
- const isComplete = hasName
205
- && hasEmail
206
- && hasPhone
207
- && hasAddress;
208
-
209
- // Bad — 4+ operands on single line
210
- const err = data.error || data.message || data.status || data.fallback;
211
- ```
212
-
213
- **Options:**
214
-
215
- | Option | Type | Default | Description |
216
- |--------|------|---------|-------------|
217
- | `maxOperands` | `integer` | `3` | Maximum operands allowed on a single line |
218
-
219
- ```javascript
220
- // Configuration example - allow up to 4 operands on single line
221
- "code-style/logical-expression-multiline": ["error", { maxOperands: 4 }]
222
- ```
223
-
224
- ---
225
-
226
- ### `multiline-if-conditions`
227
-
228
- **What it does:** When an if statement has more conditions than the threshold (default: 3), each condition goes on its own line with proper indentation.
229
-
230
- **Why use it:** Long conditions are hard to read on one line. One per line makes each condition clear and easy to modify.
231
-
232
- ```javascript
233
- // Good — 3 or fewer conditions stay inline
234
- if (isValid && isActive) {}
235
- if (a && b && c) {}
236
-
237
- // Good — 4+ conditions get one per line
238
- if (
239
- isAuthenticated &&
240
- hasPermission &&
241
- !isExpired &&
242
- isEnabled
243
- ) {
244
- allowAccess();
245
- }
246
-
247
- if (
248
- user.isAdmin ||
249
- user.isModerator ||
250
- user.hasSpecialAccess ||
251
- isPublicResource
252
- ) {
253
- showContent();
254
- }
255
-
256
- // Bad — too many conditions on one line
257
- if (isAuthenticated && hasPermission && !isExpired && isEnabled) {}
258
-
259
- // Bad — inconsistent formatting
260
- if (isAuthenticated &&
261
- hasPermission && !isExpired &&
262
- isEnabled) {}
263
- ```
264
-
265
- **Options:**
266
-
267
- | Option | Type | Default | Description |
268
- |--------|------|---------|-------------|
269
- | `maxOperands` | `integer` | `3` | Maximum operands to keep on single line. Also applies to nested groups |
270
-
271
- ```javascript
272
- // Example: Allow up to 4 operands on single line
273
- "code-style/multiline-if-conditions": ["error", { maxOperands: 4 }]
274
- ```
275
-
276
- **Auto-formatting:** Nested groups with >maxOperands are formatted multiline inline:
277
-
278
- ```javascript
279
- // Before (nested group has 4 operands)
280
- if ((a || b || c || d) && e) {}
281
-
282
- // After auto-fix — formats nested group multiline
283
- if ((
284
- a
285
- || b
286
- || c
287
- || d
288
- ) && e) {}
289
- ```
290
-
291
- **Double nesting:** Both levels expand when both exceed maxOperands:
292
-
293
- ```javascript
294
- // Before (both parent and nested have 4 operands)
295
- if ((a || (c && d && a && b) || c || d) && e) {}
296
-
297
- // After auto-fix — both levels formatted multiline
298
- if ((
299
- a
300
- || (
301
- c
302
- && d
303
- && a
304
- && b
305
- )
306
- || c
307
- || d
308
- ) && e) {}
309
- ```
310
-
311
- **Extraction:** Groups exceeding nesting level 2 are extracted to variables:
312
-
313
- ```javascript
314
- // Before (level 3 nesting)
315
- if ((a && (b || (c && d))) || e) {}
316
-
317
- // After auto-fix — extracts deepest nested group
318
- const isCAndD = (c && d);
319
- if ((a && (b || isCAndD)) || e) {}
320
- ```
321
-
322
- ---
323
-
324
- ### `no-empty-lines-in-switch-cases`
325
-
326
- **What it does:** Removes empty lines at the start of case blocks and between consecutive case statements.
327
-
328
- **Why use it:** Empty lines inside switch cases create unnecessary gaps. Cases should flow together as a cohesive block.
329
-
330
- ```javascript
331
- // Good — no empty lines
332
- switch (status) {
333
- case "pending":
334
- return "Waiting...";
335
- case "success":
336
- return "Done!";
337
- case "error":
338
- return "Failed";
339
- default:
340
- return "Unknown";
341
- }
342
-
343
- // Good — fall-through cases grouped
344
- switch (day) {
345
- case "Saturday":
346
- case "Sunday":
347
- return "Weekend";
348
- default:
349
- return "Weekday";
350
- }
351
-
352
- // Bad — empty line after case label
353
- switch (status) {
354
- case "pending":
355
-
356
- return "Waiting...";
357
- case "success":
358
- return "Done!";
359
- }
360
-
361
- // Bad — empty lines between cases
362
- switch (status) {
363
- case "pending":
364
- return "Waiting...";
365
-
366
- case "success":
367
- return "Done!";
368
-
369
- default:
370
- return "Unknown";
371
- }
372
- ```
373
-
374
- ---
375
-
376
- ### `ternary-condition-multiline`
377
-
378
- **What it does:** Formats ternary expressions based on condition operand count:
379
- - <=maxOperands (default: 3): Always collapse to single line regardless of line length
380
- - \>maxOperands: Expand to multiline with each operand on its own line
381
- - Simple parenthesized nested ternaries (<=maxOperands) count as 1 operand and collapse
382
- - Complex nested ternaries (>maxOperands in their condition) are skipped for manual formatting
383
- - Nesting level is fixed at 2 to prevent overly complex conditions
384
-
385
- **Why use it:** Consistent formatting based on complexity, not line length. Simple conditions stay readable on one line; complex conditions get proper multiline formatting.
386
-
387
- **Options:**
388
-
389
- | Option | Type | Default | Description |
390
- |--------|------|---------|-------------|
391
- | `maxOperands` | `integer` | `3` | Maximum condition operands to keep ternary on single line. Also applies to nested groups |
392
-
393
- ```javascript
394
- // Good — <=3 operands always on single line
395
- const x = a && b && c ? "yes" : "no";
396
- const url = lang === "ar" ? `${apiEndpoints.exam.status}/${jobId}?lang=ar` : `${apiEndpoints.exam.status}/${jobId}`;
397
-
398
- // Good — parenthesized nested ternary counts as 1 operand
399
- const inputType = showToggle ? (showPassword ? "text" : "password") : type;
400
-
401
- // Good — >3 operands formatted multiline
402
- const style = variant === "ghost"
403
- || variant === "ghost-danger"
404
- || variant === "muted"
405
- || variant === "primary"
406
- ? "transparent"
407
- : "solid";
408
-
409
- // Good — nested group with >3 operands formatted multiline inline
410
- const result = (
411
- a
412
- || (
413
- c
414
- && d
415
- && a
416
- && b
417
- )
418
- || c
419
- || d
420
- ) && e ? "yes" : "no";
421
-
422
- // Bad — <=3 operands split across lines
423
- const x = a && b && c
424
- ? "yes"
425
- : "no";
426
-
427
- // Bad — >3 operands crammed on one line
428
- const style = variant === "ghost" || variant === "ghost-danger" || variant === "muted" || variant === "primary" ? "transparent" : "solid";
429
- ```
430
-
431
- **Auto-extraction:** Nested groups are auto-extracted to variables only when nesting depth exceeds 2 levels:
432
-
433
- ```javascript
434
- // Before (level 3 nesting exceeds limit)
435
- const result = (a && (b || (c && d))) || e ? "yes" : "no";
436
-
437
- // After auto-fix — extracts deepest nested group
438
- const isCAndD = (c && d);
439
- const result = (a && (b || isCAndD)) || e ? "yes" : "no";
440
- ```
441
-
442
- **Note:** When nested groups exceed `maxOperands` but stay within the 2-level nesting limit, they are formatted multiline inline (not extracted).
443
-
444
- <br />
445
-
446
- ---
447
-
448
- [<- Back to Rules Index](./README.md) | [<- Back to Main README](../../README.md)
@@ -1,232 +0,0 @@
1
- # Function Rules
2
-
3
- ### `function-call-spacing`
4
-
5
- **What it does:** Removes any space between a function name and its opening parenthesis.
6
-
7
- **Why use it:** Standard JavaScript convention. `fn()` is correct, `fn ()` looks like a typo and can cause confusion.
8
-
9
- ```javascript
10
- // ✅ Good — no space before parenthesis
11
- useDispatch();
12
- myFunction(arg);
13
- console.log("message");
14
- array.map((x) => x * 2);
15
- obj.method();
16
-
17
- // ❌ Bad — space before parenthesis
18
- useDispatch ();
19
- myFunction (arg);
20
- console.log ("message");
21
- array.map ((x) => x * 2);
22
- ```
23
-
24
- ---
25
-
26
- ### `function-declaration-style`
27
-
28
- **What it does:** Converts function declarations to `const` arrow function expressions. This is the auto-fixable companion to ESLint's built-in `func-style` rule.
29
-
30
- **Why use it:** The built-in `func-style: ["error", "expression"]` rule reports function declarations but does not auto-fix them. This rule provides the auto-fix. Both rules should be used together for the best experience.
31
-
32
- > **Important:** This rule depends on `func-style: ["error", "expression"]` being configured. If `func-style` is set to `"declaration"` or is disabled, do not enable this rule — it would conflict.
33
-
34
- ```typescript
35
- // ✅ Good — arrow function expression
36
- export const getToken = (): string | null => getCookie(tokenKey);
37
-
38
- export const clearAuth = (): void => {
39
- removeToken();
40
- clearStorage();
41
- };
42
-
43
- const isAuthenticated = (): boolean => {
44
- const token = getToken();
45
- return !!token;
46
- };
47
-
48
- // ❌ Bad — function declaration
49
- export function getToken(): string | null {
50
- return getCookie(tokenKey);
51
- }
52
-
53
- export function clearAuth(): void {
54
- removeToken();
55
- clearStorage();
56
- }
57
-
58
- function isAuthenticated(): boolean {
59
- const token = getToken();
60
- return !!token;
61
- }
62
- ```
63
-
64
- ---
65
-
66
- ### `function-naming-convention`
67
-
68
- **What it does:** Enforces naming conventions for functions:
69
- - **camelCase** required
70
- - **Verb prefix** required (get, set, fetch, is, has, can, should, click, submit, etc.)
71
- - **Handler suffix** required (all functions must end with `Handler`)
72
- - **Auto-fixes** `handleXxx` to `xxxHandler` (avoids redundant `handleClickHandler`)
73
- - **Auto-fixes** PascalCase to camelCase for verb-prefixed functions
74
-
75
- **Why use it:** Function names should describe actions. Verb prefixes make the purpose immediately clear, and consistent Handler suffix makes event handlers easy to identify.
76
-
77
- ```javascript
78
- // ✅ Good — verb prefix + Handler suffix
79
- function getUserDataHandler() {}
80
- function setUserNameHandler(name) {}
81
- function clickHandler() {}
82
- function submitHandler() {}
83
- function isValidEmailHandler(email) {}
84
- function hasPermissionHandler(user) {}
85
- function canAccessHandler(resource) {}
86
- const fetchUsersHandler = async () => {};
87
-
88
- // ❌ Bad (auto-fixed) — handleXxx → xxxHandler
89
- function handleClick() {} // → clickHandler
90
- function handleSubmit() {} // → submitHandler
91
- function handleChange() {} // → changeHandler
92
-
93
- // ❌ Bad (auto-fixed) — missing Handler suffix
94
- function getUserData() {} // → getUserDataHandler
95
- function setUserName() {} // → setUserNameHandler
96
- function fetchUsers() {} // → fetchUsersHandler
97
-
98
- // ❌ Bad (auto-fixed) — PascalCase to camelCase
99
- function GetUserData() {} // → getUserDataHandler
100
- function FetchStatus() {} // → fetchStatusHandler
101
- ```
102
-
103
- ---
104
-
105
- ### `function-object-destructure`
106
-
107
- **What it does:** Enforces that non-component functions should not destructure parameters in the function signature. Instead, use a typed parameter and destructure at the top of the function body. Also reports when parameters are accessed via dot notation (suggesting destructuring).
108
-
109
- **Why use it:** Keeping function signatures clean and short improves readability. Destructuring in the body makes it clear what properties are being used. For React components, this rule does NOT apply — components should destructure props in the signature.
110
-
111
- ```typescript
112
- // ✅ Good — typed param with destructuring in body
113
- const createUserHandler = async (data: CreateUserParamsInterface) => {
114
- const { age, email, isActive, name } = data;
115
-
116
- // Use age, email, isActive, name...
117
- };
118
-
119
- const updateUserHandler = (params: UpdateParamsInterface) => {
120
- const { id, updates } = params;
121
-
122
- // Use id, updates...
123
- };
124
-
125
- // ✅ Good — React components CAN destructure in signature
126
- const UserCard = ({
127
- name,
128
- email,
129
- } : {
130
- name: string,
131
- email: string,
132
- }) => (
133
- <div>{name} - {email}</div>
134
- );
135
-
136
- // ❌ Bad — non-component function destructures in signature
137
- const createUserHandler = async ({
138
- age,
139
- email,
140
- isActive,
141
- name,
142
- }: CreateUserParamsInterface) => {
143
- // ...
144
- };
145
-
146
- // ❌ Bad — accessing param via dot notation (should destructure)
147
- const processDataHandler = (data: DataInterface) => {
148
- console.log(data.id); // Bad: use destructuring
149
- console.log(data.name); // Bad: use destructuring
150
- return data.value * 2; // Bad: use destructuring
151
- };
152
- ```
153
-
154
- ---
155
-
156
- ### `function-params-per-line`
157
-
158
- **What it does:** When function parameters span multiple lines, ensures each parameter is on its own line with consistent indentation.
159
-
160
- **Why use it:** Mixed formatting (some params on same line, some on different lines) is confusing. One per line is scannable and easy to edit.
161
-
162
- ```javascript
163
- // ✅ Good — each param on own line
164
- function createUser(
165
- name,
166
- email,
167
- password,
168
- role,
169
- ) {}
170
-
171
- const handler = (
172
- event,
173
- context,
174
- callback,
175
- ) => {};
176
-
177
- // ✅ Good — short params can stay on one line
178
- function add(a, b) {}
179
-
180
- // ❌ Bad — mixed formatting
181
- function createUser(name,
182
- email, password,
183
- role) {}
184
-
185
- // ❌ Bad — some on same line, some not
186
- const handler = (event, context,
187
- callback) => {};
188
- ```
189
-
190
- ---
191
-
192
- ### `no-empty-lines-in-function-params`
193
-
194
- **What it does:** Removes empty lines within function parameter lists — between parameters and after opening/before closing parentheses.
195
-
196
- **Why use it:** Empty lines in parameter lists waste space and make parameters harder to scan as a group.
197
-
198
- ```javascript
199
- // ✅ Good — no empty lines
200
- function createUser(
201
- name,
202
- email,
203
- role,
204
- ) {}
205
-
206
- const handler = (
207
- event,
208
- context,
209
- ) => {};
210
-
211
- // ❌ Bad — empty line between params
212
- function createUser(
213
- name,
214
-
215
- email,
216
-
217
- role,
218
- ) {}
219
-
220
- // ❌ Bad — empty line after opening paren
221
- const handler = (
222
-
223
- event,
224
- context,
225
- ) => {};
226
- ```
227
-
228
- <br />
229
-
230
- ---
231
-
232
- [← Back to Rules Index](./README.md) | [← Back to Main README](../../README.md)