eslint-plugin-code-style 1.2.0 → 1.2.7
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 +5 -5
- package/README.md +169 -35
- package/index.d.ts +8 -0
- package/index.js +1333 -94
- package/package.json +2 -2
package/AGENTS.md
CHANGED
|
@@ -4,9 +4,9 @@ Instructions for AI coding agents working with this codebase.
|
|
|
4
4
|
|
|
5
5
|
## Project Overview
|
|
6
6
|
|
|
7
|
-
**eslint-plugin-code-style** is an ESLint plugin providing
|
|
7
|
+
**eslint-plugin-code-style** is an ESLint plugin providing 60 custom auto-fixable formatting rules for React/JSX projects. It's designed for ESLint v9+ flat config system.
|
|
8
8
|
|
|
9
|
-
- **Main entry:** `index.js` - Contains all
|
|
9
|
+
- **Main entry:** `index.js` - Contains all 60 rules in a single file
|
|
10
10
|
- **Type definitions:** `index.d.ts` - TypeScript declarations for IDE support
|
|
11
11
|
- **Recommended configs:** `recommended-configs/` - Ready-to-use ESLint configurations
|
|
12
12
|
- **Test apps:** `_tests_/` - Sample apps for testing rules
|
|
@@ -44,7 +44,7 @@ index.js
|
|
|
44
44
|
├── imports (fs, path, url)
|
|
45
45
|
├── Rule 1 definition (const ruleName = { create(), meta: {} })
|
|
46
46
|
├── Rule 2 definition
|
|
47
|
-
├── ... (
|
|
47
|
+
├── ... (60 rules total)
|
|
48
48
|
└── export default { meta: {}, rules: {} }
|
|
49
49
|
```
|
|
50
50
|
|
|
@@ -209,7 +209,7 @@ Rules are organized in these categories (alphabetically sorted in index.js and R
|
|
|
209
209
|
- **Function Rules:** `function-call-spacing`, `function-naming-convention`, `function-object-destructure`, `function-params-per-line`, `no-empty-lines-in-function-params`
|
|
210
210
|
- **Hook Rules:** `hook-callback-format`, `hook-deps-per-line`
|
|
211
211
|
- **Import/Export Rules:** `absolute-imports-only`, `export-format`, `import-format`, `import-source-spacing`, `index-export-style`, `module-index-exports`
|
|
212
|
-
- **JSX Rules:** `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`
|
|
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
213
|
- **Object Rules:** `no-empty-lines-in-objects`, `object-property-per-line`, `object-property-value-brace`, `object-property-value-format`, `string-property-spacing`
|
|
214
214
|
- **React Rules:** `react-code-order`
|
|
215
215
|
- **Spacing Rules:** `assignment-value-same-line`, `member-expression-bracket-spacing`
|
|
@@ -230,7 +230,7 @@ Rules are organized in these categories (alphabetically sorted in index.js and R
|
|
|
230
230
|
|
|
231
231
|
## Documentation Files
|
|
232
232
|
|
|
233
|
-
- `README.md` - Main documentation with all
|
|
233
|
+
- `README.md` - Main documentation with all 60 rules
|
|
234
234
|
- `recommended-configs/<config-name>/README.md` - Config-specific documentation (references main README for rule details)
|
|
235
235
|
- `index.d.ts` - TypeScript types for IDE autocomplete
|
|
236
236
|
|
package/README.md
CHANGED
|
@@ -7,9 +7,10 @@
|
|
|
7
7
|
[](https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/blob/main/LICENSE)
|
|
8
8
|
|
|
9
9
|
[](https://eslint.org/)
|
|
10
|
-
[](https://nodejs.org/)
|
|
11
11
|
[](https://react.dev/)
|
|
12
|
-
[](https://www.typescriptlang.org/)
|
|
13
|
+
[](https://tailwindcss.com/)
|
|
13
14
|
|
|
14
15
|
[](https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/stargazers)
|
|
15
16
|
[](https://github.com/Mohamed-Elhawary/eslint-plugin-code-style/issues)
|
|
@@ -18,7 +19,7 @@
|
|
|
18
19
|
|
|
19
20
|
**A powerful ESLint plugin for enforcing consistent code formatting and style rules in React/JSX projects.**
|
|
20
21
|
|
|
21
|
-
*
|
|
22
|
+
*60 auto-fixable rules to keep your codebase clean and consistent*
|
|
22
23
|
|
|
23
24
|
</div>
|
|
24
25
|
|
|
@@ -26,7 +27,7 @@
|
|
|
26
27
|
|
|
27
28
|
## 🎯 Why This Plugin?
|
|
28
29
|
|
|
29
|
-
This plugin provides **
|
|
30
|
+
This plugin provides **60 custom auto-fixable rules** for code formatting. Built for **ESLint v9 flat configs**.
|
|
30
31
|
|
|
31
32
|
> **Note:** ESLint [deprecated 79 formatting rules](https://eslint.org/blog/2023/10/deprecating-formatting-rules/) in v8.53.0. Our recommended configs use `@stylistic/eslint-plugin` as the replacement for these deprecated rules.
|
|
32
33
|
|
|
@@ -35,7 +36,7 @@ This plugin provides **56 custom auto-fixable rules** for code formatting. Built
|
|
|
35
36
|
- **Works alongside existing tools** — Complements ESLint's built-in rules and packages like eslint-plugin-react, eslint-plugin-import, etc
|
|
36
37
|
- **Self-sufficient rules** — Each rule handles complete formatting independently
|
|
37
38
|
- **Consistency at scale** — Reduces code-style differences between team members by enforcing uniform formatting across your projects
|
|
38
|
-
- **Fully automated** — All
|
|
39
|
+
- **Fully automated** — All 60 rules support auto-fix, eliminating manual style reviews
|
|
39
40
|
|
|
40
41
|
When combined with ESLint's native rules and other popular plugins, this package helps create a complete code style solution that keeps your codebase clean and consistent.
|
|
41
42
|
|
|
@@ -59,7 +60,7 @@ We provide **ready-to-use ESLint flat configuration files** that combine `eslint
|
|
|
59
60
|
|
|
60
61
|
### 💡 Why Use These Configs?
|
|
61
62
|
|
|
62
|
-
- **Complete Coverage** — Combines ESLint built-in rules, third-party plugins, and all
|
|
63
|
+
- **Complete Coverage** — Combines ESLint built-in rules, third-party plugins, and all 60 code-style rules
|
|
63
64
|
- **Ready-to-Use** — Copy the config file and start linting immediately
|
|
64
65
|
- **Battle-Tested** — These configurations have been refined through real-world usage
|
|
65
66
|
- **Fully Documented** — Each config includes detailed instructions and explanations
|
|
@@ -96,7 +97,7 @@ We provide **ready-to-use ESLint flat configuration files** that combine `eslint
|
|
|
96
97
|
<td width="50%">
|
|
97
98
|
|
|
98
99
|
### 🔧 Auto-Fixable Rules
|
|
99
|
-
All **
|
|
100
|
+
All **60 rules** support automatic fixing with `eslint --fix`. No manual code changes needed.
|
|
100
101
|
|
|
101
102
|
</td>
|
|
102
103
|
<td width="50%">
|
|
@@ -142,7 +143,7 @@ yarn add eslint-plugin-code-style -D
|
|
|
142
143
|
| Dependency | Version |
|
|
143
144
|
|------------|---------|
|
|
144
145
|
| **ESLint** | `>= 9.0.0` |
|
|
145
|
-
| **Node.js** | `>=
|
|
146
|
+
| **Node.js** | `>= 20.0.0` |
|
|
146
147
|
|
|
147
148
|
<br />
|
|
148
149
|
|
|
@@ -180,18 +181,24 @@ eslint src/ --fix
|
|
|
180
181
|
|
|
181
182
|
```javascript
|
|
182
183
|
rules: {
|
|
184
|
+
"code-style/absolute-imports-only": "error",
|
|
183
185
|
"code-style/array-items-per-line": "error",
|
|
184
186
|
"code-style/array-objects-on-new-lines": "error",
|
|
185
187
|
"code-style/arrow-function-block-body": "error",
|
|
186
188
|
"code-style/arrow-function-simple-jsx": "error",
|
|
187
189
|
"code-style/arrow-function-simplify": "error",
|
|
188
|
-
"code-style/curried-arrow-same-line": "error",
|
|
189
190
|
"code-style/assignment-value-same-line": "error",
|
|
190
191
|
"code-style/block-statement-newlines": "error",
|
|
192
|
+
"code-style/classname-dynamic-at-end": "error",
|
|
193
|
+
"code-style/classname-multiline": "error",
|
|
194
|
+
"code-style/classname-no-extra-spaces": "error",
|
|
191
195
|
"code-style/comment-format": "error",
|
|
192
196
|
"code-style/component-props-destructure": "error",
|
|
193
|
-
"code-style/react-code-order": "error",
|
|
194
197
|
"code-style/component-props-inline-type": "error",
|
|
198
|
+
"code-style/curried-arrow-same-line": "error",
|
|
199
|
+
"code-style/enum-format": "error",
|
|
200
|
+
"code-style/export-format": "error",
|
|
201
|
+
"code-style/function-arguments-format": "error",
|
|
195
202
|
"code-style/function-call-spacing": "error",
|
|
196
203
|
"code-style/function-naming-convention": "error",
|
|
197
204
|
"code-style/function-object-destructure": "error",
|
|
@@ -199,13 +206,10 @@ rules: {
|
|
|
199
206
|
"code-style/hook-callback-format": "error",
|
|
200
207
|
"code-style/hook-deps-per-line": "error",
|
|
201
208
|
"code-style/if-statement-format": "error",
|
|
202
|
-
"code-style/multiline-if-conditions": "error",
|
|
203
|
-
"code-style/absolute-imports-only": "error",
|
|
204
|
-
"code-style/export-format": "error",
|
|
205
209
|
"code-style/import-format": "error",
|
|
206
210
|
"code-style/import-source-spacing": "error",
|
|
207
211
|
"code-style/index-export-style": "error",
|
|
208
|
-
"code-style/
|
|
212
|
+
"code-style/interface-format": "error",
|
|
209
213
|
"code-style/jsx-children-on-new-line": "error",
|
|
210
214
|
"code-style/jsx-closing-bracket-spacing": "error",
|
|
211
215
|
"code-style/jsx-element-child-new-line": "error",
|
|
@@ -216,7 +220,8 @@ rules: {
|
|
|
216
220
|
"code-style/jsx-string-value-trim": "error",
|
|
217
221
|
"code-style/jsx-ternary-format": "error",
|
|
218
222
|
"code-style/member-expression-bracket-spacing": "error",
|
|
219
|
-
"code-style/
|
|
223
|
+
"code-style/module-index-exports": "error",
|
|
224
|
+
"code-style/multiline-if-conditions": "error",
|
|
220
225
|
"code-style/nested-call-closing-brackets": "error",
|
|
221
226
|
"code-style/no-empty-lines-in-function-calls": "error",
|
|
222
227
|
"code-style/no-empty-lines-in-function-params": "error",
|
|
@@ -227,15 +232,14 @@ rules: {
|
|
|
227
232
|
"code-style/object-property-value-brace": "error",
|
|
228
233
|
"code-style/object-property-value-format": "error",
|
|
229
234
|
"code-style/opening-brackets-same-line": "error",
|
|
235
|
+
"code-style/react-code-order": "error",
|
|
230
236
|
"code-style/simple-call-single-line": "error",
|
|
231
237
|
"code-style/single-argument-on-one-line": "error",
|
|
232
238
|
"code-style/string-property-spacing": "error",
|
|
233
|
-
"code-style/variable-naming-convention": "error",
|
|
234
|
-
"code-style/enum-format": "error",
|
|
235
|
-
"code-style/interface-format": "error",
|
|
236
239
|
"code-style/type-annotation-spacing": "error",
|
|
237
240
|
"code-style/type-format": "error",
|
|
238
241
|
"code-style/typescript-definition-location": "error",
|
|
242
|
+
"code-style/variable-naming-convention": "error",
|
|
239
243
|
}
|
|
240
244
|
```
|
|
241
245
|
|
|
@@ -245,7 +249,7 @@ rules: {
|
|
|
245
249
|
|
|
246
250
|
## 📖 Rules Summary
|
|
247
251
|
|
|
248
|
-
> All **
|
|
252
|
+
> All **60 rules** are auto-fixable. See detailed examples for each rule in the [Rules Reference](#-rules-reference) section below.
|
|
249
253
|
>
|
|
250
254
|
> Rules marked with ⚙️ support customization options (e.g., extending default folder lists).
|
|
251
255
|
|
|
@@ -264,7 +268,7 @@ rules: {
|
|
|
264
268
|
| `nested-call-closing-brackets` | Chain closing brackets on same line: `}));` not scattered across lines |
|
|
265
269
|
| `no-empty-lines-in-function-calls` | No empty lines between arguments or after `(`/before `)` |
|
|
266
270
|
| `opening-brackets-same-line` | Opening `{`, `[`, or `(` on same line as function call, not on new line |
|
|
267
|
-
| `simple-call-single-line` | Collapse simple
|
|
271
|
+
| `simple-call-single-line` | Collapse simple arrow function calls to single line (including callbacks with params and optional chaining) |
|
|
268
272
|
| `single-argument-on-one-line` | Single simple argument stays on one line: `fn(x)` not expanded |
|
|
269
273
|
| **Comment Rules** | |
|
|
270
274
|
| `comment-format` | Space after `//`, space inside `/* */`, convert single-line blocks to `//`, no blank lines between file-top comments |
|
|
@@ -293,6 +297,9 @@ rules: {
|
|
|
293
297
|
| `index-export-style` | Index files: no blank lines, enforce shorthand or import-export style; Regular files: require blank lines between exports (default: shorthand) ⚙️ |
|
|
294
298
|
| `module-index-exports` | Index files must export all folder contents (files and subfolders) ⚙️ |
|
|
295
299
|
| **JSX Rules** | |
|
|
300
|
+
| `classname-dynamic-at-end` | Dynamic expressions (`${className}`) must be at the end of class strings (JSX and variables) |
|
|
301
|
+
| `classname-multiline` | Long className strings broken into multiple lines, one class per line; uses `"..."` in JSX (no expressions) or `` `...` `` (with expressions/variables) ⚙️ |
|
|
302
|
+
| `classname-no-extra-spaces` | No extra/leading/trailing spaces in class strings (JSX, variables, and objects) |
|
|
296
303
|
| `jsx-children-on-new-line` | Multiple JSX children: each on own line with proper indentation |
|
|
297
304
|
| `jsx-closing-bracket-spacing` | No space before `>` or `/>` in JSX tags |
|
|
298
305
|
| `jsx-element-child-new-line` | Nested JSX elements on new lines; text/expression children can stay inline |
|
|
@@ -321,7 +328,7 @@ rules: {
|
|
|
321
328
|
| **React Rules** | |
|
|
322
329
|
| `react-code-order` | Enforce consistent ordering in components and hooks: props destructure → refs → state → redux → router → context → custom hooks → derived → memo → callback → handlers → effects → return |
|
|
323
330
|
| **Variable Rules** | |
|
|
324
|
-
| `variable-naming-convention` | camelCase for variables
|
|
331
|
+
| `variable-naming-convention` | camelCase for all variables and constants, PascalCase for components, `use` prefix for hooks |
|
|
325
332
|
|
|
326
333
|
<br />
|
|
327
334
|
|
|
@@ -721,17 +728,18 @@ items.map(
|
|
|
721
728
|
|
|
722
729
|
### `simple-call-single-line`
|
|
723
730
|
|
|
724
|
-
**What it does:** Collapses simple function calls with an arrow function
|
|
731
|
+
**What it does:** Collapses simple function calls with an arrow function onto one line when the result fits within 120 characters. Handles:
|
|
732
|
+
- Zero-param callbacks: `lazy(() => import("./Page"))`
|
|
733
|
+
- Callbacks with params and simple expression bodies: `.find((f) => f.code === x)`
|
|
734
|
+
- Optional chaining: `.find(...)?.symbol`
|
|
725
735
|
|
|
726
|
-
**Why use it:** Common patterns like `lazy(() => import(...))` don't need multiline formatting. Single line is cleaner.
|
|
736
|
+
**Why use it:** Common patterns like `lazy(() => import(...))` and `.find((item) => item.id === id)` don't need multiline formatting. Single line is cleaner.
|
|
727
737
|
|
|
728
738
|
```javascript
|
|
729
739
|
// ✅ Good — simple patterns on one line
|
|
730
740
|
const Page = lazy(() => import("./Page"));
|
|
731
|
-
const Modal = lazy(() => import("./Modal"));
|
|
732
741
|
setTimeout(() => callback(), 100);
|
|
733
|
-
|
|
734
|
-
items.filter(() => isValid(item));
|
|
742
|
+
const symbol = items.find(({ code }) => code === currency)?.symbol;
|
|
735
743
|
|
|
736
744
|
// ✅ Good — complex callbacks stay multiline
|
|
737
745
|
const Page = lazy(() => {
|
|
@@ -744,10 +752,11 @@ const Page = lazy(
|
|
|
744
752
|
() => import("./Page"),
|
|
745
753
|
);
|
|
746
754
|
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
)
|
|
755
|
+
const symbol = items.find(({ code }) =>
|
|
756
|
+
code === currency)?.symbol;
|
|
757
|
+
|
|
758
|
+
const symbol = items.find(({ code }) => code === currency)?.
|
|
759
|
+
symbol;
|
|
751
760
|
```
|
|
752
761
|
|
|
753
762
|
---
|
|
@@ -1637,6 +1646,132 @@ import { Button } from "@/components/Button/Button"; // Avoid this!
|
|
|
1637
1646
|
|
|
1638
1647
|
## ⚛️ JSX Rules
|
|
1639
1648
|
|
|
1649
|
+
### `classname-dynamic-at-end`
|
|
1650
|
+
|
|
1651
|
+
**What it does:** Enforces that dynamic expressions in className template literals are placed at the end, after all static class names. Also applies to variables with names containing "class" or "Class".
|
|
1652
|
+
|
|
1653
|
+
**Why use it:** When using Tailwind CSS with `tailwindcss/classnames-order`, static classes are automatically sorted. However, dynamic expressions like `${className}` or `${styles.button}` can break the visual order if placed in the middle. This rule ensures dynamic parts come last for consistent, readable class strings.
|
|
1654
|
+
|
|
1655
|
+
```javascript
|
|
1656
|
+
// ✅ Good — dynamic expressions at the end (JSX)
|
|
1657
|
+
<div className={`flex items-center gap-4 ${className}`} />
|
|
1658
|
+
|
|
1659
|
+
// ✅ Good — dynamic expressions at the end (variable)
|
|
1660
|
+
const buttonClasses = `flex items-center ${className} ${styles.button}`;
|
|
1661
|
+
|
|
1662
|
+
// ❌ Bad — dynamic expression at the beginning
|
|
1663
|
+
<div className={`${className} flex items-center gap-4`} />
|
|
1664
|
+
|
|
1665
|
+
// ❌ Bad — dynamic expression in the middle (variable)
|
|
1666
|
+
const buttonClasses = `flex ${className} items-center gap-4`;
|
|
1667
|
+
```
|
|
1668
|
+
|
|
1669
|
+
---
|
|
1670
|
+
|
|
1671
|
+
### `classname-multiline`
|
|
1672
|
+
|
|
1673
|
+
**What it does:** Enforces that long className strings are broken into multiple lines, with each class on its own line. Triggers when either the class count exceeds `maxClassCount` (default: 3) or the string length exceeds `maxLength` (default: 80). Also enforces:
|
|
1674
|
+
- JSX `className` with no dynamic expressions uses `"..."` string literal format
|
|
1675
|
+
- JSX `className` with dynamic expressions uses `` {`...`} `` template literal format
|
|
1676
|
+
- Variables/object properties use `` `...` `` template literal for multiline (JS requires it)
|
|
1677
|
+
- No empty lines between classes or before/after the quotes
|
|
1678
|
+
- Under-threshold multiline classes are collapsed back to a single line
|
|
1679
|
+
|
|
1680
|
+
Applies to JSX `className` attributes, variables with class-related names, and object properties within class-related objects.
|
|
1681
|
+
|
|
1682
|
+
**Why use it:** Long single-line class strings are hard to read and review. Breaking them into one class per line makes diffs cleaner and classes easier to scan. Using string literals when no expressions are needed keeps the code simpler.
|
|
1683
|
+
|
|
1684
|
+
```javascript
|
|
1685
|
+
// ✅ Good — JSX with no expressions uses "..." format
|
|
1686
|
+
<div
|
|
1687
|
+
className="
|
|
1688
|
+
flex
|
|
1689
|
+
items-center
|
|
1690
|
+
justify-center
|
|
1691
|
+
rounded-lg
|
|
1692
|
+
p-4
|
|
1693
|
+
"
|
|
1694
|
+
/>
|
|
1695
|
+
|
|
1696
|
+
// ✅ Good — JSX with expressions uses {`...`} format
|
|
1697
|
+
<div
|
|
1698
|
+
className={`
|
|
1699
|
+
flex
|
|
1700
|
+
items-center
|
|
1701
|
+
justify-center
|
|
1702
|
+
${className}
|
|
1703
|
+
`}
|
|
1704
|
+
/>
|
|
1705
|
+
|
|
1706
|
+
// ✅ Good — variable multiline uses template literal
|
|
1707
|
+
const buttonClasses = `
|
|
1708
|
+
flex
|
|
1709
|
+
items-center
|
|
1710
|
+
justify-center
|
|
1711
|
+
${className}
|
|
1712
|
+
`;
|
|
1713
|
+
|
|
1714
|
+
// ✅ Good — object property multiline uses template literal
|
|
1715
|
+
const variantClasses = {
|
|
1716
|
+
danger: `
|
|
1717
|
+
flex
|
|
1718
|
+
items-center
|
|
1719
|
+
justify-center
|
|
1720
|
+
bg-red-500
|
|
1721
|
+
`,
|
|
1722
|
+
};
|
|
1723
|
+
|
|
1724
|
+
// ✅ Good — short class strings stay on one line
|
|
1725
|
+
<div className="flex items-center" />
|
|
1726
|
+
|
|
1727
|
+
// ❌ Bad — too many classes on one line
|
|
1728
|
+
<div className="flex items-center justify-center rounded-lg p-4 font-bold" />
|
|
1729
|
+
|
|
1730
|
+
// ❌ Bad — using template literal in JSX when no expressions
|
|
1731
|
+
<div className={`
|
|
1732
|
+
flex
|
|
1733
|
+
items-center
|
|
1734
|
+
justify-center
|
|
1735
|
+
rounded-lg
|
|
1736
|
+
`} />
|
|
1737
|
+
|
|
1738
|
+
// ❌ Bad — empty lines between classes
|
|
1739
|
+
<div className="
|
|
1740
|
+
flex
|
|
1741
|
+
|
|
1742
|
+
items-center
|
|
1743
|
+
justify-center
|
|
1744
|
+
" />
|
|
1745
|
+
```
|
|
1746
|
+
|
|
1747
|
+
---
|
|
1748
|
+
|
|
1749
|
+
### `classname-no-extra-spaces`
|
|
1750
|
+
|
|
1751
|
+
**What it does:** Removes multiple consecutive spaces and leading/trailing spaces inside className values. Applies to:
|
|
1752
|
+
- JSX `className` attributes (string literals and template literals)
|
|
1753
|
+
- Variables with names containing "class" (e.g., `buttonClasses`, `variantClasses`)
|
|
1754
|
+
- Object properties within class-related objects
|
|
1755
|
+
|
|
1756
|
+
**Why use it:** Extra spaces between class names are usually unintentional and can cause issues. This rule normalizes spacing and removes unnecessary whitespace.
|
|
1757
|
+
|
|
1758
|
+
```javascript
|
|
1759
|
+
// ✅ Good — single space between classes
|
|
1760
|
+
<div className="flex items-center gap-4 rounded-lg" />
|
|
1761
|
+
const buttonClasses = `flex items-center ${className}`;
|
|
1762
|
+
const variantClasses = { primary: "bg-blue-500 text-white" };
|
|
1763
|
+
|
|
1764
|
+
// ❌ Bad — multiple consecutive spaces
|
|
1765
|
+
<div className="flex items-center gap-4" />
|
|
1766
|
+
const buttonClasses = `flex items-center`;
|
|
1767
|
+
const variantClasses = { primary: "bg-blue-500 text-white" };
|
|
1768
|
+
|
|
1769
|
+
// ❌ Bad — leading/trailing spaces in template literal
|
|
1770
|
+
const buttonClasses = ` flex items-center ${className} `;
|
|
1771
|
+
```
|
|
1772
|
+
|
|
1773
|
+
---
|
|
1774
|
+
|
|
1640
1775
|
### `jsx-children-on-new-line`
|
|
1641
1776
|
|
|
1642
1777
|
**What it does:** When a JSX element has multiple children, ensures each child is on its own line with proper indentation.
|
|
@@ -2782,8 +2917,7 @@ const YetAnotherBad = ({ title }) => {
|
|
|
2782
2917
|
### `variable-naming-convention`
|
|
2783
2918
|
|
|
2784
2919
|
**What it does:** Enforces naming conventions for variables:
|
|
2785
|
-
- **camelCase** for
|
|
2786
|
-
- **UPPER_CASE** for constants (primitive values)
|
|
2920
|
+
- **camelCase** for all variables and constants
|
|
2787
2921
|
- **PascalCase** for React components and classes
|
|
2788
2922
|
- **camelCase with `use` prefix** for hooks
|
|
2789
2923
|
|
|
@@ -2793,14 +2927,14 @@ const YetAnotherBad = ({ title }) => {
|
|
|
2793
2927
|
// ✅ Good — correct conventions
|
|
2794
2928
|
const userName = "John"; // camelCase for variables
|
|
2795
2929
|
const itemCount = 42; // camelCase for variables
|
|
2796
|
-
const
|
|
2797
|
-
const
|
|
2930
|
+
const maxRetries = 3; // camelCase for constants
|
|
2931
|
+
const apiBaseUrl = "/api"; // camelCase for constants
|
|
2798
2932
|
const UserProfile = () => <div />; // PascalCase for components
|
|
2799
2933
|
const useAuth = () => {}; // camelCase with use prefix for hooks
|
|
2800
2934
|
|
|
2801
2935
|
// ❌ Bad — wrong conventions
|
|
2802
2936
|
const user_name = "John"; // snake_case
|
|
2803
|
-
const
|
|
2937
|
+
const MAX_RETRIES = 3; // should be camelCase
|
|
2804
2938
|
const userProfile = () => <div />; // should be PascalCase
|
|
2805
2939
|
const UseAuth = () => {}; // hooks should be camelCase
|
|
2806
2940
|
```
|
package/index.d.ts
CHANGED
|
@@ -29,6 +29,10 @@ export type RuleNames =
|
|
|
29
29
|
| "code-style/import-format"
|
|
30
30
|
| "code-style/import-source-spacing"
|
|
31
31
|
| "code-style/index-export-style"
|
|
32
|
+
| "code-style/classname-dynamic-at-end"
|
|
33
|
+
| "code-style/classname-multiline"
|
|
34
|
+
| "code-style/classname-no-extra-spaces"
|
|
35
|
+
| "code-style/classname-order"
|
|
32
36
|
| "code-style/jsx-children-on-new-line"
|
|
33
37
|
| "code-style/jsx-closing-bracket-spacing"
|
|
34
38
|
| "code-style/jsx-element-child-new-line"
|
|
@@ -106,6 +110,10 @@ interface PluginRules {
|
|
|
106
110
|
"import-format": Rule.RuleModule;
|
|
107
111
|
"import-source-spacing": Rule.RuleModule;
|
|
108
112
|
"index-export-style": Rule.RuleModule;
|
|
113
|
+
"classname-dynamic-at-end": Rule.RuleModule;
|
|
114
|
+
"classname-multiline": Rule.RuleModule;
|
|
115
|
+
"classname-no-extra-spaces": Rule.RuleModule;
|
|
116
|
+
"classname-order": Rule.RuleModule;
|
|
109
117
|
"jsx-children-on-new-line": Rule.RuleModule;
|
|
110
118
|
"jsx-closing-bracket-spacing": Rule.RuleModule;
|
|
111
119
|
"jsx-element-child-new-line": Rule.RuleModule;
|