Skip to content

Commit 53e7266

Browse files
Rel1cxCopilotDremorakarlhorky
authored
Merge 2.0.0 into main, closes #335 (#1238)
Signed-off-by: REL1CX <dokimondex@gmail.com> Signed-off-by: Kirill Korolyov <kirill.korolyov@gmail.com> Signed-off-by: REL1CX <rel1cx@proton.me> Signed-off-by: Karl Horky <karl.horky@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Kirill Korolyov <kirill.korolyov@gmail.com> Co-authored-by: Karl Horky <karl.horky@gmail.com>
1 parent 31c3d15 commit 53e7266

File tree

493 files changed

+8980
-11593
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

493 files changed

+8980
-11593
lines changed

.gitignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ coverage/
1818
.eslintcache
1919

2020
# misc
21+
/log
2122
.DS_Store
2223
*.pem
2324

@@ -38,11 +39,9 @@ yarn-error.log*
3839

3940
# vercel
4041
.vercel
41-
4242
stats.html
4343
*.config-*.mjs
4444
/eslint-config.json
4545
*.bundled_*.mjs
4646
*.tgz
4747
eslint-results.sarif
48-
.tsup

.pkgs/configs/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@
2323
"@stylistic/eslint-plugin": "^5.4.0",
2424
"eslint-plugin-de-morgan": "^1.3.1",
2525
"eslint-plugin-function": "^0.0.30",
26-
"eslint-plugin-jsdoc": "^60.0.0",
26+
"eslint-plugin-jsdoc": "^60.3.1",
2727
"eslint-plugin-perfectionist": "^4.15.0",
2828
"eslint-plugin-regexp": "^2.10.0",
2929
"eslint-plugin-unicorn": "^61.0.2",
30-
"typescript-eslint": "^8.44.0"
30+
"typescript-eslint": "^8.44.1"
3131
},
3232
"peerDependencies": {
3333
"eslint": "^9.36.0",
34-
"typescript": "^4.9.5 || ^5.4.5"
34+
"typescript": "^5.9.2"
3535
}
3636
}

.pkgs/eslint-plugin-local/package.json

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,12 @@
2828
"@eslint-react/var": "workspace:*",
2929
"@eslint/js": "^9.36.0",
3030
"@stylistic/eslint-plugin": "^5.4.0",
31-
"@typescript-eslint/scope-manager": "^8.44.0",
32-
"@typescript-eslint/type-utils": "^8.44.0",
33-
"@typescript-eslint/types": "^8.44.0",
34-
"@typescript-eslint/utils": "^8.44.0",
31+
"@typescript-eslint/scope-manager": "^8.44.1",
32+
"@typescript-eslint/type-utils": "^8.44.1",
33+
"@typescript-eslint/types": "^8.44.1",
34+
"@typescript-eslint/utils": "^8.44.1",
3535
"eslint-plugin-de-morgan": "^1.3.1",
36-
"eslint-plugin-jsdoc": "^60.0.0",
36+
"eslint-plugin-jsdoc": "^60.3.1",
3737
"eslint-plugin-perfectionist": "^4.15.0",
3838
"eslint-plugin-regexp": "^2.10.0",
3939
"eslint-plugin-unicorn": "^61.0.2",
@@ -44,11 +44,11 @@
4444
"@local/configs": "workspace:*",
4545
"@types/react": "^19.1.13",
4646
"@types/react-dom": "^19.1.9",
47-
"tsdown": "^0.15.3"
47+
"tsdown": "^0.15.4"
4848
},
4949
"peerDependencies": {
5050
"eslint": "^9.36.0",
51-
"typescript": "^4.9.5 || ^5.4.5"
51+
"typescript": "^5.9.2"
5252
},
5353
"engines": {
5454
"node": ">=20.19.0"

CHANGELOG.md

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,118 @@
1+
## v2.0.0 (TBD)
2+
3+
### 💥 Breaking Changes
4+
5+
**Target Environment Updates: Now ESM and ESLint Flat Config Only**
6+
7+
- Drop support for CommonJS (CJS) module format, packages are now distributed only as ECMAScript Modules (ESM)
8+
- Drop support for ESLint legacy config system, packages now support only ESLint Flat Config (`eslint.config.js`)
9+
- Drop support for Node.js 16 and 18, minimum required version is now Node.js 20
10+
- Drop support for ESLint 8, minimum required version is now ESLint 9.3.6
11+
- Drop support for TypeScript 4, minimum required version is now TypeScript 5.9.2
12+
13+
**Removed Rules**
14+
15+
| Rule | Replaced by | Reason |
16+
| :--------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | :----------- |
17+
| react-x/avoid-shorthand-boolean | [`react-x/jsx-shorthand-boolean`](/docs/rules/jsx-shorthand-boolean) | consolidated |
18+
| react-x/avoid-shorthand-fragment | [`react-x/jsx-shorthand-fragment`](/docs/rules/jsx-shorthand-fragment) | consolidated |
19+
| react-x/ensure-forward-ref-using-ref | [`react-x/no-useless-forward-ref`](/docs/rules/no-useless-forward-ref) | renamed |
20+
| react-x/jsx-no-duplicate-props | [`react-x/jsx-no-duplicate-props`](/docs/rules/jsx-no-duplicate-props) | renamed |
21+
| react-x/no-comment-textnodes | [`react-x/jsx-no-comment-textnodes`](/docs/rules/jsx-no-comment-textnodes) | renamed |
22+
| react-x/no-complicated-conditional-rendering | | discontinued |
23+
| react-x/no-nested-components | [`react-x/no-nested-component-definitions`](/docs/rules/no-nested-component-definitions) | renamed |
24+
| react-x/prefer-react-namespace-import | [`react-x/prefer-namespace-import`](/docs/rules/prefer-namespace-import) | renamed |
25+
| react-x/prefer-shorthand-boolean | [`react-x/jsx-shorthand-boolean`](/docs/rules/jsx-shorthand-boolean) | consolidated |
26+
| react-x/prefer-shorthand-fragment | [`react-x/jsx-shorthand-fragment`](/docs/rules/jsx-shorthand-fragment) | consolidated |
27+
| react-x/use-jsx-vars | [`react-x/jsx-uses-vars`](/docs/rules/jsx-uses-vars) | renamed |
28+
| react-dom/no-children-in-void-dom-elements | [`react-dom/no-void-elements-with-children`](/docs/rules/dom-no-void-elements-with-children) | renamed |
29+
| react-hooks-extra/no-direct-set-state-in-use-layout-effect | [`react-hooks-extra/no-direct-set-state-in-use-effect`](/docs/rules/hooks-extra-no-direct-set-state-in-use-effect) | consolidated |
30+
| react-hooks-extra/no-unnecessary-use-callback | [`react-x/no-unnecessary-use-callback`](/docs/rules/no-unnecessary-use-callback) | relocated |
31+
| react-hooks-extra/no-unnecessary-use-memo | [`react-x/no-unnecessary-use-memo`](/docs/rules/no-unnecessary-use-memo) | relocated |
32+
| react-hooks-extra/no-unnecessary-use-prefix | [`react-x/no-unnecessary-use-prefix`](/docs/rules/no-unnecessary-use-prefix) | relocated |
33+
| react-hooks-extra/prefer-use-state-lazy-initialization | [`react-x/prefer-use-state-lazy-initialization`](/docs/rules/prefer-use-state-lazy-initialization) | relocated |
34+
35+
**Removed Presets**
36+
37+
| Preset | Replaced by | Reason |
38+
| :-------------------------------- | :------------ | :----------- |
39+
| `core` | `x` | renamed |
40+
| `core-legacy` | | discontinued |
41+
| `off-dom` | `disable-dom` | renamed |
42+
| `off-dom-legacy` | | discontinued |
43+
| `x-legacy` | | discontinued |
44+
| `dom-legacy` | | discontinued |
45+
| `web-api-legacy` | | discontinued |
46+
| `recommended-legacy` | | discontinued |
47+
| `recommended-typescript-legacy` | | discontinued |
48+
| `recommended-type-checked-legacy` | | discontinued |
49+
50+
**Removed Settings**
51+
52+
| Setting | Replaced by | Reason |
53+
| :--------------------- | :---------- | :----------- |
54+
| `additionalComponents` | | discontinued |
55+
| `additionalHooks` | | discontinued |
56+
| `skipImportCheck` | | discontinued |
57+
58+
The rule implementations have been refactored to improve performance and maintainability.
59+
60+
### ✨ New
61+
62+
**Added the following new rules:**
63+
64+
- `react-x/jsx-shorthand-boolean`: Enforces a consistent style for boolean attributes
65+
- `react-x/jsx-shorthand-fragment`: Enforces a consistent style for React Fragments
66+
- `react-x/no-forbidden-props`: Disallows specific props on components
67+
- `react-x/no-unnecessary-key`: Reports unnecessary `key` props on elements
68+
- `react-x/no-unused-props`: Reports unused props in components
69+
- `react-dom/no-string-style-prop`: Disallows string values for the `style` prop
70+
- `react-dom/prefer-namespace-import`: Enforces using a namespace import for `react-dom`
71+
72+
**Added the following new rule to the `recommended-type-checked` preset:**
73+
74+
- `react-x/no-unused-props`: Reports unused props in components
75+
76+
**The following rules now support Codemod features:**
77+
78+
- `react-x/no-component-did-update`
79+
- `react-x/no-component-will-receive-props`
80+
- `react-x/no-component-will-update`
81+
- `react-x/no-context-provider`
82+
- `react-x/no-forward-ref`
83+
- `react-x/no-string-refs`
84+
85+
**The following rules now support auto-fix:**
86+
87+
- `react-x/prefer-namespace-import`
88+
- `react-dom/prefer-namespace-import`
89+
90+
**The following rules now support suggestion fixes:**
91+
92+
- `react-dom/no-missing-button-type`
93+
- `react-dom/no-missing-iframe-sandbox`
94+
- `react-dom/no-unsafe-target-blank`
95+
96+
**New configuration preset added:**
97+
98+
- `disable-conflict-eslint-plugin-react`: Disable rules in `eslint-plugin-react` that conflict with rules in our plugins
99+
100+
### 🐞 Fixes
101+
102+
- fix(react-x/no-unnecessary-use-prefix): fix false positive of React Hooks defined within the callback function of `vi.mock(...)` in Vitest test files
103+
- fix(react-web-api/no-leaked-event-listener): fix `useEffect` setup function check to handle `React.useEffect()` calls correctly
104+
- fix(react-naming-convention/filename): fix false positive on well-known filenames like `404.tsx`, `_app.tsx`, `[slug].tsx`
105+
106+
### 🪄 Improvements
107+
108+
- refactor: simplify React APIs detection logic
109+
- refactor: cleanup utilities and simplify rule implementations
110+
- docs: add comparison table between `eslint-plugin-react` and `eslint-react` rules
111+
- docs: replace `tseslint.config` with `defineConfig` in all examples
112+
- build: migrate build system from `tsup` to `tsdown` for better performance
113+
114+
**Full Changelog**: https://github.com/Rel1cx/eslint-react/compare/v1.53.1...v2.0.0
115+
1116
## v1.53.1 (2025-09-11)
2117

3118
### 🐞 Fixes

README.md

Lines changed: 43 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,18 @@
2222
- [TypeScript Specialized](#typescript-specialized)
2323
- [Other](#other)
2424
- [Rules](#rules)
25+
- [Benchmark](#benchmark)
2526
- [FAQ](#faq)
2627
- [Roadmap](#roadmap)
2728
- [Contributing](#contributing)
2829
- [License](#license)
2930

3031
## Features
3132

32-
- **Modern**: First-class support for TypeScript, React 19, and more.
33-
- **Flexible**: Fully customizable rule severity levels, allowing you to enforce or relax rules as needed.
34-
- **Performant**: Built with performance in mind, optimized for large codebases, **4-7x faster** than other ESLint plugins.
35-
- **Context-aware Linting**: Rules that understand the context of your code and project configuration to provide more accurate linting.
33+
- **Modern**: First-class support for **TypeScript**, **React 19**, and more.
34+
- **Flexible**: Fully customizable rule severity levels, allowing you to **enforce** or **relax** rules as needed.
35+
- **Performant**: Built with performance in mind, optimized for large codebases, [**4-7x faster**](https://github.com/Rel1cx/eslint-react-benchmark) than other ESLint plugins.
36+
- **Context-aware Linting**: Rules that understand the context of your code and [project configuration](https://eslint-react.xyz/docs/configuration/configure-project-config) to provide more **accurate** linting.
3637

3738
## Public Packages
3839

@@ -53,8 +54,8 @@
5354
> [!NOTE]\
5455
> ESLint React requires the following minimum versions:
5556
>
56-
> - Node.js: 18.18.0
57-
> - ESLint: 8.57.0
57+
> - Node.js: 20.19.0
58+
> - ESLint: 9.24.0
5859
> - TypeScript: 4.9.5
5960
6061
### Install
@@ -68,46 +69,46 @@ npm install --save-dev typescript-eslint @eslint-react/eslint-plugin
6869
```js
6970
// eslint.config.js
7071

71-
// @ts-check
7272
import eslintReact from "@eslint-react/eslint-plugin";
7373
import eslintJs from "@eslint/js";
74+
import { defineConfig } from "eslint/config";
7475
import tseslint from "typescript-eslint";
7576

76-
export default tseslint.config({
77-
files: ["**/*.ts", "**/*.tsx"],
78-
79-
// Extend recommended rule sets from:
80-
// 1. ESLint JS's recommended rules
81-
// 2. TypeScript ESLint recommended rules
82-
// 3. ESLint React's recommended-typescript rules
83-
extends: [
84-
eslintJs.configs.recommended,
85-
tseslint.configs.recommended,
86-
eslintReact.configs["recommended-typescript"],
87-
],
88-
89-
// Configure language/parsing options
90-
languageOptions: {
91-
// Use TypeScript ESLint parser for TypeScript files
92-
parser: tseslint.parser,
93-
parserOptions: {
94-
// Enable project service for better TypeScript integration
95-
projectService: true,
96-
tsconfigRootDir: import.meta.dirname,
77+
export default defineConfig([
78+
{
79+
files: ["**/*.ts", "**/*.tsx"],
80+
81+
// Extend recommended rule sets from:
82+
// 1. ESLint JS's recommended rules
83+
// 2. TypeScript ESLint recommended rules
84+
// 3. ESLint React's recommended-typescript rules
85+
extends: [
86+
eslintJs.configs.recommended,
87+
tseslint.configs.recommended,
88+
eslintReact.configs["recommended-typescript"],
89+
],
90+
91+
// Configure language/parsing options
92+
languageOptions: {
93+
// Use TypeScript ESLint parser for TypeScript files
94+
parser: tseslint.parser,
95+
parserOptions: {
96+
// Enable project service for better TypeScript integration
97+
projectService: true,
98+
tsconfigRootDir: import.meta.dirname,
99+
},
97100
},
98-
},
99101

100-
// Custom rule overrides (modify rule levels or disable rules)
101-
rules: {
102-
"@eslint-react/no-missing-key": "warn",
102+
// Custom rule overrides (modify rule levels or disable rules)
103+
rules: {
104+
"@eslint-react/no-missing-key": "warn",
105+
},
103106
},
104-
});
107+
]);
105108
```
106109

107110
[Full Installation Guide ↗](https://eslint-react.xyz/docs/getting-started/typescript)
108111

109-
</details>
110-
111112
## Presets
112113

113114
### Bare Bones
@@ -141,6 +142,8 @@ export default tseslint.config({
141142
Disable rules in the `web-api` preset.
142143
- `disable-type-checked`\
143144
Disable rules that require type information.
145+
- `disable-conflict-eslint-plugin-react`\
146+
Disable rules in `eslint-plugin-react` that conflict with rules in our plugins.
144147
- `off`\
145148
Disable all rules in this plugin except for debug rules.
146149

@@ -150,6 +153,10 @@ export default tseslint.config({
150153

151154
[Rules Overview ↗](https://eslint-react.xyz/docs/rules/overview)
152155

156+
## Benchmark
157+
158+
[Benchmark Results ↗](https://github.com/Rel1cx/eslint-react-benchmark)
159+
153160
## FAQ
154161

155162
[Frequently Asked Questions ↗](https://eslint-react.xyz/docs/faq)
@@ -162,7 +169,7 @@ export default tseslint.config({
162169

163170
Contributions are welcome!
164171

165-
Please follow our [contributing guidelines](./.github/CONTRIBUTING.md).
172+
Please follow our [contributing guidelines](.github/CONTRIBUTING.md).
166173

167174
## License
168175

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.53.2-beta.1
1+
2.0.0-beta.194

apps/website/app/base.css renamed to apps/website/app/app.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
@import "tailwindcss";
22
@import "tailwindcss-animated";
3-
@import "./theme.css";
3+
@import "./theme/theme.css";
44
@import "fumadocs-ui/css/preset.css";
55
@import "fumadocs-twoslash/twoslash.css";
66

File renamed without changes.

apps/website/app/docs/layout.tsx

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,3 @@ export default function Layout({ children }: { children: ReactNode }) {
1515
</DocsLayout>
1616
);
1717
}
18-
19-
// Notebook layout
20-
// import type { ReactNode } from "react";
21-
// import { baseOptions } from "#/app/layout.config";
22-
// import { source } from "#/lib/source";
23-
// import { DocsLayout } from "fumadocs-ui/layouts/notebook";
24-
25-
// export default function Layout({ children }: { children: ReactNode }) {
26-
// return (
27-
// <DocsLayout
28-
// {...baseOptions}
29-
// links={baseOptions.links?.slice(1, -1) ?? []}
30-
// // the position of navbar
31-
// nav={{ ...baseOptions.nav, mode: "top" }}
32-
// // the position of Sidebar Tabs
33-
// tabMode="navbar"
34-
// tree={source.pageTree}
35-
// >
36-
// {children}
37-
// </DocsLayout>
38-
// );
39-
// }

apps/website/app/layout.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import type { ReactNode } from "react";
55

66
import { ViewTransitions } from "next-view-transitions";
77

8-
import "./base.css";
9-
import "./overrides.css";
8+
import "#/app/app.css";
9+
import "#/app/app.override.css";
1010

1111
const themeOptions = {
1212
enabled: true,

0 commit comments

Comments
 (0)