eslint-plugin-nextfriday 4.4.0 → 5.0.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,33 @@
1
1
  # eslint-plugin-nextfriday
2
2
 
3
+ ## 5.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - [#136](https://github.com/next-friday/eslint-plugin-nextfriday/pull/136) [`d5dd064`](https://github.com/next-friday/eslint-plugin-nextfriday/commit/d5dd064c4de84ef90cc67cbb914e31288b13afab) Thanks [@joetakara](https://github.com/joetakara)! - fix `index-export-only` to allow string directive prologues (e.g. `"use strict"`) in index files — previously flagged as disallowed expression statements
8
+
9
+ fix `sort-imports` group ordering — `import type` now belongs to the same group as its source (external type after external value, internal alias type after internal alias value, etc.) and relative imports are split into parent (`../`) and current (`./`) sub-groups
10
+
11
+ fix `sort-imports` `checkOrder` return type — early-return now yields `false` instead of `undefined`, satisfying the declared `boolean` return type
12
+
13
+ remove `no-inline-default-export` rule — the rule conflicts with framework route handler patterns that require inline named function exports (`export async function GET`)
14
+
15
+ remove `no-nested-ternary` rule — duplicates ESLint's built-in `no-nested-ternary` with identical behavior; use the built-in rule directly instead
16
+
17
+ remove `enforce-property-case` rule — duplicates ESLint's built-in `camelcase` with `{ properties: "always" }`; use the built-in rule directly instead
18
+
19
+ remove `no-single-char-variables` rule — duplicates ESLint's built-in `id-length` with `{ min: 2, exceptions: ["_", "i", "j", "k", "n"] }`; use the built-in rule directly instead
20
+
21
+ remove `prefer-function-declaration` rule — duplicates ESLint's built-in `func-style` with `["declaration", { allowArrowFunctions: false }]`; use the built-in rule directly instead
22
+
23
+ remove `enforce-camel-case` rule — duplicates ESLint's built-in `camelcase`; use the built-in rule directly instead
24
+
25
+ remove `prefer-jsx-template-literals` rule — duplicates ESLint's built-in `prefer-template` with broader coverage; use the built-in rule directly instead
26
+
27
+ remove `no-redundant-fragment` rule — duplicates `eslint-plugin-react`'s `react/jsx-no-useless-fragment` with identical behavior; use the plugin rule directly instead
28
+
29
+ remove `react-props-destructure` rule — duplicates `eslint-plugin-react`'s `react/destructuring-assignment` with `["error", "always"]`; use the plugin rule directly instead
30
+
3
31
  ## 4.4.0
4
32
 
5
33
  ### Minor Changes
package/README.md CHANGED
@@ -50,7 +50,7 @@ export default [nextfriday.configs["nextjs/recommended"]];
50
50
 
51
51
  To use a preset and adjust individual rules, append a second config object after the preset. Later objects override earlier ones, so you can change severity, swap options, or add rules without re-declaring the entire preset.
52
52
 
53
- For example, start with the `react/recommended` preset (which runs `nextfriday/enforce-camel-case` and `nextfriday/enforce-props-suffix` as errors) and add a rule override on top:
53
+ For example, start with the `react/recommended` preset (which runs `nextfriday/enforce-constant-case` and `nextfriday/enforce-props-suffix` as errors) and add a rule override on top:
54
54
 
55
55
  ```js
56
56
  import nextfriday from "eslint-plugin-nextfriday";
@@ -99,18 +99,14 @@ export default [
99
99
  },
100
100
  rules: {
101
101
  // Variable Naming
102
- "nextfriday/no-single-char-variables": "error",
103
102
  "nextfriday/no-lazy-identifiers": "error",
104
103
  "nextfriday/boolean-naming-prefix": "error",
105
- "nextfriday/enforce-camel-case": "error",
106
104
  "nextfriday/enforce-constant-case": "error",
107
- "nextfriday/enforce-property-case": "error",
108
105
  "nextfriday/no-misleading-constant-case": "error",
109
106
 
110
107
  // Code Style
111
108
  "nextfriday/no-emoji": "error",
112
109
  "nextfriday/prefer-destructuring-params": "error",
113
- "nextfriday/prefer-function-declaration": "error",
114
110
  "nextfriday/require-explicit-return-type": "error",
115
111
  "nextfriday/no-complex-inline-return": "error",
116
112
  "nextfriday/no-logic-in-params": "error",
@@ -125,7 +121,6 @@ export default [
125
121
  "nextfriday/no-inline-nested-object": "error",
126
122
  "nextfriday/no-inline-return-properties": "error",
127
123
  "nextfriday/prefer-async-await": "error",
128
- "nextfriday/no-nested-ternary": "error",
129
124
  "nextfriday/prefer-guard-clause": "error",
130
125
 
131
126
  // Import Optimization
@@ -156,8 +151,6 @@ export default [
156
151
  "nextfriday/jsx-simple-props": "error",
157
152
  "nextfriday/jsx-sort-props": "error",
158
153
  "nextfriday/jsx-spread-props-last": "error",
159
- "nextfriday/prefer-jsx-template-literals": "error",
160
- "nextfriday/react-props-destructure": "error",
161
154
  "nextfriday/enforce-props-suffix": "error",
162
155
  "nextfriday/enforce-readonly-component-props": "error",
163
156
  },
@@ -208,7 +201,6 @@ export default [
208
201
  files: ["**/*.{test,spec}.{ts,tsx}"],
209
202
  rules: {
210
203
  "nextfriday/require-explicit-return-type": "off",
211
- "nextfriday/no-single-char-variables": "off",
212
204
  "nextfriday/no-direct-date": "off",
213
205
  },
214
206
  },
@@ -335,7 +327,6 @@ export default [
335
327
  files: ["src/legacy/**/*.{ts,tsx}"],
336
328
  rules: {
337
329
  "nextfriday/no-relative-imports": "off",
338
- "nextfriday/enforce-camel-case": "off",
339
330
  },
340
331
  },
341
332
  ];
@@ -382,7 +373,7 @@ When the warn-level preset surfaces hundreds of violations, fix them in this ord
382
373
  | Tier | Examples | Why first |
383
374
  | ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
384
375
  | High — correctness and runtime safety | `no-direct-date`, `no-env-fallback`, `enforce-readonly-component-props`, `jsx-no-non-component-function`, `enforce-hook-naming`, `no-logic-in-params` | Each violation can mask a bug, leak config, or break React's rules of hooks. Fix before they ship. |
385
- | Medium — structure and naming | `boolean-naming-prefix`, `enforce-camel-case`, `enforce-constant-case`, `enforce-props-suffix`, `prefer-import-type` | No runtime impact, but inconsistent naming compounds review and onboarding cost. Fix once the high tier is clean. |
376
+ | Medium — structure and naming | `boolean-naming-prefix`, `enforce-constant-case`, `enforce-props-suffix`, `prefer-import-type` | No runtime impact, but inconsistent naming compounds review and onboarding cost. Fix once the high tier is clean. |
386
377
  | Low — formatting and ordering | `sort-imports`, `sort-exports`, `sort-type-alphabetically`, `jsx-sort-props`, `newline-before-return`, `newline-after-multiline-block`, `no-emoji` | Cosmetic. Most are auto-fixable, so a single `pnpm eslint --fix` pass typically clears the whole codebase. Save these for last. |
387
378
 
388
379
  In practice: turn the high tier on as `"error"` first, leave the medium tier as `"warn"` while you migrate, and run the auto-fixers for the low tier in a single dedicated PR.
@@ -395,12 +386,9 @@ In practice: turn the high tier on as `"error"` first, leave the medium tier as
395
386
 
396
387
  | Rule | Description | Fixable |
397
388
  | ------------------------------------------------------------------------ | --------------------------------------------------------------------- | ------- |
398
- | [no-single-char-variables](docs/rules/NO_SINGLE_CHAR_VARIABLES.md) | Disallow single character variable names (e.g., `d`, `u`, `l`) | ❌ |
399
389
  | [no-lazy-identifiers](docs/rules/NO_LAZY_IDENTIFIERS.md) | Disallow lazy identifiers like `xxx`, `asdf`, `qwerty` | ❌ |
400
390
  | [boolean-naming-prefix](docs/rules/BOOLEAN_NAMING_PREFIX.md) | Enforce boolean variables to have prefix (is, has, should, can, etc.) | ❌ |
401
- | [enforce-camel-case](docs/rules/ENFORCE_CAMEL_CASE.md) | Ban snake_case and restrict PascalCase to React components | ❌ |
402
391
  | [enforce-constant-case](docs/rules/ENFORCE_CONSTANT_CASE.md) | Enforce SCREAMING_SNAKE_CASE for global static constant values | ❌ |
403
- | [enforce-property-case](docs/rules/ENFORCE_PROPERTY_CASE.md) | Enforce camelCase for unquoted object property keys | ❌ |
404
392
  | [no-misleading-constant-case](docs/rules/NO_MISLEADING_CONSTANT_CASE.md) | Disallow SCREAMING_SNAKE_CASE in local scope and for dynamic values | ❌ |
405
393
 
406
394
  ### Code Style Rules
@@ -409,7 +397,6 @@ In practice: turn the high tier on as `"error"` first, leave the medium tier as
409
397
  | ---------------------------------------------------------------------------- | ---------------------------------------------------------------------- | ------- |
410
398
  | [no-emoji](docs/rules/NO_EMOJI.md) | Disallow emoji characters in source code | ❌ |
411
399
  | [prefer-destructuring-params](docs/rules/PREFER_DESTRUCTURING_PARAMS.md) | Enforce destructuring for functions with multiple parameters | ❌ |
412
- | [prefer-function-declaration](docs/rules/PREFER_FUNCTION_DECLARATION.md) | Enforce function declarations over arrow functions in .ts files | ❌ |
413
400
  | [require-explicit-return-type](docs/rules/REQUIRE_EXPLICIT_RETURN_TYPE.md) | Require explicit return types on functions for better documentation | ❌ |
414
401
  | [no-complex-inline-return](docs/rules/NO_COMPLEX_INLINE_RETURN.md) | Disallow complex inline expressions in return - extract to const first | ❌ |
415
402
  | [no-logic-in-params](docs/rules/NO_LOGIC_IN_PARAMS.md) | Disallow logic/conditions in function parameters - extract to const | ❌ |
@@ -419,7 +406,6 @@ In practice: turn the high tier on as `"error"` first, leave the medium tier as
419
406
  | [enforce-service-naming](docs/rules/ENFORCE_SERVICE_NAMING.md) | Enforce 'fetch' prefix for async functions in \*.service.ts files | ❌ |
420
407
  | [enforce-sorted-destructuring](docs/rules/ENFORCE_SORTED_DESTRUCTURING.md) | Enforce alphabetical sorting of destructured properties | ✅ |
421
408
  | [no-env-fallback](docs/rules/NO_ENV_FALLBACK.md) | Disallow fallback values for environment variables | ❌ |
422
- | [no-inline-default-export](docs/rules/NO_INLINE_DEFAULT_EXPORT.md) | Disallow inline default exports - declare first, then export | ❌ |
423
409
  | [index-export-only](docs/rules/INDEX_EXPORT_ONLY.md) | Restrict index files to imports, re-exports, and type declarations | ❌ |
424
410
  | [no-direct-date](docs/rules/NO_DIRECT_DATE.md) | Disallow direct usage of Date constructor and methods | ❌ |
425
411
  | [newline-after-multiline-block](docs/rules/NEWLINE_AFTER_MULTILINE_BLOCK.md) | Require a blank line after multi-line statements | ✅ |
@@ -427,7 +413,6 @@ In practice: turn the high tier on as `"error"` first, leave the medium tier as
427
413
  | [no-inline-nested-object](docs/rules/NO_INLINE_NESTED_OBJECT.md) | Require nested objects and arrays to span multiple lines | ✅ |
428
414
  | [no-inline-return-properties](docs/rules/NO_INLINE_RETURN_PROPERTIES.md) | Require return object properties to use shorthand notation | ❌ |
429
415
  | [prefer-async-await](docs/rules/PREFER_ASYNC_AWAIT.md) | Enforce async/await over .then() promise chains | ❌ |
430
- | [no-nested-ternary](docs/rules/NO_NESTED_TERNARY.md) | Disallow nested ternary expressions | ❌ |
431
416
  | [prefer-guard-clause](docs/rules/PREFER_GUARD_CLAUSE.md) | Enforce guard clause pattern instead of nested if statements | ❌ |
432
417
  | [no-helper-function-in-hook](docs/rules/NO_HELPER_FUNCTION_IN_HOOK.md) | Disallow non-hook helper function definitions in hook files | ❌ |
433
418
  | [no-helper-function-in-test](docs/rules/NO_HELPER_FUNCTION_IN_TEST.md) | Disallow helper function definitions in test files | ❌ |
@@ -474,10 +459,7 @@ In practice: turn the high tier on as `"error"` first, leave the medium tier as
474
459
  | [jsx-sort-props](docs/rules/JSX_SORT_PROPS.md) | Enforce JSX props are sorted by value type | ✅ |
475
460
  | [jsx-spread-props-last](docs/rules/JSX_SPREAD_PROPS_LAST.md) | Enforce JSX spread attributes appear after all other props | ❌ |
476
461
  | [no-ghost-wrapper](docs/rules/NO_GHOST_WRAPPER.md) | Disallow bare `<div>`/`<span>` with no meaningful attributes | ❌ |
477
- | [no-redundant-fragment](docs/rules/NO_REDUNDANT_FRAGMENT.md) | Disallow Fragments wrapping zero or one child | ❌ |
478
- | [prefer-jsx-template-literals](docs/rules/PREFER_JSX_TEMPLATE_LITERALS.md) | Enforce template literals instead of mixing text and JSX expressions | ✅ |
479
462
  | [prefer-props-with-children](docs/rules/PREFER_PROPS_WITH_CHILDREN.md) | Prefer PropsWithChildren over manually declaring children: ReactNode | ❌ |
480
- | [react-props-destructure](docs/rules/REACT_PROPS_DESTRUCTURE.md) | Enforce destructuring props inside React component body | ❌ |
481
463
  | [enforce-props-suffix](docs/rules/ENFORCE_PROPS_SUFFIX.md) | Enforce 'Props' suffix for interfaces and types in \*.tsx files | ❌ |
482
464
  | [enforce-readonly-component-props](docs/rules/ENFORCE_READONLY_COMPONENT_PROPS.md) | Enforce Readonly wrapper for React component props | ✅ |
483
465
  | [enforce-render-naming](docs/rules/ENFORCE_RENDER_NAMING.md) | Enforce 'render' prefix for variables holding JSX inside components | ❌ |
@@ -502,12 +484,10 @@ The `nextjs` and `nextjs/recommended` presets currently share the same rule set
502
484
  Included in `base`, `base/recommended`, and all other presets:
503
485
 
504
486
  - `nextfriday/boolean-naming-prefix`
505
- - `nextfriday/enforce-camel-case`
506
487
  - `nextfriday/enforce-constant-case`
507
488
  - `nextfriday/enforce-hook-filename`
508
489
  - `nextfriday/enforce-hook-naming`
509
490
  - `nextfriday/enforce-test-filename`
510
- - `nextfriday/enforce-property-case`
511
491
  - `nextfriday/enforce-service-naming`
512
492
  - `nextfriday/enforce-sorted-destructuring`
513
493
  - `nextfriday/enforce-type-declaration-order`
@@ -518,7 +498,6 @@ Included in `base`, `base/recommended`, and all other presets:
518
498
  - `nextfriday/no-direct-date`
519
499
  - `nextfriday/no-emoji`
520
500
  - `nextfriday/no-env-fallback`
521
- - `nextfriday/no-inline-default-export`
522
501
  - `nextfriday/no-inline-nested-object`
523
502
  - `nextfriday/no-inline-return-properties`
524
503
  - `nextfriday/no-inline-type-import`
@@ -526,12 +505,9 @@ Included in `base`, `base/recommended`, and all other presets:
526
505
  - `nextfriday/no-logic-in-params`
527
506
  - `nextfriday/no-misleading-constant-case`
528
507
  - `nextfriday/no-nested-interface-declaration`
529
- - `nextfriday/no-nested-ternary`
530
508
  - `nextfriday/no-relative-imports`
531
- - `nextfriday/no-single-char-variables`
532
509
  - `nextfriday/prefer-async-await`
533
510
  - `nextfriday/prefer-destructuring-params`
534
- - `nextfriday/prefer-function-declaration`
535
511
  - `nextfriday/prefer-guard-clause`
536
512
  - `nextfriday/prefer-import-type`
537
513
  - `nextfriday/prefer-inline-literal-union`
@@ -564,12 +540,9 @@ Additionally included in `react`, `react/recommended`, `nextjs`, `nextjs/recomme
564
540
  - `nextfriday/jsx-sort-props`
565
541
  - `nextfriday/jsx-spread-props-last`
566
542
  - `nextfriday/no-ghost-wrapper`
567
- - `nextfriday/no-redundant-fragment`
568
543
  - `nextfriday/prefer-interface-for-component-props`
569
544
  - `nextfriday/prefer-interface-over-inline-types`
570
- - `nextfriday/prefer-jsx-template-literals`
571
545
  - `nextfriday/prefer-props-with-children`
572
- - `nextfriday/react-props-destructure`
573
546
 
574
547
  ### Severity Levels
575
548
 
@@ -101,5 +101,4 @@ If you need stricter coverage of object/class members, pair this rule with [`@ty
101
101
 
102
102
  ## Related Rules
103
103
 
104
- - [no-single-char-variables](./NO_SINGLE_CHAR_VARIABLES.md) - Disallows single character variable names
105
104
  - [@typescript-eslint/naming-convention](https://typescript-eslint.io/rules/naming-convention/) - More comprehensive naming convention rule
@@ -109,7 +109,6 @@ export default [
109
109
  rules: {
110
110
  "nextfriday/enforce-constant-case": "error",
111
111
  "nextfriday/no-misleading-constant-case": "error",
112
- "nextfriday/enforce-camel-case": "error",
113
112
  },
114
113
  },
115
114
  ];
@@ -166,4 +165,3 @@ This plugin only supports ESLint 9+ flat config — legacy `.eslintrc` is not su
166
165
  ## Related Rules
167
166
 
168
167
  - [no-misleading-constant-case](NO_MISLEADING_CONSTANT_CASE.md) - Disallows SCREAMING_SNAKE_CASE in local scope and for dynamic values
169
- - [enforce-camel-case](ENFORCE_CAMEL_CASE.md) - Enforces camelCase for variables and functions
@@ -92,4 +92,3 @@ This rule is fixable using ESLint's `--fix` option. The fixer will automatically
92
92
  ## Related Rules
93
93
 
94
94
  - [`prefer-interface-over-inline-types`](./PREFER_INTERFACE_OVER_INLINE_TYPES.md) - Enforces interface declarations over inline types
95
- - [`react-props-destructure`](./REACT_PROPS_DESTRUCTURE.md) - Enforces destructuring props inside component body
@@ -43,6 +43,12 @@ console.log("loaded");
43
43
 
44
44
  ### Correct
45
45
 
46
+ ```ts
47
+ "use strict";
48
+
49
+ export { cn } from "./cn";
50
+ ```
51
+
46
52
  ```ts
47
53
  export { cn } from "./cn";
48
54
  export * from "./types";
@@ -66,6 +72,7 @@ export interface Bar {
66
72
  ## What This Rule Allows
67
73
 
68
74
  - `import` statements (including side-effect imports like `import "./styles.css"`)
75
+ - String directive prologues (e.g. `"use strict"`)
69
76
  - Specifier-only `export` and `export ... from` re-exports
70
77
  - `export *` and `export * as ns` re-exports
71
78
  - `export default identifier` where the identifier comes from an import
@@ -69,7 +69,3 @@ Any of the following attributes count as meaningful and silence the rule:
69
69
  ## When Not To Use It
70
70
 
71
71
  If your codebase intentionally uses bare `<div>` and `<span>` as structural placeholders, or if you rely on parent CSS selectors that target a fixed wrapper depth.
72
-
73
- ## Related Rules
74
-
75
- - [no-redundant-fragment](NO_REDUNDANT_FRAGMENT.md)
@@ -78,7 +78,7 @@ Variables containing 4 or more consecutive keyboard row characters:
78
78
 
79
79
  ### Short Identifiers
80
80
 
81
- Identifiers shorter than 3 characters are ignored (use `no-single-char-variables` for those).
81
+ Identifiers shorter than 3 characters are ignored (use the core ESLint `id-length` rule with `min: 2` for those).
82
82
 
83
83
  ### Underscore-Prefixed
84
84
 
@@ -95,5 +95,4 @@ const _unused = getValue();
95
95
 
96
96
  ## Related Rules
97
97
 
98
- - [no-single-char-variables](./NO_SINGLE_CHAR_VARIABLES.md) - Disallows single character variable names
99
98
  - [boolean-naming-prefix](./BOOLEAN_NAMING_PREFIX.md) - Enforces naming conventions for boolean variables
@@ -73,4 +73,3 @@ If your project does not follow the convention that SCREAMING_SNAKE_CASE is rese
73
73
  ## Related Rules
74
74
 
75
75
  - [enforce-constant-case](ENFORCE_CONSTANT_CASE.md) - The complementary rule that enforces SCREAMING_SNAKE_CASE for global static constants
76
- - [enforce-camel-case](ENFORCE_CAMEL_CASE.md) - Enforces camelCase for variables and functions
@@ -17,12 +17,13 @@ This rule enforces that import statements are grouped and ordered by their sourc
17
17
  ### Import Group Order
18
18
 
19
19
  1. **Side-effect imports** — no specifiers (e.g., `import "./setup"`)
20
- 2. **Node.js builtins** `node:` prefix or known builtin names (e.g., `import fs from "node:fs"`)
21
- 3. **External packages** scoped or plain package names (e.g., `import React from "react"`)
22
- 4. **Internal aliases** — paths starting with `@/`, `~/`, or `#` (e.g., `import { utils } from "@/lib/utils"`)
23
- 5. **Relative imports** — paths starting with `.` (e.g., `import { foo } from "../foo"`)
20
+ 2. **Builtin** value **builtin type**
21
+ 3. **External** value **external type**
22
+ 4. **Internal alias** value → **internal alias type** — paths starting with `@/`, `~/`, or `#`
23
+ 5. **Parent relative** value → **parent relative type** — paths starting with `../` (any depth)
24
+ 6. **Relative** value → **relative type** — paths starting with `./`
24
25
 
25
- Type-only imports (`import type`) are skipped and do not affect ordering.
26
+ Within each group, value imports come first, then `import type` for the same group.
26
27
 
27
28
  Non-contiguous imports (separated by other statements) are checked independently.
28
29
 
@@ -31,7 +32,13 @@ Non-contiguous imports (separated by other statements) are checked independently
31
32
  ### Incorrect
32
33
 
33
34
  ```ts
34
- // Bad: Relative before external
35
+ // Bad: type import before value import in same group
36
+ import type { Foo } from "some-lib";
37
+ import { bar } from "some-lib";
38
+ ```
39
+
40
+ ```ts
41
+ // Bad: relative before external
35
42
  import { foo } from "../foo";
36
43
  import React from "react";
37
44
  ```
@@ -51,19 +58,22 @@ import "./setup";
51
58
  ### Correct
52
59
 
53
60
  ```ts
54
- // Good: All 5 groups in correct order
55
61
  import "./setup";
62
+
56
63
  import fs from "node:fs";
64
+
57
65
  import React from "react";
66
+ import type { FC } from "react";
67
+
58
68
  import { utils } from "@/lib/utils";
59
- import { foo } from "../foo";
60
- ```
69
+ import type { Utils } from "@/lib/utils";
61
70
 
62
- ```ts
63
- // Good: Type imports can appear anywhere
64
- import type { FC } from "react";
65
- import { foo } from "../foo";
66
- import React from "react";
71
+ import { foo } from "../../foo";
72
+ import { bar } from "../bar";
73
+ import type { Bar } from "../bar";
74
+
75
+ import { baz } from "./baz";
76
+ import type { Baz } from "./baz";
67
77
  ```
68
78
 
69
79
  ```ts