@@ -4,165 +4,246 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
44
55## Project Overview
66
7- ESLint React is a high-performance ESLint plugin for React (4-7x faster than alternatives). It provides composable ESLint rules for React and related libraries. It's a monorepo with multiple specialized ESLint plugins that can be used individually or as a unified plugin .
7+ ESLint React is a monorepo containing composable, high-performance ESLint plugins for React and related frameworks. The project provides both a unified plugin ( ` @eslint-react/eslint-plugin ` ) and modular plugins for specific concerns (react-x, react-dom, react-web-api, react-hooks-extra, react-naming-convention) .
88
9- ## Build System
9+ ## Development Commands
1010
11- - ** Package Manager** : pnpm (v10.28.2)
12- - ** Build Tool** : tsdown - TypeScript to JavaScript bundler
13- - ** Formatter** : dprint
14- - ** Test Runner** : vitest
15- - ** TypeScript** : v5.9.3 with strict configuration
16-
17- ## Common Commands
11+ ### Building
1812
1913``` bash
20- # Build all packages (must be run before tests/linting )
14+ # Build all packages (includes update scripts, pkgs, packages, and docs )
2115pnpm run build
2216
23- # Run all tests
24- pnpm run test
17+ # Build internal packages used in the monorepo (.pkgs)
18+ pnpm run build:pkgs
2519
26- # Run a single test file
27- pnpm vitest packages/plugins/eslint-plugin-react-x/src/rules/no-missing-key.spec.ts
20+ # Build publishable packages only
21+ pnpm run build: packages
2822
29- # Run all linting checks
30- pnpm run lint
31-
32- # Run specific lint checks
33- pnpm run lint:es # ESLint
34- pnpm run lint:ts # TypeScript type checking
35- pnpm run lint:deps # Dependency analysis with skott
36- pnpm run lint:publish # Package linting with publint
37-
38- # Format code
39- pnpm run format:write
23+ # Build TypeDoc documentation for all packages
24+ pnpm run build:docs
4025
41- # Update generated files (versions, READMEs, website docs)
42- pnpm run update:all
26+ # Build the website
27+ pnpm run build:website
4328```
4429
45- ## Monorepo Structure
30+ ### Testing
4631
47- ### Packages (` /packages/ ` )
32+ ``` bash
33+ # Run all tests
34+ pnpm test
4835
49- ** Core packages:**
36+ # Run a single test file
37+ pnpm vitest packages/plugins/eslint-plugin-react-x/src/rules/[rule-name].spec.ts
5038
51- - ` @eslint-react/core ` - Core ESLint utility module for static analysis of React core APIs
52- - ` @eslint-react/shared ` - Shared constants, types, and functions
39+ # Run tests with heap usage logging
40+ pnpm test --logHeapUsage
41+ ```
5342
54- ** Plugin packages ** ( ` /packages/plugins/ ` ):
43+ ### Linting and Formatting
5544
56- - ` eslint-plugin ` - Unified plugin combining all individual plugins
57- - ` eslint-plugin-react-x ` - Core React rules (renderer-agnostic)
58- - ` eslint-plugin-react-dom ` - DOM-specific rules
59- - ` eslint-plugin-react-web-api ` - Web API interaction rules
60- - ` eslint-plugin-react-hooks-extra ` - Additional React Hooks rules
61- - ` eslint-plugin-react-naming-convention ` - Naming convention rules
62- - ` eslint-plugin-react-debug ` - Debug utilities
45+ ``` bash
46+ # Format code with dprint
47+ pnpm run format:write
6348
64- ** Utility packages** (` /packages/utilities/ ` ):
49+ # Check formatting
50+ pnpm run format:check
6551
66- - ` @eslint-react/ast ` - AST manipulation utilities
67- - ` @eslint-react/eff ` - Effect/functional programming utilities
68- - ` @eslint-react/var ` - Variable analysis utilities
52+ # Run all linting checks (deps, publish, ts, es, examples)
53+ pnpm run lint
6954
70- ### Local Packages (` /.pkgs/ ` )
55+ # Run ESLint
56+ pnpm run lint:es
7157
72- Private workspace packages:
58+ # Run TypeScript type checking
59+ pnpm run lint:ts
7360
74- - ` @local/configs ` - Shared ESLint and TypeScript configurations
75- - ` @local/function-rules ` - Custom function-based lint rules
61+ # Check for circular dependencies
62+ pnpm run lint:deps
7663
77- ### Applications (` /apps/ ` )
64+ # Verify package.json for publishing
65+ pnpm run lint:publish
66+ ```
7867
79- - ` website ` - Documentation website built with Next.js and Fumadocs
68+ ### Maintenance Scripts
8069
81- ### Examples (` /examples/ ` )
70+ ``` bash
71+ # Update version across all packages
72+ pnpm run update:version
8273
83- Example projects showing integrations with Next.js, React DOM, and various parsers.
74+ # Update README files
75+ pnpm run update:readme
8476
85- ## Rule Structure
77+ # Update website documentation from package sources
78+ pnpm run update:website
8679
87- Each ESLint rule follows this structure:
80+ # Verify rule metadata consistency
81+ pnpm run verify:rules-metas
8882
89- ```
90- packages/plugins/[plugin-name]/src/rules/
91- ├── rule-name.ts # Rule implementation
92- ├── rule-name.spec.ts # Test file
93- └── rule-name.mdx # Documentation
83+ # Sort package.json files
84+ pnpm run sort:package-json
9485```
9586
87+ ## Architecture
88+
89+ ### Monorepo Structure
90+
91+ The repository is organized as a pnpm workspace with the following structure:
92+
93+ - ** ` .pkgs/ ` ** - Internal packages used within the monorepo (configs, function-rules)
94+ - ** ` packages/ ` ** - Publishable packages organized by type:
95+ - ** ` packages/utilities/ ` ** - Low-level utilities (ast, eff, var)
96+ - ** ` packages/shared/ ` ** - Shared constants, types, and utilities
97+ - ** ` packages/core/ ` ** - Core React analysis utilities (component, hook, jsx detection)
98+ - ** ` packages/plugins/ ` ** - ESLint plugin packages
99+ - ** ` test/ ` ** - Shared test utilities and fixtures
100+ - ** ` scripts/ ` ** - Maintenance and build scripts
101+ - ** ` apps/ ` ** - Applications (website)
102+ - ** ` examples/ ` ** - Example projects
103+
104+ ### Package Dependencies
105+
106+ The dependency hierarchy flows bottom-up:
107+
108+ 1 . ** ` @eslint-react/eff ` ** - Base JavaScript/TypeScript utilities (no dependencies)
109+ 2 . ** ` @eslint-react/ast ` ** - TSESTree AST utilities (depends on: eff)
110+ 3 . ** ` @eslint-react/var ` ** - Variable and scope analysis (depends on: eff)
111+ 4 . ** ` @eslint-react/shared ` ** - Shared constants, settings, types (depends on: eff)
112+ 5 . ** ` @eslint-react/core ` ** - React-specific analysis (depends on: ast, eff, shared, var)
113+ 6 . ** Plugin packages** - ESLint rules (depend on: core and lower-level packages)
114+ 7 . ** ` @eslint-react/eslint-plugin ` ** - Unified plugin (aggregates all individual plugins)
115+
116+ ### Core Package Organization
117+
118+ The ` @eslint-react/core ` package provides React-specific analysis utilities organized by domain:
119+
120+ - ** ` api/ ` ** - React API detection and analysis
121+ - ** ` component/ ` ** - Component detection, collection, and analysis
122+ - Component collectors for both modern and legacy patterns
123+ - Component definition detection
124+ - Component naming and identification
125+ - Semantic node representations
126+ - ** ` function/ ` ** - Function analysis utilities
127+ - ** ` hierarchy/ ` ** - Component hierarchy analysis
128+ - ** ` hook/ ` ** - React Hook detection and analysis
129+ - Hook identification and naming
130+ - Hook collectors for tracking hook usage
131+ - Semantic node representations for hooks
132+ - ** ` jsx/ ` ** - JSX element and attribute analysis
133+ - JSX detection and configuration
134+ - Attribute value extraction
135+ - Element type analysis
136+ - ** ` ref/ ` ** - React ref analysis
137+ - ** ` semantic/ ` ** - Semantic node type definitions
138+
139+ ### Plugin Structure
140+
141+ Each plugin package follows a consistent structure:
142+
143+ - ** ` src/rules/ ` ** - Rule implementations (` .ts ` ) with co-located tests (` .spec.ts ` ) and documentation (` .mdx ` )
144+ - ** ` src/configs/ ` ** - Preset configurations
145+ - ** ` src/utils/ ` ** - Plugin-specific utilities (e.g., ` create-rule.ts ` )
146+ - ** ` src/plugin.ts ` ** - Plugin definition with rule exports
147+ - ** ` src/index.ts ` ** - Entry point with flat config adapters
148+
96149### Rule Implementation Pattern
97150
98- Rules are created using ` createRule ` from ` @typescript-eslint/utils ` :
151+ Rules follow a consistent pattern:
152+
153+ 1 . Import utilities from ` @eslint-react/core ` , ` @eslint-react/ast ` , ` @eslint-react/shared ` , etc.
154+ 2 . Define rule metadata: ` RULE_NAME ` , ` RULE_FEATURES ` , ` MessageID ` type
155+ 3 . Use ` createRule ` from ` ../utils ` to create the rule with TypeScript types
156+ 4 . Implement rule logic using collectors (e.g., ` useComponentCollector ` , ` useHookCollector ` )
157+ 5 . Export the rule as default
99158
159+ Example structure:
100160``` typescript
161+ import * as core from " @eslint-react/core" ;
101162import { createRule } from " ../utils" ;
102163
103164export const RULE_NAME = " rule-name" ;
104165export const RULE_FEATURES = [] as const satisfies RuleFeature [];
105166export type MessageID = " messageId" ;
106167
107168export default createRule <[], MessageID >({
108- meta: {
109- type: " problem" ,
110- docs: { description: " ..." },
111- messages: { messageId: " Error message" },
112- schema: [],
169+ meta: { /* ... */ },
170+ create(context ) {
171+ // Rule implementation
113172 },
114- name: RULE_NAME ,
115- create ,
116- defaultOptions: [],
117173});
118-
119- export function create(ctx : RuleContext <MessageID , []>): RuleListener {
120- return {
121- // AST visitors
122- };
123- }
124174```
125175
126- ### Testing Pattern
176+ ### Testing
127177
128- Tests use the TypeScript ESLint Rule Tester with vitest:
178+ - Tests use Vitest with ` @typescript-eslint/rule-tester `
179+ - Test files are co-located with source files: ` rule-name.spec.ts ` next to ` rule-name.ts `
180+ - Shared test utilities in ` test/ ` directory:
181+ - ` test/rule-tester.ts ` - Configured rule testers (with/without type checking)
182+ - ` test/fixtures/ ` - TypeScript configuration fixtures for different JSX modes
183+ - ` test/helpers.ts ` - Test helper functions
184+ - Use ` dedent ` (imported as ` tsx ` ) for formatting test code
185+ - Two rule testers available:
186+ - ` ruleTester ` - For rules without type information
187+ - ` ruleTesterWithTypes ` - For rules requiring TypeScript type information
129188
130- ``` typescript
131- import { ruleTester } from " ../../../../../test" ;
132- import rule , { RULE_NAME } from " ./rule-name" ;
189+ ### Build System
133190
134- ruleTester .run (RULE_NAME , rule , {
135- invalid: [{ code: " ..." , errors: [{ messageId: " ..." }] }],
136- valid: [" ..." ],
137- });
138- ```
191+ - Uses ` tsdown ` for building packages (configured via ` tsdown.config.ts ` )
192+ - Uses ` dprint ` for code formatting (configured via ` dprint.json ` )
193+ - TypeScript configuration extends from ` @local/configs/tsconfig.base.json `
194+ - All packages target Node.js 20+ and ESM format
139195
140- Use ` ruleTesterWithTypes ` for type-aware rules. Import test helpers from ` /test ` :
196+ ### Settings and Configuration
141197
142- ``` typescript
143- import { allValid , ruleTester , ruleTesterWithTypes } from " ../../../../../test" ;
144- ```
198+ ESLint React supports custom settings via ` settings["react-x"] ` :
199+
200+ - ` importSource ` - Custom React import source (default: "react")
201+ - ` polymorphicPropName ` - Prop name for polymorphic components (e.g., "as")
202+ - ` version ` - React version (default: "detect")
203+ - ` additionalStateHooks ` - Regex pattern for custom state hooks
145204
146- ## Key Dependencies
205+ Access settings in rules using ` coerceSettings(context.settings) ` from ` @eslint-react/shared ` .
147206
148- - ` @typescript-eslint/* ` - TypeScript ESLint integration
149- - ` effect ` - Functional programming library used throughout
150- - ` ts-pattern ` - Pattern matching library
151- - ` tsdown ` - TypeScript bundler for building packages
207+ ## Development Workflow
152208
153- ## Adding a New Rule
209+ ### Adding a New Rule
154210
1552111 . Create the rule file in the appropriate plugin's ` src/rules/ ` directory
156- 2 . Create the corresponding ` .spec.ts ` test file
157- 3 . Export the rule in the plugin's ` src/plugin.ts ` entry file
158- 4 . Add documentation as ` .mdx ` file with the same name
159- 5 . Update preset configurations if the rule should be enabled by default
160- 6 . Update the unified plugin to include the new rule
161- 7 . Run ` pnpm run build ` and ` pnpm run test `
162-
163- ## Architecture Notes
164-
165- - Rules use the ` @eslint-react/core ` package for React-specific analysis (component detection, hook analysis, JSX analysis)
166- - The ` @eslint-react/shared ` package provides common types, settings, and reporting utilities
167- - The ` effect ` library is used for functional programming patterns
168- - Each plugin is independently publishable but the unified plugin (` @eslint-react/eslint-plugin ` ) combines them all
212+ 2 . Implement the rule following the pattern above
213+ 3 . Create the test file (` .spec.ts ` ) with valid and invalid test cases
214+ 4 . Create documentation file (` .mdx ` ) describing the rule
215+ 5 . Export the rule in ` src/plugin.ts `
216+ 6 . Add the rule to appropriate preset configs in ` src/configs/ `
217+ 7 . If adding to a modular plugin, update the unified plugin (` packages/plugins/eslint-plugin/ ` )
218+ 8 . Run ` pnpm run update:website ` to sync documentation
219+ 9 . Run ` pnpm run verify:rules-metas ` to verify metadata consistency
220+ 10 . Run tests and build to ensure everything works
221+
222+ ### Modifying Core Utilities
223+
224+ When modifying packages in ` packages/core/ ` or ` packages/utilities/ ` :
225+
226+ 1 . Make changes to the source files
227+ 2 . Run ` pnpm run build:pkgs ` if changes affect internal packages
228+ 3 . Run ` pnpm run build:packages ` to rebuild dependent packages
229+ 4 . Run tests to ensure no regressions
230+ 5 . Update TypeDoc comments if changing public APIs
231+
232+ ### Working with the Website
233+
234+ The website is built from rule documentation (` .mdx ` files) in plugin packages:
235+
236+ 1 . Edit ` .mdx ` files in ` packages/plugins/*/src/rules/ `
237+ 2 . Run ` pnpm run update:website ` to sync changes to the website
238+ 3 . Run ` pnpm run build:website ` to build the website
239+ 4 . Website source is in ` apps/website/ `
240+
241+ ## Important Notes
242+
243+ - ** Never use ` git add -A ` or ` git add . ` ** - Always stage specific files to avoid committing sensitive data
244+ - ** Test files are co-located with source files** - Keep ` rule-name.spec.ts ` next to ` rule-name.ts `
245+ - ** Use workspace dependencies** - Reference internal packages with ` workspace:* ` in package.json
246+ - ** Follow the existing patterns** - Look at similar rules for guidance on implementation
247+ - ** Type safety is critical** - All packages use strict TypeScript settings
248+ - ** Performance matters** - This project emphasizes performance; avoid unnecessary AST traversals
249+ - ** Use collectors for stateful analysis** - Use ` useComponentCollector ` , ` useHookCollector ` from ` @eslint-react/core ` for tracking components and hooks across the AST
0 commit comments