eslint-plugin-code-style 1.2.8 → 1.3.3

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.
Files changed (4) hide show
  1. package/AGENTS.md +457 -23
  2. package/README.md +1 -1
  3. package/index.js +13 -2
  4. package/package.json +1 -1
package/AGENTS.md CHANGED
@@ -111,15 +111,113 @@ const ruleName = {
111
111
  };
112
112
  ```
113
113
 
114
- ### Adding a New Rule
114
+ ### Adding a New Rule — Complete Checklist
115
115
 
116
- 1. Add the rule definition (const) following the pattern above
117
- 2. Add to the `rules` object in the default export (keep alphabetical within categories)
118
- 3. Update `index.d.ts` to add the rule name to the `RuleNames` type
119
- 4. Update `README.md`:
120
- - Add to the Rules Summary table
121
- - Add detailed description with examples
122
- 5. Add to relevant recommended configs in `recommended-configs/`
116
+ When creating a new rule, ALL of the following files must be updated:
117
+
118
+ #### 1. `index.js` Rule Implementation
119
+ - [ ] Add JSDoc comment block with the standard format (see Rule Implementation Pattern above)
120
+ - [ ] Include: Description, Options (if any), Good examples, Bad examples
121
+ - [ ] Add `const ruleName = { create(), meta: {} }` definition
122
+ - [ ] Add to `rules` object in default export (keep alphabetical order)
123
+ - [ ] Update the rule count in any comments if present
124
+
125
+ #### 2. `index.d.ts` — TypeScript Types
126
+ - [ ] Add rule name to `RuleNames` type union (alphabetically sorted)
127
+ - [ ] Add rule to `PluginRules` interface (alphabetically sorted)
128
+
129
+ #### 3. `AGENTS.md` — Agent Instructions
130
+ - [ ] Update rule count in "Project Overview" section (e.g., "61 custom auto-fixable formatting rules")
131
+ - [ ] Update rule count in "Code Structure" section
132
+ - [ ] Add rule to its category in "[Rule Categories](#rule-categories)" section (see list below for all categories)
133
+ - [ ] Update rule count in "Documentation Files" section
134
+
135
+ #### 4. `README.md` — Main Documentation
136
+ - [ ] Update rule count in badges/header section
137
+ - [ ] Update rule count in "Why This Plugin?" section
138
+ - [ ] Update rule count in "Key Features" section
139
+ - [ ] Update rule count in "Auto-Fixable Rules" section
140
+ - [ ] Add rule to `rules: {}` example in "Quick Start" section
141
+ - [ ] Add rule to "Rules Summary" table (with description)
142
+ - [ ] Add detailed rule documentation with:
143
+ - "What it does" description
144
+ - Code examples (Good ✅ and Bad ❌)
145
+ - Options table (if rule has options)
146
+ - Configuration example (if rule has options)
147
+
148
+ #### 5. Config Files — Add Rule to Configs
149
+ - [ ] `recommended-configs/react/eslint.config.js`
150
+ - [ ] `recommended-configs/react-ts-tw/eslint.config.js`
151
+ - [ ] `_tests_/react/eslint.config.js`
152
+ - [ ] `_tests_/react-ts-tw/eslint.config.js`
153
+
154
+ #### 6. Config READMEs (if rule count changed)
155
+ - [ ] `recommended-configs/react/README.md` — Update any rule counts
156
+ - [ ] `recommended-configs/react-ts-tw/README.md` — Update any rule counts
157
+
158
+ ---
159
+
160
+ ### Editing an Existing Rule — Checklist
161
+
162
+ When modifying an existing rule, check if these need updates:
163
+
164
+ #### If changing rule behavior:
165
+ - [ ] Update JSDoc in `index.js` (Good/Bad examples)
166
+ - [ ] Update `README.md` rule documentation (examples, description)
167
+ - [ ] Test in `_tests_/` apps with `npm run lint` and `npm run lint:fix`
168
+
169
+ #### If adding new options:
170
+ - [ ] Add option to `schema` in rule's `meta` object
171
+ - [ ] Add option handling in `create()` function
172
+ - [ ] Update JSDoc Options section in `index.js`
173
+ - [ ] Update README.md options table for the rule
174
+ - [ ] Add configuration example in README.md
175
+
176
+ #### If adding auto-fix to rule that didn't have it:
177
+ - [ ] Add `fixable: "code"` to rule's `meta` object
178
+ - [ ] Add `fix()` function in `context.report()`
179
+
180
+ #### If changing default values:
181
+ - [ ] Update JSDoc in `index.js`
182
+ - [ ] Update README.md options table
183
+ - [ ] Consider if this is a MAJOR version bump (breaking change)
184
+
185
+ ---
186
+
187
+ ### Rule Documentation Format in README.md
188
+
189
+ Each rule should have this format in the Rules Reference section:
190
+
191
+ ```markdown
192
+ ### `rule-name`
193
+
194
+ **What it does:** One-line description of the rule's purpose.
195
+
196
+ **Why use it:** Optional context for why this rule is helpful.
197
+
198
+ > **Note:** Any special notes or dependencies (optional).
199
+
200
+ \`\`\`javascript
201
+ // ✅ Good — description
202
+ const example = "correct code";
203
+
204
+ // ❌ Bad — description
205
+ const example = "incorrect code";
206
+ \`\`\`
207
+
208
+ **Options:** (if rule has options)
209
+
210
+ | Option | Type | Default | Description |
211
+ |--------|------|---------|-------------|
212
+ | `optionName` | `string` | `"value"` | What the option does |
213
+
214
+ \`\`\`javascript
215
+ // Configuration example
216
+ "code-style/rule-name": ["error", { optionName: "value" }]
217
+ \`\`\`
218
+
219
+ ---
220
+ ```
123
221
 
124
222
  ## Key Patterns & Conventions
125
223
 
@@ -200,21 +298,36 @@ if (node.parent?.type === "CallExpression") return;
200
298
 
201
299
  Rules are organized in these categories (alphabetically sorted in index.js and README.md):
202
300
 
203
- - **Array Rules:** `array-items-per-line`, `array-objects-on-new-lines`
204
- - **Arrow Function Rules:** `arrow-function-block-body`, `arrow-function-simple-jsx`, `arrow-function-simplify`, `curried-arrow-same-line`
205
- - **Call Expression Rules:** `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`
206
- - **Comment Rules:** `comment-format`
207
- - **Component Rules:** `component-props-destructure`, `component-props-inline-type`
208
- - **Control Flow Rules:** `block-statement-newlines`, `if-statement-format`, `multiline-if-conditions`, `no-empty-lines-in-switch-cases`
209
- - **Function Rules:** `function-call-spacing`, `function-declaration-style`, `function-naming-convention`, `function-object-destructure`, `function-params-per-line`, `no-empty-lines-in-function-params`
210
- - **Hook Rules:** `hook-callback-format`, `hook-deps-per-line`
211
- - **Import/Export Rules:** `absolute-imports-only`, `export-format`, `import-format`, `import-source-spacing`, `index-export-style`, `module-index-exports`
212
- - **JSX Rules:** `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`
213
- - **Object Rules:** `no-empty-lines-in-objects`, `object-property-per-line`, `object-property-value-brace`, `object-property-value-format`, `string-property-spacing`
214
- - **React Rules:** `react-code-order`
215
- - **Spacing Rules:** `assignment-value-same-line`, `member-expression-bracket-spacing`
216
- - **TypeScript Rules:** `enum-format`, `interface-format`, `type-annotation-spacing`, `type-format`, `typescript-definition-location`
217
- - **Variable Rules:** `variable-naming-convention`
301
+ - **Array Rules** — Rules for array formatting
302
+ - `array-items-per-line`, `array-objects-on-new-lines`
303
+ - **Arrow Function Rules** Arrow function syntax and style
304
+ - `arrow-function-block-body`, `arrow-function-simple-jsx`, `arrow-function-simplify`, `curried-arrow-same-line`
305
+ - **Call Expression Rules** Function call formatting
306
+ - `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`
307
+ - **Comment Rules** Comment formatting
308
+ - `comment-format`
309
+ - **Component Rules** React component patterns
310
+ - `component-props-destructure`, `component-props-inline-type`
311
+ - **Control Flow Rules** if/switch/block statements
312
+ - `block-statement-newlines`, `if-statement-format`, `multiline-if-conditions`, `no-empty-lines-in-switch-cases`
313
+ - **Function Rules** Function declarations and params
314
+ - `function-call-spacing`, `function-declaration-style`, `function-naming-convention`, `function-object-destructure`, `function-params-per-line`, `no-empty-lines-in-function-params`
315
+ - **Hook Rules** — React hooks formatting
316
+ - `hook-callback-format`, `hook-deps-per-line`
317
+ - **Import/Export Rules** — Import/export statements
318
+ - `absolute-imports-only`, `export-format`, `import-format`, `import-source-spacing`, `index-export-style`, `module-index-exports`
319
+ - **JSX Rules** — JSX elements and attributes
320
+ - `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`
321
+ - **Object Rules** — Object literal formatting
322
+ - `no-empty-lines-in-objects`, `object-property-per-line`, `object-property-value-brace`, `object-property-value-format`, `string-property-spacing`
323
+ - **React Rules** — React-specific patterns
324
+ - `react-code-order`
325
+ - **Spacing Rules** — General spacing rules
326
+ - `assignment-value-same-line`, `member-expression-bracket-spacing`
327
+ - **TypeScript Rules** — TypeScript-specific rules (TS configs only)
328
+ - `enum-format`, `interface-format`, `type-annotation-spacing`, `type-format`, `typescript-definition-location`
329
+ - **Variable Rules** — Variable declarations and naming
330
+ - `variable-naming-convention`
218
331
 
219
332
  ## Naming Conventions
220
333
 
@@ -241,3 +354,324 @@ Rules are organized in these categories (alphabetically sorted in index.js and R
241
354
  - Object properties in `context.report()` must be alphabetically sorted
242
355
  - Keep rules self-sufficient (no dependencies on other ESLint rules)
243
356
  - Test with relevant test app in `_tests_/` before publishing
357
+
358
+ ## Git Workflow
359
+
360
+ ### Commit Message Format
361
+
362
+ Follow [Conventional Commits](https://www.conventionalcommits.org/) specification:
363
+
364
+ ```
365
+ <type>: <subject>
366
+
367
+ [optional body]
368
+ ```
369
+
370
+ **Types:**
371
+ - `feat` - New feature or rule
372
+ - `fix` - Bug fix
373
+ - `docs` - Documentation only changes
374
+ - `refactor` - Code change that neither fixes a bug nor adds a feature
375
+ - `chore` - Maintenance tasks (deps, configs)
376
+
377
+ **Subject line rules:**
378
+ - Use lowercase (except proper nouns)
379
+ - No period at the end
380
+ - Maximum 72 characters
381
+ - Use imperative mood ("add" not "added")
382
+
383
+ **Examples:**
384
+ ```
385
+ feat: add function-declaration-style rule
386
+ fix: allow relative imports in entry files
387
+ docs: update options descriptions
388
+ ```
389
+
390
+ **Multi-feature commits:**
391
+ ```
392
+ feat: add function-declaration-style rule and enhancements
393
+
394
+ New rule:
395
+ - function-declaration-style: auto-fixes to arrow expressions
396
+
397
+ Enhancements:
398
+ - function-naming-convention: add auto-fix
399
+ ```
400
+
401
+ ---
402
+
403
+ ### Versioning (SemVer)
404
+
405
+ Format: `MAJOR.MINOR.PATCH` (e.g., `1.2.8`)
406
+
407
+ | Change Type | Version | Examples |
408
+ |-------------|---------|----------|
409
+ | **PATCH** | `x.x.+1` | Bug fixes, typo corrections, doc updates |
410
+ | **MINOR** | `x.+1.0` | New rules, new features, new options |
411
+ | **MAJOR** | `+1.0.0` | Breaking changes, removed/renamed rules |
412
+
413
+ **Decision guide:**
414
+ - New rule → MINOR
415
+ - Auto-fix to existing rule → MINOR
416
+ - New option → MINOR
417
+ - Bug fix → PATCH
418
+ - Doc update only → PATCH
419
+ - Change default values → MAJOR (breaking)
420
+ - Rename/remove rule → MAJOR (breaking)
421
+
422
+ ---
423
+
424
+ ### Release Steps
425
+
426
+ 1. **Update version in package.json**
427
+ 2. **Commit changes:** `git commit -m "feat: description"`
428
+ 3. **Create annotated tag:**
429
+ ```bash
430
+ git tag -a v1.2.9 -m "v1.2.9
431
+
432
+ - Feature description 1
433
+ - Feature description 2"
434
+ ```
435
+ 4. **Push (requires explicit approval):** `git push origin HEAD && git push origin v1.2.9`
436
+ 5. **Publish (requires explicit approval):** `npm publish`
437
+
438
+ ---
439
+
440
+ ### GitHub Releases (Grouped Tags)
441
+
442
+ GitHub Releases group multiple version tags into a single release announcement. Create a release when a significant milestone is reached (new features, major enhancements).
443
+
444
+ **When to create a GitHub Release:**
445
+ - After multiple PATCH/MINOR versions accumulate significant changes
446
+ - When a new major feature is complete
447
+ - At logical milestones (e.g., v1.2.0 → v1.3.0)
448
+
449
+ **Release format:**
450
+
451
+ ```markdown
452
+ ## Release Title
453
+ <Short, descriptive title summarizing the main changes>
454
+
455
+ ## Version Range
456
+ vX.X.X → vY.Y.Y
457
+
458
+ ---
459
+
460
+ ## What's New
461
+
462
+ <Brief intro paragraph mentioning key highlights and rule count change>
463
+
464
+ ### New Rules
465
+
466
+ | Rule | Description |
467
+ |------|-------------|
468
+ | `rule-name` | What it does |
469
+
470
+ ### Enhancements
471
+
472
+ | Rule | Enhancement |
473
+ |------|-------------|
474
+ | `rule-name` | What was improved |
475
+
476
+ ### New Features
477
+
478
+ - Feature 1 description
479
+ - Feature 2 description
480
+
481
+ ### Bug Fixes
482
+
483
+ - Fix 1 description
484
+ - Fix 2 description
485
+
486
+ ### Documentation
487
+
488
+ - Doc change 1
489
+ - Doc change 2
490
+
491
+ ## Installation
492
+
493
+ \`\`\`bash
494
+ npm install eslint-plugin-code-style@Y.Y.Y
495
+ \`\`\`
496
+
497
+ ## Stats
498
+
499
+ - Total Rules: X (was Y)
500
+ - All rules are auto-fixable with `eslint --fix`
501
+
502
+ **Full Changelog**: https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/compare/vX.X.X...vY.Y.Y
503
+ ```
504
+
505
+ **Steps to create a GitHub Release:**
506
+
507
+ 1. Go to repository → Releases → "Draft a new release"
508
+ 2. Choose the latest tag (e.g., `v1.3.0`)
509
+ 3. Set release title (short, descriptive)
510
+ 4. Paste the release description following the format above
511
+ 5. Update `CHANGELOG.md` with the same information
512
+ 6. Publish release
513
+
514
+ **CHANGELOG.md:**
515
+
516
+ All releases are documented in `CHANGELOG.md` at the project root. Update this file whenever creating a GitHub Release.
517
+
518
+ Each release entry in CHANGELOG.md must include a **Full Changelog** link at the end:
519
+
520
+ ```markdown
521
+ **Full Changelog:** https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/compare/vFIRST...vLAST
522
+ ```
523
+
524
+ Where:
525
+ - `vFIRST` = First version tag in the release range (the tag after the last tag of the previous release)
526
+ - `vLAST` = Last version tag in the release range (current release)
527
+
528
+ Example: For release 1.2.0 with version range v1.1.10 → v1.2.0:
529
+ ```markdown
530
+ **Full Changelog:** https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/compare/v1.1.10...v1.2.0
531
+ ```
532
+
533
+ ## Skills
534
+
535
+ 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.
536
+
537
+ | Skill | Description |
538
+ |-------|-------------|
539
+ | `test-rule` | Test an ESLint rule after creating or modifying it |
540
+ | `validate-types` | Verify TypeScript definitions match rules in index.js |
541
+ | `review-config` | Review a recommended ESLint configuration |
542
+ | `audit-docs` | Verify documentation accuracy across all files |
543
+
544
+ See `.skills/*/SKILL.md` for detailed instructions.
545
+
546
+ ---
547
+
548
+ ## Workflows
549
+
550
+ Reusable workflows for common tasks. Any AI agent should follow these when performing the specified task.
551
+
552
+ ---
553
+
554
+ ### Workflow: Test Rule
555
+
556
+ Test an ESLint rule to verify it works correctly.
557
+
558
+ **When to use:** After creating or modifying a rule.
559
+
560
+ **Steps:**
561
+
562
+ 1. **Find the rule** in `index.js` and understand what it checks
563
+ 2. **Identify test app** — Use `_tests_/react/` for JS rules or `_tests_/react-ts-tw/` for TS rules
564
+ 3. **Create test cases** in the test app:
565
+ - Add code that should PASS (no violations)
566
+ - Add code that should FAIL (triggers violations)
567
+ 4. **Run the linter:**
568
+ ```bash
569
+ cd _tests_/<config-name>
570
+ npm run lint # Check for violations
571
+ npm run lint:fix # Verify auto-fix works
572
+ ```
573
+ 5. **Verify results:**
574
+ - Valid code produces no errors
575
+ - Invalid code triggers the expected error message
576
+ - Auto-fix transforms code correctly
577
+
578
+ ---
579
+
580
+ ### Workflow: Validate Types
581
+
582
+ Verify TypeScript definitions match the rules in `index.js`.
583
+
584
+ **When to use:** After adding new rules or before releases.
585
+
586
+ **Steps:**
587
+
588
+ 1. **Count rules in index.js:**
589
+ ```bash
590
+ grep -c "^const .* = {$" index.js
591
+ ```
592
+ Or count entries in the `rules` export object.
593
+
594
+ 2. **Check index.d.ts:**
595
+ - Verify `RuleNames` type includes all rule names (alphabetically sorted)
596
+ - Verify `PluginRules` interface includes all rules
597
+
598
+ 3. **Look for mismatches:**
599
+ - Rules in `index.js` missing from `index.d.ts`?
600
+ - Rules in `index.d.ts` that don't exist in `index.js`?
601
+
602
+ 4. **Report:**
603
+ - Total rules: X
604
+ - Types match: Yes/No
605
+ - Missing types: [list]
606
+ - Extra types: [list]
607
+
608
+ ---
609
+
610
+ ### Workflow: Review Config
611
+
612
+ Review a recommended ESLint configuration for consistency.
613
+
614
+ **When to use:** After adding rules or modifying configs.
615
+
616
+ **Arguments:** `<config-name>` (e.g., `react`, `react-ts-tw`)
617
+
618
+ **Steps:**
619
+
620
+ 1. **Check config file:** `recommended-configs/<config-name>/eslint.config.js`
621
+ - Does it import the plugin correctly?
622
+ - Are rules set to `"error"` (not `"off"`)?
623
+ - Are rule options valid per the rule's schema?
624
+
625
+ 2. **Compare with test config:** `_tests_/<config-name>/eslint.config.js`
626
+ - Should have the same rules enabled
627
+ - Test config may have additional test-specific settings
628
+
629
+ 3. **Test the config:**
630
+ ```bash
631
+ cd _tests_/<config-name>
632
+ npm run lint
633
+ ```
634
+
635
+ 4. **Check README:** `recommended-configs/<config-name>/README.md`
636
+ - Does it list all enabled rules?
637
+ - Are rule counts accurate?
638
+
639
+ 5. **Report:**
640
+ - Config valid: Yes/No
641
+ - Rules enabled: X
642
+ - Issues found: [list]
643
+
644
+ ---
645
+
646
+ ### Workflow: Audit Docs
647
+
648
+ Verify documentation accuracy across all files.
649
+
650
+ **When to use:** Before releases or after adding rules.
651
+
652
+ **Steps:**
653
+
654
+ 1. **Count actual rules:**
655
+ ```bash
656
+ grep -c "^const .* = {$" index.js
657
+ ```
658
+
659
+ 2. **Check rule count references:**
660
+ - `AGENTS.md`: "61 custom auto-fixable formatting rules"
661
+ - `README.md`: Multiple mentions of rule count
662
+ - `recommended-configs/*/README.md`: Any rule count mentions
663
+
664
+ 3. **Verify version consistency:**
665
+ - `package.json` version matches latest tag
666
+ - No outdated version references in docs
667
+
668
+ 4. **Check links:**
669
+ - Config paths in README exist
670
+ - Test app paths exist
671
+ - Internal markdown links work
672
+
673
+ 5. **Report:**
674
+ - Actual rule count: X
675
+ - Documented counts match: Yes/No
676
+ - Outdated references: [list]
677
+ - Broken links: [list]
package/README.md CHANGED
@@ -248,7 +248,7 @@ rules: {
248
248
 
249
249
  ---
250
250
 
251
- ## 📖 Rules Summary
251
+ ## 📖 Rules Categories
252
252
 
253
253
  > All **61 rules** are auto-fixable. See detailed examples for each rule in the [Rules Reference](#-rules-reference) section below.
254
254
  >
package/index.js CHANGED
@@ -1874,15 +1874,26 @@ const functionNamingConvention = {
1874
1874
  if (!variable) return fixer.replaceText(identifierNode, newName);
1875
1875
 
1876
1876
  const fixes = [];
1877
+ const fixedRanges = new Set();
1878
+
1879
+ // Helper to add fix only if not already fixed (avoid overlapping fixes)
1880
+ const addFixHandler = (nodeToFix) => {
1881
+ const rangeKey = `${nodeToFix.range[0]}-${nodeToFix.range[1]}`;
1882
+
1883
+ if (!fixedRanges.has(rangeKey)) {
1884
+ fixedRanges.add(rangeKey);
1885
+ fixes.push(fixer.replaceText(nodeToFix, newName));
1886
+ }
1887
+ };
1877
1888
 
1878
1889
  // Fix the definition
1879
1890
  variable.defs.forEach((def) => {
1880
- fixes.push(fixer.replaceText(def.name, newName));
1891
+ addFixHandler(def.name);
1881
1892
  });
1882
1893
 
1883
1894
  // Fix all references
1884
1895
  variable.references.forEach((ref) => {
1885
- fixes.push(fixer.replaceText(ref.identifier, newName));
1896
+ addFixHandler(ref.identifier);
1886
1897
  });
1887
1898
 
1888
1899
  return fixes;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-code-style",
3
- "version": "1.2.8",
3
+ "version": "1.3.3",
4
4
  "description": "A custom ESLint plugin for enforcing consistent code formatting and style rules in React/JSX projects",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",