@favorodera/eslint-config 0.0.10 → 0.0.12

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`)
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/markdown/setup' | 'favorodera/markdown/rules' | 'favorodera/markdown/code-in-md/disables' | 'favorodera/node/setup' | 'favorodera/node/rules' | '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 */
@@ -18196,7 +18196,80 @@ type NodeConfigOptions = SharedOptions;
18196
18196
  //#endregion
18197
18197
  //#region src/configs/perfectionist.d.ts
18198
18198
  /** Options for configuring Perfectionist linting rules. */
18199
- type PerfectionistConfigOptions = SharedOptions;
18199
+ type PerfectionistConfigOptions = SharedOptions & {
18200
+ /**
18201
+ * Global settings for the Perfectionist plugin, applied to all rules
18202
+ * unless overridden by rule-specific options.
18203
+ * @see https://perfectionist.dev/guide/getting-started#settings
18204
+ * @see https://perfectionist.dev/configs/recommended-custom
18205
+ */
18206
+ settings?: {
18207
+ /**
18208
+ * The type of sorting algorithm.
18209
+ * @default 'natural'
18210
+ */
18211
+ type?: 'alphabetical' | 'custom' | 'line-length' | 'natural';
18212
+ /**
18213
+ * The order of sorting.
18214
+ * @default 'asc'
18215
+ */
18216
+ order?: 'asc' | 'desc';
18217
+ /**
18218
+ * The fallback sorting type and order used when two elements are equal
18219
+ * under the primary comparison.
18220
+ */
18221
+ fallbackSort?: {
18222
+ order?: 'asc' | 'desc';
18223
+ type: 'alphabetical' | 'custom' | 'line-length' | 'natural';
18224
+ };
18225
+ /**
18226
+ * Custom alphabet string for the `'custom'` sort type.
18227
+ * Defines the exact character order to use.
18228
+ */
18229
+ alphabet?: string;
18230
+ /**
18231
+ * Ignore case when sorting.
18232
+ * @default true
18233
+ */
18234
+ ignoreCase?: boolean;
18235
+ /**
18236
+ * Control whether special characters should be kept, trimmed or removed
18237
+ * before sorting.
18238
+ * @default 'keep'
18239
+ */
18240
+ specialCharacters?: 'keep' | 'remove' | 'trim';
18241
+ /**
18242
+ * Locale(s) used for locale-aware string comparison.
18243
+ * A BCP 47 language tag or an array of such tags.
18244
+ * @default 'en-US'
18245
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare#locales
18246
+ */
18247
+ locales?: Array<string> | string;
18248
+ /**
18249
+ * Partition sorted elements by comments.
18250
+ * Can be `true`, `false`, a regexp pattern string, or an array of patterns.
18251
+ * @default true
18252
+ */
18253
+ partitionByComment?: Array<string> | boolean | string;
18254
+ /**
18255
+ * Partition sorted elements by newlines.
18256
+ * @default true
18257
+ */
18258
+ partitionByNewLine?: boolean;
18259
+ /**
18260
+ * Specifies how to handle newlines between groups.
18261
+ * `'ignore'` preserves existing newlines; a number enforces that many blank lines.
18262
+ * @default 'ignore'
18263
+ */
18264
+ newlinesBetween?: 'ignore' | number;
18265
+ /**
18266
+ * Specifies how to handle newlines between elements of each group.
18267
+ * `'ignore'` preserves existing newlines; a number enforces that many blank lines.
18268
+ * @default 'ignore'
18269
+ */
18270
+ newlinesInside?: 'ignore' | 'newlinesBetween' | number;
18271
+ };
18272
+ };
18200
18273
  //#endregion
18201
18274
  //#region src/configs/stylistic.d.ts
18202
18275
  /** Options for configuring Stylistic formatting rules. */
@@ -18210,6 +18283,7 @@ type TailwindConfigOptions = SharedOptions & {
18210
18283
  /**
18211
18284
  * Custom settings for the `eslint-plugin-better-tailwindcss` plugin.
18212
18285
  * Configure project paths, detection features, and rule specifics.
18286
+ * @see https://github.com/schoero/eslint-plugin-better-tailwindcss/blob/main/docs/settings/settings.md
18213
18287
  */
18214
18288
  settings?: {
18215
18289
  /**
@@ -18263,6 +18337,10 @@ type TypescriptConfigOptions = SharedOptions;
18263
18337
  /** Options for configuring Unicorn linting rules. */
18264
18338
  type UnicornConfigOptions = SharedOptions;
18265
18339
  //#endregion
18340
+ //#region src/configs/unused-imports.d.ts
18341
+ /** Options for configuring unused imports linting rules. */
18342
+ type UnusedImportsConfigOptions = SharedOptions;
18343
+ //#endregion
18266
18344
  //#region src/configs/vue.d.ts
18267
18345
  /** Options for configuring Vue single-file component linting rules. */
18268
18346
  type VueConfigOptions = SharedOptions & {
@@ -18290,7 +18368,7 @@ type YAMLConfigOptions = SharedOptions;
18290
18368
  interface ConfigOptions {
18291
18369
  /** Glob patterns to exclude from linting. */
18292
18370
  ignores?: IgnoresPatterns;
18293
- /** 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`). */
18294
18372
  imports?: boolean | ImportsConfigOptions;
18295
18373
  /** Core JavaScript language rules (via `@eslint/js`). */
18296
18374
  javascript?: boolean | JavascriptConfigOptions;
@@ -18316,6 +18394,8 @@ interface ConfigOptions {
18316
18394
  typescript?: boolean | TypescriptConfigOptions;
18317
18395
  /** Unicorn rules for various code quality improvements (via `eslint-plugin-unicorn`). */
18318
18396
  unicorn?: boolean | UnicornConfigOptions;
18397
+ /** Unused imports and variables detection and cleanup (via `eslint-plugin-unused-imports`). */
18398
+ unusedImports?: boolean | UnusedImportsConfigOptions;
18319
18399
  /** Vue single-file components linting (via `eslint-plugin-vue`). */
18320
18400
  vue?: boolean | VueConfigOptions;
18321
18401
  /** YAML files linting and sorting (via `eslint-plugin-yml`). */
@@ -18389,4 +18469,4 @@ declare function importModule<TModule>(module: Awaitable<TModule>): Promise<TMod
18389
18469
  default: infer TModuleDefault;
18390
18470
  } ? TModuleDefault : TModule>;
18391
18471
  //#endregion
18392
- 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
  }];
@@ -462,7 +357,9 @@ async function jsonc(options) {
462
357
  language: "jsonc/x",
463
358
  name: "favorodera/jsonc/rules",
464
359
  rules: {
360
+ "jsonc/array-bracket-newline": "error",
465
361
  "jsonc/array-bracket-spacing": ["error", "never"],
362
+ "jsonc/array-element-newline": "error",
466
363
  "jsonc/comma-dangle": ["error", "never"],
467
364
  "jsonc/comma-style": ["error", "last"],
468
365
  "jsonc/indent": ["error", 2],
@@ -478,6 +375,7 @@ async function jsonc(options) {
478
375
  "jsonc/no-floating-decimal": "error",
479
376
  "jsonc/no-hexadecimal-numeric-literals": "error",
480
377
  "jsonc/no-infinity": "error",
378
+ "jsonc/no-irregular-whitespace": "error",
481
379
  "jsonc/no-multi-str": "error",
482
380
  "jsonc/no-nan": "error",
483
381
  "jsonc/no-number-props": "error",
@@ -498,7 +396,7 @@ async function jsonc(options) {
498
396
  multiline: true
499
397
  }],
500
398
  "jsonc/object-curly-spacing": ["error", "always"],
501
- "jsonc/object-property-newline": ["error", { allowAllPropertiesOnSameLine: true }],
399
+ "jsonc/object-property-newline": ["error", { allowAllPropertiesOnSameLine: false }],
502
400
  "jsonc/quote-props": "error",
503
401
  "jsonc/quotes": "error",
504
402
  "jsonc/space-unary-ops": "error",
@@ -723,6 +621,12 @@ async function jsonc(options) {
723
621
  pathPattern: "^compilerOptions$"
724
622
  }
725
623
  ] }
624
+ },
625
+ {
626
+ files: resolved.files,
627
+ language: "jsonc/x",
628
+ name: "favorodera/jsonc/disables",
629
+ rules: { "no-irregular-whitespace": "off" }
726
630
  }
727
631
  ];
728
632
  }
@@ -809,36 +713,68 @@ const nodeDefaults = { files: [
809
713
  async function node(options) {
810
714
  const resolved = defu(options, nodeDefaults);
811
715
  const nodePlugin = await importModule(import("eslint-plugin-n"));
812
- const baseRules = nodePlugin.configs?.["flat/recommended"]?.rules || {};
813
- return [{
814
- name: "favorodera/node/setup",
815
- plugins: { node: nodePlugin }
816
- }, {
817
- files: resolved.files,
818
- name: "favorodera/node/rules",
819
- rules: {
820
- ...renamePluginsInRules(baseRules, { n: "node" }),
821
- "node/handle-callback-err": ["error", "^(err|error)$"],
822
- "node/no-deprecated-api": "error",
823
- "node/no-exports-assign": "error",
824
- "node/no-missing-import": "off",
825
- "node/no-new-require": "error",
826
- "node/no-path-concat": "error",
827
- "node/no-unpublished-import": "off",
828
- "node/prefer-global/buffer": ["error", "never"],
829
- "node/prefer-global/process": ["error", "never"],
830
- "node/process-exit-as-throw": "error",
831
- ...resolved.overrides
716
+ const baseRules = nodePlugin.configs?.["flat/recommended-module"]?.rules || {};
717
+ return [
718
+ {
719
+ name: "favorodera/node/setup",
720
+ plugins: { node: nodePlugin }
721
+ },
722
+ {
723
+ files: resolved.files,
724
+ name: "favorodera/node/rules",
725
+ rules: {
726
+ ...renamePluginsInRules(baseRules, { n: "node" }),
727
+ "node/callback-return": "error",
728
+ "node/handle-callback-err": ["error", "^(err|error)$"],
729
+ "node/no-callback-literal": "error",
730
+ "node/no-new-require": "error",
731
+ "node/no-path-concat": "error",
732
+ "node/no-unpublished-import": "error",
733
+ "node/prefer-global/buffer": "error",
734
+ "node/prefer-global/console": "error",
735
+ "node/prefer-global/crypto": "error",
736
+ "node/prefer-global/process": "error",
737
+ "node/prefer-global/text-decoder": "error",
738
+ "node/prefer-global/text-encoder": "error",
739
+ "node/prefer-global/timers": "error",
740
+ "node/prefer-global/url": "error",
741
+ "node/prefer-global/url-search-params": "error",
742
+ "node/prefer-node-protocol": "error",
743
+ "node/prefer-promises/dns": "error",
744
+ "node/prefer-promises/fs": "error",
745
+ ...resolved.overrides
746
+ }
747
+ },
748
+ {
749
+ files: [tsGlob, vueGlob],
750
+ name: "favorodera/node/disables",
751
+ rules: {
752
+ "node/no-missing-import": "off",
753
+ "node/no-missing-require": "off"
754
+ }
832
755
  }
833
- }];
756
+ ];
834
757
  }
835
758
  //#endregion
836
759
  //#region src/configs/perfectionist.ts
837
- const perfectionistDefaults = { files: [
838
- jsGlob,
839
- tsGlob,
840
- vueGlob
841
- ] };
760
+ const perfectionistDefaults = {
761
+ files: [
762
+ jsGlob,
763
+ tsGlob,
764
+ vueGlob
765
+ ],
766
+ settings: {
767
+ ignoreCase: true,
768
+ locales: "en-US",
769
+ newlinesBetween: "ignore",
770
+ newlinesInside: "ignore",
771
+ order: "asc",
772
+ partitionByComment: true,
773
+ partitionByNewLine: true,
774
+ specialCharacters: "keep",
775
+ type: "natural"
776
+ }
777
+ };
842
778
  /**
843
779
  * Constructs the flat config items for Perfectionist linting, providing rules
844
780
  * to naturally sort objects, imports, classes, and other elements in your code.
@@ -848,53 +784,17 @@ const perfectionistDefaults = { files: [
848
784
  async function perfectionist(options) {
849
785
  const resolved = defu(options, perfectionistDefaults);
850
786
  const perfectionistPlugin = await importModule(import("eslint-plugin-perfectionist"));
851
- const baseRules = perfectionistPlugin.configs["recommended-natural"]?.rules || {};
787
+ const safeType = resolved.settings?.type ?? "natural";
788
+ const baseRules = perfectionistPlugin.configs[`recommended-${safeType}`]?.rules || {};
852
789
  return [{
853
790
  name: "favorodera/perfectionist/setup",
854
- plugins: { perfectionist: perfectionistPlugin }
791
+ plugins: { perfectionist: perfectionistPlugin },
792
+ settings: { perfectionist: resolved.settings }
855
793
  }, {
856
794
  files: resolved.files,
857
795
  name: "favorodera/perfectionist/rules",
858
796
  rules: {
859
797
  ...baseRules,
860
- "perfectionist/sort-exports": ["error", {
861
- order: "asc",
862
- type: "natural"
863
- }],
864
- "perfectionist/sort-imports": ["error", {
865
- groups: [
866
- "type-import",
867
- [
868
- "type-parent",
869
- "type-sibling",
870
- "type-index",
871
- "type-internal"
872
- ],
873
- "value-builtin",
874
- "value-external",
875
- "value-internal",
876
- [
877
- "value-parent",
878
- "value-sibling",
879
- "value-index"
880
- ],
881
- "side-effect",
882
- "ts-equals-import",
883
- "unknown"
884
- ],
885
- newlinesBetween: "ignore",
886
- newlinesInside: "ignore",
887
- order: "asc",
888
- type: "natural"
889
- }],
890
- "perfectionist/sort-named-exports": ["error", {
891
- order: "asc",
892
- type: "natural"
893
- }],
894
- "perfectionist/sort-named-imports": ["error", {
895
- order: "asc",
896
- type: "natural"
897
- }],
898
798
  ...resolved.overrides
899
799
  }
900
800
  }];
@@ -919,6 +819,12 @@ async function pnpm() {
919
819
  rules: {
920
820
  "pnpm/json-enforce-catalog": ["error", {
921
821
  autofix: true,
822
+ fields: [
823
+ "dependencies",
824
+ "devDependencies",
825
+ "optionalDependencies",
826
+ "peerDependencies"
827
+ ],
922
828
  ignores: ["@types/vscode"]
923
829
  }],
924
830
  "pnpm/json-prefer-workspace-settings": ["error", { autofix: true }],
@@ -935,7 +841,8 @@ async function pnpm() {
935
841
  trustPolicy: "no-downgrade"
936
842
  } }],
937
843
  "pnpm/yaml-no-duplicate-catalog-item": ["error", { checkDuplicates: "exact-version" }],
938
- "pnpm/yaml-no-unused-catalog-item": "error"
844
+ "pnpm/yaml-no-unused-catalog-item": "error",
845
+ "pnpm/yaml-valid-packages": "error"
939
846
  }
940
847
  }
941
848
  ];
@@ -987,7 +894,7 @@ async function stylistic(options) {
987
894
  "style/implicit-arrow-linebreak": "error",
988
895
  "style/line-comment-position": "error",
989
896
  "style/linebreak-style": "error",
990
- "style/multiline-comment-style": "error",
897
+ "style/multiline-comment-style": ["error", "separate-lines"],
991
898
  "style/newline-per-chained-call": "error",
992
899
  "style/no-confusing-arrow": "error",
993
900
  "style/no-extra-semi": "error",
@@ -1039,11 +946,11 @@ async function tailwind(options) {
1039
946
  unknownClassOrder: "asc",
1040
947
  unknownClassPosition: "start"
1041
948
  }],
1042
- "tailwind/enforce-consistent-important-position": "off",
1043
949
  "tailwind/enforce-consistent-line-wrapping": ["error", { group: "emptyLine" }],
1044
- "tailwind/enforce-consistent-variable-syntax": "off",
1045
950
  "tailwind/enforce-consistent-variant-order": "error",
1046
951
  "tailwind/enforce-logical-properties": "error",
952
+ "tailwind/enforce-consistent-important-position": "off",
953
+ "tailwind/enforce-consistent-variable-syntax": "off",
1047
954
  "tailwind/enforce-shorthand-classes": "off",
1048
955
  ...resolved.overrides
1049
956
  }
@@ -1131,10 +1038,7 @@ async function test(options) {
1131
1038
  {
1132
1039
  files: resolved.files,
1133
1040
  name: "favorodera/test/disables",
1134
- rules: {
1135
- "no-unused-expressions": "off",
1136
- "node/prefer-global/process": "off"
1137
- }
1041
+ rules: { "no-unused-expressions": "off" }
1138
1042
  }
1139
1043
  ];
1140
1044
  }
@@ -1209,6 +1113,51 @@ async function unicorn(options) {
1209
1113
  }];
1210
1114
  }
1211
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
1212
1161
  //#region src/configs/vue.ts
1213
1162
  const sfcBlocksDefaults = { blocks: {
1214
1163
  customBlocks: true,
@@ -1475,6 +1424,7 @@ function factory(options = {}) {
1475
1424
  test,
1476
1425
  typescript,
1477
1426
  unicorn,
1427
+ unusedImports,
1478
1428
  vue,
1479
1429
  yaml
1480
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.10",
4
+ "version": "0.0.12",
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>",