eslint-config-jc 5.0.2 → 5.2.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/README.md CHANGED
@@ -4,17 +4,45 @@ My personal coding style.
4
4
 
5
5
  This is designed to be a replacement for `eslint:recommended`, `plugin:react-hooks/recommended`, `plugin:@typescript-eslint/recommended`, and of course, everyone's favorite `airbnb`. It also extends `prettier`.
6
6
 
7
+ ## Installation
8
+
9
+ ```sh
10
+ yarn add -D eslint-config-jc
11
+ ```
12
+
13
+ No need to install any other plugins. You should probably also have the following dependencies:
14
+
15
+ - `eslint`
16
+ - `typescript-eslint` (for authoring the config)
17
+
7
18
  ## Configuration
8
19
 
9
- ESLint config:
20
+ `eslint.config.mjs`:
10
21
 
11
- ```json
12
- {
13
- "root": true,
14
- "extends": ["jc"]
15
- }
22
+ ```js
23
+ import jcRules from "eslint-config-jc";
24
+ import tseslint from "typescript-eslint";
25
+
26
+ export default tseslint.config(
27
+ ...jcRules({
28
+ // options
29
+ }),
30
+ {
31
+ // Your overrides here
32
+ },
33
+ );
16
34
  ```
17
35
 
36
+ The `jcRules` function has the following options:
37
+
38
+ - `react`: enable React and JSX rules (also loads browser globals)
39
+ - `typescriptTypeCheck`: enabled type-checked rules
40
+ - `node`: enable Node.js rules (also loads Node globals)
41
+ - `reactClassComp`: enable rules for class components (you probably don't need this)
42
+ - `reactPropTypes`: enable rules for prop types (you probably don't need this)
43
+
44
+ Each option can be set to `true` to enable, or an array of paths used for the `files` ESLint option.
45
+
18
46
  ## Configuration philosophy
19
47
 
20
48
  When analyzing whether a rule should be `error`, `warn`, or `off`, the following assumptions are made:
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import type { TSESLint } from "@typescript-eslint/utils";
2
2
  export default function configCreator({ react, typescriptTypeCheck, node, reactClassComp, reactPropTypes, }?: {
3
- react?: boolean;
4
- typescriptTypeCheck?: boolean;
5
- node?: boolean;
6
- reactClassComp?: boolean;
7
- reactPropTypes?: boolean;
3
+ react?: boolean | TSESLint.FlatConfig.FileSpec[];
4
+ typescriptTypeCheck?: boolean | TSESLint.FlatConfig.FileSpec[];
5
+ node?: boolean | TSESLint.FlatConfig.FileSpec[];
6
+ reactClassComp?: boolean | TSESLint.FlatConfig.FileSpec[];
7
+ reactPropTypes?: boolean | TSESLint.FlatConfig.FileSpec[];
8
8
  }): TSESLint.FlatConfig.ConfigArray;
package/dist/index.js CHANGED
@@ -11,6 +11,16 @@ import typescriptTypeCheckRules from "./typescript-typecheck.js";
11
11
  import nodeRules from "./node.js";
12
12
  import reactClassCompRules from "./react-class-comps.js";
13
13
  import reactPropTypesRules from "./react-prop-types.js";
14
+ function expandConfig(config, enabled) {
15
+ if (enabled === true)
16
+ return config;
17
+ if (!enabled)
18
+ return [];
19
+ return config.map((v) => ({
20
+ files: enabled,
21
+ ...v,
22
+ }));
23
+ }
14
24
  export default function configCreator({ react, typescriptTypeCheck, node, reactClassComp, reactPropTypes, } = {}) {
15
25
  return tseslint.config({
16
26
  linterOptions: {
@@ -20,5 +30,5 @@ export default function configCreator({ react, typescriptTypeCheck, node, reactC
20
30
  ecmaVersion: "latest",
21
31
  parser: tseslintParser,
22
32
  },
23
- }, prettierRules, ...baseRules, ...regexRules, ...typescriptRules, ...importRules, ...(react ? reactRules : []), ...(react ? jsxRules : []), ...(typescriptTypeCheck ? typescriptTypeCheckRules : []), ...(node ? nodeRules : []), ...(reactClassComp ? reactClassCompRules : []), ...(reactPropTypes ? reactPropTypesRules : []));
33
+ }, prettierRules, ...baseRules, ...regexRules, ...typescriptRules, ...importRules, ...expandConfig([...reactRules, ...jsxRules], react), ...expandConfig(typescriptTypeCheckRules, typescriptTypeCheck), ...expandConfig(nodeRules, node), ...expandConfig(reactClassCompRules, reactClassComp), ...expandConfig(reactPropTypesRules, reactPropTypes));
24
34
  }
package/dist/jsx.js CHANGED
@@ -224,7 +224,11 @@ export default tseslint.config({
224
224
  },
225
225
  ],
226
226
  "react/iframe-missing-sandbox": "error",
227
- "react/jsx-boolean-value": ["error", "never"],
227
+ "react/jsx-boolean-value": [
228
+ "error",
229
+ "never",
230
+ { assumeUndefinedIsFalse: false },
231
+ ],
228
232
  "react/jsx-child-element-spacing": "warn",
229
233
  // Formatting
230
234
  "react/jsx-closing-bracket-location": "off",
@@ -305,7 +309,7 @@ export default tseslint.config({
305
309
  "react/no-unknown-property": [
306
310
  "error",
307
311
  {
308
- // TODO: not released: requireDataLowercase: true,
312
+ requireDataLowercase: true,
309
313
  },
310
314
  ],
311
315
  "react/self-closing-comp": ["error", { component: true, html: true }],
package/dist/node.js CHANGED
@@ -55,6 +55,7 @@ export default tseslint.config({
55
55
  "n/prefer-global/text-encoder": ["error", "always"],
56
56
  "n/prefer-global/url": ["error", "always"],
57
57
  "n/prefer-global/url-search-params": ["error", "always"],
58
+ "n/prefer-node-protocol": "error",
58
59
  "n/prefer-promises/dns": "error",
59
60
  "n/prefer-promises/fs": "error",
60
61
  "n/process-exit-as-throw": "warn",
package/dist/react.js CHANGED
@@ -17,6 +17,10 @@ export default tseslint.config({
17
17
  "react-hooks/exhaustive-deps": "error",
18
18
  "react-hooks/rules-of-hooks": "error",
19
19
  "react/boolean-prop-naming": "off",
20
+ "react/checked-requires-onchange-or-readonly": ["error", {
21
+ ignoreExclusiveCheckedAttribute: false,
22
+ ignoreMissingProperties: false,
23
+ }],
20
24
  // Sometimes we do need `props` as a whole, e.g. for spreading
21
25
  "react/destructuring-assignment": "off",
22
26
  // Isn't useful
package/dist/regex.js CHANGED
@@ -67,7 +67,12 @@ export default tseslint.config({
67
67
  ],
68
68
  "regexp/no-trivially-nested-assertion": "error",
69
69
  "regexp/no-trivially-nested-quantifier": "error",
70
- "regexp/no-unused-capturing-group": "warn",
70
+ "regexp/no-unused-capturing-group": [
71
+ "warn",
72
+ {
73
+ allowNamed: false,
74
+ },
75
+ ],
71
76
  "regexp/no-useless-assertions": "error",
72
77
  "no-useless-backreference": "off",
73
78
  "regexp/no-useless-backreference": "error",
@@ -120,6 +125,18 @@ export default tseslint.config({
120
125
  "regexp/sort-flags": "error",
121
126
  "regexp/strict": "error",
122
127
  "regexp/unicode-escape": ["error", "unicodeEscape"],
128
+ "regexp/unicode-property": [
129
+ "error",
130
+ {
131
+ generalCategory: "never",
132
+ key: "short",
133
+ property: {
134
+ binary: "long",
135
+ generalCategory: "long",
136
+ script: "long",
137
+ },
138
+ },
139
+ ],
123
140
  "regexp/use-ignore-case": "error",
124
141
  },
125
142
  });
@@ -3,6 +3,8 @@ export default tseslint.config({
3
3
  rules: {
4
4
  // https://jc-verse.github.io/js-style-guide/typescript/type-checked#await-thenable
5
5
  "@typescript-eslint/await-thenable": "error",
6
+ // Not worth turning on
7
+ "@typescript-eslint/consistent-return": "off",
6
8
  // Also enforced by --isolatedModules
7
9
  // https://jc-verse.github.io/js-style-guide/typescript/type-checked#consistent-type-exports
8
10
  "@typescript-eslint/consistent-type-exports": [
@@ -63,7 +65,10 @@ export default tseslint.config({
63
65
  "@typescript-eslint/prefer-reduce-type-parameter": "error",
64
66
  "@typescript-eslint/prefer-regexp-exec": "warn",
65
67
  "@typescript-eslint/prefer-return-this-type": "warn",
66
- "@typescript-eslint/prefer-string-starts-ends-with": "warn",
68
+ "@typescript-eslint/prefer-string-starts-ends-with": [
69
+ "warn",
70
+ { allowSingleElementEquality: "never" },
71
+ ],
67
72
  // Not useful. Sometimes we intentionally make the function non-async.
68
73
  "@typescript-eslint/promise-function-async": "off",
69
74
  "@typescript-eslint/require-array-sort-compare": "error",
@@ -74,6 +79,7 @@ export default tseslint.config({
74
79
  "warn",
75
80
  {
76
81
  allowAny: false,
82
+ allowArray: false,
77
83
  allowBoolean: false,
78
84
  allowNullish: false,
79
85
  allowNumber: true,
@@ -85,5 +91,6 @@ export default tseslint.config({
85
91
  "@typescript-eslint/switch-exhaustiveness-check": "error",
86
92
  // Not very useful in practice... A lot of false-positives
87
93
  "@typescript-eslint/unbound-method": "off",
94
+ "@typescript-eslint/use-unknown-in-catch-callback-variables": "error",
88
95
  },
89
96
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-config-jc",
3
- "version": "5.0.2",
3
+ "version": "5.2.0",
4
4
  "description": "Josh-Cena's personal coding style",
5
5
  "type": "module",
6
6
  "repository": {
@@ -36,18 +36,18 @@
36
36
  "prepublishOnly": "yarn build"
37
37
  },
38
38
  "dependencies": {
39
- "@typescript-eslint/eslint-plugin": "^7.7.0",
40
- "@typescript-eslint/parser": "^7.7.0",
39
+ "@typescript-eslint/eslint-plugin": "^7.8.0",
40
+ "@typescript-eslint/parser": "^7.8.0",
41
41
  "eslint-config-prettier": "^9.1.0",
42
42
  "eslint-plugin-header": "^3.1.1",
43
43
  "eslint-plugin-import": "^2.29.1",
44
44
  "eslint-plugin-jsx-a11y": "^6.8.0",
45
- "eslint-plugin-n": "^17.2.1",
45
+ "eslint-plugin-n": "^17.4.0",
46
46
  "eslint-plugin-react": "^7.34.1",
47
- "eslint-plugin-react-hooks": "^4.6.0",
47
+ "eslint-plugin-react-hooks": "^4.6.2",
48
48
  "eslint-plugin-regexp": "^2.5.0",
49
49
  "globals": "^15.0.0",
50
- "typescript-eslint": "^7.7.0"
50
+ "typescript-eslint": "^7.8.0"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@types/eslint-config-prettier": "^6.11.3"
package/src/index.ts CHANGED
@@ -15,6 +15,18 @@ import nodeRules from "./node.js";
15
15
  import reactClassCompRules from "./react-class-comps.js";
16
16
  import reactPropTypesRules from "./react-prop-types.js";
17
17
 
18
+ function expandConfig(
19
+ config: TSESLint.FlatConfig.ConfigArray,
20
+ enabled: undefined | boolean | TSESLint.FlatConfig.FileSpec[],
21
+ ): TSESLint.FlatConfig.ConfigArray {
22
+ if (enabled === true) return config;
23
+ if (!enabled) return [];
24
+ return config.map((v) => ({
25
+ files: enabled,
26
+ ...v,
27
+ }));
28
+ }
29
+
18
30
  export default function configCreator({
19
31
  react,
20
32
  typescriptTypeCheck,
@@ -22,11 +34,11 @@ export default function configCreator({
22
34
  reactClassComp,
23
35
  reactPropTypes,
24
36
  }: {
25
- react?: boolean;
26
- typescriptTypeCheck?: boolean;
27
- node?: boolean;
28
- reactClassComp?: boolean;
29
- reactPropTypes?: boolean;
37
+ react?: boolean | TSESLint.FlatConfig.FileSpec[];
38
+ typescriptTypeCheck?: boolean | TSESLint.FlatConfig.FileSpec[];
39
+ node?: boolean | TSESLint.FlatConfig.FileSpec[];
40
+ reactClassComp?: boolean | TSESLint.FlatConfig.FileSpec[];
41
+ reactPropTypes?: boolean | TSESLint.FlatConfig.FileSpec[];
30
42
  } = {}): TSESLint.FlatConfig.ConfigArray {
31
43
  return tseslint.config(
32
44
  {
@@ -43,11 +55,10 @@ export default function configCreator({
43
55
  ...regexRules,
44
56
  ...typescriptRules,
45
57
  ...importRules,
46
- ...(react ? reactRules : []),
47
- ...(react ? jsxRules : []),
48
- ...(typescriptTypeCheck ? typescriptTypeCheckRules : []),
49
- ...(node ? nodeRules : []),
50
- ...(reactClassComp ? reactClassCompRules : []),
51
- ...(reactPropTypes ? reactPropTypesRules : []),
58
+ ...expandConfig([...reactRules, ...jsxRules], react),
59
+ ...expandConfig(typescriptTypeCheckRules, typescriptTypeCheck),
60
+ ...expandConfig(nodeRules, node),
61
+ ...expandConfig(reactClassCompRules, reactClassComp),
62
+ ...expandConfig(reactPropTypesRules, reactPropTypes),
52
63
  );
53
64
  }
package/src/jsx.ts CHANGED
@@ -264,7 +264,11 @@ export default tseslint.config({
264
264
 
265
265
  "react/iframe-missing-sandbox": "error",
266
266
 
267
- "react/jsx-boolean-value": ["error", "never"],
267
+ "react/jsx-boolean-value": [
268
+ "error",
269
+ "never",
270
+ { assumeUndefinedIsFalse: false },
271
+ ],
268
272
 
269
273
  "react/jsx-child-element-spacing": "warn",
270
274
 
@@ -381,7 +385,7 @@ export default tseslint.config({
381
385
  "react/no-unknown-property": [
382
386
  "error",
383
387
  {
384
- // TODO: not released: requireDataLowercase: true,
388
+ requireDataLowercase: true,
385
389
  },
386
390
  ],
387
391
 
package/src/node.ts CHANGED
@@ -87,6 +87,8 @@ export default tseslint.config({
87
87
 
88
88
  "n/prefer-global/url-search-params": ["error", "always"],
89
89
 
90
+ "n/prefer-node-protocol": "error",
91
+
90
92
  "n/prefer-promises/dns": "error",
91
93
 
92
94
  "n/prefer-promises/fs": "error",
package/src/react.ts CHANGED
@@ -21,6 +21,11 @@ export default tseslint.config({
21
21
 
22
22
  "react/boolean-prop-naming": "off",
23
23
 
24
+ "react/checked-requires-onchange-or-readonly": ["error", {
25
+ ignoreExclusiveCheckedAttribute: false,
26
+ ignoreMissingProperties: false,
27
+ }],
28
+
24
29
  // Sometimes we do need `props` as a whole, e.g. for spreading
25
30
  "react/destructuring-assignment": "off",
26
31
 
package/src/regex.ts CHANGED
@@ -30,7 +30,6 @@ export default tseslint.config({
30
30
 
31
31
  "regexp/no-contradiction-with-assertion": "error",
32
32
 
33
-
34
33
  "no-control-regex": "off",
35
34
  "regexp/no-control-character": "error",
36
35
 
@@ -49,7 +48,6 @@ export default tseslint.config({
49
48
 
50
49
  "regexp/no-empty-capturing-group": "error",
51
50
 
52
-
53
51
  "no-empty-character-class": "off",
54
52
  "regexp/no-empty-character-class": "error",
55
53
 
@@ -63,7 +61,6 @@ export default tseslint.config({
63
61
 
64
62
  "regexp/no-extra-lookaround-assertions": "error",
65
63
 
66
-
67
64
  "no-invalid-regexp": "off",
68
65
  "regexp/no-invalid-regexp": "error",
69
66
 
@@ -78,7 +75,6 @@ export default tseslint.config({
78
75
  { reportBacktrackingEnds: true },
79
76
  ],
80
77
 
81
-
82
78
  "no-misleading-character-class": "off",
83
79
  "regexp/no-misleading-unicode-character": ["error", { fixable: false }],
84
80
 
@@ -108,11 +104,15 @@ export default tseslint.config({
108
104
 
109
105
  "regexp/no-trivially-nested-quantifier": "error",
110
106
 
111
- "regexp/no-unused-capturing-group": "warn",
107
+ "regexp/no-unused-capturing-group": [
108
+ "warn",
109
+ {
110
+ allowNamed: false,
111
+ },
112
+ ],
112
113
 
113
114
  "regexp/no-useless-assertions": "error",
114
115
 
115
-
116
116
  "no-useless-backreference": "off",
117
117
  "regexp/no-useless-backreference": "error",
118
118
 
@@ -157,7 +157,6 @@ export default tseslint.config({
157
157
 
158
158
  "regexp/prefer-named-backreference": "error",
159
159
 
160
-
161
160
  "prefer-named-capture-group": "off",
162
161
  "regexp/prefer-named-capture-group": "warn",
163
162
 
@@ -190,7 +189,7 @@ export default tseslint.config({
190
189
  "regexp/prefer-w": "error",
191
190
 
192
191
  "require-unicode-regexp": "off",
193
-
192
+
194
193
  "regexp/require-unicode-regexp": "error",
195
194
 
196
195
  // Maybe in the future?
@@ -208,6 +207,19 @@ export default tseslint.config({
208
207
 
209
208
  "regexp/unicode-escape": ["error", "unicodeEscape"],
210
209
 
210
+ "regexp/unicode-property": [
211
+ "error",
212
+ {
213
+ generalCategory: "never",
214
+ key: "short",
215
+ property: {
216
+ binary: "long",
217
+ generalCategory: "long",
218
+ script: "long",
219
+ },
220
+ },
221
+ ],
222
+
211
223
  "regexp/use-ignore-case": "error",
212
224
  },
213
225
  });
@@ -5,6 +5,9 @@ export default tseslint.config({
5
5
  // https://jc-verse.github.io/js-style-guide/typescript/type-checked#await-thenable
6
6
  "@typescript-eslint/await-thenable": "error",
7
7
 
8
+ // Not worth turning on
9
+ "@typescript-eslint/consistent-return": "off",
10
+
8
11
  // Also enforced by --isolatedModules
9
12
  // https://jc-verse.github.io/js-style-guide/typescript/type-checked#consistent-type-exports
10
13
  "@typescript-eslint/consistent-type-exports": [
@@ -93,7 +96,10 @@ export default tseslint.config({
93
96
 
94
97
  "@typescript-eslint/prefer-return-this-type": "warn",
95
98
 
96
- "@typescript-eslint/prefer-string-starts-ends-with": "warn",
99
+ "@typescript-eslint/prefer-string-starts-ends-with": [
100
+ "warn",
101
+ { allowSingleElementEquality: "never" },
102
+ ],
97
103
 
98
104
  // Not useful. Sometimes we intentionally make the function non-async.
99
105
  "@typescript-eslint/promise-function-async": "off",
@@ -108,6 +114,7 @@ export default tseslint.config({
108
114
  "warn",
109
115
  {
110
116
  allowAny: false,
117
+ allowArray: false,
111
118
  allowBoolean: false,
112
119
  allowNullish: false,
113
120
  allowNumber: true,
@@ -122,5 +129,7 @@ export default tseslint.config({
122
129
 
123
130
  // Not very useful in practice... A lot of false-positives
124
131
  "@typescript-eslint/unbound-method": "off",
132
+
133
+ "@typescript-eslint/use-unknown-in-catch-callback-variables": "error",
125
134
  },
126
135
  });