eslint-plugin-code-style 1.0.17 → 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.
- package/README.md +1339 -472
- package/index.js +617 -407
- 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
|
-
*
|
|
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 **
|
|
28
|
+
This plugin provides **48 custom auto-fixable rules** for code formatting. Built for **ESLint v9 flat configs**.
|
|
29
29
|
|
|
30
|
-
**
|
|
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
|
-
|
|
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
|
|
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 **
|
|
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/
|
|
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 **
|
|
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` |
|
|
242
|
-
| `array-objects-on-new-lines` |
|
|
243
|
-
| `arrow-function-block-body` |
|
|
244
|
-
| `arrow-function-simple-jsx` |
|
|
245
|
-
| `arrow-function-simplify` |
|
|
246
|
-
| `curried-arrow-same-line` |
|
|
247
|
-
| `assignment-value-same-line` |
|
|
248
|
-
| `block-statement-newlines` |
|
|
249
|
-
| `comment-spacing` |
|
|
250
|
-
| `function-call-spacing` |
|
|
251
|
-
| `function-naming-convention` |
|
|
252
|
-
| `function-params-per-line` |
|
|
253
|
-
| `hook-callback-format` |
|
|
254
|
-
| `hook-deps-per-line` |
|
|
255
|
-
| `if-statement-format` |
|
|
256
|
-
| `multiline-if-conditions` |
|
|
257
|
-
| `absolute-imports-only` |
|
|
258
|
-
| `export-format` |
|
|
259
|
-
| `import-format` |
|
|
260
|
-
| `import-source-spacing` |
|
|
261
|
-
| `index-export-style` |
|
|
262
|
-
| `module-index-exports` |
|
|
263
|
-
| `jsx-children-on-new-line` |
|
|
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
|
|
266
|
-
| `jsx-logical-expression-simplify` |
|
|
267
|
-
| `jsx-parentheses-position` |
|
|
268
|
-
| `jsx-prop-naming-convention` |
|
|
269
|
-
| `jsx-simple-element-one-line` |
|
|
270
|
-
| `jsx-string-value-trim` |
|
|
271
|
-
| `jsx-ternary-format` |
|
|
272
|
-
| `member-expression-bracket-spacing` |
|
|
273
|
-
| `
|
|
274
|
-
| `
|
|
275
|
-
| `
|
|
276
|
-
| `no-empty-lines-in-function-
|
|
277
|
-
| `no-empty-lines-in-
|
|
278
|
-
| `no-empty-lines-in-
|
|
279
|
-
| `no-empty-lines-in-
|
|
280
|
-
| `
|
|
281
|
-
| `object-property-
|
|
282
|
-
| `object-property-value-
|
|
283
|
-
| `
|
|
284
|
-
| `
|
|
285
|
-
| `
|
|
286
|
-
| `
|
|
287
|
-
| `
|
|
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
|
-
|
|
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
|
|
309
|
-
const
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
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
|
|
318
|
-
|
|
319
|
-
|
|
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
|
|
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
|
|
331
|
-
{ id: 1, name: "
|
|
332
|
-
{ id: 2, name: "
|
|
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" },
|
|
333
354
|
];
|
|
334
355
|
|
|
335
|
-
//
|
|
336
|
-
const
|
|
337
|
-
{
|
|
356
|
+
// ✅ Good — even short objects get their own line
|
|
357
|
+
const points = [
|
|
358
|
+
{ x: 0, y: 0 },
|
|
359
|
+
{ x: 10, y: 20 },
|
|
360
|
+
];
|
|
361
|
+
|
|
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
|
-
|
|
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
|
-
|
|
352
|
-
|
|
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
|
+
);
|
|
354
394
|
|
|
355
|
-
// Bad
|
|
356
|
-
() => (
|
|
395
|
+
// ❌ Bad — comma operator is confusing
|
|
396
|
+
const handleSubmit = () => (validateForm(), submitData(), result);
|
|
397
|
+
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
371
|
-
<
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
388
|
-
|
|
389
|
-
(x) =>
|
|
390
|
-
|
|
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
|
-
|
|
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
|
|
402
|
-
|
|
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
|
|
472
|
+
// ❌ Bad — chain broken across lines
|
|
473
|
+
const createAction = (type) =>
|
|
474
|
+
(payload) => ({ type, payload });
|
|
475
|
+
|
|
476
|
+
const mapDispatch = () =>
|
|
407
477
|
async (dispatch) => {
|
|
408
|
-
dispatch(
|
|
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
|
-
|
|
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
|
|
424
|
-
|
|
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
|
|
507
|
+
const config =
|
|
431
508
|
{
|
|
432
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
465
|
-
|
|
466
|
-
|
|
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
|
-
|
|
593
|
+
**What it does:** Removes spaces inside brackets in computed member expressions (array access, dynamic property access).
|
|
474
594
|
|
|
475
|
-
|
|
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
|
-
|
|
481
|
-
|
|
482
|
-
|
|
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
|
-
|
|
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
|
|
494
|
-
|
|
495
|
-
|
|
619
|
+
// ✅ Good — no empty lines
|
|
620
|
+
function createUser(
|
|
621
|
+
name,
|
|
622
|
+
email,
|
|
623
|
+
role,
|
|
496
624
|
) {}
|
|
497
625
|
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
626
|
+
const handler = (
|
|
627
|
+
event,
|
|
628
|
+
context,
|
|
629
|
+
) => {};
|
|
630
|
+
|
|
631
|
+
// ❌ Bad — empty line between params
|
|
632
|
+
function createUser(
|
|
633
|
+
name,
|
|
501
634
|
|
|
502
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
520
|
-
|
|
521
|
-
const
|
|
522
|
-
const
|
|
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
|
-
|
|
682
|
+
**What it does:** Removes any space between a function name and its opening parenthesis.
|
|
532
683
|
|
|
533
|
-
|
|
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
|
-
|
|
539
|
-
|
|
540
|
-
|
|
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
|
-
|
|
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
|
|
554
|
-
|
|
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
|
|
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
|
|
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
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
745
|
+
// ✅ Good — each param on own line
|
|
746
|
+
function createUser(
|
|
747
|
+
name,
|
|
748
|
+
email,
|
|
749
|
+
password,
|
|
750
|
+
role,
|
|
574
751
|
) {}
|
|
575
752
|
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
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
|
-
|
|
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
|
|
784
|
+
useEffect(
|
|
785
|
+
() => {
|
|
786
|
+
fetchData();
|
|
787
|
+
},
|
|
788
|
+
[userId],
|
|
789
|
+
);
|
|
790
|
+
|
|
791
|
+
useCallback(
|
|
792
|
+
() => {
|
|
793
|
+
handleSubmit(data);
|
|
794
|
+
},
|
|
795
|
+
[data, handleSubmit],
|
|
796
|
+
);
|
|
797
|
+
|
|
798
|
+
useMemo(
|
|
799
|
+
() => expensiveCalculation(items),
|
|
800
|
+
[items],
|
|
801
|
+
);
|
|
802
|
+
|
|
803
|
+
// ✅ Good — cleanup function visible
|
|
591
804
|
useEffect(
|
|
592
|
-
() => {
|
|
593
|
-
|
|
805
|
+
() => {
|
|
806
|
+
const subscription = subscribe();
|
|
807
|
+
|
|
808
|
+
return () => subscription.unsubscribe();
|
|
809
|
+
},
|
|
810
|
+
[subscribe],
|
|
594
811
|
);
|
|
595
812
|
|
|
596
|
-
// Bad
|
|
597
|
-
useEffect(() => {
|
|
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
|
-
|
|
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(() => {}, [
|
|
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
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
858
|
+
userId, token, refreshToken,
|
|
859
|
+
]);
|
|
860
|
+
```
|
|
861
|
+
|
|
862
|
+
**Options:**
|
|
863
|
+
|
|
864
|
+
| Option | Type | Default | Description |
|
|
865
|
+
|--------|------|---------|-------------|
|
|
866
|
+
| `maxDeps` | `integer` | `2` | Maximum dependencies to keep on single line |
|
|
614
867
|
|
|
615
|
-
|
|
616
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
946
|
+
isAuthenticated &&
|
|
947
|
+
hasPermission &&
|
|
948
|
+
!isExpired &&
|
|
949
|
+
isEnabled
|
|
950
|
+
) {
|
|
951
|
+
allowAccess();
|
|
952
|
+
}
|
|
659
953
|
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
954
|
+
if (
|
|
955
|
+
user.isAdmin ||
|
|
956
|
+
user.isModerator ||
|
|
957
|
+
user.hasSpecialAccess ||
|
|
958
|
+
isPublicResource
|
|
959
|
+
) {
|
|
960
|
+
showContent();
|
|
961
|
+
}
|
|
962
|
+
|
|
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
|
-
|
|
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 (
|
|
674
|
-
case
|
|
675
|
-
return "
|
|
676
|
-
case
|
|
677
|
-
return "
|
|
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";
|
|
678
1002
|
}
|
|
679
1003
|
|
|
680
|
-
//
|
|
681
|
-
switch (
|
|
682
|
-
case
|
|
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!";
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
// ❌ Bad — empty lines between cases
|
|
1023
|
+
switch (status) {
|
|
1024
|
+
case "pending":
|
|
1025
|
+
return "Waiting...";
|
|
683
1026
|
|
|
684
|
-
|
|
1027
|
+
case "success":
|
|
1028
|
+
return "Done!";
|
|
685
1029
|
|
|
686
|
-
|
|
687
|
-
return "
|
|
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
|
-
|
|
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
|
-
//
|
|
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,118 +1093,196 @@ import { useAuth } from "@/hooks/auth/useAuth";
|
|
|
733
1093
|
|
|
734
1094
|
### `export-format`
|
|
735
1095
|
|
|
736
|
-
|
|
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 {
|
|
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
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
1112
|
+
Button,
|
|
1113
|
+
Input,
|
|
1114
|
+
Select,
|
|
1115
|
+
Checkbox,
|
|
746
1116
|
};
|
|
747
1117
|
|
|
748
|
-
//
|
|
749
|
-
export {
|
|
750
|
-
export {
|
|
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
|
-
|
|
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 {
|
|
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
|
|
762
1167
|
import {
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
} from "
|
|
1168
|
+
useState,
|
|
1169
|
+
useEffect,
|
|
1170
|
+
useCallback,
|
|
1171
|
+
useMemo,
|
|
1172
|
+
} from "react";
|
|
1173
|
+
|
|
1174
|
+
import {
|
|
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";
|
|
1187
|
+
|
|
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 |
|
|
768
1201
|
|
|
769
|
-
|
|
770
|
-
import
|
|
771
|
-
import { a, b, c, d, e } from "module";
|
|
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
|
-
|
|
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";
|
|
1219
|
+
|
|
1220
|
+
// ❌ Bad — leading space
|
|
1221
|
+
import { Button } from " @mui/material";
|
|
1222
|
+
|
|
1223
|
+
// ❌ Bad — trailing space
|
|
1224
|
+
import React from "react ";
|
|
783
1225
|
|
|
784
|
-
// Bad
|
|
785
|
-
import
|
|
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
|
-
|
|
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
|
|
1257
|
+
// ✅ Good — shorthand re-exports, no blank lines
|
|
797
1258
|
export { Button } from "./button";
|
|
798
1259
|
export { Input, Select } from "./form";
|
|
799
|
-
export {
|
|
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
|
|
1266
|
+
// ✅ Good — imports grouped, single export at bottom
|
|
805
1267
|
import { Button } from "./button";
|
|
806
1268
|
import { Input, Select } from "./form";
|
|
807
|
-
import {
|
|
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
|
-
**
|
|
819
|
-
```javascript
|
|
820
|
-
// Bad - mixing styles
|
|
821
|
-
export { Button } from "./button";
|
|
822
|
-
import { Input } from "./input";
|
|
823
|
-
export { Input };
|
|
824
|
-
|
|
825
|
-
// Bad - empty lines between shorthand exports
|
|
826
|
-
export { Button } from "./button";
|
|
827
|
-
|
|
828
|
-
export { Input } from "./input";
|
|
829
|
-
|
|
830
|
-
// Bad - multiple standalone exports (should be one)
|
|
831
|
-
import { Button } from "./button";
|
|
832
|
-
import { Input } from "./input";
|
|
833
|
-
export { Button };
|
|
834
|
-
export { Input };
|
|
835
|
-
```
|
|
836
|
-
|
|
837
|
-
**Customization Options:**
|
|
1279
|
+
**Options:**
|
|
838
1280
|
|
|
839
1281
|
| Option | Type | Default | Description |
|
|
840
1282
|
|--------|------|---------|-------------|
|
|
841
|
-
| `style` | `"shorthand"` \| `"import-export"` | `"shorthand"` |
|
|
1283
|
+
| `style` | `"shorthand"` \| `"import-export"` | `"shorthand"` | Export style for index files |
|
|
842
1284
|
|
|
843
1285
|
```javascript
|
|
844
|
-
// Example: Use shorthand style (default)
|
|
845
|
-
"code-style/index-export-style": "error"
|
|
846
|
-
|
|
847
|
-
// Example: Use import-then-export style
|
|
848
1286
|
"code-style/index-export-style": ["error", { style: "import-export" }]
|
|
849
1287
|
```
|
|
850
1288
|
|
|
@@ -852,37 +1290,45 @@ export { Input };
|
|
|
852
1290
|
|
|
853
1291
|
### `module-index-exports`
|
|
854
1292
|
|
|
855
|
-
|
|
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.
|
|
856
1296
|
|
|
857
1297
|
```javascript
|
|
858
|
-
// Good
|
|
859
|
-
// index.js
|
|
1298
|
+
// ✅ Good — components/index.js exports everything
|
|
860
1299
|
export { Button } from "./Button";
|
|
861
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";
|
|
862
1306
|
|
|
863
|
-
// Bad
|
|
864
|
-
//
|
|
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!
|
|
865
1311
|
```
|
|
866
1312
|
|
|
867
1313
|
**Default Module Folders:**
|
|
868
1314
|
`apis`, `assets`, `atoms`, `components`, `constants`, `contexts`, `data`, `hooks`, `layouts`, `middlewares`, `providers`, `redux`, `requests`, `routes`, `schemas`, `services`, `styles`, `theme`, `utils`, `views`
|
|
869
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
|
+
|
|
870
1319
|
**Customization Options:**
|
|
871
1320
|
|
|
872
1321
|
| Option | Type | Description |
|
|
873
1322
|
|--------|------|-------------|
|
|
874
1323
|
| `extraModuleFolders` | `string[]` | Add extra module folders to the default list |
|
|
875
1324
|
| `extraLazyLoadFolders` | `string[]` | Add extra lazy load folders (default: `views`) |
|
|
876
|
-
| `extraIgnorePatterns` | `string[]` | Add extra ignore patterns (supports wildcards
|
|
1325
|
+
| `extraIgnorePatterns` | `string[]` | Add extra ignore patterns (supports wildcards) |
|
|
877
1326
|
| `moduleFolders` | `string[]` | Replace default module folders entirely |
|
|
878
1327
|
| `lazyLoadFolders` | `string[]` | Replace default lazy load folders entirely |
|
|
879
1328
|
| `ignorePatterns` | `string[]` | Replace default ignore patterns entirely |
|
|
880
1329
|
|
|
881
|
-
**Default Ignore Patterns:**
|
|
882
|
-
`index.js`, `index.jsx`, `index.ts`, `index.tsx`, `.DS_Store`, `__tests__`, `__mocks__`, `*.test.js`, `*.test.jsx`, `*.spec.js`, `*.spec.jsx`
|
|
883
|
-
|
|
884
1330
|
```javascript
|
|
885
|
-
// Example: Add custom folders and patterns
|
|
1331
|
+
// Example: Add custom folders and patterns
|
|
886
1332
|
"code-style/module-index-exports": ["error", {
|
|
887
1333
|
extraModuleFolders: ["features", "modules", "lib"],
|
|
888
1334
|
extraLazyLoadFolders: ["pages"],
|
|
@@ -896,185 +1342,342 @@ export { Input } from "./Input";
|
|
|
896
1342
|
|
|
897
1343
|
### `jsx-children-on-new-line`
|
|
898
1344
|
|
|
899
|
-
When a JSX element has multiple children, each child
|
|
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.
|
|
900
1348
|
|
|
901
1349
|
```javascript
|
|
902
|
-
// Good
|
|
1350
|
+
// ✅ Good — each child on its own line
|
|
903
1351
|
<Container>
|
|
904
1352
|
<Header />
|
|
905
1353
|
<Content />
|
|
906
1354
|
<Footer />
|
|
907
1355
|
</Container>
|
|
908
1356
|
|
|
909
|
-
|
|
910
|
-
<
|
|
911
|
-
<
|
|
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>
|
|
912
1373
|
```
|
|
913
1374
|
|
|
914
1375
|
---
|
|
915
1376
|
|
|
916
1377
|
### `jsx-closing-bracket-spacing`
|
|
917
1378
|
|
|
918
|
-
|
|
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.
|
|
919
1382
|
|
|
920
1383
|
```javascript
|
|
921
|
-
// Good
|
|
1384
|
+
// ✅ Good — no space before closing
|
|
922
1385
|
<Button />
|
|
923
|
-
<
|
|
1386
|
+
<Input type="text" />
|
|
1387
|
+
<div className="container">
|
|
1388
|
+
<Modal isOpen={true}>
|
|
924
1389
|
|
|
925
|
-
// Bad
|
|
1390
|
+
// ❌ Bad — space before />
|
|
926
1391
|
<Button / >
|
|
927
|
-
<
|
|
1392
|
+
<Input type="text" / >
|
|
1393
|
+
|
|
1394
|
+
// ❌ Bad — space before >
|
|
1395
|
+
<div className="container" >
|
|
1396
|
+
<Modal isOpen={true} >
|
|
928
1397
|
```
|
|
929
1398
|
|
|
930
1399
|
---
|
|
931
1400
|
|
|
932
1401
|
### `jsx-element-child-new-line`
|
|
933
1402
|
|
|
934
|
-
JSX element
|
|
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.
|
|
935
1406
|
|
|
936
1407
|
```javascript
|
|
937
|
-
// Good
|
|
1408
|
+
// ✅ Good — nested element on new line
|
|
938
1409
|
<Button>
|
|
939
|
-
<Icon />
|
|
1410
|
+
<Icon name="check" />
|
|
940
1411
|
</Button>
|
|
941
1412
|
|
|
942
|
-
|
|
943
|
-
<
|
|
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>
|
|
944
1428
|
```
|
|
945
1429
|
|
|
946
1430
|
---
|
|
947
1431
|
|
|
948
1432
|
### `jsx-logical-expression-simplify`
|
|
949
1433
|
|
|
950
|
-
|
|
1434
|
+
**What it does:** Removes unnecessary parentheses around conditions and JSX elements in logical expressions.
|
|
951
1435
|
|
|
952
|
-
|
|
953
|
-
// Good
|
|
954
|
-
{condition && <Component />}
|
|
955
|
-
{isVisible && <Modal />}
|
|
1436
|
+
**Why use it:** Extra parentheses add visual noise. Simple conditions and elements don't need wrapping.
|
|
956
1437
|
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
{
|
|
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 />)}
|
|
960
1455
|
```
|
|
961
1456
|
|
|
962
1457
|
---
|
|
963
1458
|
|
|
964
1459
|
### `jsx-parentheses-position`
|
|
965
1460
|
|
|
966
|
-
|
|
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.
|
|
967
1464
|
|
|
968
1465
|
```javascript
|
|
969
|
-
// Good
|
|
970
|
-
const
|
|
971
|
-
<div>
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
<div>content</div>
|
|
1466
|
+
// ✅ Good — parenthesis on same line as =>
|
|
1467
|
+
const Card = () => (
|
|
1468
|
+
<div className="card">
|
|
1469
|
+
<h1>Title</h1>
|
|
1470
|
+
</div>
|
|
975
1471
|
);
|
|
976
1472
|
|
|
977
|
-
//
|
|
978
|
-
|
|
979
|
-
(
|
|
980
|
-
<div>
|
|
1473
|
+
// ✅ Good — parenthesis on same line as return
|
|
1474
|
+
function Card() {
|
|
1475
|
+
return (
|
|
1476
|
+
<div className="card">
|
|
1477
|
+
<h1>Title</h1>
|
|
1478
|
+
</div>
|
|
981
1479
|
);
|
|
982
|
-
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
// ❌ Bad — parenthesis on new line after =>
|
|
1483
|
+
const Card = () =>
|
|
983
1484
|
(
|
|
984
|
-
<div>
|
|
1485
|
+
<div className="card">
|
|
1486
|
+
<h1>Title</h1>
|
|
1487
|
+
</div>
|
|
985
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
|
+
}
|
|
986
1499
|
```
|
|
987
1500
|
|
|
988
1501
|
---
|
|
989
1502
|
|
|
990
1503
|
### `jsx-prop-naming-convention`
|
|
991
1504
|
|
|
992
|
-
|
|
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.
|
|
993
1511
|
|
|
994
1512
|
```javascript
|
|
995
|
-
// Good
|
|
996
|
-
<Button onClick={
|
|
997
|
-
<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
|
|
998
1523
|
<Modal ContentComponent={Panel} />
|
|
1524
|
+
<Route Component={HomePage} />
|
|
999
1525
|
|
|
1000
|
-
// Bad
|
|
1001
|
-
<Button on_click={handler} />
|
|
1002
|
-
<Input
|
|
1526
|
+
// ❌ Bad — snake_case props
|
|
1527
|
+
<Button on_click={handler} is_disabled={false} />
|
|
1528
|
+
<Input on_change={handler} auto_focus />
|
|
1529
|
+
|
|
1530
|
+
// ❌ Bad — kebab-case for regular props
|
|
1531
|
+
<Button is-disabled={false} />
|
|
1003
1532
|
```
|
|
1004
1533
|
|
|
1005
1534
|
---
|
|
1006
1535
|
|
|
1007
1536
|
### `jsx-simple-element-one-line`
|
|
1008
1537
|
|
|
1009
|
-
|
|
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.
|
|
1010
1541
|
|
|
1011
1542
|
```javascript
|
|
1012
|
-
// Good
|
|
1013
|
-
<Button>{
|
|
1014
|
-
<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>
|
|
1548
|
+
|
|
1549
|
+
// ✅ Good — complex children stay multiline
|
|
1550
|
+
<Button>
|
|
1551
|
+
<Icon />
|
|
1552
|
+
{buttonText}
|
|
1553
|
+
</Button>
|
|
1015
1554
|
|
|
1016
|
-
// Bad
|
|
1555
|
+
// ❌ Bad — unnecessary multiline for simple content
|
|
1017
1556
|
<Button>
|
|
1018
|
-
{
|
|
1557
|
+
{buttonText}
|
|
1019
1558
|
</Button>
|
|
1559
|
+
|
|
1560
|
+
<Title>
|
|
1561
|
+
Welcome
|
|
1562
|
+
</Title>
|
|
1563
|
+
|
|
1564
|
+
<span>
|
|
1565
|
+
{count}
|
|
1566
|
+
</span>
|
|
1020
1567
|
```
|
|
1021
1568
|
|
|
1022
1569
|
---
|
|
1023
1570
|
|
|
1024
1571
|
### `jsx-string-value-trim`
|
|
1025
1572
|
|
|
1026
|
-
|
|
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).
|
|
1027
1576
|
|
|
1028
1577
|
```javascript
|
|
1029
|
-
// Good
|
|
1030
|
-
className="
|
|
1031
|
-
|
|
1578
|
+
// ✅ Good — no extra whitespace
|
|
1579
|
+
<Button className="primary" />
|
|
1580
|
+
<Input placeholder="Enter email" />
|
|
1581
|
+
<a href="/home">Home</a>
|
|
1032
1582
|
|
|
1033
|
-
// Bad
|
|
1034
|
-
className="
|
|
1035
|
-
|
|
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>
|
|
1590
|
+
|
|
1591
|
+
// ❌ Bad — both
|
|
1592
|
+
<Button className=" primary " />
|
|
1036
1593
|
```
|
|
1037
1594
|
|
|
1038
1595
|
---
|
|
1039
1596
|
|
|
1040
1597
|
### `jsx-ternary-format`
|
|
1041
1598
|
|
|
1042
|
-
|
|
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.
|
|
1043
1604
|
|
|
1044
1605
|
```javascript
|
|
1045
|
-
// Good
|
|
1046
|
-
{
|
|
1047
|
-
{
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
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>
|
|
1051
1618
|
)}
|
|
1052
1619
|
|
|
1053
|
-
//
|
|
1054
|
-
{
|
|
1055
|
-
|
|
1056
|
-
|
|
1620
|
+
// ✅ Good — one simple, one complex
|
|
1621
|
+
{isLoading ? <Spinner /> : (
|
|
1622
|
+
<Content>
|
|
1623
|
+
<Header />
|
|
1624
|
+
<Body />
|
|
1625
|
+
</Content>
|
|
1626
|
+
)}
|
|
1627
|
+
|
|
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>}
|
|
1057
1638
|
```
|
|
1058
1639
|
|
|
1059
1640
|
---
|
|
1060
1641
|
|
|
1061
1642
|
### `no-empty-lines-in-jsx`
|
|
1062
1643
|
|
|
1063
|
-
|
|
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.
|
|
1064
1647
|
|
|
1065
1648
|
```javascript
|
|
1066
|
-
// Good
|
|
1649
|
+
// ✅ Good — no empty lines inside
|
|
1067
1650
|
<div>
|
|
1068
|
-
<
|
|
1069
|
-
<
|
|
1651
|
+
<Header />
|
|
1652
|
+
<Content />
|
|
1653
|
+
<Footer />
|
|
1070
1654
|
</div>
|
|
1071
1655
|
|
|
1072
|
-
|
|
1656
|
+
<Form>
|
|
1657
|
+
<Input name="email" />
|
|
1658
|
+
<Input name="password" />
|
|
1659
|
+
<Button>Submit</Button>
|
|
1660
|
+
</Form>
|
|
1661
|
+
|
|
1662
|
+
// ❌ Bad — empty line after opening tag
|
|
1073
1663
|
<div>
|
|
1074
1664
|
|
|
1075
|
-
<
|
|
1665
|
+
<Header />
|
|
1666
|
+
<Content />
|
|
1667
|
+
</div>
|
|
1668
|
+
|
|
1669
|
+
// ❌ Bad — empty lines between children
|
|
1670
|
+
<Form>
|
|
1671
|
+
<Input name="email" />
|
|
1672
|
+
|
|
1673
|
+
<Input name="password" />
|
|
1674
|
+
|
|
1675
|
+
<Button>Submit</Button>
|
|
1676
|
+
</Form>
|
|
1076
1677
|
|
|
1077
|
-
|
|
1678
|
+
// ❌ Bad — empty line before closing tag
|
|
1679
|
+
<div>
|
|
1680
|
+
<Content />
|
|
1078
1681
|
|
|
1079
1682
|
</div>
|
|
1080
1683
|
```
|
|
@@ -1083,133 +1686,270 @@ JSX elements should not contain empty lines between children or after opening/be
|
|
|
1083
1686
|
|
|
1084
1687
|
## 📞 Call Expression Rules
|
|
1085
1688
|
|
|
1086
|
-
### `
|
|
1689
|
+
### `function-arguments-format`
|
|
1690
|
+
|
|
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)
|
|
1087
1696
|
|
|
1088
|
-
|
|
1697
|
+
**Why use it:** Consistent argument formatting makes function calls scannable and diffs clean when adding/removing arguments.
|
|
1089
1698
|
|
|
1090
1699
|
```javascript
|
|
1091
|
-
// Good
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
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
|
+
);
|
|
1732
|
+
|
|
1733
|
+
// ❌ Bad — multiple arguments on same line
|
|
1734
|
+
setValue("email", "user@example.com");
|
|
1735
|
+
createUser(name, email, password);
|
|
1096
1736
|
|
|
1097
|
-
// Bad
|
|
1737
|
+
// ❌ Bad — inconsistent formatting
|
|
1098
1738
|
fn(arg1,
|
|
1099
|
-
arg2)
|
|
1739
|
+
arg2, arg3);
|
|
1100
1740
|
```
|
|
1101
1741
|
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
### `multiple-arguments-per-line`
|
|
1742
|
+
**Options:**
|
|
1105
1743
|
|
|
1106
|
-
|
|
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 |
|
|
1107
1749
|
|
|
1108
1750
|
```javascript
|
|
1109
|
-
//
|
|
1110
|
-
|
|
1111
|
-
"numberOfCopies",
|
|
1112
|
-
null,
|
|
1113
|
-
)
|
|
1751
|
+
// Example: Require multiline for 3+ arguments
|
|
1752
|
+
"code-style/function-arguments-format": ["error", { minArgs: 3 }]
|
|
1114
1753
|
|
|
1115
|
-
//
|
|
1116
|
-
|
|
1754
|
+
// Example: Don't skip React hooks
|
|
1755
|
+
"code-style/function-arguments-format": ["error", { skipHooks: false }]
|
|
1117
1756
|
```
|
|
1118
1757
|
|
|
1119
1758
|
---
|
|
1120
1759
|
|
|
1121
1760
|
### `nested-call-closing-brackets`
|
|
1122
1761
|
|
|
1123
|
-
|
|
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.
|
|
1124
1765
|
|
|
1125
1766
|
```javascript
|
|
1126
|
-
// Good
|
|
1127
|
-
styled(Card)(({ theme }) => ({
|
|
1128
|
-
color: theme.
|
|
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,
|
|
1129
1775
|
}));
|
|
1130
1776
|
|
|
1131
|
-
//
|
|
1132
|
-
|
|
1133
|
-
|
|
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,
|
|
1134
1786
|
})
|
|
1135
1787
|
);
|
|
1788
|
+
|
|
1789
|
+
// ❌ Bad — each bracket on its own line
|
|
1790
|
+
const StyledCard = styled(Card)(({ theme }) => ({
|
|
1791
|
+
color: theme.colors.primary,
|
|
1792
|
+
})
|
|
1793
|
+
)
|
|
1794
|
+
;
|
|
1136
1795
|
```
|
|
1137
1796
|
|
|
1138
1797
|
---
|
|
1139
1798
|
|
|
1140
1799
|
### `no-empty-lines-in-function-calls`
|
|
1141
1800
|
|
|
1142
|
-
|
|
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.
|
|
1143
1804
|
|
|
1144
1805
|
```javascript
|
|
1145
|
-
// Good
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1806
|
+
// ✅ Good — no empty lines
|
|
1807
|
+
createUser(
|
|
1808
|
+
name,
|
|
1809
|
+
email,
|
|
1810
|
+
password,
|
|
1811
|
+
role,
|
|
1812
|
+
);
|
|
1150
1813
|
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1814
|
+
fetchData(
|
|
1815
|
+
url,
|
|
1816
|
+
{
|
|
1817
|
+
method: "POST",
|
|
1818
|
+
body: data,
|
|
1819
|
+
},
|
|
1820
|
+
);
|
|
1154
1821
|
|
|
1155
|
-
|
|
1156
|
-
|
|
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
|
+
);
|
|
1157
1844
|
```
|
|
1158
1845
|
|
|
1159
1846
|
---
|
|
1160
1847
|
|
|
1161
1848
|
### `opening-brackets-same-line`
|
|
1162
1849
|
|
|
1163
|
-
|
|
1850
|
+
**What it does:** Ensures opening brackets (`{`, `[`, `(`) in function arguments stay on the same line as the function call.
|
|
1164
1851
|
|
|
1165
|
-
|
|
1166
|
-
// Good
|
|
1167
|
-
fn({ prop: value })
|
|
1168
|
-
.map(({ x }) => x)
|
|
1169
|
-
fn([1, 2, 3])
|
|
1852
|
+
**Why use it:** Opening brackets on new lines create unnecessary indentation and vertical space.
|
|
1170
1853
|
|
|
1171
|
-
|
|
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
|
|
1172
1872
|
fn(
|
|
1173
|
-
{
|
|
1174
|
-
)
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1873
|
+
{ key: value }
|
|
1874
|
+
);
|
|
1875
|
+
|
|
1876
|
+
process(
|
|
1877
|
+
[1, 2, 3]
|
|
1878
|
+
);
|
|
1879
|
+
|
|
1880
|
+
items.map(
|
|
1881
|
+
({ id }) => id
|
|
1882
|
+
);
|
|
1178
1883
|
```
|
|
1179
1884
|
|
|
1180
1885
|
---
|
|
1181
1886
|
|
|
1182
1887
|
### `simple-call-single-line`
|
|
1183
1888
|
|
|
1184
|
-
|
|
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.
|
|
1185
1892
|
|
|
1186
1893
|
```javascript
|
|
1187
|
-
// Good
|
|
1188
|
-
|
|
1189
|
-
lazy(() => import("./
|
|
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
|
+
);
|
|
1190
1911
|
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
)
|
|
1912
|
+
setTimeout(
|
|
1913
|
+
() => callback(),
|
|
1914
|
+
100,
|
|
1915
|
+
);
|
|
1195
1916
|
```
|
|
1196
1917
|
|
|
1197
1918
|
---
|
|
1198
1919
|
|
|
1199
1920
|
### `single-argument-on-one-line`
|
|
1200
1921
|
|
|
1201
|
-
|
|
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.
|
|
1202
1925
|
|
|
1203
1926
|
```javascript
|
|
1204
|
-
// Good
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
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
|
+
);
|
|
1208
1945
|
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1946
|
+
console.log(
|
|
1947
|
+
message,
|
|
1948
|
+
);
|
|
1949
|
+
|
|
1950
|
+
dispatch(
|
|
1951
|
+
action,
|
|
1952
|
+
);
|
|
1213
1953
|
```
|
|
1214
1954
|
|
|
1215
1955
|
<br />
|
|
@@ -1218,92 +1958,219 @@ fn(
|
|
|
1218
1958
|
|
|
1219
1959
|
### `no-empty-lines-in-objects`
|
|
1220
1960
|
|
|
1221
|
-
|
|
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.
|
|
1222
1964
|
|
|
1223
1965
|
```javascript
|
|
1224
|
-
// Good
|
|
1225
|
-
{
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1966
|
+
// ✅ Good — no empty lines
|
|
1967
|
+
const user = {
|
|
1968
|
+
name: "John",
|
|
1969
|
+
email: "john@example.com",
|
|
1970
|
+
role: "admin",
|
|
1971
|
+
};
|
|
1229
1972
|
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1973
|
+
const config = {
|
|
1974
|
+
host: "localhost",
|
|
1975
|
+
port: 3000,
|
|
1976
|
+
debug: true,
|
|
1977
|
+
};
|
|
1233
1978
|
|
|
1234
|
-
|
|
1235
|
-
|
|
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
|
+
};
|
|
1236
2001
|
```
|
|
1237
2002
|
|
|
1238
2003
|
---
|
|
1239
2004
|
|
|
1240
2005
|
### `object-property-per-line`
|
|
1241
2006
|
|
|
1242
|
-
|
|
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.
|
|
1243
2012
|
|
|
1244
2013
|
```javascript
|
|
1245
|
-
// Good
|
|
1246
|
-
{
|
|
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 = {
|
|
1247
2026
|
name: "John",
|
|
1248
|
-
|
|
1249
|
-
|
|
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" };
|
|
1250
2043
|
|
|
1251
|
-
// Bad
|
|
1252
|
-
{
|
|
1253
|
-
|
|
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 |
|
|
2054
|
+
|
|
2055
|
+
```javascript
|
|
2056
|
+
// Example: Require 3+ properties for expansion
|
|
2057
|
+
"code-style/object-property-per-line": ["error", { minProperties: 3 }]
|
|
1254
2058
|
```
|
|
1255
2059
|
|
|
1256
2060
|
---
|
|
1257
2061
|
|
|
1258
2062
|
### `object-property-value-brace`
|
|
1259
2063
|
|
|
1260
|
-
|
|
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.
|
|
1261
2067
|
|
|
1262
2068
|
```javascript
|
|
1263
|
-
// Good
|
|
1264
|
-
|
|
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
|
+
};
|
|
1265
2081
|
|
|
1266
|
-
// Bad
|
|
1267
|
-
|
|
1268
|
-
|
|
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
|
+
};
|
|
1269
2097
|
```
|
|
1270
2098
|
|
|
1271
2099
|
---
|
|
1272
2100
|
|
|
1273
2101
|
### `object-property-value-format`
|
|
1274
2102
|
|
|
1275
|
-
|
|
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.
|
|
1276
2106
|
|
|
1277
2107
|
```javascript
|
|
1278
|
-
// Good
|
|
1279
|
-
{
|
|
2108
|
+
// ✅ Good — values on same line as colon
|
|
2109
|
+
const user = {
|
|
1280
2110
|
name: "John",
|
|
1281
2111
|
age: 30,
|
|
1282
|
-
|
|
2112
|
+
isActive: true,
|
|
2113
|
+
role: userRole,
|
|
2114
|
+
};
|
|
1283
2115
|
|
|
1284
|
-
//
|
|
1285
|
-
{
|
|
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 = {
|
|
1286
2129
|
name:
|
|
1287
2130
|
"John",
|
|
1288
2131
|
age:
|
|
1289
2132
|
30,
|
|
1290
|
-
|
|
2133
|
+
isActive:
|
|
2134
|
+
true,
|
|
2135
|
+
};
|
|
1291
2136
|
```
|
|
1292
2137
|
|
|
1293
2138
|
---
|
|
1294
2139
|
|
|
1295
2140
|
### `string-property-spacing`
|
|
1296
2141
|
|
|
1297
|
-
|
|
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.
|
|
1298
2145
|
|
|
1299
2146
|
```javascript
|
|
1300
|
-
// Good
|
|
1301
|
-
|
|
1302
|
-
{ "
|
|
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
|
+
};
|
|
2158
|
+
|
|
2159
|
+
// ❌ Bad — leading whitespace
|
|
2160
|
+
const styles = {
|
|
2161
|
+
" & a": { color: "red" },
|
|
2162
|
+
" & .button": { padding: "10px" },
|
|
2163
|
+
};
|
|
1303
2164
|
|
|
1304
|
-
// Bad
|
|
1305
|
-
|
|
1306
|
-
|
|
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
|
+
};
|
|
1307
2174
|
```
|
|
1308
2175
|
|
|
1309
2176
|
<br />
|