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.
- package/README.md +1339 -461
- package/index.js +800 -463
- 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" },
|
|
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
|
|
337
|
-
|
|
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
|
+
);
|
|
394
|
+
|
|
395
|
+
// ❌ Bad — comma operator is confusing
|
|
396
|
+
const handleSubmit = () => (validateForm(), submitData(), result);
|
|
354
397
|
|
|
355
|
-
// Bad
|
|
356
|
-
() =>
|
|
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
|
+
) => {};
|
|
501
630
|
|
|
502
|
-
|
|
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
|
-
|
|
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
|
|
591
784
|
useEffect(
|
|
592
|
-
() => {
|
|
593
|
-
|
|
785
|
+
() => {
|
|
786
|
+
fetchData();
|
|
787
|
+
},
|
|
788
|
+
[userId],
|
|
789
|
+
);
|
|
790
|
+
|
|
791
|
+
useCallback(
|
|
792
|
+
() => {
|
|
793
|
+
handleSubmit(data);
|
|
794
|
+
},
|
|
795
|
+
[data, handleSubmit],
|
|
594
796
|
);
|
|
595
797
|
|
|
596
|
-
|
|
597
|
-
|
|
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
|
-
|
|
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:**
|
|
614
863
|
|
|
615
|
-
|
|
616
|
-
|
|
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
|
-
|
|
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
|
+
}
|
|
953
|
+
|
|
954
|
+
if (
|
|
955
|
+
user.isAdmin ||
|
|
956
|
+
user.isModerator ||
|
|
957
|
+
user.hasSpecialAccess ||
|
|
958
|
+
isPublicResource
|
|
959
|
+
) {
|
|
960
|
+
showContent();
|
|
961
|
+
}
|
|
659
962
|
|
|
660
|
-
// Bad
|
|
661
|
-
if (
|
|
662
|
-
|
|
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";
|
|
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 (
|
|
682
|
-
case
|
|
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,107 +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
|
|
1167
|
+
import {
|
|
1168
|
+
useState,
|
|
1169
|
+
useEffect,
|
|
1170
|
+
useCallback,
|
|
1171
|
+
useMemo,
|
|
1172
|
+
} from "react";
|
|
1173
|
+
|
|
762
1174
|
import {
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
} from "
|
|
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 {
|
|
771
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 - 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"` |
|
|
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
|
-
|
|
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
|
-
//
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
899
|
-
<
|
|
900
|
-
<
|
|
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
|
-
|
|
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
|
-
<
|
|
1386
|
+
<Input type="text" />
|
|
1387
|
+
<div className="container">
|
|
1388
|
+
<Modal isOpen={true}>
|
|
913
1389
|
|
|
914
|
-
// Bad
|
|
1390
|
+
// ❌ Bad — space before />
|
|
915
1391
|
<Button / >
|
|
916
|
-
<
|
|
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
|
|
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
|
-
|
|
932
|
-
<
|
|
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
|
-
|
|
1434
|
+
**What it does:** Removes unnecessary parentheses around conditions and JSX elements in logical expressions.
|
|
940
1435
|
|
|
941
|
-
|
|
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
|
-
|
|
947
|
-
|
|
948
|
-
{
|
|
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
|
-
|
|
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
|
|
960
|
-
<div>
|
|
961
|
-
|
|
962
|
-
|
|
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
|
-
//
|
|
967
|
-
|
|
968
|
-
(
|
|
969
|
-
<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
|
-
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
// ❌ Bad — parenthesis on new line after =>
|
|
1483
|
+
const Card = () =>
|
|
972
1484
|
(
|
|
973
|
-
<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
|
-
|
|
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={
|
|
986
|
-
<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
|
|
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
|
-
|
|
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>{
|
|
1003
|
-
<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
|
-
//
|
|
1549
|
+
// ✅ Good — complex children stay multiline
|
|
1006
1550
|
<Button>
|
|
1007
|
-
|
|
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
|
-
|
|
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="
|
|
1020
|
-
|
|
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="
|
|
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
|
-
|
|
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
|
-
{
|
|
1036
|
-
{
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
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
|
-
{
|
|
1044
|
-
? <
|
|
1045
|
-
: <
|
|
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
|
-
|
|
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
|
-
<
|
|
1058
|
-
<
|
|
1651
|
+
<Header />
|
|
1652
|
+
<Content />
|
|
1653
|
+
<Footer />
|
|
1059
1654
|
</div>
|
|
1060
1655
|
|
|
1061
|
-
|
|
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
|
-
<
|
|
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
|
-
<
|
|
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
|
-
### `
|
|
1689
|
+
### `function-arguments-format`
|
|
1076
1690
|
|
|
1077
|
-
|
|
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
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
1099
|
-
|
|
1100
|
-
"numberOfCopies",
|
|
1101
|
-
null,
|
|
1102
|
-
)
|
|
1751
|
+
// Example: Require multiline for 3+ arguments
|
|
1752
|
+
"code-style/function-arguments-format": ["error", { minArgs: 3 }]
|
|
1103
1753
|
|
|
1104
|
-
//
|
|
1105
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
//
|
|
1121
|
-
|
|
1122
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1806
|
+
// ✅ Good — no empty lines
|
|
1807
|
+
createUser(
|
|
1808
|
+
name,
|
|
1809
|
+
email,
|
|
1810
|
+
password,
|
|
1811
|
+
role,
|
|
1812
|
+
);
|
|
1139
1813
|
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1814
|
+
fetchData(
|
|
1815
|
+
url,
|
|
1816
|
+
{
|
|
1817
|
+
method: "POST",
|
|
1818
|
+
body: data,
|
|
1819
|
+
},
|
|
1820
|
+
);
|
|
1143
1821
|
|
|
1144
|
-
|
|
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
|
-
|
|
1850
|
+
**What it does:** Ensures opening brackets (`{`, `[`, `(`) in function arguments stay on the same line as the function call.
|
|
1153
1851
|
|
|
1154
|
-
|
|
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
|
-
|
|
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
|
-
{
|
|
1163
|
-
)
|
|
1164
|
-
|
|
1165
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1178
|
-
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
|
+
);
|
|
1179
1911
|
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
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
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1966
|
+
// ✅ Good — no empty lines
|
|
1967
|
+
const user = {
|
|
1968
|
+
name: "John",
|
|
1969
|
+
email: "john@example.com",
|
|
1970
|
+
role: "admin",
|
|
1971
|
+
};
|
|
1218
1972
|
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1973
|
+
const config = {
|
|
1974
|
+
host: "localhost",
|
|
1975
|
+
port: 3000,
|
|
1976
|
+
debug: true,
|
|
1977
|
+
};
|
|
1222
1978
|
|
|
1223
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1257
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
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
|
-
|
|
1291
|
-
{ "
|
|
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
|
-
|
|
1295
|
-
|
|
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 />
|