@fabdeh/eslint-config 0.2.2 → 0.3.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 +258 -6
- package/dist/index.d.mts +44 -8
- package/dist/index.mjs +94 -25
- package/package.json +19 -9
package/README.md
CHANGED
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
- Designed to work with TypeScript, JSX, etc. Out-of-box.
|
|
10
10
|
- Opinionated, but [very customizable](#customization)
|
|
11
11
|
- [ESLint Flat config](https://eslint.org/docs/latest/use/configure/configuration-files-new), compose easily!
|
|
12
|
-
- Automatic [Angular](#angular), [NGRX](#ngrx), [
|
|
13
|
-
|
|
12
|
+
- Automatic [Angular](#angular), [NGRX](#ngrx), [TypeScript](#typescript), [Vitest](#vitest) support when the corresponding dependency is detected.
|
|
13
|
+
- Optional [formatters](#formatters) support for formatting CSS, HTML, XML, etc.
|
|
14
14
|
- **Style principle**: Minimal for reading, stable for diff, consistent
|
|
15
15
|
- Sorted imports, dangling commas
|
|
16
16
|
- Single quotes, no semi
|
|
@@ -49,8 +49,8 @@ For example:
|
|
|
49
49
|
```json
|
|
50
50
|
{
|
|
51
51
|
"scripts": {
|
|
52
|
-
"lint": "eslint .",
|
|
53
|
-
"lint:
|
|
52
|
+
"lint": "eslint . --fix",
|
|
53
|
+
"lint:ci": "eslint ."
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
```
|
|
@@ -78,11 +78,27 @@ Add the following settings to your `.vscode/settings.json`:
|
|
|
78
78
|
"source.organizeImports": "never"
|
|
79
79
|
},
|
|
80
80
|
|
|
81
|
-
//
|
|
81
|
+
// Silence the style rules in you IDE, but still fix them automatically
|
|
82
82
|
"eslint.rules.customizations": [{ "rule": "@stylistic/*", "severity": "off", "fixable": true }],
|
|
83
83
|
|
|
84
84
|
// Enable eslint for all supported languages
|
|
85
|
-
"eslint.validate": [
|
|
85
|
+
"eslint.validate": [
|
|
86
|
+
"css",
|
|
87
|
+
"html",
|
|
88
|
+
"javascript",
|
|
89
|
+
"javascriptreact",
|
|
90
|
+
"json",
|
|
91
|
+
"jsonc",
|
|
92
|
+
"json5",
|
|
93
|
+
"less",
|
|
94
|
+
"markdown",
|
|
95
|
+
"scss",
|
|
96
|
+
"typescript",
|
|
97
|
+
"typescriptreact",
|
|
98
|
+
"toml",
|
|
99
|
+
"yaml",
|
|
100
|
+
"xml"
|
|
101
|
+
]
|
|
86
102
|
}
|
|
87
103
|
```
|
|
88
104
|
|
|
@@ -202,6 +218,242 @@ Check out the [configs](https://github.com/FabienDehopre/eslint-config/blob/main
|
|
|
202
218
|
|
|
203
219
|
> Thanks to [antfu/eslint-config](https://github.com/antfu/eslint-config) for the inspiration and reference.
|
|
204
220
|
|
|
221
|
+
### Rules Overrides
|
|
222
|
+
|
|
223
|
+
All the rules are always bound to one or more file extensions (via minimatch pattern. i.e.: \*_/_.?([cm])[jt]s?(x) for all JS and TS file types including JSX syntax).
|
|
224
|
+
If you want to override the rules, you need to specify the file extension:
|
|
225
|
+
|
|
226
|
+
```js
|
|
227
|
+
// eslint.config.js
|
|
228
|
+
import { createConfig } from '@fabdeh/eslint-config';
|
|
229
|
+
|
|
230
|
+
export default createConfig(
|
|
231
|
+
{
|
|
232
|
+
typescript: true,
|
|
233
|
+
vitest: true
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
// Remember to specify the file glob here, otherwise it might cause the vitest plugin to handle non-spec files
|
|
237
|
+
files: ['**/*.spec.?([cm])[jt]s', '**/*.test.?([cm])[jt]s'],
|
|
238
|
+
rules: {
|
|
239
|
+
'vitest/consistent-test-it': ['error', { fn: 'it' }],
|
|
240
|
+
}
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
// Without `files`, they are general rules for all files
|
|
244
|
+
rules: {
|
|
245
|
+
'@stylistic/semi': ['error', 'never']
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
);
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
We also provide the `overrides` option in each integration to make it easier:
|
|
252
|
+
|
|
253
|
+
```js
|
|
254
|
+
// eslint.config.js
|
|
255
|
+
import { createConfig } from '@fabdeh/eslint-config';
|
|
256
|
+
|
|
257
|
+
export default createConfig({
|
|
258
|
+
typescript: {
|
|
259
|
+
overrides: {
|
|
260
|
+
'@typescript-eslint/consisten-type-definitions': ['error', 'interface'],
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
angular: {
|
|
264
|
+
tsOverrides: {
|
|
265
|
+
'@angular-eslint/prefer-signals': 'off',
|
|
266
|
+
},
|
|
267
|
+
htmlOverrides: {
|
|
268
|
+
'@angular-eslint/template/no-any': 'warn',
|
|
269
|
+
},
|
|
270
|
+
},
|
|
271
|
+
yaml: {
|
|
272
|
+
overrides: {
|
|
273
|
+
// ...
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### Auto-detected integrations
|
|
280
|
+
|
|
281
|
+
The following integrations are automatically enabled if the corresponding package is installed in your project:
|
|
282
|
+
|
|
283
|
+
- [TypeScript](#typescript)
|
|
284
|
+
- [Angular](#angular)
|
|
285
|
+
- [NgRx](#ngrx)
|
|
286
|
+
- [Vitest](#vitest)
|
|
287
|
+
|
|
288
|
+
#### TypeScript
|
|
289
|
+
|
|
290
|
+
Most of TypeScript rules are enable automatically if `typescript` package is installed in you project. Some `@typescript-eslint` rules are also enabled by default for JavaScript files.
|
|
291
|
+
You can explicitly enable/disable TypeScript integration manually:
|
|
292
|
+
|
|
293
|
+
```js
|
|
294
|
+
// eslint.config.js
|
|
295
|
+
import { createConfig } from '@fabdeh/eslint-config';
|
|
296
|
+
|
|
297
|
+
export default createConfig({
|
|
298
|
+
typescript: true,
|
|
299
|
+
});
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
##### Erasable Syntax Only
|
|
303
|
+
|
|
304
|
+
The TypeScript integration also allow you to turn on/off rules that will report on using syntax that will not be allowed by TypeScript's [--erasableSyntaxOnly option](https://devblogs.microsoft.com/typescript/announcing-typescript-5-8-beta/#the---erasablesyntaxonly-option):
|
|
305
|
+
|
|
306
|
+
> Recently, Node.js 23.6 unflagged [experimental support for running TypeScript files directly](https://nodejs.org/api/typescript.html#type-stripping); however, only certain constructs are supported under this mode.
|
|
307
|
+
>
|
|
308
|
+
> ...
|
|
309
|
+
>
|
|
310
|
+
> TypeScript 5.8 introduces the `--erasableSyntaxOnly` flag. When this flag is enabled, TypeScript will only allow you to use constructs that can be erased from a file, and will issue an error if it encounters any constructs that cannot be erased.
|
|
311
|
+
|
|
312
|
+
You can enable these rules as follow:
|
|
313
|
+
|
|
314
|
+
```js
|
|
315
|
+
// eslint.config.js
|
|
316
|
+
import { createConfig } from '@fabdeh/eslint-config';
|
|
317
|
+
|
|
318
|
+
export default createConfig({
|
|
319
|
+
typescript: {
|
|
320
|
+
enableErasableSyntaxOnly: true,
|
|
321
|
+
},
|
|
322
|
+
});
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
These rules are disabled by default and therefore the associated ESLint plugin is also not installed by default.
|
|
326
|
+
Running `pnpx eslint` should prompt you to install the required plugin; otherwise, you can install it manually:
|
|
327
|
+
|
|
328
|
+
```bash
|
|
329
|
+
pnpm add -D eslint-plugin-erasable-syntax-only
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
#### Angular
|
|
333
|
+
|
|
334
|
+
Angular support is detected automatically by checking if `@angular/core` is installed in your project. You can also explicitly enable/disable it:
|
|
335
|
+
|
|
336
|
+
```js
|
|
337
|
+
// eslint.config.js
|
|
338
|
+
import { createConfig } from '@fabdeh/eslint-config';
|
|
339
|
+
|
|
340
|
+
export default createConfig({
|
|
341
|
+
angular: true,
|
|
342
|
+
});
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
#### NgRx
|
|
346
|
+
|
|
347
|
+
NgRx support is also detected automatically if any of the following package is installed in your project.
|
|
348
|
+
|
|
349
|
+
- `@ngrx/store`
|
|
350
|
+
- `@ngrx/effects`
|
|
351
|
+
- `@ngrx/signals`
|
|
352
|
+
- `@ngrx/operators`
|
|
353
|
+
|
|
354
|
+
As the Angular integration is can be explicitly enabled/disabled:
|
|
355
|
+
|
|
356
|
+
```js
|
|
357
|
+
// eslint.config.js
|
|
358
|
+
import { createConfig } from '@fabdeh/eslint-config';
|
|
359
|
+
|
|
360
|
+
export default createConfig({
|
|
361
|
+
ngrx: true,
|
|
362
|
+
});
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
> Of course, NgRx depends on Angular so the Angular integration will be enabled as well.
|
|
366
|
+
|
|
367
|
+
#### Vitest
|
|
368
|
+
|
|
369
|
+
The vitest integration is detected automatically by checking if `vitest` is installed in your project. It can be enable/disable manually in the configuration:
|
|
370
|
+
|
|
371
|
+
```js
|
|
372
|
+
// eslint.config.js
|
|
373
|
+
import { createConfig } from '@fabdeh/eslint-config';
|
|
374
|
+
|
|
375
|
+
export default createConfig({
|
|
376
|
+
vitest: true,
|
|
377
|
+
});
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
### Optional integrations
|
|
381
|
+
|
|
382
|
+
We provide some optional integrations for specific use cases, that we don't include their dependencies by default.
|
|
383
|
+
|
|
384
|
+
#### Formatters
|
|
385
|
+
|
|
386
|
+
Use external formatters to format files that ESLint cannot handle yet (`.css`, `.html`, etc). Powered by [`eslint-plugin-format`](https://github.com/antfu/eslint-plugin-format).
|
|
387
|
+
|
|
388
|
+
```js
|
|
389
|
+
// eslint.config.js
|
|
390
|
+
import { createConfig } from '@fabdeh/eslint-config';
|
|
391
|
+
|
|
392
|
+
export default createConfig({
|
|
393
|
+
formatters: {
|
|
394
|
+
/**
|
|
395
|
+
* Format CSS, LESS, SCSS files
|
|
396
|
+
*/
|
|
397
|
+
css: true,
|
|
398
|
+
/**
|
|
399
|
+
* Format HTML files
|
|
400
|
+
*/
|
|
401
|
+
html: true,
|
|
402
|
+
/**
|
|
403
|
+
* Format Markdown files
|
|
404
|
+
*/
|
|
405
|
+
markdown: true,
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
Running `npx eslint` should prompt you to install the required dependencies; otherwise, you can install them manually:
|
|
411
|
+
|
|
412
|
+
```bash
|
|
413
|
+
pnpm add -D eslint-plugin-format
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
### Lint Staged
|
|
417
|
+
|
|
418
|
+
If you want to apply lint and auto-fix before every commit, you can add the following to your `package.json`:
|
|
419
|
+
|
|
420
|
+
```json
|
|
421
|
+
{
|
|
422
|
+
"simple-git-hooks": {
|
|
423
|
+
"pre-commit": "pnpm nano-staged"
|
|
424
|
+
},
|
|
425
|
+
"nano-staged": {
|
|
426
|
+
"*": "eslint --fix"
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
and then
|
|
432
|
+
|
|
433
|
+
```bash
|
|
434
|
+
pnpm add -D nano-staged simple-git-hooks
|
|
435
|
+
|
|
436
|
+
# then, to activate the hooks
|
|
437
|
+
pnpm simple-git-hooks
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
## Versioning Policy
|
|
441
|
+
|
|
442
|
+
This project follows [Semantic Versioning](https://semver.org/) for releases. However, since this is just a config and involves opinions and many moving parts, we don't treat rules changes as breaking changes.
|
|
443
|
+
|
|
444
|
+
### Changes Considered as Breaking Changes
|
|
445
|
+
|
|
446
|
+
- Node.js version requirement changes
|
|
447
|
+
- Huge refactors that might break the config
|
|
448
|
+
- Plugins made major changes that might break the config
|
|
449
|
+
- Changes that might affect most of the codebases
|
|
450
|
+
|
|
451
|
+
### Changes Considered as Non-breaking Changes
|
|
452
|
+
|
|
453
|
+
- Enable/disable rules and plugins (that might become stricter)
|
|
454
|
+
- Rules options changes
|
|
455
|
+
- Version bumps of dependencies
|
|
456
|
+
|
|
205
457
|
## License
|
|
206
458
|
|
|
207
459
|
[MIT](./LICENSE) License © 2025-PRESENT [Fabien Dehopré](https://github.com/FabienDehopre)
|
package/dist/index.d.mts
CHANGED
|
@@ -170,9 +170,9 @@ interface UnicornOptions {
|
|
|
170
170
|
allRecommended?: boolean;
|
|
171
171
|
}
|
|
172
172
|
/**
|
|
173
|
-
* An alias for the `StylisticCustomizeOptions` type without the `
|
|
173
|
+
* An alias for the `StylisticCustomizeOptions` type without the `pluginName` property.
|
|
174
174
|
*/
|
|
175
|
-
type StylisticConfig = Omit<StylisticCustomizeOptions, '
|
|
175
|
+
type StylisticConfig = Omit<StylisticCustomizeOptions, 'pluginName'>;
|
|
176
176
|
/**
|
|
177
177
|
* Interface representing the stylistic options.
|
|
178
178
|
*/
|
|
@@ -191,6 +191,14 @@ interface TypeScriptParserOptions {
|
|
|
191
191
|
*/
|
|
192
192
|
parserOptions?: TSESLint.FlatConfig.ParserOptions;
|
|
193
193
|
}
|
|
194
|
+
interface TypeScriptErasableSyntaxOnlyOptions {
|
|
195
|
+
/**
|
|
196
|
+
* Indicates whether the erasable syntax only rules should be enabled or not.
|
|
197
|
+
*
|
|
198
|
+
* @default false
|
|
199
|
+
*/
|
|
200
|
+
enableErasableSyntaxOnly?: boolean;
|
|
201
|
+
}
|
|
194
202
|
/**
|
|
195
203
|
* Options for configuring Angular-specific linting rules.
|
|
196
204
|
*/
|
|
@@ -283,6 +291,19 @@ interface FormattersOptions {
|
|
|
283
291
|
files?: string[];
|
|
284
292
|
};
|
|
285
293
|
}
|
|
294
|
+
interface RegExpOptions {
|
|
295
|
+
/**
|
|
296
|
+
* Override rules level.
|
|
297
|
+
*/
|
|
298
|
+
level?: 'error' | 'warn';
|
|
299
|
+
}
|
|
300
|
+
interface TailwindcssParserPerGlobOptions {
|
|
301
|
+
/**
|
|
302
|
+
* Provides a specific ESLint parser per glob pattern.
|
|
303
|
+
* This is only needed if you want to lint tailwindcss without using Angular and TypeScript.
|
|
304
|
+
*/
|
|
305
|
+
parsers?: Record<string, TSESLint.FlatConfig.Parser>;
|
|
306
|
+
}
|
|
286
307
|
/**
|
|
287
308
|
* Options for creating an ESLint configuration.
|
|
288
309
|
*
|
|
@@ -307,7 +328,7 @@ interface CreateConfigOptions {
|
|
|
307
328
|
*
|
|
308
329
|
* @default auto-detected
|
|
309
330
|
*/
|
|
310
|
-
typescript?: boolean | (OverridesOptions & TypeScriptParserOptions);
|
|
331
|
+
typescript?: boolean | (OverridesOptions & TypeScriptErasableSyntaxOnlyOptions & TypeScriptParserOptions);
|
|
311
332
|
/**
|
|
312
333
|
* Enable stylistic rules.
|
|
313
334
|
*
|
|
@@ -315,6 +336,13 @@ interface CreateConfigOptions {
|
|
|
315
336
|
* @default true
|
|
316
337
|
*/
|
|
317
338
|
stylistic?: boolean | (OverridesOptions & StylisticConfig);
|
|
339
|
+
/**
|
|
340
|
+
* Enable regexp rules.
|
|
341
|
+
*
|
|
342
|
+
* @see https://ota-meshi.github.io/eslint-plugin-regexp/
|
|
343
|
+
* @default true
|
|
344
|
+
*/
|
|
345
|
+
regexp?: boolean | (OverridesOptions & RegExpOptions);
|
|
318
346
|
/**
|
|
319
347
|
* Options for eslint-plugin-unicorn.
|
|
320
348
|
*
|
|
@@ -342,9 +370,9 @@ interface CreateConfigOptions {
|
|
|
342
370
|
/**
|
|
343
371
|
* Options for the TailwindCSS linting rules.
|
|
344
372
|
*
|
|
345
|
-
* @default
|
|
373
|
+
* @default false
|
|
346
374
|
*/
|
|
347
|
-
tailwindcss?: OverridesOptions |
|
|
375
|
+
tailwindcss?: boolean | (FilesOptions & OverridesOptions) | (OverridesOptions & TailwindcssParserPerGlobOptions);
|
|
348
376
|
/**
|
|
349
377
|
* Enable JSONC support.
|
|
350
378
|
*
|
|
@@ -529,6 +557,14 @@ declare function ngrx(options?: NgrxOptions): Promise<ConfigArray>;
|
|
|
529
557
|
*/
|
|
530
558
|
declare function perfectionist(): Promise<ConfigArray>;
|
|
531
559
|
|
|
560
|
+
/**
|
|
561
|
+
* Configure the recommended regexp rules.
|
|
562
|
+
*
|
|
563
|
+
* @param options - The options
|
|
564
|
+
* @returns The ESLint configuration for regexp linting
|
|
565
|
+
*/
|
|
566
|
+
declare function regexp(options?: OverridesOptions & RegExpOptions): ConfigArray;
|
|
567
|
+
|
|
532
568
|
/**
|
|
533
569
|
* Configures ESLint rules for sorting keys and array values in `package.json` files.
|
|
534
570
|
*
|
|
@@ -577,7 +613,7 @@ declare function stylistic(options?: StylisticOptions): Promise<ConfigArray>;
|
|
|
577
613
|
* },
|
|
578
614
|
* });
|
|
579
615
|
*/
|
|
580
|
-
declare function tailwindcss(options?: OverridesOptions): Promise<ConfigArray>;
|
|
616
|
+
declare function tailwindcss(options?: (FilesOptions & OverridesOptions) | (OverridesOptions & TailwindcssParserPerGlobOptions)): Promise<ConfigArray>;
|
|
581
617
|
|
|
582
618
|
/**
|
|
583
619
|
* Generates an ESLint configuration for TOML files.
|
|
@@ -600,7 +636,7 @@ declare function toml(options?: FilesOptions & OverridesOptions & StylisticOptio
|
|
|
600
636
|
* @param options.overrides - Additional rule overrides.
|
|
601
637
|
* @returns A ConfigArray containing the TypeScript ESLint configuration.
|
|
602
638
|
*/
|
|
603
|
-
declare function typescript(options?: OverridesOptions & StylisticOptions & TypeScriptParserOptions): ConfigArray
|
|
639
|
+
declare function typescript(options?: OverridesOptions & StylisticOptions & TypeScriptErasableSyntaxOnlyOptions & TypeScriptParserOptions): Promise<ConfigArray>;
|
|
604
640
|
|
|
605
641
|
/**
|
|
606
642
|
* Generates a configuration array for the Unicorn plugin with the specified options.
|
|
@@ -739,4 +775,4 @@ type ResolvedOptions<T> = T extends boolean ? never : NonNullable<T>;
|
|
|
739
775
|
*/
|
|
740
776
|
declare function resolveSubOptions<K extends keyof CreateConfigOptions>(options: CreateConfigOptions, key: K): ResolvedOptions<CreateConfigOptions[K]>;
|
|
741
777
|
|
|
742
|
-
export { type AngularOptions, type Awaitable, type CreateConfigOptions, type FilesOptions, type FormattersOptions, GLOB_HTML, GLOB_JS, GLOB_SRC, GLOB_TESTS, GLOB_TS, type NgrxOperators, type NgrxOptions, type OverridesOptions, type ResolvedOptions, STYLISTIC_CONFIG_DEFAULT, type StylisticConfig, type StylisticOptions, type TestingOptions, type TypeScriptParserOptions, type UnicornOptions, angular, comments, createConfig, ensurePackages, findNearestPackageJsonName, getWorkspaceRoot, ignores, imports, interopDefault, isPackageInScope, javascript, jsdoc, jsonc, markdown, ngrx, perfectionist, resolveSubOptions, sortPackageJson, sortTsConfig, stylistic, tailwindcss, toml, typescript, unicorn, vitest, yaml };
|
|
778
|
+
export { type AngularOptions, type Awaitable, type CreateConfigOptions, type FilesOptions, type FormattersOptions, GLOB_HTML, GLOB_JS, GLOB_SRC, GLOB_TESTS, GLOB_TS, type NgrxOperators, type NgrxOptions, type OverridesOptions, type RegExpOptions, type ResolvedOptions, STYLISTIC_CONFIG_DEFAULT, type StylisticConfig, type StylisticOptions, type TailwindcssParserPerGlobOptions, type TestingOptions, type TypeScriptErasableSyntaxOnlyOptions, type TypeScriptParserOptions, type UnicornOptions, angular, comments, createConfig, ensurePackages, findNearestPackageJsonName, getWorkspaceRoot, ignores, imports, interopDefault, isPackageInScope, javascript, jsdoc, jsonc, markdown, ngrx, perfectionist, regexp, resolveSubOptions, sortPackageJson, sortTsConfig, stylistic, tailwindcss, toml, typescript, unicorn, vitest, yaml };
|
package/dist/index.mjs
CHANGED
|
@@ -14,6 +14,7 @@ import jsdocPlugin from 'eslint-plugin-jsdoc';
|
|
|
14
14
|
import * as importX from 'eslint-plugin-import-x';
|
|
15
15
|
import perfectionistPlugin from 'eslint-plugin-perfectionist';
|
|
16
16
|
import unicornPlugin from 'eslint-plugin-unicorn';
|
|
17
|
+
import { configs } from 'eslint-plugin-regexp';
|
|
17
18
|
import { mergeProcessors, processorPassThrough } from 'eslint-merge-processors';
|
|
18
19
|
|
|
19
20
|
const GLOB_SRC_EXT = "?([cm])[jt]s?(x)";
|
|
@@ -37,7 +38,7 @@ const GLOB_XML = "**/*.xml";
|
|
|
37
38
|
const GLOB_SVG = "**/*.svg";
|
|
38
39
|
const GLOB_GRAPHQL = "**/*.{g,graph}ql";
|
|
39
40
|
const GLOB_HTML = "**/*.htm?(l)";
|
|
40
|
-
const GLOB_TESTS = [`**/*.spec
|
|
41
|
+
const GLOB_TESTS = [`**/*.spec.?([cm])[jt]s`, `**/*.test.?([cm])[jt]s`, `**/test-setup.?([cm])[jt]s`];
|
|
41
42
|
const GLOB_EXCLUDE = [
|
|
42
43
|
"**/node_modules",
|
|
43
44
|
"**/dist",
|
|
@@ -934,6 +935,27 @@ async function perfectionist() {
|
|
|
934
935
|
});
|
|
935
936
|
}
|
|
936
937
|
|
|
938
|
+
function regexp(options = {}) {
|
|
939
|
+
const { level, overrides } = options;
|
|
940
|
+
const config = configs["flat/recommended"];
|
|
941
|
+
const rules = Object.fromEntries(
|
|
942
|
+
Object.entries(config.rules).map(([ruleName, ruleLevel]) => [ruleName, level === "warn" ? level : ruleLevel])
|
|
943
|
+
);
|
|
944
|
+
return tseslint.config(
|
|
945
|
+
{
|
|
946
|
+
name: "fabdeh/regexp/rules",
|
|
947
|
+
files: [GLOB_SRC],
|
|
948
|
+
plugins: {
|
|
949
|
+
...config.plugins
|
|
950
|
+
},
|
|
951
|
+
rules: {
|
|
952
|
+
...rules,
|
|
953
|
+
...overrides
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
);
|
|
957
|
+
}
|
|
958
|
+
|
|
937
959
|
function sortPackageJson() {
|
|
938
960
|
return tseslint.config({
|
|
939
961
|
name: "fabdeh/sort/package-json",
|
|
@@ -1168,9 +1190,12 @@ const STYLISTIC_CONFIG_DEFAULT = {
|
|
|
1168
1190
|
quoteProps: "as-needed"
|
|
1169
1191
|
};
|
|
1170
1192
|
async function stylistic(options = {}) {
|
|
1171
|
-
const stylisticOptions = {
|
|
1193
|
+
const stylisticOptions = {
|
|
1194
|
+
...STYLISTIC_CONFIG_DEFAULT,
|
|
1195
|
+
...typeof options.stylistic === "boolean" ? {} : options.stylistic
|
|
1196
|
+
};
|
|
1172
1197
|
const stylisticPlugin = await interopDefault(import('@stylistic/eslint-plugin'));
|
|
1173
|
-
const config = stylisticPlugin.configs.customize(
|
|
1198
|
+
const config = stylisticPlugin.configs.customize(stylisticOptions);
|
|
1174
1199
|
return tseslint.config({
|
|
1175
1200
|
name: "fabdeh/stylistic/rules",
|
|
1176
1201
|
files: [GLOB_SRC],
|
|
@@ -1186,22 +1211,45 @@ async function stylistic(options = {}) {
|
|
|
1186
1211
|
});
|
|
1187
1212
|
}
|
|
1188
1213
|
|
|
1214
|
+
function isTailwindcssParserPerGlobOptions(options) {
|
|
1215
|
+
return "parsers" in options && options.parsers !== void 0;
|
|
1216
|
+
}
|
|
1189
1217
|
async function tailwindcss(options = {}) {
|
|
1218
|
+
await ensurePackages(["eslint-plugin-tailwindcss"]);
|
|
1190
1219
|
const tailwindcssPlugin = await interopDefault(import('eslint-plugin-tailwindcss'));
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1220
|
+
let files;
|
|
1221
|
+
let parserConfigs;
|
|
1222
|
+
const { overrides = {} } = options;
|
|
1223
|
+
if (isTailwindcssParserPerGlobOptions(options)) {
|
|
1224
|
+
const parsers = options.parsers ?? {};
|
|
1225
|
+
files = { files: [...new Set(Object.keys(parsers))] };
|
|
1226
|
+
parserConfigs = Object.entries(parsers).map(([glob, parser], index) => ({
|
|
1227
|
+
name: `fabdeh/tailwindcss/parser-${index + 1}`,
|
|
1228
|
+
file: [glob],
|
|
1229
|
+
languageOptions: {
|
|
1230
|
+
parser
|
|
1231
|
+
}
|
|
1232
|
+
}));
|
|
1233
|
+
} else {
|
|
1234
|
+
files = { files: options.files ?? [GLOB_SRC, GLOB_HTML] };
|
|
1235
|
+
parserConfigs = [];
|
|
1236
|
+
}
|
|
1237
|
+
return tseslint.config(
|
|
1238
|
+
...parserConfigs,
|
|
1239
|
+
{
|
|
1240
|
+
name: "fabdeh/tailwindcss/rules",
|
|
1241
|
+
plugins: { tailwindcss: tailwindcssPlugin },
|
|
1242
|
+
...files,
|
|
1243
|
+
rules: {
|
|
1244
|
+
"tailwindcss/classnames-order": "error",
|
|
1245
|
+
"tailwindcss/enforces-negative-arbitrary-values": "error",
|
|
1246
|
+
"tailwindcss/enforces-shorthand": "error",
|
|
1247
|
+
"tailwindcss/no-contradicting-classname": "error",
|
|
1248
|
+
"tailwindcss/no-unnecessary-arbitrary-value": "error",
|
|
1249
|
+
...overrides
|
|
1250
|
+
}
|
|
1203
1251
|
}
|
|
1204
|
-
|
|
1252
|
+
);
|
|
1205
1253
|
}
|
|
1206
1254
|
|
|
1207
1255
|
async function toml(options = {}) {
|
|
@@ -1278,8 +1326,16 @@ const memberOrdering = {
|
|
|
1278
1326
|
]
|
|
1279
1327
|
};
|
|
1280
1328
|
|
|
1281
|
-
function typescript(options = {}) {
|
|
1282
|
-
const { stylistic = true, parserOptions = {}, overrides = {} } = options;
|
|
1329
|
+
async function typescript(options = {}) {
|
|
1330
|
+
const { stylistic = true, parserOptions = {}, overrides = {}, enableErasableSyntaxOnly = false } = options;
|
|
1331
|
+
let erasableSyntaxOnlyPlugin;
|
|
1332
|
+
let erasableSyntaxOnlyRules;
|
|
1333
|
+
if (enableErasableSyntaxOnly) {
|
|
1334
|
+
await ensurePackages(["eslint-plugin-erasable-syntax-only"]);
|
|
1335
|
+
const erasableSyntaxOnly = await interopDefault(import('eslint-plugin-erasable-syntax-only'));
|
|
1336
|
+
erasableSyntaxOnlyPlugin = erasableSyntaxOnly;
|
|
1337
|
+
erasableSyntaxOnlyRules = erasableSyntaxOnly.configs.recommended.rules;
|
|
1338
|
+
}
|
|
1283
1339
|
return tseslint.config(
|
|
1284
1340
|
{
|
|
1285
1341
|
name: "fabdeh/typescript/setup",
|
|
@@ -1304,7 +1360,8 @@ function typescript(options = {}) {
|
|
|
1304
1360
|
ignores: [`${GLOB_MARKDOWN}/**`],
|
|
1305
1361
|
plugins: {
|
|
1306
1362
|
"@typescript-eslint": tseslint.plugin,
|
|
1307
|
-
"unused-imports": unusedImports
|
|
1363
|
+
"unused-imports": unusedImports,
|
|
1364
|
+
...erasableSyntaxOnlyPlugin ? { "erasable-syntax-only": erasableSyntaxOnlyPlugin } : {}
|
|
1308
1365
|
},
|
|
1309
1366
|
rules: {
|
|
1310
1367
|
...tseslint.configs.strictTypeChecked.find((c) => c.name === "typescript-eslint/eslint-recommended")?.rules,
|
|
@@ -1371,6 +1428,7 @@ function typescript(options = {}) {
|
|
|
1371
1428
|
"@typescript-eslint/unbound-method": ["error", { ignoreStatic: true }],
|
|
1372
1429
|
"@typescript-eslint/unified-signatures": "error",
|
|
1373
1430
|
"@typescript-eslint/no-unused-vars": "off",
|
|
1431
|
+
...erasableSyntaxOnlyRules,
|
|
1374
1432
|
...overrides
|
|
1375
1433
|
}
|
|
1376
1434
|
}
|
|
@@ -1610,7 +1668,7 @@ function mergePrettierOptions(options, overrides = {}) {
|
|
|
1610
1668
|
/* eslint-enable @typescript-eslint/no-unsafe-assignment */
|
|
1611
1669
|
};
|
|
1612
1670
|
}
|
|
1613
|
-
async function formatters(options = {}, stylistic = {}) {
|
|
1671
|
+
async function formatters(options = {}, stylistic = {}, hasAngularTemplateParser = false) {
|
|
1614
1672
|
if (options === true) {
|
|
1615
1673
|
const isPrettierPluginXmlInScope = isPackageInScope("@prettier/plugin-xml");
|
|
1616
1674
|
options = {
|
|
@@ -1707,8 +1765,10 @@ async function formatters(options = {}, stylistic = {}) {
|
|
|
1707
1765
|
if (options.html) {
|
|
1708
1766
|
configs.push({
|
|
1709
1767
|
name: "fabdeh/formatter/html",
|
|
1710
|
-
|
|
1711
|
-
|
|
1768
|
+
...hasAngularTemplateParser ? {} : {
|
|
1769
|
+
languageOptions: {
|
|
1770
|
+
parser: formatPlugin.parserPlain
|
|
1771
|
+
}
|
|
1712
1772
|
},
|
|
1713
1773
|
files: [GLOB_HTML],
|
|
1714
1774
|
rules: {
|
|
@@ -1828,7 +1888,8 @@ async function createConfig(options = {}, ...userConfigs) {
|
|
|
1828
1888
|
angular: enableAngular = isPackageExists("@angular/core"),
|
|
1829
1889
|
gitignore: enableGitignore = true,
|
|
1830
1890
|
ngrx: enableNgrx = NGRX_PACKAGES.some((p) => isPackageExists(p)),
|
|
1831
|
-
|
|
1891
|
+
regexp: enableRegexp = true,
|
|
1892
|
+
tailwindcss: enableTailwind = false,
|
|
1832
1893
|
typescript: enableTypescript = isPackageExists("typescript"),
|
|
1833
1894
|
unicorn: enableUnicorn = true,
|
|
1834
1895
|
vitest: enableVitest = isPackageExists("vitest")
|
|
@@ -1873,6 +1934,10 @@ async function createConfig(options = {}, ...userConfigs) {
|
|
|
1873
1934
|
if (stylisticOptions) {
|
|
1874
1935
|
configs.push(stylistic({ stylistic: stylisticOptions }));
|
|
1875
1936
|
}
|
|
1937
|
+
if (enableRegexp) {
|
|
1938
|
+
const regexpOptions = resolveSubOptions(options, "regexp");
|
|
1939
|
+
configs.push(regexp(regexpOptions));
|
|
1940
|
+
}
|
|
1876
1941
|
if (enableAngular) {
|
|
1877
1942
|
const angularOptions = resolveSubOptions(options, "angular");
|
|
1878
1943
|
configs.push(angular(angularOptions));
|
|
@@ -1919,7 +1984,11 @@ async function createConfig(options = {}, ...userConfigs) {
|
|
|
1919
1984
|
configs.push(markdown(markdownOptions));
|
|
1920
1985
|
}
|
|
1921
1986
|
if (options.formatters) {
|
|
1922
|
-
configs.push(formatters(
|
|
1987
|
+
configs.push(formatters(
|
|
1988
|
+
options.formatters,
|
|
1989
|
+
typeof stylisticOptions === "boolean" ? {} : stylisticOptions,
|
|
1990
|
+
Boolean(enableAngular)
|
|
1991
|
+
));
|
|
1923
1992
|
}
|
|
1924
1993
|
if ("files" in options) {
|
|
1925
1994
|
throw new Error('[@fabdeh/eslint-config] The first argument should not contain the "files" property as the options are supposed to be global. Place it in the second or later config instead.');
|
|
@@ -1933,4 +2002,4 @@ async function createConfig(options = {}, ...userConfigs) {
|
|
|
1933
2002
|
return tseslint.config(...await Promise.all(configs), ...await Promise.all(userConfigs));
|
|
1934
2003
|
}
|
|
1935
2004
|
|
|
1936
|
-
export { GLOB_HTML, GLOB_JS, GLOB_SRC, GLOB_TESTS, GLOB_TS, STYLISTIC_CONFIG_DEFAULT, angular, comments, createConfig, ensurePackages, findNearestPackageJsonName, getWorkspaceRoot, ignores, imports, interopDefault, isPackageInScope, javascript, jsdoc, jsonc, markdown, ngrx, perfectionist, resolveSubOptions, sortPackageJson, sortTsConfig, stylistic, tailwindcss, toml, typescript, unicorn, vitest, yaml };
|
|
2005
|
+
export { GLOB_HTML, GLOB_JS, GLOB_SRC, GLOB_TESTS, GLOB_TS, STYLISTIC_CONFIG_DEFAULT, angular, comments, createConfig, ensurePackages, findNearestPackageJsonName, getWorkspaceRoot, ignores, imports, interopDefault, isPackageInScope, javascript, jsdoc, jsonc, markdown, ngrx, perfectionist, regexp, resolveSubOptions, sortPackageJson, sortTsConfig, stylistic, tailwindcss, toml, typescript, unicorn, vitest, yaml };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fabdeh/eslint-config",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.3.0",
|
|
5
5
|
"packageManager": "pnpm@10.4.1",
|
|
6
6
|
"description": "My personal eslint config preset",
|
|
7
7
|
"author": {
|
|
@@ -55,16 +55,24 @@
|
|
|
55
55
|
"peerDependencies": {
|
|
56
56
|
"@prettier/plugin-xml": "^3.4.1",
|
|
57
57
|
"eslint": "^9.20.0",
|
|
58
|
+
"eslint-plugin-erasable-syntax-only": "^0.2.1",
|
|
58
59
|
"eslint-plugin-format": "^1.0.1",
|
|
60
|
+
"eslint-plugin-tailwindcss": "^3.18.0",
|
|
59
61
|
"prettier-plugin-slidev": "^1.0.5"
|
|
60
62
|
},
|
|
61
63
|
"peerDependenciesMeta": {
|
|
62
64
|
"@prettier/plugin-xml": {
|
|
63
65
|
"optional": true
|
|
64
66
|
},
|
|
67
|
+
"eslint-plugin-erasable-syntax-only": {
|
|
68
|
+
"optional": true
|
|
69
|
+
},
|
|
65
70
|
"eslint-plugin-format": {
|
|
66
71
|
"optional": true
|
|
67
72
|
},
|
|
73
|
+
"eslint-plugin-tailwindcss": {
|
|
74
|
+
"optional": true
|
|
75
|
+
},
|
|
68
76
|
"prettier-plugin-slidev": {
|
|
69
77
|
"optional": true
|
|
70
78
|
}
|
|
@@ -73,10 +81,10 @@
|
|
|
73
81
|
"@antfu/install-pkg": "^1.0.0",
|
|
74
82
|
"@clack/prompts": "^0.10.0",
|
|
75
83
|
"@eslint-community/eslint-plugin-eslint-comments": "^4.4.1",
|
|
76
|
-
"@eslint/js": "^9.
|
|
84
|
+
"@eslint/js": "^9.21.0",
|
|
77
85
|
"@eslint/markdown": "^6.2.2",
|
|
78
86
|
"@ngrx/eslint-plugin": "^19.0.1",
|
|
79
|
-
"@stylistic/eslint-plugin": "^
|
|
87
|
+
"@stylistic/eslint-plugin": "^4.0.1",
|
|
80
88
|
"@typescript-eslint/eslint-plugin": "^8.24.1",
|
|
81
89
|
"@typescript-eslint/parser": "^8.24.1",
|
|
82
90
|
"@typescript-eslint/utils": "^8.24.1",
|
|
@@ -91,13 +99,13 @@
|
|
|
91
99
|
"eslint-plugin-jsonc": "^2.19.1",
|
|
92
100
|
"eslint-plugin-perfectionist": "^4.9.0",
|
|
93
101
|
"eslint-plugin-prefer-arrow-functions": "^3.6.2",
|
|
94
|
-
"eslint-plugin-
|
|
102
|
+
"eslint-plugin-regexp": "^2.7.0",
|
|
95
103
|
"eslint-plugin-testing-library": "^7.1.1",
|
|
96
104
|
"eslint-plugin-toml": "^0.12.0",
|
|
97
105
|
"eslint-plugin-unicorn": "^57.0.0",
|
|
98
106
|
"eslint-plugin-unused-imports": "^4.1.4",
|
|
99
107
|
"eslint-plugin-yml": "^1.17.0",
|
|
100
|
-
"globals": "^
|
|
108
|
+
"globals": "^16.0.0",
|
|
101
109
|
"jsonc-eslint-parser": "^2.4.0",
|
|
102
110
|
"local-pkg": "^1.0.0",
|
|
103
111
|
"toml-eslint-parser": "^0.10.0",
|
|
@@ -105,7 +113,7 @@
|
|
|
105
113
|
"yaml-eslint-parser": "^1.2.3"
|
|
106
114
|
},
|
|
107
115
|
"devDependencies": {
|
|
108
|
-
"@angular/core": "^19.1.
|
|
116
|
+
"@angular/core": "^19.1.7",
|
|
109
117
|
"@commitlint/cli": "^19.7.1",
|
|
110
118
|
"@commitlint/config-conventional": "^19.7.1",
|
|
111
119
|
"@commitlint/cz-commitlint": "^19.6.1",
|
|
@@ -118,12 +126,14 @@
|
|
|
118
126
|
"@testing-library/angular": "^17.3.6",
|
|
119
127
|
"@testing-library/jest-dom": "^6.6.3",
|
|
120
128
|
"@types/fs-extra": "^11.0.4",
|
|
121
|
-
"@types/node": "^22.13.
|
|
129
|
+
"@types/node": "^22.13.5",
|
|
122
130
|
"bumpp": "^10.0.3",
|
|
123
131
|
"changelogithub": "^13.12.1",
|
|
124
132
|
"commitizen": "^4.3.1",
|
|
125
|
-
"eslint": "^9.
|
|
133
|
+
"eslint": "^9.21.0",
|
|
134
|
+
"eslint-plugin-erasable-syntax-only": "^0.2.1",
|
|
126
135
|
"eslint-plugin-format": "^1.0.1",
|
|
136
|
+
"eslint-plugin-tailwindcss": "^3.18.0",
|
|
127
137
|
"execa": "^9.5.2",
|
|
128
138
|
"fast-glob": "^3.3.3",
|
|
129
139
|
"fs-extra": "^11.3.0",
|
|
@@ -136,7 +146,7 @@
|
|
|
136
146
|
"tailwindcss": "^3.4.17",
|
|
137
147
|
"typescript": "^5.7.3",
|
|
138
148
|
"unbuild": "^3.3.1",
|
|
139
|
-
"vitest": "^3.0.
|
|
149
|
+
"vitest": "^3.0.6"
|
|
140
150
|
},
|
|
141
151
|
"pnpm": {
|
|
142
152
|
"overrides": {
|