eslint-plugin-nextfriday 1.20.0 → 1.22.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # eslint-plugin-nextfriday
2
2
 
3
+ ## 1.22.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#92](https://github.com/next-friday/eslint-plugin-nextfriday/pull/92) [`432b4b4`](https://github.com/next-friday/eslint-plugin-nextfriday/commit/432b4b49cabc0d6ea9289441b13e7442d328614f) Thanks [@joetakara](https://github.com/joetakara)! - Rework enforce-service-naming rule to ban misleading prefixes (set, delete, do, handle) instead of forcing fetch prefix. Allow single-property inline nested objects in no-inline-nested-object rule. Fix documentation inconsistencies across README, rule docs, and configuration presets. Update dependencies to resolve security vulnerabilities.
8
+
9
+ ## 1.21.0
10
+
11
+ ### Minor Changes
12
+
13
+ - [#87](https://github.com/next-friday/eslint-plugin-nextfriday/pull/87) [`ed401e3`](https://github.com/next-friday/eslint-plugin-nextfriday/commit/ed401e39db04857995ddcc29d7444298181ee60b) Thanks [@joetakara](https://github.com/joetakara)! - Add `no-inline-return-properties` rule that enforces shorthand-only properties in return objects
14
+
15
+ - [#90](https://github.com/next-friday/eslint-plugin-nextfriday/pull/90) [`d5e9db5`](https://github.com/next-friday/eslint-plugin-nextfriday/commit/d5e9db562cb9e38beadd59da39f8618b6f5825ed) Thanks [@joetakara](https://github.com/joetakara)! - Add comprehensive naming convention rules and fix prefer-import-type JSX prop bug
16
+ - Add `enforce-camel-case` rule: ban snake_case variables/functions, restrict PascalCase to React components
17
+ - Add `enforce-property-case` rule: enforce camelCase for unquoted object property keys
18
+ - Refactor `enforce-constant-case` to only check global scope, support RegExp/objects/arrays/as const
19
+ - Refactor `no-misleading-constant-case` to flag SCREAMING_SNAKE_CASE in local scope
20
+ - Fix `prefer-import-type` incorrectly converting imports used as JSX prop values to type imports
21
+
3
22
  ## 1.20.0
4
23
 
5
24
  ### Minor Changes
package/README.md CHANGED
@@ -78,12 +78,14 @@ export default [
78
78
  "nextfriday/no-single-char-variables": "error",
79
79
  "nextfriday/no-lazy-identifiers": "error",
80
80
  "nextfriday/boolean-naming-prefix": "error",
81
+ "nextfriday/enforce-camel-case": "error",
81
82
  "nextfriday/enforce-constant-case": "error",
83
+ "nextfriday/enforce-property-case": "error",
84
+ "nextfriday/no-misleading-constant-case": "error",
82
85
 
83
86
  // File Naming
84
87
  "nextfriday/file-kebab-case": "error",
85
88
  "nextfriday/jsx-pascal-case": "error",
86
- "nextfriday/md-filename-case-restriction": "error",
87
89
 
88
90
  // Code Style
89
91
  "nextfriday/no-emoji": "error",
@@ -97,9 +99,11 @@ export default [
97
99
  "nextfriday/enforce-sorted-destructuring": "error",
98
100
  "nextfriday/no-env-fallback": "error",
99
101
  "nextfriday/no-inline-default-export": "error",
102
+ "nextfriday/no-direct-date": "error",
100
103
  "nextfriday/newline-after-multiline-block": "error",
101
104
  "nextfriday/newline-before-return": "error",
102
105
  "nextfriday/no-inline-nested-object": "error",
106
+ "nextfriday/no-inline-return-properties": "error",
103
107
  "nextfriday/prefer-async-await": "error",
104
108
  "nextfriday/enforce-curly-newline": "error",
105
109
  "nextfriday/no-nested-ternary": "error",
@@ -155,16 +159,17 @@ export default [
155
159
  | [no-single-char-variables](docs/rules/NO_SINGLE_CHAR_VARIABLES.md) | Disallow single character variable names (e.g., `d`, `u`, `l`) | ❌ |
156
160
  | [no-lazy-identifiers](docs/rules/NO_LAZY_IDENTIFIERS.md) | Disallow lazy identifiers like `xxx`, `asdf`, `qwerty` | ❌ |
157
161
  | [boolean-naming-prefix](docs/rules/BOOLEAN_NAMING_PREFIX.md) | Enforce boolean variables to have prefix (is, has, should, can, etc.) | ❌ |
158
- | [enforce-constant-case](docs/rules/ENFORCE_CONSTANT_CASE.md) | Enforce SCREAMING_SNAKE_CASE for static constant primitive values | ❌ |
159
- | [no-misleading-constant-case](docs/rules/NO_MISLEADING_CONSTANT_CASE.md) | Disallow SCREAMING_SNAKE_CASE for non-constant or non-static values | ❌ |
162
+ | [enforce-camel-case](docs/rules/ENFORCE_CAMEL_CASE.md) | Ban snake_case and restrict PascalCase to React components | ❌ |
163
+ | [enforce-constant-case](docs/rules/ENFORCE_CONSTANT_CASE.md) | Enforce SCREAMING_SNAKE_CASE for global static constant values | ❌ |
164
+ | [enforce-property-case](docs/rules/ENFORCE_PROPERTY_CASE.md) | Enforce camelCase for unquoted object property keys | ❌ |
165
+ | [no-misleading-constant-case](docs/rules/NO_MISLEADING_CONSTANT_CASE.md) | Disallow SCREAMING_SNAKE_CASE in local scope and for dynamic values | ❌ |
160
166
 
161
167
  ### File Naming Rules
162
168
 
163
- | Rule | Description | Fixable |
164
- | -------------------------------------------------------------------------- | ---------------------------------------------------- | ------- |
165
- | [file-kebab-case](docs/rules/FILE_KEBAB_CASE.md) | Enforce kebab-case filenames for .ts and .js files | ❌ |
166
- | [jsx-pascal-case](docs/rules/JSX_PASCAL_CASE.md) | Enforce PascalCase filenames for .jsx and .tsx files | ❌ |
167
- | [md-filename-case-restriction](docs/rules/MD_FILENAME_CASE_RESTRICTION.md) | Enforce SNAKE_CASE filenames for .md files | ❌ |
169
+ | Rule | Description | Fixable |
170
+ | ------------------------------------------------ | ---------------------------------------------------- | ------- |
171
+ | [file-kebab-case](docs/rules/FILE_KEBAB_CASE.md) | Enforce kebab-case filenames for .ts and .js files | ❌ |
172
+ | [jsx-pascal-case](docs/rules/JSX_PASCAL_CASE.md) | Enforce PascalCase filenames for .jsx and .tsx files | ❌ |
168
173
 
169
174
  ### Code Style Rules
170
175
 
@@ -185,6 +190,7 @@ export default [
185
190
  | [newline-after-multiline-block](docs/rules/NEWLINE_AFTER_MULTILINE_BLOCK.md) | Require a blank line after multi-line statements | ✅ |
186
191
  | [newline-before-return](docs/rules/NEWLINE_BEFORE_RETURN.md) | Require a blank line before return statements | ✅ |
187
192
  | [no-inline-nested-object](docs/rules/NO_INLINE_NESTED_OBJECT.md) | Require nested objects and arrays to span multiple lines | ✅ |
193
+ | [no-inline-return-properties](docs/rules/NO_INLINE_RETURN_PROPERTIES.md) | Require return object properties to use shorthand notation | ❌ |
188
194
  | [prefer-async-await](docs/rules/PREFER_ASYNC_AWAIT.md) | Enforce async/await over .then() promise chains | ❌ |
189
195
  | [enforce-curly-newline](docs/rules/ENFORCE_CURLY_NEWLINE.md) | Enforce curly braces for multi-line if, forbid for single-line | ✅ |
190
196
  | [no-nested-ternary](docs/rules/NO_NESTED_TERNARY.md) | Disallow nested ternary expressions | ❌ |
@@ -243,26 +249,27 @@ export default [
243
249
 
244
250
  | Preset | Severity | Base Rules | JSX Rules | Next.js Rules | Total Rules |
245
251
  | -------------------- | -------- | ---------- | --------- | ------------- | ----------- |
246
- | `base` | warn | 37 | 0 | 0 | 37 |
247
- | `base/recommended` | error | 37 | 0 | 0 | 37 |
248
- | `react` | warn | 37 | 15 | 0 | 52 |
249
- | `react/recommended` | error | 37 | 15 | 0 | 52 |
250
- | `nextjs` | warn | 37 | 15 | 1 | 53 |
251
- | `nextjs/recommended` | error | 37 | 15 | 1 | 53 |
252
+ | `base` | warn | 40 | 0 | 0 | 40 |
253
+ | `base/recommended` | error | 40 | 0 | 0 | 40 |
254
+ | `react` | warn | 40 | 15 | 0 | 55 |
255
+ | `react/recommended` | error | 40 | 15 | 0 | 55 |
256
+ | `nextjs` | warn | 40 | 15 | 1 | 56 |
257
+ | `nextjs/recommended` | error | 40 | 15 | 1 | 56 |
252
258
 
253
- ### Base Configuration Rules (37 rules)
259
+ ### Base Configuration Rules (40 rules)
254
260
 
255
261
  Included in `base`, `base/recommended`, and all other presets:
256
262
 
257
263
  - `nextfriday/boolean-naming-prefix`
264
+ - `nextfriday/enforce-camel-case`
258
265
  - `nextfriday/enforce-constant-case`
259
266
  - `nextfriday/enforce-curly-newline`
260
267
  - `nextfriday/enforce-hook-naming`
268
+ - `nextfriday/enforce-property-case`
261
269
  - `nextfriday/enforce-service-naming`
262
270
  - `nextfriday/enforce-sorted-destructuring`
263
271
  - `nextfriday/enforce-type-declaration-order`
264
272
  - `nextfriday/file-kebab-case`
265
- - `nextfriday/md-filename-case-restriction`
266
273
  - `nextfriday/newline-after-multiline-block`
267
274
  - `nextfriday/newline-before-return`
268
275
  - `nextfriday/no-complex-inline-return`
@@ -271,8 +278,10 @@ Included in `base`, `base/recommended`, and all other presets:
271
278
  - `nextfriday/no-env-fallback`
272
279
  - `nextfriday/no-inline-default-export`
273
280
  - `nextfriday/no-inline-nested-object`
281
+ - `nextfriday/no-inline-return-properties`
274
282
  - `nextfriday/no-lazy-identifiers`
275
283
  - `nextfriday/no-logic-in-params`
284
+ - `nextfriday/no-misleading-constant-case`
276
285
  - `nextfriday/no-nested-interface-declaration`
277
286
  - `nextfriday/no-nested-ternary`
278
287
  - `nextfriday/no-relative-imports`
@@ -336,7 +345,7 @@ Additionally included in `nextjs`, `nextjs/recommended` only:
336
345
 
337
346
  ## Agent Skill
338
347
 
339
- This plugin ships with an [Agent Skill](https://github.com/anthropics/skills) that teaches AI coding assistants (Claude Code, Cursor, etc.) all 53 rules so they generate compliant code from the start.
348
+ This plugin ships with an [Agent Skill](https://github.com/anthropics/skills) that teaches AI coding assistants (Claude Code, Cursor, etc.) all 56 rules so they generate compliant code from the start.
340
349
 
341
350
  ```bash
342
351
  npx skills add next-friday/eslint-plugin-nextfriday --skill eslint-plugin-nextfriday
@@ -0,0 +1,68 @@
1
+ # enforce-camel-case
2
+
3
+ Enforce camelCase for variables and functions, ban snake_case, and restrict PascalCase to React components.
4
+
5
+ ## Rule Details
6
+
7
+ This rule enforces consistent naming conventions across your codebase:
8
+
9
+ - Variables and functions must use camelCase
10
+ - snake_case is banned for all variable and function declarations
11
+ - PascalCase is reserved exclusively for React components (functions that return JSX)
12
+
13
+ Global static constants are not checked by this rule. Use `enforce-constant-case` for those.
14
+
15
+ ### Why?
16
+
17
+ Consistent naming conventions reduce cognitive load. When PascalCase is reserved for components and camelCase is used for everything else, the name alone tells you what something is.
18
+
19
+ ## Examples
20
+
21
+ ### Incorrect
22
+
23
+ ```ts
24
+ // snake_case variables
25
+ let current_index = 0;
26
+ const first_name = "John";
27
+
28
+ // snake_case functions
29
+ function calculate_total() {
30
+ return 0;
31
+ }
32
+
33
+ // PascalCase for non-component functions
34
+ const CalculateTotal = () => 0;
35
+ const FormatDate = (date: string) => date;
36
+ ```
37
+
38
+ ### Correct
39
+
40
+ ```ts
41
+ // camelCase variables
42
+ let currentIndex = 0;
43
+ const firstName = "John";
44
+
45
+ // camelCase functions
46
+ function calculateTotal() { return 0; }
47
+ const formatDate = (date: string) => date;
48
+
49
+ // PascalCase for React components
50
+ const ArticleCard = () => <div />;
51
+ const WrappedComponent = memo(() => <div />);
52
+ const LazyPage = lazy(() => import("./Page"));
53
+ ```
54
+
55
+ ## Exceptions
56
+
57
+ - Global static constants (handled by `enforce-constant-case`)
58
+ - SCREAMING_SNAKE_CASE variables (handled by `no-misleading-constant-case`)
59
+ - React components wrapped with `memo`, `forwardRef`, or `lazy`
60
+
61
+ ## When Not To Use It
62
+
63
+ If your project does not follow the convention that PascalCase is reserved for React components.
64
+
65
+ ## Related Rules
66
+
67
+ - [enforce-constant-case](ENFORCE_CONSTANT_CASE.md) - Enforces SCREAMING_SNAKE_CASE for global static constants
68
+ - [no-misleading-constant-case](NO_MISLEADING_CONSTANT_CASE.md) - Disallows SCREAMING_SNAKE_CASE in local scope
@@ -1,10 +1,12 @@
1
1
  # enforce-constant-case
2
2
 
3
- Enforce SCREAMING_SNAKE_CASE for constant primitive values.
3
+ Enforce SCREAMING_SNAKE_CASE for global constant static values.
4
4
 
5
5
  ## Rule Details
6
6
 
7
- This rule ensures that `const` declarations with static primitive values (strings, numbers, booleans, static template literals) use SCREAMING_SNAKE_CASE naming convention. Template literals with expressions (e.g., `` `${variable}` ``) are considered dynamic and are not checked. Objects, arrays, and functions are not checked. Only `const` declarations are checked; `let` and `var` are ignored.
7
+ This rule ensures that global-scope `const` declarations with static values use SCREAMING_SNAKE_CASE naming convention. Static values include: string/number/boolean literals, RegExp, static template literals, `as const` assertions, and objects/arrays containing only literal values.
8
+
9
+ Only global scope (top-level of a file) is checked. Local scope constants inside functions are not checked by this rule.
8
10
 
9
11
  ## Examples
10
12
 
@@ -15,6 +17,9 @@ const defaultCover = "/images/default.jpg";
15
17
  const pageLimit = 10;
16
18
  const apiBaseUrl = "https://api.example.com";
17
19
  const template = `hello world`;
20
+ const phoneRegex = /^[0-9]{10}$/;
21
+ const default_theme = "dark";
22
+ export const categories = [{ id: "1" }] as const;
18
23
  ```
19
24
 
20
25
  ### Correct
@@ -24,27 +29,37 @@ const DEFAULT_COVER = "/images/default.jpg";
24
29
  const PAGE_LIMIT = 10;
25
30
  const API_BASE_URL = "https://api.example.com";
26
31
  const TEMPLATE = `hello world`;
32
+ const PHONE_REGEX = /^[0-9]{10}$/;
33
+ const DEFAULT_THEME = "dark";
34
+ export const CATEGORIES = [{ id: "1" }] as const;
35
+
36
+ const SKELETON_ITEMS = [1, 2, 3, 4, 5];
37
+ const MAP_STYLE = { height: "320px", width: "100%" };
38
+ const STATUS_MAP = { ACTIVE: "active" } as const;
27
39
 
28
- // Booleans with standard prefixes (is, has, should, can, etc.) are exempt
29
- const isEnabled = true;
40
+ // Booleans with standard prefixes (is, has, should, etc.) are exempt
41
+ const isProduction = true;
30
42
  const hasAccess = false;
31
- const shouldRender = true;
32
43
 
33
44
  // Template literals with expressions are dynamic, camelCase is fine
34
45
  const pendingHref = `/branch/${branch.branchNumber}`;
35
- const greeting = `Hello, ${user.name}!`;
36
46
 
37
- // Objects, arrays, and functions can use camelCase
38
- const config = { key: "value" };
39
- const items = [1, 2, 3];
47
+ // Functions and components are not checked
40
48
  const handleClick = () => {};
49
+ const MyComponent = () => {};
41
50
 
42
- // Let and var declarations are not checked
43
- let defaultCover = "/images/default.jpg";
44
- var pageLimit = 10;
51
+ // Local scope is not checked
52
+ function foo() {
53
+ const maxRetry = 3;
54
+ }
45
55
  ```
46
56
 
47
57
  ## When Not To Use It
48
58
 
49
59
  - If your project uses different naming conventions for constants
50
60
  - If you prefer camelCase for all variable declarations
61
+
62
+ ## Related Rules
63
+
64
+ - [no-misleading-constant-case](NO_MISLEADING_CONSTANT_CASE.md) - Disallows SCREAMING_SNAKE_CASE in local scope and for dynamic values
65
+ - [enforce-camel-case](ENFORCE_CAMEL_CASE.md) - Enforces camelCase for variables and functions
@@ -16,35 +16,29 @@ This rule manages curly braces for `IfStatement` based on visual layout (line br
16
16
  ### Incorrect
17
17
 
18
18
  ```ts
19
- // Single-line with braces (BAD)
20
19
  if (!data) {
21
20
  return [];
22
21
  }
23
22
  if (x > 0) {
24
23
  doSomething();
25
24
  }
25
+ ```
26
26
 
27
- // Multi-line without braces (BAD)
27
+ ```ts
28
28
  if (veryLongCondition && anotherCondition) return [];
29
-
30
- if (condition) doSomething();
31
29
  ```
32
30
 
33
31
  ### Correct
34
32
 
35
33
  ```ts
36
- // Single-line without braces (GOOD)
37
34
  if (!data) return [];
38
35
  if (x > 0) doSomething();
36
+ ```
39
37
 
40
- // Multi-line with braces (GOOD)
38
+ ```ts
41
39
  if (veryLongCondition && anotherCondition) {
42
40
  return [];
43
41
  }
44
-
45
- if (condition) {
46
- doSomething();
47
- }
48
42
  ```
49
43
 
50
44
  ## Auto-Fix
@@ -0,0 +1,63 @@
1
+ # enforce-property-case
2
+
3
+ Enforce camelCase for unquoted object property keys.
4
+
5
+ ## Rule Details
6
+
7
+ This rule bans snake_case and SCREAMING_SNAKE_CASE for unquoted object property keys. Quoted keys (string literals) are allowed for API boundaries where external systems require different conventions.
8
+
9
+ ### Why?
10
+
11
+ Object properties should follow the same camelCase convention as variables. When an external API requires snake_case keys, wrapping them in quotes makes it explicit that the naming is intentional and driven by an external contract.
12
+
13
+ ## Examples
14
+
15
+ ### Incorrect
16
+
17
+ ```ts
18
+ const userPayload = {
19
+ first_name: "John",
20
+ last_name: "Doe",
21
+ };
22
+
23
+ const item = {
24
+ ITEM_ID: 1,
25
+ };
26
+ ```
27
+
28
+ ### Correct
29
+
30
+ ```ts
31
+ // camelCase properties
32
+ const userPayload = {
33
+ firstName: "John",
34
+ lastName: "Doe",
35
+ };
36
+
37
+ // Quoted keys for API boundaries
38
+ const apiPayload = {
39
+ first_name: "John",
40
+ last_name: "Doe",
41
+ };
42
+
43
+ // as const objects are exempt (enum-like pattern)
44
+ const STATUS_MAP = {
45
+ ACTIVE: "active",
46
+ INACTIVE: "inactive",
47
+ } as const;
48
+ ```
49
+
50
+ ## Exceptions
51
+
52
+ - Quoted property keys (`"first_name"`) are always allowed
53
+ - Computed property keys (`[key]`) are not checked
54
+ - Properties inside `as const` objects and arrays are exempt
55
+
56
+ ## When Not To Use It
57
+
58
+ If your project frequently uses snake_case or SCREAMING_SNAKE_CASE for object properties without quoting.
59
+
60
+ ## Related Rules
61
+
62
+ - [enforce-camel-case](ENFORCE_CAMEL_CASE.md) - Enforces camelCase for variables and functions
63
+ - [enforce-constant-case](ENFORCE_CONSTANT_CASE.md) - Enforces SCREAMING_SNAKE_CASE for global constants
@@ -1,48 +1,60 @@
1
1
  # enforce-service-naming
2
2
 
3
- Enforce `fetch` prefix for async functions in `*.service.ts` files instead of `get` or `load`.
3
+ Ban misleading function name prefixes in `*.service.ts` files.
4
4
 
5
5
  ## Rule Details
6
6
 
7
- This rule ensures consistent naming conventions for service layer functions. In `*.service.ts` files, async data-fetching functions should use the `fetch` prefix to clearly indicate they perform network/API calls.
7
+ This rule flags misleading prefixes on async exported functions in `*.service.ts` files. It does not force a specific prefix developers choose based on intent.
8
8
 
9
9
  ### Why?
10
10
 
11
- - **Clarity**: `fetch` clearly indicates a network operation, while `get` is ambiguous (could be synchronous accessor)
12
- - **Consistency**: Standardizes naming across all service files
13
- - **Semantics**: `fetch` aligns with the Fetch API and implies async data retrieval
11
+ Service functions represent API/network calls. Certain prefixes are misleading in this context:
12
+
13
+ - `set` implies a local setter, not an API call
14
+ - `delete` is a JS reserved word that may conflict
15
+ - `do` is vague and conveys no intent
16
+ - `handle` is typically for UI event handlers, not service operations
17
+
18
+ ### Banned Prefixes
19
+
20
+ | Prefix | Why banned | Suggested alternatives |
21
+ | -------- | ----------------------------------------- | ------------------------- |
22
+ | `set` | Implies local setter, not API call | `update`, `save`, `patch` |
23
+ | `delete` | JS reserved word, may conflict | `remove`, `archive` |
24
+ | `do` | Vague, no intent | `submit`, `process` |
25
+ | `handle` | Vague, typically for event handlers in UI | `create`, `verify` |
14
26
 
15
27
  ## Examples
16
28
 
17
29
  ### Incorrect
18
30
 
19
31
  ```ts
20
- // article.service.ts
21
- export async function getArticles() {}
22
- export async function loadFaq() {}
23
- export async function getUserById() {}
24
- export const getUsers = async () => {};
32
+ // profile.service.ts
33
+ export async function setProfile(data: ProfileRequest) {}
34
+ export async function deleteComment(id: string) {}
35
+ export async function doLogin(credentials: LoginRequest) {}
36
+ export async function handlePayment(data: PaymentRequest) {}
25
37
  ```
26
38
 
27
39
  ### Correct
28
40
 
29
41
  ```ts
30
- // article.service.ts
42
+ // profile.service.ts
43
+ export async function getArticles() {}
31
44
  export async function fetchArticles() {}
32
- export async function fetchFaqList() {}
33
- export async function fetchUserById() {}
34
- export const fetchUsers = async () => {};
45
+ export async function searchArticles(query: string) {}
46
+ export async function createOrder(data: OrderRequest) {}
47
+ export async function updateProfile(id: string, data: ProfileRequest) {}
48
+ export async function removeComment(id: string) {}
49
+ export async function verifyEmail(token: string) {}
35
50
 
36
51
  // Non-async functions can use any prefix
37
- export function getArticleById(id: string) {}
52
+ export function setLocalState(value: string) {}
38
53
 
39
- // Other prefixes are allowed
40
- export async function createUser() {}
41
- export async function updateArticle() {}
42
- export async function deleteComment() {}
54
+ // Non-exported functions are not checked
55
+ async function handleInternal() {}
43
56
  ```
44
57
 
45
58
  ## When Not To Use It
46
59
 
47
- - If your project uses different naming conventions for service functions
48
- - If you prefer `get`/`load` prefixes for data-fetching operations
60
+ If your project does not follow a service layer pattern or has different naming conventions for service functions.
@@ -39,4 +39,4 @@ If your team prefers explicit ternary expressions for conditional rendering, eve
39
39
 
40
40
  ## Related Rules
41
41
 
42
- - [no-nested-ternary](JSX_NO_TERNARY_NULL.md)
42
+ - [no-nested-ternary](NO_NESTED_TERNARY.md)
@@ -1,10 +1,10 @@
1
1
  # no-inline-nested-object
2
2
 
3
- Require nested objects and arrays to span multiple lines.
3
+ Require nested objects and arrays with multiple properties to span multiple lines.
4
4
 
5
5
  ## Rule Details
6
6
 
7
- This rule enforces that when an object property's value is another object or array, it should span multiple lines rather than being written inline. This improves readability and makes diffs cleaner when properties are added or removed.
7
+ This rule enforces that when an object property's value is another object or array with more than one element, it should span multiple lines rather than being written inline. Single-property nested objects are allowed inline. This improves readability and makes diffs cleaner when properties are added or removed.
8
8
 
9
9
  ## Examples
10
10
 
@@ -25,6 +25,12 @@ const routes = {
25
25
 
26
26
  ### Correct
27
27
 
28
+ ```ts
29
+ const config = {
30
+ database: { host: "localhost" },
31
+ };
32
+ ```
33
+
28
34
  ```ts
29
35
  const config = {
30
36
  database: {
@@ -65,8 +71,8 @@ const initialState = {
65
71
 
66
72
  ## When Not To Use It
67
73
 
68
- If you prefer compact inline nested objects for simple cases, or if your team has different formatting preferences.
74
+ If you prefer compact inline nested objects for all cases, or if your team has different formatting preferences.
69
75
 
70
76
  ## Fixable
71
77
 
72
- This rule is auto-fixable. Running ESLint with the `--fix` flag will automatically expand inline nested objects and arrays to multiple lines.
78
+ This rule is auto-fixable. Running ESLint with the `--fix` flag will automatically expand inline nested objects and arrays with multiple properties to multiple lines.
@@ -0,0 +1,83 @@
1
+ # no-inline-return-properties
2
+
3
+ Require return object properties to use shorthand notation by extracting non-shorthand values to const variables.
4
+
5
+ ## Rule Details
6
+
7
+ This rule enforces that all properties in a returned object literal use shorthand notation. When a return statement contains an object with renamed or computed properties, the values should be extracted into const variables before the return statement.
8
+
9
+ ### Why?
10
+
11
+ Return objects with a mix of shorthand and non-shorthand properties are harder to scan. Extracting values into named constants before returning keeps the return statement clean and makes the data flow easier to follow.
12
+
13
+ ## Examples
14
+
15
+ ### Incorrect
16
+
17
+ ```ts
18
+ function useBranch() {
19
+ return {
20
+ admins,
21
+ branch,
22
+ coursesCurrentPage: coursePage,
23
+ coursesTotalPages: Math.ceil(sortedLearning.length / COURSES_PER_PAGE) || 1,
24
+ members,
25
+ membersHref: `/branch/${branchNumber}/members`,
26
+ news,
27
+ newsCurrentPage: newsData?.currentPage ?? 1,
28
+ newsTotalPages: newsData?.pages ?? 1,
29
+ stats,
30
+ };
31
+ }
32
+ ```
33
+
34
+ ```ts
35
+ function useJoin() {
36
+ return {
37
+ error,
38
+ isSubmitting,
39
+ onJoin: handleJoin,
40
+ };
41
+ }
42
+ ```
43
+
44
+ ### Correct
45
+
46
+ ```ts
47
+ function useBranch() {
48
+ const coursesCurrentPage = coursePage;
49
+ const coursesTotalPages = Math.ceil(sortedLearning.length / COURSES_PER_PAGE) || 1;
50
+ const membersHref = `/branch/${branchNumber}/members`;
51
+ const newsCurrentPage = newsData?.currentPage ?? 1;
52
+ const newsTotalPages = newsData?.pages ?? 1;
53
+
54
+ return {
55
+ admins,
56
+ branch,
57
+ coursesCurrentPage,
58
+ coursesTotalPages,
59
+ members,
60
+ membersHref,
61
+ news,
62
+ newsCurrentPage,
63
+ newsTotalPages,
64
+ stats,
65
+ };
66
+ }
67
+ ```
68
+
69
+ ```ts
70
+ function useJoin() {
71
+ const onJoin = handleJoin;
72
+
73
+ return {
74
+ error,
75
+ isSubmitting,
76
+ onJoin,
77
+ };
78
+ }
79
+ ```
80
+
81
+ ## When Not To Use It
82
+
83
+ If your project prefers inline property values in return statements for brevity.