eslint-plugin-code-style 1.0.9 → 1.0.14

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.
Files changed (4) hide show
  1. package/README.md +994 -158
  2. package/index.d.ts +1 -1
  3. package/index.js +110 -10
  4. package/package.json +2 -2
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  [![License](https://img.shields.io/npm/l/eslint-plugin-code-style?style=for-the-badge&color=blue)](https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/blob/main/LICENSE)
8
8
 
9
9
  [![ESLint](https://img.shields.io/badge/ESLint-%3E%3D9.0.0-4B32C3?style=for-the-badge&logo=eslint&logoColor=white)](https://eslint.org/)
10
- [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D24.0.0-339933?style=for-the-badge&logo=node.js&logoColor=white)](https://nodejs.org/)
10
+ [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D18.0.0-339933?style=for-the-badge&logo=node.js&logoColor=white)](https://nodejs.org/)
11
11
  [![React](https://img.shields.io/badge/React-JSX%20Support-61DAFB?style=for-the-badge&logo=react&logoColor=black)](https://react.dev/)
12
12
 
13
13
  [![GitHub stars](https://img.shields.io/github/stars/Mohamed-Elhawary/eslint-plugin-code-style?style=for-the-badge&logo=github&color=yellow)](https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/stargazers)
@@ -17,20 +17,69 @@
17
17
 
18
18
  **A powerful ESLint plugin for enforcing consistent code formatting and style rules in React/JSX projects.**
19
19
 
20
- *45+ auto-fixable rules to keep your codebase clean and consistent*
20
+ *47 auto-fixable rules to keep your codebase clean and consistent*
21
+
22
+ </div>
23
+
24
+ <br />
25
+
26
+ ## 🎯 Why This Plugin?
27
+
28
+ This plugin provides **rules that don't exist in ESLint's built-in rule set** and are **not available in popular third-party ESLint packages**. These are the style requirements that teams often check manually, making them easy to miss and hard to enforce consistently.
29
+
30
+ **Key Benefits:**
31
+ - **Fills the gaps** — Covers formatting rules that ESLint and other plugins miss
32
+ - **Works alongside existing tools** — Complements ESLint's built-in rules and packages like `eslint-plugin-react`, `eslint-plugin-import`, etc.
33
+ - **Consistency at scale** — Reduces code-style differences between team members by enforcing uniform formatting across your projects
34
+ - **Fully automated** — All 47 rules support auto-fix, eliminating manual style reviews
35
+
36
+ When combined with ESLint's native rules and other popular plugins, this package helps create a **complete code style solution** that keeps your codebase clean and consistent.
37
+
38
+ <div align="center">
21
39
 
22
40
  <br />
23
41
 
24
42
  [Installation](#-installation) •
25
43
  [Quick Start](#-quick-start) •
44
+ [Recommended Configs](#-recommended-configurations) •
26
45
  [Rules](#-rules-reference) •
27
- [Examples](#-examples) •
28
46
  [Contributing](#-contributing)
29
47
 
30
48
  </div>
31
49
 
32
50
  <br />
33
51
 
52
+ ## 📁 Recommended Configurations
53
+
54
+ We provide **ready-to-use ESLint flat configuration files** that combine `eslint-plugin-code-style` with carefully selected third-party plugins and ESLint built-in rules. These configurations represent our battle-tested setup that reduces code-style differences by ~95%.
55
+
56
+ ### 💡 Why Use These Configs?
57
+
58
+ - **Complete Coverage** — Combines ESLint built-in rules, third-party plugins, and all 47 code-style rules
59
+ - **Ready-to-Use** — Copy the config file and start linting immediately
60
+ - **Battle-Tested** — These configurations have been refined through real-world usage
61
+ - **Fully Documented** — Each config includes detailed instructions and explanations
62
+
63
+ ### 📋 Available Configurations
64
+
65
+ | Configuration | Description | Link |
66
+ |---------------|-------------|------|
67
+ | **React** | React.js projects (JavaScript, JSX) | [View Config](./recommended-configs/react/) |
68
+ | **React + TS + Tailwind** | React + TypeScript + Tailwind CSS | *Coming Soon* |
69
+ | **Next.js + TS + Tailwind** | Next.js + TypeScript + Tailwind CSS | *Coming Soon* |
70
+
71
+ ### ⚡ Quick Start with Recommended Config
72
+
73
+ 1. Navigate to the [recommended-configs](./recommended-configs/) folder
74
+ 2. Choose the configuration for your project type
75
+ 3. Follow the installation instructions in the README
76
+ 4. Copy the `eslint.config.js` to your project root
77
+ 5. Run `eslint src/ --fix`
78
+
79
+ > **Note:** Each configuration includes a detailed README with installation commands, plugin explanations, and rule documentation.
80
+
81
+ <br />
82
+
34
83
  ---
35
84
 
36
85
  <br />
@@ -41,13 +90,13 @@
41
90
  <tr>
42
91
  <td width="50%">
43
92
 
44
- ### Auto-Fixable Rules
45
- All **45+ rules** support automatic fixing with `eslint --fix`. No manual code changes needed.
93
+ ### 🔧 Auto-Fixable Rules
94
+ All **47 rules** support automatic fixing with `eslint --fix`. No manual code changes needed.
46
95
 
47
96
  </td>
48
97
  <td width="50%">
49
98
 
50
- ### React & JSX Support
99
+ ### ⚛️ React & JSX Support
51
100
  Built specifically for React projects with comprehensive JSX formatting rules.
52
101
 
53
102
  </td>
@@ -55,13 +104,13 @@ Built specifically for React projects with comprehensive JSX formatting rules.
55
104
  <tr>
56
105
  <td width="50%">
57
106
 
58
- ### ESLint v9+ Ready
107
+ ### ESLint v9+ Ready
59
108
  Designed for ESLint's new flat config system. Modern and future-proof.
60
109
 
61
110
  </td>
62
111
  <td width="50%">
63
112
 
64
- ### Zero Dependencies
113
+ ### 📭 Zero Dependencies
65
114
  Lightweight plugin with no external dependencies. Fast and efficient.
66
115
 
67
116
  </td>
@@ -83,12 +132,12 @@ pnpm add eslint-plugin-code-style -D
83
132
  yarn add eslint-plugin-code-style -D
84
133
  ```
85
134
 
86
- ### Requirements
135
+ ### 📋 Requirements
87
136
 
88
137
  | Dependency | Version |
89
138
  |------------|---------|
90
139
  | **ESLint** | `>= 9.0.0` |
91
- | **Node.js** | `>= 24.0.0` |
140
+ | **Node.js** | `>= 18.0.0` |
92
141
 
93
142
  <br />
94
143
 
@@ -126,25 +175,27 @@ eslint src/ --fix
126
175
 
127
176
  ```javascript
128
177
  rules: {
129
- "code-style/absolute-imports-only": "error",
130
178
  "code-style/array-items-per-line": "error",
131
179
  "code-style/array-objects-on-new-lines": "error",
132
180
  "code-style/arrow-function-block-body": "error",
133
181
  "code-style/arrow-function-simple-jsx": "error",
134
182
  "code-style/arrow-function-simplify": "error",
183
+ "code-style/curried-arrow-same-line": "error",
135
184
  "code-style/assignment-value-same-line": "error",
136
185
  "code-style/block-statement-newlines": "error",
137
186
  "code-style/comment-spacing": "error",
138
- "code-style/curried-arrow-same-line": "error",
139
- "code-style/export-format": "error",
140
187
  "code-style/function-call-spacing": "error",
141
188
  "code-style/function-naming-convention": "error",
142
189
  "code-style/function-params-per-line": "error",
143
190
  "code-style/hook-callback-format": "error",
144
191
  "code-style/hook-deps-per-line": "error",
145
192
  "code-style/if-statement-format": "error",
193
+ "code-style/multiline-if-conditions": "error",
194
+ "code-style/absolute-imports-only": "error",
195
+ "code-style/export-format": "error",
146
196
  "code-style/import-format": "error",
147
197
  "code-style/import-source-spacing": "error",
198
+ "code-style/module-index-exports": "error",
148
199
  "code-style/jsx-children-on-new-line": "error",
149
200
  "code-style/jsx-closing-bracket-spacing": "error",
150
201
  "code-style/jsx-element-child-new-line": "error",
@@ -155,9 +206,7 @@ rules: {
155
206
  "code-style/jsx-string-value-trim": "error",
156
207
  "code-style/jsx-ternary-format": "error",
157
208
  "code-style/member-expression-bracket-spacing": "error",
158
- "code-style/module-index-exports": "error",
159
209
  "code-style/multiline-argument-newline": "error",
160
- "code-style/multiline-if-conditions": "error",
161
210
  "code-style/multiple-arguments-per-line": "error",
162
211
  "code-style/nested-call-closing-brackets": "error",
163
212
  "code-style/no-empty-lines-in-function-calls": "error",
@@ -170,7 +219,7 @@ rules: {
170
219
  "code-style/object-property-value-format": "error",
171
220
  "code-style/opening-brackets-same-line": "error",
172
221
  "code-style/simple-call-single-line": "error",
173
- "code-style/single-argument-on-line": "error",
222
+ "code-style/single-argument-on-one-line": "error",
174
223
  "code-style/string-property-spacing": "error",
175
224
  "code-style/variable-naming-convention": "error",
176
225
  }
@@ -178,237 +227,1024 @@ rules: {
178
227
 
179
228
  <br />
180
229
 
181
- ## 📖 Rules Reference
182
-
183
- > All rules are **auto-fixable** using `eslint --fix`
230
+ ---
184
231
 
185
- <br />
232
+ ## 📖 Rules Summary
186
233
 
187
- ### 📥 Import/Export Rules
234
+ > All **47 rules** are auto-fixable. See detailed examples for each rule in the [Rules Reference](#-rules-reference) section below.
235
+ >
236
+ > Rules marked with ⚙️ support customization options (e.g., extending default folder lists).
188
237
 
189
238
  | Rule | Description |
190
239
  |------|-------------|
191
- | `absolute-imports-only` | Enforce absolute imports using `@/` alias instead of relative paths |
192
- | `import-format` | Format imports: `import {` on same line, `} from` on same line, collapse 1-3 specifiers |
240
+ | `array-items-per-line` | Enforce array formatting: 3 or less items on one line, more than 3 each on new line |
241
+ | `array-objects-on-new-lines` | Enforce array of objects to have each object on a new line |
242
+ | `arrow-function-block-body` | Enforce parentheses for arrow functions with multiline expressions |
243
+ | `arrow-function-simple-jsx` | Simplify arrow functions returning simple JSX to single line |
244
+ | `arrow-function-simplify` | Simplify arrow functions in JSX props with single statement block body |
245
+ | `curried-arrow-same-line` | Enforce curried arrow function to start on same line as `=>` |
246
+ | `assignment-value-same-line` | Enforce assignment value on same line as equals sign |
247
+ | `block-statement-newlines` | Enforce newlines after opening brace and before closing brace |
248
+ | `comment-spacing` | Enforce comment spacing and formatting |
249
+ | `function-call-spacing` | Enforce no space between function name and opening parenthesis |
250
+ | `function-naming-convention` | Enforce function naming conventions (camelCase, verb prefix) |
251
+ | `function-params-per-line` | Enforce function parameters on separate lines when multiline |
252
+ | `hook-callback-format` | Enforce consistent formatting for React hooks callbacks |
253
+ | `hook-deps-per-line` | Enforce each hook dependency on its own line when more than 2 |
254
+ | `if-statement-format` | Ensure if statement has proper formatting |
255
+ | `multiline-if-conditions` | Enforce multiline if conditions when there are multiple operands |
256
+ | `absolute-imports-only` | Enforce absolute imports using `@/` alias instead of relative paths ⚙️ |
257
+ | `export-format` | Format exports: collapse 1-3 specifiers, multiline for 4+ |
258
+ | `import-format` | Format imports: collapse 1-3 specifiers, multiline for 4+ |
193
259
  | `import-source-spacing` | Enforce no extra spaces inside import path quotes |
194
- | `export-format` | Format exports: `export {` on same line, collapse 1-3 specifiers, multiline for 4+ |
195
- | `module-index-exports` | Enforce proper exports in index files |
260
+ | `module-index-exports` | Enforce proper exports in index files ⚙️ |
261
+ | `jsx-children-on-new-line` | Enforce JSX children on separate lines from parent tags |
262
+ | `jsx-closing-bracket-spacing` | No space before `>` or `/>` in JSX tags |
263
+ | `jsx-element-child-new-line` | JSX element children must be on new lines |
264
+ | `jsx-logical-expression-simplify` | Simplify logical expressions in JSX |
265
+ | `jsx-parentheses-position` | Enforce opening parenthesis position for JSX in arrow functions |
266
+ | `jsx-prop-naming-convention` | Enforce JSX prop naming conventions (camelCase) |
267
+ | `jsx-simple-element-one-line` | Simple JSX elements with single child on one line |
268
+ | `jsx-string-value-trim` | Disallow leading/trailing whitespace in JSX string values |
269
+ | `jsx-ternary-format` | Enforce consistent formatting for JSX ternary expressions |
270
+ | `member-expression-bracket-spacing` | Enforce no spaces inside brackets for member expressions |
271
+ | `multiline-argument-newline` | Enforce newlines for function calls with multiline arguments |
272
+ | `multiple-arguments-per-line` | Enforce multiple arguments to each be on their own line |
273
+ | `nested-call-closing-brackets` | Enforce nested function call closing brackets on same line |
274
+ | `no-empty-lines-in-function-calls` | Disallow empty lines in function calls |
275
+ | `no-empty-lines-in-function-params` | Disallow empty lines in function parameters |
276
+ | `no-empty-lines-in-jsx` | Disallow empty lines inside JSX elements |
277
+ | `no-empty-lines-in-objects` | Disallow empty lines inside objects |
278
+ | `no-empty-lines-in-switch-cases` | Prevent empty lines at the beginning of switch case logic |
279
+ | `object-property-per-line` | Enforce each property on its own line when object has 2+ properties |
280
+ | `object-property-value-brace` | Enforce opening brace on same line as colon for object values |
281
+ | `object-property-value-format` | Enforce property value on same line as colon |
282
+ | `opening-brackets-same-line` | Enforce opening brackets on same line for function calls |
283
+ | `simple-call-single-line` | Simplify simple function calls with arrow function to single line |
284
+ | `single-argument-on-one-line` | Enforce single simple argument calls to be on one line |
285
+ | `string-property-spacing` | Enforce no extra spaces inside string property keys |
286
+ | `variable-naming-convention` | Enforce variable naming conventions (camelCase, UPPER_CASE, PascalCase) |
196
287
 
197
288
  <br />
198
289
 
199
- ### ⚡ Function Rules
290
+ ---
200
291
 
201
- | Rule | Description |
202
- |------|-------------|
203
- | `arrow-function-block-body` | Enforce parentheses for arrow functions with multiline expressions |
204
- | `arrow-function-simplify` | Simplify arrow functions returning simple JSX to single line |
205
- | `arrow-function-simple-jsx` | Simplify arrow functions in JSX props with single statement block body |
206
- | `function-call-spacing` | Enforce no space between function name and opening parenthesis |
207
- | `function-naming-convention` | Enforce function naming conventions (camelCase) |
208
- | `function-params-per-line` | Enforce function parameters on separate lines when more than 2 |
209
- | `curried-arrow-same-line` | Enforce curried arrow function to start on same line as `=>` |
292
+ ## 📖 Rules Reference
293
+
294
+ > All rules are **auto-fixable** using `eslint --fix`
210
295
 
211
296
  <br />
212
297
 
213
- ### 📦 Object Rules
298
+ ## 📚 Array Rules
214
299
 
215
- | Rule | Description |
216
- |------|-------------|
217
- | `object-property-per-line` | Enforce each property on its own line when object has 2+ properties |
218
- | `object-property-value-format` | Enforce property value on same line as colon with proper spacing |
219
- | `object-property-value-brace` | Enforce opening brace on same line as colon for object property values |
220
- | `no-empty-lines-in-objects` | Disallow empty lines inside objects |
221
- | `string-property-spacing` | Enforce no extra spaces inside string property keys |
300
+ ### `array-items-per-line`
222
301
 
223
- <br />
302
+ Enforce array formatting based on item count. 3 or less items on one line, more than 3 items each on its own line.
224
303
 
225
- ### 📚 Array Rules
304
+ ```javascript
305
+ // Good
306
+ const arr = [1, 2, 3];
307
+ const arr = [
308
+ item1,
309
+ item2,
310
+ item3,
311
+ item4,
312
+ ];
226
313
 
227
- | Rule | Description |
228
- |------|-------------|
229
- | `array-items-per-line` | Enforce array formatting: 3 or less items on one line, more than 3 each on new line |
230
- | `array-objects-on-new-lines` | Enforce array of objects to have each object on a new line |
314
+ // Bad
315
+ const arr = [1, 2, 3, 4, 5];
316
+ const arr = [item1,
317
+ item2, item3];
318
+ ```
319
+
320
+ ---
321
+
322
+ ### `array-objects-on-new-lines`
323
+
324
+ In arrays of objects, each object should start on a new line for better readability.
325
+
326
+ ```javascript
327
+ // Good
328
+ const items = [
329
+ { id: 1, name: "first" },
330
+ { id: 2, name: "second" },
331
+ ];
332
+
333
+ // Bad
334
+ const items = [{ id: 1, name: "first" },
335
+ { id: 2, name: "second" }];
336
+ ```
231
337
 
232
338
  <br />
233
339
 
234
- ### ⚛️ JSX Rules
340
+ ## ➡️ Arrow Function Rules
235
341
 
236
- | Rule | Description |
237
- |------|-------------|
238
- | `jsx-children-on-new-line` | Enforce JSX children on separate lines from parent tags |
239
- | `jsx-closing-bracket-spacing` | No space before `>` or `/>` in JSX tags |
240
- | `jsx-element-child-new-line` | JSX children that are JSX elements must be on new lines |
241
- | `jsx-logical-expression-simplify` | Simplify logical expressions in JSX when right side is single-line |
242
- | `jsx-parentheses-position` | Enforce opening parenthesis position for JSX in arrow functions |
243
- | `jsx-prop-naming-convention` | Enforce JSX prop naming conventions (camelCase) |
244
- | `jsx-simple-element-one-line` | Simple JSX elements with only text/expression children on one line |
245
- | `jsx-string-value-trim` | Disallow leading/trailing whitespace in JSX string values |
246
- | `jsx-ternary-format` | Enforce consistent formatting for JSX ternary expressions |
247
- | `no-empty-lines-in-jsx` | Disallow empty lines inside JSX elements |
342
+ ### `arrow-function-block-body`
343
+
344
+ Arrow functions with complex logic should use block body. Ensures consistent formatting when function body needs multiple statements or complex expressions.
345
+
346
+ ```javascript
347
+ // Good
348
+ () => {
349
+ doSomething();
350
+ return value;
351
+ }
352
+
353
+ // Bad
354
+ () => (doSomething(), value)
355
+ ```
356
+
357
+ ---
358
+
359
+ ### `arrow-function-simple-jsx`
360
+
361
+ Simplify arrow functions returning simple JSX to single line by removing unnecessary parentheses and line breaks.
362
+
363
+ ```javascript
364
+ // Good
365
+ export const X = ({ children }) => <Sidebar>{children}</Sidebar>;
366
+
367
+ // Bad
368
+ export const X = ({ children }) => (
369
+ <Sidebar>{children}</Sidebar>
370
+ );
371
+ ```
372
+
373
+ ---
374
+
375
+ ### `arrow-function-simplify`
376
+
377
+ Simplify arrow functions that have a single return statement by using implicit return instead of block body.
378
+
379
+ ```javascript
380
+ // Good
381
+ () => value
382
+ (x) => x * 2
383
+ items.map(item => item.name)
384
+
385
+ // Bad
386
+ () => { return value; }
387
+ (x) => { return x * 2; }
388
+ items.map(item => { return item.name; })
389
+ ```
390
+
391
+ ---
392
+
393
+ ### `curried-arrow-same-line`
394
+
395
+ Curried arrow function body must start on the same line as the arrow (=>), not on a new line.
396
+
397
+ ```javascript
398
+ // Good
399
+ const fn = () => async (dispatch) => {
400
+ dispatch(action);
401
+ };
402
+
403
+ // Bad
404
+ const fn = () =>
405
+ async (dispatch) => {
406
+ dispatch(action);
407
+ };
408
+ ```
248
409
 
249
410
  <br />
250
411
 
251
- ### 📞 Call Expression Rules
412
+ ## 📐 Spacing & Formatting Rules
252
413
 
253
- | Rule | Description |
254
- |------|-------------|
255
- | `simple-call-single-line` | Simplify simple function calls with arrow function to single line |
256
- | `single-argument-on-line` | Enforce single simple argument calls to be on one line |
257
- | `multiple-arguments-per-line` | Enforce multiple arguments to each be on their own line |
258
- | `multiline-argument-newline` | Enforce newlines for function calls with multiline arguments |
259
- | `nested-call-closing-brackets` | Enforce nested function call closing brackets on same line |
260
- | `no-empty-lines-in-function-calls` | Disallow empty lines in function calls |
261
- | `opening-brackets-same-line` | Enforce opening brackets on same line for function calls |
414
+ ### `assignment-value-same-line`
415
+
416
+ The value in an assignment should start on the same line as the equals sign, not on a new line.
417
+
418
+ ```javascript
419
+ // Good
420
+ const name = "John";
421
+ const data = {
422
+ key: "value",
423
+ };
424
+
425
+ // Bad
426
+ const name =
427
+ "John";
428
+ const data =
429
+ {
430
+ key: "value",
431
+ };
432
+ ```
433
+
434
+ ---
435
+
436
+ ### `block-statement-newlines`
437
+
438
+ Block statements should have proper newlines after the opening brace and before the closing brace.
439
+
440
+ ```javascript
441
+ // Good
442
+ if (condition) {
443
+ doSomething();
444
+ }
445
+
446
+ // Bad
447
+ if (condition) { doSomething(); }
448
+ if (condition) {doSomething();}
449
+ ```
450
+
451
+ ---
452
+
453
+ ### `comment-spacing`
454
+
455
+ Comments should have proper spacing: a space after the opening delimiter (// or block comment opener), and proper blank lines around comment blocks.
456
+
457
+ ```javascript
458
+ // Good
459
+ // This is a comment
460
+ /* This is a block comment */
461
+
462
+ // Bad
463
+ //This is a comment (missing space)
464
+ /*No space after opener*/
465
+ ```
466
+
467
+ ---
468
+
469
+ ### `member-expression-bracket-spacing`
470
+
471
+ No spaces inside brackets in computed member expressions. The property name should touch both brackets.
472
+
473
+ ```javascript
474
+ // Good
475
+ arr[value]
476
+ obj[key]
477
+
478
+ // Bad
479
+ arr[ value ]
480
+ obj[ key ]
481
+ ```
482
+
483
+ ---
484
+
485
+ ### `no-empty-lines-in-function-params`
486
+
487
+ Function parameter lists should not contain empty lines between parameters or after opening/before closing parens.
488
+
489
+ ```javascript
490
+ // Good
491
+ function test(
492
+ param1,
493
+ param2,
494
+ ) {}
495
+
496
+ // Bad
497
+ function test(
498
+ param1,
499
+
500
+ param2,
501
+ ) {}
502
+ ```
503
+
504
+ ---
505
+
506
+ ### `variable-naming-convention`
507
+
508
+ Variable names should follow naming conventions: camelCase for regular variables, UPPER_CASE for constants, and PascalCase for React components.
509
+
510
+ ```javascript
511
+ // Good
512
+ const userName = "John";
513
+ const MAX_RETRIES = 3;
514
+ const UserProfile = () => <div />;
515
+ const useCustomHook = () => {};
516
+
517
+ // Bad
518
+ const user_name = "John";
519
+ const maxretries = 3;
520
+ const userProfile = () => <div />;
521
+ ```
262
522
 
263
523
  <br />
264
524
 
265
- ### 🪝 React Hooks Rules
525
+ ## Function Rules
266
526
 
267
- | Rule | Description |
268
- |------|-------------|
269
- | `hook-callback-format` | Enforce consistent formatting for React hooks (useEffect, useCallback, etc.) |
270
- | `hook-deps-per-line` | Enforce each hook dependency on its own line when more than 2 dependencies |
527
+ ### `function-call-spacing`
528
+
529
+ No space between function name and opening parenthesis.
530
+
531
+ ```javascript
532
+ // Good
533
+ useDispatch()
534
+ myFunction(arg)
535
+
536
+ // Bad
537
+ useDispatch ()
538
+ myFunction (arg)
539
+ ```
540
+
541
+ ---
542
+
543
+ ### `function-naming-convention`
544
+
545
+ Function names should follow naming conventions: camelCase, starting with a verb, and handlers ending with "Handler".
546
+
547
+ ```javascript
548
+ // Good
549
+ function getUserData() {}
550
+ function handleClick() {}
551
+ function isValidEmail() {}
552
+ const submitHandler = () => {}
553
+
554
+ // Bad
555
+ function GetUserData() {}
556
+ function user_data() {}
557
+ function click() {}
558
+ ```
559
+
560
+ ---
561
+
562
+ ### `function-params-per-line`
563
+
564
+ When function parameters span multiple lines, each parameter should be on its own line with consistent indentation.
565
+
566
+ ```javascript
567
+ // Good
568
+ function test(
569
+ param1,
570
+ param2,
571
+ param3,
572
+ ) {}
573
+
574
+ // Bad
575
+ function test(param1,
576
+ param2, param3) {}
577
+ ```
271
578
 
272
579
  <br />
273
580
 
274
- ### 🔀 Control Flow Rules
581
+ ## 🪝 React Hooks Rules
275
582
 
276
- | Rule | Description |
277
- |------|-------------|
278
- | `if-statement-format` | Ensure if statement has proper formatting |
279
- | `multiline-if-conditions` | Enforce multiline if conditions when there are more than 3 operands |
280
- | `no-empty-lines-in-switch-cases` | Prevent empty lines at the beginning of switch case logic |
583
+ ### `hook-callback-format`
584
+
585
+ Enforce consistent formatting for React hooks like useEffect, useCallback, useMemo with callback and dependency array.
586
+
587
+ ```javascript
588
+ // Good
589
+ useEffect(
590
+ () => { doSomething(); },
591
+ [dep1, dep2],
592
+ );
593
+
594
+ // Bad
595
+ useEffect(() => { doSomething(); }, [dep1, dep2]);
596
+ ```
597
+
598
+ ---
599
+
600
+ ### `hook-deps-per-line`
601
+
602
+ React hook dependency arrays with more than 2 dependencies should have each dependency on its own line.
603
+
604
+ ```javascript
605
+ // Good
606
+ useEffect(() => {}, [dep1, dep2])
607
+ useEffect(() => {}, [
608
+ dep1,
609
+ dep2,
610
+ dep3,
611
+ ])
612
+
613
+ // Bad
614
+ useEffect(() => {}, [dep1, dep2, dep3, dep4])
615
+ ```
281
616
 
282
617
  <br />
283
618
 
284
- ### 📐 Spacing & Formatting Rules
619
+ ## 🔀 Control Flow Rules
285
620
 
286
- | Rule | Description |
287
- |------|-------------|
288
- | `assignment-value-same-line` | Enforce assignment value on same line as equals sign |
289
- | `block-statement-newlines` | Enforce newlines after opening brace and before closing brace |
290
- | `comment-spacing` | Enforce comment spacing and formatting |
291
- | `member-expression-bracket-spacing` | Enforce no spaces inside brackets for member expressions |
292
- | `no-empty-lines-in-function-params` | Disallow empty lines in function parameters |
293
- | `variable-naming-convention` | Enforce variable naming conventions (camelCase) |
621
+ ### `if-statement-format`
622
+
623
+ If statements should have consistent formatting with the opening brace on the same line as the condition and else on the same line as the closing brace.
624
+
625
+ ```javascript
626
+ // Good
627
+ if (condition) {
628
+ doSomething();
629
+ } else {
630
+ doOther();
631
+ }
632
+
633
+ // Bad
634
+ if (condition)
635
+ {
636
+ doSomething();
637
+ }
638
+ else
639
+ {
640
+ doOther();
641
+ }
642
+ ```
643
+
644
+ ---
645
+
646
+ ### `multiline-if-conditions`
647
+
648
+ When an if statement has multiple conditions that span multiple lines, each condition should be on its own line.
649
+
650
+ ```javascript
651
+ // Good
652
+ if (
653
+ conditionA &&
654
+ conditionB &&
655
+ conditionC
656
+ ) {}
657
+
658
+ // Bad
659
+ if (conditionA &&
660
+ conditionB && conditionC) {}
661
+ ```
662
+
663
+ ---
664
+
665
+ ### `no-empty-lines-in-switch-cases`
666
+
667
+ Switch case blocks should not have empty lines at the beginning of the case logic or between consecutive cases.
668
+
669
+ ```javascript
670
+ // Good
671
+ switch (value) {
672
+ case 1:
673
+ return "one";
674
+ case 2:
675
+ return "two";
676
+ }
677
+
678
+ // Bad
679
+ switch (value) {
680
+ case 1:
681
+
682
+ return "one";
683
+
684
+ case 2:
685
+ return "two";
686
+ }
687
+ ```
294
688
 
295
689
  <br />
296
690
 
297
- ## 💡 Examples
691
+ ## 📥 Import/Export Rules
692
+
693
+ ### `absolute-imports-only`
298
694
 
299
- ### Import Formatting
695
+ Enforce absolute imports from index files only for local paths. Local paths (starting with @/) should only import from folder-level index files.
300
696
 
301
697
  ```javascript
302
- // Good - 3 or fewer specifiers on one line
303
- import { Box, Button, Grid } from "@mui/material";
698
+ // Good
699
+ import { Button } from "@/components";
700
+ import { useAuth } from "@/hooks";
304
701
 
305
- // ✅ Good - 4+ specifiers on multiple lines
306
- import {
307
- Box,
308
- Button,
309
- Grid,
310
- Typography,
311
- } from "@mui/material";
702
+ // Bad
703
+ import { Button } from "@/components/buttons/primary-button";
704
+ import { useAuth } from "@/hooks/auth/useAuth";
705
+ ```
706
+
707
+ **Default Allowed Folders:**
708
+ `actions`, `apis`, `assets`, `atoms`, `components`, `constants`, `contexts`, `data`, `hooks`, `layouts`, `middlewares`, `providers`, `reducers`, `redux`, `requests`, `routes`, `schemas`, `services`, `store`, `styles`, `theme`, `thunks`, `types`, `utils`, `views`
709
+
710
+ **Customization Options:**
711
+
712
+ | Option | Type | Description |
713
+ |--------|------|-------------|
714
+ | `extraAllowedFolders` | `string[]` | Add extra folders to the default list |
715
+ | `extraReduxSubfolders` | `string[]` | Add extra redux subfolders (default: `actions`, `reducers`, `store`, `thunks`, `types`) |
716
+ | `extraDeepImportFolders` | `string[]` | Add extra folders that allow deep imports (default: `assets`) |
717
+ | `aliasPrefix` | `string` | Change the import alias prefix (default: `@/`) |
718
+ | `allowedFolders` | `string[]` | Replace default folders entirely |
719
+ | `reduxSubfolders` | `string[]` | Replace default redux subfolders entirely |
720
+ | `deepImportFolders` | `string[]` | Replace default deep import folders entirely |
721
+
722
+ ```javascript
723
+ // Example: Add custom folders to the defaults
724
+ "code-style/absolute-imports-only": ["error", {
725
+ extraAllowedFolders: ["features", "modules", "lib"],
726
+ extraDeepImportFolders: ["images", "fonts"]
727
+ }]
728
+ ```
729
+
730
+ ---
731
+
732
+ ### `export-format`
733
+
734
+ Export statements should have consistent formatting with proper spacing. Collapse 1-3 specifiers on one line, use multiline for 4+ specifiers.
735
+
736
+ ```javascript
737
+ // Good
738
+ export { a, b, c };
739
+ export {
740
+ a,
741
+ b,
742
+ c,
743
+ d,
744
+ };
745
+
746
+ // Bad
747
+ export {a,b,c};
748
+ export { a, b, c, d, e };
749
+ ```
750
+
751
+ ---
312
752
 
313
- // ❌ Bad
753
+ ### `import-format`
754
+
755
+ Import statements should have consistent formatting with proper spacing. Collapse 1-3 specifiers on one line, use multiline for 4+ specifiers.
756
+
757
+ ```javascript
758
+ // Good
759
+ import { a, b, c } from "module";
314
760
  import {
315
- Box, Button, Grid } from "@mui/material";
761
+ a,
762
+ b,
763
+ c,
764
+ d,
765
+ } from "module";
766
+
767
+ // Bad
768
+ import {a,b,c} from "module";
769
+ import { a, b, c, d, e } from "module";
316
770
  ```
317
771
 
318
- <br />
772
+ ---
773
+
774
+ ### `import-source-spacing`
319
775
 
320
- ### Function Parameters
776
+ No spaces inside import path quotes. The module path should not have leading or trailing whitespace.
321
777
 
322
778
  ```javascript
323
- // Good - 2 or fewer params on one line
324
- const fn = (a, b) => {};
779
+ // Good
780
+ import { Button } from "@mui/material";
325
781
 
326
- // ✅ Good - 3+ params on separate lines
327
- const fn = (
328
- param1,
329
- param2,
330
- param3,
331
- ) => {};
782
+ // Bad
783
+ import { Button } from " @mui/material ";
784
+ ```
785
+
786
+ ---
787
+
788
+ ### `module-index-exports`
789
+
790
+ Ensure module folders have index files that export all contents. Each module folder must have an index file that exports all subfolders and files in the module.
791
+
792
+ ```javascript
793
+ // Good
794
+ // index.js
795
+ export { Button } from "./Button";
796
+ export { Input } from "./Input";
797
+
798
+ // Bad
799
+ // Missing exports in index.js
800
+ ```
801
+
802
+ **Default Module Folders:**
803
+ `apis`, `assets`, `atoms`, `components`, `constants`, `contexts`, `data`, `hooks`, `layouts`, `middlewares`, `providers`, `redux`, `requests`, `routes`, `schemas`, `services`, `styles`, `theme`, `utils`, `views`
804
+
805
+ **Customization Options:**
806
+
807
+ | Option | Type | Description |
808
+ |--------|------|-------------|
809
+ | `extraModuleFolders` | `string[]` | Add extra module folders to the default list |
810
+ | `extraLazyLoadFolders` | `string[]` | Add extra lazy load folders (default: `views`) |
811
+ | `extraIgnorePatterns` | `string[]` | Add extra ignore patterns (supports wildcards like `*.stories.js`) |
812
+ | `moduleFolders` | `string[]` | Replace default module folders entirely |
813
+ | `lazyLoadFolders` | `string[]` | Replace default lazy load folders entirely |
814
+ | `ignorePatterns` | `string[]` | Replace default ignore patterns entirely |
815
+
816
+ **Default Ignore Patterns:**
817
+ `index.js`, `index.jsx`, `index.ts`, `index.tsx`, `.DS_Store`, `__tests__`, `__mocks__`, `*.test.js`, `*.test.jsx`, `*.spec.js`, `*.spec.jsx`
332
818
 
333
- // ❌ Bad
334
- const fn = (param1, param2, param3) => {};
819
+ ```javascript
820
+ // Example: Add custom folders and patterns to the defaults
821
+ "code-style/module-index-exports": ["error", {
822
+ extraModuleFolders: ["features", "modules", "lib"],
823
+ extraLazyLoadFolders: ["pages"],
824
+ extraIgnorePatterns: ["*.stories.js", "*.mock.js"]
825
+ }]
335
826
  ```
336
827
 
337
828
  <br />
338
829
 
339
- ### JSX Ternary
830
+ ## ⚛️ JSX Rules
831
+
832
+ ### `jsx-children-on-new-line`
833
+
834
+ When a JSX element has multiple children, each child should be on its own line with proper indentation.
340
835
 
341
836
  ```javascript
342
- // Good - Simple ternary on one line
343
- {condition ? <Simple /> : <Other />}
837
+ // Good
838
+ <Container>
839
+ <Header />
840
+ <Content />
841
+ <Footer />
842
+ </Container>
843
+
844
+ // Bad
845
+ <Container><Header /><Content />
846
+ <Footer /></Container>
847
+ ```
848
+
849
+ ---
850
+
851
+ ### `jsx-closing-bracket-spacing`
852
+
853
+ No space before > or /> in JSX tags. The closing bracket should be directly after the last attribute or tag name.
854
+
855
+ ```javascript
856
+ // Good
857
+ <Button />
858
+ <Button className="primary">
859
+
860
+ // Bad
861
+ <Button / >
862
+ <Button className="primary" >
863
+ ```
864
+
865
+ ---
344
866
 
345
- // ✅ Good - Complex ternary with proper formatting
346
- {condition ? (
867
+ ### `jsx-element-child-new-line`
868
+
869
+ JSX element children (nested JSX elements) must be on their own line, not on the same line as the opening tag.
870
+
871
+ ```javascript
872
+ // Good
873
+ <Button>
874
+ <Icon />
875
+ </Button>
876
+
877
+ // Bad
878
+ <Button><Icon /></Button>
879
+ ```
880
+
881
+ ---
882
+
883
+ ### `jsx-logical-expression-simplify`
884
+
885
+ Simplify JSX logical expressions by removing unnecessary parentheses around conditions and JSX elements.
886
+
887
+ ```javascript
888
+ // Good
889
+ {condition && <Component />}
890
+ {isVisible && <Modal />}
891
+
892
+ // Bad
893
+ {(condition) && (<Component />)}
894
+ {(isVisible) && (<Modal />)}
895
+ ```
896
+
897
+ ---
898
+
899
+ ### `jsx-parentheses-position`
900
+
901
+ JSX return parentheses should be on the same line as the arrow or return keyword, not on a new line.
902
+
903
+ ```javascript
904
+ // Good
905
+ const Component = () => (
906
+ <div>content</div>
907
+ );
908
+ return (
909
+ <div>content</div>
910
+ );
911
+
912
+ // Bad
913
+ const Component = () =>
914
+ (
915
+ <div>content</div>
916
+ );
917
+ return
918
+ (
919
+ <div>content</div>
920
+ );
921
+ ```
922
+
923
+ ---
924
+
925
+ ### `jsx-prop-naming-convention`
926
+
927
+ Enforce camelCase naming for JSX props. Allows PascalCase for component reference props, and kebab-case for data-* and aria-*.
928
+
929
+ ```javascript
930
+ // Good
931
+ <Button onClick={handler} />
932
+ <Input data-testid="input" />
933
+ <Modal ContentComponent={Panel} />
934
+
935
+ // Bad
936
+ <Button on_click={handler} />
937
+ <Input test_id="input" />
938
+ ```
939
+
940
+ ---
941
+
942
+ ### `jsx-simple-element-one-line`
943
+
944
+ Simple JSX elements with only a single text or expression child should be collapsed onto a single line.
945
+
946
+ ```javascript
947
+ // Good
948
+ <Button>{buttonLinkText}</Button>
949
+ <Title>Hello</Title>
950
+
951
+ // Bad
952
+ <Button>
953
+ {buttonLinkText}
954
+ </Button>
955
+ ```
956
+
957
+ ---
958
+
959
+ ### `jsx-string-value-trim`
960
+
961
+ JSX string attribute values should not have leading or trailing whitespace inside the quotes.
962
+
963
+ ```javascript
964
+ // Good
965
+ className="button"
966
+ title="Hello World"
967
+
968
+ // Bad
969
+ className=" button "
970
+ title=" Hello World "
971
+ ```
972
+
973
+ ---
974
+
975
+ ### `jsx-ternary-format`
976
+
977
+ Format ternary expressions in JSX with proper structure. Simple branches stay on one line, complex branches get parentheses with proper indentation.
978
+
979
+ ```javascript
980
+ // Good
981
+ {condition ? <Simple /> : <Other />}
982
+ {condition ? <Simple /> : (
347
983
  <Complex>
348
- <Children />
984
+ <Child />
349
985
  </Complex>
350
- ) : (
351
- <Alternative>
352
- <Content />
353
- </Alternative>
354
986
  )}
355
987
 
356
- // Bad - Empty lines inside ternary
357
- {condition ? (
988
+ // Bad
989
+ {condition
990
+ ? <Simple />
991
+ : <Other />}
992
+ ```
358
993
 
359
- <Button />
994
+ ---
360
995
 
361
- ) : (
996
+ ### `no-empty-lines-in-jsx`
362
997
 
363
- <Link />
998
+ JSX elements should not contain empty lines between children or after opening/before closing tags.
364
999
 
365
- )}
1000
+ ```javascript
1001
+ // Good
1002
+ <div>
1003
+ <span>text</span>
1004
+ <span>more</span>
1005
+ </div>
1006
+
1007
+ // Bad
1008
+ <div>
1009
+
1010
+ <span>text</span>
1011
+
1012
+ <span>more</span>
1013
+
1014
+ </div>
366
1015
  ```
367
1016
 
368
1017
  <br />
369
1018
 
370
- ### React Hooks
1019
+ ## 📞 Call Expression Rules
1020
+
1021
+ ### `multiline-argument-newline`
1022
+
1023
+ When function arguments span multiple lines, each argument should start on its own line with consistent indentation.
371
1024
 
372
1025
  ```javascript
373
- // Good
374
- useEffect(
375
- () => {
376
- doSomething();
377
- },
378
- [dependency],
1026
+ // Good
1027
+ fn(
1028
+ arg1,
1029
+ arg2,
1030
+ )
1031
+
1032
+ // Bad
1033
+ fn(arg1,
1034
+ arg2)
1035
+ ```
1036
+
1037
+ ---
1038
+
1039
+ ### `multiple-arguments-per-line`
1040
+
1041
+ When a function call has 2+ arguments, each argument should be on its own line with proper indentation.
1042
+
1043
+ ```javascript
1044
+ // Good
1045
+ setValue(
1046
+ "numberOfCopies",
1047
+ null,
1048
+ )
1049
+
1050
+ // Bad
1051
+ setValue("numberOfCopies", null)
1052
+ ```
1053
+
1054
+ ---
1055
+
1056
+ ### `nested-call-closing-brackets`
1057
+
1058
+ Nested function calls (like styled-components) should have closing brackets on the same line: }));
1059
+
1060
+ ```javascript
1061
+ // Good
1062
+ styled(Card)(({ theme }) => ({
1063
+ color: theme.color,
1064
+ }));
1065
+
1066
+ // Bad
1067
+ styled(Card)(({ theme }) => ({
1068
+ color: theme.color,
1069
+ })
379
1070
  );
1071
+ ```
380
1072
 
381
- // ✅ Good - Simple callback
382
- useEffect(() => doSomething(), []);
1073
+ ---
383
1074
 
384
- // ❌ Bad
385
- useEffect(() => {
386
- doSomething();
387
- }, [dependency]);
1075
+ ### `no-empty-lines-in-function-calls`
1076
+
1077
+ Function call arguments should not have empty lines between them or after opening/before closing parentheses.
1078
+
1079
+ ```javascript
1080
+ // Good
1081
+ fn(
1082
+ arg1,
1083
+ arg2,
1084
+ )
1085
+
1086
+ // Bad
1087
+ fn(
1088
+ arg1,
1089
+
1090
+ arg2,
1091
+ )
1092
+ ```
1093
+
1094
+ ---
1095
+
1096
+ ### `opening-brackets-same-line`
1097
+
1098
+ Opening brackets should be on the same line as function/method calls. This applies to objects, arrays, and arrow function parameters.
1099
+
1100
+ ```javascript
1101
+ // Good
1102
+ fn({ prop: value })
1103
+ .map(({ x }) => x)
1104
+ fn([1, 2, 3])
1105
+
1106
+ // Bad
1107
+ fn(
1108
+ { prop: value }
1109
+ )
1110
+ .map(
1111
+ ({ x }) => x
1112
+ )
1113
+ ```
1114
+
1115
+ ---
1116
+
1117
+ ### `simple-call-single-line`
1118
+
1119
+ Simple function calls with an arrow function containing a simple call expression should be on a single line.
1120
+
1121
+ ```javascript
1122
+ // Good
1123
+ fn(() => call(arg))
1124
+ lazy(() => import("./module"))
1125
+
1126
+ // Bad
1127
+ fn(
1128
+ () => call(arg),
1129
+ )
1130
+ ```
1131
+
1132
+ ---
1133
+
1134
+ ### `single-argument-on-one-line`
1135
+
1136
+ Function calls with a single simple argument (literal, identifier, member expression) should be on one line.
1137
+
1138
+ ```javascript
1139
+ // Good
1140
+ fn(arg)
1141
+ getValue("key")
1142
+ obj.method(value)
1143
+
1144
+ // Bad
1145
+ fn(
1146
+ arg,
1147
+ )
388
1148
  ```
389
1149
 
390
1150
  <br />
391
1151
 
392
- ### Multiline Conditions
1152
+ ## 📦 Object Rules
1153
+
1154
+ ### `no-empty-lines-in-objects`
1155
+
1156
+ Object literals should not contain empty lines between properties or after opening/before closing braces.
393
1157
 
394
1158
  ```javascript
395
- // Good - 3 or fewer operands on one line
396
- if (a && b && c) {}
1159
+ // Good
1160
+ {
1161
+ a: 1,
1162
+ b: 2,
1163
+ }
397
1164
 
398
- // ✅ Good - 4+ operands on multiple lines
399
- if (
400
- condition1
401
- && condition2
402
- && condition3
403
- && condition4
404
- ) {}
1165
+ // Bad
1166
+ {
1167
+ a: 1,
1168
+
1169
+ b: 2,
1170
+ }
1171
+ ```
1172
+
1173
+ ---
1174
+
1175
+ ### `object-property-per-line`
1176
+
1177
+ When an object has 2 or more properties and spans multiple lines, each property should be on its own line.
1178
+
1179
+ ```javascript
1180
+ // Good
1181
+ {
1182
+ name: "John",
1183
+ age: 30,
1184
+ }
1185
+
1186
+ // Bad
1187
+ { name: "John",
1188
+ age: 30 }
1189
+ ```
1190
+
1191
+ ---
1192
+
1193
+ ### `object-property-value-brace`
1194
+
1195
+ Opening brace of an object value should be on the same line as the colon, not on a new line.
1196
+
1197
+ ```javascript
1198
+ // Good
1199
+ "& a": { color: "red" }
1200
+
1201
+ // Bad
1202
+ "& a":
1203
+ { color: "red" }
1204
+ ```
1205
+
1206
+ ---
1207
+
1208
+ ### `object-property-value-format`
405
1209
 
406
- // Bad
407
- if (condition1 && condition2 && condition3 && condition4) {}
1210
+ Object property values should be on the same line as the colon with proper spacing for simple values.
1211
+
1212
+ ```javascript
1213
+ // Good
1214
+ {
1215
+ name: "John",
1216
+ age: 30,
1217
+ }
1218
+
1219
+ // Bad
1220
+ {
1221
+ name:
1222
+ "John",
1223
+ age:
1224
+ 30,
1225
+ }
1226
+ ```
1227
+
1228
+ ---
1229
+
1230
+ ### `string-property-spacing`
1231
+
1232
+ String property keys should not have extra leading or trailing spaces inside the quotes.
1233
+
1234
+ ```javascript
1235
+ // Good
1236
+ { "& a": value }
1237
+ { "selector": value }
1238
+
1239
+ // Bad
1240
+ { " & a ": value }
1241
+ { " selector ": value }
408
1242
  ```
409
1243
 
410
1244
  <br />
411
1245
 
1246
+ ---
1247
+
412
1248
  ## 🔧 Auto-fixing
413
1249
 
414
1250
  All rules support auto-fixing. Run ESLint with the `--fix` flag: