@rnzeus/eslint-plugin 0.1.2 → 0.1.4
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/README.md +149 -9
- package/dist/configs/imports.cjs +595 -0
- package/dist/configs/imports.cjs.map +1 -0
- package/dist/configs/styles.cjs +161 -0
- package/dist/configs/styles.cjs.map +1 -1
- package/dist/plugin.cjs +161 -0
- package/dist/plugin.cjs.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
# @rnzeus/eslint-plugin
|
|
1
|
+
# @rnzeus/eslint-plugin
|
|
2
2
|
|
|
3
|
-
ESLint plugin for React / React Native projects focused on **style discipline**.
|
|
3
|
+
ESLint plugin for React / React Native projects focused on **style discipline** and **FSD import boundaries**.
|
|
4
4
|
|
|
5
5
|
This plugin is designed to solve real-world problems that appear during refactoring:
|
|
6
6
|
- unused styles left in `*.styles.ts` files
|
|
7
7
|
- inconsistent style naming
|
|
8
8
|
- unsafe dynamic style usage
|
|
9
9
|
- passing whole `styles` objects to components
|
|
10
|
+
- architectural erosion via unconstrained cross-slice imports (FSD)
|
|
10
11
|
|
|
11
12
|
The plugin is **static**, **runtime-free**, and optimized for **ESLint Flat Config (ESLint v9+)**.
|
|
12
13
|
|
|
@@ -20,9 +21,10 @@ Ensures that all styles declared in `*.styles.ts(x)` files are actually used in
|
|
|
20
21
|
**What it checks:**
|
|
21
22
|
- detects unused style keys
|
|
22
23
|
- forbids passing the whole `styles` object (`styles={styles}`)
|
|
23
|
-
- supports arrays: `style={[styles.foo, styles.bar]}`
|
|
24
|
+
- supports arrays: `style={[styles.foo, condition && styles.bar]}`
|
|
24
25
|
- supports conditional styles
|
|
25
26
|
- supports dynamic styles **only with explicit directive comments**
|
|
27
|
+
- supports additional “style-like” props (configurable): e.g. `contentContainerStyle`
|
|
26
28
|
|
|
27
29
|
**File convention (required):**
|
|
28
30
|
```
|
|
@@ -46,12 +48,48 @@ item_name: {}
|
|
|
46
48
|
|
|
47
49
|
---
|
|
48
50
|
|
|
51
|
+
### ✅ `rnzeus/slice-imports`
|
|
52
|
+
Enforces **FSD import boundaries** for alias imports:
|
|
53
|
+
- **layer order**: lower layers cannot import higher layers
|
|
54
|
+
- **same-slice imports** must be **relative**
|
|
55
|
+
- **cross-slice** imports inside the same layer are allowed only via `@x/<currentSlice>`
|
|
56
|
+
|
|
57
|
+
This rule validates only alias imports starting with `@` (relative imports are ignored).
|
|
58
|
+
|
|
59
|
+
**Assumed structure (defaults):**
|
|
60
|
+
- `srcRoot`: `"src"`
|
|
61
|
+
- `layers`: `shared -> entities -> features -> widgets -> pages -> app`
|
|
62
|
+
|
|
63
|
+
**Examples (same slice must be relative):**
|
|
64
|
+
```ts
|
|
65
|
+
// file: src/features/auth/ui/Login.tsx
|
|
66
|
+
|
|
67
|
+
// ❌ bad (same slice via alias)
|
|
68
|
+
import { submit } from "@features/auth/model/submit";
|
|
69
|
+
|
|
70
|
+
// ✅ good
|
|
71
|
+
import { submit } from "../model/submit";
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Examples (cross-slice via @x):**
|
|
75
|
+
```ts
|
|
76
|
+
// file: src/entities/product/ui/ProductCard.tsx
|
|
77
|
+
|
|
78
|
+
// ❌ bad (direct cross-slice import inside same layer)
|
|
79
|
+
import { getCartTotal } from "@entities/cart/model/getCartTotal";
|
|
80
|
+
|
|
81
|
+
// ✅ good (cart exposes cross-slice API specifically for product slice)
|
|
82
|
+
import { getCartTotal } from "@entities/cart/@x/product";
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
49
87
|
## Installation
|
|
50
88
|
|
|
51
89
|
```bash
|
|
52
|
-
npm install -D @rnzeus/eslint-plugin
|
|
90
|
+
npm install -D @rnzeus/eslint-plugin
|
|
53
91
|
# or
|
|
54
|
-
yarn add -D @rnzeus/eslint-plugin
|
|
92
|
+
yarn add -D @rnzeus/eslint-plugin
|
|
55
93
|
```
|
|
56
94
|
|
|
57
95
|
> Peer dependency: `eslint >= 9`
|
|
@@ -63,10 +101,11 @@ yarn add -D @rnzeus/eslint-plugin-style
|
|
|
63
101
|
This plugin exports **ready-to-use flat config presets**.
|
|
64
102
|
No `.default` access and no manual plugin wiring is required.
|
|
65
103
|
|
|
66
|
-
### Import
|
|
104
|
+
### Import presets
|
|
67
105
|
|
|
68
106
|
```js
|
|
69
|
-
const styles = require(
|
|
107
|
+
const styles = require("@rnzeus/eslint-plugin/configs/styles");
|
|
108
|
+
const imports = require("@rnzeus/eslint-plugin/configs/imports");
|
|
70
109
|
```
|
|
71
110
|
|
|
72
111
|
### Minimal setup
|
|
@@ -74,6 +113,7 @@ const styles = require('@rnzeus/eslint-plugin-style/configs/styles');
|
|
|
74
113
|
```js
|
|
75
114
|
module.exports = [
|
|
76
115
|
...styles,
|
|
116
|
+
...imports,
|
|
77
117
|
];
|
|
78
118
|
```
|
|
79
119
|
|
|
@@ -81,11 +121,71 @@ module.exports = [
|
|
|
81
121
|
|
|
82
122
|
```js
|
|
83
123
|
const rnfsd = require('@rnzeus/themis/eslint/rnfsd');
|
|
84
|
-
const styles = require(
|
|
124
|
+
const styles = require("@rnzeus/eslint-plugin/configs/styles");
|
|
125
|
+
const imports = require("@rnzeus/eslint-plugin/configs/imports");
|
|
85
126
|
|
|
86
127
|
module.exports = [
|
|
87
128
|
...rnfsd,
|
|
88
129
|
...styles,
|
|
130
|
+
...imports,
|
|
131
|
+
];
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Configure `styles-usage` style props
|
|
137
|
+
|
|
138
|
+
By default, `rnzeus/styles-usage` tracks style usage from these JSX props:
|
|
139
|
+
|
|
140
|
+
- `style`
|
|
141
|
+
- `contentContainerStyle`
|
|
142
|
+
|
|
143
|
+
You can extend or override this list via rule options.
|
|
144
|
+
|
|
145
|
+
### Merge (default)
|
|
146
|
+
|
|
147
|
+
`type: "merge"` is the default behavior:
|
|
148
|
+
- takes plugin defaults
|
|
149
|
+
- adds your `styleProps`
|
|
150
|
+
- de-duplicates
|
|
151
|
+
|
|
152
|
+
Example (add FlatList prop):
|
|
153
|
+
|
|
154
|
+
```js
|
|
155
|
+
module.exports = [
|
|
156
|
+
...styles,
|
|
157
|
+
{
|
|
158
|
+
rules: {
|
|
159
|
+
"rnzeus/styles-usage": [
|
|
160
|
+
"error",
|
|
161
|
+
{
|
|
162
|
+
styleProps: ["columnWrapperStyle"],
|
|
163
|
+
type: "merge", // optional (default)
|
|
164
|
+
},
|
|
165
|
+
],
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
];
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Override
|
|
172
|
+
|
|
173
|
+
`type: "override"` ignores plugin defaults and uses **only** your `styleProps`.
|
|
174
|
+
|
|
175
|
+
```js
|
|
176
|
+
module.exports = [
|
|
177
|
+
...styles,
|
|
178
|
+
{
|
|
179
|
+
rules: {
|
|
180
|
+
"rnzeus/styles-usage": [
|
|
181
|
+
"error",
|
|
182
|
+
{
|
|
183
|
+
styleProps: ["style"],
|
|
184
|
+
type: "override",
|
|
185
|
+
},
|
|
186
|
+
],
|
|
187
|
+
},
|
|
188
|
+
},
|
|
89
189
|
];
|
|
90
190
|
```
|
|
91
191
|
|
|
@@ -119,6 +219,34 @@ This makes dynamic styles:
|
|
|
119
219
|
|
|
120
220
|
---
|
|
121
221
|
|
|
222
|
+
## Configure `slice-imports`
|
|
223
|
+
|
|
224
|
+
`rnzeus/slice-imports` supports these options:
|
|
225
|
+
- `srcRoot` (default: `"src"`): marker folder used to detect layer/slice from absolute filename
|
|
226
|
+
- `layers` (default: `["shared","entities","features","widgets","pages","app"]`): allowed layers in dependency order
|
|
227
|
+
|
|
228
|
+
Example (custom `srcRoot` and layers):
|
|
229
|
+
```js
|
|
230
|
+
const imports = require("@rnzeus/eslint-plugin/configs/imports");
|
|
231
|
+
|
|
232
|
+
module.exports = [
|
|
233
|
+
...imports,
|
|
234
|
+
{
|
|
235
|
+
rules: {
|
|
236
|
+
"rnzeus/slice-imports": [
|
|
237
|
+
"error",
|
|
238
|
+
{
|
|
239
|
+
srcRoot: "src",
|
|
240
|
+
layers: ["shared", "entities", "features", "widgets", "pages", "app"],
|
|
241
|
+
},
|
|
242
|
+
],
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
];
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
122
250
|
## Rules
|
|
123
251
|
|
|
124
252
|
### `rnzeus/styles-usage`
|
|
@@ -126,10 +254,11 @@ This makes dynamic styles:
|
|
|
126
254
|
| Check | Status |
|
|
127
255
|
|-----|------|
|
|
128
256
|
Unused styles | ✅ |
|
|
129
|
-
Whole styles object | ❌ |
|
|
257
|
+
Whole styles object (`styles={styles}`) | ❌ |
|
|
130
258
|
Array styles | ✅ |
|
|
131
259
|
Conditional styles | ✅ |
|
|
132
260
|
Dynamic styles | ⚠️ (directive required) |
|
|
261
|
+
Extra style props | ✅ (configurable) |
|
|
133
262
|
|
|
134
263
|
---
|
|
135
264
|
|
|
@@ -148,6 +277,17 @@ Regex used:
|
|
|
148
277
|
|
|
149
278
|
---
|
|
150
279
|
|
|
280
|
+
### `rnzeus/slice-imports`
|
|
281
|
+
|
|
282
|
+
| Check | Status |
|
|
283
|
+
|-----|------|
|
|
284
|
+
Layer order (lower cannot import higher) | ✅ |
|
|
285
|
+
Same slice must be relative | ✅ |
|
|
286
|
+
Cross-slice via `@x/<currentSlice>` | ✅ |
|
|
287
|
+
Relative imports | Ignored |
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
151
291
|
## Philosophy
|
|
152
292
|
|
|
153
293
|
This plugin intentionally:
|