@shakuroinc/eslint-config-react 6.4.3 → 7.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/README.md +209 -14
- package/eslint.config.js +318 -0
- package/package.json +47 -42
- package/prettier.config.js +19 -1
- package/.eslintrc.js +0 -255
- package/.vscode/settings.json +0 -42
package/README.md
CHANGED
|
@@ -1,32 +1,227 @@
|
|
|
1
1
|
# @shakuroinc/eslint-config-react
|
|
2
2
|
|
|
3
|
-
[Shakuro](https://shakuro.com/)
|
|
3
|
+
[Shakuro](https://shakuro.com/) shared ESLint + Prettier config for React projects.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**v7** is a flat-config rewrite targeting:
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- ESLint 9 / 10 (flat config only — `eslint.config.js`)
|
|
8
|
+
- React 19
|
|
9
|
+
- Tailwind CSS v4 (`eslint-plugin-tailwindcss@4.x` beta)
|
|
10
|
+
- `eslint-plugin-react-hooks@7`
|
|
11
|
+
- `typescript-eslint@8`
|
|
12
|
+
- Prettier 3 with `prettier-plugin-tailwindcss@0.8`
|
|
8
13
|
|
|
9
|
-
|
|
14
|
+
> Upgrading from v6? See [Migration from v6](#migration-from-v6) below.
|
|
10
15
|
|
|
11
|
-
|
|
16
|
+
## Install
|
|
12
17
|
|
|
13
|
-
|
|
18
|
+
```sh
|
|
19
|
+
pnpm add -D @shakuroinc/eslint-config-react
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Install the peer dependencies. The config does not bundle plugins — your project
|
|
23
|
+
owns the versions, so updating a plugin doesn't require a new release of this
|
|
24
|
+
package.
|
|
25
|
+
|
|
26
|
+
```sh
|
|
27
|
+
pnpm add -D \
|
|
28
|
+
eslint \
|
|
29
|
+
eslint-config-prettier \
|
|
30
|
+
eslint-plugin-prettier \
|
|
31
|
+
eslint-plugin-react-hooks \
|
|
32
|
+
eslint-plugin-simple-import-sort \
|
|
33
|
+
eslint-plugin-tailwindcss@beta \
|
|
34
|
+
globals \
|
|
35
|
+
prettier \
|
|
36
|
+
prettier-plugin-tailwindcss \
|
|
37
|
+
typescript-eslint
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Optional peers (only needed if you lint `.md` / `.mdx`):
|
|
41
|
+
|
|
42
|
+
```sh
|
|
43
|
+
pnpm add -D eslint-mdx eslint-plugin-mdx
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Configure ESLint
|
|
47
|
+
|
|
48
|
+
The package exports a **factory function**. Call it with your project options
|
|
49
|
+
and spread the result into your flat config.
|
|
50
|
+
|
|
51
|
+
```js
|
|
52
|
+
// eslint.config.js
|
|
53
|
+
const { resolve } = require('node:path');
|
|
54
|
+
const shakuroConfig = require('@shakuroinc/eslint-config-react');
|
|
55
|
+
|
|
56
|
+
module.exports = shakuroConfig({
|
|
57
|
+
tailwindStylesheet: resolve(__dirname, 'src/styles/globals.css'),
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Composing with other configs
|
|
62
|
+
|
|
63
|
+
`shakuroConfig()` returns an array, so you can prepend or append your own
|
|
64
|
+
blocks. A typical Next.js setup looks like this:
|
|
65
|
+
|
|
66
|
+
```js
|
|
67
|
+
// eslint.config.js
|
|
68
|
+
const { resolve } = require('node:path');
|
|
69
|
+
const shakuroConfig = require('@shakuroinc/eslint-config-react');
|
|
70
|
+
const nextCoreWebVitals = require('eslint-config-next/core-web-vitals');
|
|
71
|
+
|
|
72
|
+
module.exports = [
|
|
73
|
+
...nextCoreWebVitals,
|
|
74
|
+
...shakuroConfig({
|
|
75
|
+
tailwindStylesheet: resolve(__dirname, 'src/styles/globals.css'),
|
|
76
|
+
tailwindCallees: ['cn', 'clsx', 'cva'],
|
|
77
|
+
next: { rootDir: 'apps/frontend/' },
|
|
78
|
+
}),
|
|
79
|
+
// Project-specific overrides — keep them after the shared config so they win.
|
|
80
|
+
{
|
|
81
|
+
rules: { 'max-lines': 'off' },
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Factory options
|
|
87
|
+
|
|
88
|
+
| Option | Type | Default | Description |
|
|
89
|
+
| -------------------- | --------------------- | ---------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
|
|
90
|
+
| `tailwindStylesheet` | `string` | `undefined` | Absolute path to your Tailwind v4 entry CSS file. Forwarded to the plugin's `config` setting. |
|
|
91
|
+
| `tailwindCallees` | `string[]` | `['cn', 'clsx', 'cva', 'tv']` | Function names whose string arguments contain Tailwind class names. |
|
|
92
|
+
| `tailwindWhitelist` | `string[]` | See [Default whitelist](#default-tailwind-whitelist) | Regex patterns ignored by `tailwindcss/no-custom-classname`. |
|
|
93
|
+
| `ignores` | `string[]` | `[]` | Extra globs appended to the default ignore list. |
|
|
94
|
+
| `reactVersion` | `string` | `'19.0'` | Pinned React version for `eslint-plugin-react`. **Do not set to `'detect'`** — it's broken under ESLint 10 in current plugin versions. |
|
|
95
|
+
| `next` | `{ rootDir: string }` | `undefined` | Forwarded to `settings.next` for `eslint-plugin-next`. |
|
|
96
|
+
|
|
97
|
+
### Default ignores
|
|
98
|
+
|
|
99
|
+
```text
|
|
100
|
+
**/node_modules/**
|
|
101
|
+
**/public/**
|
|
102
|
+
**/dist/**
|
|
103
|
+
**/dist_keycloak/**
|
|
104
|
+
**/.next/**
|
|
105
|
+
**/.turbo/**
|
|
106
|
+
**/coverage/**
|
|
107
|
+
**/storybook-static/**
|
|
108
|
+
**/next-env.d.ts
|
|
109
|
+
**/*.json.ts
|
|
110
|
+
**/importMap.js
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Append more via the `ignores` option.
|
|
114
|
+
|
|
115
|
+
### Default Tailwind whitelist
|
|
116
|
+
|
|
117
|
+
```text
|
|
118
|
+
pf-.*
|
|
119
|
+
g-recaptcha
|
|
120
|
+
cn-input-otp
|
|
121
|
+
-?translate-x-\\[[-]?50%\\]
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Named exports
|
|
125
|
+
|
|
126
|
+
The factory is also available under several named exports for advanced use:
|
|
127
|
+
|
|
128
|
+
```js
|
|
129
|
+
const shakuroConfig = require('@shakuroinc/eslint-config-react');
|
|
130
|
+
|
|
131
|
+
const {
|
|
132
|
+
sharedRules, // The rule map applied to JS/TS/JSX/TSX files.
|
|
133
|
+
mdxRuleOverrides, // Rule overrides applied to .md/.mdx blocks.
|
|
134
|
+
DEFAULT_IGNORES,
|
|
135
|
+
DEFAULT_TAILWIND_CALLEES,
|
|
136
|
+
DEFAULT_TAILWIND_WHITELIST,
|
|
137
|
+
} = shakuroConfig;
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
This is useful if you want to drop the rule set into your own custom flat-config
|
|
141
|
+
block instead of using the factory.
|
|
14
142
|
|
|
15
|
-
|
|
143
|
+
## Configure Prettier
|
|
16
144
|
|
|
17
|
-
|
|
145
|
+
Most projects only need to point `tailwindStylesheet` at their own globals.css:
|
|
18
146
|
|
|
19
147
|
```js
|
|
20
|
-
// .
|
|
148
|
+
// prettier.config.js
|
|
21
149
|
module.exports = {
|
|
22
|
-
|
|
23
|
-
|
|
150
|
+
...require('@shakuroinc/eslint-config-react/prettier'),
|
|
151
|
+
tailwindStylesheet: './src/styles/globals.css',
|
|
24
152
|
};
|
|
25
153
|
```
|
|
26
154
|
|
|
27
|
-
|
|
155
|
+
The base config sets:
|
|
28
156
|
|
|
29
157
|
```js
|
|
30
|
-
|
|
31
|
-
|
|
158
|
+
{
|
|
159
|
+
arrowParens: 'avoid',
|
|
160
|
+
bracketSpacing: true,
|
|
161
|
+
plugins: ['prettier-plugin-tailwindcss'],
|
|
162
|
+
printWidth: 100,
|
|
163
|
+
semi: true,
|
|
164
|
+
singleQuote: true,
|
|
165
|
+
tabWidth: 2,
|
|
166
|
+
trailingComma: 'all',
|
|
167
|
+
// prettier-plugin-tailwindcss (v4):
|
|
168
|
+
tailwindFunctions: ['cn', 'clsx', 'cva', 'tv'],
|
|
169
|
+
tailwindAttributes: ['className', 'classNames', '.*ClassName'],
|
|
170
|
+
}
|
|
32
171
|
```
|
|
172
|
+
|
|
173
|
+
## What's included
|
|
174
|
+
|
|
175
|
+
- `typescript-eslint`'s `recommended` flat preset.
|
|
176
|
+
- `eslint-plugin-react-hooks` (legacy + v7 rules — only the classic ones are
|
|
177
|
+
pinned; v7 introduces new rules like `react-hooks/refs` and
|
|
178
|
+
`react-hooks/set-state-in-effect`, which are inherited at their plugin
|
|
179
|
+
defaults and surface real issues you should fix).
|
|
180
|
+
- `eslint-plugin-simple-import-sort` with the Shakuro import grouping
|
|
181
|
+
(`react`/`next` → vendors → `@shakuroinc`/`@sh` → project aliases → relative
|
|
182
|
+
→ side-effect CSS).
|
|
183
|
+
- `eslint-plugin-tailwindcss@4` with class-order disabled (Prettier handles
|
|
184
|
+
ordering) and `no-contradicting-classname` enabled.
|
|
185
|
+
- `eslint-plugin-prettier` + `eslint-config-prettier` so formatting violations
|
|
186
|
+
surface as lint errors.
|
|
187
|
+
- MDX support via `eslint-plugin-mdx` (optional peer).
|
|
188
|
+
- A `padding-line-between-statements` rule preserving the previous Shakuro
|
|
189
|
+
spacing conventions.
|
|
190
|
+
|
|
191
|
+
## Migration from v6
|
|
192
|
+
|
|
193
|
+
| v6 (legacy) | v7 (flat config) |
|
|
194
|
+
| ------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- |
|
|
195
|
+
| `.eslintrc.js` with `extends: ['@shakuroinc/eslint-config-react']` | `eslint.config.js` calling `shakuroConfig({ ... })` (see above) |
|
|
196
|
+
| `main: '.eslintrc.js'` | `main: 'eslint.config.js'`, named export `./prettier` |
|
|
197
|
+
| ESLint ≥ 8.29 | ESLint ≥ 9 |
|
|
198
|
+
| `eslint-plugin-react@7.31.11`, `react-hooks@4` | `eslint-plugin-react@^7.37` (inherited from your config), `react-hooks@7` |
|
|
199
|
+
| `tailwindcss@3.x` plugin, class-order on | `tailwindcss@4.x-beta` plugin, class-order off (Prettier handles it) |
|
|
200
|
+
| `@typescript-eslint/padding-line-between-statements` | Stock `padding-line-between-statements` (TS-only selectors dropped — install `@stylistic/eslint-plugin` if you need them) |
|
|
201
|
+
| `prettier-plugin-tailwindcss@0.2` | `prettier-plugin-tailwindcss@0.8` with `tailwindStylesheet` for v4 |
|
|
202
|
+
|
|
203
|
+
### Breaking rule changes
|
|
204
|
+
|
|
205
|
+
- `tailwindcss/classnames-order` is **off** — Prettier sorts classes via
|
|
206
|
+
`prettier-plugin-tailwindcss`. Run prettier `--write` once on the codebase
|
|
207
|
+
before enforcing.
|
|
208
|
+
- Legacy `eslint-plugin-import` overrides are dropped. If your project uses
|
|
209
|
+
`eslint-config-next`, the import plugin comes along for the ride; otherwise
|
|
210
|
+
add it yourself in a follow-up block.
|
|
211
|
+
- `naming-convention` no longer flags string-literal object keys or numeric
|
|
212
|
+
keys — pre-existing `// eslint-disable-next-line @typescript-eslint/naming-convention`
|
|
213
|
+
comments above those constructs will be reported as unused.
|
|
214
|
+
- `@typescript-eslint/no-var-requires` was renamed to
|
|
215
|
+
`@typescript-eslint/no-require-imports`. Update any local disable comments.
|
|
216
|
+
|
|
217
|
+
## Give it a try and reach us
|
|
218
|
+
|
|
219
|
+
Explore our expertise in <a href="https://shakuro.com/services/native-mobile-development/?utm_source=github&utm_medium=repository&utm_campaign=eslint">Native Mobile Development</a> and <a href="https://shakuro.com/services/ios-dev/?utm_source=github&utm_medium=repository&utm_campaign=eslint">iOS Development</a>.</p>
|
|
220
|
+
|
|
221
|
+
If you need professional assistance with your mobile or web project, feel free to <a href="https://shakuro.com/get-in-touch/?utm_source=github&utm_medium=repository&utm_campaign=eslint">contact our team</a>
|
|
222
|
+
Override `tailwindFunctions` or `tailwindAttributes` only if your project uses
|
|
223
|
+
non-default helpers (e.g. `twMerge`) or custom class-name prop names.
|
|
224
|
+
|
|
225
|
+
## License
|
|
226
|
+
|
|
227
|
+
MIT
|
package/eslint.config.js
ADDED
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/**
|
|
3
|
+
* @shakuroinc/eslint-config-react — flat config for ESLint 9+.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* // eslint.config.js
|
|
7
|
+
* const shakuroConfig = require('@shakuroinc/eslint-config-react');
|
|
8
|
+
*
|
|
9
|
+
* module.exports = shakuroConfig({
|
|
10
|
+
* tailwindStylesheet: './src/styles/globals.css',
|
|
11
|
+
* ignores: ['custom/**'],
|
|
12
|
+
* });
|
|
13
|
+
*
|
|
14
|
+
* You can also spread the result and append your own blocks:
|
|
15
|
+
* module.exports = [
|
|
16
|
+
* ...shakuroConfig(),
|
|
17
|
+
* { rules: { 'no-console': 'off' } },
|
|
18
|
+
* ];
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
// @ts-ignore
|
|
22
|
+
const tseslint = require('typescript-eslint');
|
|
23
|
+
const prettierPlugin = require('eslint-plugin-prettier');
|
|
24
|
+
const prettierConfig = require('eslint-config-prettier');
|
|
25
|
+
const simpleImportSort = require('eslint-plugin-simple-import-sort');
|
|
26
|
+
const tailwindcss = require('eslint-plugin-tailwindcss');
|
|
27
|
+
const reactHooks = require('eslint-plugin-react-hooks');
|
|
28
|
+
const mdx = require('eslint-plugin-mdx');
|
|
29
|
+
const globals = require('globals');
|
|
30
|
+
|
|
31
|
+
const DEFAULT_IGNORES = [
|
|
32
|
+
'**/node_modules/**',
|
|
33
|
+
'**/public/**',
|
|
34
|
+
'**/dist/**',
|
|
35
|
+
'**/dist_keycloak/**',
|
|
36
|
+
'**/.next/**',
|
|
37
|
+
'**/.turbo/**',
|
|
38
|
+
'**/coverage/**',
|
|
39
|
+
'**/storybook-static/**',
|
|
40
|
+
'**/next-env.d.ts',
|
|
41
|
+
'**/*.json.ts',
|
|
42
|
+
'**/importMap.js',
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
const DEFAULT_TAILWIND_CALLEES = ['cn', 'clsx', 'cva', 'tv'];
|
|
46
|
+
|
|
47
|
+
const DEFAULT_TAILWIND_WHITELIST = [
|
|
48
|
+
'pf-.*',
|
|
49
|
+
'g-recaptcha',
|
|
50
|
+
'cn-input-otp',
|
|
51
|
+
'-?translate-x-\\[[-]?50%\\]',
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
/** Shared lint rules (TypeScript + React + a11y + tailwind + prettier). */
|
|
55
|
+
const sharedRules = {
|
|
56
|
+
// typescript-eslint relaxations
|
|
57
|
+
'@typescript-eslint/ban-ts-comment': 'off',
|
|
58
|
+
'@typescript-eslint/explicit-function-return-type': 'off',
|
|
59
|
+
'@typescript-eslint/explicit-member-accessibility': 'off',
|
|
60
|
+
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
|
61
|
+
'@typescript-eslint/no-empty-function': 'off',
|
|
62
|
+
'@typescript-eslint/no-explicit-any': 'off',
|
|
63
|
+
'@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^[_]*$' }],
|
|
64
|
+
'no-unused-vars': 'off',
|
|
65
|
+
|
|
66
|
+
// Naming conventions
|
|
67
|
+
'@typescript-eslint/naming-convention': [
|
|
68
|
+
'error',
|
|
69
|
+
{
|
|
70
|
+
selector: 'default',
|
|
71
|
+
format: ['PascalCase', 'camelCase'],
|
|
72
|
+
leadingUnderscore: 'forbid',
|
|
73
|
+
trailingUnderscore: 'forbid',
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
selector: ['variable'],
|
|
77
|
+
format: ['PascalCase', 'camelCase', 'UPPER_CASE'],
|
|
78
|
+
leadingUnderscore: 'forbid',
|
|
79
|
+
trailingUnderscore: 'forbid',
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
selector: ['property'],
|
|
83
|
+
format: null,
|
|
84
|
+
leadingUnderscore: 'forbid',
|
|
85
|
+
trailingUnderscore: 'forbid',
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
selector: ['default', 'variable', 'property'],
|
|
89
|
+
format: null,
|
|
90
|
+
leadingUnderscore: 'allow',
|
|
91
|
+
filter: '^[_]*$',
|
|
92
|
+
},
|
|
93
|
+
{ selector: 'typeLike', format: ['PascalCase'] },
|
|
94
|
+
{
|
|
95
|
+
selector: ['enumMember', 'enum'],
|
|
96
|
+
format: ['camelCase', 'UPPER_CASE', 'snake_case', 'PascalCase'],
|
|
97
|
+
},
|
|
98
|
+
{ selector: 'property', format: null, filter: '^__html$' },
|
|
99
|
+
],
|
|
100
|
+
|
|
101
|
+
// Statement spacing
|
|
102
|
+
// NOTE: stock `padding-line-between-statements` does not support TS-only types
|
|
103
|
+
// like `interface`/`type`/`multiline-const`. We keep the rule on common
|
|
104
|
+
// statement kinds; consumers who want the TS-specific selectors can layer
|
|
105
|
+
// `@stylistic/padding-line-between-statements` on top.
|
|
106
|
+
'padding-line-between-statements': [
|
|
107
|
+
'error',
|
|
108
|
+
{ blankLine: 'always', prev: '*', next: ['return'] },
|
|
109
|
+
{ blankLine: 'always', prev: 'function', next: 'function' },
|
|
110
|
+
{
|
|
111
|
+
blankLine: 'always',
|
|
112
|
+
prev: 'import',
|
|
113
|
+
next: [
|
|
114
|
+
'block',
|
|
115
|
+
'block-like',
|
|
116
|
+
'case',
|
|
117
|
+
'class',
|
|
118
|
+
'const',
|
|
119
|
+
'export',
|
|
120
|
+
'expression',
|
|
121
|
+
'for',
|
|
122
|
+
'function',
|
|
123
|
+
'if',
|
|
124
|
+
'let',
|
|
125
|
+
'return',
|
|
126
|
+
'throw',
|
|
127
|
+
'try',
|
|
128
|
+
'while',
|
|
129
|
+
],
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
blankLine: 'always',
|
|
133
|
+
prev: [
|
|
134
|
+
'import',
|
|
135
|
+
'block',
|
|
136
|
+
'block-like',
|
|
137
|
+
'case',
|
|
138
|
+
'class',
|
|
139
|
+
'const',
|
|
140
|
+
'expression',
|
|
141
|
+
'for',
|
|
142
|
+
'function',
|
|
143
|
+
'if',
|
|
144
|
+
'let',
|
|
145
|
+
'return',
|
|
146
|
+
'throw',
|
|
147
|
+
'try',
|
|
148
|
+
'while',
|
|
149
|
+
],
|
|
150
|
+
next: 'export',
|
|
151
|
+
},
|
|
152
|
+
{ blankLine: 'always', prev: 'directive', next: '*' },
|
|
153
|
+
],
|
|
154
|
+
|
|
155
|
+
// Core JS
|
|
156
|
+
curly: ['error', 'multi-line'],
|
|
157
|
+
'no-console': 'error',
|
|
158
|
+
'no-duplicate-imports': 'error',
|
|
159
|
+
'no-restricted-imports': [
|
|
160
|
+
'error',
|
|
161
|
+
{
|
|
162
|
+
paths: ['ui'],
|
|
163
|
+
patterns: [
|
|
164
|
+
{
|
|
165
|
+
group: ['@sh/app', '@sh/app/*'],
|
|
166
|
+
message: 'Importing from `app` package is disallowed for architecture reasons',
|
|
167
|
+
},
|
|
168
|
+
],
|
|
169
|
+
},
|
|
170
|
+
],
|
|
171
|
+
quotes: ['error', 'single', { allowTemplateLiterals: false, avoidEscape: true }],
|
|
172
|
+
'sort-imports': 'off',
|
|
173
|
+
|
|
174
|
+
// a11y
|
|
175
|
+
'jsx-a11y/anchor-is-valid': [
|
|
176
|
+
'error',
|
|
177
|
+
{
|
|
178
|
+
components: ['Link'],
|
|
179
|
+
specialLink: ['hrefLeft', 'hrefRight'],
|
|
180
|
+
aspects: ['invalidHref', 'preferButton'],
|
|
181
|
+
},
|
|
182
|
+
],
|
|
183
|
+
|
|
184
|
+
// react
|
|
185
|
+
'react/button-has-type': 'error',
|
|
186
|
+
'react/display-name': 'off',
|
|
187
|
+
'react/function-component-definition': 'off',
|
|
188
|
+
'react/jsx-curly-brace-presence': [2, { props: 'never', children: 'never' }],
|
|
189
|
+
'react/jsx-sort-props': [
|
|
190
|
+
2,
|
|
191
|
+
{ ignoreCase: true, callbacksLast: true, shorthandLast: false, reservedFirst: true },
|
|
192
|
+
],
|
|
193
|
+
'react/no-unescaped-entities': 'off',
|
|
194
|
+
'react/prop-types': 'off',
|
|
195
|
+
'react/react-in-jsx-scope': 'off',
|
|
196
|
+
'react/self-closing-comp': 'warn',
|
|
197
|
+
|
|
198
|
+
// react-hooks (v7 introduces new rules; we enable the classic ones explicitly)
|
|
199
|
+
'react-hooks/exhaustive-deps': 'error',
|
|
200
|
+
'react-hooks/rules-of-hooks': 'error',
|
|
201
|
+
|
|
202
|
+
// simple-import-sort
|
|
203
|
+
'simple-import-sort/exports': 'warn',
|
|
204
|
+
'simple-import-sort/imports': [
|
|
205
|
+
1,
|
|
206
|
+
{
|
|
207
|
+
groups: [
|
|
208
|
+
['^\\u0000'],
|
|
209
|
+
['^react', '^next', '^[^.]'],
|
|
210
|
+
['^@shakuroinc/', '^@sh/'],
|
|
211
|
+
['^@/', '^~/', '^#/', '^libs$', '^libs/', '^features/'],
|
|
212
|
+
['^\\.\\.(?!/?$)', '^\\.\\./?$', '^\\./(?=.*/)(?!/?$)', '^\\.(?!/?$)', '^\\./?$'],
|
|
213
|
+
['^.+\\.s?css$'],
|
|
214
|
+
],
|
|
215
|
+
},
|
|
216
|
+
],
|
|
217
|
+
|
|
218
|
+
// tailwindcss
|
|
219
|
+
// Class order is handled by prettier-plugin-tailwindcss.
|
|
220
|
+
'tailwindcss/classnames-order': 'off',
|
|
221
|
+
'tailwindcss/no-contradicting-classname': 'error',
|
|
222
|
+
// Consumers override the whitelist via factory options.
|
|
223
|
+
'tailwindcss/no-custom-classname': ['warn', { whitelist: DEFAULT_TAILWIND_WHITELIST }],
|
|
224
|
+
|
|
225
|
+
// Misc
|
|
226
|
+
'max-lines': ['error', { max: 300, skipComments: true }],
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
const mdxRuleOverrides = {
|
|
230
|
+
'@next/next/no-img-element': 'off',
|
|
231
|
+
'@typescript-eslint/naming-convention': 'off',
|
|
232
|
+
'padding-line-between-statements': 'off',
|
|
233
|
+
'max-lines': 'off',
|
|
234
|
+
'no-unused-expressions': 'off',
|
|
235
|
+
'react/self-closing-comp': 'off',
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Build the flat config array.
|
|
240
|
+
*
|
|
241
|
+
* @param {object} [options]
|
|
242
|
+
* @param {string} [options.tailwindStylesheet] Path to the Tailwind CSS entry file (Tailwind v4).
|
|
243
|
+
* @param {string[]} [options.tailwindCallees] Function names that accept Tailwind class strings.
|
|
244
|
+
* @param {string[]} [options.tailwindWhitelist] Patterns to whitelist for `no-custom-classname`.
|
|
245
|
+
* @param {string[]} [options.ignores] Extra ignore patterns appended to the defaults.
|
|
246
|
+
* @param {string} [options.reactVersion] Pinned React version for `eslint-plugin-react`.
|
|
247
|
+
* @param {{ rootDir?: string }} [options.next] Settings forwarded to `eslint-plugin-next`.
|
|
248
|
+
* @returns {import('eslint').Linter.FlatConfig[]}
|
|
249
|
+
*/
|
|
250
|
+
function shakuroConfig(options = {}) {
|
|
251
|
+
const {
|
|
252
|
+
tailwindStylesheet,
|
|
253
|
+
tailwindCallees = DEFAULT_TAILWIND_CALLEES,
|
|
254
|
+
tailwindWhitelist = DEFAULT_TAILWIND_WHITELIST,
|
|
255
|
+
ignores = [],
|
|
256
|
+
reactVersion = '19.0',
|
|
257
|
+
next: nextSettings,
|
|
258
|
+
} = options;
|
|
259
|
+
|
|
260
|
+
/** @type {import('eslint').Linter.FlatConfig[]} */
|
|
261
|
+
const config = [
|
|
262
|
+
{ ignores: [...DEFAULT_IGNORES, ...ignores] },
|
|
263
|
+
|
|
264
|
+
// typescript-eslint flat presets
|
|
265
|
+
...tseslint.configs.recommended,
|
|
266
|
+
|
|
267
|
+
{
|
|
268
|
+
files: ['**/*.{js,jsx,mjs,ts,tsx,mts,cts}'],
|
|
269
|
+
plugins: {
|
|
270
|
+
'simple-import-sort': simpleImportSort,
|
|
271
|
+
tailwindcss,
|
|
272
|
+
'react-hooks': reactHooks,
|
|
273
|
+
prettier: prettierPlugin,
|
|
274
|
+
},
|
|
275
|
+
languageOptions: {
|
|
276
|
+
ecmaVersion: 'latest',
|
|
277
|
+
sourceType: 'module',
|
|
278
|
+
parserOptions: { ecmaFeatures: { jsx: true } },
|
|
279
|
+
globals: { ...globals.browser, ...globals.node, ...globals.es2024 },
|
|
280
|
+
},
|
|
281
|
+
settings: {
|
|
282
|
+
react: { version: reactVersion },
|
|
283
|
+
...(nextSettings ? { next: nextSettings } : {}),
|
|
284
|
+
tailwindcss: {
|
|
285
|
+
callees: tailwindCallees,
|
|
286
|
+
...(tailwindStylesheet ? { config: tailwindStylesheet } : {}),
|
|
287
|
+
officialSorting: true,
|
|
288
|
+
},
|
|
289
|
+
},
|
|
290
|
+
rules: {
|
|
291
|
+
...sharedRules,
|
|
292
|
+
'tailwindcss/no-custom-classname': ['warn', { whitelist: tailwindWhitelist }],
|
|
293
|
+
...prettierConfig.rules,
|
|
294
|
+
'prettier/prettier': 'error',
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
|
|
298
|
+
// MDX
|
|
299
|
+
{
|
|
300
|
+
files: ['**/*.{md,mdx}'],
|
|
301
|
+
...mdx.flat,
|
|
302
|
+
rules: {
|
|
303
|
+
...(mdx.flat.rules ?? {}),
|
|
304
|
+
...mdxRuleOverrides,
|
|
305
|
+
},
|
|
306
|
+
},
|
|
307
|
+
];
|
|
308
|
+
|
|
309
|
+
return config;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
module.exports = shakuroConfig;
|
|
313
|
+
module.exports.default = shakuroConfig;
|
|
314
|
+
module.exports.sharedRules = sharedRules;
|
|
315
|
+
module.exports.mdxRuleOverrides = mdxRuleOverrides;
|
|
316
|
+
module.exports.DEFAULT_IGNORES = DEFAULT_IGNORES;
|
|
317
|
+
module.exports.DEFAULT_TAILWIND_CALLEES = DEFAULT_TAILWIND_CALLEES;
|
|
318
|
+
module.exports.DEFAULT_TAILWIND_WHITELIST = DEFAULT_TAILWIND_WHITELIST;
|
package/package.json
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shakuroinc/eslint-config-react",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
3
|
+
"version": "7.0.1",
|
|
4
|
+
"description": "Shakuro shared ESLint + Prettier config (flat config, ESLint 9/10, React 19, Tailwind v4).",
|
|
5
|
+
"main": "eslint.config.js",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": "./eslint.config.js",
|
|
8
|
+
"./prettier": "./prettier.config.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"eslint.config.js",
|
|
12
|
+
"prettier.config.js",
|
|
13
|
+
"README.md"
|
|
14
|
+
],
|
|
5
15
|
"author": "Shakuro team",
|
|
6
16
|
"license": "MIT",
|
|
7
17
|
"repository": {
|
|
@@ -9,52 +19,47 @@
|
|
|
9
19
|
"url": "https://github.com/shakurocom/eslint-config-react"
|
|
10
20
|
},
|
|
11
21
|
"scripts": {
|
|
12
|
-
"lint": "eslint . --ext .ts,.tsx,.js,.mdx,.md --ignore-path .gitignore",
|
|
13
22
|
"release": "git push origin master --tags && npm publish --access public --new-version"
|
|
14
23
|
},
|
|
15
|
-
"
|
|
16
|
-
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"eslint": "^
|
|
20
|
-
"eslint-config-prettier": "^8.8.0",
|
|
21
|
-
"eslint-mdx": "^2.1.0",
|
|
22
|
-
"eslint-plugin-mdx": "^2.1.0",
|
|
24
|
+
"peerDependencies": {
|
|
25
|
+
"eslint": "^9.0.0 || ^10.0.0",
|
|
26
|
+
"eslint-config-prettier": "^10.0.0",
|
|
27
|
+
"eslint-mdx": "^3.0.0",
|
|
28
|
+
"eslint-plugin-mdx": "^3.0.0",
|
|
23
29
|
"eslint-plugin-prettier": "^5.0.0",
|
|
24
|
-
"eslint-plugin-
|
|
25
|
-
"eslint-plugin-
|
|
30
|
+
"eslint-plugin-react-hooks": "^7.0.0",
|
|
31
|
+
"eslint-plugin-simple-import-sort": "^13.0.0",
|
|
32
|
+
"eslint-plugin-tailwindcss": "^4.0.0-beta.0",
|
|
33
|
+
"globals": "^15.0.0 || ^16.0.0 || ^17.0.0",
|
|
26
34
|
"prettier": "^3.0.0",
|
|
27
|
-
"prettier-plugin-tailwindcss": "^0.
|
|
28
|
-
"
|
|
29
|
-
"typescript": "^5.1.6"
|
|
35
|
+
"prettier-plugin-tailwindcss": "^0.6.0 || ^0.7.0 || ^0.8.0",
|
|
36
|
+
"typescript-eslint": "^8.0.0"
|
|
30
37
|
},
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
"eslint-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
"
|
|
39
|
-
|
|
40
|
-
"eslint-plugin-mdx": "^2.0.5",
|
|
41
|
-
"eslint-plugin-prettier": "^4.2.1",
|
|
42
|
-
"eslint-plugin-react": "7.31.11",
|
|
43
|
-
"eslint-plugin-react-hooks": "^4.6.0",
|
|
44
|
-
"eslint-plugin-simple-import-sort": "^8.0.0",
|
|
45
|
-
"eslint-plugin-tailwindcss": "^3.7.1",
|
|
46
|
-
"prettier-plugin-tailwindcss": "^0.2.0"
|
|
47
|
-
},
|
|
48
|
-
"lint-staged": {
|
|
49
|
-
"*.{js,ts,tsx}": "eslint"
|
|
50
|
-
},
|
|
51
|
-
"husky": {
|
|
52
|
-
"hooks": {
|
|
53
|
-
"pre-commit": "lint-staged"
|
|
38
|
+
"peerDependenciesMeta": {
|
|
39
|
+
"eslint-plugin-mdx": {
|
|
40
|
+
"optional": true
|
|
41
|
+
},
|
|
42
|
+
"eslint-mdx": {
|
|
43
|
+
"optional": true
|
|
44
|
+
},
|
|
45
|
+
"prettier-plugin-tailwindcss": {
|
|
46
|
+
"optional": true
|
|
54
47
|
}
|
|
55
48
|
},
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"eslint": "^10.3.0",
|
|
51
|
+
"eslint-config-prettier": "^10.1.8",
|
|
52
|
+
"eslint-mdx": "^3.7.0",
|
|
53
|
+
"eslint-plugin-mdx": "^3.7.0",
|
|
54
|
+
"eslint-plugin-prettier": "^5.5.5",
|
|
55
|
+
"eslint-plugin-react-hooks": "^7.1.1",
|
|
56
|
+
"eslint-plugin-simple-import-sort": "^13.0.0",
|
|
57
|
+
"eslint-plugin-tailwindcss": "4.0.0-beta.0",
|
|
58
|
+
"globals": "^16.5.0",
|
|
59
|
+
"prettier": "^3.8.3",
|
|
60
|
+
"prettier-plugin-tailwindcss": "^0.8.0",
|
|
61
|
+
"react": "^19.2.6",
|
|
62
|
+
"typescript": "^6.0.3",
|
|
63
|
+
"typescript-eslint": "^8.59.3"
|
|
59
64
|
}
|
|
60
65
|
}
|
package/prettier.config.js
CHANGED
|
@@ -1,4 +1,20 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Shared Prettier base config.
|
|
3
|
+
*
|
|
4
|
+
* Tailwind v4 keys (consumed by `prettier-plugin-tailwindcss`) are set to
|
|
5
|
+
* sensible Shakuro defaults. Consumers usually only need to override
|
|
6
|
+
* `tailwindStylesheet` to point at their own globals.css:
|
|
7
|
+
*
|
|
8
|
+
* const base = require('@shakuroinc/eslint-config-react/prettier');
|
|
9
|
+
* module.exports = {
|
|
10
|
+
* ...base,
|
|
11
|
+
* tailwindStylesheet: './packages/ui/src/styles/globals.css',
|
|
12
|
+
* };
|
|
13
|
+
*
|
|
14
|
+
* Override `tailwindFunctions` / `tailwindAttributes` only if your project uses
|
|
15
|
+
* non-default helpers (e.g. `twMerge`, custom class-name props).
|
|
16
|
+
*/
|
|
17
|
+
/** @type {import('prettier').Config} */
|
|
2
18
|
module.exports = {
|
|
3
19
|
arrowParens: 'avoid',
|
|
4
20
|
bracketSpacing: true,
|
|
@@ -8,4 +24,6 @@ module.exports = {
|
|
|
8
24
|
singleQuote: true,
|
|
9
25
|
tabWidth: 2,
|
|
10
26
|
trailingComma: 'all',
|
|
27
|
+
tailwindFunctions: ['cn', 'clsx', 'cva', 'tv'],
|
|
28
|
+
tailwindAttributes: ['className', 'classNames', '.*ClassName'],
|
|
11
29
|
};
|
package/.eslintrc.js
DELETED
|
@@ -1,255 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
/* eslint-disable @typescript-eslint/naming-convention */
|
|
3
|
-
module.exports = {
|
|
4
|
-
parser: '@typescript-eslint/parser',
|
|
5
|
-
|
|
6
|
-
plugins: [
|
|
7
|
-
'@typescript-eslint',
|
|
8
|
-
'react',
|
|
9
|
-
'react-hooks',
|
|
10
|
-
'jsx-a11y',
|
|
11
|
-
'simple-import-sort',
|
|
12
|
-
'tailwindcss',
|
|
13
|
-
],
|
|
14
|
-
|
|
15
|
-
extends: [
|
|
16
|
-
'plugin:@typescript-eslint/recommended',
|
|
17
|
-
'plugin:jsx-a11y/recommended',
|
|
18
|
-
'plugin:prettier/recommended',
|
|
19
|
-
'plugin:react/recommended',
|
|
20
|
-
],
|
|
21
|
-
|
|
22
|
-
parserOptions: {
|
|
23
|
-
ecmaVersion: 'latest',
|
|
24
|
-
sourceType: 'module',
|
|
25
|
-
ecmaFeatures: {
|
|
26
|
-
jsx: true,
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
|
|
30
|
-
settings: {
|
|
31
|
-
react: {
|
|
32
|
-
version: 'detect',
|
|
33
|
-
},
|
|
34
|
-
tailwindcss: {
|
|
35
|
-
officialSorting: true,
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
|
|
39
|
-
rules: {
|
|
40
|
-
'@typescript-eslint/ban-ts-ignore': 'off',
|
|
41
|
-
'@typescript-eslint/explicit-function-return-type': 'off',
|
|
42
|
-
'@typescript-eslint/explicit-member-accessibility': 'off',
|
|
43
|
-
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
|
44
|
-
'@typescript-eslint/interface-name-prefix': 'off',
|
|
45
|
-
'@typescript-eslint/naming-convention': [
|
|
46
|
-
'error',
|
|
47
|
-
{
|
|
48
|
-
selector: 'default',
|
|
49
|
-
format: ['PascalCase', 'camelCase'],
|
|
50
|
-
leadingUnderscore: 'forbid',
|
|
51
|
-
trailingUnderscore: 'forbid',
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
selector: ['variable'],
|
|
55
|
-
format: ['PascalCase', 'camelCase', 'UPPER_CASE'],
|
|
56
|
-
leadingUnderscore: 'forbid',
|
|
57
|
-
trailingUnderscore: 'forbid',
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
selector: ['property'],
|
|
61
|
-
format: null,
|
|
62
|
-
leadingUnderscore: 'forbid',
|
|
63
|
-
trailingUnderscore: 'forbid',
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
selector: ['default', 'variable', 'property'],
|
|
67
|
-
format: null,
|
|
68
|
-
leadingUnderscore: 'allow',
|
|
69
|
-
filter: '^[_]*$',
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
selector: 'typeLike',
|
|
73
|
-
format: ['PascalCase'],
|
|
74
|
-
},
|
|
75
|
-
{
|
|
76
|
-
selector: ['enumMember', 'enum'],
|
|
77
|
-
format: ['camelCase', 'UPPER_CASE', 'snake_case', 'PascalCase'],
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
selector: 'property',
|
|
81
|
-
format: null,
|
|
82
|
-
filter: '^__html$',
|
|
83
|
-
},
|
|
84
|
-
],
|
|
85
|
-
'@typescript-eslint/no-empty-function': 'off',
|
|
86
|
-
'no-unused-vars': 'off',
|
|
87
|
-
'@typescript-eslint/no-unused-vars': ['warn', { 'argsIgnorePattern': '^[_]*$' }],
|
|
88
|
-
'@typescript-eslint/no-explicit-any': 'off',
|
|
89
|
-
'@typescript-eslint/no-object-literal-type-assertion': 'off',
|
|
90
|
-
'@typescript-eslint/padding-line-between-statements': [
|
|
91
|
-
'error',
|
|
92
|
-
{
|
|
93
|
-
blankLine: 'always',
|
|
94
|
-
prev: ['interface', 'type'],
|
|
95
|
-
next: '*',
|
|
96
|
-
},
|
|
97
|
-
{ blankLine: 'always', prev: '*', next: ['return'] },
|
|
98
|
-
{ blankLine: 'always', prev: 'function', next: 'function' },
|
|
99
|
-
{ blankLine: 'always', prev: 'multiline-const', next: '*' },
|
|
100
|
-
{
|
|
101
|
-
blankLine: 'always',
|
|
102
|
-
prev: 'import',
|
|
103
|
-
next: [
|
|
104
|
-
'interface',
|
|
105
|
-
'type',
|
|
106
|
-
'block',
|
|
107
|
-
'block-like',
|
|
108
|
-
'case',
|
|
109
|
-
'class',
|
|
110
|
-
'const',
|
|
111
|
-
'export',
|
|
112
|
-
'expression',
|
|
113
|
-
'for',
|
|
114
|
-
'function',
|
|
115
|
-
'if',
|
|
116
|
-
'let',
|
|
117
|
-
'return',
|
|
118
|
-
'throw',
|
|
119
|
-
'try',
|
|
120
|
-
'while',
|
|
121
|
-
],
|
|
122
|
-
},
|
|
123
|
-
{
|
|
124
|
-
blankLine: 'always',
|
|
125
|
-
prev: [
|
|
126
|
-
'import',
|
|
127
|
-
'interface',
|
|
128
|
-
'type',
|
|
129
|
-
'block',
|
|
130
|
-
'block-like',
|
|
131
|
-
'case',
|
|
132
|
-
'class',
|
|
133
|
-
'const',
|
|
134
|
-
'expression',
|
|
135
|
-
'for',
|
|
136
|
-
'function',
|
|
137
|
-
'if',
|
|
138
|
-
'let',
|
|
139
|
-
'return',
|
|
140
|
-
'throw',
|
|
141
|
-
'try',
|
|
142
|
-
'while',
|
|
143
|
-
],
|
|
144
|
-
next: 'export',
|
|
145
|
-
},
|
|
146
|
-
{ blankLine: 'always', prev: 'directive', next: '*' },
|
|
147
|
-
],
|
|
148
|
-
'jsx-a11y/anchor-is-valid': [
|
|
149
|
-
'error',
|
|
150
|
-
{
|
|
151
|
-
components: ['Link'],
|
|
152
|
-
specialLink: ['hrefLeft', 'hrefRight'],
|
|
153
|
-
aspects: ['invalidHref', 'preferButton'],
|
|
154
|
-
},
|
|
155
|
-
],
|
|
156
|
-
curly: ['error', 'multi-line'],
|
|
157
|
-
'no-duplicate-imports': 'error',
|
|
158
|
-
'no-restricted-imports': [
|
|
159
|
-
'error',
|
|
160
|
-
{
|
|
161
|
-
paths: ['ui'],
|
|
162
|
-
patterns: [
|
|
163
|
-
{
|
|
164
|
-
group: ['@sh/app', '@sh/app/*'],
|
|
165
|
-
message: 'Importing from `app` package is disallowed for architecture reasons',
|
|
166
|
-
},
|
|
167
|
-
],
|
|
168
|
-
},
|
|
169
|
-
],
|
|
170
|
-
'react-hooks/exhaustive-deps': 'error',
|
|
171
|
-
'react-hooks/rules-of-hooks': 'error',
|
|
172
|
-
'react/button-has-type': 'error',
|
|
173
|
-
'react/display-name': 'off',
|
|
174
|
-
'react/no-unescaped-entities': 'off',
|
|
175
|
-
'react/prop-types': 'off',
|
|
176
|
-
'react/react-in-jsx-scope': 'off',
|
|
177
|
-
'react/self-closing-comp': 'warn',
|
|
178
|
-
'sort-imports': 'off',
|
|
179
|
-
'react/function-component-definition': "off",
|
|
180
|
-
'react/jsx-curly-brace-presence': [
|
|
181
|
-
2,
|
|
182
|
-
{
|
|
183
|
-
props: 'never',
|
|
184
|
-
children: 'never',
|
|
185
|
-
},
|
|
186
|
-
],
|
|
187
|
-
'react/jsx-sort-props': [
|
|
188
|
-
2,
|
|
189
|
-
{ ignoreCase: true, callbacksLast: true, shorthandLast: false, reservedFirst: true },
|
|
190
|
-
],
|
|
191
|
-
'max-lines': [
|
|
192
|
-
'error',
|
|
193
|
-
{
|
|
194
|
-
max: 300,
|
|
195
|
-
skipComments: true,
|
|
196
|
-
},
|
|
197
|
-
],
|
|
198
|
-
'no-console': 'error',
|
|
199
|
-
'simple-import-sort/imports': [
|
|
200
|
-
1,
|
|
201
|
-
{
|
|
202
|
-
groups: [
|
|
203
|
-
['^\\u0000'],
|
|
204
|
-
['^react', '^next', '^[^.]'],
|
|
205
|
-
['^@shakuroinc/', '^@sh/'],
|
|
206
|
-
['^@/', '^~/', '^#/', '^libs$', '^libs/', '^features/'],
|
|
207
|
-
['^\\.\\.(?!/?$)', '^\\.\\./?$', '^\\./(?=.*/)(?!/?$)', '^\\.(?!/?$)', '^\\./?$'],
|
|
208
|
-
['^.+\\.s?css$'],
|
|
209
|
-
],
|
|
210
|
-
},
|
|
211
|
-
],
|
|
212
|
-
'simple-import-sort/exports': 'warn',
|
|
213
|
-
'tailwindcss/classnames-order': 'error',
|
|
214
|
-
'tailwindcss/no-contradicting-classname': 'error',
|
|
215
|
-
'tailwindcss/no-custom-classname': 'warn',
|
|
216
|
-
quotes: ['error', 'single', { allowTemplateLiterals: false, avoidEscape: true }],
|
|
217
|
-
},
|
|
218
|
-
|
|
219
|
-
overrides: [
|
|
220
|
-
{
|
|
221
|
-
files: ['*js?x', '*ts?x'],
|
|
222
|
-
extends: ['plugin:import/recommended', 'plugin:import/typescript'],
|
|
223
|
-
rules: {
|
|
224
|
-
'import/order': 'off',
|
|
225
|
-
'import/no-restricted-paths': [
|
|
226
|
-
'error',
|
|
227
|
-
{
|
|
228
|
-
zones: [
|
|
229
|
-
{
|
|
230
|
-
target: 'ui',
|
|
231
|
-
from: 'app',
|
|
232
|
-
message: 'Importing from `app` package is disallowed for architecture reasons',
|
|
233
|
-
},
|
|
234
|
-
],
|
|
235
|
-
},
|
|
236
|
-
],
|
|
237
|
-
},
|
|
238
|
-
},
|
|
239
|
-
{
|
|
240
|
-
files: ['*.mdx', '*.md'],
|
|
241
|
-
extends: 'plugin:mdx/recommended',
|
|
242
|
-
parserOptions: {
|
|
243
|
-
ecmaVersion: 'latest',
|
|
244
|
-
},
|
|
245
|
-
rules: {
|
|
246
|
-
'@next/next/no-img-element': 'off',
|
|
247
|
-
'@typescript-eslint/naming-convention': 'off',
|
|
248
|
-
'@typescript-eslint/padding-line-between-statements': 'off',
|
|
249
|
-
'max-lines': 'off',
|
|
250
|
-
'no-unused-expressions': 'off',
|
|
251
|
-
'react/self-closing-comp': 'off',
|
|
252
|
-
},
|
|
253
|
-
},
|
|
254
|
-
],
|
|
255
|
-
};
|
package/.vscode/settings.json
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"typescript.tsdk": "node_modules/typescript/lib",
|
|
3
|
-
"eslint.validate": [
|
|
4
|
-
"markdown",
|
|
5
|
-
"mdx",
|
|
6
|
-
"javascript",
|
|
7
|
-
"javascriptreact",
|
|
8
|
-
"typescript",
|
|
9
|
-
"typescriptreact"
|
|
10
|
-
],
|
|
11
|
-
"eslint.options": {
|
|
12
|
-
"extensions": [".mdx", ".js", ".jsx", ".ts", ".tsx"]
|
|
13
|
-
},
|
|
14
|
-
"editor.formatOnSave": true,
|
|
15
|
-
"[javascript]": {
|
|
16
|
-
"editor.formatOnSave": false
|
|
17
|
-
},
|
|
18
|
-
"[javascriptreact]": {
|
|
19
|
-
"editor.formatOnSave": false
|
|
20
|
-
},
|
|
21
|
-
"[typescript]": {
|
|
22
|
-
"editor.formatOnSave": false
|
|
23
|
-
},
|
|
24
|
-
"[typescriptreact]": {
|
|
25
|
-
"editor.formatOnSave": false
|
|
26
|
-
},
|
|
27
|
-
"editor.codeActionsOnSave": {
|
|
28
|
-
"eslint.autoFixOnSave": true,
|
|
29
|
-
"source.fixAll.eslint": true
|
|
30
|
-
},
|
|
31
|
-
"window.title": "@shakuroinc/eslint-config-react | ${activeEditorShort}${separator}${rootName}",
|
|
32
|
-
"tailwindCSS.emmetCompletions": true,
|
|
33
|
-
"tailwindCSS.experimental.classRegex": [
|
|
34
|
-
"ClassName='([^']*)", // prefixClassName='...'
|
|
35
|
-
"ClassName=\"([^']*)", // prefixClassName="..."
|
|
36
|
-
["clsx\\(([^)]*)\\)", "(?:'|\"|`)([^']*)(?:'|\"|`)"] // clsx(...)
|
|
37
|
-
],
|
|
38
|
-
"cSpell.words": [
|
|
39
|
-
"clsx",
|
|
40
|
-
"shakuroinc"
|
|
41
|
-
]
|
|
42
|
-
}
|