@itstandu/code-style 0.1.0
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/.prettierignore +54 -0
- package/README.md +262 -0
- package/eslint/angular.js +36 -0
- package/eslint/base.js +73 -0
- package/eslint/javascript.js +5 -0
- package/eslint/nest.js +12 -0
- package/eslint/next.js +10 -0
- package/eslint/node.js +18 -0
- package/eslint/react.js +101 -0
- package/eslint/recommended.js +29 -0
- package/eslint/strict.js +35 -0
- package/eslint/typescript.js +36 -0
- package/eslint/vue.js +101 -0
- package/index.js +13 -0
- package/package.json +80 -0
- package/prettier/index.cjs +21 -0
package/.prettierignore
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Dependencies
|
|
2
|
+
node_modules/
|
|
3
|
+
.pnp
|
|
4
|
+
.pnp.js
|
|
5
|
+
|
|
6
|
+
# Build outputs
|
|
7
|
+
dist/
|
|
8
|
+
build/
|
|
9
|
+
.next/
|
|
10
|
+
out/
|
|
11
|
+
.output/
|
|
12
|
+
.turbo/
|
|
13
|
+
.cache/
|
|
14
|
+
|
|
15
|
+
# Logs
|
|
16
|
+
*.log
|
|
17
|
+
npm-debug.log*
|
|
18
|
+
yarn-debug.log*
|
|
19
|
+
yarn-error.log*
|
|
20
|
+
pnpm-debug.log*
|
|
21
|
+
lerna-debug.log*
|
|
22
|
+
|
|
23
|
+
# Environment files
|
|
24
|
+
.env
|
|
25
|
+
.env.local
|
|
26
|
+
.env.*.local
|
|
27
|
+
|
|
28
|
+
# Test coverage
|
|
29
|
+
coverage/
|
|
30
|
+
.nyc_output/
|
|
31
|
+
|
|
32
|
+
# Lock files (optional - some teams prefer to format them)
|
|
33
|
+
# package-lock.json
|
|
34
|
+
# yarn.lock
|
|
35
|
+
# pnpm-lock.yaml
|
|
36
|
+
|
|
37
|
+
# Generated files
|
|
38
|
+
*.min.js
|
|
39
|
+
*.min.css
|
|
40
|
+
|
|
41
|
+
# OS files
|
|
42
|
+
.DS_Store
|
|
43
|
+
Thumbs.db
|
|
44
|
+
|
|
45
|
+
# IDE files
|
|
46
|
+
.vscode/
|
|
47
|
+
.idea/
|
|
48
|
+
*.swp
|
|
49
|
+
*.swo
|
|
50
|
+
*~
|
|
51
|
+
|
|
52
|
+
# Temporary files
|
|
53
|
+
*.tmp
|
|
54
|
+
*.temp
|
package/README.md
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
# @itstandu/code-style
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@itstandu/code-style)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
Production-ready shared ESLint + Prettier configuration library for JavaScript and TypeScript projects.
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- **ESLint v9** (Flat Config)
|
|
11
|
+
- **Prettier v3** with Tailwind CSS support
|
|
12
|
+
- Supports **JavaScript** and **TypeScript**
|
|
13
|
+
- Framework presets: **React**, **Next.js**, **Vue**, **Angular**, **NestJS**
|
|
14
|
+
- **Node.js** backend support
|
|
15
|
+
- Stable import sorting with `eslint-plugin-simple-import-sort`
|
|
16
|
+
- Auto-fix friendly rules
|
|
17
|
+
- **Complete Prettier coverage** - All formatting handled by Prettier, no conflicts with ESLint
|
|
18
|
+
- No style rules in ESLint (Prettier handles all formatting)
|
|
19
|
+
- Architecture rules via `eslint-plugin-boundaries` (opt-in only)
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
Choose your package manager:
|
|
24
|
+
|
|
25
|
+
### npm
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install -D @itstandu/code-style
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### pnpm
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pnpm add -D @itstandu/code-style
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### yarn
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
yarn add -D @itstandu/code-style
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### bun
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
bun add -d @itstandu/code-style
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Note:** You do NOT need to install `eslint`, `prettier`, or any plugins separately. This package includes all dependencies.
|
|
50
|
+
|
|
51
|
+
## Usage
|
|
52
|
+
|
|
53
|
+
### ESLint
|
|
54
|
+
|
|
55
|
+
Create `eslint.config.js` (or `eslint.config.mjs`) in your project root:
|
|
56
|
+
|
|
57
|
+
#### Base Preset (Minimal)
|
|
58
|
+
|
|
59
|
+
```javascript
|
|
60
|
+
const codeStyle = require('@itstandu/code-style')
|
|
61
|
+
|
|
62
|
+
module.exports = [
|
|
63
|
+
codeStyle.base,
|
|
64
|
+
codeStyle.typescript,
|
|
65
|
+
codeStyle.node
|
|
66
|
+
]
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
#### Recommended Preset (Better Safety)
|
|
70
|
+
|
|
71
|
+
```javascript
|
|
72
|
+
const codeStyle = require('@itstandu/code-style')
|
|
73
|
+
|
|
74
|
+
module.exports = [
|
|
75
|
+
codeStyle.recommended,
|
|
76
|
+
codeStyle.typescript,
|
|
77
|
+
codeStyle.node
|
|
78
|
+
]
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
#### Strict Preset (Opt-in, includes boundaries)
|
|
82
|
+
|
|
83
|
+
```javascript
|
|
84
|
+
const codeStyle = require('@itstandu/code-style')
|
|
85
|
+
|
|
86
|
+
module.exports = [
|
|
87
|
+
codeStyle.strict,
|
|
88
|
+
codeStyle.typescript,
|
|
89
|
+
codeStyle.node
|
|
90
|
+
]
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Framework Presets
|
|
94
|
+
|
|
95
|
+
#### React
|
|
96
|
+
|
|
97
|
+
```javascript
|
|
98
|
+
const codeStyle = require('@itstandu/code-style')
|
|
99
|
+
|
|
100
|
+
module.exports = [
|
|
101
|
+
codeStyle.recommended,
|
|
102
|
+
codeStyle.typescript,
|
|
103
|
+
codeStyle.react
|
|
104
|
+
]
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
#### Next.js
|
|
108
|
+
|
|
109
|
+
```javascript
|
|
110
|
+
const codeStyle = require('@itstandu/code-style')
|
|
111
|
+
|
|
112
|
+
module.exports = [
|
|
113
|
+
codeStyle.recommended,
|
|
114
|
+
codeStyle.typescript,
|
|
115
|
+
codeStyle.next
|
|
116
|
+
]
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
#### Vue
|
|
120
|
+
|
|
121
|
+
```javascript
|
|
122
|
+
const codeStyle = require('@itstandu/code-style')
|
|
123
|
+
|
|
124
|
+
module.exports = [
|
|
125
|
+
codeStyle.recommended,
|
|
126
|
+
codeStyle.vue
|
|
127
|
+
]
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
#### Angular
|
|
131
|
+
|
|
132
|
+
```javascript
|
|
133
|
+
const codeStyle = require('@itstandu/code-style')
|
|
134
|
+
|
|
135
|
+
module.exports = [
|
|
136
|
+
codeStyle.recommended,
|
|
137
|
+
codeStyle.typescript,
|
|
138
|
+
codeStyle.angular
|
|
139
|
+
]
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
#### NestJS
|
|
143
|
+
|
|
144
|
+
```javascript
|
|
145
|
+
const codeStyle = require('@itstandu/code-style')
|
|
146
|
+
|
|
147
|
+
module.exports = [
|
|
148
|
+
codeStyle.recommended,
|
|
149
|
+
codeStyle.typescript,
|
|
150
|
+
codeStyle.nest
|
|
151
|
+
]
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Prettier
|
|
155
|
+
|
|
156
|
+
Create `.prettierrc.js` (or `.prettierrc.cjs`) in your project root:
|
|
157
|
+
|
|
158
|
+
```javascript
|
|
159
|
+
module.exports = require('@itstandu/code-style/prettier')
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Or add to `package.json`:
|
|
163
|
+
|
|
164
|
+
```json
|
|
165
|
+
{
|
|
166
|
+
"prettier": "@itstandu/code-style/prettier"
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
**Optional:** Copy `.prettierignore` from this package to your project root to ignore common files:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
cp node_modules/@itstandu/code-style/.prettierignore .prettierignore
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Ensuring Consistent Formatting
|
|
177
|
+
|
|
178
|
+
This package ensures **100% Prettier coverage** for all formatting:
|
|
179
|
+
|
|
180
|
+
- ✅ All ESLint formatting rules are disabled via `eslint-config-prettier`
|
|
181
|
+
- ✅ React/JSX formatting rules are disabled (Prettier handles JSX)
|
|
182
|
+
- ✅ Vue template formatting rules are disabled (Prettier handles Vue)
|
|
183
|
+
- ✅ Comprehensive Prettier options cover all formatting scenarios
|
|
184
|
+
- ✅ Tailwind CSS class sorting is automatic (via `prettier-plugin-tailwindcss`)
|
|
185
|
+
|
|
186
|
+
### Import Sorting Philosophy
|
|
187
|
+
|
|
188
|
+
**Critical Principle:**
|
|
189
|
+
|
|
190
|
+
> **Sort import → ESLint. Prettier TUYỆT ĐỐI không làm việc này.**
|
|
191
|
+
|
|
192
|
+
**Why ESLint, not Prettier?**
|
|
193
|
+
|
|
194
|
+
- **ESLint understands semantics**: side-effect imports, type vs value imports, module boundaries, aliases
|
|
195
|
+
- **Prettier only formats syntax**: whitespace, commas, line breaks — it doesn't understand import logic
|
|
196
|
+
- **Deterministic vs Context-aware**: Prettier aims for same input → same output. Import sorting needs context and grouping rules
|
|
197
|
+
|
|
198
|
+
**This package configuration:**
|
|
199
|
+
|
|
200
|
+
- ✅ **ESLint**: `simple-import-sort` handles all import sorting
|
|
201
|
+
- ✅ **Prettier**: Only formats code (whitespace, quotes, etc.) — **NO import sorting**
|
|
202
|
+
- ✅ **Exception**: Tailwind class sorting (string order, no logic impact)
|
|
203
|
+
|
|
204
|
+
**Result:** Clean separation of concerns, no conflicts, battle-tested approach.
|
|
205
|
+
|
|
206
|
+
**Important:** Make sure your editor/IDE:
|
|
207
|
+
- Uses Prettier as default formatter with `formatOnSave`
|
|
208
|
+
- Runs ESLint auto-fix on save (`source.fixAll.eslint`) for import sorting
|
|
209
|
+
|
|
210
|
+
## Presets
|
|
211
|
+
|
|
212
|
+
### `base`
|
|
213
|
+
Minimal, safe defaults. Good starting point.
|
|
214
|
+
|
|
215
|
+
### `recommended`
|
|
216
|
+
Enhanced safety rules while remaining practical. Recommended for most projects.
|
|
217
|
+
|
|
218
|
+
### `strict`
|
|
219
|
+
Opt-in preset with additional rules including:
|
|
220
|
+
- `eslint-plugin-unicorn` (code quality)
|
|
221
|
+
- `eslint-plugin-sonarjs` (bug detection)
|
|
222
|
+
- `eslint-plugin-boundaries` (architecture enforcement, disabled by default)
|
|
223
|
+
|
|
224
|
+
## Available Configs
|
|
225
|
+
|
|
226
|
+
- `base` - Base ESLint configuration
|
|
227
|
+
- `javascript` - JavaScript support
|
|
228
|
+
- `typescript` - TypeScript support
|
|
229
|
+
- `node` - Node.js backend rules
|
|
230
|
+
- `react` - React framework rules
|
|
231
|
+
- `next` - Next.js framework rules
|
|
232
|
+
- `vue` - Vue framework rules
|
|
233
|
+
- `angular` - Angular framework rules
|
|
234
|
+
- `nest` - NestJS framework rules
|
|
235
|
+
- `recommended` - Recommended preset
|
|
236
|
+
- `strict` - Strict preset (opt-in)
|
|
237
|
+
|
|
238
|
+
## Principles
|
|
239
|
+
|
|
240
|
+
- **Practical and stable** - Designed for long-term use (5-10 years)
|
|
241
|
+
- **Not over-opinionated** - Focuses on bugs, correctness, and maintainability
|
|
242
|
+
- **Auto-fix friendly** - Most rules are auto-fixable
|
|
243
|
+
- **No style rules in ESLint** - Prettier handles all formatting
|
|
244
|
+
- **Stable import sorting** - Uses `eslint-plugin-simple-import-sort` for predictable sorting
|
|
245
|
+
- **Architecture rules optional** - Boundaries enforcement is opt-in only
|
|
246
|
+
|
|
247
|
+
## Requirements
|
|
248
|
+
|
|
249
|
+
- Node.js >= 18.0.0
|
|
250
|
+
- TypeScript >= 5.0.0 (peer dependency, optional for JS-only projects)
|
|
251
|
+
|
|
252
|
+
## Contributing
|
|
253
|
+
|
|
254
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
255
|
+
|
|
256
|
+
## License
|
|
257
|
+
|
|
258
|
+
MIT
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
Made with ❤️ by [@itstandu](https://github.com/itstandu)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const ts = require('./typescript')
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
...ts,
|
|
5
|
+
plugins: {
|
|
6
|
+
...ts.plugins,
|
|
7
|
+
'@angular-eslint': require('@angular-eslint/eslint-plugin'),
|
|
8
|
+
'@angular-eslint/template': require('@angular-eslint/eslint-plugin-template')
|
|
9
|
+
},
|
|
10
|
+
rules: {
|
|
11
|
+
...ts.rules,
|
|
12
|
+
'@angular-eslint/directive-selector': [
|
|
13
|
+
'warn',
|
|
14
|
+
{
|
|
15
|
+
type: 'attribute',
|
|
16
|
+
prefix: 'app',
|
|
17
|
+
style: 'camelCase'
|
|
18
|
+
}
|
|
19
|
+
],
|
|
20
|
+
'@angular-eslint/component-selector': [
|
|
21
|
+
'warn',
|
|
22
|
+
{
|
|
23
|
+
type: 'element',
|
|
24
|
+
prefix: 'app',
|
|
25
|
+
style: 'kebab-case'
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
'@angular-eslint/no-empty-lifecycle-method': 'warn',
|
|
29
|
+
'@angular-eslint/no-host-metadata-property': 'warn',
|
|
30
|
+
'@angular-eslint/no-input-rename': 'warn',
|
|
31
|
+
'@angular-eslint/no-output-on-prefix': 'warn',
|
|
32
|
+
'@angular-eslint/no-output-rename': 'warn',
|
|
33
|
+
'@angular-eslint/use-lifecycle-interface': 'warn',
|
|
34
|
+
'@angular-eslint/use-pipe-transform-interface': 'warn'
|
|
35
|
+
}
|
|
36
|
+
}
|
package/eslint/base.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
const prettierConfig = require('eslint-config-prettier')
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
ignores: [
|
|
5
|
+
'**/node_modules/**',
|
|
6
|
+
'**/dist/**',
|
|
7
|
+
'**/build/**',
|
|
8
|
+
'**/.next/**',
|
|
9
|
+
'**/.output/**',
|
|
10
|
+
'**/.turbo/**',
|
|
11
|
+
'**/.cache/**',
|
|
12
|
+
'**/coverage/**'
|
|
13
|
+
],
|
|
14
|
+
languageOptions: {
|
|
15
|
+
ecmaVersion: 'latest',
|
|
16
|
+
sourceType: 'module',
|
|
17
|
+
globals: {}
|
|
18
|
+
},
|
|
19
|
+
plugins: {
|
|
20
|
+
'simple-import-sort': require('eslint-plugin-simple-import-sort'),
|
|
21
|
+
'unused-imports': require('eslint-plugin-unused-imports'),
|
|
22
|
+
import: require('eslint-plugin-import')
|
|
23
|
+
},
|
|
24
|
+
settings: {
|
|
25
|
+
'import/resolver': {
|
|
26
|
+
node: {
|
|
27
|
+
extensions: ['.js', '.jsx', '.ts', '.tsx', '.mjs', '.cjs']
|
|
28
|
+
},
|
|
29
|
+
typescript: {
|
|
30
|
+
alwaysTryTypes: true
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
rules: {
|
|
35
|
+
...prettierConfig.rules,
|
|
36
|
+
|
|
37
|
+
'no-undef': 'error',
|
|
38
|
+
'no-unreachable': 'error',
|
|
39
|
+
'no-duplicate-imports': 'error',
|
|
40
|
+
'no-console': 'warn',
|
|
41
|
+
|
|
42
|
+
'no-var': 'error',
|
|
43
|
+
'prefer-const': 'error',
|
|
44
|
+
'no-shadow': 'off',
|
|
45
|
+
|
|
46
|
+
'no-fallthrough': 'error',
|
|
47
|
+
'no-empty': ['error', { allowEmptyCatch: true }],
|
|
48
|
+
|
|
49
|
+
'no-async-promise-executor': 'error',
|
|
50
|
+
|
|
51
|
+
'simple-import-sort/imports': [
|
|
52
|
+
'error',
|
|
53
|
+
{
|
|
54
|
+
groups: [
|
|
55
|
+
['^\\u0000'],
|
|
56
|
+
['^node:'],
|
|
57
|
+
['^@?\\w'],
|
|
58
|
+
['^@/'],
|
|
59
|
+
['^\\.\\.'],
|
|
60
|
+
['^\\.']
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
],
|
|
64
|
+
'simple-import-sort/exports': 'error',
|
|
65
|
+
|
|
66
|
+
'unused-imports/no-unused-imports': 'error',
|
|
67
|
+
'no-unused-vars': 'off',
|
|
68
|
+
|
|
69
|
+
'import/first': 'error',
|
|
70
|
+
'import/newline-after-import': 'error',
|
|
71
|
+
'import/no-duplicates': 'error'
|
|
72
|
+
}
|
|
73
|
+
}
|
package/eslint/nest.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const node = require('./node')
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
...node,
|
|
5
|
+
rules: {
|
|
6
|
+
...node.rules,
|
|
7
|
+
'@typescript-eslint/explicit-function-return-type': 'off',
|
|
8
|
+
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
|
9
|
+
'@typescript-eslint/interface-name-prefix': 'off',
|
|
10
|
+
'@typescript-eslint/naming-convention': 'off'
|
|
11
|
+
}
|
|
12
|
+
}
|
package/eslint/next.js
ADDED
package/eslint/node.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const ts = require('./typescript')
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
...ts,
|
|
5
|
+
plugins: {
|
|
6
|
+
...ts.plugins,
|
|
7
|
+
promise: require('eslint-plugin-promise'),
|
|
8
|
+
n: require('eslint-plugin-n')
|
|
9
|
+
},
|
|
10
|
+
rules: {
|
|
11
|
+
...ts.rules,
|
|
12
|
+
'n/no-process-exit': 'off',
|
|
13
|
+
'n/no-missing-import': 'off',
|
|
14
|
+
'promise/always-return': 'off',
|
|
15
|
+
'promise/no-nesting': 'off',
|
|
16
|
+
'promise/no-callback-in-promise': 'warn'
|
|
17
|
+
}
|
|
18
|
+
}
|
package/eslint/react.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
const ts = require('./typescript')
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
...ts,
|
|
5
|
+
languageOptions: {
|
|
6
|
+
...ts.languageOptions,
|
|
7
|
+
parserOptions: {
|
|
8
|
+
...ts.languageOptions.parserOptions,
|
|
9
|
+
ecmaFeatures: {
|
|
10
|
+
jsx: true
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
globals: {
|
|
14
|
+
...ts.languageOptions.globals,
|
|
15
|
+
React: 'readonly',
|
|
16
|
+
JSX: 'readonly'
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
plugins: {
|
|
20
|
+
...ts.plugins,
|
|
21
|
+
react: require('eslint-plugin-react'),
|
|
22
|
+
'react-hooks': require('eslint-plugin-react-hooks'),
|
|
23
|
+
'jsx-a11y': require('eslint-plugin-jsx-a11y')
|
|
24
|
+
},
|
|
25
|
+
settings: {
|
|
26
|
+
react: {
|
|
27
|
+
version: 'detect'
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
rules: {
|
|
31
|
+
...ts.rules,
|
|
32
|
+
'react/react-in-jsx-scope': 'off',
|
|
33
|
+
'react/prop-types': 'off',
|
|
34
|
+
'react/display-name': 'off',
|
|
35
|
+
'react/jsx-uses-react': 'off',
|
|
36
|
+
'react/jsx-uses-vars': 'error',
|
|
37
|
+
'react/jsx-key': 'error',
|
|
38
|
+
'react/jsx-no-duplicate-props': 'error',
|
|
39
|
+
'react/jsx-no-undef': 'error',
|
|
40
|
+
'react/jsx-no-useless-fragment': 'warn',
|
|
41
|
+
'react/jsx-pascal-case': 'warn',
|
|
42
|
+
'react/no-array-index-key': 'warn',
|
|
43
|
+
'react/no-danger': 'warn',
|
|
44
|
+
'react/no-deprecated': 'warn',
|
|
45
|
+
'react/no-direct-mutation-state': 'error',
|
|
46
|
+
'react/no-unescaped-entities': 'off',
|
|
47
|
+
'react/no-unknown-property': 'error',
|
|
48
|
+
'react/self-closing-comp': 'off',
|
|
49
|
+
|
|
50
|
+
'react/jsx-boolean-value': 'off',
|
|
51
|
+
'react/jsx-child-element-spacing': 'off',
|
|
52
|
+
'react/jsx-closing-bracket-location': 'off',
|
|
53
|
+
'react/jsx-closing-tag-location': 'off',
|
|
54
|
+
'react/jsx-curly-brace-presence': 'off',
|
|
55
|
+
'react/jsx-curly-newline': 'off',
|
|
56
|
+
'react/jsx-curly-spacing': 'off',
|
|
57
|
+
'react/jsx-equals-spacing': 'off',
|
|
58
|
+
'react/jsx-first-prop-newline': 'off',
|
|
59
|
+
'react/jsx-indent': 'off',
|
|
60
|
+
'react/jsx-indent-props': 'off',
|
|
61
|
+
'react/jsx-max-props-per-line': 'off',
|
|
62
|
+
'react/jsx-newline': 'off',
|
|
63
|
+
'react/jsx-one-expression-per-line': 'off',
|
|
64
|
+
'react/jsx-props-no-multi-spaces': 'off',
|
|
65
|
+
'react/jsx-quotes': 'off',
|
|
66
|
+
'react/jsx-sort-props': 'off',
|
|
67
|
+
'react/jsx-tag-spacing': 'off',
|
|
68
|
+
'react/jsx-wrap-multilines': 'off',
|
|
69
|
+
|
|
70
|
+
'react-hooks/rules-of-hooks': 'error',
|
|
71
|
+
'react-hooks/exhaustive-deps': 'warn',
|
|
72
|
+
|
|
73
|
+
'jsx-a11y/alt-text': 'warn',
|
|
74
|
+
'jsx-a11y/anchor-has-content': 'warn',
|
|
75
|
+
'jsx-a11y/anchor-is-valid': 'warn',
|
|
76
|
+
'jsx-a11y/aria-activedescendant-has-tabindex': 'warn',
|
|
77
|
+
'jsx-a11y/aria-props': 'warn',
|
|
78
|
+
'jsx-a11y/aria-proptypes': 'warn',
|
|
79
|
+
'jsx-a11y/aria-role': 'warn',
|
|
80
|
+
'jsx-a11y/aria-unsupported-elements': 'warn',
|
|
81
|
+
'jsx-a11y/click-events-have-key-events': 'warn',
|
|
82
|
+
'jsx-a11y/heading-has-content': 'warn',
|
|
83
|
+
'jsx-a11y/html-has-lang': 'warn',
|
|
84
|
+
'jsx-a11y/img-redundant-alt': 'warn',
|
|
85
|
+
'jsx-a11y/interactive-supports-focus': 'warn',
|
|
86
|
+
'jsx-a11y/label-has-associated-control': 'warn',
|
|
87
|
+
'jsx-a11y/mouse-events-have-key-events': 'warn',
|
|
88
|
+
'jsx-a11y/no-access-key': 'warn',
|
|
89
|
+
'jsx-a11y/no-autofocus': 'warn',
|
|
90
|
+
'jsx-a11y/no-distracting-elements': 'warn',
|
|
91
|
+
'jsx-a11y/no-interactive-element-to-noninteractive-role': 'warn',
|
|
92
|
+
'jsx-a11y/no-noninteractive-element-interactions': 'warn',
|
|
93
|
+
'jsx-a11y/no-noninteractive-element-to-interactive-role': 'warn',
|
|
94
|
+
'jsx-a11y/no-redundant-roles': 'warn',
|
|
95
|
+
'jsx-a11y/no-static-element-interactions': 'warn',
|
|
96
|
+
'jsx-a11y/role-has-required-aria-props': 'warn',
|
|
97
|
+
'jsx-a11y/role-supports-aria-props': 'warn',
|
|
98
|
+
'jsx-a11y/scope': 'warn',
|
|
99
|
+
'jsx-a11y/tabindex-no-positive': 'warn'
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const base = require('./base')
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
...base,
|
|
5
|
+
rules: {
|
|
6
|
+
...base.rules,
|
|
7
|
+
'no-console': 'warn',
|
|
8
|
+
'no-debugger': 'error',
|
|
9
|
+
'no-alert': 'warn',
|
|
10
|
+
'no-eval': 'error',
|
|
11
|
+
'no-implied-eval': 'error',
|
|
12
|
+
'no-new-func': 'error',
|
|
13
|
+
'no-script-url': 'error',
|
|
14
|
+
|
|
15
|
+
'prefer-arrow-callback': 'warn',
|
|
16
|
+
'prefer-template': 'warn',
|
|
17
|
+
'prefer-spread': 'warn',
|
|
18
|
+
'prefer-rest-params': 'warn',
|
|
19
|
+
|
|
20
|
+
'no-useless-return': 'warn',
|
|
21
|
+
'no-useless-concat': 'warn',
|
|
22
|
+
'no-useless-escape': 'warn',
|
|
23
|
+
|
|
24
|
+
'import/no-unresolved': 'off',
|
|
25
|
+
'import/no-cycle': 'warn',
|
|
26
|
+
'import/no-self-import': 'error',
|
|
27
|
+
'import/no-useless-path-segments': 'error'
|
|
28
|
+
}
|
|
29
|
+
}
|
package/eslint/strict.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const recommended = require('./recommended')
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
...recommended,
|
|
5
|
+
plugins: {
|
|
6
|
+
...recommended.plugins,
|
|
7
|
+
boundaries: require('eslint-plugin-boundaries'),
|
|
8
|
+
unicorn: require('eslint-plugin-unicorn'),
|
|
9
|
+
sonarjs: require('eslint-plugin-sonarjs')
|
|
10
|
+
},
|
|
11
|
+
rules: {
|
|
12
|
+
...recommended.rules,
|
|
13
|
+
|
|
14
|
+
'unicorn/prefer-module': 'off',
|
|
15
|
+
'unicorn/prefer-node-protocol': 'warn',
|
|
16
|
+
'unicorn/no-array-callback-reference': 'warn',
|
|
17
|
+
'unicorn/prefer-array-find': 'warn',
|
|
18
|
+
'unicorn/prefer-array-some': 'warn',
|
|
19
|
+
'unicorn/prefer-array-index-of': 'warn',
|
|
20
|
+
'unicorn/prefer-string-starts-ends-with': 'warn',
|
|
21
|
+
'unicorn/prefer-string-slice': 'warn',
|
|
22
|
+
'unicorn/no-useless-undefined': 'warn',
|
|
23
|
+
'unicorn/prefer-optional-catch-binding': 'warn',
|
|
24
|
+
|
|
25
|
+
'sonarjs/cognitive-complexity': 'off',
|
|
26
|
+
'sonarjs/no-duplicate-string': 'off',
|
|
27
|
+
'sonarjs/no-small-switch': 'off',
|
|
28
|
+
'sonarjs/prefer-immediate-return': 'warn',
|
|
29
|
+
'sonarjs/prefer-single-boolean-return': 'warn',
|
|
30
|
+
|
|
31
|
+
'boundaries/element-types': 'off',
|
|
32
|
+
'boundaries/no-private': 'off',
|
|
33
|
+
'boundaries/entry-point': 'off'
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const base = require('./base')
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
...base,
|
|
5
|
+
languageOptions: {
|
|
6
|
+
...base.languageOptions,
|
|
7
|
+
parser: require('@typescript-eslint/parser'),
|
|
8
|
+
parserOptions: {
|
|
9
|
+
ecmaVersion: 'latest',
|
|
10
|
+
sourceType: 'module',
|
|
11
|
+
project: true,
|
|
12
|
+
tsconfigRootDir: process.cwd()
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
plugins: {
|
|
16
|
+
...base.plugins,
|
|
17
|
+
'@typescript-eslint': require('@typescript-eslint/eslint-plugin')
|
|
18
|
+
},
|
|
19
|
+
rules: {
|
|
20
|
+
...base.rules,
|
|
21
|
+
'no-unused-vars': 'off',
|
|
22
|
+
'@typescript-eslint/no-unused-vars': 'off',
|
|
23
|
+
'@typescript-eslint/no-floating-promises': 'error',
|
|
24
|
+
'@typescript-eslint/no-misused-promises': 'error',
|
|
25
|
+
'@typescript-eslint/consistent-type-imports': [
|
|
26
|
+
'error',
|
|
27
|
+
{ prefer: 'type-imports', fixStyle: 'inline-type-imports' }
|
|
28
|
+
],
|
|
29
|
+
'@typescript-eslint/no-explicit-any': 'off',
|
|
30
|
+
'@typescript-eslint/explicit-function-return-type': 'off',
|
|
31
|
+
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
|
32
|
+
'@typescript-eslint/no-non-null-assertion': 'warn',
|
|
33
|
+
'@typescript-eslint/prefer-nullish-coalescing': 'warn',
|
|
34
|
+
'@typescript-eslint/prefer-optional-chain': 'warn'
|
|
35
|
+
}
|
|
36
|
+
}
|
package/eslint/vue.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
const base = require('./base')
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
...base,
|
|
5
|
+
languageOptions: {
|
|
6
|
+
...base.languageOptions,
|
|
7
|
+
parser: require('vue-eslint-parser'),
|
|
8
|
+
parserOptions: {
|
|
9
|
+
parser: require('@typescript-eslint/parser'),
|
|
10
|
+
ecmaVersion: 'latest',
|
|
11
|
+
sourceType: 'module',
|
|
12
|
+
project: true
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
plugins: {
|
|
16
|
+
...base.plugins,
|
|
17
|
+
vue: require('eslint-plugin-vue'),
|
|
18
|
+
'@typescript-eslint': require('@typescript-eslint/eslint-plugin')
|
|
19
|
+
},
|
|
20
|
+
rules: {
|
|
21
|
+
...base.rules,
|
|
22
|
+
'no-unused-vars': 'off',
|
|
23
|
+
'@typescript-eslint/no-unused-vars': 'off',
|
|
24
|
+
'@typescript-eslint/no-floating-promises': 'error',
|
|
25
|
+
'@typescript-eslint/no-misused-promises': 'error',
|
|
26
|
+
'@typescript-eslint/consistent-type-imports': [
|
|
27
|
+
'error',
|
|
28
|
+
{ prefer: 'type-imports', fixStyle: 'inline-type-imports' }
|
|
29
|
+
],
|
|
30
|
+
|
|
31
|
+
'vue/component-name-in-template-casing': ['warn', 'PascalCase'],
|
|
32
|
+
'vue/component-definition-name-casing': ['warn', 'PascalCase'],
|
|
33
|
+
'vue/custom-event-name-casing': 'warn',
|
|
34
|
+
'vue/define-macros-order': 'warn',
|
|
35
|
+
'vue/html-closing-bracket-newline': 'off',
|
|
36
|
+
'vue/html-closing-bracket-spacing': 'off',
|
|
37
|
+
'vue/html-end-tags': 'error',
|
|
38
|
+
'vue/html-indent': 'off',
|
|
39
|
+
'vue/html-quotes': 'off',
|
|
40
|
+
'vue/html-self-closing': 'off',
|
|
41
|
+
'vue/max-attributes-per-line': 'off',
|
|
42
|
+
'vue/multiline-html-element-content-newline': 'off',
|
|
43
|
+
'vue/mustache-interpolation-spacing': 'off',
|
|
44
|
+
'vue/no-multi-spaces': 'off',
|
|
45
|
+
'vue/no-spaces-around-equal-signs-in-attribute': 'off',
|
|
46
|
+
'vue/no-template-shadow': 'warn',
|
|
47
|
+
'vue/one-component-per-file': 'error',
|
|
48
|
+
'vue/prop-name-casing': 'off',
|
|
49
|
+
'vue/require-default-prop': 'off',
|
|
50
|
+
'vue/require-explicit-emits': 'warn',
|
|
51
|
+
'vue/require-prop-types': 'off',
|
|
52
|
+
'vue/singleline-html-element-content-newline': 'off',
|
|
53
|
+
'vue/v-bind-style': 'off',
|
|
54
|
+
'vue/v-on-style': 'off',
|
|
55
|
+
'vue/v-slot-style': 'off',
|
|
56
|
+
'vue/attribute-hyphenation': 'off',
|
|
57
|
+
'vue/component-tags-order': [
|
|
58
|
+
'warn',
|
|
59
|
+
{
|
|
60
|
+
order: ['script', 'template', 'style']
|
|
61
|
+
}
|
|
62
|
+
],
|
|
63
|
+
'vue/define-emits-declaration': 'warn',
|
|
64
|
+
'vue/define-props-declaration': 'warn',
|
|
65
|
+
'vue/no-duplicate-attributes': 'error',
|
|
66
|
+
'vue/no-empty-component-block': 'warn',
|
|
67
|
+
'vue/no-multiple-object-in-class': 'error',
|
|
68
|
+
'vue/no-multiple-slot-args': 'error',
|
|
69
|
+
'vue/no-reserved-component-names': 'error',
|
|
70
|
+
'vue/no-static-inline-styles': 'warn',
|
|
71
|
+
'vue/no-template-key': 'error',
|
|
72
|
+
'vue/no-textarea-mustache': 'error',
|
|
73
|
+
'vue/no-unused-components': 'warn',
|
|
74
|
+
'vue/no-unused-refs': 'warn',
|
|
75
|
+
'vue/no-unused-v-else-if': 'error',
|
|
76
|
+
'vue/no-use-v-if-with-v-for': 'error',
|
|
77
|
+
'vue/no-useless-mustaches': 'warn',
|
|
78
|
+
'vue/no-useless-v-bind': 'warn',
|
|
79
|
+
'vue/prefer-separate-static-class': 'warn',
|
|
80
|
+
'vue/prefer-true-attribute-shorthand': 'warn',
|
|
81
|
+
'vue/require-toggle-inside-transition': 'error',
|
|
82
|
+
'vue/use-v-on-exact': 'warn',
|
|
83
|
+
'vue/valid-v-bind-sync': 'error',
|
|
84
|
+
'vue/valid-v-bind': 'error',
|
|
85
|
+
'vue/valid-v-cloak': 'error',
|
|
86
|
+
'vue/valid-v-else-if': 'error',
|
|
87
|
+
'vue/valid-v-else': 'error',
|
|
88
|
+
'vue/valid-v-for': 'error',
|
|
89
|
+
'vue/valid-v-html': 'error',
|
|
90
|
+
'vue/valid-v-if': 'error',
|
|
91
|
+
'vue/valid-v-is': 'error',
|
|
92
|
+
'vue/valid-v-memo': 'error',
|
|
93
|
+
'vue/valid-v-model': 'error',
|
|
94
|
+
'vue/valid-v-on': 'error',
|
|
95
|
+
'vue/valid-v-once': 'error',
|
|
96
|
+
'vue/valid-v-pre': 'error',
|
|
97
|
+
'vue/valid-v-show': 'error',
|
|
98
|
+
'vue/valid-v-slot': 'error',
|
|
99
|
+
'vue/valid-v-text': 'error'
|
|
100
|
+
}
|
|
101
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
base: require('./eslint/base'),
|
|
3
|
+
javascript: require('./eslint/javascript'),
|
|
4
|
+
typescript: require('./eslint/typescript'),
|
|
5
|
+
node: require('./eslint/node'),
|
|
6
|
+
react: require('./eslint/react'),
|
|
7
|
+
next: require('./eslint/next'),
|
|
8
|
+
vue: require('./eslint/vue'),
|
|
9
|
+
angular: require('./eslint/angular'),
|
|
10
|
+
nest: require('./eslint/nest'),
|
|
11
|
+
recommended: require('./eslint/recommended'),
|
|
12
|
+
strict: require('./eslint/strict')
|
|
13
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@itstandu/code-style",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Production-ready shared ESLint + Prettier configuration for JavaScript and TypeScript projects",
|
|
5
|
+
"type": "commonjs",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./index.js",
|
|
9
|
+
"./prettier": "./prettier/index.cjs"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"eslint",
|
|
13
|
+
"prettier",
|
|
14
|
+
"index.js",
|
|
15
|
+
"README.md",
|
|
16
|
+
".prettierignore"
|
|
17
|
+
],
|
|
18
|
+
"keywords": [
|
|
19
|
+
"eslint",
|
|
20
|
+
"prettier",
|
|
21
|
+
"code-style",
|
|
22
|
+
"linting",
|
|
23
|
+
"formatting",
|
|
24
|
+
"typescript",
|
|
25
|
+
"javascript",
|
|
26
|
+
"react",
|
|
27
|
+
"vue",
|
|
28
|
+
"angular",
|
|
29
|
+
"nextjs",
|
|
30
|
+
"nestjs"
|
|
31
|
+
],
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "git+https://github.com/itstandu/code-style.git"
|
|
35
|
+
},
|
|
36
|
+
"homepage": "https://github.com/itstandu/code-style#readme",
|
|
37
|
+
"bugs": {
|
|
38
|
+
"url": "https://github.com/itstandu/code-style/issues"
|
|
39
|
+
},
|
|
40
|
+
"license": "MIT",
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=18.0.0"
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"@angular-eslint/eslint-plugin": "*",
|
|
46
|
+
"@angular-eslint/eslint-plugin-template": "*",
|
|
47
|
+
"@angular-eslint/template-parser": "*",
|
|
48
|
+
"@typescript-eslint/eslint-plugin": "*",
|
|
49
|
+
"@typescript-eslint/parser": "*",
|
|
50
|
+
"eslint": "*",
|
|
51
|
+
"eslint-config-prettier": "*",
|
|
52
|
+
"eslint-plugin-boundaries": "*",
|
|
53
|
+
"eslint-plugin-import": "*",
|
|
54
|
+
"eslint-plugin-jsx-a11y": "*",
|
|
55
|
+
"eslint-plugin-n": "*",
|
|
56
|
+
"eslint-plugin-promise": "*",
|
|
57
|
+
"eslint-plugin-react": "*",
|
|
58
|
+
"eslint-plugin-react-hooks": "*",
|
|
59
|
+
"eslint-plugin-simple-import-sort": "*",
|
|
60
|
+
"eslint-plugin-sonarjs": "*",
|
|
61
|
+
"eslint-plugin-unicorn": "*",
|
|
62
|
+
"eslint-plugin-unused-imports": "*",
|
|
63
|
+
"eslint-plugin-vue": "*",
|
|
64
|
+
"@prettier/plugin-oxc": "*",
|
|
65
|
+
"prettier": "*",
|
|
66
|
+
"prettier-plugin-tailwindcss": "*",
|
|
67
|
+
"vue-eslint-parser": "*"
|
|
68
|
+
},
|
|
69
|
+
"peerDependencies": {
|
|
70
|
+
"typescript": ">=5.0.0"
|
|
71
|
+
},
|
|
72
|
+
"peerDependenciesMeta": {
|
|
73
|
+
"typescript": {
|
|
74
|
+
"optional": true
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
"scripts": {
|
|
78
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
semi: false,
|
|
3
|
+
singleQuote: true,
|
|
4
|
+
trailingComma: 'all',
|
|
5
|
+
printWidth: 100,
|
|
6
|
+
tabWidth: 2,
|
|
7
|
+
useTabs: false,
|
|
8
|
+
arrowParens: 'always',
|
|
9
|
+
endOfLine: 'lf',
|
|
10
|
+
bracketSpacing: true,
|
|
11
|
+
bracketSameLine: false,
|
|
12
|
+
proseWrap: 'preserve',
|
|
13
|
+
htmlWhitespaceSensitivity: 'css',
|
|
14
|
+
insertPragma: false,
|
|
15
|
+
jsxSingleQuote: false,
|
|
16
|
+
quoteProps: 'as-needed',
|
|
17
|
+
requirePragma: false,
|
|
18
|
+
vueIndentScriptAndStyle: false,
|
|
19
|
+
|
|
20
|
+
plugins: ['@prettier/plugin-oxc', 'prettier-plugin-tailwindcss']
|
|
21
|
+
}
|