@peerigon/configs 1.0.0-beta.1
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/LICENSE +21 -0
- package/README.md +452 -0
- package/eslint/lib/glob-patterns.js +11 -0
- package/eslint/lib/rule-options.js +130 -0
- package/eslint/presets/javascript-browser.js +6 -0
- package/eslint/presets/javascript-node.js +6 -0
- package/eslint/presets/javascript.js +5 -0
- package/eslint/presets/javascript.test/eslint.config.js +1 -0
- package/eslint/presets/javascript.test/main.js +62 -0
- package/eslint/presets/javascript.test/other.js +2 -0
- package/eslint/presets/typescript-node.js +13 -0
- package/eslint/presets/typescript-react.js +15 -0
- package/eslint/presets/typescript-react.test/App.tsx +45 -0
- package/eslint/presets/typescript-react.test/Other.tsx +5 -0
- package/eslint/presets/typescript-react.test/eslint.config.js +1 -0
- package/eslint/presets/typescript-react.test/tsconfig.json +7 -0
- package/eslint/presets/typescript.js +6 -0
- package/eslint/presets/typescript.test/eslint.config.js +1 -0
- package/eslint/presets/typescript.test/main.ts +31 -0
- package/eslint/presets/typescript.test/message.ts +3 -0
- package/eslint/presets/typescript.test/test.json +1 -0
- package/eslint/presets/typescript.test/tsconfig.json +4 -0
- package/eslint/presets/typescript.test/types.d.ts +11 -0
- package/eslint/rules/base.js +18 -0
- package/eslint/rules/browser.js +12 -0
- package/eslint/rules/javascript.js +147 -0
- package/eslint/rules/node.js +12 -0
- package/eslint/rules/react.js +169 -0
- package/eslint/rules/typescript.js +198 -0
- package/eslint/styles/jsx-no-literals.js +31 -0
- package/eslint/styles/jsx-no-literals.test/eslint.config.js +4 -0
- package/eslint/styles/jsx-no-literals.test/main.tsx +4 -0
- package/eslint/styles/jsx-no-literals.test/tsconfig.json +7 -0
- package/eslint/styles/no-default-export.js +19 -0
- package/eslint/styles/no-default-export.test/eslint.config.js +4 -0
- package/eslint/styles/no-default-export.test/main.ts +2 -0
- package/eslint/styles/no-default-export.test/tsconfig.json +4 -0
- package/eslint/styles/no-null.js +10 -0
- package/eslint/styles/no-null.test/eslint.config.js +4 -0
- package/eslint/styles/no-null.test/main.ts +2 -0
- package/eslint/styles/no-null.test/tsconfig.json +4 -0
- package/eslint/styles/prefer-array-shorthand.js +15 -0
- package/eslint/styles/prefer-array-shorthand.test/eslint.config.js +4 -0
- package/eslint/styles/prefer-array-shorthand.test/main.ts +4 -0
- package/eslint/styles/prefer-array-shorthand.test/tsconfig.json +4 -0
- package/eslint/styles/prefer-interface.js +10 -0
- package/eslint/styles/prefer-interface.test/eslint.config.js +4 -0
- package/eslint/styles/prefer-interface.test/main.ts +8 -0
- package/eslint/styles/prefer-interface.test/tsconfig.json +4 -0
- package/eslint/types.d.ts +48 -0
- package/package.json +108 -0
- package/prettier/base.js +30 -0
- package/typescript/base.json +20 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Peerigon
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
# eslint-config-peerigon
|
|
2
|
+
|
|
3
|
+
**[Peerigon](https://peerigon.com/) coding rules as [ESLint](http://eslint.org/) config.**
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/eslint-config-peerigon)
|
|
6
|
+
[](https://github.com/semantic-release/semantic-release)
|
|
7
|
+
[](https://www.npmjs.com/package/eslint-config-peerigon)<br>
|
|
8
|
+
[](./LICENSE)
|
|
9
|
+
|
|
10
|
+
Linting and formatting rules are always a balance between
|
|
11
|
+
|
|
12
|
+
- ease of reading
|
|
13
|
+
- ease of refactoring
|
|
14
|
+
- ease of writing.
|
|
15
|
+
|
|
16
|
+
We think that
|
|
17
|
+
|
|
18
|
+
- code is read more often than refactored
|
|
19
|
+
- and refactored more often than written from scratch.
|
|
20
|
+
|
|
21
|
+
Our linting rules have been designed with these assumptions in mind.
|
|
22
|
+
|
|
23
|
+
## Table of contents
|
|
24
|
+
|
|
25
|
+
- [Quick start](#quick-start)
|
|
26
|
+
- [Practical guide](#practical-guide)
|
|
27
|
+
- [Provided configs](#provided-configs)
|
|
28
|
+
- [Styles](#styles)
|
|
29
|
+
|
|
30
|
+
## Quick start
|
|
31
|
+
|
|
32
|
+
Recommended configuration in your `package.json`:
|
|
33
|
+
|
|
34
|
+
```js
|
|
35
|
+
{
|
|
36
|
+
"scripts": {
|
|
37
|
+
"test:lint": "eslint --max-warnings 0 --cache",
|
|
38
|
+
"posttest": "npm run test:lint"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
We also offer a [Prettier](https://prettier.io/) config that matches our ESLint config. Create a `.prettierrc.json` in your project with the following content:
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
"eslint-config-peerigon/prettier.config.js"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
There are presets for the most common setups:
|
|
50
|
+
|
|
51
|
+
### TypeScript
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
npm i eslint eslint-config-peerigon --save-dev
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
```js
|
|
58
|
+
{
|
|
59
|
+
"extends": [
|
|
60
|
+
"peerigon/presets/typescript.js"
|
|
61
|
+
],
|
|
62
|
+
"env": {
|
|
63
|
+
"node": true
|
|
64
|
+
},
|
|
65
|
+
"root": true
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### TypeScript + React
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
npm i eslint eslint-config-peerigon eslint-plugin-react eslint-plugin-jsx-a11y eslint-plugin-react-hooks --save-dev
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
```js
|
|
76
|
+
{
|
|
77
|
+
"extends": [
|
|
78
|
+
"peerigon/presets/typescript-react.js"
|
|
79
|
+
],
|
|
80
|
+
"env": {
|
|
81
|
+
"node": true,
|
|
82
|
+
"browser": true
|
|
83
|
+
},
|
|
84
|
+
"root": true
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### TypeScript + Node
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
npm i eslint eslint-config-peerigon eslint-plugin-n --save-dev
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
```js
|
|
95
|
+
{
|
|
96
|
+
"extends": [
|
|
97
|
+
"peerigon/presets/typescript-node.js"
|
|
98
|
+
],
|
|
99
|
+
"root": true
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Practical guide
|
|
104
|
+
|
|
105
|
+
### Disabling rules
|
|
106
|
+
|
|
107
|
+
Try to disable as less rules as possible. In most cases it's best to just write
|
|
108
|
+
|
|
109
|
+
```js
|
|
110
|
+
// eslint-disable-next-line [rule-code]
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
where `[rule-code]` is the code that is displayed along the error message. Disabling the next line is usually better because it resists [Prettier](https://prettier.io/) reformatting.
|
|
114
|
+
|
|
115
|
+
Sometimes it makes sense to disable a rule within a specifc file. In that case you can put the following snippet at the beginning of the file:
|
|
116
|
+
|
|
117
|
+
```js
|
|
118
|
+
/* eslint-disable [rule-code] */
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
If you don't agree with a rule, please do not just disable the rule. Often there are good reasons and the current setting is the result of years of experience. It's better to create an issue here to start a discussion about the pros and cons of a rule.
|
|
122
|
+
|
|
123
|
+
### Different styles
|
|
124
|
+
|
|
125
|
+
We acknowledge that there are certain rules where there are no actual pros and cons or where there is no clear winner. You just have to decide for one style and stick with it. We also know that some rules make sense in one project, but don't make sense in another project. That's why we also provide a list of [accepted custom styles](#styles) (see also [this discussion](https://github.com/peerigon/eslint-config-peerigon/issues/11)) which you can pick.
|
|
126
|
+
|
|
127
|
+
### VSCode
|
|
128
|
+
|
|
129
|
+
This is our recommended VSCode configuration using the [Prettier extension](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode). Adjust it to the needs of your particular project:
|
|
130
|
+
|
|
131
|
+
```json
|
|
132
|
+
{
|
|
133
|
+
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
|
134
|
+
"editor.formatOnSave": true,
|
|
135
|
+
"editor.codeActionsOnSave": {
|
|
136
|
+
"source.fixAll.eslint": true
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Experimental syntax using Babel
|
|
142
|
+
|
|
143
|
+
If you're using Babel you should set [`requireConfigFile: true`](https://github.com/babel/babel/tree/main/eslint/babel-eslint-parser#additional-parser-configuration) in your ESLint config. ESLint will then use your `babel.config.json`.
|
|
144
|
+
|
|
145
|
+
```js
|
|
146
|
+
{
|
|
147
|
+
"parserOptions": { "requireConfigFile": true },
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Naming conventions for properties
|
|
152
|
+
|
|
153
|
+
Sometimes we're not in full control over the naming conventions in our codebase, for instance if data is coming from a foreign API. While it often is preferable to transform property names into camelCase, it might not be practical. In these situations you can disable the check for properties like this:
|
|
154
|
+
|
|
155
|
+
```js
|
|
156
|
+
const options = require("eslint-config-peerigon/options.js");
|
|
157
|
+
|
|
158
|
+
module.exports = {
|
|
159
|
+
/* ... */
|
|
160
|
+
rules: {
|
|
161
|
+
// The API uses snake_case as properties
|
|
162
|
+
camelcase: [
|
|
163
|
+
"warn",
|
|
164
|
+
{
|
|
165
|
+
...options["camelcase"],
|
|
166
|
+
properties: "never",
|
|
167
|
+
},
|
|
168
|
+
],
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
**In TypeScript projects:**
|
|
174
|
+
|
|
175
|
+
```js
|
|
176
|
+
const options = require("eslint-config-peerigon/options.js");
|
|
177
|
+
|
|
178
|
+
module.exports = {
|
|
179
|
+
/* ... */
|
|
180
|
+
rules: {
|
|
181
|
+
// The API uses snake_case as properties
|
|
182
|
+
"@typescript-eslint/naming-convention": [
|
|
183
|
+
"warn",
|
|
184
|
+
options["@typescript-eslint/naming-convention"].ignoreProperties,
|
|
185
|
+
...options["@typescript-eslint/naming-convention"].defaultRules,
|
|
186
|
+
],
|
|
187
|
+
},
|
|
188
|
+
};
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Provided configs
|
|
192
|
+
|
|
193
|
+
### [`peerigon`](base.js)
|
|
194
|
+
|
|
195
|
+
**Base rules for every project. You should always add these rules.**
|
|
196
|
+
|
|
197
|
+
```
|
|
198
|
+
npm i eslint eslint-config-peerigon --save-dev
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
These rules assume a modern project with full ES2015 support, including ES modules. For specific environments like Node.js or old JS engines, see below. The base rules do not define an `env`, so you might want to do that for yourself to enable specific globals.
|
|
202
|
+
|
|
203
|
+
Add an `.eslintrc.json` to the project's root folder:
|
|
204
|
+
|
|
205
|
+
```js
|
|
206
|
+
{
|
|
207
|
+
"extends": [
|
|
208
|
+
// Base rules for every project
|
|
209
|
+
"peerigon"
|
|
210
|
+
],
|
|
211
|
+
// Do not search for further eslint configs in upper directories
|
|
212
|
+
"root": true,
|
|
213
|
+
// If you're using Babel, you should set requireConfigFile: true
|
|
214
|
+
// ESLint will then use your babel.config.json.
|
|
215
|
+
// "parserOptions": { "requireConfigFile": true },
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
The base rules use the `eslint-plugin-import` to resolve imports. Although it's possible to define [custom resolvers](https://github.com/benmosher/eslint-plugin-import#resolvers), it's highly discouraged to deviate from the common Node.js resolving algorithm. Other tools like linters and intellisense don't work reliably when you change the resolver.
|
|
220
|
+
|
|
221
|
+
### [`peerigon/typescript`](typescript.js)
|
|
222
|
+
|
|
223
|
+
Rules for [TypeScript](https://www.typescriptlang.org/).
|
|
224
|
+
|
|
225
|
+
```js
|
|
226
|
+
{
|
|
227
|
+
"extends": [
|
|
228
|
+
"peerigon",
|
|
229
|
+
"peerigon/typescript",
|
|
230
|
+
// Arrow functions are preferred with TypeScript
|
|
231
|
+
// See https://github.com/peerigon/eslint-config-peerigon/issues/23#issuecomment-472614432
|
|
232
|
+
"peerigon/styles/prefer-arrow"
|
|
233
|
+
],
|
|
234
|
+
"root": true,
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
You need to add `--ext js,jsx,cjs,mjs,ts,tsx` to the `test:lint` script:
|
|
239
|
+
|
|
240
|
+
```js
|
|
241
|
+
{
|
|
242
|
+
"scripts": {
|
|
243
|
+
"test:lint": "eslint --max-warnings 0 --cache --ext js,jsx,cjs,mjs,ts,tsx --ignore-path .gitignore ."
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
_We recommend using [`peerigon/styles/prefer-arrow`](#peerigonstylesprefer-arrow) because arrow functions (or function expressions in general) can leverage [TypeScript's contextual typing](https://www.typescriptlang.org/docs/handbook/type-inference.html#contextual-typing)._
|
|
249
|
+
|
|
250
|
+
### [`peerigon/node`](node.js)
|
|
251
|
+
|
|
252
|
+
**Important: Requires [`eslint-plugin-n`](https://github.com/eslint-community/eslint-plugin-n).**
|
|
253
|
+
|
|
254
|
+
```
|
|
255
|
+
npm i eslint-plugin-n --save-dev
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
```js
|
|
259
|
+
{
|
|
260
|
+
"extends": [
|
|
261
|
+
"peerigon",
|
|
262
|
+
"peerigon/node"
|
|
263
|
+
],
|
|
264
|
+
// Setting env.node = true is not necessary, this is already done by peerigon/node
|
|
265
|
+
"root": true
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### [`peerigon/react`](react.js)
|
|
270
|
+
|
|
271
|
+
**Important: Requires [`eslint-plugin-react`](https://github.com/yannickcr/eslint-plugin-react), [`eslint-plugin-jsx-a11y`](https://github.com/evcohen/eslint-plugin-jsx-a11y) and [`eslint-plugin-react-hooks`](https://www.npmjs.com/package/eslint-plugin-react-hooks) as project dependency.**
|
|
272
|
+
|
|
273
|
+
```
|
|
274
|
+
npm i eslint-plugin-react eslint-plugin-jsx-a11y eslint-plugin-react-hooks --save-dev
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
Rules for [React](https://facebook.github.io/react/) development, including accessibility rules.
|
|
278
|
+
These rules are also applicable in other JSX environments, like [Preact](https://github.com/developit/preact):
|
|
279
|
+
|
|
280
|
+
```js
|
|
281
|
+
{
|
|
282
|
+
"extends": [
|
|
283
|
+
"peerigon",
|
|
284
|
+
"peerigon/react"
|
|
285
|
+
],
|
|
286
|
+
"root": true
|
|
287
|
+
}
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
_We recommend using [`peerigon/styles/react-jsx-no-literals`](#peerigonstylesreact-jsx-no-literals) if you're using i18n in your project._
|
|
291
|
+
_You can use [`peerigon/styles/react-jsx-no-bind`](#peerigonstylesreact-jsx-no-bind) if you're using `memo` and `shouldComponentUpdate` a lot._
|
|
292
|
+
|
|
293
|
+
### [`peerigon/jsdoc`](jsdoc.js)
|
|
294
|
+
|
|
295
|
+
**Important: Requires [`eslint-plugin-jsdoc`](https://github.com/gajus/eslint-plugin-jsdoc) as project dependency.**
|
|
296
|
+
|
|
297
|
+
```
|
|
298
|
+
npm i eslint-plugin-jsdoc --save-dev
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
Makes sure that JSDoc annotations are written in a standard-compliant and uniform way.
|
|
302
|
+
|
|
303
|
+
```js
|
|
304
|
+
{
|
|
305
|
+
"extends": [
|
|
306
|
+
"peerigon",
|
|
307
|
+
"peerigon/jsdoc"
|
|
308
|
+
],
|
|
309
|
+
"root": true
|
|
310
|
+
}
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
## Styles
|
|
314
|
+
|
|
315
|
+
The following rules enable specific writing styles. Use them as you prefer.
|
|
316
|
+
|
|
317
|
+
### [`peerigon/styles/prefer-arrow`](styles/prefer-arrow.js)
|
|
318
|
+
|
|
319
|
+
Enforces arrow function expressions instead of function declarations (see [#23](https://github.com/peerigon/eslint-config-peerigon/issues/23)).
|
|
320
|
+
Regular functions are still allowed as methods in objects or classes.
|
|
321
|
+
|
|
322
|
+
```js
|
|
323
|
+
"extends": [
|
|
324
|
+
"peerigon",
|
|
325
|
+
"peerigon/styles/prefer-arrow"
|
|
326
|
+
],
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### [`peerigon/styles/no-default-export`](styles/no-default-export.js)
|
|
330
|
+
|
|
331
|
+
Forbids usage of `export default`. When using default exports, it becomes harder to name classes or functions consistently throughout the codebase since every module can pick its own name for the imported thing. Nicholas C. Zakas, the creator of ESLint, wrote [an article with more compelling arguments why he stopped using `export default`](https://humanwhocodes.com/blog/2019/01/stop-using-default-exports-javascript-module/).
|
|
332
|
+
|
|
333
|
+
```js
|
|
334
|
+
"extends": [
|
|
335
|
+
"peerigon",
|
|
336
|
+
"peerigon/styles/no-default-export"
|
|
337
|
+
],
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
**Please note:** This rule is disabled in `.jsx` and `.tsx` files because React components are usually exported via `export default`. [`React.lazy`](https://reactjs.org/docs/code-splitting.html#reactlazy) even expects the lazy loaded component to be exported as `default`.
|
|
341
|
+
|
|
342
|
+
### [`peerigon/styles/no-null`](styles/no-null.js)
|
|
343
|
+
|
|
344
|
+
**Important: Requires [`eslint-plugin-no-null`](https://github.com/nene/eslint-plugin-no-null) as project dependency.**
|
|
345
|
+
|
|
346
|
+
```
|
|
347
|
+
npm i eslint-plugin-no-null --save-dev
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
Forbids the usage of `null`. In a codebase it's often better to use a single non-value to represent _the absence of a value_. With the rise of default parameters and destructuring defaults, JavaScript developed a clear tendency towards `undefined`. [This issue](https://github.com/peerigon/eslint-config-peerigon/issues/71) summarizes the arguments (and trade-offs) of **null vs. undefined**.
|
|
351
|
+
|
|
352
|
+
```js
|
|
353
|
+
"extends": [
|
|
354
|
+
"peerigon",
|
|
355
|
+
"peerigon/styles/no-null"
|
|
356
|
+
],
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
**Please note:** If you use this rule, you will probably still need a single `null` value which you can refer to whenever you need to use `null` because of third-party code:
|
|
360
|
+
|
|
361
|
+
```js
|
|
362
|
+
// eslint-disable-next-line no-null/no-null
|
|
363
|
+
export const NULL = null;
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### [`peerigon/styles/prefer-interface`](styles/prefer-interface.js)
|
|
367
|
+
|
|
368
|
+
**Important: Use it in combination with [`peerigon/typescript`](typescript.js).**
|
|
369
|
+
|
|
370
|
+
[Prefer `interface` over `type`](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/prefer-interface.md).
|
|
371
|
+
|
|
372
|
+
```js
|
|
373
|
+
"extends": [
|
|
374
|
+
"peerigon",
|
|
375
|
+
"peerigon/typescript",
|
|
376
|
+
"peerigon/styles/prefer-interface"
|
|
377
|
+
],
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
### [`peerigon/styles/react-jsx-no-bind`](styles/react-jsx-no-bind.js)
|
|
381
|
+
|
|
382
|
+
**Important: Use it in combination with [`peerigon/react`](react.js).**
|
|
383
|
+
|
|
384
|
+
Depending on the way you write your components, it might be not ok to create functions during `render()`. Use it if you're using things like `React.memo()` or `shouldComponentUpdate` a lot.
|
|
385
|
+
|
|
386
|
+
```js
|
|
387
|
+
"extends": [
|
|
388
|
+
"peerigon",
|
|
389
|
+
"peerigon/react",
|
|
390
|
+
"peerigon/styles/react-jsx-no-bind"
|
|
391
|
+
],
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
### [`peerigon/styles/react-jsx-no-literals`](styles/react-jsx-no-literals.js)
|
|
395
|
+
|
|
396
|
+
**Important: Use it in combination with [`peerigon/react`](react.js).**
|
|
397
|
+
|
|
398
|
+
Use this style if you're using i18n. It prevents people from putting raw strings in components.
|
|
399
|
+
|
|
400
|
+
```js
|
|
401
|
+
"extends": [
|
|
402
|
+
"peerigon",
|
|
403
|
+
"peerigon/react",
|
|
404
|
+
"peerigon/styles/react-jsx-no-literals"
|
|
405
|
+
],
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
It disallows this:
|
|
409
|
+
|
|
410
|
+
```jsx
|
|
411
|
+
const Hello = <div>test</div>;
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
As an escape hatch, this is still allowed:
|
|
415
|
+
|
|
416
|
+
```jsx
|
|
417
|
+
const Hello = <div>{"test"}</div>;
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
### [`peerigon/styles/prefer-array-shorthand`](styles/prefer-array-shorthand.js)
|
|
421
|
+
|
|
422
|
+
**Important: Use it in combination with [`peerigon/typescript`](typescript.js).**
|
|
423
|
+
|
|
424
|
+
Enforces typescript arrays to use the shorthand array-style instead of the generic style.
|
|
425
|
+
|
|
426
|
+
```js
|
|
427
|
+
"extends": [
|
|
428
|
+
"peerigon",
|
|
429
|
+
"peerigon/typescript",
|
|
430
|
+
"peerigon/styles/prefer-array-shorthand"
|
|
431
|
+
],
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
It enforces this:
|
|
435
|
+
|
|
436
|
+
```ts
|
|
437
|
+
const foo: string[] = [];
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
instead of
|
|
441
|
+
|
|
442
|
+
```ts
|
|
443
|
+
const foo: Array<string> = [];
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
## License
|
|
447
|
+
|
|
448
|
+
Unlicense
|
|
449
|
+
|
|
450
|
+
## Sponsors
|
|
451
|
+
|
|
452
|
+
[<img src="https://assets.peerigon.com/peerigon/logo/peerigon-logo-flat-spinat.png" width="150" />](https://peerigon.com)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const globPatterns = {
|
|
2
|
+
javascript: ["**/*.{js,mjs,cjs}"],
|
|
3
|
+
typescript: ["**/*.{ts,cts,mts}"],
|
|
4
|
+
typescriptAmbient: ["**/*.d.ts"],
|
|
5
|
+
jsx: ["**/*.jsx"],
|
|
6
|
+
typescriptJsx: ["**/*.tsx"],
|
|
7
|
+
tests: [
|
|
8
|
+
"**/*.{test,spec,stories}.{js,mjs,cjs,ts,cts,mts,jsx,tsx}",
|
|
9
|
+
"**/test{s,}/**/*.{js,mjs,cjs,ts,cts,mts,jsx,tsx}",
|
|
10
|
+
],
|
|
11
|
+
};
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
const camelcase = {
|
|
2
|
+
allow: ["^UNSAFE_"], // Allows React UNSAFE_ methods
|
|
3
|
+
ignoreDestructuring: false,
|
|
4
|
+
properties: "always",
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export const ruleOptions = {
|
|
8
|
+
["camelcase"]: camelcase,
|
|
9
|
+
["max-lines"]: {
|
|
10
|
+
max: 700,
|
|
11
|
+
skipBlankLines: true,
|
|
12
|
+
skipComments: true,
|
|
13
|
+
},
|
|
14
|
+
["no-unused-expressions"]: {
|
|
15
|
+
allowShortCircuit: true,
|
|
16
|
+
allowTernary: true,
|
|
17
|
+
},
|
|
18
|
+
["no-unused-vars"]: {
|
|
19
|
+
vars: "all",
|
|
20
|
+
varsIgnorePattern: "^_",
|
|
21
|
+
args: "after-used",
|
|
22
|
+
argsIgnorePattern: "^_",
|
|
23
|
+
caughtErrors: "all",
|
|
24
|
+
reportUsedIgnorePattern: false,
|
|
25
|
+
// This pattern is pretty common
|
|
26
|
+
ignoreRestSiblings: true,
|
|
27
|
+
},
|
|
28
|
+
["@typescript-eslint/naming-convention"]: (() => {
|
|
29
|
+
const options = {
|
|
30
|
+
default: {
|
|
31
|
+
selector: "default",
|
|
32
|
+
format: ["camelCase", "PascalCase", "UPPER_CASE"],
|
|
33
|
+
leadingUnderscore: "allow",
|
|
34
|
+
trailingUnderscore: "allow",
|
|
35
|
+
},
|
|
36
|
+
function: {
|
|
37
|
+
selector: "function",
|
|
38
|
+
format: ["camelCase"],
|
|
39
|
+
leadingUnderscore: "allow",
|
|
40
|
+
trailingUnderscore: "allow",
|
|
41
|
+
},
|
|
42
|
+
parameter: {
|
|
43
|
+
selector: "parameter",
|
|
44
|
+
format: ["camelCase", "PascalCase"],
|
|
45
|
+
leadingUnderscore: "allow",
|
|
46
|
+
trailingUnderscore: "allow",
|
|
47
|
+
},
|
|
48
|
+
method: {
|
|
49
|
+
selector: "method",
|
|
50
|
+
format: ["camelCase"],
|
|
51
|
+
leadingUnderscore: "allow",
|
|
52
|
+
trailingUnderscore: "allow",
|
|
53
|
+
},
|
|
54
|
+
typeLike: {
|
|
55
|
+
selector: "typeLike",
|
|
56
|
+
format: ["PascalCase"],
|
|
57
|
+
leadingUnderscore: "allow",
|
|
58
|
+
trailingUnderscore: "allow",
|
|
59
|
+
},
|
|
60
|
+
enumMember: {
|
|
61
|
+
selector: "enumMember",
|
|
62
|
+
format: ["PascalCase"],
|
|
63
|
+
leadingUnderscore: "allow",
|
|
64
|
+
trailingUnderscore: "allow",
|
|
65
|
+
},
|
|
66
|
+
// In case it's destructured, we don't want to force the developer to change the casing
|
|
67
|
+
destructuring: {
|
|
68
|
+
selector: "variable",
|
|
69
|
+
modifiers: ["destructured"],
|
|
70
|
+
format: null,
|
|
71
|
+
},
|
|
72
|
+
// In case the property name requires quotes, we don't enforce any convention
|
|
73
|
+
requiresQuites: {
|
|
74
|
+
selector: [
|
|
75
|
+
"classProperty",
|
|
76
|
+
"objectLiteralProperty",
|
|
77
|
+
"typeProperty",
|
|
78
|
+
"classMethod",
|
|
79
|
+
"objectLiteralMethod",
|
|
80
|
+
"typeMethod",
|
|
81
|
+
"accessor",
|
|
82
|
+
"enumMember",
|
|
83
|
+
],
|
|
84
|
+
modifiers: ["requiresQuotes"],
|
|
85
|
+
format: null,
|
|
86
|
+
},
|
|
87
|
+
// We don't enforce any convention on object literals since these are often used
|
|
88
|
+
// for data object where we're not in control of the type (e.g. an api that takes camel_case properties)
|
|
89
|
+
objectLiteralProperty: {
|
|
90
|
+
selector: "objectLiteralProperty",
|
|
91
|
+
format: null,
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
// By enumerating all selectors explicitly we increase the
|
|
96
|
+
// specificity of these rules.
|
|
97
|
+
const escapeHatches = [
|
|
98
|
+
"variable",
|
|
99
|
+
"function",
|
|
100
|
+
"parameter",
|
|
101
|
+
"property",
|
|
102
|
+
"parameterProperty",
|
|
103
|
+
"method",
|
|
104
|
+
"accessor",
|
|
105
|
+
"enumMember",
|
|
106
|
+
"class",
|
|
107
|
+
"interface",
|
|
108
|
+
"typeAlias",
|
|
109
|
+
"enum",
|
|
110
|
+
"typeParameter",
|
|
111
|
+
].map((selector) => ({
|
|
112
|
+
filter: {
|
|
113
|
+
match: true,
|
|
114
|
+
// UNSAFE_ is a prefix used by React for all lifecycle hooks that are about to be deprecated
|
|
115
|
+
regex: "^(__|UNSAFE_).+$",
|
|
116
|
+
},
|
|
117
|
+
format: null,
|
|
118
|
+
selector,
|
|
119
|
+
}));
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
...options,
|
|
123
|
+
defaultRules: [...Object.values(options), ...escapeHatches],
|
|
124
|
+
ignoreProperties: {
|
|
125
|
+
selector: "property",
|
|
126
|
+
format: null,
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
})(),
|
|
130
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import eslintConfigPrettier from "eslint-config-prettier";
|
|
2
|
+
import { base } from "../rules/base.js";
|
|
3
|
+
import { browser } from "../rules/browser.js";
|
|
4
|
+
import { javascript } from "../rules/javascript.js";
|
|
5
|
+
|
|
6
|
+
export default [...base, ...javascript, ...browser, eslintConfigPrettier];
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import eslintConfigPrettier from "eslint-config-prettier";
|
|
2
|
+
import { base } from "../rules/base.js";
|
|
3
|
+
import { javascript } from "../rules/javascript.js";
|
|
4
|
+
import { node } from "../rules/node.js";
|
|
5
|
+
|
|
6
|
+
export default [...base, ...javascript, ...node, eslintConfigPrettier];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "../javascript-node.js";
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
//@ts-nocheck
|
|
2
|
+
// prettier-ignore
|
|
3
|
+
import { a } from "./other.js";
|
|
4
|
+
// eslint-disable-next-line no-duplicate-imports
|
|
5
|
+
import { b } from "./other.js";
|
|
6
|
+
|
|
7
|
+
// eslint-disable-next-line array-callback-return
|
|
8
|
+
[1, 2, 3].reduce((memo, item, index) => {
|
|
9
|
+
memo[item] = index;
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
for (const number of [1, 2, 3]) {
|
|
13
|
+
// eslint-disable-next-line no-await-in-loop
|
|
14
|
+
await Promise.resolve(number);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
(class {
|
|
18
|
+
constructor() {
|
|
19
|
+
// eslint-disable-next-line no-constructor-return
|
|
20
|
+
return 1;
|
|
21
|
+
}
|
|
22
|
+
})();
|
|
23
|
+
|
|
24
|
+
// eslint-disable-next-line no-promise-executor-return
|
|
25
|
+
void new Promise(() => 2);
|
|
26
|
+
|
|
27
|
+
// eslint-disable-next-line no-self-compare
|
|
28
|
+
if (a === a) {
|
|
29
|
+
void (a, b);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// eslint-disable-next-line no-template-curly-in-string
|
|
33
|
+
void "Hello ${name}!";
|
|
34
|
+
|
|
35
|
+
// eslint-disable-next-line no-unmodified-loop-condition
|
|
36
|
+
while (a) {
|
|
37
|
+
void a;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// eslint-disable-next-line no-unreachable-loop
|
|
41
|
+
for (let index = 0; index < 3; index++) {
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// eslint-disable-next-line no-useless-assignment
|
|
46
|
+
let id = "x1234";
|
|
47
|
+
id = 2;
|
|
48
|
+
void id;
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
/* empty */
|
|
52
|
+
// eslint-disable-next-line unicorn/catch-error-name
|
|
53
|
+
} catch (bla) {
|
|
54
|
+
void bla;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let c = 1;
|
|
58
|
+
// eslint-disable-next-line unicorn/prefer-top-level-await
|
|
59
|
+
(async () => {
|
|
60
|
+
// eslint-disable-next-line require-atomic-updates
|
|
61
|
+
c += await c;
|
|
62
|
+
})();
|