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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-nextfriday",
3
- "version": "4.4.0",
3
+ "version": "5.0.0",
4
4
  "description": "A comprehensive ESLint plugin providing custom rules and configurations for Next Friday development workflows.",
5
5
  "keywords": [
6
6
  "eslint",
@@ -1,68 +0,0 @@
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,63 +0,0 @@
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,97 +0,0 @@
1
- # no-inline-default-export
2
-
3
- Disallow inline exports. Declare first, then export separately.
4
-
5
- ## Rule Details
6
-
7
- This rule enforces separating declarations from exports. Instead of `export function`, declare the function first, then export it.
8
-
9
- ## Examples
10
-
11
- ### Incorrect
12
-
13
- ```ts
14
- // Inline named export
15
- export function fetchData() {
16
- return fetch("/api");
17
- }
18
-
19
- // Inline async named export
20
- export async function fetchHighlight(id: string) {
21
- return await api.get(`/highlights/${id}`);
22
- }
23
-
24
- // Inline class export
25
- export class UserService {
26
- // ...
27
- }
28
-
29
- // Inline default export
30
- export default function generator() {
31
- // ...
32
- }
33
-
34
- // Inline default class export
35
- export default class MyService {
36
- // ...
37
- }
38
-
39
- // Anonymous exports
40
- export default function () {
41
- return "anonymous";
42
- }
43
-
44
- export default () => "arrow";
45
- ```
46
-
47
- ### Correct
48
-
49
- ```ts
50
- // Declare function, then export
51
- function fetchData() {
52
- return fetch("/api");
53
- }
54
-
55
- export { fetchData };
56
-
57
- // Declare async function, then export
58
- async function fetchHighlight(id: string) {
59
- return await api.get(`/highlights/${id}`);
60
- }
61
-
62
- export { fetchHighlight };
63
-
64
- // Or use default export
65
- export default fetchHighlight;
66
-
67
- // Declare class, then export
68
- class UserService {
69
- // ...
70
- }
71
-
72
- export { UserService };
73
-
74
- // Declare function, then default export
75
- function generator() {
76
- // ...
77
- }
78
-
79
- export default generator;
80
-
81
- // Re-exports are allowed
82
- export { foo } from "./foo";
83
- export { bar as default } from "./bar";
84
- export type { Baz } from "./baz";
85
-
86
- // Literals and objects are allowed
87
- export default "literal";
88
- export default { key: "value" };
89
- ```
90
-
91
- ## When Not To Use It
92
-
93
- If your project prefers inline exports for brevity, you may want to disable this rule.
94
-
95
- ## Related Rules
96
-
97
- - [prefer-function-declaration](./PREFER_FUNCTION_DECLARATION.md) - Prefer function declarations over arrow functions
@@ -1,45 +0,0 @@
1
- # no-nested-ternary
2
-
3
- Disallow nested ternary expressions.
4
-
5
- ## Rule Details
6
-
7
- Nested ternary expressions are difficult to read and understand. This rule enforces using functions with early returns instead.
8
-
9
- ## Examples
10
-
11
- ### Incorrect
12
-
13
- ```ts
14
- const status = isLoading ? "loading" : isError ? "error" : "success";
15
-
16
- const value = a ? (b ? 1 : 2) : 3;
17
-
18
- const result = condition1 ? value1 : condition2 ? value2 : condition3 ? value3 : defaultValue;
19
- ```
20
-
21
- ### Correct
22
-
23
- ```ts
24
- // Simple ternary (no nesting)
25
- const status = isLoading ? "loading" : "success";
26
-
27
- // Function with early returns
28
- const getStatus = () => {
29
- if (isLoading) return "loading";
30
- if (isError) return "error";
31
- return "success";
32
- };
33
-
34
- // IIFE for inline usage
35
- const status = (() => {
36
- if (isLoading) return "loading";
37
- if (isError) return "error";
38
- return "success";
39
- })();
40
- ```
41
-
42
- ## When Not To Use It
43
-
44
- - If your team prefers nested ternaries for simple cases
45
- - If you have existing code with many nested ternaries and don't want to refactor
@@ -1,56 +0,0 @@
1
- # no-redundant-fragment
2
-
3
- Disallow Fragments that wrap zero or one child.
4
-
5
- ## Rule Details
6
-
7
- This rule flags Fragments (`<>...</>`, `<Fragment>...</Fragment>`, `<React.Fragment>...</React.Fragment>`) that wrap zero or one child. A Fragment is only justified when grouping multiple sibling nodes, or when a `key` prop is required during list iteration.
8
-
9
- A Fragment with a single child is structurally equivalent to that child alone. An empty Fragment renders nothing and adds noise to the source.
10
-
11
- ### Why?
12
-
13
- - **Source clarity**: A Fragment around a single child is dead syntax — it tells the reader nothing.
14
- - **Less noise in the AST**: Devtools, search, and codemods do not have to step over an extra layer.
15
- - **Forces a decision**: Either the children are siblings (Fragment is the right tool) or they are not (drop it).
16
-
17
- ## Examples
18
-
19
- ### Incorrect
20
-
21
- ```tsx
22
- <></>
23
- <>{x}</>
24
- <><A /></>
25
- <>text</>
26
- <Fragment>x</Fragment>
27
- <React.Fragment>{x}</React.Fragment>
28
- <React.Fragment></React.Fragment>
29
- ```
30
-
31
- ### Correct
32
-
33
- ```tsx
34
- <>{a}{b}</>
35
- <><A /><B /></>
36
- <Fragment>{a}{b}</Fragment>
37
- <React.Fragment>{a}{b}</React.Fragment>
38
-
39
- // key is the legitimate reason to use long-form Fragment:
40
- <React.Fragment key={item.id}>{item.label}{item.value}</React.Fragment>
41
- <Fragment key={k}>{x}</Fragment>
42
- ```
43
-
44
- ## What This Rule Checks
45
-
46
- A Fragment is flagged when its meaningful children count is `0` or `1`. JSX text nodes that contain only whitespace are not counted as children.
47
-
48
- The rule does not fire on a long-form Fragment (`<Fragment>` or `<React.Fragment>`) that carries a `key` attribute — `key` is the canonical reason long-form Fragment exists, since the shorthand `<>...</>` cannot accept attributes.
49
-
50
- ## When Not To Use It
51
-
52
- If your codebase uses single-child Fragments to keep diffs stable around conditionally-rendered siblings, or if you rely on a build-time transform that depends on the Fragment wrapper.
53
-
54
- ## Related Rules
55
-
56
- - [no-ghost-wrapper](NO_GHOST_WRAPPER.md)
@@ -1,98 +0,0 @@
1
- # no-single-char-variables
2
-
3
- Disallow single character variable and parameter names for better code readability.
4
-
5
- ## Rule Details
6
-
7
- This rule enforces descriptive variable and parameter names by disallowing single character identifiers. Single character names like `d`, `u`, `l`, `r` are cryptic and make code harder to understand. They require readers to guess or track what each variable represents.
8
-
9
- ## Examples
10
-
11
- ### Incorrect
12
-
13
- ```ts
14
- const d = new Date();
15
- const u = await getUser();
16
- const l = list.length;
17
- const r = await fetch(url);
18
-
19
- users.map((u) => u.id);
20
- onClick((e) => e.preventDefault());
21
-
22
- const add = (a, b) => a + b;
23
- const e = (x) => x * 2;
24
-
25
- function f() {
26
- return 1;
27
- }
28
-
29
- const { a } = obj;
30
- const [x] = array;
31
-
32
- try {
33
- } catch (e) {}
34
- ```
35
-
36
- ### Correct
37
-
38
- ```ts
39
- const currentDate = new Date();
40
- const currentUser = await getUser();
41
- const itemCount = list.length;
42
- const response = await fetch(url);
43
-
44
- users.map((user) => user.id);
45
- onClick((event) => event.preventDefault());
46
-
47
- const add = (val1, val2) => val1 + val2;
48
- const add = (width, height) => width * height;
49
- const calculateDouble = (value) => value * 2;
50
-
51
- function getName() {
52
- return "test";
53
- }
54
-
55
- const { alpha } = obj;
56
- const { a: alpha } = obj;
57
- const [first] = array;
58
-
59
- try {
60
- } catch (error) {}
61
- ```
62
-
63
- ## Exceptions
64
-
65
- The rule allows the following exceptions:
66
-
67
- ### Loop Counters
68
-
69
- Single character loop counters `i`, `j`, `k`, `n` are allowed in traditional for loops:
70
-
71
- ```ts
72
- for (let i = 0; i < 10; i++) {}
73
- for (let j = 0; j < items.length; j++) {}
74
- for (let i = 0, j = 10; i < j; i++, j--) {}
75
- ```
76
-
77
- Note: These are only allowed in traditional `for` loops, not in `for...of` or `for...in` loops.
78
-
79
- ### Underscore for Unused Variables
80
-
81
- A single underscore `_` is allowed to indicate intentionally unused variables:
82
-
83
- ```ts
84
- const _ = unusedValue;
85
- const [_, second] = array;
86
- array.map((_, index) => index);
87
- ```
88
-
89
- ## When Not To Use It
90
-
91
- - For very short scripts or throwaway code
92
- - When working with mathematical formulas where single letters are conventional (e.g., `x`, `y` for coordinates)
93
- - In legacy codebases where this pattern is established and changing would be disruptive
94
-
95
- ## Related Rules
96
-
97
- - [prefer-destructuring-params](./PREFER_DESTRUCTURING_PARAMS.md) - Encourages destructuring for function parameters
98
- - [prefer-named-param-types](./PREFER_NAMED_PARAM_TYPES.md) - Encourages named parameters for better readability
@@ -1,118 +0,0 @@
1
- # prefer-function-declaration
2
-
3
- Enforce function declarations over arrow functions assigned to variables in `.ts` files.
4
-
5
- ## Rule Details
6
-
7
- This rule requires using function declarations instead of arrow functions or function expressions when defining named functions. Arrow functions used as callbacks are still allowed.
8
-
9
- **Target:** `.ts` files only (not `.tsx`, `.js`, or `.d.ts`)
10
-
11
- ## Examples
12
-
13
- ### Incorrect
14
-
15
- ```ts
16
- // Arrow function assigned to variable
17
- const formatDate = (date: Date) => {
18
- return date.toLocaleDateString("th-TH");
19
- };
20
-
21
- // Arrow function with implicit return
22
- const add = (a: number, b: number) => a + b;
23
-
24
- // Function expression assigned to variable
25
- const greet = function (name: string) {
26
- return `Hello ${name}`;
27
- };
28
-
29
- // Async arrow function
30
- const fetchUser = async (id: string) => {
31
- return await api.get(`/users/${id}`);
32
- };
33
- ```
34
-
35
- ### Correct
36
-
37
- ```ts
38
- // Function declaration
39
- function formatDate(date: Date) {
40
- return date.toLocaleDateString("th-TH");
41
- }
42
-
43
- // Function declaration
44
- function add(a: number, b: number) {
45
- return a + b;
46
- }
47
-
48
- // Function declaration
49
- function greet(name: string) {
50
- return `Hello ${name}`;
51
- }
52
-
53
- // Async function declaration
54
- async function fetchUser(id: string) {
55
- return await api.get(`/users/${id}`);
56
- }
57
- ```
58
-
59
- ## What This Rule Allows
60
-
61
- Arrow functions are still allowed in the following contexts:
62
-
63
- ### Callbacks
64
-
65
- ```ts
66
- const years = dates.map((date) => date.getFullYear());
67
- const active = items.filter((item) => item.active);
68
- const sorted = items.sort((a, b) => a.name.localeCompare(b.name));
69
- items.forEach((item) => console.log(item));
70
- setTimeout(() => console.log("done"), 1000);
71
- ```
72
-
73
- ### Object Properties
74
-
75
- ```ts
76
- const handler = {
77
- onClick: () => console.log("clicked"),
78
- onHover: () => setHovered(true),
79
- };
80
- ```
81
-
82
- ### Array Elements
83
-
84
- ```ts
85
- const callbacks = [() => 1, () => 2, () => 3];
86
- ```
87
-
88
- ### Return Values
89
-
90
- ```ts
91
- function createHandler() {
92
- return () => console.log("handled");
93
- }
94
- ```
95
-
96
- ### Conditional/Logical Expressions
97
-
98
- ```ts
99
- const fn = condition ? () => valueA : () => valueB;
100
- const handler = defaultFn || (() => fallback);
101
- ```
102
-
103
- ### TSX Files
104
-
105
- ```ts
106
- // components/Button.tsx - Arrow functions allowed
107
- const Button = () => <button>Click me</button>;
108
- ```
109
-
110
- ## When Not To Use It
111
-
112
- - When you prefer arrow functions for all function definitions
113
- - In projects where arrow function style is established
114
- - When you need lexical `this` binding
115
-
116
- ## Related Rules
117
-
118
- - [no-inline-default-export](./NO_INLINE_DEFAULT_EXPORT.md) - Disallow inline exports
@@ -1,80 +0,0 @@
1
- # prefer-jsx-template-literals
2
-
3
- Enforce using template literals instead of mixing text and JSX expressions.
4
-
5
- > This rule is auto-fixable using `--fix`.
6
-
7
- ## Rule Details
8
-
9
- This rule prevents mixing plain text with JSX expressions in JSX elements, which can lead to incorrect spacing and readability issues. Instead, it enforces using template literals to combine text and expressions.
10
-
11
- ### Why?
12
-
13
- Mixing text and JSX expressions without proper spacing can cause:
14
-
15
- 1. **Spacing issues**: `<div>+ {value}</div>` renders as "+ value" with unexpected spacing
16
- 2. **Inconsistent formatting**: Hard to maintain consistent spacing across the codebase
17
- 3. **Readability problems**: Mixed syntax makes code harder to read and understand
18
-
19
- Using template literals ensures:
20
-
21
- - Explicit control over spacing
22
- - Consistent formatting
23
- - Better readability
24
- - Easier to maintain
25
-
26
- ## Examples
27
-
28
- ### Incorrect
29
-
30
- ```tsx
31
- // Bad: Text followed by expression
32
- <div>+ {fooVariable}</div>
33
- <div>+{fooVariable}</div>
34
- <div>Price: {price}</div>
35
- <div>$ {amount}</div>
36
- <span>Total: {total}</span>
37
- <p>Hello {name}</p>
38
-
39
- // Bad: Expression followed by text
40
- <div>{count} items</div>
41
- <div>{price}$</div>
42
- ```
43
-
44
- ### Correct
45
-
46
- ```tsx
47
- // Good: Using template literals
48
- <div>{`+${fooVariable}`}</div>
49
- <div>{`+ ${fooVariable}`}</div>
50
- <div>{`Price: ${price}`}</div>
51
- <div>{`$ ${amount}`}</div>
52
- <span>{`Total: ${total}`}</span>
53
- <p>{`Hello ${name}`}</p>
54
-
55
- // Good: Using template literals for expression + text
56
- <div>{`${count}items`}</div>
57
- <div>{`${price}$`}</div>
58
-
59
- // Good: Expression only
60
- <div>{fooVariable}</div>
61
- <div>{price}</div>
62
-
63
- // Good: Text only
64
- <div>Some static text</div>
65
-
66
- // Good: Expression with whitespace only around it
67
- <div> {fooVariable} </div>
68
- <div>
69
- {fooVariable}
70
- </div>
71
- ```
72
-
73
- ## When Not To Use It
74
-
75
- If you prefer mixing text and JSX expressions, you can disable this rule. However, this may lead to inconsistent spacing and formatting issues.
76
-
77
- ## Further Reading
78
-
79
- - [Template Literals (MDN)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals)
80
- - [JSX in React](https://react.dev/learn/writing-markup-with-jsx)