@fabdeh/eslint-config 0.2.3 → 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 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), [TailwindCSS](#tailwindcc), [Vitest](#vitest) support when the corresponding dependency is detected.
13
- <!--- - Optional [formatters](#formatters) support for formatting CSS, HTML, XML, etc. --->
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:fix": "eslint . --fix"
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
- // Silent the stylistic rules in you IDE, but still auto fix them
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": ["javascript", "javascriptreact", "typescript", "typescriptreact", "html"]
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 &copy; 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 `flat`, `name`, and `pluginName` properties.
173
+ * An alias for the `StylisticCustomizeOptions` type without the `pluginName` property.
174
174
  */
175
- type StylisticConfig = Omit<StylisticCustomizeOptions, 'flat' | 'name' | 'pluginName'>;
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
  */
@@ -289,6 +297,13 @@ interface RegExpOptions {
289
297
  */
290
298
  level?: 'error' | 'warn';
291
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
+ }
292
307
  /**
293
308
  * Options for creating an ESLint configuration.
294
309
  *
@@ -313,7 +328,7 @@ interface CreateConfigOptions {
313
328
  *
314
329
  * @default auto-detected
315
330
  */
316
- typescript?: boolean | (OverridesOptions & TypeScriptParserOptions);
331
+ typescript?: boolean | (OverridesOptions & TypeScriptErasableSyntaxOnlyOptions & TypeScriptParserOptions);
317
332
  /**
318
333
  * Enable stylistic rules.
319
334
  *
@@ -355,9 +370,9 @@ interface CreateConfigOptions {
355
370
  /**
356
371
  * Options for the TailwindCSS linting rules.
357
372
  *
358
- * @default auto-detect based on dependencies.
373
+ * @default false
359
374
  */
360
- tailwindcss?: OverridesOptions | boolean;
375
+ tailwindcss?: boolean | (FilesOptions & OverridesOptions) | (OverridesOptions & TailwindcssParserPerGlobOptions);
361
376
  /**
362
377
  * Enable JSONC support.
363
378
  *
@@ -543,8 +558,10 @@ declare function ngrx(options?: NgrxOptions): Promise<ConfigArray>;
543
558
  declare function perfectionist(): Promise<ConfigArray>;
544
559
 
545
560
  /**
561
+ * Configure the recommended regexp rules.
546
562
  *
547
- * @param options
563
+ * @param options - The options
564
+ * @returns The ESLint configuration for regexp linting
548
565
  */
549
566
  declare function regexp(options?: OverridesOptions & RegExpOptions): ConfigArray;
550
567
 
@@ -596,7 +613,7 @@ declare function stylistic(options?: StylisticOptions): Promise<ConfigArray>;
596
613
  * },
597
614
  * });
598
615
  */
599
- declare function tailwindcss(options?: OverridesOptions): Promise<ConfigArray>;
616
+ declare function tailwindcss(options?: (FilesOptions & OverridesOptions) | (OverridesOptions & TailwindcssParserPerGlobOptions)): Promise<ConfigArray>;
600
617
 
601
618
  /**
602
619
  * Generates an ESLint configuration for TOML files.
@@ -619,7 +636,7 @@ declare function toml(options?: FilesOptions & OverridesOptions & StylisticOptio
619
636
  * @param options.overrides - Additional rule overrides.
620
637
  * @returns A ConfigArray containing the TypeScript ESLint configuration.
621
638
  */
622
- declare function typescript(options?: OverridesOptions & StylisticOptions & TypeScriptParserOptions): ConfigArray;
639
+ declare function typescript(options?: OverridesOptions & StylisticOptions & TypeScriptErasableSyntaxOnlyOptions & TypeScriptParserOptions): Promise<ConfigArray>;
623
640
 
624
641
  /**
625
642
  * Generates a configuration array for the Unicorn plugin with the specified options.
@@ -758,4 +775,4 @@ type ResolvedOptions<T> = T extends boolean ? never : NonNullable<T>;
758
775
  */
759
776
  declare function resolveSubOptions<K extends keyof CreateConfigOptions>(options: CreateConfigOptions, key: K): ResolvedOptions<CreateConfigOptions[K]>;
760
777
 
761
- 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 TestingOptions, 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 };
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
@@ -38,7 +38,7 @@ const GLOB_XML = "**/*.xml";
38
38
  const GLOB_SVG = "**/*.svg";
39
39
  const GLOB_GRAPHQL = "**/*.{g,graph}ql";
40
40
  const GLOB_HTML = "**/*.htm?(l)";
41
- const GLOB_TESTS = [`**/*.spec.${GLOB_SRC_EXT}`, `**/*.test.${GLOB_SRC_EXT}`, `**/test-setup.${GLOB_SRC_EXT}`];
41
+ const GLOB_TESTS = [`**/*.spec.?([cm])[jt]s`, `**/*.test.?([cm])[jt]s`, `**/test-setup.?([cm])[jt]s`];
42
42
  const GLOB_EXCLUDE = [
43
43
  "**/node_modules",
44
44
  "**/dist",
@@ -1190,9 +1190,12 @@ const STYLISTIC_CONFIG_DEFAULT = {
1190
1190
  quoteProps: "as-needed"
1191
1191
  };
1192
1192
  async function stylistic(options = {}) {
1193
- const stylisticOptions = { ...STYLISTIC_CONFIG_DEFAULT, ...options };
1193
+ const stylisticOptions = {
1194
+ ...STYLISTIC_CONFIG_DEFAULT,
1195
+ ...typeof options.stylistic === "boolean" ? {} : options.stylistic
1196
+ };
1194
1197
  const stylisticPlugin = await interopDefault(import('@stylistic/eslint-plugin'));
1195
- const config = stylisticPlugin.configs.customize({ ...stylisticOptions, flat: true });
1198
+ const config = stylisticPlugin.configs.customize(stylisticOptions);
1196
1199
  return tseslint.config({
1197
1200
  name: "fabdeh/stylistic/rules",
1198
1201
  files: [GLOB_SRC],
@@ -1208,22 +1211,45 @@ async function stylistic(options = {}) {
1208
1211
  });
1209
1212
  }
1210
1213
 
1214
+ function isTailwindcssParserPerGlobOptions(options) {
1215
+ return "parsers" in options && options.parsers !== void 0;
1216
+ }
1211
1217
  async function tailwindcss(options = {}) {
1218
+ await ensurePackages(["eslint-plugin-tailwindcss"]);
1212
1219
  const tailwindcssPlugin = await interopDefault(import('eslint-plugin-tailwindcss'));
1213
- const { overrides } = options;
1214
- return tseslint.config({
1215
- name: "fabdeh/tailwindcss/rules",
1216
- plugins: { tailwindcss: tailwindcssPlugin },
1217
- files: [GLOB_SRC, GLOB_HTML],
1218
- rules: {
1219
- "tailwindcss/classnames-order": "error",
1220
- "tailwindcss/enforces-negative-arbitrary-values": "error",
1221
- "tailwindcss/enforces-shorthand": "error",
1222
- "tailwindcss/no-contradicting-classname": "error",
1223
- "tailwindcss/no-unnecessary-arbitrary-value": "error",
1224
- ...overrides
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
+ }
1225
1251
  }
1226
- });
1252
+ );
1227
1253
  }
1228
1254
 
1229
1255
  async function toml(options = {}) {
@@ -1300,8 +1326,16 @@ const memberOrdering = {
1300
1326
  ]
1301
1327
  };
1302
1328
 
1303
- function typescript(options = {}) {
1304
- 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
+ }
1305
1339
  return tseslint.config(
1306
1340
  {
1307
1341
  name: "fabdeh/typescript/setup",
@@ -1326,7 +1360,8 @@ function typescript(options = {}) {
1326
1360
  ignores: [`${GLOB_MARKDOWN}/**`],
1327
1361
  plugins: {
1328
1362
  "@typescript-eslint": tseslint.plugin,
1329
- "unused-imports": unusedImports
1363
+ "unused-imports": unusedImports,
1364
+ ...erasableSyntaxOnlyPlugin ? { "erasable-syntax-only": erasableSyntaxOnlyPlugin } : {}
1330
1365
  },
1331
1366
  rules: {
1332
1367
  ...tseslint.configs.strictTypeChecked.find((c) => c.name === "typescript-eslint/eslint-recommended")?.rules,
@@ -1393,6 +1428,7 @@ function typescript(options = {}) {
1393
1428
  "@typescript-eslint/unbound-method": ["error", { ignoreStatic: true }],
1394
1429
  "@typescript-eslint/unified-signatures": "error",
1395
1430
  "@typescript-eslint/no-unused-vars": "off",
1431
+ ...erasableSyntaxOnlyRules,
1396
1432
  ...overrides
1397
1433
  }
1398
1434
  }
@@ -1632,7 +1668,7 @@ function mergePrettierOptions(options, overrides = {}) {
1632
1668
  /* eslint-enable @typescript-eslint/no-unsafe-assignment */
1633
1669
  };
1634
1670
  }
1635
- async function formatters(options = {}, stylistic = {}) {
1671
+ async function formatters(options = {}, stylistic = {}, hasAngularTemplateParser = false) {
1636
1672
  if (options === true) {
1637
1673
  const isPrettierPluginXmlInScope = isPackageInScope("@prettier/plugin-xml");
1638
1674
  options = {
@@ -1729,8 +1765,10 @@ async function formatters(options = {}, stylistic = {}) {
1729
1765
  if (options.html) {
1730
1766
  configs.push({
1731
1767
  name: "fabdeh/formatter/html",
1732
- languageOptions: {
1733
- parser: formatPlugin.parserPlain
1768
+ ...hasAngularTemplateParser ? {} : {
1769
+ languageOptions: {
1770
+ parser: formatPlugin.parserPlain
1771
+ }
1734
1772
  },
1735
1773
  files: [GLOB_HTML],
1736
1774
  rules: {
@@ -1851,7 +1889,7 @@ async function createConfig(options = {}, ...userConfigs) {
1851
1889
  gitignore: enableGitignore = true,
1852
1890
  ngrx: enableNgrx = NGRX_PACKAGES.some((p) => isPackageExists(p)),
1853
1891
  regexp: enableRegexp = true,
1854
- tailwindcss: enableTailwind = isPackageExists("tailwindcss"),
1892
+ tailwindcss: enableTailwind = false,
1855
1893
  typescript: enableTypescript = isPackageExists("typescript"),
1856
1894
  unicorn: enableUnicorn = true,
1857
1895
  vitest: enableVitest = isPackageExists("vitest")
@@ -1946,7 +1984,11 @@ async function createConfig(options = {}, ...userConfigs) {
1946
1984
  configs.push(markdown(markdownOptions));
1947
1985
  }
1948
1986
  if (options.formatters) {
1949
- configs.push(formatters(options.formatters, typeof stylisticOptions === "boolean" ? {} : stylisticOptions));
1987
+ configs.push(formatters(
1988
+ options.formatters,
1989
+ typeof stylisticOptions === "boolean" ? {} : stylisticOptions,
1990
+ Boolean(enableAngular)
1991
+ ));
1950
1992
  }
1951
1993
  if ("files" in options) {
1952
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.');
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@fabdeh/eslint-config",
3
3
  "type": "module",
4
- "version": "0.2.3",
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.20.0",
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": "^3.1.0",
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",
@@ -92,13 +100,12 @@
92
100
  "eslint-plugin-perfectionist": "^4.9.0",
93
101
  "eslint-plugin-prefer-arrow-functions": "^3.6.2",
94
102
  "eslint-plugin-regexp": "^2.7.0",
95
- "eslint-plugin-tailwindcss": "^3.18.0",
96
103
  "eslint-plugin-testing-library": "^7.1.1",
97
104
  "eslint-plugin-toml": "^0.12.0",
98
105
  "eslint-plugin-unicorn": "^57.0.0",
99
106
  "eslint-plugin-unused-imports": "^4.1.4",
100
107
  "eslint-plugin-yml": "^1.17.0",
101
- "globals": "^15.15.0",
108
+ "globals": "^16.0.0",
102
109
  "jsonc-eslint-parser": "^2.4.0",
103
110
  "local-pkg": "^1.0.0",
104
111
  "toml-eslint-parser": "^0.10.0",
@@ -119,12 +126,14 @@
119
126
  "@testing-library/angular": "^17.3.6",
120
127
  "@testing-library/jest-dom": "^6.6.3",
121
128
  "@types/fs-extra": "^11.0.4",
122
- "@types/node": "^22.13.4",
129
+ "@types/node": "^22.13.5",
123
130
  "bumpp": "^10.0.3",
124
131
  "changelogithub": "^13.12.1",
125
132
  "commitizen": "^4.3.1",
126
- "eslint": "^9.20.1",
133
+ "eslint": "^9.21.0",
134
+ "eslint-plugin-erasable-syntax-only": "^0.2.1",
127
135
  "eslint-plugin-format": "^1.0.1",
136
+ "eslint-plugin-tailwindcss": "^3.18.0",
128
137
  "execa": "^9.5.2",
129
138
  "fast-glob": "^3.3.3",
130
139
  "fs-extra": "^11.3.0",