@miskamyasa/eslint-config 0.0.0-stage → 2.0.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 +109 -2
- package/dist/index.d.ts +45 -0
- package/dist/index.js +440 -0
- package/package.json +68 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Denis Zaitsev
|
|
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
CHANGED
|
@@ -1,3 +1,110 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @miskamyasa/eslint-config
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Opinionated ESLint config for React + TypeScript projects.
|
|
4
|
+
|
|
5
|
+
## What's included
|
|
6
|
+
|
|
7
|
+
### JS/TS
|
|
8
|
+
|
|
9
|
+
- ESLint recommended rules
|
|
10
|
+
- TypeScript strict type checking (`typescript-eslint` recommended + strictTypeChecked + stylisticTypeChecked)
|
|
11
|
+
- React rules (`@eslint-react/eslint-plugin` recommended-typescript + `react-hooks`)
|
|
12
|
+
- Import ordering and validation (`eslint-plugin-import-x` + `eslint-plugin-unused-imports`)
|
|
13
|
+
- Stylistic formatting (`@stylistic/eslint-plugin` with double quotes, no semicolons, 2-space indent, stroustrup brace style)
|
|
14
|
+
- CommonJS overrides for `.js`/`.cjs` files
|
|
15
|
+
|
|
16
|
+
### Data files (enabled by default)
|
|
17
|
+
|
|
18
|
+
- JSON/JSONC/JSON5 linting (`eslint-plugin-jsonc`)
|
|
19
|
+
|
|
20
|
+
## Requirements
|
|
21
|
+
|
|
22
|
+
- Node.js >= 22
|
|
23
|
+
- ESLint >= 9
|
|
24
|
+
- TypeScript >= 5
|
|
25
|
+
|
|
26
|
+
## Install
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
pnpm add -D @miskamyasa/eslint-config eslint typescript
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
Create `eslint.config.ts` in your project root:
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
import createConfig from "@miskamyasa/eslint-config"
|
|
38
|
+
|
|
39
|
+
export default createConfig({
|
|
40
|
+
tsconfigRootDir: import.meta.dirname,
|
|
41
|
+
})
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
> ESLint 10 requires `jiti` for TypeScript config files: `pnpm add -D jiti`
|
|
45
|
+
|
|
46
|
+
## Options
|
|
47
|
+
|
|
48
|
+
| Option | Type | Default | Description |
|
|
49
|
+
|---|---|---|---|
|
|
50
|
+
| `tsconfigRootDir` | `string` | `process.cwd()` | Root directory for TypeScript project service |
|
|
51
|
+
| `ignores` | `string[]` | `[]` | Additional glob patterns to ignore |
|
|
52
|
+
| `jsonc` | `boolean` | `true` | Enable JSON/JSONC/JSON5 linting |
|
|
53
|
+
|
|
54
|
+
### Disabling configs
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
export default createConfig({
|
|
58
|
+
tsconfigRootDir: import.meta.dirname,
|
|
59
|
+
jsonc: false,
|
|
60
|
+
})
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Overrides
|
|
64
|
+
|
|
65
|
+
Pass additional ESLint config objects after the options to override or extend rules:
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
import createConfig from "@miskamyasa/eslint-config"
|
|
69
|
+
|
|
70
|
+
export default createConfig(
|
|
71
|
+
{tsconfigRootDir: import.meta.dirname},
|
|
72
|
+
{
|
|
73
|
+
rules: {
|
|
74
|
+
"no-console": "off",
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Named exports
|
|
81
|
+
|
|
82
|
+
Individual config functions are available for advanced composition:
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
import {
|
|
86
|
+
typescript,
|
|
87
|
+
stylistic,
|
|
88
|
+
imports,
|
|
89
|
+
react,
|
|
90
|
+
javascript,
|
|
91
|
+
jsonc,
|
|
92
|
+
} from "@miskamyasa/eslint-config"
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Key style decisions
|
|
96
|
+
|
|
97
|
+
- Double quotes
|
|
98
|
+
- No semicolons
|
|
99
|
+
- 2-space indentation
|
|
100
|
+
- Stroustrup brace style
|
|
101
|
+
- No curly spacing (`{a}` not `{ a }`)
|
|
102
|
+
- Max line length: 120 (warning)
|
|
103
|
+
- Unix line endings
|
|
104
|
+
- Default exports disallowed (`import-x/no-default-export`)
|
|
105
|
+
- Imports sorted alphabetically with React first
|
|
106
|
+
- Unused imports auto-removed
|
|
107
|
+
|
|
108
|
+
## License
|
|
109
|
+
|
|
110
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { createTypeScriptImportResolver } from "eslint-import-resolver-typescript";
|
|
2
|
+
import { Linter } from "eslint";
|
|
3
|
+
declare function createImportsConfig(): Linter.Config[];
|
|
4
|
+
export declare function javascript(): Linter.Config[];
|
|
5
|
+
export declare function jsonc(): Linter.Config[];
|
|
6
|
+
export declare function react(): Linter.Config[];
|
|
7
|
+
export declare function stylistic(): Linter.Config[];
|
|
8
|
+
export declare function typescript(options: {
|
|
9
|
+
tsconfigRootDir: string;
|
|
10
|
+
}): Linter.Config[];
|
|
11
|
+
export type ConfigItem = Linter.Config;
|
|
12
|
+
export type OptionsConfig = {
|
|
13
|
+
tsconfigRootDir?: string;
|
|
14
|
+
ignores?: string[];
|
|
15
|
+
jsonc?: boolean;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Construct an array of ESLint flat config items.
|
|
19
|
+
*
|
|
20
|
+
* @param options - The options for generating the ESLint configurations.
|
|
21
|
+
* @param userConfigs - Additional user configurations to be appended.
|
|
22
|
+
* @returns The composed ESLint configurations.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```js
|
|
26
|
+
* // eslint.config.js
|
|
27
|
+
* import createConfig from "@miskamyasa/eslint-config"
|
|
28
|
+
*
|
|
29
|
+
* export default createConfig({
|
|
30
|
+
* tsconfigRootDir: import.meta.dirname,
|
|
31
|
+
* })
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare function createConfig(options?: OptionsConfig, ...userConfigs: Linter.Config[]): Linter.Config[];
|
|
35
|
+
export declare const GLOB_JS = "**/*.?([cm])js";
|
|
36
|
+
export declare const GLOB_JSX = "**/*.jsx";
|
|
37
|
+
export declare const GLOB_CJS = "**/*.cjs";
|
|
38
|
+
export declare const GLOB_TS = "**/*.?([cm])ts";
|
|
39
|
+
export declare const GLOB_TSX = "**/*.tsx";
|
|
40
|
+
export declare const GLOB_SRC: string[];
|
|
41
|
+
export declare const GLOB_JSON = "**/*.json";
|
|
42
|
+
export declare const GLOB_JSONC = "**/*.jsonc";
|
|
43
|
+
export declare const GLOB_JSON5 = "**/*.json5";
|
|
44
|
+
export declare const GLOB_EXCLUDE: string[];
|
|
45
|
+
export { createConfig as default, createTypeScriptImportResolver, createImportsConfig as imports };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
import { createTypeScriptImportResolver, createTypeScriptImportResolver as createTypeScriptImportResolver$1 } from "eslint-import-resolver-typescript";
|
|
2
|
+
import { flatConfigs } from "eslint-plugin-import-x";
|
|
3
|
+
import unusedImports from "eslint-plugin-unused-imports";
|
|
4
|
+
import jsoncPlugin from "eslint-plugin-jsonc";
|
|
5
|
+
import * as jsoncParser from "jsonc-eslint-parser";
|
|
6
|
+
import reactPlugin from "@eslint-react/eslint-plugin";
|
|
7
|
+
import reactHooksPlugin from "eslint-plugin-react-hooks";
|
|
8
|
+
import stylisticPlugin from "@stylistic/eslint-plugin";
|
|
9
|
+
import { configs, parser } from "typescript-eslint";
|
|
10
|
+
import eslint from "@eslint/js";
|
|
11
|
+
// src/globs.ts
|
|
12
|
+
const GLOB_JS = "**/*.?([cm])js";
|
|
13
|
+
const GLOB_JSX = "**/*.jsx";
|
|
14
|
+
const GLOB_CJS = "**/*.cjs";
|
|
15
|
+
const GLOB_TS = "**/*.?([cm])ts";
|
|
16
|
+
const GLOB_TSX = "**/*.tsx";
|
|
17
|
+
const GLOB_SRC = [
|
|
18
|
+
GLOB_JS,
|
|
19
|
+
GLOB_JSX,
|
|
20
|
+
GLOB_TS,
|
|
21
|
+
GLOB_TSX
|
|
22
|
+
];
|
|
23
|
+
const GLOB_JSON = "**/*.json";
|
|
24
|
+
const GLOB_JSONC = "**/*.jsonc";
|
|
25
|
+
const GLOB_JSON5 = "**/*.json5";
|
|
26
|
+
const GLOB_EXCLUDE = [
|
|
27
|
+
"**/node_modules",
|
|
28
|
+
"**/dist",
|
|
29
|
+
"**/package-lock.json",
|
|
30
|
+
"**/yarn.lock",
|
|
31
|
+
"**/pnpm-lock.yaml",
|
|
32
|
+
"**/bun.lockb"
|
|
33
|
+
];
|
|
34
|
+
// src/configs/imports.ts
|
|
35
|
+
function createImportsConfig() {
|
|
36
|
+
return [
|
|
37
|
+
{
|
|
38
|
+
name: "miskamyasa/imports/setup",
|
|
39
|
+
plugins: {
|
|
40
|
+
...flatConfigs.recommended.plugins,
|
|
41
|
+
"unused-imports": unusedImports
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: "miskamyasa/imports/recommended-rules",
|
|
46
|
+
files: GLOB_SRC,
|
|
47
|
+
rules: flatConfigs.recommended.rules
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: "miskamyasa/imports/react",
|
|
51
|
+
files: GLOB_SRC,
|
|
52
|
+
settings: flatConfigs.react.settings,
|
|
53
|
+
languageOptions: flatConfigs.react.languageOptions
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: "miskamyasa/imports/typescript",
|
|
57
|
+
files: GLOB_SRC,
|
|
58
|
+
settings: { "import-x/resolver-next": [createTypeScriptImportResolver$1()] }
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: "miskamyasa/imports/rules",
|
|
62
|
+
files: GLOB_SRC,
|
|
63
|
+
rules: {
|
|
64
|
+
"import-x/namespace": "off",
|
|
65
|
+
"import-x/newline-after-import": ["error", { count: 1 }],
|
|
66
|
+
"import-x/named": "off",
|
|
67
|
+
"import-x/no-cycle": ["error", {
|
|
68
|
+
ignoreExternal: true,
|
|
69
|
+
maxDepth: 10
|
|
70
|
+
}],
|
|
71
|
+
"import-x/no-duplicates": "error",
|
|
72
|
+
"import-x/no-useless-path-segments": "error",
|
|
73
|
+
"import-x/no-anonymous-default-export": "error",
|
|
74
|
+
"import-x/no-default-export": "error",
|
|
75
|
+
"import-x/order": ["error", {
|
|
76
|
+
alphabetize: {
|
|
77
|
+
caseInsensitive: true,
|
|
78
|
+
order: "asc"
|
|
79
|
+
},
|
|
80
|
+
groups: [
|
|
81
|
+
"builtin",
|
|
82
|
+
"external",
|
|
83
|
+
"internal",
|
|
84
|
+
"parent",
|
|
85
|
+
"sibling"
|
|
86
|
+
],
|
|
87
|
+
"newlines-between": "always",
|
|
88
|
+
pathGroups: [{
|
|
89
|
+
group: "external",
|
|
90
|
+
pattern: "react+(|-native)",
|
|
91
|
+
position: "before"
|
|
92
|
+
}],
|
|
93
|
+
pathGroupsExcludedImportTypes: ["react", "react-native"]
|
|
94
|
+
}],
|
|
95
|
+
"import-x/no-absolute-path": "error",
|
|
96
|
+
"unused-imports/no-unused-imports": "error",
|
|
97
|
+
"unused-imports/no-unused-vars": ["error", {
|
|
98
|
+
vars: "all",
|
|
99
|
+
varsIgnorePattern: "^_",
|
|
100
|
+
args: "after-used",
|
|
101
|
+
argsIgnorePattern: "^_"
|
|
102
|
+
}]
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
];
|
|
106
|
+
}
|
|
107
|
+
// src/configs/javascript.ts
|
|
108
|
+
function javascript() {
|
|
109
|
+
return [{
|
|
110
|
+
name: "miskamyasa/javascript/overrides",
|
|
111
|
+
files: ["**/*.js", GLOB_CJS],
|
|
112
|
+
languageOptions: { globals: {
|
|
113
|
+
require: "readonly",
|
|
114
|
+
module: "readonly",
|
|
115
|
+
__dirname: "readonly"
|
|
116
|
+
} },
|
|
117
|
+
rules: {
|
|
118
|
+
"@typescript-eslint/explicit-function-return-type": "off",
|
|
119
|
+
"@typescript-eslint/no-require-imports": "off",
|
|
120
|
+
"@typescript-eslint/no-var-requires": "off"
|
|
121
|
+
}
|
|
122
|
+
}];
|
|
123
|
+
}
|
|
124
|
+
// src/configs/jsonc.ts
|
|
125
|
+
const JSON_FILES = [
|
|
126
|
+
GLOB_JSON,
|
|
127
|
+
GLOB_JSONC,
|
|
128
|
+
GLOB_JSON5
|
|
129
|
+
];
|
|
130
|
+
function jsonc() {
|
|
131
|
+
const preset = jsoncPlugin.configs["flat/recommended-with-jsonc"];
|
|
132
|
+
return [
|
|
133
|
+
{
|
|
134
|
+
name: "miskamyasa/jsonc/setup",
|
|
135
|
+
plugins: preset[0].plugins
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
...preset[1],
|
|
139
|
+
name: "miskamyasa/jsonc/parser-overrides"
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
name: "miskamyasa/jsonc/recommended-rules",
|
|
143
|
+
files: JSON_FILES,
|
|
144
|
+
rules: preset[2].rules
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
name: "miskamyasa/jsonc/stylistic-rules",
|
|
148
|
+
files: JSON_FILES,
|
|
149
|
+
languageOptions: { parser: jsoncParser },
|
|
150
|
+
rules: {
|
|
151
|
+
"jsonc/indent": ["error", 2],
|
|
152
|
+
"jsonc/key-spacing": "error",
|
|
153
|
+
"jsonc/array-bracket-spacing": ["error", "never"],
|
|
154
|
+
"jsonc/sort-keys": "off"
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
name: "miskamyasa/jsonc/json-rules",
|
|
159
|
+
files: [GLOB_JSON],
|
|
160
|
+
languageOptions: { parser: jsoncParser },
|
|
161
|
+
rules: { "jsonc/comma-dangle": ["error", "never"] }
|
|
162
|
+
}
|
|
163
|
+
];
|
|
164
|
+
}
|
|
165
|
+
// src/configs/react.ts
|
|
166
|
+
function react() {
|
|
167
|
+
const preset = reactPlugin.configs["recommended-typescript"];
|
|
168
|
+
return [
|
|
169
|
+
{
|
|
170
|
+
name: "miskamyasa/react/setup",
|
|
171
|
+
plugins: {
|
|
172
|
+
...preset.plugins,
|
|
173
|
+
"react-hooks": reactHooksPlugin
|
|
174
|
+
},
|
|
175
|
+
settings: preset.settings
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
name: "miskamyasa/react/rules",
|
|
179
|
+
files: GLOB_SRC,
|
|
180
|
+
rules: preset.rules
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
name: "miskamyasa/react/hooks-rules",
|
|
184
|
+
files: GLOB_SRC,
|
|
185
|
+
rules: {
|
|
186
|
+
"react-hooks/rules-of-hooks": "error",
|
|
187
|
+
"react-hooks/exhaustive-deps": "error"
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
];
|
|
191
|
+
}
|
|
192
|
+
// src/configs/stylistic.ts
|
|
193
|
+
const JSX_SORT_PROPS_DEPRECATION_WARNING = "[@stylistic/eslint-plugin]: You are using deprecated rule(\"jsx-sort-props\")";
|
|
194
|
+
const jsxSortPropsRule = stylisticPlugin.rules["jsx-sort-props"];
|
|
195
|
+
const patchedStylisticPlugin = {
|
|
196
|
+
...stylisticPlugin,
|
|
197
|
+
rules: {
|
|
198
|
+
...stylisticPlugin.rules,
|
|
199
|
+
"jsx-sort-props": {
|
|
200
|
+
...jsxSortPropsRule,
|
|
201
|
+
create(context) {
|
|
202
|
+
const warn = console.warn;
|
|
203
|
+
console.warn = (...args) => {
|
|
204
|
+
if (typeof args[0] === "string" && args[0].startsWith(JSX_SORT_PROPS_DEPRECATION_WARNING)) return;
|
|
205
|
+
warn(...args);
|
|
206
|
+
};
|
|
207
|
+
try {
|
|
208
|
+
return jsxSortPropsRule.create(context);
|
|
209
|
+
} finally {
|
|
210
|
+
console.warn = warn;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
function stylistic() {
|
|
217
|
+
return [
|
|
218
|
+
{
|
|
219
|
+
name: "miskamyasa/stylistic/setup",
|
|
220
|
+
plugins: { "@stylistic": patchedStylisticPlugin }
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
name: "miskamyasa/stylistic/disable-legacy",
|
|
224
|
+
files: GLOB_SRC,
|
|
225
|
+
rules: stylisticPlugin.configs["disable-legacy"].rules
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
name: "miskamyasa/stylistic/rules",
|
|
229
|
+
files: GLOB_SRC,
|
|
230
|
+
rules: {
|
|
231
|
+
"@stylistic/block-spacing": ["error", "never"],
|
|
232
|
+
"@stylistic/comma-dangle": ["error", "always-multiline"],
|
|
233
|
+
"@stylistic/indent": ["error", 2],
|
|
234
|
+
"@stylistic/jsx-closing-bracket-location": ["error", {
|
|
235
|
+
"nonEmpty": "after-props",
|
|
236
|
+
"selfClosing": "after-props"
|
|
237
|
+
}],
|
|
238
|
+
"@stylistic/jsx-curly-spacing": ["error", {
|
|
239
|
+
"attributes": { "allowMultiline": false },
|
|
240
|
+
"children": true,
|
|
241
|
+
"when": "never"
|
|
242
|
+
}],
|
|
243
|
+
"@stylistic/jsx-first-prop-new-line": ["error", "multiline-multiprop"],
|
|
244
|
+
"@stylistic/jsx-indent-props": ["error", 2],
|
|
245
|
+
"@stylistic/jsx-max-props-per-line": ["error", { "maximum": 1 }],
|
|
246
|
+
"@stylistic/jsx-sort-props": ["error", {
|
|
247
|
+
"callbacksLast": true,
|
|
248
|
+
"ignoreCase": true,
|
|
249
|
+
"noSortAlphabetically": false,
|
|
250
|
+
"reservedFirst": true,
|
|
251
|
+
"shorthandFirst": true,
|
|
252
|
+
"shorthandLast": false
|
|
253
|
+
}],
|
|
254
|
+
"@stylistic/jsx-tag-spacing": ["error", {
|
|
255
|
+
"afterOpening": "never",
|
|
256
|
+
"beforeClosing": "allow",
|
|
257
|
+
"beforeSelfClosing": "allow",
|
|
258
|
+
"closingSlash": "never"
|
|
259
|
+
}],
|
|
260
|
+
"@stylistic/jsx-wrap-multilines": ["error", {
|
|
261
|
+
"arrow": "parens",
|
|
262
|
+
"assignment": "parens",
|
|
263
|
+
"condition": "ignore",
|
|
264
|
+
"declaration": "parens",
|
|
265
|
+
"logical": "ignore",
|
|
266
|
+
"prop": "ignore",
|
|
267
|
+
"return": "parens"
|
|
268
|
+
}],
|
|
269
|
+
"@stylistic/key-spacing": ["error", {
|
|
270
|
+
"afterColon": true,
|
|
271
|
+
"mode": "strict"
|
|
272
|
+
}],
|
|
273
|
+
"@stylistic/keyword-spacing": ["error", {
|
|
274
|
+
"after": true,
|
|
275
|
+
"before": true
|
|
276
|
+
}],
|
|
277
|
+
"@stylistic/linebreak-style": ["error", "unix"],
|
|
278
|
+
"@stylistic/max-len": ["warn", { "code": 120 }],
|
|
279
|
+
"@stylistic/no-multiple-empty-lines": ["error", {
|
|
280
|
+
"max": 1,
|
|
281
|
+
"maxEOF": 0,
|
|
282
|
+
"maxBOF": 0
|
|
283
|
+
}],
|
|
284
|
+
"no-multi-spaces": "error",
|
|
285
|
+
"@stylistic/object-curly-newline": ["error", {
|
|
286
|
+
"consistent": true,
|
|
287
|
+
"multiline": true
|
|
288
|
+
}],
|
|
289
|
+
"@stylistic/object-curly-spacing": ["error", "never"],
|
|
290
|
+
"@stylistic/object-property-newline": ["error", { "allowAllPropertiesOnSameLine": true }],
|
|
291
|
+
"@stylistic/operator-linebreak": [
|
|
292
|
+
"error",
|
|
293
|
+
"before",
|
|
294
|
+
{ "overrides": { "=": "after" } }
|
|
295
|
+
],
|
|
296
|
+
"@stylistic/quotes": [
|
|
297
|
+
"error",
|
|
298
|
+
"double",
|
|
299
|
+
{ "avoidEscape": true }
|
|
300
|
+
],
|
|
301
|
+
"@stylistic/semi": ["error", "never"],
|
|
302
|
+
"@stylistic/space-before-blocks": ["error", "always"],
|
|
303
|
+
"@stylistic/space-infix-ops": "error",
|
|
304
|
+
"@stylistic/switch-colon-spacing": ["error", {
|
|
305
|
+
"after": true,
|
|
306
|
+
"before": false
|
|
307
|
+
}],
|
|
308
|
+
"@stylistic/type-annotation-spacing": "error",
|
|
309
|
+
"@stylistic/member-delimiter-style": ["error", {
|
|
310
|
+
"multilineDetection": "brackets",
|
|
311
|
+
"multiline": {
|
|
312
|
+
"delimiter": "comma",
|
|
313
|
+
"requireLast": true
|
|
314
|
+
},
|
|
315
|
+
"singleline": {
|
|
316
|
+
"delimiter": "comma",
|
|
317
|
+
"requireLast": false
|
|
318
|
+
},
|
|
319
|
+
"overrides": { "interface": {
|
|
320
|
+
"multiline": { "delimiter": "none" },
|
|
321
|
+
"singleline": { "delimiter": "comma" }
|
|
322
|
+
} }
|
|
323
|
+
}],
|
|
324
|
+
"comma-spacing": ["error", {
|
|
325
|
+
"before": false,
|
|
326
|
+
"after": true
|
|
327
|
+
}],
|
|
328
|
+
"no-console": ["warn", { allow: ["warn", "error"] }],
|
|
329
|
+
"brace-style": [
|
|
330
|
+
"error",
|
|
331
|
+
"stroustrup",
|
|
332
|
+
{ "allowSingleLine": false }
|
|
333
|
+
],
|
|
334
|
+
"curly": ["error", "all"],
|
|
335
|
+
"no-use-before-define": "error",
|
|
336
|
+
"no-restricted-syntax": ["error", {
|
|
337
|
+
"selector": ["SwitchStatement:has(SwitchCase > BlockStatement.consequent)", "> SwitchCase:has(> *.consequent[type!='BlockStatement'])"].join(" "),
|
|
338
|
+
"message": "Switch cases must consistently use braces when any case uses braces"
|
|
339
|
+
}]
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
];
|
|
343
|
+
}
|
|
344
|
+
// src/configs/typescript.ts
|
|
345
|
+
function typescript(options) {
|
|
346
|
+
const recommended = configs.recommended;
|
|
347
|
+
const strictTypeChecked = configs.strictTypeChecked;
|
|
348
|
+
const stylisticTypeChecked = configs.stylisticTypeChecked;
|
|
349
|
+
return [
|
|
350
|
+
{
|
|
351
|
+
name: "miskamyasa/typescript/setup",
|
|
352
|
+
plugins: recommended[0].plugins,
|
|
353
|
+
languageOptions: { parser }
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
...recommended[1],
|
|
357
|
+
name: "miskamyasa/typescript/eslint-recommended"
|
|
358
|
+
},
|
|
359
|
+
{
|
|
360
|
+
name: "miskamyasa/typescript/recommended-rules",
|
|
361
|
+
files: GLOB_SRC,
|
|
362
|
+
rules: recommended[2].rules
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
name: "miskamyasa/typescript/strict-type-checked-rules",
|
|
366
|
+
files: GLOB_SRC,
|
|
367
|
+
rules: strictTypeChecked[2].rules
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
name: "miskamyasa/typescript/stylistic-type-checked-rules",
|
|
371
|
+
files: GLOB_SRC,
|
|
372
|
+
rules: stylisticTypeChecked[2].rules
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
name: "miskamyasa/typescript/language-options",
|
|
376
|
+
files: GLOB_SRC,
|
|
377
|
+
languageOptions: { parserOptions: {
|
|
378
|
+
projectService: true,
|
|
379
|
+
tsconfigRootDir: options.tsconfigRootDir
|
|
380
|
+
} }
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
name: "miskamyasa/typescript/rules",
|
|
384
|
+
files: GLOB_SRC,
|
|
385
|
+
rules: {
|
|
386
|
+
"@typescript-eslint/consistent-type-definitions": ["error", "type"],
|
|
387
|
+
"@typescript-eslint/no-unused-vars": "off",
|
|
388
|
+
"@typescript-eslint/restrict-template-expressions": ["error", {
|
|
389
|
+
allowNumber: true,
|
|
390
|
+
allowBoolean: false,
|
|
391
|
+
allowAny: false,
|
|
392
|
+
allowNullish: false,
|
|
393
|
+
allowRegExp: false
|
|
394
|
+
}],
|
|
395
|
+
"@typescript-eslint/no-misused-promises": ["error", { checksVoidReturn: { attributes: false } }],
|
|
396
|
+
"@typescript-eslint/switch-exhaustiveness-check": ["error", { allowDefaultCaseForExhaustiveSwitch: false }]
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
];
|
|
400
|
+
}
|
|
401
|
+
// src/factory.ts
|
|
402
|
+
/**
|
|
403
|
+
* Construct an array of ESLint flat config items.
|
|
404
|
+
*
|
|
405
|
+
* @param options - The options for generating the ESLint configurations.
|
|
406
|
+
* @param userConfigs - Additional user configurations to be appended.
|
|
407
|
+
* @returns The composed ESLint configurations.
|
|
408
|
+
*
|
|
409
|
+
* @example
|
|
410
|
+
* ```js
|
|
411
|
+
* // eslint.config.js
|
|
412
|
+
* import createConfig from "@miskamyasa/eslint-config"
|
|
413
|
+
*
|
|
414
|
+
* export default createConfig({
|
|
415
|
+
* tsconfigRootDir: import.meta.dirname,
|
|
416
|
+
* })
|
|
417
|
+
* ```
|
|
418
|
+
*/
|
|
419
|
+
function createConfig(options = {}, ...userConfigs) {
|
|
420
|
+
const { tsconfigRootDir = process.cwd(), ignores = [], jsonc: enableJsonc = true } = options;
|
|
421
|
+
return [
|
|
422
|
+
{
|
|
423
|
+
name: "miskamyasa/ignores",
|
|
424
|
+
ignores: [...GLOB_EXCLUDE, ...ignores]
|
|
425
|
+
},
|
|
426
|
+
{
|
|
427
|
+
name: "miskamyasa/eslint/recommended",
|
|
428
|
+
files: GLOB_SRC,
|
|
429
|
+
rules: eslint.configs.recommended.rules
|
|
430
|
+
},
|
|
431
|
+
...typescript({ tsconfigRootDir }),
|
|
432
|
+
...createImportsConfig(),
|
|
433
|
+
...react(),
|
|
434
|
+
...stylistic(),
|
|
435
|
+
...enableJsonc ? jsonc() : [],
|
|
436
|
+
...javascript(),
|
|
437
|
+
...userConfigs
|
|
438
|
+
];
|
|
439
|
+
}
|
|
440
|
+
export { GLOB_CJS, GLOB_EXCLUDE, GLOB_JS, GLOB_JSON, GLOB_JSON5, GLOB_JSONC, GLOB_JSX, GLOB_SRC, GLOB_TS, GLOB_TSX, createConfig, createConfig as default, createTypeScriptImportResolver, createImportsConfig as imports, javascript, jsonc, react, stylistic, typescript };
|
package/package.json
CHANGED
|
@@ -1,6 +1,70 @@
|
|
|
1
1
|
{
|
|
2
|
+
"author": "Denis <MiskaMyasa> Zaitsev",
|
|
3
|
+
"bugs": {
|
|
4
|
+
"url": "https://github.com/Miskamyasa/eslint-config/issues"
|
|
5
|
+
},
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"@eslint-react/eslint-plugin": "5.28.8",
|
|
8
|
+
"@eslint/js": "10.0.1",
|
|
9
|
+
"@stylistic/eslint-plugin": "5.10.0",
|
|
10
|
+
"eslint-import-resolver-typescript": "4.4.5",
|
|
11
|
+
"eslint-plugin-import-x": "4.17.1",
|
|
12
|
+
"eslint-plugin-jsonc": "3.4.2",
|
|
13
|
+
"eslint-plugin-react-hooks": "7.1.1",
|
|
14
|
+
"eslint-plugin-unused-imports": "4.4.1",
|
|
15
|
+
"jsonc-eslint-parser": "3.3.0",
|
|
16
|
+
"typescript-eslint": "8.72.0"
|
|
17
|
+
},
|
|
18
|
+
"description": "Opinionated ESLint config for React + TypeScript projects",
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@types/node": "26.6.5",
|
|
21
|
+
"eslint": "^10.13.0",
|
|
22
|
+
"jiti": "2.7.0",
|
|
23
|
+
"tsdown": "0.23.2",
|
|
24
|
+
"typescript": "6.0.3"
|
|
25
|
+
},
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"import": "./dist/index.js"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"dist"
|
|
34
|
+
],
|
|
35
|
+
"homepage": "https://github.com/Miskamyasa/eslint-config",
|
|
36
|
+
"keywords": [
|
|
37
|
+
"eslint",
|
|
38
|
+
"eslint-config",
|
|
39
|
+
"typescript",
|
|
40
|
+
"react",
|
|
41
|
+
"stylistic"
|
|
42
|
+
],
|
|
43
|
+
"license": "MIT",
|
|
44
|
+
"main": "./dist/index.js",
|
|
45
|
+
"module": "./dist/index.js",
|
|
2
46
|
"name": "@miskamyasa/eslint-config",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
|
|
6
|
-
|
|
47
|
+
"packageManager": "pnpm@12.11.2",
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"eslint": ">=10.0.0",
|
|
50
|
+
"typescript": ">=5.0.0 && <7.0.0"
|
|
51
|
+
},
|
|
52
|
+
"private": false,
|
|
53
|
+
"publishConfig": {
|
|
54
|
+
"access": "public"
|
|
55
|
+
},
|
|
56
|
+
"repository": {
|
|
57
|
+
"type": "git",
|
|
58
|
+
"url": "git+ssh://github.com/Miskamyasa/eslint-config.git"
|
|
59
|
+
},
|
|
60
|
+
"scripts": {
|
|
61
|
+
"build": "tsdown",
|
|
62
|
+
"lint": "eslint .",
|
|
63
|
+
"prepublishOnly": "pnpm run build",
|
|
64
|
+
"typecheck": "tsc --noEmit"
|
|
65
|
+
},
|
|
66
|
+
"sideEffects": false,
|
|
67
|
+
"type": "module",
|
|
68
|
+
"types": "./dist/index.d.ts",
|
|
69
|
+
"version": "2.0.1"
|
|
70
|
+
}
|