@maneko/eslint-config 0.1.3
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 +204 -0
- package/index.d.ts +19 -0
- package/index.js +156 -0
- package/package.json +75 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Maneko
|
|
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,204 @@
|
|
|
1
|
+
# @maneko/eslint-config
|
|
2
|
+
|
|
3
|
+
[](https://github.com/maneko-org/eslint-config/stargazers)
|
|
4
|
+
[](https://github.com/maneko-org/eslint-config/network/members)
|
|
5
|
+
[](https://github.com/maneko-org/eslint-config/pulls)
|
|
6
|
+
[](https://github.com/maneko-org/eslint-config/issues)
|
|
7
|
+
[](https://github.com/maneko-org/eslint-config/graphs/contributors)
|
|
8
|
+
[](https://github.com/maneko-org/eslint-config/blob/main/LICENSE)
|
|
9
|
+
|
|
10
|
+
A shared, ESLint config four our projects - simple, consistent and modern. Inspired by `@antfu/eslint-config`, tailored for real-world apps and libraries.
|
|
11
|
+
|
|
12
|
+
## Why use this
|
|
13
|
+
|
|
14
|
+
- **One-line setup** for a sensible, opinionated ESLint Flat config.
|
|
15
|
+
- Works with JavaScript and TypeScript (TS support is opt-in).
|
|
16
|
+
- Opt-in integrations: React, NextJS, Vue, Svelte, Astro, Solid.
|
|
17
|
+
- Fixable stylistic rules that play nicely with `eslint --fix`, CI and `lint-staged`.
|
|
18
|
+
- ESM-first and composable - easy to extend or override.
|
|
19
|
+
|
|
20
|
+
> **Note:** This preset is opinionated. It aims to reduce bikeshedding and keep diffs small. If you need different choices - override rules locally or fork.
|
|
21
|
+
|
|
22
|
+
## Quick start
|
|
23
|
+
|
|
24
|
+
Install preset + eslint in your project:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# pnpm (recommended)
|
|
28
|
+
pnpm add -D eslint @maneko/eslint-config
|
|
29
|
+
|
|
30
|
+
# yarn
|
|
31
|
+
yarn add -D eslint @maneko/eslint-config
|
|
32
|
+
|
|
33
|
+
# npm
|
|
34
|
+
npm install -D eslint @maneko/eslint-config
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
> **Why install `eslint` in the project?**
|
|
38
|
+
> The VS Code ESLint extension resolves `eslint` from the project root `node_modules`. Install it in the host project so the editor finds the binary and plugins.
|
|
39
|
+
|
|
40
|
+
Create `eslint.config.mjs` in your project root:
|
|
41
|
+
|
|
42
|
+
```js
|
|
43
|
+
import { eslint } from '@maneko/eslint-config';
|
|
44
|
+
|
|
45
|
+
export default eslint({
|
|
46
|
+
// A simple example
|
|
47
|
+
jsx: { a11y: true },
|
|
48
|
+
react: true
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Minimal preset:
|
|
53
|
+
|
|
54
|
+
```js
|
|
55
|
+
import { eslint } from '@maneko/eslint-config';
|
|
56
|
+
|
|
57
|
+
export default eslint();
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Usage & recipes
|
|
61
|
+
|
|
62
|
+
### JavaScript
|
|
63
|
+
|
|
64
|
+
```js
|
|
65
|
+
import { eslint } from '@maneko/eslint-config';
|
|
66
|
+
|
|
67
|
+
export default eslint();
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### TypeScript + React
|
|
71
|
+
|
|
72
|
+
```js
|
|
73
|
+
import { eslint } from '@maneko/eslint-config';
|
|
74
|
+
|
|
75
|
+
export default eslint({
|
|
76
|
+
typescript: true,
|
|
77
|
+
react: { a11y: true }
|
|
78
|
+
});
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Combine with legacy `.eslintrc` (FlatCompat)
|
|
82
|
+
|
|
83
|
+
If you need to migrate legacy configs, use `@eslint/eslintrc` + `FlatCompat`:
|
|
84
|
+
|
|
85
|
+
```js
|
|
86
|
+
import { FlatCompat } from '@eslint/eslintrc';
|
|
87
|
+
import { eslint } from '@maneko/eslint-config';
|
|
88
|
+
|
|
89
|
+
const compat = new FlatCompat();
|
|
90
|
+
export default eslint({}, ...compat.config({ extends: ['eslint:recommended'] }));
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Scripts (recommended)
|
|
94
|
+
|
|
95
|
+
Add scripts to `package.json`:
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"scripts": {
|
|
100
|
+
"lint": "eslint .",
|
|
101
|
+
"lint:fix": "eslint . --fix"
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Example `lint-staged` + `husky`:
|
|
107
|
+
|
|
108
|
+
```json
|
|
109
|
+
{
|
|
110
|
+
"lint-staged": {
|
|
111
|
+
"**/*.{js,ts,jsx,tsx,mjs}": ["pnpm lint:fix"]
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## IDEs and code editors
|
|
117
|
+
|
|
118
|
+
### VS Code (recommended)
|
|
119
|
+
|
|
120
|
+
Install the ESLint extension and use:
|
|
121
|
+
|
|
122
|
+
```jsonc
|
|
123
|
+
// .vscode/settings.json
|
|
124
|
+
{
|
|
125
|
+
"prettier.enable": false,
|
|
126
|
+
"editor.formatOnSave": false,
|
|
127
|
+
"editor.codeActionsOnSave": {
|
|
128
|
+
"source.fixAll.eslint": "explicit",
|
|
129
|
+
"source.organizeImports": "never"
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
> Ensure `eslint` exists in the project root `node_modules` - the extension does not resolve nested copies reliably.
|
|
135
|
+
|
|
136
|
+
### Neovim
|
|
137
|
+
|
|
138
|
+
Use `nvim-lspconfig` or your favorite tooling. To run auto-fix on save:
|
|
139
|
+
|
|
140
|
+
```lua
|
|
141
|
+
-- call EslintFixAll on BufWritePre
|
|
142
|
+
vim.api.nvim_create_autocmd("BufWritePre", {
|
|
143
|
+
pattern = {"*.js","*.ts","*.jsx","*.tsx"},
|
|
144
|
+
callback = function() vim.cmd("EslintFixAll") end
|
|
145
|
+
})
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Or use `null-ls` / `conform.nvim` as an alternative.
|
|
149
|
+
|
|
150
|
+
## Features
|
|
151
|
+
|
|
152
|
+
- JavaScript & TypeScript support (TS opt-in via factory option).
|
|
153
|
+
- React/Next/Vue/Svelte/Astro/Solid integrations (opt-in).
|
|
154
|
+
- Accessibility rules (a11y) for React/Vue when enabled.
|
|
155
|
+
- Opinionated stylistic rules (using `style/*`) that are auto-fixable.
|
|
156
|
+
- Composer API: `.prepend()`, `.override()`, `.renamePlugins()` for advanced composition.
|
|
157
|
+
|
|
158
|
+
## Customization
|
|
159
|
+
|
|
160
|
+
Pass options or extra flat-configs to the factory:
|
|
161
|
+
|
|
162
|
+
```js
|
|
163
|
+
import { eslint } from '@maneko/eslint-config';
|
|
164
|
+
|
|
165
|
+
export default eslint(
|
|
166
|
+
{ typescript: true, react: true },
|
|
167
|
+
{
|
|
168
|
+
files: ['**/*.ts'],
|
|
169
|
+
rules: {
|
|
170
|
+
'no-console': 'warn'
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
);
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Advanced composer example:
|
|
177
|
+
|
|
178
|
+
```js
|
|
179
|
+
export default eslint()
|
|
180
|
+
.prepend(/* config */)
|
|
181
|
+
.override('maneko/stylistic/rules', {
|
|
182
|
+
rules: { 'style/semi': ['error', 'never'] }
|
|
183
|
+
})
|
|
184
|
+
.renamePlugins({ ts: '@typescript-eslint' });
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Common problems & fixes (quick)
|
|
188
|
+
|
|
189
|
+
- **VS Code not linting** - make sure `eslint` is installed in the project root (not only globally).
|
|
190
|
+
- **Missing parser/plugin errors** - install peer deps in the host project (e.g. `eslint-plugin-react`).
|
|
191
|
+
- **Rules auto-fixed unexpectedly in the editor** - check `.vscode/settings.json` - some stylistic rules may be turned off in the editor and still be fixable on CLI runs.
|
|
192
|
+
- **Legacy `.eslintrc`** - convert using `FlatCompat` or maintain a small adapter file.
|
|
193
|
+
|
|
194
|
+
## Contributing
|
|
195
|
+
|
|
196
|
+
PRs welcome. Keep changes small and document any new opinionated rules.
|
|
197
|
+
|
|
198
|
+
## Acknowledgements
|
|
199
|
+
|
|
200
|
+
Inspired by `@antfu/eslint-config` - thanks for the design & DX philosophy.
|
|
201
|
+
|
|
202
|
+
## License
|
|
203
|
+
|
|
204
|
+
`@maneko/eslint-config` is licensed under the MIT License. See the `LICENSE` file in the repository.
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
declare module '@maneko/eslint-config' {
|
|
2
|
+
import type {
|
|
3
|
+
Awaitable,
|
|
4
|
+
ConfigNames,
|
|
5
|
+
OptionsConfig,
|
|
6
|
+
TypedFlatConfigItem
|
|
7
|
+
} from '@antfu/eslint-config';
|
|
8
|
+
import type { Linter } from 'eslint';
|
|
9
|
+
import type { FlatConfigComposer } from 'eslint-flat-config-utils';
|
|
10
|
+
|
|
11
|
+
export type Eslint = (
|
|
12
|
+
options?: OptionsConfig & TypedFlatConfigItem,
|
|
13
|
+
...userConfigs: Awaitable<
|
|
14
|
+
FlatConfigComposer<any, any> | Linter.Config[] | TypedFlatConfigItem | TypedFlatConfigItem[]
|
|
15
|
+
>[]
|
|
16
|
+
) => FlatConfigComposer<TypedFlatConfigItem, ConfigNames>;
|
|
17
|
+
|
|
18
|
+
export const eslint: Eslint;
|
|
19
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import antfu from '@antfu/eslint-config';
|
|
2
|
+
import pluginReact from 'eslint-plugin-react';
|
|
3
|
+
|
|
4
|
+
/** @type {import('@maneko/eslint-config').Eslint} */
|
|
5
|
+
export const eslint = ({ ...options }, ...userConfigs) => {
|
|
6
|
+
const stylistic = options.stylistic ?? false;
|
|
7
|
+
|
|
8
|
+
if (options.react) {
|
|
9
|
+
userConfigs.unshift({
|
|
10
|
+
name: 'maneko/react',
|
|
11
|
+
plugins: {
|
|
12
|
+
'maneko-react': pluginReact
|
|
13
|
+
},
|
|
14
|
+
rules: {
|
|
15
|
+
'maneko-react/function-component-definition': [
|
|
16
|
+
'error',
|
|
17
|
+
{
|
|
18
|
+
namedComponents: ['arrow-function'],
|
|
19
|
+
unnamedComponents: 'arrow-function'
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
'maneko-react/prop-types': 'off',
|
|
23
|
+
'maneko-react/react-in-jsx-scope': 'off'
|
|
24
|
+
},
|
|
25
|
+
settings: {
|
|
26
|
+
react: {
|
|
27
|
+
version: 'detect'
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (stylistic) {
|
|
34
|
+
userConfigs.unshift({
|
|
35
|
+
name: 'maneko/stylistic',
|
|
36
|
+
rules: {
|
|
37
|
+
'style/arrow-parens': ['error', 'always'],
|
|
38
|
+
'style/brace-style': 'off',
|
|
39
|
+
'style/comma-dangle': ['error', 'never'],
|
|
40
|
+
'style/indent': ['error', 2, { SwitchCase: 1 }],
|
|
41
|
+
'style/jsx-curly-newline': 'off',
|
|
42
|
+
'style/jsx-one-expression-per-line': 'off',
|
|
43
|
+
'style/jsx-quotes': ['error', 'prefer-single'],
|
|
44
|
+
'style/linebreak-style': ['error', 'unix'],
|
|
45
|
+
'style/max-len': [
|
|
46
|
+
'error',
|
|
47
|
+
100,
|
|
48
|
+
2,
|
|
49
|
+
{
|
|
50
|
+
ignoreComments: true,
|
|
51
|
+
ignoreStrings: true,
|
|
52
|
+
ignoreTemplateLiterals: true
|
|
53
|
+
}
|
|
54
|
+
],
|
|
55
|
+
'style/member-delimiter-style': 'off',
|
|
56
|
+
'style/multiline-ternary': 'off',
|
|
57
|
+
'style/no-tabs': 'error',
|
|
58
|
+
'style/operator-linebreak': 'off',
|
|
59
|
+
'style/quote-props': 'off',
|
|
60
|
+
'style/quotes': ['error', 'single', { avoidEscape: true, allowTemplateLiterals: 'always' }],
|
|
61
|
+
'style/semi': ['error', 'always']
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
userConfigs.push(
|
|
67
|
+
{
|
|
68
|
+
name: 'maneko/rewrite',
|
|
69
|
+
rules: {
|
|
70
|
+
'antfu/curly': 'off',
|
|
71
|
+
'antfu/if-newline': 'off',
|
|
72
|
+
'antfu/top-level-function': 'off',
|
|
73
|
+
'no-console': 'warn',
|
|
74
|
+
'react-hooks/exhaustive-deps': 'off',
|
|
75
|
+
'test/prefer-lowercase-title': 'off'
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: 'maneko/sort',
|
|
80
|
+
rules: {
|
|
81
|
+
'perfectionist/sort-array-includes': [
|
|
82
|
+
'error',
|
|
83
|
+
{
|
|
84
|
+
order: 'asc',
|
|
85
|
+
type: 'alphabetical'
|
|
86
|
+
}
|
|
87
|
+
],
|
|
88
|
+
'perfectionist/sort-imports': [
|
|
89
|
+
'error',
|
|
90
|
+
{
|
|
91
|
+
groups: [
|
|
92
|
+
'type',
|
|
93
|
+
['builtin', 'external'],
|
|
94
|
+
'internal-type',
|
|
95
|
+
['internal'],
|
|
96
|
+
['parent-type', 'sibling-type', 'index-type'],
|
|
97
|
+
['parent', 'sibling', 'index'],
|
|
98
|
+
'object',
|
|
99
|
+
'style',
|
|
100
|
+
'side-effect-style',
|
|
101
|
+
'unknown'
|
|
102
|
+
],
|
|
103
|
+
internalPattern: ['^~/.*', '^@/.*'],
|
|
104
|
+
newlinesBetween: 'always',
|
|
105
|
+
order: 'asc',
|
|
106
|
+
type: 'natural'
|
|
107
|
+
}
|
|
108
|
+
],
|
|
109
|
+
'perfectionist/sort-interfaces': [
|
|
110
|
+
'error',
|
|
111
|
+
{
|
|
112
|
+
groups: ['unknown', 'method', 'multiline'],
|
|
113
|
+
order: 'asc',
|
|
114
|
+
type: 'alphabetical'
|
|
115
|
+
}
|
|
116
|
+
],
|
|
117
|
+
'perfectionist/sort-jsx-props': [
|
|
118
|
+
'error',
|
|
119
|
+
{
|
|
120
|
+
customGroups: {
|
|
121
|
+
callback: 'on*',
|
|
122
|
+
reserved: ['key', 'ref']
|
|
123
|
+
},
|
|
124
|
+
groups: ['shorthand', 'reserved', 'multiline', 'unknown', 'callback'],
|
|
125
|
+
order: 'asc',
|
|
126
|
+
type: 'alphabetical'
|
|
127
|
+
}
|
|
128
|
+
],
|
|
129
|
+
'perfectionist/sort-union-types': [
|
|
130
|
+
'error',
|
|
131
|
+
{
|
|
132
|
+
groups: [
|
|
133
|
+
'conditional',
|
|
134
|
+
'function',
|
|
135
|
+
'import',
|
|
136
|
+
'intersection',
|
|
137
|
+
'keyword',
|
|
138
|
+
'literal',
|
|
139
|
+
'named',
|
|
140
|
+
'object',
|
|
141
|
+
'operator',
|
|
142
|
+
'tuple',
|
|
143
|
+
'union',
|
|
144
|
+
'nullish'
|
|
145
|
+
],
|
|
146
|
+
order: 'asc',
|
|
147
|
+
specialCharacters: 'keep',
|
|
148
|
+
type: 'alphabetical'
|
|
149
|
+
}
|
|
150
|
+
]
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
return antfu({ ...options, stylistic }, ...userConfigs);
|
|
156
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@maneko/eslint-config",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.1.3",
|
|
5
|
+
"description": "Shared ESLint config for our projects",
|
|
6
|
+
"author": "Maneko <contact@maneko.moe>",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"homepage": "https://github.com/maneko-org/eslint-config",
|
|
9
|
+
"repository": {
|
|
10
|
+
"url": "https://github.com/maneko-org/eslint-config"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/maneko-org/eslint-config/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"javascript",
|
|
17
|
+
"typescript",
|
|
18
|
+
"jsx",
|
|
19
|
+
"vue",
|
|
20
|
+
"astro",
|
|
21
|
+
"stylistic",
|
|
22
|
+
"react",
|
|
23
|
+
"nextjs",
|
|
24
|
+
"solid",
|
|
25
|
+
"svelte"
|
|
26
|
+
],
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./index.d.ts",
|
|
30
|
+
"import": "./index.js"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public"
|
|
35
|
+
},
|
|
36
|
+
"main": "index.js",
|
|
37
|
+
"types": "index.d.ts",
|
|
38
|
+
"files": [
|
|
39
|
+
"index.d.ts",
|
|
40
|
+
"index.js"
|
|
41
|
+
],
|
|
42
|
+
"peerDependencies": {
|
|
43
|
+
"eslint": "^9.38.0"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@antfu/eslint-config": "^6.2.0",
|
|
47
|
+
"@eslint-react/eslint-plugin": "^2.3.9",
|
|
48
|
+
"@next/eslint-plugin-next": "^16.0.4",
|
|
49
|
+
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
50
|
+
"eslint-plugin-react": "^7.37.5",
|
|
51
|
+
"eslint-plugin-react-hooks": "^7.0.1",
|
|
52
|
+
"eslint-plugin-react-refresh": "^0.4.24"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@maneko/prettier-config": "^0.1.1",
|
|
56
|
+
"bumpp": "^10.3.1",
|
|
57
|
+
"eslint": "^9.38.0",
|
|
58
|
+
"eslint-flat-config-utils": "^2.1.4",
|
|
59
|
+
"husky": "^9.1.7",
|
|
60
|
+
"lint-staged": "^16.2.4",
|
|
61
|
+
"prettier": "^3.6.2",
|
|
62
|
+
"typescript": "^5.9.3"
|
|
63
|
+
},
|
|
64
|
+
"lint-staged": {
|
|
65
|
+
"*.{js,ts}": [
|
|
66
|
+
"prettier --write",
|
|
67
|
+
"eslint --fix"
|
|
68
|
+
]
|
|
69
|
+
},
|
|
70
|
+
"scripts": {
|
|
71
|
+
"format": "prettier --write \"*.js\"",
|
|
72
|
+
"lint": "eslint . --fix",
|
|
73
|
+
"lint-inspector": "npx @eslint/config-inspector"
|
|
74
|
+
}
|
|
75
|
+
}
|