eslint-plugin-code-style 1.0.16 → 1.0.34

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 (3) hide show
  1. package/README.md +1339 -461
  2. package/index.js +800 -463
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -17,7 +17,7 @@
17
17
 
18
18
  **A powerful ESLint plugin for enforcing consistent code formatting and style rules in React/JSX projects.**
19
19
 
20
- *47 auto-fixable rules to keep your codebase clean and consistent*
20
+ *48 auto-fixable rules to keep your codebase clean and consistent*
21
21
 
22
22
  </div>
23
23
 
@@ -25,15 +25,15 @@
25
25
 
26
26
  ## 🎯 Why This Plugin?
27
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.
28
+ This plugin provides **48 custom auto-fixable rules** for code formatting. Built for **ESLint v9 flat configs**.
29
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
30
+ > **Note:** ESLint [deprecated 79 formatting rules](https://eslint.org/blog/2023/10/deprecating-formatting-rules/) in v8.53.0. Our recommended configs use `@stylistic/eslint-plugin` as the replacement for these deprecated rules.
35
31
 
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.
32
+ **Key Benefits:**
33
+ - **Fills the gaps** — Provides formatting rules not available in other plugins
34
+ - **Self-sufficient rules** — Each rule handles complete formatting independently
35
+ - **Consistency at scale** — Reduces code-style differences between team members by ~95%
36
+ - **Fully automated** — All 48 rules support auto-fix, eliminating manual style reviews
37
37
 
38
38
  <div align="center">
39
39
 
@@ -55,7 +55,7 @@ We provide **ready-to-use ESLint flat configuration files** that combine `eslint
55
55
 
56
56
  ### 💡 Why Use These Configs?
57
57
 
58
- - **Complete Coverage** — Combines ESLint built-in rules, third-party plugins, and all 47 code-style rules
58
+ - **Complete Coverage** — Combines ESLint built-in rules, third-party plugins, and all 48 code-style rules
59
59
  - **Ready-to-Use** — Copy the config file and start linting immediately
60
60
  - **Battle-Tested** — These configurations have been refined through real-world usage
61
61
  - **Fully Documented** — Each config includes detailed instructions and explanations
@@ -91,7 +91,7 @@ We provide **ready-to-use ESLint flat configuration files** that combine `eslint
91
91
  <td width="50%">
92
92
 
93
93
  ### 🔧 Auto-Fixable Rules
94
- All **47 rules** support automatic fixing with `eslint --fix`. No manual code changes needed.
94
+ All **48 rules** support automatic fixing with `eslint --fix`. No manual code changes needed.
95
95
 
96
96
  </td>
97
97
  <td width="50%">
@@ -207,8 +207,7 @@ rules: {
207
207
  "code-style/jsx-string-value-trim": "error",
208
208
  "code-style/jsx-ternary-format": "error",
209
209
  "code-style/member-expression-bracket-spacing": "error",
210
- "code-style/multiline-argument-newline": "error",
211
- "code-style/multiple-arguments-per-line": "error",
210
+ "code-style/function-arguments-format": "error",
212
211
  "code-style/nested-call-closing-brackets": "error",
213
212
  "code-style/no-empty-lines-in-function-calls": "error",
214
213
  "code-style/no-empty-lines-in-function-params": "error",
@@ -232,60 +231,59 @@ rules: {
232
231
 
233
232
  ## 📖 Rules Summary
234
233
 
235
- > All **47 rules** are auto-fixable. See detailed examples for each rule in the [Rules Reference](#-rules-reference) section below.
234
+ > All **48 rules** are auto-fixable. See detailed examples for each rule in the [Rules Reference](#-rules-reference) section below.
236
235
  >
237
236
  > Rules marked with ⚙️ support customization options (e.g., extending default folder lists).
238
237
 
239
238
  | Rule | Description |
240
239
  |------|-------------|
241
- | `array-items-per-line` | Enforce array formatting: 3 or less items on one line, more than 3 each on new line |
242
- | `array-objects-on-new-lines` | Enforce array of objects to have each object on a new line |
243
- | `arrow-function-block-body` | Enforce parentheses for arrow functions with multiline expressions |
244
- | `arrow-function-simple-jsx` | Simplify arrow functions returning simple JSX to single line |
245
- | `arrow-function-simplify` | Simplify arrow functions in JSX props with single statement block body |
246
- | `curried-arrow-same-line` | Enforce curried arrow function to start on same line as `=>` |
247
- | `assignment-value-same-line` | Enforce assignment value on same line as equals sign |
248
- | `block-statement-newlines` | Enforce newlines after opening brace and before closing brace |
249
- | `comment-spacing` | Enforce comment spacing and formatting |
250
- | `function-call-spacing` | Enforce no space between function name and opening parenthesis |
251
- | `function-naming-convention` | Enforce function naming conventions (camelCase, verb prefix) |
252
- | `function-params-per-line` | Enforce function parameters on separate lines when multiline |
253
- | `hook-callback-format` | Enforce consistent formatting for React hooks callbacks |
254
- | `hook-deps-per-line` | Enforce each hook dependency on its own line when more than 2 |
255
- | `if-statement-format` | Ensure if statement has proper formatting |
256
- | `multiline-if-conditions` | Enforce multiline if conditions when there are multiple operands |
257
- | `absolute-imports-only` | Enforce absolute imports using `@/` alias instead of relative paths ⚙️ |
258
- | `export-format` | Format exports: collapse 1-3 specifiers, multiline for 4+ |
259
- | `import-format` | Format imports: collapse 1-3 specifiers, multiline for 4+ |
260
- | `import-source-spacing` | Enforce no extra spaces inside import path quotes |
261
- | `index-export-style` | Enforce consistent export style in index files (shorthand or import-then-export) ⚙️ |
262
- | `module-index-exports` | Enforce proper exports in index files ⚙️ |
263
- | `jsx-children-on-new-line` | Enforce JSX children on separate lines from parent tags |
240
+ | `array-items-per-line` | Collapse arrays threshold to one line; expand larger arrays with each item on own line (default: ≤3) ⚙️ |
241
+ | `array-objects-on-new-lines` | Each object in an array starts on its own line for better visual scanning |
242
+ | `arrow-function-block-body` | Wrap multiline arrow function expressions in parentheses for clear boundaries |
243
+ | `arrow-function-simple-jsx` | Collapse arrow functions returning simple single-element JSX to one line, remove unnecessary parens |
244
+ | `arrow-function-simplify` | Convert block body with single return to implicit return: `() => { return x; }` → `() => x` |
245
+ | `curried-arrow-same-line` | Curried arrow functions start on same line as `=>`, not on new line |
246
+ | `assignment-value-same-line` | Assignment values start on same line as `=`, not on new line |
247
+ | `block-statement-newlines` | Newline after `{` and before `}` in if/for/while/function blocks |
248
+ | `comment-spacing` | Space after `//`, space inside `/* */`, convert single-line blocks to `//`, no blank lines between file-top comments |
249
+ | `function-call-spacing` | No space between function name and `(`: `fn()` not `fn ()` |
250
+ | `function-naming-convention` | Functions use camelCase, start with verb (get/set/handle/is/has), handlers end with Handler |
251
+ | `function-params-per-line` | When multiline, each param on own line with consistent indentation |
252
+ | `hook-callback-format` | React hooks: callback on new line, deps array on separate line, proper indentation |
253
+ | `hook-deps-per-line` | Collapse deps ≤ threshold to one line; expand larger arrays with each dep on own line (default: >2) ⚙️ |
254
+ | `if-statement-format` | `{` on same line as `if`/`else if`, `else` on same line as `}`, proper spacing |
255
+ | `multiline-if-conditions` | Conditions exceeding threshold get one operand per line with proper indentation (default: >3) ⚙️ |
256
+ | `absolute-imports-only` | Use alias imports from index files only (not deep paths), no relative imports (default: `@/`) ⚙️ |
257
+ | `export-format` | `export {` on same line; collapse threshold to one line; expand larger with each specifier on own line (default: ≤3) ⚙️ |
258
+ | `import-format` | `import {` and `} from` on same line; collapse threshold; expand larger with each specifier on own line (default: ≤3) ⚙️ |
259
+ | `import-source-spacing` | No leading/trailing spaces inside import path quotes |
260
+ | `index-export-style` | Index files: no blank lines, enforce shorthand or import-export style; Regular files: require blank lines between exports (default: shorthand) ⚙️ |
261
+ | `module-index-exports` | Index files must export all folder contents (files and subfolders) ⚙️ |
262
+ | `jsx-children-on-new-line` | Multiple JSX children: each on own line with proper indentation |
264
263
  | `jsx-closing-bracket-spacing` | No space before `>` or `/>` in JSX tags |
265
- | `jsx-element-child-new-line` | JSX element children must be on new lines |
266
- | `jsx-logical-expression-simplify` | Simplify logical expressions in JSX |
267
- | `jsx-parentheses-position` | Enforce opening parenthesis position for JSX in arrow functions |
268
- | `jsx-prop-naming-convention` | Enforce JSX prop naming conventions (camelCase) |
269
- | `jsx-simple-element-one-line` | Simple JSX elements with single child on one line |
270
- | `jsx-string-value-trim` | Disallow leading/trailing whitespace in JSX string values |
271
- | `jsx-ternary-format` | Enforce consistent formatting for JSX ternary expressions |
272
- | `member-expression-bracket-spacing` | Enforce no spaces inside brackets for member expressions |
273
- | `multiline-argument-newline` | Enforce newlines for function calls with multiline arguments |
274
- | `multiple-arguments-per-line` | Enforce multiple arguments to each be on their own line |
275
- | `nested-call-closing-brackets` | Enforce nested function call closing brackets on same line |
276
- | `no-empty-lines-in-function-calls` | Disallow empty lines in function calls |
277
- | `no-empty-lines-in-function-params` | Disallow empty lines in function parameters |
278
- | `no-empty-lines-in-jsx` | Disallow empty lines inside JSX elements |
279
- | `no-empty-lines-in-objects` | Disallow empty lines inside objects |
280
- | `no-empty-lines-in-switch-cases` | Prevent empty lines at the beginning of switch case logic |
281
- | `object-property-per-line` | Enforce each property on its own line when object has 2+ properties |
282
- | `object-property-value-brace` | Enforce opening brace on same line as colon for object values |
283
- | `object-property-value-format` | Enforce property value on same line as colon |
284
- | `opening-brackets-same-line` | Enforce opening brackets on same line for function calls |
285
- | `simple-call-single-line` | Simplify simple function calls with arrow function to single line |
286
- | `single-argument-on-one-line` | Enforce single simple argument calls to be on one line |
287
- | `string-property-spacing` | Enforce no extra spaces inside string property keys |
288
- | `variable-naming-convention` | Enforce variable naming conventions (camelCase, UPPER_CASE, PascalCase) |
264
+ | `jsx-element-child-new-line` | Nested JSX elements on new lines; text/expression children can stay inline |
265
+ | `jsx-logical-expression-simplify` | Remove unnecessary parens around conditions and JSX in logical expressions |
266
+ | `jsx-parentheses-position` | Opening `(` for multiline JSX on same line as `return`/`=>`, not on new line |
267
+ | `jsx-prop-naming-convention` | Props: camelCase for regular, kebab-case for data-*/aria-*, PascalCase for component refs |
268
+ | `jsx-simple-element-one-line` | Collapse simple JSX with single text/expression child to one line |
269
+ | `jsx-string-value-trim` | No leading/trailing whitespace inside JSX string attribute values |
270
+ | `jsx-ternary-format` | Simple ternaries on one line; complex branches get parens with proper indentation |
271
+ | `member-expression-bracket-spacing` | No spaces inside brackets in computed member expressions: `arr[0]` not `arr[ 0 ]` |
272
+ | `function-arguments-format` | Args threshold or multiline: first arg on new line, each on own line, closing `)` on new line (default: ≥2) ⚙️ |
273
+ | `nested-call-closing-brackets` | Chain closing brackets on same line: `}));` not scattered across lines |
274
+ | `no-empty-lines-in-function-calls` | No empty lines between arguments or after `(`/before `)` |
275
+ | `no-empty-lines-in-function-params` | No empty lines between parameters or after `(`/before `)` |
276
+ | `no-empty-lines-in-jsx` | No empty lines between children or after opening/before closing tags |
277
+ | `no-empty-lines-in-objects` | No empty lines between properties or after `{`/before `}` |
278
+ | `no-empty-lines-in-switch-cases` | No empty line after `case X:` before code, no empty lines between cases |
279
+ | `object-property-per-line` | Collapse threshold to one line; expand larger with `{`/`}` on own lines and each property on own line (default: ≥2) ⚙️ |
280
+ | `object-property-value-brace` | Opening `{` of object value on same line as `:`, not on new line |
281
+ | `object-property-value-format` | Simple property values on same line as `:`, not on new line |
282
+ | `opening-brackets-same-line` | Opening `{`, `[`, or `(` on same line as function call, not on new line |
283
+ | `simple-call-single-line` | Collapse simple `fn(() => call())` patterns to single line |
284
+ | `single-argument-on-one-line` | Single simple argument stays on one line: `fn(x)` not expanded |
285
+ | `string-property-spacing` | No leading/trailing spaces inside string property keys |
286
+ | `variable-naming-convention` | camelCase for variables, UPPER_CASE for constants, PascalCase for components, `use` prefix for hooks |
289
287
 
290
288
  <br />
291
289
 
@@ -301,40 +299,72 @@ rules: {
301
299
 
302
300
  ### `array-items-per-line`
303
301
 
304
- Enforce array formatting based on item count. 3 or less items on one line, more than 3 items each on its own line.
302
+ **What it does:** Controls array formatting based on the number of items. Short arrays stay on one line for compactness, while longer arrays get expanded with each item on its own line for better readability.
303
+
304
+ **Why use it:** Prevents overly long single-line arrays that are hard to scan, while avoiding unnecessary vertical expansion for simple arrays.
305
305
 
306
306
  ```javascript
307
- // Good
308
- const arr = [1, 2, 3];
309
- const arr = [
310
- item1,
311
- item2,
312
- item3,
313
- item4,
307
+ // Good — 3 or fewer items stay compact
308
+ const colors = ["red", "green", "blue"];
309
+ const nums = [1, 2, 3];
310
+
311
+ // ✅ Good — 4+ items expand for readability
312
+ const weekdays = [
313
+ "Monday",
314
+ "Tuesday",
315
+ "Wednesday",
316
+ "Thursday",
317
+ "Friday",
314
318
  ];
315
319
 
316
- // Bad
317
- const arr = [1, 2, 3, 4, 5];
318
- const arr = [item1,
319
- item2, item3];
320
+ // Bad — too many items on one line
321
+ const weekdays = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"];
322
+
323
+ // ❌ Bad — inconsistent formatting
324
+ const items = [item1,
325
+ item2, item3,
326
+ item4];
327
+ ```
328
+
329
+ **Options:**
330
+
331
+ | Option | Type | Default | Description |
332
+ |--------|------|---------|-------------|
333
+ | `maxItems` | `integer` | `3` | Maximum items to keep on single line |
334
+
335
+ ```javascript
336
+ // Example: Allow up to 4 items on single line
337
+ "code-style/array-items-per-line": ["error", { maxItems: 4 }]
320
338
  ```
321
339
 
322
340
  ---
323
341
 
324
342
  ### `array-objects-on-new-lines`
325
343
 
326
- In arrays of objects, each object should start on a new line for better readability.
344
+ **What it does:** In arrays containing objects, ensures each object starts on its own line regardless of object size.
345
+
346
+ **Why use it:** Object literals in arrays are visually complex. Putting each on its own line makes it easier to scan, compare, and edit individual items.
327
347
 
328
348
  ```javascript
329
- // Good
330
- const items = [
331
- { id: 1, name: "first" },
332
- { id: 2, name: "second" },
349
+ // Good — each object clearly separated
350
+ const users = [
351
+ { id: 1, name: "Alice", role: "admin" },
352
+ { id: 2, name: "Bob", role: "user" },
353
+ { id: 3, name: "Charlie", role: "user" },
354
+ ];
355
+
356
+ // ✅ Good — even short objects get their own line
357
+ const points = [
358
+ { x: 0, y: 0 },
359
+ { x: 10, y: 20 },
333
360
  ];
334
361
 
335
- // Bad
336
- const items = [{ id: 1, name: "first" },
337
- { id: 2, name: "second" }];
362
+ // Bad — objects crammed together
363
+ const users = [{ id: 1, name: "Alice" }, { id: 2, name: "Bob" }];
364
+
365
+ // ❌ Bad — inconsistent line breaks
366
+ const items = [{ id: 1 },
367
+ { id: 2 }, { id: 3 }];
338
368
  ```
339
369
 
340
370
  <br />
@@ -343,32 +373,56 @@ const items = [{ id: 1, name: "first" },
343
373
 
344
374
  ### `arrow-function-block-body`
345
375
 
346
- Arrow functions with complex logic should use block body. Ensures consistent formatting when function body needs multiple statements or complex expressions.
376
+ **What it does:** Ensures arrow functions with multiline expressions use block body with explicit return, wrapped in parentheses when needed.
377
+
378
+ **Why use it:** Multiline expressions without block body can be confusing. Clear boundaries with `{` and `}` make the function body obvious.
347
379
 
348
380
  ```javascript
349
- // Good
350
- () => {
351
- doSomething();
352
- return value;
353
- }
381
+ // Good — block body for complex logic
382
+ const handleSubmit = () => {
383
+ validateForm();
384
+ submitData();
385
+ return result;
386
+ };
387
+
388
+ // ✅ Good — multiline JSX wrapped properly
389
+ const Button = () => (
390
+ <button className="primary">
391
+ Click me
392
+ </button>
393
+ );
394
+
395
+ // ❌ Bad — comma operator is confusing
396
+ const handleSubmit = () => (validateForm(), submitData(), result);
354
397
 
355
- // Bad
356
- () => (doSomething(), value)
398
+ // Bad — multiline without clear boundaries
399
+ const Button = () => <button className="primary">
400
+ Click me
401
+ </button>;
357
402
  ```
358
403
 
359
404
  ---
360
405
 
361
406
  ### `arrow-function-simple-jsx`
362
407
 
363
- Simplify arrow functions returning simple JSX to single line by removing unnecessary parentheses and line breaks.
408
+ **What it does:** Collapses arrow functions that return a single simple JSX element onto one line by removing unnecessary parentheses and line breaks.
409
+
410
+ **Why use it:** Simple component wrappers don't need multi-line formatting. Single-line is more scannable and reduces vertical space.
364
411
 
365
412
  ```javascript
366
- // Good
367
- export const X = ({ children }) => <Sidebar>{children}</Sidebar>;
413
+ // Good — simple JSX on one line
414
+ export const Layout = ({ children }) => <Container>{children}</Container>;
415
+ export const Icon = () => <SVGIcon />;
416
+ const Wrapper = (props) => <div {...props} />;
417
+
418
+ // ❌ Bad — unnecessary multi-line for simple JSX
419
+ export const Layout = ({ children }) => (
420
+ <Container>{children}</Container>
421
+ );
368
422
 
369
- // Bad
370
- export const X = ({ children }) => (
371
- <Sidebar>{children}</Sidebar>
423
+ // Bad — extra parentheses not needed
424
+ const Icon = () => (
425
+ <SVGIcon />
372
426
  );
373
427
  ```
374
428
 
@@ -376,36 +430,52 @@ export const X = ({ children }) => (
376
430
 
377
431
  ### `arrow-function-simplify`
378
432
 
379
- Simplify arrow functions that have a single return statement by using implicit return instead of block body.
433
+ **What it does:** Converts arrow functions with a single return statement to use implicit return, removing the block body and `return` keyword.
380
434
 
381
- ```javascript
382
- // Good
383
- () => value
384
- (x) => x * 2
385
- items.map(item => item.name)
435
+ **Why use it:** Implicit returns are more concise and idiomatic JavaScript. They reduce noise and make the code easier to read.
386
436
 
387
- // Bad
388
- () => { return value; }
389
- (x) => { return x * 2; }
390
- items.map(item => { return item.name; })
437
+ ```javascript
438
+ // Good implicit return
439
+ const double = (x) => x * 2;
440
+ const getName = (user) => user.name;
441
+ const items = data.map((item) => item.value);
442
+ const isValid = (x) => x > 0 && x < 100;
443
+
444
+ // ❌ Bad — unnecessary block body and return
445
+ const double = (x) => { return x * 2; };
446
+ const getName = (user) => { return user.name; };
447
+ const items = data.map((item) => { return item.value; });
448
+ const isValid = (x) => { return x > 0 && x < 100; };
391
449
  ```
392
450
 
393
451
  ---
394
452
 
395
453
  ### `curried-arrow-same-line`
396
454
 
397
- Curried arrow function body must start on the same line as the arrow (=>), not on a new line.
455
+ **What it does:** Ensures that when an arrow function returns another function, the returned function starts on the same line as `=>`.
456
+
457
+ **Why use it:** Curried functions are easier to read when the chain is visible. Breaking after `=>` obscures the function structure.
398
458
 
399
459
  ```javascript
400
- // Good
401
- const fn = () => async (dispatch) => {
402
- dispatch(action);
460
+ // Good — curried function visible on same line
461
+ const createAction = (type) => (payload) => ({ type, payload });
462
+
463
+ const withLogger = (fn) => (...args) => {
464
+ console.log("Called with:", args);
465
+ return fn(...args);
466
+ };
467
+
468
+ const mapDispatch = () => async (dispatch) => {
469
+ await dispatch(fetchData());
403
470
  };
404
471
 
405
- // Bad
406
- const fn = () =>
472
+ // Bad — chain broken across lines
473
+ const createAction = (type) =>
474
+ (payload) => ({ type, payload });
475
+
476
+ const mapDispatch = () =>
407
477
  async (dispatch) => {
408
- dispatch(action);
478
+ await dispatch(fetchData());
409
479
  };
410
480
  ```
411
481
 
@@ -415,111 +485,192 @@ const fn = () =>
415
485
 
416
486
  ### `assignment-value-same-line`
417
487
 
418
- The value in an assignment should start on the same line as the equals sign, not on a new line.
488
+ **What it does:** Ensures the assigned value starts on the same line as the `=` sign, not on a new line.
489
+
490
+ **Why use it:** Breaking after `=` creates awkward formatting and wastes vertical space. Keeping values on the same line as `=` is more readable.
419
491
 
420
492
  ```javascript
421
- // Good
493
+ // Good — value starts on same line as =
422
494
  const name = "John";
423
- const data = {
424
- key: "value",
495
+ const config = {
496
+ host: "localhost",
497
+ port: 3000,
425
498
  };
499
+ const items = [
500
+ "first",
501
+ "second",
502
+ ];
426
503
 
427
- // Bad
504
+ // Bad — value on new line after =
428
505
  const name =
429
506
  "John";
430
- const data =
507
+ const config =
431
508
  {
432
- key: "value",
509
+ host: "localhost",
510
+ port: 3000,
433
511
  };
512
+ const items =
513
+ [
514
+ "first",
515
+ "second",
516
+ ];
434
517
  ```
435
518
 
436
519
  ---
437
520
 
438
521
  ### `block-statement-newlines`
439
522
 
440
- Block statements should have proper newlines after the opening brace and before the closing brace.
523
+ **What it does:** Enforces newlines after the opening brace `{` and before the closing brace `}` in block statements (if, for, while, etc.).
524
+
525
+ **Why use it:** Consistent block formatting improves readability. Single-line blocks are harder to scan and edit.
441
526
 
442
527
  ```javascript
443
- // Good
528
+ // Good — proper block formatting
444
529
  if (condition) {
445
530
  doSomething();
446
531
  }
447
532
 
448
- // Bad
533
+ for (const item of items) {
534
+ process(item);
535
+ }
536
+
537
+ while (running) {
538
+ tick();
539
+ }
540
+
541
+ // ❌ Bad — everything on one line
449
542
  if (condition) { doSomething(); }
543
+
544
+ // ❌ Bad — no space after brace
450
545
  if (condition) {doSomething();}
546
+
547
+ // ❌ Bad — inconsistent formatting
548
+ for (const item of items) { process(item);
549
+ }
451
550
  ```
452
551
 
453
552
  ---
454
553
 
455
554
  ### `comment-spacing`
456
555
 
457
- Comments should have proper spacing: a space after the opening delimiter (// or block comment opener), and proper blank lines around comment blocks.
556
+ **What it does:** Enforces proper comment formatting:
557
+ - Space after `//` in line comments
558
+ - Space after `/*` and before `*/` in block comments
559
+ - Single-line block comments converted to line comments
560
+ - No blank lines between consecutive comments at file top
561
+
562
+ **Why use it:** Consistent comment formatting improves readability and maintains a clean, professional codebase.
458
563
 
459
564
  ```javascript
460
- // Good
565
+ // Good — proper spacing
461
566
  // This is a comment
462
567
  /* This is a block comment */
463
568
 
464
- // Bad
465
- //This is a comment (missing space)
466
- /*No space after opener*/
569
+ /*
570
+ * This is a multi-line
571
+ * block comment
572
+ */
573
+
574
+ // ✅ Good — file-top comments without gaps
575
+ // File: utils.js
576
+ // Author: John Doe
577
+ // License: MIT
578
+
579
+ // ❌ Bad — missing space after //
580
+ //This is a comment
581
+
582
+ // ❌ Bad — no space in block comment
583
+ /*No space*/
584
+
585
+ // ❌ Bad — single-line block should be line comment
586
+ /* This should use // syntax */
467
587
  ```
468
588
 
469
589
  ---
470
590
 
471
591
  ### `member-expression-bracket-spacing`
472
592
 
473
- No spaces inside brackets in computed member expressions. The property name should touch both brackets.
593
+ **What it does:** Removes spaces inside brackets in computed member expressions (array access, dynamic property access).
474
594
 
475
- ```javascript
476
- // Good
477
- arr[value]
478
- obj[key]
595
+ **Why use it:** Consistent with JavaScript conventions. Spaces inside brackets look inconsistent with array literals and other bracket usage.
479
596
 
480
- // Bad
481
- arr[ value ]
482
- obj[ key ]
597
+ ```javascript
598
+ // Good — no spaces inside brackets
599
+ const value = arr[0];
600
+ const name = obj[key];
601
+ const item = data[index];
602
+ const nested = matrix[row][col];
603
+
604
+ // ❌ Bad — spaces inside brackets
605
+ const value = arr[ 0 ];
606
+ const name = obj[ key ];
607
+ const item = data[ index ];
483
608
  ```
484
609
 
485
610
  ---
486
611
 
487
612
  ### `no-empty-lines-in-function-params`
488
613
 
489
- Function parameter lists should not contain empty lines between parameters or after opening/before closing parens.
614
+ **What it does:** Removes empty lines within function parameter lists — between parameters and after opening/before closing parentheses.
615
+
616
+ **Why use it:** Empty lines in parameter lists waste space and make parameters harder to scan as a group.
490
617
 
491
618
  ```javascript
492
- // Good
493
- function test(
494
- param1,
495
- param2,
619
+ // Good — no empty lines
620
+ function createUser(
621
+ name,
622
+ email,
623
+ role,
496
624
  ) {}
497
625
 
498
- // Bad
499
- function test(
500
- param1,
626
+ const handler = (
627
+ event,
628
+ context,
629
+ ) => {};
501
630
 
502
- param2,
631
+ // ❌ Bad — empty line between params
632
+ function createUser(
633
+ name,
634
+
635
+ email,
636
+
637
+ role,
503
638
  ) {}
639
+
640
+ // ❌ Bad — empty line after opening paren
641
+ const handler = (
642
+
643
+ event,
644
+ context,
645
+ ) => {};
504
646
  ```
505
647
 
506
648
  ---
507
649
 
508
650
  ### `variable-naming-convention`
509
651
 
510
- Variable names should follow naming conventions: camelCase for regular variables, UPPER_CASE for constants, and PascalCase for React components.
652
+ **What it does:** Enforces naming conventions for variables:
653
+ - **camelCase** for regular variables and functions
654
+ - **UPPER_CASE** for constants (primitive values)
655
+ - **PascalCase** for React components and classes
656
+ - **camelCase with `use` prefix** for hooks
511
657
 
512
- ```javascript
513
- // Good
514
- const userName = "John";
515
- const MAX_RETRIES = 3;
516
- const UserProfile = () => <div />;
517
- const useCustomHook = () => {};
658
+ **Why use it:** Consistent naming makes code predictable. You can tell what something is by how it's named.
518
659
 
519
- // Bad
520
- const user_name = "John";
521
- const maxretries = 3;
522
- const userProfile = () => <div />;
660
+ ```javascript
661
+ // Good — correct conventions
662
+ const userName = "John"; // camelCase for variables
663
+ const itemCount = 42; // camelCase for variables
664
+ const MAX_RETRIES = 3; // UPPER_CASE for constants
665
+ const API_BASE_URL = "/api"; // UPPER_CASE for constants
666
+ const UserProfile = () => <div />; // PascalCase for components
667
+ const useAuth = () => {}; // camelCase with use prefix for hooks
668
+
669
+ // ❌ Bad — wrong conventions
670
+ const user_name = "John"; // snake_case
671
+ const maxretries = 3; // should be UPPER_CASE
672
+ const userProfile = () => <div />; // should be PascalCase
673
+ const UseAuth = () => {}; // hooks should be camelCase
523
674
  ```
524
675
 
525
676
  <br />
@@ -528,54 +679,94 @@ const userProfile = () => <div />;
528
679
 
529
680
  ### `function-call-spacing`
530
681
 
531
- No space between function name and opening parenthesis.
682
+ **What it does:** Removes any space between a function name and its opening parenthesis.
532
683
 
533
- ```javascript
534
- // Good
535
- useDispatch()
536
- myFunction(arg)
684
+ **Why use it:** Standard JavaScript convention. `fn()` is correct, `fn ()` looks like a typo and can cause confusion.
537
685
 
538
- // Bad
539
- useDispatch ()
540
- myFunction (arg)
686
+ ```javascript
687
+ // ✅ Good — no space before parenthesis
688
+ useDispatch();
689
+ myFunction(arg);
690
+ console.log("message");
691
+ array.map((x) => x * 2);
692
+ obj.method();
693
+
694
+ // ❌ Bad — space before parenthesis
695
+ useDispatch ();
696
+ myFunction (arg);
697
+ console.log ("message");
698
+ array.map ((x) => x * 2);
541
699
  ```
542
700
 
543
701
  ---
544
702
 
545
703
  ### `function-naming-convention`
546
704
 
547
- Function names should follow naming conventions: camelCase, starting with a verb, and handlers ending with "Handler".
705
+ **What it does:** Enforces naming conventions for functions:
706
+ - **camelCase** required
707
+ - **Verb prefix** recommended (get, set, handle, is, has, can, should, etc.)
708
+ - **Event handlers** can use `handle` prefix or `Handler` suffix
709
+
710
+ **Why use it:** Function names should describe actions. Verb prefixes make the purpose immediately clear.
548
711
 
549
712
  ```javascript
550
- // Good
713
+ // Good — clear verb prefixes
551
714
  function getUserData() {}
715
+ function setUserName(name) {}
552
716
  function handleClick() {}
553
- function isValidEmail() {}
554
- const submitHandler = () => {}
717
+ function handleSubmit() {}
718
+ function isValidEmail(email) {}
719
+ function hasPermission(user) {}
720
+ function canAccess(resource) {}
721
+ function shouldUpdate(props) {}
722
+ const fetchUsers = async () => {};
723
+ const submitHandler = () => {};
724
+
725
+ // ❌ Bad — no verb, unclear purpose
726
+ function userData() {}
727
+ function userName(name) {}
728
+ function click() {}
729
+ function valid(email) {}
555
730
 
556
- // Bad
731
+ // Bad — wrong case
557
732
  function GetUserData() {}
558
- function user_data() {}
559
- function click() {}
733
+ function get_user_data() {}
560
734
  ```
561
735
 
562
736
  ---
563
737
 
564
738
  ### `function-params-per-line`
565
739
 
566
- When function parameters span multiple lines, each parameter should be on its own line with consistent indentation.
740
+ **What it does:** When function parameters span multiple lines, ensures each parameter is on its own line with consistent indentation.
741
+
742
+ **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.
567
743
 
568
744
  ```javascript
569
- // Good
570
- function test(
571
- param1,
572
- param2,
573
- param3,
745
+ // Good — each param on own line
746
+ function createUser(
747
+ name,
748
+ email,
749
+ password,
750
+ role,
574
751
  ) {}
575
752
 
576
- // Bad
577
- function test(param1,
578
- param2, param3) {}
753
+ const handler = (
754
+ event,
755
+ context,
756
+ callback,
757
+ ) => {};
758
+
759
+ // ✅ Good — short params can stay on one line
760
+ function add(a, b) {}
761
+
762
+ // ❌ Bad — mixed formatting
763
+ function createUser(name,
764
+ email, password,
765
+ role) {}
766
+
767
+ // ❌ Bad — some on same line, some not
768
+ const handler = (event, context,
769
+ callback) => {};
579
770
  ```
580
771
 
581
772
  <br />
@@ -584,36 +775,99 @@ function test(param1,
584
775
 
585
776
  ### `hook-callback-format`
586
777
 
587
- Enforce consistent formatting for React hooks like useEffect, useCallback, useMemo with callback and dependency array.
778
+ **What it does:** Enforces consistent multi-line formatting for React hooks that take a callback and dependency array (useEffect, useCallback, useMemo, useLayoutEffect).
779
+
780
+ **Why use it:** Hooks with callbacks and dependencies are complex. Multi-line formatting makes the callback, return cleanup, and dependencies clearly visible.
588
781
 
589
782
  ```javascript
590
- // Good
783
+ // Good — callback and deps clearly separated
591
784
  useEffect(
592
- () => { doSomething(); },
593
- [dep1, dep2],
785
+ () => {
786
+ fetchData();
787
+ },
788
+ [userId],
789
+ );
790
+
791
+ useCallback(
792
+ () => {
793
+ handleSubmit(data);
794
+ },
795
+ [data, handleSubmit],
594
796
  );
595
797
 
596
- // Bad
597
- useEffect(() => { doSomething(); }, [dep1, dep2]);
798
+ useMemo(
799
+ () => expensiveCalculation(items),
800
+ [items],
801
+ );
802
+
803
+ // ✅ Good — cleanup function visible
804
+ useEffect(
805
+ () => {
806
+ const subscription = subscribe();
807
+
808
+ return () => subscription.unsubscribe();
809
+ },
810
+ [subscribe],
811
+ );
812
+
813
+ // ❌ Bad — everything crammed on one line
814
+ useEffect(() => { fetchData(); }, [userId]);
815
+
816
+ // ❌ Bad — hard to see dependencies
817
+ useCallback(() => { handleSubmit(data); }, [data, handleSubmit]);
598
818
  ```
599
819
 
600
820
  ---
601
821
 
602
822
  ### `hook-deps-per-line`
603
823
 
604
- React hook dependency arrays with more than 2 dependencies should have each dependency on its own line.
824
+ **What it does:** When a hook's dependency array exceeds the threshold (default: 2), each dependency goes on its own line.
825
+
826
+ **Why use it:** Long dependency arrays are hard to scan and diff. One per line makes it easy to see what changed and catch missing/extra dependencies.
605
827
 
606
828
  ```javascript
607
- // Good
608
- useEffect(() => {}, [dep1, dep2])
829
+ // Good — 2 or fewer deps stay inline
830
+ useEffect(() => {}, [userId]);
831
+ useEffect(() => {}, [userId, token]);
832
+
833
+ // ✅ Good — 3+ deps get one per line
834
+ useEffect(
835
+ () => {},
836
+ [
837
+ userId,
838
+ token,
839
+ refreshToken,
840
+ ],
841
+ );
842
+
843
+ useCallback(
844
+ () => handleSubmit(data),
845
+ [
846
+ data,
847
+ handleSubmit,
848
+ validateForm,
849
+ showError,
850
+ ],
851
+ );
852
+
853
+ // ❌ Bad — too many deps on one line
854
+ useEffect(() => {}, [userId, token, refreshToken, apiUrl]);
855
+
856
+ // ❌ Bad — deps should be one per line when expanded
609
857
  useEffect(() => {}, [
610
- dep1,
611
- dep2,
612
- dep3,
613
- ])
858
+ userId, token, refreshToken,
859
+ ]);
860
+ ```
861
+
862
+ **Options:**
614
863
 
615
- // Bad
616
- useEffect(() => {}, [dep1, dep2, dep3, dep4])
864
+ | Option | Type | Default | Description |
865
+ |--------|------|---------|-------------|
866
+ | `maxDeps` | `integer` | `2` | Maximum dependencies to keep on single line |
867
+
868
+ ```javascript
869
+ // Example: Allow up to 3 dependencies on single line
870
+ "code-style/hook-deps-per-line": ["error", { maxDeps: 3 }]
617
871
  ```
618
872
 
619
873
  <br />
@@ -622,17 +876,48 @@ useEffect(() => {}, [dep1, dep2, dep3, dep4])
622
876
 
623
877
  ### `if-statement-format`
624
878
 
625
- 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.
879
+ **What it does:** Enforces consistent if/else formatting:
880
+ - Opening `{` on the same line as `if`/`else if`/`else`
881
+ - `else` on the same line as the closing `}`
882
+ - Proper spacing around keywords
883
+
884
+ **Why use it:** Consistent brace placement reduces visual noise and follows the most common JavaScript style (K&R / "one true brace style").
626
885
 
627
886
  ```javascript
628
- // Good
887
+ // Good — consistent formatting
888
+ if (condition) {
889
+ doSomething();
890
+ }
891
+
629
892
  if (condition) {
630
893
  doSomething();
631
894
  } else {
632
895
  doOther();
633
896
  }
634
897
 
635
- // Bad
898
+ if (conditionA) {
899
+ handleA();
900
+ } else if (conditionB) {
901
+ handleB();
902
+ } else {
903
+ handleDefault();
904
+ }
905
+
906
+ // ❌ Bad — brace on new line
907
+ if (condition)
908
+ {
909
+ doSomething();
910
+ }
911
+
912
+ // ❌ Bad — else on new line
913
+ if (condition) {
914
+ doSomething();
915
+ }
916
+ else {
917
+ doOther();
918
+ }
919
+
920
+ // ❌ Bad — inconsistent formatting
636
921
  if (condition)
637
922
  {
638
923
  doSomething();
@@ -647,44 +932,103 @@ else
647
932
 
648
933
  ### `multiline-if-conditions`
649
934
 
650
- When an if statement has multiple conditions that span multiple lines, each condition should be on its own line.
935
+ **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.
936
+
937
+ **Why use it:** Long conditions are hard to read on one line. One per line makes each condition clear and easy to modify.
651
938
 
652
939
  ```javascript
653
- // Good
940
+ // Good — 3 or fewer conditions stay inline
941
+ if (isValid && isActive) {}
942
+ if (a && b && c) {}
943
+
944
+ // ✅ Good — 4+ conditions get one per line
654
945
  if (
655
- conditionA &&
656
- conditionB &&
657
- conditionC
658
- ) {}
946
+ isAuthenticated &&
947
+ hasPermission &&
948
+ !isExpired &&
949
+ isEnabled
950
+ ) {
951
+ allowAccess();
952
+ }
953
+
954
+ if (
955
+ user.isAdmin ||
956
+ user.isModerator ||
957
+ user.hasSpecialAccess ||
958
+ isPublicResource
959
+ ) {
960
+ showContent();
961
+ }
659
962
 
660
- // Bad
661
- if (conditionA &&
662
- conditionB && conditionC) {}
963
+ // Bad — too many conditions on one line
964
+ if (isAuthenticated && hasPermission && !isExpired && isEnabled) {}
965
+
966
+ // ❌ Bad — inconsistent formatting
967
+ if (isAuthenticated &&
968
+ hasPermission && !isExpired &&
969
+ isEnabled) {}
970
+ ```
971
+
972
+ **Options:**
973
+
974
+ | Option | Type | Default | Description |
975
+ |--------|------|---------|-------------|
976
+ | `maxOperands` | `integer` | `3` | Maximum operands to keep on single line |
977
+
978
+ ```javascript
979
+ // Example: Allow up to 4 operands on single line
980
+ "code-style/multiline-if-conditions": ["error", { maxOperands: 4 }]
663
981
  ```
664
982
 
665
983
  ---
666
984
 
667
985
  ### `no-empty-lines-in-switch-cases`
668
986
 
669
- Switch case blocks should not have empty lines at the beginning of the case logic or between consecutive cases.
987
+ **What it does:** Removes empty lines at the start of case blocks and between consecutive case statements.
988
+
989
+ **Why use it:** Empty lines inside switch cases create unnecessary gaps. Cases should flow together as a cohesive block.
670
990
 
671
991
  ```javascript
672
- // Good
673
- switch (value) {
674
- case 1:
675
- return "one";
676
- case 2:
677
- return "two";
992
+ // Good — no empty lines
993
+ switch (status) {
994
+ case "pending":
995
+ return "Waiting...";
996
+ case "success":
997
+ return "Done!";
998
+ case "error":
999
+ return "Failed";
1000
+ default:
1001
+ return "Unknown";
1002
+ }
1003
+
1004
+ // ✅ Good — fall-through cases grouped
1005
+ switch (day) {
1006
+ case "Saturday":
1007
+ case "Sunday":
1008
+ return "Weekend";
1009
+ default:
1010
+ return "Weekday";
1011
+ }
1012
+
1013
+ // ❌ Bad — empty line after case label
1014
+ switch (status) {
1015
+ case "pending":
1016
+
1017
+ return "Waiting...";
1018
+ case "success":
1019
+ return "Done!";
678
1020
  }
679
1021
 
680
- // Bad
681
- switch (value) {
682
- case 1:
1022
+ // Bad — empty lines between cases
1023
+ switch (status) {
1024
+ case "pending":
1025
+ return "Waiting...";
683
1026
 
684
- return "one";
1027
+ case "success":
1028
+ return "Done!";
685
1029
 
686
- case 2:
687
- return "two";
1030
+ default:
1031
+ return "Unknown";
688
1032
  }
689
1033
  ```
690
1034
 
@@ -694,16 +1038,32 @@ switch (value) {
694
1038
 
695
1039
  ### `absolute-imports-only`
696
1040
 
697
- Enforce absolute imports from index files only for local paths. Local paths (starting with @/) should only import from folder-level index files.
1041
+ **What it does:** Enforces importing from folder index files using absolute paths (aliases like `@/`) instead of relative paths or deep file imports.
1042
+
1043
+ **Why use it:**
1044
+ - Absolute imports are cleaner than `../../../components`
1045
+ - Index imports create a public API for each folder
1046
+ - Refactoring file locations doesn't break imports
1047
+ - Encourages proper module organization
698
1048
 
699
1049
  ```javascript
700
- // Good
701
- import { Button } from "@/components";
702
- import { useAuth } from "@/hooks";
1050
+ // Good — import from index files using alias
1051
+ import { Button, Input } from "@/components";
1052
+ import { useAuth, useUser } from "@/hooks";
1053
+ import { fetchUsers } from "@/apis";
1054
+ import { formatDate } from "@/utils";
703
1055
 
704
- // Bad
1056
+ // ✅ Good — assets allow deep imports by default
1057
+ import logo from "@/assets/images/logo.png";
1058
+
1059
+ // ❌ Bad — relative imports
1060
+ import { Button } from "../../components";
1061
+ import { useAuth } from "../../../hooks";
1062
+
1063
+ // ❌ Bad — deep imports into component internals
705
1064
  import { Button } from "@/components/buttons/primary-button";
706
1065
  import { useAuth } from "@/hooks/auth/useAuth";
1066
+ import { fetchUsers } from "@/apis/users/fetchUsers";
707
1067
  ```
708
1068
 
709
1069
  **Default Allowed Folders:**
@@ -733,107 +1093,196 @@ import { useAuth } from "@/hooks/auth/useAuth";
733
1093
 
734
1094
  ### `export-format`
735
1095
 
736
- Export statements should have consistent formatting with proper spacing. Collapse 1-3 specifiers on one line, use multiline for 4+ specifiers.
1096
+ **What it does:** Formats export statements consistently:
1097
+ - `export {` always on the same line as `export` keyword
1098
+ - ≤3 specifiers stay on one line (collapsed)
1099
+ - 4+ specifiers get one per line (expanded)
1100
+ - Proper spacing and trailing commas
1101
+
1102
+ **Why use it:** Consistent export formatting improves readability. Short exports stay compact, long exports become scannable.
737
1103
 
738
1104
  ```javascript
739
- // Good
740
- export { a, b, c };
1105
+ // Good — 3 or fewer specifiers stay compact
1106
+ export { Button };
1107
+ export { Button, Input };
1108
+ export { Button, Input, Select };
1109
+
1110
+ // ✅ Good — 4+ specifiers expand with one per line
741
1111
  export {
742
- a,
743
- b,
744
- c,
745
- d,
1112
+ Button,
1113
+ Input,
1114
+ Select,
1115
+ Checkbox,
746
1116
  };
747
1117
 
748
- // Bad
749
- export {a,b,c};
750
- export { a, b, c, d, e };
1118
+ // ✅ Good — re-exports follow same rules
1119
+ export { Button, Input, Select } from "./components";
1120
+ export {
1121
+ createUser,
1122
+ updateUser,
1123
+ deleteUser,
1124
+ getUser,
1125
+ } from "./api";
1126
+
1127
+ // ❌ Bad — no spaces
1128
+ export {Button,Input,Select};
1129
+
1130
+ // ❌ Bad — keyword on different line
1131
+ export
1132
+ { Button };
1133
+
1134
+ // ❌ Bad — too many on one line
1135
+ export { Button, Input, Select, Checkbox, Radio };
1136
+ ```
1137
+
1138
+ **Options:**
1139
+
1140
+ | Option | Type | Default | Description |
1141
+ |--------|------|---------|-------------|
1142
+ | `maxSpecifiers` | `integer` | `3` | Maximum specifiers to keep on single line |
1143
+
1144
+ ```javascript
1145
+ "code-style/export-format": ["error", { maxSpecifiers: 4 }]
751
1146
  ```
752
1147
 
753
1148
  ---
754
1149
 
755
1150
  ### `import-format`
756
1151
 
757
- Import statements should have consistent formatting with proper spacing. Collapse 1-3 specifiers on one line, use multiline for 4+ specifiers.
1152
+ **What it does:** Formats import statements consistently:
1153
+ - `import {` on the same line as `import` keyword
1154
+ - `} from` on the same line as closing brace
1155
+ - ≤3 specifiers stay on one line (collapsed)
1156
+ - 4+ specifiers get one per line (expanded)
1157
+
1158
+ **Why use it:** Consistent import formatting improves readability and makes diffs cleaner when adding/removing imports.
758
1159
 
759
1160
  ```javascript
760
- // Good
761
- import { a, b, c } from "module";
1161
+ // Good — 3 or fewer specifiers stay compact
1162
+ import { useState } from "react";
1163
+ import { Button, Input } from "@/components";
1164
+ import { get, post, put } from "@/api";
1165
+
1166
+ // ✅ Good — 4+ specifiers expand with one per line
1167
+ import {
1168
+ useState,
1169
+ useEffect,
1170
+ useCallback,
1171
+ useMemo,
1172
+ } from "react";
1173
+
762
1174
  import {
763
- a,
764
- b,
765
- c,
766
- d,
767
- } from "module";
1175
+ Button,
1176
+ Input,
1177
+ Select,
1178
+ Checkbox,
1179
+ } from "@/components";
1180
+
1181
+ // ❌ Bad — no spaces
1182
+ import {useState,useEffect} from "react";
1183
+
1184
+ // ❌ Bad — keyword on different line
1185
+ import
1186
+ { Button } from "@/components";
768
1187
 
769
- // Bad
770
- import {a,b,c} from "module";
771
- import { a, b, c, d, e } from "module";
1188
+ // Bad — from on different line
1189
+ import { Button }
1190
+ from "@/components";
1191
+
1192
+ // ❌ Bad — too many on one line
1193
+ import { useState, useEffect, useCallback, useMemo, useRef } from "react";
1194
+ ```
1195
+
1196
+ **Options:**
1197
+
1198
+ | Option | Type | Default | Description |
1199
+ |--------|------|---------|-------------|
1200
+ | `maxSpecifiers` | `integer` | `3` | Maximum specifiers to keep on single line |
1201
+
1202
+ ```javascript
1203
+ "code-style/import-format": ["error", { maxSpecifiers: 4 }]
772
1204
  ```
773
1205
 
774
1206
  ---
775
1207
 
776
1208
  ### `import-source-spacing`
777
1209
 
778
- No spaces inside import path quotes. The module path should not have leading or trailing whitespace.
1210
+ **What it does:** Removes any leading or trailing whitespace inside import path strings.
1211
+
1212
+ **Why use it:** Spaces in module paths are almost always typos and can cause import resolution issues.
779
1213
 
780
1214
  ```javascript
781
- // Good
1215
+ // Good — no extra spaces
782
1216
  import { Button } from "@mui/material";
1217
+ import React from "react";
1218
+ import styles from "./styles.css";
783
1219
 
784
- // Bad
785
- import { Button } from " @mui/material ";
1220
+ // Bad — leading space
1221
+ import { Button } from " @mui/material";
1222
+
1223
+ // ❌ Bad — trailing space
1224
+ import React from "react ";
1225
+
1226
+ // ❌ Bad — both
1227
+ import styles from " ./styles.css ";
786
1228
  ```
787
1229
 
788
1230
  ---
789
1231
 
790
1232
  ### `index-export-style`
791
1233
 
792
- Enforce consistent export style in index files. Choose between shorthand re-exports or import-then-export pattern.
1234
+ **What it does:** Enforces different export formatting rules for index files vs regular files:
1235
+ - **Index files**: No blank lines between exports, use shorthand or import-export style
1236
+ - **Regular files**: Require blank lines between exports
1237
+
1238
+ **Why use it:** Index files are re-export aggregators and should be compact. Regular files benefit from spacing between exports for readability.
1239
+
1240
+ **Regular files (non-index):**
1241
+ ```javascript
1242
+ // ✅ Good — blank lines between exports
1243
+ export const API_URL = "/api";
1244
+
1245
+ export const MAX_RETRIES = 3;
1246
+
1247
+ export const fetchData = async () => {};
1248
+
1249
+ // ❌ Bad — no blank lines in regular file
1250
+ export const API_URL = "/api";
1251
+ export const MAX_RETRIES = 3;
1252
+ export const fetchData = async () => {};
1253
+ ```
793
1254
 
794
- **Style: "shorthand" (default)**
1255
+ **Index files — Style: "shorthand" (default):**
795
1256
  ```javascript
796
- // Good - shorthand re-exports
1257
+ // Good shorthand re-exports, no blank lines
797
1258
  export { Button } from "./button";
798
1259
  export { Input, Select } from "./form";
799
- export { StyledCard, StyledCardWithActions } from "./card";
1260
+ export { Modal } from "./modal";
1261
+ export { useAuth, useUser } from "./hooks";
800
1262
  ```
801
1263
 
802
- **Style: "import-export"**
1264
+ **Index files — Style: "import-export":**
803
1265
  ```javascript
804
- // Good - import then export
1266
+ // Good imports grouped, single export at bottom
805
1267
  import { Button } from "./button";
806
1268
  import { Input, Select } from "./form";
807
- import { StyledCard, StyledCardWithActions } from "./card";
1269
+ import { Modal } from "./modal";
808
1270
 
809
1271
  export {
810
1272
  Button,
811
1273
  Input,
1274
+ Modal,
812
1275
  Select,
813
- StyledCard,
814
- StyledCardWithActions,
815
1276
  };
816
1277
  ```
817
1278
 
818
- **Bad - mixing styles**
819
- ```javascript
820
- // Bad - don't mix shorthand with import-then-export
821
- export { Button } from "./button";
822
- import { Input } from "./input";
823
- export { Input };
824
- ```
825
-
826
- **Customization Options:**
1279
+ **Options:**
827
1280
 
828
1281
  | Option | Type | Default | Description |
829
1282
  |--------|------|---------|-------------|
830
- | `style` | `"shorthand"` \| `"import-export"` | `"shorthand"` | The export style to enforce |
1283
+ | `style` | `"shorthand"` \| `"import-export"` | `"shorthand"` | Export style for index files |
831
1284
 
832
1285
  ```javascript
833
- // Example: Use shorthand style (default)
834
- "code-style/index-export-style": "error"
835
-
836
- // Example: Use import-then-export style
837
1286
  "code-style/index-export-style": ["error", { style: "import-export" }]
838
1287
  ```
839
1288
 
@@ -841,37 +1290,45 @@ export { Input };
841
1290
 
842
1291
  ### `module-index-exports`
843
1292
 
844
- 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.
1293
+ **What it does:** Ensures module folders have index files that export all their contents, creating a proper public API for each module.
1294
+
1295
+ **Why use it:** Index files allow importing from the folder level (`@/components`) instead of deep paths (`@/components/Button/Button`). This enforces proper module boundaries.
845
1296
 
846
1297
  ```javascript
847
- // Good
848
- // index.js
1298
+ // Good — components/index.js exports everything
849
1299
  export { Button } from "./Button";
850
1300
  export { Input } from "./Input";
1301
+ export { Select } from "./Select";
1302
+ export { Modal } from "./Modal";
1303
+
1304
+ // Then consumers can import cleanly:
1305
+ import { Button, Input, Select } from "@/components";
851
1306
 
852
- // Bad
853
- // Missing exports in index.js
1307
+ // Bad — missing exports in index.js
1308
+ // If Button exists but isn't exported from index.js,
1309
+ // consumers have to use deep imports:
1310
+ import { Button } from "@/components/Button/Button"; // Avoid this!
854
1311
  ```
855
1312
 
856
1313
  **Default Module Folders:**
857
1314
  `apis`, `assets`, `atoms`, `components`, `constants`, `contexts`, `data`, `hooks`, `layouts`, `middlewares`, `providers`, `redux`, `requests`, `routes`, `schemas`, `services`, `styles`, `theme`, `utils`, `views`
858
1315
 
1316
+ **Default Ignore Patterns:**
1317
+ `index.js`, `index.jsx`, `index.ts`, `index.tsx`, `.DS_Store`, `__tests__`, `__mocks__`, `*.test.js`, `*.test.jsx`, `*.spec.js`, `*.spec.jsx`
1318
+
859
1319
  **Customization Options:**
860
1320
 
861
1321
  | Option | Type | Description |
862
1322
  |--------|------|-------------|
863
1323
  | `extraModuleFolders` | `string[]` | Add extra module folders to the default list |
864
1324
  | `extraLazyLoadFolders` | `string[]` | Add extra lazy load folders (default: `views`) |
865
- | `extraIgnorePatterns` | `string[]` | Add extra ignore patterns (supports wildcards like `*.stories.js`) |
1325
+ | `extraIgnorePatterns` | `string[]` | Add extra ignore patterns (supports wildcards) |
866
1326
  | `moduleFolders` | `string[]` | Replace default module folders entirely |
867
1327
  | `lazyLoadFolders` | `string[]` | Replace default lazy load folders entirely |
868
1328
  | `ignorePatterns` | `string[]` | Replace default ignore patterns entirely |
869
1329
 
870
- **Default Ignore Patterns:**
871
- `index.js`, `index.jsx`, `index.ts`, `index.tsx`, `.DS_Store`, `__tests__`, `__mocks__`, `*.test.js`, `*.test.jsx`, `*.spec.js`, `*.spec.jsx`
872
-
873
1330
  ```javascript
874
- // Example: Add custom folders and patterns to the defaults
1331
+ // Example: Add custom folders and patterns
875
1332
  "code-style/module-index-exports": ["error", {
876
1333
  extraModuleFolders: ["features", "modules", "lib"],
877
1334
  extraLazyLoadFolders: ["pages"],
@@ -885,185 +1342,342 @@ export { Input } from "./Input";
885
1342
 
886
1343
  ### `jsx-children-on-new-line`
887
1344
 
888
- When a JSX element has multiple children, each child should be on its own line with proper indentation.
1345
+ **What it does:** When a JSX element has multiple children, ensures each child is on its own line with proper indentation.
1346
+
1347
+ **Why use it:** Multiple children on one line are hard to scan. Individual lines make the component structure clear.
889
1348
 
890
1349
  ```javascript
891
- // Good
1350
+ // Good — each child on its own line
892
1351
  <Container>
893
1352
  <Header />
894
1353
  <Content />
895
1354
  <Footer />
896
1355
  </Container>
897
1356
 
898
- // Bad
899
- <Container><Header /><Content />
900
- <Footer /></Container>
1357
+ <Form>
1358
+ <Input name="email" />
1359
+ <Input name="password" />
1360
+ <Button type="submit">Login</Button>
1361
+ </Form>
1362
+
1363
+ // ✅ Good — single child can stay inline
1364
+ <Button><Icon /></Button>
1365
+
1366
+ // ❌ Bad — multiple children crammed together
1367
+ <Container><Header /><Content /><Footer /></Container>
1368
+
1369
+ // ❌ Bad — inconsistent formatting
1370
+ <Form><Input name="email" />
1371
+ <Input name="password" />
1372
+ <Button>Login</Button></Form>
901
1373
  ```
902
1374
 
903
1375
  ---
904
1376
 
905
1377
  ### `jsx-closing-bracket-spacing`
906
1378
 
907
- No space before > or /> in JSX tags. The closing bracket should be directly after the last attribute or tag name.
1379
+ **What it does:** Removes any space before `>` or `/>` in JSX tags.
1380
+
1381
+ **Why use it:** Standard JSX convention. Spaces before closing brackets look inconsistent and can be confusing.
908
1382
 
909
1383
  ```javascript
910
- // Good
1384
+ // Good — no space before closing
911
1385
  <Button />
912
- <Button className="primary">
1386
+ <Input type="text" />
1387
+ <div className="container">
1388
+ <Modal isOpen={true}>
913
1389
 
914
- // Bad
1390
+ // Bad — space before />
915
1391
  <Button / >
916
- <Button className="primary" >
1392
+ <Input type="text" / >
1393
+
1394
+ // ❌ Bad — space before >
1395
+ <div className="container" >
1396
+ <Modal isOpen={true} >
917
1397
  ```
918
1398
 
919
1399
  ---
920
1400
 
921
1401
  ### `jsx-element-child-new-line`
922
1402
 
923
- JSX element children (nested JSX elements) must be on their own line, not on the same line as the opening tag.
1403
+ **What it does:** When a JSX element contains another JSX element as a child, the child must be on its own line.
1404
+
1405
+ **Why use it:** Nested elements on the same line hide the component structure. New lines make nesting visible.
924
1406
 
925
1407
  ```javascript
926
- // Good
1408
+ // Good — nested element on new line
927
1409
  <Button>
928
- <Icon />
1410
+ <Icon name="check" />
929
1411
  </Button>
930
1412
 
931
- // Bad
932
- <Button><Icon /></Button>
1413
+ <Card>
1414
+ <CardHeader>
1415
+ <Title>Hello</Title>
1416
+ </CardHeader>
1417
+ </Card>
1418
+
1419
+ // ✅ Good — text children can stay inline
1420
+ <Button>Click me</Button>
1421
+ <Title>{title}</Title>
1422
+
1423
+ // ❌ Bad — nested element inline
1424
+ <Button><Icon name="check" /></Button>
1425
+
1426
+ // ❌ Bad — complex nesting all inline
1427
+ <Card><CardHeader><Title>Hello</Title></CardHeader></Card>
933
1428
  ```
934
1429
 
935
1430
  ---
936
1431
 
937
1432
  ### `jsx-logical-expression-simplify`
938
1433
 
939
- Simplify JSX logical expressions by removing unnecessary parentheses around conditions and JSX elements.
1434
+ **What it does:** Removes unnecessary parentheses around conditions and JSX elements in logical expressions.
940
1435
 
941
- ```javascript
942
- // Good
943
- {condition && <Component />}
944
- {isVisible && <Modal />}
1436
+ **Why use it:** Extra parentheses add visual noise. Simple conditions and elements don't need wrapping.
945
1437
 
946
- // Bad
947
- {(condition) && (<Component />)}
948
- {(isVisible) && (<Modal />)}
1438
+ ```javascript
1439
+ // Good — clean logical expressions
1440
+ {isLoading && <Spinner />}
1441
+ {error && <ErrorMessage>{error}</ErrorMessage>}
1442
+ {items.length > 0 && <List items={items} />}
1443
+ {user.isAdmin && <AdminPanel />}
1444
+
1445
+ // ❌ Bad — unnecessary parentheses around condition
1446
+ {(isLoading) && <Spinner />}
1447
+ {(error) && <ErrorMessage />}
1448
+
1449
+ // ❌ Bad — unnecessary parentheses around JSX
1450
+ {isLoading && (<Spinner />)}
1451
+ {error && (<ErrorMessage />)}
1452
+
1453
+ // ❌ Bad — both
1454
+ {(isLoading) && (<Spinner />)}
949
1455
  ```
950
1456
 
951
1457
  ---
952
1458
 
953
1459
  ### `jsx-parentheses-position`
954
1460
 
955
- JSX return parentheses should be on the same line as the arrow or return keyword, not on a new line.
1461
+ **What it does:** Ensures the opening parenthesis `(` for multiline JSX is on the same line as `return` or `=>`, not on a new line.
1462
+
1463
+ **Why use it:** Parenthesis on new line wastes vertical space and looks disconnected from the statement it belongs to.
956
1464
 
957
1465
  ```javascript
958
- // Good
959
- const Component = () => (
960
- <div>content</div>
961
- );
962
- return (
963
- <div>content</div>
1466
+ // Good — parenthesis on same line as =>
1467
+ const Card = () => (
1468
+ <div className="card">
1469
+ <h1>Title</h1>
1470
+ </div>
964
1471
  );
965
1472
 
966
- // Bad
967
- const Component = () =>
968
- (
969
- <div>content</div>
1473
+ // ✅ Good — parenthesis on same line as return
1474
+ function Card() {
1475
+ return (
1476
+ <div className="card">
1477
+ <h1>Title</h1>
1478
+ </div>
970
1479
  );
971
- return
1480
+ }
1481
+
1482
+ // ❌ Bad — parenthesis on new line after =>
1483
+ const Card = () =>
972
1484
  (
973
- <div>content</div>
1485
+ <div className="card">
1486
+ <h1>Title</h1>
1487
+ </div>
974
1488
  );
1489
+
1490
+ // ❌ Bad — parenthesis on new line after return
1491
+ function Card() {
1492
+ return
1493
+ (
1494
+ <div className="card">
1495
+ <h1>Title</h1>
1496
+ </div>
1497
+ );
1498
+ }
975
1499
  ```
976
1500
 
977
1501
  ---
978
1502
 
979
1503
  ### `jsx-prop-naming-convention`
980
1504
 
981
- Enforce camelCase naming for JSX props. Allows PascalCase for component reference props, and kebab-case for data-* and aria-*.
1505
+ **What it does:** Enforces camelCase naming for JSX props, with exceptions for:
1506
+ - `data-*` attributes (kebab-case allowed)
1507
+ - `aria-*` attributes (kebab-case allowed)
1508
+ - Props that reference components (PascalCase allowed)
1509
+
1510
+ **Why use it:** Consistent prop naming follows React conventions and makes code predictable.
982
1511
 
983
1512
  ```javascript
984
- // Good
985
- <Button onClick={handler} />
986
- <Input data-testid="input" />
1513
+ // Good — camelCase props
1514
+ <Button onClick={handleClick} isDisabled={false} />
1515
+ <Input onChange={handleChange} autoFocus />
1516
+ <Modal onClose={close} isVisible={true} />
1517
+
1518
+ // ✅ Good — data-* and aria-* use kebab-case
1519
+ <Button data-testid="submit-btn" aria-label="Submit" />
1520
+ <Input data-cy="email-input" aria-describedby="help" />
1521
+
1522
+ // ✅ Good — component reference props use PascalCase
987
1523
  <Modal ContentComponent={Panel} />
1524
+ <Route Component={HomePage} />
1525
+
1526
+ // ❌ Bad — snake_case props
1527
+ <Button on_click={handler} is_disabled={false} />
1528
+ <Input on_change={handler} auto_focus />
988
1529
 
989
- // Bad
990
- <Button on_click={handler} />
991
- <Input test_id="input" />
1530
+ // Bad — kebab-case for regular props
1531
+ <Button is-disabled={false} />
992
1532
  ```
993
1533
 
994
1534
  ---
995
1535
 
996
1536
  ### `jsx-simple-element-one-line`
997
1537
 
998
- Simple JSX elements with only a single text or expression child should be collapsed onto a single line.
1538
+ **What it does:** Collapses simple JSX elements (single text or expression child) onto one line.
1539
+
1540
+ **Why use it:** Simple elements don't need multi-line formatting. Single line is more compact and scannable.
999
1541
 
1000
1542
  ```javascript
1001
- // Good
1002
- <Button>{buttonLinkText}</Button>
1003
- <Title>Hello</Title>
1543
+ // Good — simple elements on one line
1544
+ <Button>{buttonText}</Button>
1545
+ <Title>Welcome</Title>
1546
+ <span>{count}</span>
1547
+ <Label>{user.name}</Label>
1004
1548
 
1005
- // Bad
1549
+ // ✅ Good — complex children stay multiline
1006
1550
  <Button>
1007
- {buttonLinkText}
1551
+ <Icon />
1552
+ {buttonText}
1553
+ </Button>
1554
+
1555
+ // ❌ Bad — unnecessary multiline for simple content
1556
+ <Button>
1557
+ {buttonText}
1008
1558
  </Button>
1559
+
1560
+ <Title>
1561
+ Welcome
1562
+ </Title>
1563
+
1564
+ <span>
1565
+ {count}
1566
+ </span>
1009
1567
  ```
1010
1568
 
1011
1569
  ---
1012
1570
 
1013
1571
  ### `jsx-string-value-trim`
1014
1572
 
1015
- JSX string attribute values should not have leading or trailing whitespace inside the quotes.
1573
+ **What it does:** Removes leading and trailing whitespace inside JSX string attribute values.
1574
+
1575
+ **Why use it:** Whitespace in class names and other string values is usually unintentional and can cause bugs (e.g., CSS class not matching).
1016
1576
 
1017
1577
  ```javascript
1018
- // Good
1019
- className="button"
1020
- title="Hello World"
1578
+ // Good — no extra whitespace
1579
+ <Button className="primary" />
1580
+ <Input placeholder="Enter email" />
1581
+ <a href="/home">Home</a>
1582
+
1583
+ // ❌ Bad — leading whitespace
1584
+ <Button className=" primary" />
1585
+ <Input placeholder=" Enter email" />
1586
+
1587
+ // ❌ Bad — trailing whitespace
1588
+ <Button className="primary " />
1589
+ <a href="/home ">Home</a>
1021
1590
 
1022
- // Bad
1023
- className=" button "
1024
- title=" Hello World "
1591
+ // Bad — both
1592
+ <Button className=" primary " />
1025
1593
  ```
1026
1594
 
1027
1595
  ---
1028
1596
 
1029
1597
  ### `jsx-ternary-format`
1030
1598
 
1031
- Format ternary expressions in JSX with proper structure. Simple branches stay on one line, complex branches get parentheses with proper indentation.
1599
+ **What it does:** Formats ternary expressions in JSX consistently:
1600
+ - Simple branches stay on one line
1601
+ - Complex/multiline branches get parentheses with proper indentation
1602
+
1603
+ **Why use it:** Consistent ternary formatting makes conditional rendering predictable and readable.
1032
1604
 
1033
1605
  ```javascript
1034
- // Good
1035
- {condition ? <Simple /> : <Other />}
1036
- {condition ? <Simple /> : (
1037
- <Complex>
1038
- <Child />
1039
- </Complex>
1606
+ // Good — simple ternary on one line
1607
+ {isLoading ? <Spinner /> : <Content />}
1608
+ {error ? <Error /> : <Success />}
1609
+
1610
+ // ✅ Good — complex branches get parentheses
1611
+ {isLoading ? (
1612
+ <Spinner size="large" />
1613
+ ) : (
1614
+ <Content>
1615
+ <Header />
1616
+ <Body />
1617
+ </Content>
1618
+ )}
1619
+
1620
+ // ✅ Good — one simple, one complex
1621
+ {isLoading ? <Spinner /> : (
1622
+ <Content>
1623
+ <Header />
1624
+ <Body />
1625
+ </Content>
1040
1626
  )}
1041
1627
 
1042
- // Bad
1043
- {condition
1044
- ? <Simple />
1045
- : <Other />}
1628
+ // Bad — awkward line breaks
1629
+ {isLoading
1630
+ ? <Spinner />
1631
+ : <Content />}
1632
+
1633
+ // ❌ Bad — missing parentheses for complex branch
1634
+ {isLoading ? <Spinner /> : <Content>
1635
+ <Header />
1636
+ <Body />
1637
+ </Content>}
1046
1638
  ```
1047
1639
 
1048
1640
  ---
1049
1641
 
1050
1642
  ### `no-empty-lines-in-jsx`
1051
1643
 
1052
- JSX elements should not contain empty lines between children or after opening/before closing tags.
1644
+ **What it does:** Removes empty lines inside JSX elements — between children and after opening/before closing tags.
1645
+
1646
+ **Why use it:** Empty lines inside JSX create visual gaps that break the component's visual structure.
1053
1647
 
1054
1648
  ```javascript
1055
- // Good
1649
+ // Good — no empty lines inside
1056
1650
  <div>
1057
- <span>text</span>
1058
- <span>more</span>
1651
+ <Header />
1652
+ <Content />
1653
+ <Footer />
1059
1654
  </div>
1060
1655
 
1061
- // Bad
1656
+ <Form>
1657
+ <Input name="email" />
1658
+ <Input name="password" />
1659
+ <Button>Submit</Button>
1660
+ </Form>
1661
+
1662
+ // ❌ Bad — empty line after opening tag
1062
1663
  <div>
1063
1664
 
1064
- <span>text</span>
1665
+ <Header />
1666
+ <Content />
1667
+ </div>
1668
+
1669
+ // ❌ Bad — empty lines between children
1670
+ <Form>
1671
+ <Input name="email" />
1672
+
1673
+ <Input name="password" />
1065
1674
 
1066
- <span>more</span>
1675
+ <Button>Submit</Button>
1676
+ </Form>
1677
+
1678
+ // ❌ Bad — empty line before closing tag
1679
+ <div>
1680
+ <Content />
1067
1681
 
1068
1682
  </div>
1069
1683
  ```
@@ -1072,133 +1686,270 @@ JSX elements should not contain empty lines between children or after opening/be
1072
1686
 
1073
1687
  ## 📞 Call Expression Rules
1074
1688
 
1075
- ### `multiline-argument-newline`
1689
+ ### `function-arguments-format`
1076
1690
 
1077
- When function arguments span multiple lines, each argument should start on its own line with consistent indentation.
1691
+ **What it does:** Enforces consistent formatting for function call arguments:
1692
+ - Single simple argument stays on one line
1693
+ - 2+ arguments get one per line
1694
+ - Multiline arguments trigger full expansion
1695
+ - React hooks are skipped by default (they have their own rule)
1696
+
1697
+ **Why use it:** Consistent argument formatting makes function calls scannable and diffs clean when adding/removing arguments.
1078
1698
 
1079
1699
  ```javascript
1080
- // Good
1081
- fn(
1082
- arg1,
1083
- arg2,
1084
- )
1700
+ // Good — single argument stays compact
1701
+ fetchUser(userId);
1702
+ console.log(message);
1703
+ dispatch(action);
1704
+
1705
+ // ✅ Good — 2+ arguments get one per line
1706
+ setValue(
1707
+ "email",
1708
+ "user@example.com",
1709
+ );
1710
+
1711
+ createUser(
1712
+ name,
1713
+ email,
1714
+ password,
1715
+ );
1716
+
1717
+ // ✅ Good — multiline argument triggers expansion
1718
+ processData(
1719
+ {
1720
+ id: 1,
1721
+ name: "test",
1722
+ },
1723
+ );
1724
+
1725
+ // ✅ Good — callback with body triggers expansion
1726
+ items.forEach(
1727
+ (item) => {
1728
+ process(item);
1729
+ save(item);
1730
+ },
1731
+ );
1085
1732
 
1086
- // Bad
1733
+ // Bad — multiple arguments on same line
1734
+ setValue("email", "user@example.com");
1735
+ createUser(name, email, password);
1736
+
1737
+ // ❌ Bad — inconsistent formatting
1087
1738
  fn(arg1,
1088
- arg2)
1739
+ arg2, arg3);
1089
1740
  ```
1090
1741
 
1091
- ---
1092
-
1093
- ### `multiple-arguments-per-line`
1742
+ **Options:**
1094
1743
 
1095
- When a function call has 2+ arguments, each argument should be on its own line with proper indentation.
1744
+ | Option | Type | Default | Description |
1745
+ |--------|------|---------|-------------|
1746
+ | `minArgs` | `integer` | `2` | Minimum arguments to enforce multiline |
1747
+ | `skipHooks` | `boolean` | `true` | Skip React hooks (useEffect, etc.) |
1748
+ | `skipSingleArg` | `boolean` | `true` | Skip calls with single complex argument |
1096
1749
 
1097
1750
  ```javascript
1098
- // Good
1099
- setValue(
1100
- "numberOfCopies",
1101
- null,
1102
- )
1751
+ // Example: Require multiline for 3+ arguments
1752
+ "code-style/function-arguments-format": ["error", { minArgs: 3 }]
1103
1753
 
1104
- // Bad
1105
- setValue("numberOfCopies", null)
1754
+ // Example: Don't skip React hooks
1755
+ "code-style/function-arguments-format": ["error", { skipHooks: false }]
1106
1756
  ```
1107
1757
 
1108
1758
  ---
1109
1759
 
1110
1760
  ### `nested-call-closing-brackets`
1111
1761
 
1112
- Nested function calls (like styled-components) should have closing brackets on the same line: }));
1762
+ **What it does:** Ensures nested function calls (common in styled-components, HOCs) have closing brackets on the same line: `}));`
1763
+
1764
+ **Why use it:** Scattered closing brackets (`}\n);\n` ) waste vertical space and make it harder to see where expressions end.
1113
1765
 
1114
1766
  ```javascript
1115
- // Good
1116
- styled(Card)(({ theme }) => ({
1117
- color: theme.color,
1767
+ // Good — closing brackets together
1768
+ const StyledCard = styled(Card)(({ theme }) => ({
1769
+ color: theme.palette.text.primary,
1770
+ padding: theme.spacing(2),
1771
+ }));
1772
+
1773
+ const StyledButton = styled("button")(({ theme }) => ({
1774
+ backgroundColor: theme.colors.primary,
1118
1775
  }));
1119
1776
 
1120
- // Bad
1121
- styled(Card)(({ theme }) => ({
1122
- color: theme.color,
1777
+ // ✅ Good — multiple levels
1778
+ const Component = connect(
1779
+ mapStateToProps,
1780
+ mapDispatchToProps,
1781
+ )(withRouter(MyComponent));
1782
+
1783
+ // ❌ Bad — closing brackets scattered
1784
+ const StyledCard = styled(Card)(({ theme }) => ({
1785
+ color: theme.palette.text.primary,
1123
1786
  })
1124
1787
  );
1788
+
1789
+ // ❌ Bad — each bracket on its own line
1790
+ const StyledCard = styled(Card)(({ theme }) => ({
1791
+ color: theme.colors.primary,
1792
+ })
1793
+ )
1794
+ ;
1125
1795
  ```
1126
1796
 
1127
1797
  ---
1128
1798
 
1129
1799
  ### `no-empty-lines-in-function-calls`
1130
1800
 
1131
- Function call arguments should not have empty lines between them or after opening/before closing parentheses.
1801
+ **What it does:** Removes empty lines within function call argument lists — between arguments and after opening/before closing parentheses.
1802
+
1803
+ **Why use it:** Empty lines between arguments break visual grouping. Arguments should flow as a cohesive list.
1132
1804
 
1133
1805
  ```javascript
1134
- // Good
1135
- fn(
1136
- arg1,
1137
- arg2,
1138
- )
1806
+ // Good — no empty lines
1807
+ createUser(
1808
+ name,
1809
+ email,
1810
+ password,
1811
+ role,
1812
+ );
1139
1813
 
1140
- // Bad
1141
- fn(
1142
- arg1,
1814
+ fetchData(
1815
+ url,
1816
+ {
1817
+ method: "POST",
1818
+ body: data,
1819
+ },
1820
+ );
1143
1821
 
1144
- arg2,
1145
- )
1822
+ // ❌ Bad — empty line between arguments
1823
+ createUser(
1824
+ name,
1825
+
1826
+ email,
1827
+
1828
+ password,
1829
+ );
1830
+
1831
+ // ❌ Bad — empty line after opening paren
1832
+ fetchData(
1833
+
1834
+ url,
1835
+ options,
1836
+ );
1837
+
1838
+ // ❌ Bad — empty line before closing paren
1839
+ fetchData(
1840
+ url,
1841
+ options,
1842
+
1843
+ );
1146
1844
  ```
1147
1845
 
1148
1846
  ---
1149
1847
 
1150
1848
  ### `opening-brackets-same-line`
1151
1849
 
1152
- Opening brackets should be on the same line as function/method calls. This applies to objects, arrays, and arrow function parameters.
1850
+ **What it does:** Ensures opening brackets (`{`, `[`, `(`) in function arguments stay on the same line as the function call.
1153
1851
 
1154
- ```javascript
1155
- // Good
1156
- fn({ prop: value })
1157
- .map(({ x }) => x)
1158
- fn([1, 2, 3])
1852
+ **Why use it:** Opening brackets on new lines create unnecessary indentation and vertical space.
1159
1853
 
1160
- // Bad
1854
+ ```javascript
1855
+ // ✅ Good — brackets on same line as call
1856
+ fn({ key: value });
1857
+ process([1, 2, 3]);
1858
+ items.map(({ id }) => id);
1859
+ configure({ debug: true });
1860
+
1861
+ // ✅ Good — multiline content is fine
1862
+ fn({
1863
+ key: value,
1864
+ other: data,
1865
+ });
1866
+
1867
+ items.map(({ id, name }) => (
1868
+ <Item key={id} name={name} />
1869
+ ));
1870
+
1871
+ // ❌ Bad — opening bracket on new line
1161
1872
  fn(
1162
- { prop: value }
1163
- )
1164
- .map(
1165
- ({ x }) => x
1166
- )
1873
+ { key: value }
1874
+ );
1875
+
1876
+ process(
1877
+ [1, 2, 3]
1878
+ );
1879
+
1880
+ items.map(
1881
+ ({ id }) => id
1882
+ );
1167
1883
  ```
1168
1884
 
1169
1885
  ---
1170
1886
 
1171
1887
  ### `simple-call-single-line`
1172
1888
 
1173
- Simple function calls with an arrow function containing a simple call expression should be on a single line.
1889
+ **What it does:** Collapses simple function calls with an arrow function containing a single call expression onto one line.
1890
+
1891
+ **Why use it:** Common patterns like `lazy(() => import(...))` don't need multiline formatting. Single line is cleaner.
1174
1892
 
1175
1893
  ```javascript
1176
- // Good
1177
- fn(() => call(arg))
1178
- lazy(() => import("./module"))
1894
+ // Good — simple patterns on one line
1895
+ const Page = lazy(() => import("./Page"));
1896
+ const Modal = lazy(() => import("./Modal"));
1897
+ setTimeout(() => callback(), 100);
1898
+ requestAnimationFrame(() => render());
1899
+ items.filter(() => isValid(item));
1900
+
1901
+ // ✅ Good — complex callbacks stay multiline
1902
+ const Page = lazy(() => {
1903
+ console.log("Loading page");
1904
+ return import("./Page");
1905
+ });
1906
+
1907
+ // ❌ Bad — unnecessary multiline for simple pattern
1908
+ const Page = lazy(
1909
+ () => import("./Page"),
1910
+ );
1179
1911
 
1180
- // Bad
1181
- fn(
1182
- () => call(arg),
1183
- )
1912
+ setTimeout(
1913
+ () => callback(),
1914
+ 100,
1915
+ );
1184
1916
  ```
1185
1917
 
1186
1918
  ---
1187
1919
 
1188
1920
  ### `single-argument-on-one-line`
1189
1921
 
1190
- Function calls with a single simple argument (literal, identifier, member expression) should be on one line.
1922
+ **What it does:** Ensures function calls with a single simple argument (literal, identifier, member expression) stay on one line.
1923
+
1924
+ **Why use it:** Single-argument calls don't need multiline formatting. Expanding them wastes vertical space.
1191
1925
 
1192
1926
  ```javascript
1193
- // Good
1194
- fn(arg)
1195
- getValue("key")
1196
- obj.method(value)
1927
+ // Good — single argument on one line
1928
+ fetchUser(userId);
1929
+ console.log(message);
1930
+ process(data.items);
1931
+ dispatch(action);
1932
+ setValue("key");
1933
+ getElement(document.body);
1934
+
1935
+ // ✅ Good — complex single argument can be multiline
1936
+ processConfig({
1937
+ key: value,
1938
+ other: data,
1939
+ });
1940
+
1941
+ // ❌ Bad — simple argument expanded unnecessarily
1942
+ fetchUser(
1943
+ userId,
1944
+ );
1197
1945
 
1198
- // Bad
1199
- fn(
1200
- arg,
1201
- )
1946
+ console.log(
1947
+ message,
1948
+ );
1949
+
1950
+ dispatch(
1951
+ action,
1952
+ );
1202
1953
  ```
1203
1954
 
1204
1955
  <br />
@@ -1207,92 +1958,219 @@ fn(
1207
1958
 
1208
1959
  ### `no-empty-lines-in-objects`
1209
1960
 
1210
- Object literals should not contain empty lines between properties or after opening/before closing braces.
1961
+ **What it does:** Removes empty lines within object literals — between properties and after opening/before closing braces.
1962
+
1963
+ **Why use it:** Empty lines inside objects break the visual grouping of properties. Properties should flow as a cohesive unit.
1211
1964
 
1212
1965
  ```javascript
1213
- // Good
1214
- {
1215
- a: 1,
1216
- b: 2,
1217
- }
1966
+ // Good — no empty lines
1967
+ const user = {
1968
+ name: "John",
1969
+ email: "john@example.com",
1970
+ role: "admin",
1971
+ };
1218
1972
 
1219
- // Bad
1220
- {
1221
- a: 1,
1973
+ const config = {
1974
+ host: "localhost",
1975
+ port: 3000,
1976
+ debug: true,
1977
+ };
1222
1978
 
1223
- b: 2,
1224
- }
1979
+ // ❌ Bad — empty line between properties
1980
+ const user = {
1981
+ name: "John",
1982
+
1983
+ email: "john@example.com",
1984
+
1985
+ role: "admin",
1986
+ };
1987
+
1988
+ // ❌ Bad — empty line after opening brace
1989
+ const config = {
1990
+
1991
+ host: "localhost",
1992
+ port: 3000,
1993
+ };
1994
+
1995
+ // ❌ Bad — empty line before closing brace
1996
+ const config = {
1997
+ host: "localhost",
1998
+ port: 3000,
1999
+
2000
+ };
1225
2001
  ```
1226
2002
 
1227
2003
  ---
1228
2004
 
1229
2005
  ### `object-property-per-line`
1230
2006
 
1231
- When an object has 2 or more properties and spans multiple lines, each property should be on its own line.
2007
+ **What it does:** Controls object formatting based on property count:
2008
+ - 1 property: stays on single line `{ name: "John" }`
2009
+ - 2+ properties: expands with `{` and `}` on own lines, each property on its own line
2010
+
2011
+ **Why use it:** Single-property objects are clear on one line. Multiple properties need expansion for readability and clean diffs.
1232
2012
 
1233
2013
  ```javascript
1234
- // Good
1235
- {
2014
+ // Good — single property stays compact
2015
+ const point = { x: 10 };
2016
+ const config = { debug: true };
2017
+ fn({ callback: handleClick });
2018
+
2019
+ // ✅ Good — 2+ properties get full expansion
2020
+ const point = {
2021
+ x: 10,
2022
+ y: 20,
2023
+ };
2024
+
2025
+ const user = {
1236
2026
  name: "John",
1237
- age: 30,
1238
- }
2027
+ email: "john@example.com",
2028
+ role: "admin",
2029
+ };
2030
+
2031
+ // ✅ Good — nested objects follow same rules
2032
+ const config = {
2033
+ server: { port: 3000 },
2034
+ database: {
2035
+ host: "localhost",
2036
+ name: "mydb",
2037
+ },
2038
+ };
2039
+
2040
+ // ❌ Bad — multiple properties on one line
2041
+ const point = { x: 10, y: 20 };
2042
+ const user = { name: "John", email: "john@example.com" };
2043
+
2044
+ // ❌ Bad — inconsistent formatting
2045
+ const point = { x: 10,
2046
+ y: 20 };
2047
+ ```
2048
+
2049
+ **Options:**
2050
+
2051
+ | Option | Type | Default | Description |
2052
+ |--------|------|---------|-------------|
2053
+ | `minProperties` | `integer` | `2` | Minimum properties to trigger expansion |
1239
2054
 
1240
- // Bad
1241
- { name: "John",
1242
- age: 30 }
2055
+ ```javascript
2056
+ // Example: Require 3+ properties for expansion
2057
+ "code-style/object-property-per-line": ["error", { minProperties: 3 }]
1243
2058
  ```
1244
2059
 
1245
2060
  ---
1246
2061
 
1247
2062
  ### `object-property-value-brace`
1248
2063
 
1249
- Opening brace of an object value should be on the same line as the colon, not on a new line.
2064
+ **What it does:** Ensures opening braces of object values start on the same line as the colon, not on a new line.
2065
+
2066
+ **Why use it:** Braces on new lines waste vertical space and disconnect the property key from its value.
1250
2067
 
1251
2068
  ```javascript
1252
- // Good
1253
- "& a": { color: "red" }
2069
+ // Good — brace on same line as colon
2070
+ const styles = {
2071
+ "& a": { color: "red" },
2072
+ "& button": { padding: "10px" },
2073
+ };
2074
+
2075
+ const config = {
2076
+ server: {
2077
+ host: "localhost",
2078
+ port: 3000,
2079
+ },
2080
+ };
1254
2081
 
1255
- // Bad
1256
- "& a":
1257
- { color: "red" }
2082
+ // Bad — brace on new line
2083
+ const styles = {
2084
+ "& a":
2085
+ { color: "red" },
2086
+ "& button":
2087
+ { padding: "10px" },
2088
+ };
2089
+
2090
+ // ❌ Bad — inconsistent
2091
+ const config = {
2092
+ server:
2093
+ {
2094
+ host: "localhost",
2095
+ },
2096
+ };
1258
2097
  ```
1259
2098
 
1260
2099
  ---
1261
2100
 
1262
2101
  ### `object-property-value-format`
1263
2102
 
1264
- Object property values should be on the same line as the colon with proper spacing for simple values.
2103
+ **What it does:** Ensures property values start on the same line as the colon for simple values (strings, numbers, identifiers).
2104
+
2105
+ **Why use it:** Values on new lines after the colon waste space and look disconnected from their keys.
1265
2106
 
1266
2107
  ```javascript
1267
- // Good
1268
- {
2108
+ // Good — values on same line as colon
2109
+ const user = {
1269
2110
  name: "John",
1270
2111
  age: 30,
1271
- }
2112
+ isActive: true,
2113
+ role: userRole,
2114
+ };
1272
2115
 
1273
- // Bad
1274
- {
2116
+ // ✅ Good — complex values can span lines
2117
+ const config = {
2118
+ handler: (event) => {
2119
+ process(event);
2120
+ },
2121
+ items: [
2122
+ "first",
2123
+ "second",
2124
+ ],
2125
+ };
2126
+
2127
+ // ❌ Bad — simple values on new line
2128
+ const user = {
1275
2129
  name:
1276
2130
  "John",
1277
2131
  age:
1278
2132
  30,
1279
- }
2133
+ isActive:
2134
+ true,
2135
+ };
1280
2136
  ```
1281
2137
 
1282
2138
  ---
1283
2139
 
1284
2140
  ### `string-property-spacing`
1285
2141
 
1286
- String property keys should not have extra leading or trailing spaces inside the quotes.
2142
+ **What it does:** Removes leading and trailing whitespace inside string property keys.
2143
+
2144
+ **Why use it:** Whitespace in property keys is usually unintentional and can cause bugs when accessing properties.
1287
2145
 
1288
2146
  ```javascript
1289
- // Good
1290
- { "& a": value }
1291
- { "selector": value }
2147
+ // Good — no extra whitespace
2148
+ const styles = {
2149
+ "& a": { color: "red" },
2150
+ "& .button": { padding: "10px" },
2151
+ "data-testid": "myElement",
2152
+ };
2153
+
2154
+ const obj = {
2155
+ "Content-Type": "application/json",
2156
+ "X-Custom-Header": "value",
2157
+ };
1292
2158
 
1293
- // Bad
1294
- { " & a ": value }
1295
- { " selector ": value }
2159
+ // Bad — leading whitespace
2160
+ const styles = {
2161
+ " & a": { color: "red" },
2162
+ " & .button": { padding: "10px" },
2163
+ };
2164
+
2165
+ // ❌ Bad — trailing whitespace
2166
+ const obj = {
2167
+ "Content-Type ": "application/json",
2168
+ };
2169
+
2170
+ // ❌ Bad — both
2171
+ const styles = {
2172
+ " & a ": { color: "red" },
2173
+ };
1296
2174
  ```
1297
2175
 
1298
2176
  <br />