@favorodera/eslint-config 0.0.11 → 0.0.13

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
@@ -33,7 +33,8 @@ The following configurations are bundled and enabled by default (they can be ind
33
33
  - **Stylistic** — Formatting rules (`@stylistic/eslint-plugin`)
34
34
  - **Tailwind CSS** — Utility class linting and sorting (`eslint-plugin-better-tailwindcss`)
35
35
  - **Test** — Test and Vitest specific linting (`@vitest/eslint-plugin`)
36
- - **Imports** — Auto-sorting and unused imports removal (`eslint-plugin-import-lite`, `eslint-plugin-unused-imports`)
36
+ - **Imports** — Auto-sorting and import quality rules (`eslint-plugin-import-lite`)
37
+ - **Unused Imports** — Unused imports and variables detection and cleanup (`eslint-plugin-unused-imports`)
37
38
  - **Markdown** — Linting for markdown files and embedded code blocks (`@eslint/markdown`)
38
39
  - **JSON/JSONC/JSON5** — Formatting and sorting for JSON files like `package.json` (`eslint-plugin-jsonc`)
39
40
  - **JSDoc** — Standardized comment formatting (`eslint-plugin-jsdoc`)
@@ -80,7 +81,9 @@ bun add -D eslint @favorodera/eslint-config
80
81
 
81
82
  ### Configure
82
83
 
83
- Create an `eslint.config.ts` file in the root of your project. Since all configurations are enabled by default, you only need to pass options if you want to disable or customize something:
84
+ Create an `eslint.config.ts` file in the root of your project. Since all configurations are enabled by default, you only need to pass options if you want to disable or customize something.
85
+
86
+ The `factory()` function returns a `FlatConfigComposer` instance (powered by [`eslint-flat-config-utils`](https://github.com/antfu/eslint-flat-config-utils)), which acts as a powerful composer. This makes it incredibly easy to append your own configurations, override existing rules, or insert plugins seamlessly.
84
87
 
85
88
  ```ts
86
89
  import { factory } from '@favorodera/eslint-config'
@@ -99,6 +102,19 @@ export default factory({
99
102
  // Example: Disable tailwind if you aren't using it
100
103
  tailwind: false,
101
104
  })
105
+ // You can seamlessly chain methods to compose your config
106
+ .append({
107
+ // Add your own custom ESLint configs
108
+ ignores: ['src/types/rules.d.ts'],
109
+ })
110
+ .overrides({
111
+ // Easily override predefined rules by their name
112
+ 'favorodera/typescript/rules': {
113
+ rules: {
114
+ 'ts/no-explicit-any': 'off',
115
+ },
116
+ },
117
+ })
102
118
  ```
103
119
 
104
120
  ## Development
package/dist/index.d.mts CHANGED
@@ -18125,7 +18125,7 @@ type Yoda = [] | [("always" | "never")] | [("always" | "never"), {
18125
18125
  exceptRange?: boolean;
18126
18126
  onlyEquality?: boolean;
18127
18127
  }]; // Names of all the configs
18128
- type ConfigNames = 'favorodera/ignores' | 'favorodera/imports/setup' | 'favorodera/imports/rules' | 'favorodera/javascript/setup' | 'favorodera/javascript/rules' | 'favorodera/jsdoc/setup' | 'favorodera/jsdoc/rules' | 'favorodera/jsonc/setup' | 'favorodera/jsonc/rules' | 'favorodera/jsonc/sort/package-json' | 'favorodera/jsonc/sort/tsconfig-json' | 'favorodera/jsonc/disables' | 'favorodera/markdown/setup' | 'favorodera/markdown/rules' | 'favorodera/markdown/code-in-md/disables' | 'favorodera/node/setup' | 'favorodera/node/rules' | 'favorodera/node/disables' | 'favorodera/perfectionist/setup' | 'favorodera/perfectionist/rules' | 'favorodera/pnpm/setup' | 'favorodera/pnpm/package-json' | 'favorodera/pnpm/pnpm-workspace-yaml' | 'favorodera/stylistic/setup' | 'favorodera/stylistic/rules' | 'favorodera/tailwind/setup' | 'favorodera/tailwind/rules' | 'favorodera/test/setup' | 'favorodera/test/rules' | 'favorodera/test/disables' | 'favorodera/typescript/setup' | 'favorodera/typescript/rules' | 'favorodera/unicorn/setup' | 'favorodera/unicorn/rules' | 'favorodera/vue/setup' | 'favorodera/vue/rules' | 'favorodera/yaml/setup' | 'favorodera/yaml/rules' | 'favorodera/yaml/sort/pnpm-workspace-yaml';
18128
+ type ConfigNames = 'favorodera/ignores' | 'favorodera/imports/setup' | 'favorodera/imports/rules' | 'favorodera/javascript/setup' | 'favorodera/javascript/rules' | 'favorodera/jsdoc/setup' | 'favorodera/jsdoc/rules' | 'favorodera/jsonc/setup' | 'favorodera/jsonc/rules' | 'favorodera/jsonc/sort/package-json' | 'favorodera/jsonc/sort/tsconfig-json' | 'favorodera/jsonc/disables' | 'favorodera/markdown/setup' | 'favorodera/markdown/rules' | 'favorodera/markdown/code-in-md/disables' | 'favorodera/node/setup' | 'favorodera/node/rules' | 'favorodera/node/disables' | 'favorodera/perfectionist/setup' | 'favorodera/perfectionist/rules' | 'favorodera/pnpm/setup' | 'favorodera/pnpm/package-json' | 'favorodera/pnpm/pnpm-workspace-yaml' | 'favorodera/stylistic/setup' | 'favorodera/stylistic/rules' | 'favorodera/tailwind/setup' | 'favorodera/tailwind/rules' | 'favorodera/test/setup' | 'favorodera/test/rules' | 'favorodera/test/disables' | 'favorodera/typescript/setup' | 'favorodera/typescript/rules' | 'favorodera/unicorn/setup' | 'favorodera/unicorn/rules' | 'favorodera/unused-imports/setup' | 'favorodera/unused-imports/rules' | 'favorodera/unused-imports/disables' | 'favorodera/vue/setup' | 'favorodera/vue/rules' | 'favorodera/yaml/setup' | 'favorodera/yaml/rules' | 'favorodera/yaml/sort/pnpm-workspace-yaml';
18129
18129
  //#endregion
18130
18130
  //#region src/types/utils.d.ts
18131
18131
  /** ESLint rules configuration with type-safe autocompletion */
@@ -18241,8 +18241,8 @@ type PerfectionistConfigOptions = SharedOptions & {
18241
18241
  /**
18242
18242
  * Locale(s) used for locale-aware string comparison.
18243
18243
  * A BCP 47 language tag or an array of such tags.
18244
- * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare#locales
18245
18244
  * @default 'en-US'
18245
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare#locales
18246
18246
  */
18247
18247
  locales?: Array<string> | string;
18248
18248
  /**
@@ -18337,6 +18337,10 @@ type TypescriptConfigOptions = SharedOptions;
18337
18337
  /** Options for configuring Unicorn linting rules. */
18338
18338
  type UnicornConfigOptions = SharedOptions;
18339
18339
  //#endregion
18340
+ //#region src/configs/unused-imports.d.ts
18341
+ /** Options for configuring unused imports linting rules. */
18342
+ type UnusedImportsConfigOptions = SharedOptions;
18343
+ //#endregion
18340
18344
  //#region src/configs/vue.d.ts
18341
18345
  /** Options for configuring Vue single-file component linting rules. */
18342
18346
  type VueConfigOptions = SharedOptions & {
@@ -18364,7 +18368,7 @@ type YAMLConfigOptions = SharedOptions;
18364
18368
  interface ConfigOptions {
18365
18369
  /** Glob patterns to exclude from linting. */
18366
18370
  ignores?: IgnoresPatterns;
18367
- /** Imports sorting and unused imports cleanup (via `eslint-plugin-import-lite` and `eslint-plugin-unused-imports`). */
18371
+ /** Imports sorting and quality rules (via `eslint-plugin-import-lite`). */
18368
18372
  imports?: boolean | ImportsConfigOptions;
18369
18373
  /** Core JavaScript language rules (via `@eslint/js`). */
18370
18374
  javascript?: boolean | JavascriptConfigOptions;
@@ -18390,6 +18394,8 @@ interface ConfigOptions {
18390
18394
  typescript?: boolean | TypescriptConfigOptions;
18391
18395
  /** Unicorn rules for various code quality improvements (via `eslint-plugin-unicorn`). */
18392
18396
  unicorn?: boolean | UnicornConfigOptions;
18397
+ /** Unused imports and variables detection and cleanup (via `eslint-plugin-unused-imports`). */
18398
+ unusedImports?: boolean | UnusedImportsConfigOptions;
18393
18399
  /** Vue single-file components linting (via `eslint-plugin-vue`). */
18394
18400
  vue?: boolean | VueConfigOptions;
18395
18401
  /** YAML files linting and sorting (via `eslint-plugin-yml`). */
@@ -18463,4 +18469,4 @@ declare function importModule<TModule>(module: Awaitable<TModule>): Promise<TMod
18463
18469
  default: infer TModuleDefault;
18464
18470
  } ? TModuleDefault : TModule>;
18465
18471
  //#endregion
18466
- export { type ConfigNames, type ConfigOptions, type RuleOptions, type Rules, type SharedOptions, type TypedFlatConfigItem, codeInMdGlob, extractRules, factory, ignoresGlob, importModule, jsGlob, json5Glob, jsonGlob, jsoncGlob, mdGlob, mdInMdGlob, packageJsonGlob, pnpmWorkspaceGlob, scriptsGlob, testGlob, tsConfigGlob, tsGlob, vueGlob, yamlGlob };
18472
+ export { type ConfigNames, type ConfigOptions, type TypedFlatConfigItem, codeInMdGlob, extractRules, factory, ignoresGlob, importModule, jsGlob, json5Glob, jsonGlob, jsoncGlob, mdGlob, mdInMdGlob, packageJsonGlob, pnpmWorkspaceGlob, scriptsGlob, testGlob, tsConfigGlob, tsGlob, vueGlob, yamlGlob };
package/dist/index.mjs CHANGED
@@ -135,20 +135,17 @@ const importsDefaults = { files: [
135
135
  ] };
136
136
  /**
137
137
  * Constructs the flat config items for imports linting, providing plugin setup and
138
- * specific rules to enforce consistent import ordering and unused variable checks.
138
+ * specific rules to enforce consistent import ordering and quality.
139
139
  * @param options Configuration options for imports linting.
140
140
  * @returns Promise resolving to imports ESLint config items.
141
141
  */
142
142
  async function imports(options) {
143
143
  const resolved = defu(options, importsDefaults);
144
- const [importPlugin, unusedImportsPlugin] = await Promise.all([importModule(import("eslint-plugin-import-lite")), importModule(import("eslint-plugin-unused-imports"))]);
144
+ const importPlugin = await importModule(import("eslint-plugin-import-lite"));
145
145
  const baseRules = importPlugin.configs.recommended?.rules || {};
146
146
  return [{
147
147
  name: "favorodera/imports/setup",
148
- plugins: {
149
- "import": importPlugin,
150
- "unused-imports": unusedImportsPlugin
151
- }
148
+ plugins: { import: importPlugin }
152
149
  }, {
153
150
  files: resolved.files,
154
151
  name: "favorodera/imports/rules",
@@ -157,17 +154,9 @@ async function imports(options) {
157
154
  "import/consistent-type-specifier-style": ["error", "prefer-top-level"],
158
155
  "import/first": "error",
159
156
  "import/newline-after-import": ["error", { count: 1 }],
160
- "import/no-duplicates": "error",
157
+ "import/no-duplicates": ["error", { "prefer-inline": true }],
161
158
  "import/no-mutable-exports": "error",
162
159
  "import/no-named-default": "error",
163
- "unused-imports/no-unused-imports": "error",
164
- "unused-imports/no-unused-vars": ["error", {
165
- args: "after-used",
166
- argsIgnorePattern: "^_",
167
- ignoreRestSiblings: true,
168
- vars: "all",
169
- varsIgnorePattern: "^_"
170
- }],
171
160
  ...resolved.overrides
172
161
  }
173
162
  }];
@@ -210,148 +199,68 @@ async function javascript(options) {
210
199
  ...baseRules,
211
200
  "array-callback-return": "error",
212
201
  "block-scoped-var": "error",
213
- "constructor-super": "error",
214
202
  "default-case-last": "error",
215
- "dot-notation": ["error", { allowKeywords: true }],
216
- "eqeqeq": ["error", "smart"],
217
- "new-cap": ["error", {
218
- capIsNew: false,
219
- newIsCap: true,
220
- properties: true
221
- }],
203
+ "dot-notation": "error",
204
+ "eqeqeq": "error",
205
+ "new-cap": "error",
222
206
  "no-alert": "error",
223
207
  "no-array-constructor": "error",
224
- "no-async-promise-executor": "error",
225
208
  "no-caller": "error",
226
- "no-case-declarations": "error",
227
- "no-class-assign": "error",
228
- "no-compare-neg-zero": "error",
229
- "no-cond-assign": ["error", "always"],
230
209
  "no-console": ["error", { allow: ["warn", "error"] }],
231
- "no-const-assign": "error",
232
- "no-control-regex": "error",
233
- "no-debugger": "error",
234
- "no-delete-var": "error",
235
- "no-dupe-args": "error",
236
- "no-dupe-class-members": "error",
237
- "no-dupe-keys": "error",
238
- "no-duplicate-case": "error",
239
210
  "no-empty": ["error", { allowEmptyCatch: true }],
240
- "no-empty-character-class": "error",
241
- "no-empty-pattern": "error",
242
211
  "no-eval": "error",
243
- "no-ex-assign": "error",
244
212
  "no-extend-native": "error",
245
213
  "no-extra-bind": "error",
246
- "no-extra-boolean-cast": "error",
247
- "no-fallthrough": "error",
248
- "no-func-assign": "error",
249
- "no-global-assign": "error",
250
214
  "no-implied-eval": "error",
251
- "no-import-assign": "error",
252
- "no-invalid-regexp": "error",
253
- "no-irregular-whitespace": "error",
254
215
  "no-iterator": "error",
255
216
  "no-labels": ["error", {
256
217
  allowLoop: false,
257
218
  allowSwitch: false
258
219
  }],
220
+ "no-await-in-loop": "error",
221
+ "no-constructor-return": "error",
222
+ "no-continue": "error",
223
+ "no-duplicate-imports": ["error", { includeExports: true }],
224
+ "no-else-return": "error",
225
+ "no-eq-null": "error",
259
226
  "no-lone-blocks": "error",
260
- "no-loss-of-precision": "error",
261
- "no-misleading-character-class": "error",
227
+ "no-loop-func": "error",
262
228
  "no-multi-str": "error",
229
+ "no-negated-condition": "error",
230
+ "no-nested-ternary": "error",
263
231
  "no-new": "error",
264
232
  "no-new-func": "error",
265
- "no-new-native-nonconstructor": "error",
266
233
  "no-new-wrappers": "error",
267
- "no-obj-calls": "error",
268
- "no-octal": "error",
234
+ "no-object-constructor": "error",
269
235
  "no-octal-escape": "error",
236
+ "no-param-reassign": "error",
237
+ "no-promise-executor-return": "error",
270
238
  "no-proto": "error",
271
- "no-prototype-builtins": "error",
272
- "no-redeclare": ["error", { builtinGlobals: false }],
273
- "no-regex-spaces": "error",
274
- "no-restricted-globals": [
275
- "error",
276
- {
277
- message: "Use `globalThis` instead.",
278
- name: "global"
279
- },
280
- {
281
- message: "Use `globalThis` instead.",
282
- name: "self"
283
- }
284
- ],
285
- "no-restricted-properties": [
286
- "error",
287
- {
288
- message: "Use `Object.getPrototypeOf` or `Object.setPrototypeOf` instead.",
289
- property: "__proto__"
290
- },
291
- {
292
- message: "Use `Object.defineProperty` instead.",
293
- property: "__defineGetter__"
294
- },
295
- {
296
- message: "Use `Object.defineProperty` instead.",
297
- property: "__defineSetter__"
298
- },
299
- {
300
- message: "Use `Object.getOwnPropertyDescriptor` instead.",
301
- property: "__lookupGetter__"
302
- },
303
- {
304
- message: "Use `Object.getOwnPropertyDescriptor` instead.",
305
- property: "__lookupSetter__"
306
- }
307
- ],
308
- "no-restricted-syntax": [
309
- "error",
310
- "TSEnumDeclaration[const=true]",
311
- "TSExportAssignment"
312
- ],
313
- "no-self-assign": ["error", { props: true }],
239
+ "no-return-assign": "error",
240
+ "no-script-url": "error",
314
241
  "no-self-compare": "error",
315
242
  "no-sequences": "error",
316
- "no-shadow-restricted-names": "error",
317
- "no-sparse-arrays": "error",
318
243
  "no-template-curly-in-string": "error",
319
- "no-this-before-super": "error",
320
244
  "no-throw-literal": "error",
321
- "no-undef": "error",
322
245
  "no-undef-init": "error",
323
- "no-unexpected-multiline": "error",
324
246
  "no-unmodified-loop-condition": "error",
325
247
  "no-unneeded-ternary": ["error", { defaultAssignment: false }],
326
- "no-unreachable": "error",
327
248
  "no-unreachable-loop": "error",
328
- "no-unsafe-finally": "error",
329
- "no-unsafe-negation": "error",
330
249
  "no-unused-expressions": ["error", {
331
250
  allowShortCircuit: true,
332
251
  allowTaggedTemplates: true,
333
252
  allowTernary: true
334
253
  }],
335
- "no-unused-vars": ["error", {
336
- args: "none",
337
- caughtErrors: "none",
338
- ignoreRestSiblings: true,
339
- vars: "all"
340
- }],
341
254
  "no-use-before-define": ["error", {
342
255
  classes: false,
343
- functions: false,
344
- variables: true
256
+ functions: false
345
257
  }],
346
- "no-useless-backreference": "error",
347
258
  "no-useless-call": "error",
348
- "no-useless-catch": "error",
349
259
  "no-useless-computed-key": "error",
260
+ "no-useless-concat": "error",
350
261
  "no-useless-constructor": "error",
351
262
  "no-useless-rename": "error",
352
263
  "no-useless-return": "error",
353
- "no-var": "error",
354
- "no-with": "error",
355
264
  "object-shorthand": [
356
265
  "error",
357
266
  "always",
@@ -372,18 +281,12 @@ async function javascript(options) {
372
281
  "prefer-exponentiation-operator": "error",
373
282
  "prefer-promise-reject-errors": "error",
374
283
  "prefer-regex-literals": ["error", { disallowRedundantWrapping: true }],
375
- "prefer-rest-params": "error",
376
- "prefer-spread": "error",
377
284
  "prefer-template": "error",
378
285
  "symbol-description": "error",
379
- "unicode-bom": ["error", "never"],
380
- "use-isnan": ["error", {
381
- enforceForIndexOf: true,
382
- enforceForSwitchCase: true
383
- }],
286
+ "unicode-bom": "error",
384
287
  "valid-typeof": ["error", { requireStringLiterals: true }],
385
288
  "vars-on-top": "error",
386
- "yoda": ["error", "never"],
289
+ "yoda": "error",
387
290
  ...resolved.overrides
388
291
  }
389
292
  }];
@@ -416,23 +319,15 @@ async function jsdoc(options) {
416
319
  name: "favorodera/jsdoc/rules",
417
320
  rules: {
418
321
  ...baseRules,
419
- "jsdoc/check-access": "warn",
420
- "jsdoc/check-alignment": "warn",
421
- "jsdoc/check-param-names": "warn",
422
- "jsdoc/check-property-names": "warn",
423
- "jsdoc/check-types": "warn",
424
- "jsdoc/empty-tags": "warn",
425
- "jsdoc/implements-on-classes": "warn",
426
- "jsdoc/multiline-blocks": "warn",
427
- "jsdoc/no-defaults": "warn",
428
- "jsdoc/no-multi-asterisks": "warn",
429
- "jsdoc/require-param-name": "warn",
430
- "jsdoc/require-property": "warn",
431
- "jsdoc/require-property-description": "warn",
432
- "jsdoc/require-property-name": "warn",
433
- "jsdoc/require-returns-check": "warn",
434
- "jsdoc/require-returns-description": "warn",
435
- "jsdoc/require-yields-check": "warn",
322
+ "jsdoc/check-indentation": "error",
323
+ "jsdoc/check-template-names": "error",
324
+ "jsdoc/imports-as-dependencies": "error",
325
+ "jsdoc/multiline-blocks": "error",
326
+ "jsdoc/no-bad-blocks": "error",
327
+ "jsdoc/no-blank-block-descriptions": "error",
328
+ "jsdoc/no-blank-blocks": "error",
329
+ "jsdoc/require-throws-type": "off",
330
+ "jsdoc/sort-tags": "error",
436
331
  ...resolved.overrides
437
332
  }
438
333
  }];
@@ -1218,6 +1113,51 @@ async function unicorn(options) {
1218
1113
  }];
1219
1114
  }
1220
1115
  //#endregion
1116
+ //#region src/configs/unused-imports.ts
1117
+ const unusedImportsDefaults = { files: [
1118
+ jsGlob,
1119
+ tsGlob,
1120
+ vueGlob
1121
+ ] };
1122
+ /**
1123
+ * Constructs the flat config items for unused imports linting, providing plugin setup and
1124
+ * specific rules to detect and remove unused imports and variables.
1125
+ * @param options Configuration options for unused imports linting.
1126
+ * @returns Promise resolving to unused imports ESLint config items.
1127
+ */
1128
+ async function unusedImports(options) {
1129
+ const resolved = defu(options, unusedImportsDefaults);
1130
+ return [
1131
+ {
1132
+ name: "favorodera/unused-imports/setup",
1133
+ plugins: { "unused-imports": await importModule(import("eslint-plugin-unused-imports")) }
1134
+ },
1135
+ {
1136
+ files: resolved.files,
1137
+ name: "favorodera/unused-imports/rules",
1138
+ rules: {
1139
+ "unused-imports/no-unused-imports": "error",
1140
+ "unused-imports/no-unused-vars": ["error", {
1141
+ args: "after-used",
1142
+ argsIgnorePattern: "^_",
1143
+ ignoreRestSiblings: true,
1144
+ vars: "all",
1145
+ varsIgnorePattern: "^_"
1146
+ }],
1147
+ ...resolved.overrides
1148
+ }
1149
+ },
1150
+ {
1151
+ files: resolved.files,
1152
+ name: "favorodera/unused-imports/disables",
1153
+ rules: {
1154
+ "no-unused-vars": "off",
1155
+ "ts/no-unused-vars": "off"
1156
+ }
1157
+ }
1158
+ ];
1159
+ }
1160
+ //#endregion
1221
1161
  //#region src/configs/vue.ts
1222
1162
  const sfcBlocksDefaults = { blocks: {
1223
1163
  customBlocks: true,
@@ -1484,6 +1424,7 @@ function factory(options = {}) {
1484
1424
  test,
1485
1425
  typescript,
1486
1426
  unicorn,
1427
+ unusedImports,
1487
1428
  vue,
1488
1429
  yaml
1489
1430
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@favorodera/eslint-config",
3
3
  "type": "module",
4
- "version": "0.0.11",
4
+ "version": "0.0.13",
5
5
  "private": false,
6
6
  "description": "Opinionated, type-safe flat ESLint configuration factory for Vue, TypeScript, Tailwind, and more.",
7
7
  "author": "Favour Emeka <favorodera@gmail.com>",