eslint-plugin-code-style 2.0.0 → 2.0.2

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/AGENTS.md DELETED
@@ -1,1387 +0,0 @@
1
- # AGENTS.md
2
-
3
- Instructions for AI coding agents working with this codebase.
4
-
5
- ## Project Overview
6
-
7
- **eslint-plugin-code-style** is an ESLint plugin providing 79 custom formatting rules (70 auto-fixable, 19 configurable, 9 report-only) for React/JSX projects. It's designed for ESLint v9+ flat config system.
8
-
9
- - **Source code:** `src/` - Modular rule files organized by category
10
- - **Built output:** `dist/index.js` - Bundled + minified (generated by esbuild, gitignored)
11
- - **Type definitions:** `index.d.ts` - TypeScript declarations for IDE support
12
- - **Recommended configs:** `recommended-configs/` - Ready-to-use ESLint configurations
13
- - **Test apps:** `_tests_/` - Sample apps for testing rules
14
-
15
- ### Available Configurations
16
-
17
- | Config | Recommended Folder | Test Folder | Status |
18
- |--------|-------------------|-------------|--------|
19
- | React (JS) | `recommended-configs/react/` | `_tests_/react/` | Available |
20
- | React + TS + Tailwind | `recommended-configs/react-ts-tw/` | `_tests_/react-ts-tw/` | Available |
21
- | React + TypeScript | `recommended-configs/react-ts/` | `_tests_/react-ts/` | Available |
22
- | React + Tailwind | `recommended-configs/react-tw/` | `_tests_/react-tw/` | Available |
23
-
24
- ### Test Projects & Rule Compatibility
25
-
26
- **IMPORTANT:** When adding/editing rules, they must be tested in ALL applicable test projects.
27
-
28
- Each test project in `_tests_/` corresponds to a specific tech stack. Rules should ONLY be added to projects that support them:
29
-
30
- | Rule Category | `react/` (JS only) | `react-ts-tw/` (TS + Tailwind) | `react-ts/` (TS) | `react-tw/` (TW) |
31
- |---------------|:------------------:|:------------------------------:|:-------------------:|:-------------------:|
32
- | **General rules** (arrays, functions, etc.) | ✅ | ✅ | ✅ | ✅ |
33
- | **JSX/React rules** | ✅ | ✅ | ✅ | ✅ |
34
- | **TypeScript rules** | ❌ | ✅ | ✅ | ❌ |
35
- | **Tailwind rules** | ❌ | ✅ | ❌ | ✅ |
36
-
37
- **TypeScript-only rules** (70 rules in JS projects, 79 in TS projects):
38
- - `component-props-inline-type`
39
- - `enum-format`
40
- - `enum-type-enforcement`
41
- - `interface-format`
42
- - `no-inline-type-definitions`
43
- - `prop-naming-convention`
44
- - `type-annotation-spacing`
45
- - `type-format`
46
- - `typescript-definition-location`
47
-
48
- **Tailwind-related rules** (work in all projects but most useful with Tailwind):
49
- - `classname-dynamic-at-end` - Enforce dynamic expressions at end of className
50
- - `classname-multiline` - Format long className strings with one class per line
51
- - `classname-no-extra-spaces` - Remove extra/leading/trailing spaces in className
52
- - `classname-order` - Enforce Tailwind CSS class ordering in variables, object properties, and return statements
53
-
54
- > **Note:** `classname-order` complements the official `tailwindcss/classnames-order` plugin:
55
- > - **`tailwindcss/classnames-order`** - Handles JSX `className` attributes directly
56
- > - **`classname-order`** - Handles class strings in variables, object properties, and return statements (areas the Tailwind plugin doesn't cover)
57
- >
58
- > Both rules should be enabled together for complete Tailwind class ordering coverage.
59
-
60
- **When adding a new test project:**
61
- 1. Create folder: `_tests_/<project-name>/`
62
- 2. Copy structure from similar existing project
63
- 3. Create `eslint.config.js` with appropriate rules for that stack
64
- 4. Add ALL applicable rules (skip rules for unsupported tech)
65
- 5. Update this table in AGENTS.md
66
- 6. Update "Available Configurations" table above
67
-
68
- ## Build & Test Commands
69
-
70
- ```bash
71
- # Build (required before testing or publishing)
72
- npm run build # Bundles src/ into dist/index.js via esbuild
73
-
74
- # Test rules against a test app (e.g., react, react-ts, react-ts-tw)
75
- cd _tests_/<config-name>
76
- npm install
77
- npm run lint # Check for errors
78
- npm run lint:fix # Auto-fix issues
79
-
80
- # Publish (from root folder only — run build first)
81
- npm run build && npm publish
82
- ```
83
-
84
- ## Code Structure
85
-
86
- Rules are organized in modular source files under `src/`:
87
-
88
- ```
89
- src/
90
- ├── index.js — Entry point, imports all rules, exports plugin object
91
- ├── utils/
92
- │ └── tailwind.js — Tailwind CSS class utilities (shared across classname-* rules)
93
- └── rules/
94
- ├── arrays.js — 3 rules
95
- ├── arrow-functions.js — 4 rules
96
- ├── call-expressions.js — 6 rules
97
- ├── classes.js — 2 rules
98
- ├── comments.js — 1 rule
99
- ├── components.js — 6 rules
100
- ├── control-flow.js — 8 rules
101
- ├── functions.js — 6 rules
102
- ├── hooks.js — 3 rules
103
- ├── imports-exports.js — 8 rules
104
- ├── jsx.js — 14 rules
105
- ├── objects.js — 5 rules
106
- ├── react.js — 1 rule
107
- ├── spacing.js — 2 rules
108
- ├── strings.js — 1 rule
109
- ├── typescript.js — 8 rules
110
- └── variables.js — 1 rule
111
- dist/
112
- └── index.js — Bundled + minified output (generated, gitignored)
113
- ```
114
-
115
- The build step (`npm run build`) uses esbuild to bundle all source files into a single minified `dist/index.js`.
116
-
117
- ## Rule Implementation Pattern
118
-
119
- Every rule follows this exact structure:
120
-
121
- ```javascript
122
- /**
123
- * ───────────────────────────────────────────────────────────────
124
- * Rule: Rule Name Here
125
- * ───────────────────────────────────────────────────────────────
126
- *
127
- * Description:
128
- * Brief description of what the rule does.
129
- *
130
- * Options:
131
- * { optionName: defaultValue } - Description of option
132
- *
133
- * ✓ Good:
134
- * // Example of correct code
135
- *
136
- * ✗ Bad:
137
- * // Example of incorrect code
138
- */
139
- const ruleName = {
140
- create(context) {
141
- const sourceCode = context.sourceCode || context.getSourceCode();
142
- const options = context.options[0] || {};
143
- const optionName = options.optionName !== undefined ? options.optionName : defaultValue;
144
-
145
- return {
146
- NodeType(node) {
147
- // Rule logic here
148
-
149
- // Report issues with auto-fix
150
- context.report({
151
- fix: (fixer) => fixer.replaceText(node, "fixed code"),
152
- message: "Error message describing the issue",
153
- node,
154
- });
155
- },
156
- };
157
- },
158
- meta: {
159
- docs: { description: "Short description for documentation" },
160
- fixable: "code", // Required for auto-fix rules
161
- schema: [
162
- {
163
- additionalProperties: false,
164
- properties: {
165
- optionName: {
166
- default: 3,
167
- description: "Option description",
168
- minimum: 1,
169
- type: "integer",
170
- },
171
- },
172
- type: "object",
173
- },
174
- ],
175
- type: "layout", // "layout" for formatting, "suggestion" for conventions
176
- },
177
- };
178
- ```
179
-
180
- ### Adding a New Rule — Complete Checklist
181
-
182
- **IMPORTANT:** Adding a new rule requires a **MINOR version bump** (e.g., 1.5.0 → 1.6.0).
183
-
184
- When creating a new rule, ALL of the following files must be updated:
185
-
186
- #### 1. `src/rules/<category>.js` — Rule Implementation
187
-
188
- - [ ] Add rule to the appropriate category file in `src/rules/`
189
- - [ ] Add the variable name to the file's `export { ... }` block
190
- - [ ] Add JSDoc comment block with the standard format:
191
- ```javascript
192
- /**
193
- * ───────────────────────────────────────────────────────────────
194
- * Rule: Rule Name Here
195
- * ───────────────────────────────────────────────────────────────
196
- *
197
- * Description:
198
- * Brief description of what the rule does.
199
- *
200
- * ✓ Good:
201
- * // Example of correct code
202
- *
203
- * ✗ Bad:
204
- * // Example of incorrect code
205
- */
206
- ```
207
- - [ ] Add `const ruleName = { create(), meta: {} }` definition
208
- - [ ] Include `fixable: "code"` or `fixable: "whitespace"` in meta if auto-fixable
209
- - [ ] Import rule in `src/index.js` and add to `rules` object in default export (keep **alphabetical order**)
210
- - [ ] Run `npm run build` to regenerate `dist/index.js`
211
-
212
- #### 2. `index.d.ts` — TypeScript Types
213
-
214
- - [ ] Add rule name to `RuleNames` type union (**alphabetically sorted**):
215
- ```typescript
216
- | "code-style/new-rule-name"
217
- ```
218
- - [ ] Add rule to `PluginRules` interface (**alphabetically sorted**):
219
- ```typescript
220
- "new-rule-name": Rule.RuleModule;
221
- ```
222
-
223
- #### 3. `README.md` — Main Documentation
224
-
225
- > ⚠️ **IMPORTANT:** README.md has **three separate sections** that mention rules. When adding or editing a rule, you must update ALL relevant sections:
226
- > - **Rule counts** (5 locations) — must match actual rule count
227
- > - **Quick Start example** (~line 184) — alphabetically sorted configuration example
228
- > - **Rules Summary table** — brief description with emoji indicators
229
- >
230
- > Missing any section will leave documentation inconsistent. Use the `audit-docs` skill to verify all sections are in sync.
231
-
232
- **a) Update rule counts** (see [Rule Count Locations](#rule-count-locations) for all positions):
233
- - [ ] Line ~22: `*XX rules (YY auto-fixable)*`
234
- - [ ] Line ~30: `**XX custom rules** (YY auto-fixable)`
235
- - [ ] Line ~39: `YY of XX rules support auto-fix`
236
- - [ ] Line ~272: `**XX rules total** — YY with auto-fix`
237
- - [ ] Line ~409: `YY of XX rules support auto-fixing`
238
-
239
- **b) Add rule to Quick Start example** (~line 184, alphabetically sorted):
240
- ```javascript
241
- "code-style/new-rule-name": "error",
242
- ```
243
-
244
- **c) Add rule to Rules Summary table** (find the appropriate category):
245
- ```markdown
246
- | `new-rule-name` | Brief description of what it does 🔧 |
247
- ```
248
- - Add 🔧 emoji if auto-fixable
249
- - Add ⚙️ emoji if has configurable options
250
-
251
- #### 3b. `docs/rules/<category>.md` — Detailed Rule Documentation
252
-
253
- Add detailed rule documentation to the appropriate category file in `docs/rules/`:
254
-
255
- ```markdown
256
- ### `new-rule-name`
257
-
258
- **What it does:** One-line description of the rule's purpose.
259
-
260
- **Why use it:** Context for why this rule is helpful (optional).
261
-
262
- \`\`\`javascript
263
- // ✅ Good — description of correct pattern
264
- const example = "correct code";
265
-
266
- // ✅ Good — another correct example
267
- const another = "also correct";
268
-
269
- // ❌ Bad — description of incorrect pattern
270
- const example = "incorrect code";
271
-
272
- // ❌ Bad — another incorrect example
273
- const wrong = "also wrong";
274
- \`\`\`
275
-
276
- **Options:** (only if rule has options)
277
-
278
- | Option | Type | Default | Description |
279
- |--------|------|---------|-------------|
280
- | `optionName` | `string` | `"value"` | What the option does |
281
-
282
- \`\`\`javascript
283
- // Configuration example
284
- "code-style/new-rule-name": ["error", { optionName: "value" }]
285
- \`\`\`
286
-
287
- ---
288
- ```
289
-
290
- #### 4. `AGENTS.md` — Agent Instructions
291
-
292
- - [ ] Update rule counts in [Rule Count Locations](#rule-count-locations) section (Current Counts table)
293
- - [ ] Update all rule count references (see table in Rule Count Locations)
294
- - [ ] Add rule to its category in [Rule Categories](#rule-categories) section
295
-
296
- #### 5. Config Files — Add Rule to Configs
297
-
298
- Add the rule (**alphabetically sorted**) to ALL config files:
299
-
300
- - [ ] `recommended-configs/react-ts-tw/eslint.config.js`
301
- - [ ] `recommended-configs/react/eslint.config.js` (skip if TypeScript-only rule)
302
- - [ ] `_tests_/react-ts-tw/eslint.config.js`
303
- - [ ] `_tests_/react/eslint.config.js` (skip if TypeScript-only rule)
304
-
305
- **TypeScript-only rules** (only add to `-ts-tw` configs):
306
- - `component-props-inline-type`, `enum-format`, `interface-format`
307
- - `no-inline-type-definitions`, `type-annotation-spacing`, `type-format`
308
- - `typescript-definition-location`
309
-
310
- #### 6. Config READMEs — Update Rule Counts
311
-
312
- - [ ] `recommended-configs/react-ts-tw/README.md` (~line 396)
313
- - [ ] `recommended-configs/react/README.md` (~line 286)
314
-
315
- #### 7. Version & Tag
316
-
317
- - [ ] Update `package.json` version (MINOR bump: x.Y.0)
318
- - [ ] Commit with message: `feat: add rule-name rule`
319
- - [ ] Create tag: `git tag vX.Y.0`
320
-
321
- #### 8. Testing the Rule
322
-
323
- **IMPORTANT:** Every new rule MUST be tested before committing.
324
-
325
- **a) Add examples to existing test project code:**
326
-
327
- The test projects (`_tests_/react/`, `_tests_/react-ts-tw/`, etc.) contain real code (components, hooks, utils, etc.) that should naturally exercise all rules. When adding a new rule:
328
-
329
- - Add code examples to **existing files** in the test project that are relevant to the rule
330
- - For example: if adding an array rule, add array code to existing component files
331
- - The test project code should cover ALL rules through its natural structure
332
-
333
- ```
334
- _tests_/react-ts-tw/src/
335
- ├── app.tsx # Main app - exercises component rules
336
- ├── components/ # Components - exercises JSX, props rules
337
- │ ├── button.tsx
338
- │ └── card.tsx
339
- ├── hooks/ # Hooks - exercises hook rules
340
- ├── utils/ # Utils - exercises function rules
341
- ├── interfaces/ # Interfaces - exercises TS rules
342
- └── types/ # Types - exercises type rules
343
- ```
344
-
345
- **b) Create temporary test file for quick verification:**
346
-
347
- For quick testing during development, create a temporary test file:
348
-
349
- ```bash
350
- # Create temp test file
351
- _tests_/react-ts-tw/src/test-rule-name.tsx
352
- ```
353
-
354
- ```javascript
355
- // Temporary test file: test-rule-name.tsx
356
-
357
- // Test case 1: Should trigger error (BAD code)
358
- const badExample = /* code that violates the rule */;
359
-
360
- // Test case 2: Should NOT trigger error (GOOD code)
361
- const goodExample = /* code that follows the rule */;
362
- ```
363
-
364
- **c) Run the linter to verify:**
365
-
366
- ```bash
367
- cd _tests_/react-ts-tw
368
-
369
- # Check errors are reported for bad code
370
- npx eslint src/test-rule-name.tsx
371
-
372
- # Verify auto-fix works (if rule is fixable)
373
- npx eslint src/test-rule-name.tsx --fix
374
- cat src/test-rule-name.tsx # Verify fixed code is correct
375
-
376
- # Also run on entire project to ensure no regressions
377
- npx eslint src/
378
- ```
379
-
380
- **d) Clean up temporary test file:**
381
-
382
- ```bash
383
- rm _tests_/react-ts-tw/src/test-rule-name.tsx
384
- rm _tests_/react/src/test-rule-name.jsx # if created
385
- ```
386
-
387
- **e) Ensure test project code covers the new rule:**
388
-
389
- After temporary testing, make sure the actual test project code (components, hooks, etc.) includes examples that exercise the new rule. This provides ongoing regression testing.
390
-
391
- #### 9. Verification
392
-
393
- Run these commands to verify all rules are in sync:
394
-
395
- ```bash
396
- # Count rules in each location
397
- grep -rc "^const [a-zA-Z]* = {$" src/rules/
398
- grep -c 'code-style/' index.d.ts
399
- grep -c '"code-style/' recommended-configs/react-ts-tw/eslint.config.js
400
-
401
- # Find rules missing from README
402
- grep -oE '"[a-z-]+":' src/index.js | tr -d '":' | sort > /tmp/a.txt
403
- grep -oE '\`[a-z-]+\`' README.md | tr -d '\`' | sort | uniq > /tmp/b.txt
404
- comm -23 /tmp/a.txt /tmp/b.txt
405
- ```
406
-
407
- ---
408
-
409
- ### Removing a Rule — Complete Checklist
410
-
411
- **IMPORTANT:** Removing a rule is a **BREAKING CHANGE** requiring a **MAJOR version bump** (e.g., 1.6.0 → 2.0.0).
412
-
413
- #### 1. `src/rules/<category>.js` + `src/index.js`
414
- - [ ] Remove the rule's JSDoc comment block and `const` definition from category file
415
- - [ ] Remove from the file's `export { ... }` block
416
- - [ ] Remove import and `rules` object entry from `src/index.js`
417
- - [ ] Run `npm run build` to regenerate `dist/index.js`
418
-
419
- #### 2. `index.d.ts`
420
- - [ ] Remove from `RuleNames` type union
421
- - [ ] Remove from `PluginRules` interface
422
-
423
- #### 3. `README.md` + `docs/rules/`
424
- - [ ] Update all rule counts (see [Rule Count Locations](#rule-count-locations))
425
- - [ ] Remove from `rules: {}` example in Quick Start
426
- - [ ] Remove from Rules Summary table
427
- - [ ] Remove detailed documentation from `docs/rules/<category>.md`
428
-
429
- #### 4. `AGENTS.md`
430
- - [ ] Update all rule counts
431
- - [ ] Remove from Rule Categories section
432
-
433
- #### 5. Config Files
434
- - [ ] Remove from `recommended-configs/react-ts-tw/eslint.config.js`
435
- - [ ] Remove from `recommended-configs/react/eslint.config.js`
436
- - [ ] Remove from `_tests_/react-ts-tw/eslint.config.js`
437
- - [ ] Remove from `_tests_/react/eslint.config.js`
438
-
439
- #### 6. Config READMEs
440
- - [ ] Update `recommended-configs/react-ts-tw/README.md`
441
- - [ ] Update `recommended-configs/react/README.md`
442
-
443
- #### 7. Version & Tag
444
- - [ ] Update `package.json` version (MAJOR bump: X.0.0)
445
- - [ ] Commit with message: `feat!: remove rule-name rule` (note the `!` for breaking change)
446
- - [ ] Create tag: `git tag vX.0.0`
447
-
448
- ---
449
-
450
- ### Editing an Existing Rule — Checklist
451
-
452
- When modifying an existing rule, check if these need updates:
453
-
454
- > ⚠️ **Documentation Reminder:** If the rule's behavior, examples, or options change, update README.md (Quick Start example, Rules Summary table) and the detailed docs in `docs/rules/<category>.md`. See the note in "Adding a New Rule" section for details.
455
-
456
- #### If fixing a bug (PATCH version: x.x.+1):
457
- - [ ] Fix the issue in rule's `create()` function in `src/rules/<category>.js`
458
- - [ ] Test in `_tests_/` apps with `npm run lint` and `npm run lint:fix`
459
- - [ ] Commit: `fix: description of what was fixed in rule-name`
460
-
461
- #### If changing rule behavior (PATCH or MINOR depending on scope):
462
- - [ ] Update rule logic in `src/rules/<category>.js`
463
- - [ ] Update JSDoc in source file (Good/Bad examples if they changed)
464
- - [ ] Update `README.md` rule documentation section:
465
- - Update "What it does" if behavior changed
466
- - Update code examples (✅ Good / ❌ Bad) to reflect new behavior
467
- - [ ] Test in `_tests_/` apps with `npm run lint` and `npm run lint:fix`
468
-
469
- #### If adding new options (MINOR version: x.+1.0):
470
- - [ ] Add option to `schema` in rule's `meta` object in `src/rules/<category>.js`
471
- - [ ] Add option handling in `create()` function with default value:
472
- ```javascript
473
- const options = context.options[0] || {};
474
- const newOption = options.newOption !== undefined ? options.newOption : defaultValue;
475
- ```
476
- - [ ] Update JSDoc Options section in source file
477
- - [ ] Update README.md rule documentation:
478
- - Add row to Options table
479
- - Add configuration example showing the new option
480
-
481
- #### If adding auto-fix to rule that didn't have it (MINOR version: x.+1.0):
482
- - [ ] Add `fixable: "code"` or `fixable: "whitespace"` to rule's `meta` object
483
- - [ ] Add `fix()` function in `context.report()`:
484
- ```javascript
485
- context.report({
486
- fix: (fixer) => fixer.replaceText(node, "fixed code"),
487
- message: "Error message",
488
- node,
489
- });
490
- ```
491
- - [ ] Update README.md Rules Summary table: add 🔧 emoji
492
- - [ ] Update rule counts: increment auto-fixable count, decrement report-only count
493
- - [ ] Test auto-fix with `npm run lint:fix`
494
-
495
- #### If changing default values (MAJOR version: +1.0.0 — breaking change):
496
- - [ ] Update default value in `create()` function
497
- - [ ] Update JSDoc in source file
498
- - [ ] Update README.md options table (Default column)
499
- - [ ] Commit with `!`: `feat!: change default value for rule-name option`
500
-
501
- #### Testing After Any Edit
502
-
503
- **IMPORTANT:** Always test rule changes before committing.
504
-
505
- 1. **Create a temporary test file** for quick verification:
506
- ```bash
507
- # Create in appropriate project(s)
508
- _tests_/react-ts-tw/src/test-rule-name.tsx # For TS rules
509
- _tests_/react/src/test-rule-name.jsx # For general rules (test in both)
510
- ```
511
-
512
- 2. **Add test cases:**
513
- ```javascript
514
- // Temporary test file
515
-
516
- // Should trigger the rule (BAD - test this fails)
517
- const badCode = /* code that should fail */;
518
-
519
- // Should pass (GOOD - test this passes)
520
- const goodCode = /* code that should pass */;
521
- ```
522
-
523
- 3. **Run tests:**
524
- ```bash
525
- cd _tests_/react-ts-tw
526
- npx eslint src/test-rule-name.tsx # Verify error is reported
527
- npx eslint src/test-rule-name.tsx --fix # Verify auto-fix works
528
- npx eslint src/ # Ensure no regressions
529
- ```
530
-
531
- 4. **Clean up temporary test file:**
532
- ```bash
533
- rm _tests_/react-ts-tw/src/test-rule-name.tsx
534
- rm _tests_/react/src/test-rule-name.jsx # if created
535
- ```
536
-
537
- 5. **Ensure test project code covers the change:**
538
- - Update existing code in test project (components, hooks, etc.) if needed
539
- - The test project should naturally exercise the edited rule behavior
540
-
541
- #### Version Bump After Edits
542
-
543
- **IMPORTANT:** Every commit requires a version bump and tag. After committing your changes:
544
-
545
- 1. Bump version in `package.json` (PATCH for fixes, MINOR for new features)
546
- 2. Update `CHANGELOG.md`:
547
- - Add new version entry at the top
548
- - Add comparison link at the bottom: `[X.Y.Z]: https://github.com/.../compare/vPREV...vX.Y.Z`
549
- 3. Commit: `chore: bump version to X.Y.Z`
550
- 4. Create tag: `git tag -a vX.Y.Z -m "vX.Y.Z - description"`
551
- 5. Push: `git push origin main --tags`
552
-
553
- See "When to Bump Version & Create Tag" section in Git Workflow for details.
554
-
555
- ---
556
-
557
- ### Rule Documentation Format in docs/rules/
558
-
559
- Each rule should have this format in its category file under `docs/rules/`:
560
-
561
- ```markdown
562
- ### `rule-name`
563
-
564
- **What it does:** One-line description of the rule's purpose.
565
-
566
- **Why use it:** Optional context for why this rule is helpful.
567
-
568
- > **Note:** Any special notes or dependencies (optional).
569
-
570
- \`\`\`javascript
571
- // ✅ Good — description
572
- const example = "correct code";
573
-
574
- // ❌ Bad — description
575
- const example = "incorrect code";
576
- \`\`\`
577
-
578
- **Options:** (if rule has options)
579
-
580
- | Option | Type | Default | Description |
581
- |--------|------|---------|-------------|
582
- | `optionName` | `string` | `"value"` | What the option does |
583
-
584
- \`\`\`javascript
585
- // Configuration example
586
- "code-style/rule-name": ["error", { optionName: "value" }]
587
- \`\`\`
588
-
589
- ---
590
- ```
591
-
592
- ## Key Patterns & Conventions
593
-
594
- ### Source Code Access
595
- ```javascript
596
- const sourceCode = context.sourceCode || context.getSourceCode();
597
- ```
598
-
599
- ### Options with Defaults
600
- ```javascript
601
- const options = context.options[0] || {};
602
- const maxItems = options.maxItems !== undefined ? options.maxItems : 3;
603
- ```
604
-
605
- ### Getting Tokens
606
- ```javascript
607
- const openBracket = sourceCode.getFirstToken(node);
608
- const closeBracket = sourceCode.getLastToken(node);
609
- const tokenBefore = sourceCode.getTokenBefore(node);
610
- const tokenAfter = sourceCode.getTokenAfter(node);
611
- ```
612
-
613
- ### Getting Text
614
- ```javascript
615
- const text = sourceCode.getText(node);
616
- const lines = sourceCode.lines; // Array of all lines
617
- ```
618
-
619
- ### Indentation Calculation
620
- ```javascript
621
- const lineText = sourceCode.lines[node.loc.start.line - 1];
622
- const baseIndent = lineText.match(/^\s*/)[0];
623
- const itemIndent = baseIndent + " "; // 4 spaces
624
- ```
625
-
626
- ### Fixer Methods
627
- ```javascript
628
- fixer.replaceText(node, "new text")
629
- fixer.replaceTextRange([start, end], "new text")
630
- fixer.insertTextBefore(node, "text")
631
- fixer.insertTextAfter(node, "text")
632
- fixer.remove(node)
633
- fixer.removeRange([start, end])
634
- ```
635
-
636
- ### Common Node Type Checks
637
- ```javascript
638
- // Check parent type
639
- if (node.parent && node.parent.type === "Property") { }
640
-
641
- // Check for specific patterns
642
- if (node.type === "ArrowFunctionExpression") { }
643
- if (node.type === "JSXElement") { }
644
- if (node.type === "ObjectExpression") { }
645
-
646
- // React hooks detection
647
- if (/^use[A-Z]/.test(node.callee.name)) { }
648
- ```
649
-
650
- ### Skip Conditions (Common Patterns)
651
- ```javascript
652
- // Skip empty structures
653
- if (elements.length === 0) return;
654
-
655
- // Skip complex elements
656
- const hasComplexElement = elements.some((el) =>
657
- el.type === "SpreadElement" ||
658
- el.type === "ObjectExpression" ||
659
- el.type === "ArrowFunctionExpression"
660
- );
661
- if (hasComplexElement) return;
662
-
663
- // Skip specific parent contexts
664
- if (node.parent?.type === "CallExpression") return;
665
- ```
666
-
667
- ## Rule Categories
668
-
669
- Rules are organized in these categories (alphabetically sorted in src/index.js and README.md):
670
-
671
- - **Array Rules** — Rules for array formatting
672
- - `array-callback-destructure`, `array-items-per-line`, `array-objects-on-new-lines`
673
- - **Arrow Function Rules** — Arrow function syntax and style
674
- - `arrow-function-block-body`, `arrow-function-simple-jsx`, `arrow-function-simplify`, `curried-arrow-same-line`
675
- - **Call Expression Rules** — Function call formatting
676
- - `function-arguments-format`, `nested-call-closing-brackets`, `no-empty-lines-in-function-calls`, `opening-brackets-same-line`, `simple-call-single-line`, `single-argument-on-one-line`
677
- - **Class Rules** — Class and method definition formatting
678
- - `class-method-definition-format`, `class-naming-convention`
679
- - **Comment Rules** — Comment formatting
680
- - `comment-format`
681
- - **Component Rules** — React component patterns
682
- - `component-props-destructure`, `component-props-inline-type`, `folder-based-naming-convention`, `folder-structure-consistency`, `no-redundant-folder-suffix`, `svg-icon-naming-convention`
683
- - **Control Flow Rules** — if/switch/block statements
684
- - `block-statement-newlines`, `if-else-spacing`, `if-statement-format`, `multiline-if-conditions`, `no-empty-lines-in-switch-cases`, `ternary-condition-multiline`
685
- - **Function Rules** — Function declarations and params
686
- - `function-call-spacing`, `function-declaration-style`, `function-naming-convention`, `function-object-destructure`, `function-params-per-line`, `no-empty-lines-in-function-params`
687
- - **Hook Rules** — React hooks formatting
688
- - `hook-callback-format`, `hook-deps-per-line`
689
- - **Import/Export Rules** — Import/export statements
690
- - `absolute-imports-only`, `export-format`, `import-format`, `import-source-spacing`, `index-export-style`, `index-exports-only`, `inline-export-declaration`, `module-index-exports`
691
- - **JSX Rules** — JSX elements and attributes
692
- - `classname-dynamic-at-end`, `classname-multiline`, `classname-no-extra-spaces`, `classname-order`, `jsx-children-on-new-line`, `jsx-closing-bracket-spacing`, `jsx-element-child-new-line`, `jsx-logical-expression-simplify`, `jsx-parentheses-position`, `jsx-prop-naming-convention`, `jsx-simple-element-one-line`, `jsx-string-value-trim`, `jsx-ternary-format`, `no-empty-lines-in-jsx`
693
- - **Object Rules** — Object literal formatting
694
- - `no-empty-lines-in-objects`, `object-property-per-line`, `object-property-value-brace`, `object-property-value-format`, `string-property-spacing`
695
- - **React Rules** — React-specific patterns
696
- - `react-code-order`
697
- - **Spacing Rules** — General spacing rules
698
- - `assignment-value-same-line`, `member-expression-bracket-spacing`
699
- - **TypeScript Rules** — TypeScript-specific rules (TS configs only)
700
- - `enum-format`, `interface-format`, `no-inline-type-definitions`, `prop-naming-convention`, `type-annotation-spacing`, `type-format`, `typescript-definition-location`
701
- - **Variable Rules** — Variable declarations and naming
702
- - `variable-naming-convention`
703
-
704
- ## Naming Conventions
705
-
706
- - **Rule names:** kebab-case (e.g., `array-items-per-line`)
707
- - **Internal variables:** camelCase (e.g., `arrayItemsPerLine`)
708
- - **Handler functions:** end with `Handler` (e.g., `checkPatternHandler`)
709
- - **Options:** camelCase (e.g., `maxItems`, `minProperties`)
710
-
711
- ## Meta Types
712
-
713
- - `type: "layout"` - Formatting/whitespace rules (most rules)
714
- - `type: "suggestion"` - Code convention rules (naming conventions)
715
-
716
- ## Documentation Files
717
-
718
- - `README.md` - Main documentation with rule overview and links
719
- - `docs/rules/` - Detailed rule documentation (17 category files with examples and options)
720
- - `recommended-configs/<config-name>/README.md` - Config-specific documentation (references docs/rules/ for rule details)
721
- - `index.d.ts` - TypeScript types for IDE autocomplete
722
-
723
- ## Important Notes
724
-
725
- - Most rules should be auto-fixable (`fixable: "code"` or `fixable: "whitespace"` in meta)
726
- - Rules that require file creation/movement or architectural decisions may be report-only
727
- - Currently: 70 auto-fixable rules, 19 configurable rules, 9 report-only rules
728
- - Use 4-space indentation throughout
729
- - Object properties in `context.report()` must be alphabetically sorted
730
- - Keep rules self-sufficient (no dependencies on other ESLint rules)
731
- - Test with relevant test app in `_tests_/` before publishing
732
-
733
- ---
734
-
735
- ## Rule Count Locations
736
-
737
- **IMPORTANT:** When adding/removing rules, update the rule counts in ALL these locations:
738
-
739
- ### Current Counts (update these when changing rules)
740
- - **Total rules:** 79
741
- - **Auto-fixable:** 70
742
- - **Configurable:** 19 (rules with ⚙️ that have options)
743
- - **Report-only:** 9
744
-
745
- **IMPORTANT:** All counts must be uniform across ALL files. When updating:
746
- - Total rules, auto-fixable count, configurable count, and report-only count must match everywhere
747
- - The auto-fixable breakdown (code vs whitespace) in this section must match actual `grep` counts
748
- - Use the Quick Verification Commands below to verify counts before committing
749
-
750
- ### Files & Line Numbers to Update
751
-
752
- | File | Line(s) | What to Update |
753
- |------|---------|----------------|
754
- | `README.md` | ~22 | `*79 rules (70 auto-fixable, 19 configurable)*` |
755
- | `README.md` | ~30 | `**79 custom rules** (70 auto-fixable, 19 configurable)` |
756
- | `README.md` | ~39 | `70 of 79 rules support auto-fix` |
757
- | `README.md` | ~272 | `**79 rules total** — 70 with auto-fix, 19 configurable` |
758
- | `README.md` | ~409 | `70 of 79 rules support auto-fixing` |
759
- | `docs/rules/README.md` | ~3 | `**79 rules total** — 70 with auto-fix, 19 configurable` |
760
- | `AGENTS.md` | ~7 | `79 custom formatting rules (70 auto-fixable, 19 configurable, 9 report-only)` |
761
- | `AGENTS.md` | ~9 | `Contains all 79 rules` |
762
- | `AGENTS.md` | ~36 | `(70 rules in JS projects, 79 in TS projects)` |
763
- | `AGENTS.md` | ~89 | `(79 rules total)` |
764
- | `AGENTS.md` | ~675 | `all 79 rules` |
765
- | `AGENTS.md` | ~697 | `70 auto-fixable rules, 19 configurable rules, 9 report-only` |
766
- | `AGENTS.md` | Rule Count Locations section | Current Counts table |
767
- | `recommended-configs/react-ts-tw/README.md` | ~396 | `**70 auto-fixable rules** (79 total, 19 configurable, 9 report-only)` |
768
- | `recommended-configs/react/README.md` | ~286 | `**70 auto-fixable rules** (79 total, 19 configurable, 9 report-only)` |
769
-
770
- ### Quick Verification Commands
771
-
772
- ```bash
773
- # Count total rules
774
- grep -rc "^const [a-zA-Z]* = {$" src/rules/
775
-
776
- # Count auto-fixable (code)
777
- grep -rc 'fixable: "code"' src/rules/
778
-
779
- # Count auto-fixable (whitespace)
780
- grep -rc 'fixable: "whitespace"' src/rules/
781
-
782
- # Count configurable rules (rules with ⚙️ in README table)
783
- grep "| \`" README.md | grep -c "⚙️"
784
-
785
- # Find all rule count mentions (excluding CHANGELOG)
786
- grep -rn "[0-9][0-9] rules\|[0-9][0-9] auto" --include="*.md" | grep -v CHANGELOG
787
- ```
788
-
789
- ---
790
-
791
- ## Git Workflow
792
-
793
- ### Commit Message Format
794
-
795
- Follow [Conventional Commits](https://www.conventionalcommits.org/) specification:
796
-
797
- ```
798
- <type>: <subject>
799
-
800
- [optional body]
801
- ```
802
-
803
- **Types:**
804
- - `feat` - New feature or rule
805
- - `fix` - Bug fix
806
- - `docs` - Documentation only changes
807
- - `refactor` - Code change that neither fixes a bug nor adds a feature
808
- - `chore` - Maintenance tasks (deps, configs)
809
-
810
- **Subject line rules:**
811
- - Use lowercase (except proper nouns)
812
- - No period at the end
813
- - Maximum 72 characters
814
- - Use imperative mood ("add" not "added")
815
-
816
- **Examples:**
817
- ```
818
- feat: add function-declaration-style rule
819
- fix: allow relative imports in entry files
820
- docs: update options descriptions
821
- ```
822
-
823
- **Multi-feature commits:**
824
- ```
825
- feat: add function-declaration-style rule and enhancements
826
-
827
- New rule:
828
- - function-declaration-style: auto-fixes to arrow expressions
829
-
830
- Enhancements:
831
- - function-naming-convention: add auto-fix
832
- ```
833
-
834
- ---
835
-
836
- ### Versioning (SemVer)
837
-
838
- Format: `MAJOR.MINOR.PATCH` (e.g., `1.2.8`)
839
-
840
- | Change Type | Version | Examples |
841
- |-------------|---------|----------|
842
- | **PATCH** | `x.x.+1` | Bug fixes, typo corrections, doc updates |
843
- | **MINOR** | `x.+1.0` | New rules, new features, new options |
844
- | **MAJOR** | `+1.0.0` | Breaking changes, removed/renamed rules |
845
-
846
- **Decision guide:**
847
- - New rule → MINOR
848
- - Auto-fix to existing rule → MINOR
849
- - New option → MINOR
850
- - Bug fix → PATCH
851
- - Doc update only → PATCH
852
- - Change default values → MAJOR (breaking)
853
- - Rename/remove rule → MAJOR (breaking)
854
-
855
- ---
856
-
857
- ### When to Bump Version & Create Tag
858
-
859
- **IMPORTANT:** Every commit requires a version bump and tag. Follow this workflow:
860
-
861
- #### Commit Workflow (Always Bump Version)
862
- After every meaningful change:
863
- 1. Make changes and commit with appropriate message
864
- 2. Bump version in `package.json`
865
- 3. Update `CHANGELOG.md`:
866
- - Add new version entry at the top
867
- - Add comparison link at the bottom: `[X.Y.Z]: https://github.com/.../compare/vPREV...vX.Y.Z`
868
- 4. Commit version bump with descriptive message (see below)
869
- 5. Create annotated tag with descriptive message
870
- 6. Push commits and tags
871
-
872
- #### Version Bump Commit Messages
873
-
874
- **IMPORTANT:** Do NOT use generic messages like `chore: bump version to X.Y.Z`. Instead, use descriptive messages that summarize what changes are in this version.
875
-
876
- **Format:** `chore: release vX.Y.Z - brief description`
877
-
878
- **Good examples:**
879
- ```
880
- chore: release v1.7.2 - fix double comma bug in enum/interface format
881
- chore: release v1.7.1 - multiple rule fixes for destructuring and ternaries
882
- chore: release v1.6.0 - add 3 new rules and enhance ternary formatting
883
- ```
884
-
885
- **Bad examples:**
886
- ```
887
- chore: bump version to 1.7.2
888
- chore: version bump
889
- chore: v1.7.2
890
- ```
891
-
892
- This makes `git log` readable and helps understand what each version contains without checking the CHANGELOG.
893
-
894
- #### Version Bump Rules
895
- | Change Type | Version Bump | Example | GitHub Release? |
896
- |-------------|--------------|---------|-----------------|
897
- | Bug fix | PATCH (+0.0.1) | 1.5.2 → 1.5.3 | No |
898
- | Enhancement to existing rule | PATCH (+0.0.1) | 1.5.3 → 1.5.4 | No |
899
- | New rule | MINOR (+0.1.0) | 1.5.4 → 1.6.0 | **Yes** |
900
- | Breaking change | MAJOR (+1.0.0) | 1.6.0 → 2.0.0 | **Yes** |
901
- | Docs only | PATCH (+0.0.1) | 1.5.2 → 1.5.3 | No |
902
-
903
- #### MINOR/MAJOR Release Format (GitHub Releases)
904
-
905
- When bumping MINOR or MAJOR version, the CHANGELOG entry must follow this format.
906
-
907
- **IMPORTANT:** The release should contain ALL changes since the **previous RELEASE** (MINOR/MAJOR). The Version Range starts from the first version AFTER the previous release.
908
-
909
- Example: If releasing v1.7.0 and the previous release was v1.6.0:
910
- - Version Range: **v1.6.1 → v1.7.0** (starts AFTER v1.6.0)
911
- - Include changes from: v1.6.1, v1.6.2, ... v1.6.6, AND v1.7.0
912
-
913
- ```markdown
914
- ## [X.Y.0] - YYYY-MM-DD
915
-
916
- **Release Title (Brief Description of Main Features)**
917
-
918
- **Version Range:** vAfterPreviousRelease → vCurrent
919
-
920
- ### Added
921
-
922
- **New Rules (N)**
923
- - `rule-name` - Description 🔧
924
-
925
- ### Enhanced
926
-
927
- - **`rule-name`** - What was enhanced (consolidate all enhancements since last release)
928
-
929
- ### Fixed
930
-
931
- - **`rule-name`** - What was fixed (consolidate all fixes since last release)
932
-
933
- ### Stats
934
-
935
- - Total Rules: XX (was YY)
936
- - Auto-fixable: ZZ rules 🔧
937
- - Report-only: N rules
938
-
939
- **Full Changelog:** [vAfterPreviousRelease...vCurrent](https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/compare/vAfterPreviousRelease...vCurrent)
940
- ```
941
-
942
- **Required elements for MINOR/MAJOR releases:**
943
- 1. **Release title** in bold describing main changes
944
- 2. **Version Range** showing first version AFTER previous release → current version
945
- 3. **Consolidated changes** from all versions since last release
946
- 4. **Stats** section with rule counts
947
- 5. **Full Changelog** link at the end
948
-
949
- #### Example Workflow
950
- ```bash
951
- # 1. Make changes and commit
952
- git add .
953
- git commit -m "fix: handle edge case in rule-name"
954
-
955
- # 2. Bump version in package.json (1.5.2 → 1.5.3)
956
- # 3. Update CHANGELOG.md with new entry
957
-
958
- # 4. Commit version bump with descriptive message
959
- git add package.json CHANGELOG.md
960
- git commit -m "chore: release v1.5.3 - fix edge case in rule-name"
961
-
962
- # 5. Create annotated tag with descriptive message
963
- git tag -a v1.5.3 -m "v1.5.3 - Fix Edge Case in rule-name
964
-
965
- - Fixed edge case handling in rule-name
966
- - Improved error messages"
967
-
968
- # 6. Push
969
- git push origin main --tags
970
- ```
971
-
972
- ---
973
-
974
- ### Release Steps
975
-
976
- 1. **Update version in package.json**
977
- 2. **Update CHANGELOG.md:**
978
- - Add new version entry at the top
979
- - Add comparison link at the bottom: `[X.Y.Z]: https://github.com/.../compare/vPREV...vX.Y.Z`
980
- 3. **Commit version bump with descriptive message:**
981
- ```bash
982
- git commit -m "chore: release v1.2.9 - brief description of changes"
983
- ```
984
- 4. **Create annotated tag with descriptive message:**
985
- ```bash
986
- git tag -a v1.2.9 -m "v1.2.9 - Brief Description
987
-
988
- - Feature description 1
989
- - Feature description 2"
990
- ```
991
- 5. **Push (requires explicit approval):** `git push origin main --tags`
992
- 6. **Publish (requires explicit approval):** `npm publish`
993
-
994
- ---
995
-
996
- ### GitHub Releases (Grouped Tags)
997
-
998
- GitHub Releases group multiple version tags into a single release announcement. Create a release when a significant milestone is reached (new features, major enhancements).
999
-
1000
- **When to create a GitHub Release:**
1001
- - **All MINOR versions (x.Y.0)** - Every new MINOR version is a release
1002
- - **All MAJOR versions (X.0.0)** - Every new MAJOR version is a release
1003
- - Optionally after multiple PATCH versions accumulate significant changes
1004
-
1005
- **Note:** All MINOR versions (e.g., v1.7.0, v1.8.0) and MAJOR versions (e.g., v2.0.0) are considered releases and must be added to the "Current releases" list. The Version Range for a release always starts from the first version AFTER the previous release (MINOR or MAJOR) up to the current version.
1006
-
1007
- **Release format:**
1008
-
1009
- ```markdown
1010
- ## Release Title
1011
- <Short, descriptive title summarizing the main changes>
1012
-
1013
- ## Version Range
1014
- vX.X.X → vY.Y.Y
1015
-
1016
- ---
1017
-
1018
- ## What's New
1019
-
1020
- <Brief intro paragraph mentioning key highlights and rule count change>
1021
-
1022
- ### New Rules
1023
-
1024
- | Rule | Description |
1025
- |------|-------------|
1026
- | `rule-name` | What it does |
1027
-
1028
- ### Enhancements
1029
-
1030
- | Rule | Enhancement |
1031
- |------|-------------|
1032
- | `rule-name` | What was improved |
1033
-
1034
- ### New Features
1035
-
1036
- - Feature 1 description
1037
- - Feature 2 description
1038
-
1039
- ### Bug Fixes
1040
-
1041
- - Fix 1 description
1042
- - Fix 2 description
1043
-
1044
- ### Documentation
1045
-
1046
- - Doc change 1
1047
- - Doc change 2
1048
-
1049
- ## Installation
1050
-
1051
- \`\`\`bash
1052
- npm install eslint-plugin-code-style@Y.Y.Y
1053
- \`\`\`
1054
-
1055
- ## Stats
1056
-
1057
- - Total Rules: X (was Y)
1058
- - All rules are auto-fixable with `eslint --fix`
1059
-
1060
- **Full Changelog**: https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/compare/vX.X.X...vY.Y.Y
1061
- ```
1062
-
1063
- **Steps to create a GitHub Release:**
1064
-
1065
- 1. Go to repository → Releases → "Draft a new release"
1066
- 2. Choose the latest tag (e.g., `v1.3.0`)
1067
- 3. Set release title (short, descriptive)
1068
- 4. Paste the release description following the format above
1069
- 5. Update `CHANGELOG.md` with the same information
1070
- 6. Publish release
1071
-
1072
- ### CHANGELOG.md
1073
-
1074
- This project follows the [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) standard.
1075
-
1076
- **IMPORTANT:**
1077
- - The CHANGELOG must list **ALL version tags** (currently 82 tags)
1078
- - Update the CHANGELOG with every new tag/release
1079
- - Keep it in sync with changes as you work
1080
- - **Releases must match GitHub Releases content exactly**
1081
-
1082
- #### Two Types of Entries
1083
-
1084
- **1. Releases** (published to GitHub Releases)
1085
- - Have **Version Range** showing tags covered
1086
- - Full detailed sections with sub-categories
1087
- - Include **Full Changelog** link at the end
1088
- - Content must match the GitHub Release description
1089
- - **Current releases:** v1.15.0, v1.14.0, v1.13.0, v1.12.0, v1.11.0, v1.10.0, v1.9.0, v1.8.0, v1.7.0, v1.6.0, v1.5.0, v1.4.2, v1.3.0, v1.2.0, v1.1.0, v1.0.16, v1.0.14, v1.0.7, v1.0.6
1090
-
1091
- **2. Tags/PATCH versions** (between releases)
1092
- - Simpler entries with just the changes
1093
- - **NO title** (bold description line after date)
1094
- - **NO Version Range**
1095
- - **NO Full Changelog link** in the entry body
1096
- - **MUST add link reference** at bottom of CHANGELOG.md: `[X.Y.Z]: https://github.com/.../compare/vA.B.C...vX.Y.Z`
1097
- - Just `### Fixed`, `### Enhanced`, or other section headers directly
1098
-
1099
- #### When to Create a Release
1100
-
1101
- Create a release when:
1102
- - Adding new rules (MINOR version bump)
1103
- - Significant feature additions
1104
- - Major documentation overhauls
1105
- - Grouping multiple related changes together
1106
-
1107
- After creating a release:
1108
- 1. Create the GitHub Release with full description
1109
- 2. Copy the same content to CHANGELOG.md
1110
- 3. Add **Full Changelog** link at the end
1111
- 4. Ensure both match exactly
1112
-
1113
- #### Release Format
1114
-
1115
- ```markdown
1116
- ## [1.4.2] - 2026-01-30
1117
-
1118
- **New Rules, Enhanced Auto-Fix & Comprehensive Documentation**
1119
-
1120
- **Version Range:** v1.3.1 → v1.4.2
1121
-
1122
- ### Added
1123
-
1124
- **New Rules (3)**
1125
- - `rule-name` - Description 🔧
1126
-
1127
- **Feature Category**
1128
- - Feature description
1129
-
1130
- ### Enhanced
1131
-
1132
- - **`rule-name`** - What was improved
1133
- - **`rule-name`** - Another improvement
1134
-
1135
- ### Fixed
1136
-
1137
- - **`rule-name`** - What was fixed
1138
-
1139
- ### Documentation
1140
-
1141
- - What docs were updated
1142
-
1143
- ### Stats
1144
-
1145
- - Total Rules: 64 (was 61)
1146
- - Auto-fixable: 58 rules 🔧
1147
- - Report-only: 6 rules
1148
-
1149
- **Full Changelog:** [v1.3.1...v1.4.2](https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/compare/v1.3.1...v1.4.2)
1150
- ```
1151
-
1152
- #### Tag Format (PATCH versions)
1153
-
1154
- PATCH versions (x.y.+1) have a simpler format - NO title, NO version range, NO full changelog in entry:
1155
-
1156
- ```markdown
1157
- ## [1.11.2] - 2026-02-04
1158
-
1159
- ### Fixed
1160
-
1161
- - **`rule-name`** - What was fixed
1162
- - **`another-rule`** - Another fix
1163
-
1164
- ---
1165
- ```
1166
-
1167
- For version bumps with no changes:
1168
- ```markdown
1169
- ## [1.0.19] - 2026-01-11
1170
-
1171
- - Version bump
1172
-
1173
- ---
1174
- ```
1175
-
1176
- **IMPORTANT:** Even though PATCH entries don't have Full Changelog links in the body, you MUST still add the link reference at the bottom of CHANGELOG.md:
1177
- ```markdown
1178
- [1.11.2]: https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/compare/v1.11.1...v1.11.2
1179
- [1.11.1]: https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/compare/v1.11.0...v1.11.1
1180
- ```
1181
-
1182
- #### Section Types
1183
-
1184
- | Section | Use for |
1185
- |---------|---------|
1186
- | **Added** | New rules, features, configurations |
1187
- | **Changed** | Breaking changes, behavior changes |
1188
- | **Enhanced** | Improvements to existing functionality |
1189
- | **Fixed** | Bug fixes |
1190
- | **Deprecated** | Features to be removed in future |
1191
- | **Removed** | Removed features |
1192
- | **Security** | Security fixes |
1193
- | **Documentation** | Doc-only changes |
1194
- | **Stats** | Rule counts (include for releases) |
1195
-
1196
- #### Comparison Links
1197
-
1198
- At the bottom of CHANGELOG.md, maintain comparison links for **every version**:
1199
-
1200
- ```markdown
1201
- [1.4.2]: https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/compare/v1.4.1...v1.4.2
1202
- [1.4.1]: https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/compare/v1.4.0...v1.4.1
1203
- ```
1204
-
1205
- #### When to Update
1206
-
1207
- Update CHANGELOG.md when creating any new tag:
1208
- - [ ] Add new section at top: `## [X.Y.Z] - YYYY-MM-DD`
1209
- - [ ] For releases: add **Version Range**, full detailed sections, and **Full Changelog** link
1210
- - [ ] For tags: add appropriate subsections
1211
- - [ ] Add comparison link at bottom
1212
- - [ ] Separate each version with `---`
1213
-
1214
- **Tip:** Update the CHANGELOG as you make changes, not just at release time
1215
-
1216
- #### Release Checklist
1217
-
1218
- When creating a release:
1219
- - [ ] Write full release description with all sections (Added, Enhanced, Fixed, Stats, etc.)
1220
- - [ ] Create GitHub Release with the description and title
1221
- - [ ] Copy exact same content to CHANGELOG.md
1222
- - [ ] Add **Release Title** (bold text after version header)
1223
- - [ ] Add **Version Range** showing first and last tag in release
1224
- - [ ] Add **Full Changelog** link at the end: `**Full Changelog:** [vX.X.X...vY.Y.Y](compare-url)`
1225
- - [ ] Update the "Current releases" list in this file (AGENTS.md)
1226
- - [ ] Verify content matches between GitHub Release and CHANGELOG
1227
-
1228
- #### Verifying CHANGELOG
1229
-
1230
- To verify all tags are in CHANGELOG:
1231
- ```bash
1232
- # Count tags vs CHANGELOG entries
1233
- echo "Tags: $(git tag | wc -l)"
1234
- echo "CHANGELOG: $(grep -c '^## \[' CHANGELOG.md)"
1235
-
1236
- # Check for missing tags
1237
- git tag -l | sort -V > /tmp/tags.txt
1238
- grep '^## \[' CHANGELOG.md | sed 's/.*\[\([^]]*\)\].*/v\1/' | sort -V > /tmp/changelog.txt
1239
- diff /tmp/tags.txt /tmp/changelog.txt
1240
- ```
1241
-
1242
- ## Skills
1243
-
1244
- This project includes reusable skills in the `.skills/` directory following the [Agent Skills](https://agentskills.io) open standard. These work with Claude Code, Cursor, VS Code, GitHub Copilot, Gemini CLI, and other compatible agents.
1245
-
1246
- | Skill | Description |
1247
- |-------|-------------|
1248
- | `audit-docs` | Verify documentation accuracy across all files |
1249
- | `manage-rule` | Add, edit, or remove an ESLint rule with all required file updates |
1250
- | `review-config` | Review a recommended ESLint configuration |
1251
- | `test-rule` | Test an ESLint rule after creating or modifying it |
1252
- | `validate-types` | Verify TypeScript definitions match rules in src/index.js |
1253
-
1254
- See `.skills/*/skill.md` for detailed instructions.
1255
-
1256
- ---
1257
-
1258
- ## Workflows
1259
-
1260
- Reusable workflows for common tasks. Any AI agent should follow these when performing the specified task.
1261
-
1262
- ---
1263
-
1264
- ### Workflow: Test Rule
1265
-
1266
- Test an ESLint rule to verify it works correctly.
1267
-
1268
- **When to use:** After creating or modifying a rule.
1269
-
1270
- **Steps:**
1271
-
1272
- 1. **Find the rule** in `src/rules/<category>.js` and understand what it checks
1273
- 2. **Identify test app** — Use `_tests_/react/` for JS rules or `_tests_/react-ts-tw/` for TS rules
1274
- 3. **Create test cases** in the test app:
1275
- - Add code that should PASS (no violations)
1276
- - Add code that should FAIL (triggers violations)
1277
- 4. **Run the linter:**
1278
- ```bash
1279
- cd _tests_/<config-name>
1280
- npm run lint # Check for violations
1281
- npm run lint:fix # Verify auto-fix works
1282
- ```
1283
- 5. **Verify results:**
1284
- - Valid code produces no errors
1285
- - Invalid code triggers the expected error message
1286
- - Auto-fix transforms code correctly
1287
-
1288
- ---
1289
-
1290
- ### Workflow: Validate Types
1291
-
1292
- Verify TypeScript definitions match the rules in `src/index.js`.
1293
-
1294
- **When to use:** After adding new rules or before releases.
1295
-
1296
- **Steps:**
1297
-
1298
- 1. **Count rules in src/:**
1299
- ```bash
1300
- grep -rc "^const .* = {$" src/rules/
1301
- ```
1302
- Or count entries in the `rules` export object.
1303
-
1304
- 2. **Check index.d.ts:**
1305
- - Verify `RuleNames` type includes all rule names (alphabetically sorted)
1306
- - Verify `PluginRules` interface includes all rules
1307
-
1308
- 3. **Look for mismatches:**
1309
- - Rules in `src/index.js` missing from `index.d.ts`?
1310
- - Rules in `index.d.ts` that don't exist in `src/index.js`?
1311
-
1312
- 4. **Report:**
1313
- - Total rules: X
1314
- - Types match: Yes/No
1315
- - Missing types: [list]
1316
- - Extra types: [list]
1317
-
1318
- ---
1319
-
1320
- ### Workflow: Review Config
1321
-
1322
- Review a recommended ESLint configuration for consistency.
1323
-
1324
- **When to use:** After adding rules or modifying configs.
1325
-
1326
- **Arguments:** `<config-name>` (e.g., `react`, `react-ts-tw`)
1327
-
1328
- **Steps:**
1329
-
1330
- 1. **Check config file:** `recommended-configs/<config-name>/eslint.config.js`
1331
- - Does it import the plugin correctly?
1332
- - Are rules set to `"error"` (not `"off"`)?
1333
- - Are rule options valid per the rule's schema?
1334
-
1335
- 2. **Compare with test config:** `_tests_/<config-name>/eslint.config.js`
1336
- - Should have the same rules enabled
1337
- - Test config may have additional test-specific settings
1338
-
1339
- 3. **Test the config:**
1340
- ```bash
1341
- cd _tests_/<config-name>
1342
- npm run lint
1343
- ```
1344
-
1345
- 4. **Check README:** `recommended-configs/<config-name>/README.md`
1346
- - Does it list all enabled rules?
1347
- - Are rule counts accurate?
1348
-
1349
- 5. **Report:**
1350
- - Config valid: Yes/No
1351
- - Rules enabled: X
1352
- - Issues found: [list]
1353
-
1354
- ---
1355
-
1356
- ### Workflow: Audit Docs
1357
-
1358
- Verify documentation accuracy across all files.
1359
-
1360
- **When to use:** Before releases or after adding rules.
1361
-
1362
- **Steps:**
1363
-
1364
- 1. **Count actual rules:**
1365
- ```bash
1366
- grep -rc "^const .* = {$" src/rules/
1367
- ```
1368
-
1369
- 2. **Check rule count references:**
1370
- - `AGENTS.md`: "61 custom auto-fixable formatting rules"
1371
- - `README.md`: Multiple mentions of rule count
1372
- - `recommended-configs/*/README.md`: Any rule count mentions
1373
-
1374
- 3. **Verify version consistency:**
1375
- - `package.json` version matches latest tag
1376
- - No outdated version references in docs
1377
-
1378
- 4. **Check links:**
1379
- - Config paths in README exist
1380
- - Test app paths exist
1381
- - Internal markdown links work
1382
-
1383
- 5. **Report:**
1384
- - Actual rule count: X
1385
- - Documented counts match: Yes/No
1386
- - Outdated references: [list]
1387
- - Broken links: [list]