@favorodera/eslint-config 0.0.5 → 0.0.7

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/dist/index.mjs CHANGED
@@ -16,6 +16,10 @@ const mdGlob = "**/*.md";
16
16
  const mdInMdGlob = "**/*.md/*.md";
17
17
  /** Glob pattern for matching code blocks embedded in Markdown files */
18
18
  const codeInMdGlob = "**/*.md/**/*.{js,cjs,mjs,ts,cts,mts,vue}";
19
+ /** Glob pattern for matching scripts files */
20
+ const scriptsGlob = "**/*.{js,cjs,mjs,ts,cts,mts}";
21
+ /** Glob pattern for matching test files */
22
+ const testsGlob = ["**/*.{tests,specs,benchmark,bench}.{js,cjs,mjs,ts,cts,mts}", "**/__tests__/**/*.{js,cjs,mjs,ts,cts,mts}"];
19
23
  /** Glob pattern for matching JSON files */
20
24
  const jsonGlob = "**/*.json";
21
25
  /** Glob pattern for matching JSON5 files */
@@ -24,11 +28,17 @@ const json5Glob = "**/*.json5";
24
28
  const jsoncGlob = "**/*.jsonc";
25
29
  /** Glob patterns for matching TypeScript configuration files */
26
30
  const tsConfigGlob = ["**/tsconfig.json", "**/tsconfig.*.json"];
31
+ /** Glob pattern for matching YAML files */
32
+ const yamlGlob = "**/*.{yml,yaml}";
33
+ /** Glob pattern for matching pnpm-workspace.yaml file */
34
+ const pnpmWorkspaceGlob = "pnpm-workspace.yaml";
27
35
  /** Glob pattern for matching package.json files */
28
36
  const packageJsonGlob = "**/package.json";
29
- //#endregion
30
- //#region src/configs/ignores.ts
31
- const defaultPatterns = [
37
+ /**
38
+ * Common glob patterns for files and directories that should be ignored by ESLint.
39
+ * Includes node_modules, build outputs, lock files, temporary files, and tool-specific caches.
40
+ */
41
+ const ignoresGlob = [
32
42
  "**/node_modules/**",
33
43
  "**/dist/**",
34
44
  "**/package-lock.json",
@@ -65,6 +75,9 @@ const defaultPatterns = [
65
75
  "**/.agents",
66
76
  "**/.*/skills"
67
77
  ];
78
+ //#endregion
79
+ //#region src/configs/ignores.ts
80
+ const defaultPatterns = ignoresGlob;
68
81
  /**
69
82
  * Globs for ignoring files and directories from ESLint scanning.
70
83
  * @param patterns Additional ignore patterns or a function to modify the defaults.
@@ -195,12 +208,182 @@ async function javascript(options) {
195
208
  name: "favorodera/javascript/rules",
196
209
  rules: {
197
210
  ...baseRules,
198
- "accessor-pairs": ["error", {
199
- enforceForClassMembers: true,
200
- setWithoutGet: true
201
- }],
202
211
  "array-callback-return": "error",
203
212
  "block-scoped-var": "error",
213
+ "constructor-super": "error",
214
+ "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
+ }],
222
+ "no-alert": "error",
223
+ "no-array-constructor": "error",
224
+ "no-async-promise-executor": "error",
225
+ "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
+ "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
+ "no-empty": ["error", { allowEmptyCatch: true }],
240
+ "no-empty-character-class": "error",
241
+ "no-empty-pattern": "error",
242
+ "no-eval": "error",
243
+ "no-ex-assign": "error",
244
+ "no-extend-native": "error",
245
+ "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
+ "no-implied-eval": "error",
251
+ "no-import-assign": "error",
252
+ "no-invalid-regexp": "error",
253
+ "no-irregular-whitespace": "error",
254
+ "no-iterator": "error",
255
+ "no-labels": ["error", {
256
+ allowLoop: false,
257
+ allowSwitch: false
258
+ }],
259
+ "no-lone-blocks": "error",
260
+ "no-loss-of-precision": "error",
261
+ "no-misleading-character-class": "error",
262
+ "no-multi-str": "error",
263
+ "no-new": "error",
264
+ "no-new-func": "error",
265
+ "no-new-native-nonconstructor": "error",
266
+ "no-new-wrappers": "error",
267
+ "no-obj-calls": "error",
268
+ "no-octal": "error",
269
+ "no-octal-escape": "error",
270
+ "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 }],
314
+ "no-self-compare": "error",
315
+ "no-sequences": "error",
316
+ "no-shadow-restricted-names": "error",
317
+ "no-sparse-arrays": "error",
318
+ "no-template-curly-in-string": "error",
319
+ "no-this-before-super": "error",
320
+ "no-throw-literal": "error",
321
+ "no-undef": "error",
322
+ "no-undef-init": "error",
323
+ "no-unexpected-multiline": "error",
324
+ "no-unmodified-loop-condition": "error",
325
+ "no-unneeded-ternary": ["error", { defaultAssignment: false }],
326
+ "no-unreachable": "error",
327
+ "no-unreachable-loop": "error",
328
+ "no-unsafe-finally": "error",
329
+ "no-unsafe-negation": "error",
330
+ "no-unused-expressions": ["error", {
331
+ allowShortCircuit: true,
332
+ allowTaggedTemplates: true,
333
+ allowTernary: true
334
+ }],
335
+ "no-unused-vars": ["error", {
336
+ args: "none",
337
+ caughtErrors: "none",
338
+ ignoreRestSiblings: true,
339
+ vars: "all"
340
+ }],
341
+ "no-use-before-define": ["error", {
342
+ classes: false,
343
+ functions: false,
344
+ variables: true
345
+ }],
346
+ "no-useless-backreference": "error",
347
+ "no-useless-call": "error",
348
+ "no-useless-catch": "error",
349
+ "no-useless-computed-key": "error",
350
+ "no-useless-constructor": "error",
351
+ "no-useless-rename": "error",
352
+ "no-useless-return": "error",
353
+ "no-var": "error",
354
+ "no-with": "error",
355
+ "object-shorthand": [
356
+ "error",
357
+ "always",
358
+ {
359
+ avoidQuotes: true,
360
+ ignoreConstructors: false
361
+ }
362
+ ],
363
+ "one-var": ["error", { initialized: "never" }],
364
+ "prefer-arrow-callback": ["error", {
365
+ allowNamedFunctions: false,
366
+ allowUnboundThis: true
367
+ }],
368
+ "prefer-const": ["error", {
369
+ destructuring: "all",
370
+ ignoreReadBeforeAssign: true
371
+ }],
372
+ "prefer-exponentiation-operator": "error",
373
+ "prefer-promise-reject-errors": "error",
374
+ "prefer-regex-literals": ["error", { disallowRedundantWrapping: true }],
375
+ "prefer-rest-params": "error",
376
+ "prefer-spread": "error",
377
+ "prefer-template": "error",
378
+ "symbol-description": "error",
379
+ "unicode-bom": ["error", "never"],
380
+ "use-isnan": ["error", {
381
+ enforceForIndexOf: true,
382
+ enforceForSwitchCase: true
383
+ }],
384
+ "valid-typeof": ["error", { requireStringLiterals: true }],
385
+ "vars-on-top": "error",
386
+ "yoda": ["error", "never"],
204
387
  ...resolved.overrides
205
388
  }
206
389
  }];
@@ -230,7 +413,7 @@ async function jsdoc(options) {
230
413
  plugins: { jsdoc: jsdocPlugin }
231
414
  }, {
232
415
  files: resolved.files,
233
- name: "favorodera/tailwind/rules",
416
+ name: "favorodera/jsdoc/rules",
234
417
  rules: {
235
418
  ...baseRules,
236
419
  "jsdoc/check-access": "warn",
@@ -580,7 +763,7 @@ async function markdown(options) {
580
763
  {
581
764
  files: [codeInMdGlob],
582
765
  languageOptions: { parserOptions: { ecmaFeatures: { impliedStrict: true } } },
583
- name: "favorodera/markdown/disables/code",
766
+ name: "favorodera/markdown/code-in-md/disables",
584
767
  rules: {
585
768
  "no-alert": "off",
586
769
  "no-console": "off",
@@ -717,6 +900,47 @@ async function perfectionist(options) {
717
900
  }];
718
901
  }
719
902
  //#endregion
903
+ //#region src/configs/pnpm.ts
904
+ /**
905
+ * Constructs the flat config items for pnpm linting.
906
+ * @returns Promise resolving to pnpm ESLint config items.
907
+ */
908
+ async function pnpm() {
909
+ const [pnpmPlugin, yamlParser] = await Promise.all([importModule(import("eslint-plugin-pnpm")), importModule(import("yaml-eslint-parser"))]);
910
+ return [
911
+ {
912
+ name: "favorodera/pnpm/setup",
913
+ plugins: { pnpm: pnpmPlugin }
914
+ },
915
+ {
916
+ files: [packageJsonGlob],
917
+ language: "jsonc/x",
918
+ name: "favorodera/pnpm/package-json",
919
+ rules: {
920
+ "pnpm/json-enforce-catalog": ["error", {
921
+ autofix: true,
922
+ ignores: ["@types/vscode"]
923
+ }],
924
+ "pnpm/json-prefer-workspace-settings": ["error", { autofix: true }],
925
+ "pnpm/json-valid-catalog": ["error", { autofix: true }]
926
+ }
927
+ },
928
+ {
929
+ files: [pnpmWorkspaceGlob],
930
+ languageOptions: { parser: yamlParser },
931
+ name: "favorodera/pnpm/pnpm-workspace-yaml",
932
+ rules: {
933
+ "pnpm/yaml-enforce-settings": ["error", { settings: {
934
+ shellEmulator: true,
935
+ trustPolicy: "no-downgrade"
936
+ } }],
937
+ "pnpm/yaml-no-duplicate-catalog-item": ["error", { checkDuplicates: "exact-version" }],
938
+ "pnpm/yaml-no-unused-catalog-item": "error"
939
+ }
940
+ }
941
+ ];
942
+ }
943
+ //#endregion
720
944
  //#region src/configs/stylistic.ts
721
945
  const stylisticDefaults = {
722
946
  files: [
@@ -811,12 +1035,55 @@ async function tailwind(options) {
811
1035
  rules: {
812
1036
  ...renamePluginsInRules(baseRules, { "better-tailwindcss": "tailwind" }),
813
1037
  "tailwind/enforce-consistent-line-wrapping": ["error", { group: "emptyLine" }],
814
- "tailwind/no-unregistered-classes": "off",
815
1038
  ...resolved.overrides
816
1039
  }
817
1040
  }];
818
1041
  }
819
1042
  //#endregion
1043
+ //#region src/configs/test.ts
1044
+ const testDefaults = { files: testsGlob };
1045
+ /**
1046
+ * Constructs the flat config items for test linting, extending
1047
+ * the recommended Vitest rule sets.
1048
+ * @param options Test configuration options.
1049
+ * @returns Promise resolving to test ESLint config items.
1050
+ */
1051
+ async function test(options) {
1052
+ const resolved = defu(options, testDefaults);
1053
+ const testPlugin = await importModule(import("@vitest/eslint-plugin"));
1054
+ const baseRules = extractRules(testPlugin.configs.recommended);
1055
+ return [
1056
+ {
1057
+ name: "favorodera/test/setup",
1058
+ plugins: { test: testPlugin }
1059
+ },
1060
+ {
1061
+ files: resolved.files,
1062
+ name: "favorodera/test/rules",
1063
+ rules: {
1064
+ ...renamePluginsInRules(baseRules, { vitest: "test" }),
1065
+ "test/consistent-test-it": ["error", {
1066
+ fn: "it",
1067
+ withinDescribe: "it"
1068
+ }],
1069
+ "test/no-identical-title": "error",
1070
+ "test/no-import-node-test": "error",
1071
+ "test/prefer-hooks-in-order": "error",
1072
+ "test/prefer-lowercase-title": "error",
1073
+ ...resolved.overrides
1074
+ }
1075
+ },
1076
+ {
1077
+ files: resolved.files,
1078
+ name: "favorodera/test/disables",
1079
+ rules: {
1080
+ "no-unused-expressions": "off",
1081
+ "node/prefer-global/process": "off"
1082
+ }
1083
+ }
1084
+ ];
1085
+ }
1086
+ //#endregion
820
1087
  //#region src/configs/typescript.ts
821
1088
  const typescriptDefaults = { files: [tsGlob] };
822
1089
  /**
@@ -867,7 +1134,7 @@ const unicornDefaults = { files: [
867
1134
  async function unicorn(options) {
868
1135
  const resolved = defu(options, unicornDefaults);
869
1136
  const unicornPlugin = await importModule(import("eslint-plugin-unicorn"));
870
- const baseRules = unicornPlugin.configs["unopinionated"]?.rules || {};
1137
+ const baseRules = unicornPlugin.configs.recommended?.rules || {};
871
1138
  return [{
872
1139
  name: "favorodera/unicorn/setup",
873
1140
  plugins: { unicorn: unicornPlugin }
@@ -877,21 +1144,7 @@ async function unicorn(options) {
877
1144
  name: "favorodera/unicorn/rules",
878
1145
  rules: {
879
1146
  ...baseRules,
880
- "unicorn/consistent-empty-array-spread": "error",
881
- "unicorn/error-message": "error",
882
- "unicorn/escape-case": "error",
883
- "unicorn/new-for-builtins": "error",
884
- "unicorn/no-instanceof-builtins": "error",
885
- "unicorn/no-new-array": "error",
886
- "unicorn/no-new-buffer": "error",
887
- "unicorn/number-literal-case": "error",
888
- "unicorn/prefer-dom-node-text-content": "error",
889
- "unicorn/prefer-includes": "error",
890
- "unicorn/prefer-node-protocol": "error",
891
- "unicorn/prefer-number-properties": "error",
892
- "unicorn/prefer-string-starts-ends-with": "error",
893
- "unicorn/prefer-type-error": "error",
894
- "unicorn/throw-new-error": "error",
1147
+ "unicorn/filename-case": "off",
895
1148
  ...resolved.overrides
896
1149
  }
897
1150
  }];
@@ -921,7 +1174,7 @@ async function vue(options) {
921
1174
  importModule(import("vue-eslint-parser")),
922
1175
  importModule(import("typescript-eslint"))
923
1176
  ]);
924
- const baseRules = extractRules(vuePlugin.configs["flat/essential"], vuePlugin.configs["flat/strongly-recommended"], vuePlugin.configs["flat/recommended"]);
1177
+ const baseRules = extractRules(vuePlugin.configs["flat/recommended-error"]);
925
1178
  const processor = sfcBlocks === false ? vuePlugin.processors[".vue"] : mergeProcessors([vuePlugin.processors[".vue"], vueBlocksProcessor(sfcBlocks)]);
926
1179
  return [{
927
1180
  languageOptions: { globals: {
@@ -956,27 +1209,190 @@ async function vue(options) {
956
1209
  processor,
957
1210
  rules: {
958
1211
  ...baseRules,
1212
+ "vue/block-lang": ["error", { script: { lang: "ts" } }],
959
1213
  "vue/block-order": ["error", { order: [
960
1214
  "script",
961
1215
  "template",
962
1216
  "style"
963
1217
  ] }],
964
1218
  "vue/block-tag-newline": ["error", {
965
- multiline: "ignore",
966
- singleline: "ignore"
1219
+ multiline: "always",
1220
+ singleline: "always"
967
1221
  }],
968
- "vue/component-name-in-template-casing": ["error", "PascalCase"],
969
- "vue/component-options-name-casing": ["error", "PascalCase"],
1222
+ "vue/comment-directive": ["error", { reportUnusedDisableDirectives: true }],
1223
+ "vue/define-macros-order": ["error", {
1224
+ defineExposeLast: true,
1225
+ order: [
1226
+ "defineOptions",
1227
+ "definePage",
1228
+ "defineSlots",
1229
+ "defineEmits",
1230
+ "defineProps",
1231
+ "defineModel"
1232
+ ]
1233
+ }],
1234
+ "vue/define-props-declaration": ["error", "type-based"],
1235
+ "vue/define-props-destructuring": ["error", { destructure: "never" }],
970
1236
  "vue/multi-word-component-names": "off",
971
- "vue/multiline-html-element-content-newline": ["error", {
972
- allowEmptyLines: true,
973
- ignores: ["pre", "textarea"]
1237
+ "vue/next-tick-style": ["error", "promise"],
1238
+ "vue/no-import-compiler-macros": "error",
1239
+ "vue/no-negated-v-if-condition": "error",
1240
+ "vue/no-reserved-component-names": ["error", {
1241
+ disallowVue3BuiltInComponents: true,
1242
+ disallowVueBuiltInComponents: true,
1243
+ htmlElementCaseSensitive: false
974
1244
  }],
1245
+ "vue/no-root-v-if": "error",
1246
+ "vue/no-template-target-blank": "error",
1247
+ "vue/no-unused-emit-declarations": "error",
1248
+ "vue/no-unused-properties": "error",
1249
+ "vue/no-unused-refs": "error",
1250
+ "vue/no-use-v-else-with-v-for": "error",
1251
+ "vue/no-useless-mustaches": "error",
1252
+ "vue/no-useless-v-bind": "error",
1253
+ "vue/padding-line-between-blocks": "error",
1254
+ "vue/padding-line-between-tags": ["error", [
1255
+ {
1256
+ blankLine: "always",
1257
+ next: "*:multi-line",
1258
+ prev: "*:single-line"
1259
+ },
1260
+ {
1261
+ blankLine: "always",
1262
+ next: "*:single-line",
1263
+ prev: "*:multi-line"
1264
+ },
1265
+ {
1266
+ blankLine: "always",
1267
+ next: "*:multi-line",
1268
+ prev: "*:multi-line"
1269
+ },
1270
+ {
1271
+ blankLine: "never",
1272
+ next: "*:single-line",
1273
+ prev: "*:single-line"
1274
+ }
1275
+ ]],
1276
+ "vue/prefer-prop-type-boolean-first": "error",
1277
+ "vue/prefer-separate-static-class": "error",
1278
+ "vue/prefer-single-event-payload": "error",
1279
+ "vue/prefer-use-template-ref": "error",
1280
+ "vue/require-explicit-slots": "error",
1281
+ "vue/require-macro-variable-name": "error",
1282
+ "vue/slot-name-casing": ["error", "kebab-case"],
1283
+ "vue/v-for-delimiter-style": ["error", "in"],
975
1284
  ...resolved.overrides
976
1285
  }
977
1286
  }];
978
1287
  }
979
1288
  //#endregion
1289
+ //#region src/configs/yaml.ts
1290
+ const yamlDefaults = { files: [yamlGlob] };
1291
+ /**
1292
+ * Constructs the flat config items for YAML linting, setting up
1293
+ * the custom parser and rule validations.
1294
+ * @param options YAML configuration options.
1295
+ * @returns Promise resolving to YAML ESLint config items.
1296
+ */
1297
+ async function yaml(options) {
1298
+ const resolved = defu(options, yamlDefaults);
1299
+ const [yamlPlugin, yamlParser] = await Promise.all([importModule(import("eslint-plugin-yml")), importModule(import("yaml-eslint-parser"))]);
1300
+ const baseRules = extractRules(yamlPlugin.configs.standard);
1301
+ return [
1302
+ {
1303
+ name: "favorodera/yaml/setup",
1304
+ plugins: { yaml: yamlPlugin }
1305
+ },
1306
+ {
1307
+ files: resolved.files,
1308
+ languageOptions: { parser: yamlParser },
1309
+ name: "favorodera/yaml/rules",
1310
+ rules: {
1311
+ ...renamePluginsInRules(baseRules, { yml: "yaml" }),
1312
+ "yaml/quotes": ["error", {
1313
+ avoidEscape: true,
1314
+ prefer: "single"
1315
+ }],
1316
+ "yaml/require-string-key": "error",
1317
+ ...resolved.overrides
1318
+ }
1319
+ },
1320
+ {
1321
+ files: [pnpmWorkspaceGlob],
1322
+ languageOptions: { parser: yamlParser },
1323
+ name: "favorodera/yaml/sort/pnpm-workspace-yaml",
1324
+ rules: { "yaml/sort-keys": [
1325
+ "error",
1326
+ {
1327
+ order: [
1328
+ "cacheDir",
1329
+ "catalogMode",
1330
+ "cleanupUnusedCatalogs",
1331
+ "dedupeDirectDeps",
1332
+ "deployAllFiles",
1333
+ "enablePrePostScripts",
1334
+ "engineStrict",
1335
+ "extendNodePath",
1336
+ "hoist",
1337
+ "hoistPattern",
1338
+ "hoistWorkspacePackages",
1339
+ "ignoreCompatibilityDb",
1340
+ "ignoreDepScripts",
1341
+ "ignoreScripts",
1342
+ "ignoreWorkspaceRootCheck",
1343
+ "managePackageManagerVersions",
1344
+ "minimumReleaseAge",
1345
+ "minimumReleaseAgeExclude",
1346
+ "modulesDir",
1347
+ "nodeLinker",
1348
+ "nodeVersion",
1349
+ "optimisticRepeatInstall",
1350
+ "packageManagerStrict",
1351
+ "packageManagerStrictVersion",
1352
+ "preferSymlinkedExecutables",
1353
+ "preferWorkspacePackages",
1354
+ "publicHoistPattern",
1355
+ "registrySupportsTimeField",
1356
+ "requiredScripts",
1357
+ "resolutionMode",
1358
+ "savePrefix",
1359
+ "scriptShell",
1360
+ "shamefullyHoist",
1361
+ "shellEmulator",
1362
+ "stateDir",
1363
+ "supportedArchitectures",
1364
+ "symlink",
1365
+ "tag",
1366
+ "trustPolicy",
1367
+ "trustPolicyExclude",
1368
+ "updateNotifier",
1369
+ "packages",
1370
+ "overrides",
1371
+ "patchedDependencies",
1372
+ "catalog",
1373
+ "catalogs",
1374
+ "allowedDeprecatedVersions",
1375
+ "allowNonAppliedPatches",
1376
+ "configDependencies",
1377
+ "ignoredBuiltDependencies",
1378
+ "ignoredOptionalDependencies",
1379
+ "neverBuiltDependencies",
1380
+ "onlyBuiltDependencies",
1381
+ "onlyBuiltDependenciesFile",
1382
+ "packageExtensions",
1383
+ "peerDependencyRules"
1384
+ ],
1385
+ pathPattern: "^$"
1386
+ },
1387
+ {
1388
+ order: { type: "asc" },
1389
+ pathPattern: ".*"
1390
+ }
1391
+ ] }
1392
+ }
1393
+ ];
1394
+ }
1395
+ //#endregion
980
1396
  //#region src/factory.ts
981
1397
  /**
982
1398
  * Factory to create a flat ESLint config.
@@ -994,11 +1410,14 @@ function factory(options = {}) {
994
1410
  markdown,
995
1411
  node,
996
1412
  perfectionist,
1413
+ pnpm,
997
1414
  stylistic,
998
1415
  tailwind,
1416
+ test,
999
1417
  typescript,
1000
1418
  unicorn,
1001
- vue
1419
+ vue,
1420
+ yaml
1002
1421
  };
1003
1422
  for (const [key, configFunction] of Object.entries(configFunctions)) {
1004
1423
  const configOption = options[key];
@@ -1011,9 +1430,11 @@ function factory(options = {}) {
1011
1430
  "better-tailwindcss": "tailwind",
1012
1431
  "import-lite": "import",
1013
1432
  "markdown": "md",
1014
- "n": "node"
1433
+ "n": "node",
1434
+ "vitest": "test",
1435
+ "yml": "yaml"
1015
1436
  });
1016
1437
  return composer;
1017
1438
  }
1018
1439
  //#endregion
1019
- export { factory, importModule };
1440
+ export { codeInMdGlob, extractRules, factory, ignoresGlob, importModule, jsGlob, json5Glob, jsonGlob, jsoncGlob, mdGlob, mdInMdGlob, packageJsonGlob, pnpmWorkspaceGlob, scriptsGlob, testsGlob, tsConfigGlob, tsGlob, vueGlob, yamlGlob };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@favorodera/eslint-config",
3
3
  "type": "module",
4
- "version": "0.0.5",
4
+ "version": "0.0.7",
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>",
@@ -51,6 +51,7 @@
51
51
  "@eslint/js": "^10.0.1",
52
52
  "@eslint/markdown": "^8.0.2",
53
53
  "@stylistic/eslint-plugin": "^5.10.0",
54
+ "@vitest/eslint-plugin": "^1.6.19",
54
55
  "defu": "^6.1.7",
55
56
  "eslint-flat-config-utils": "^3.2.0",
56
57
  "eslint-merge-processors": "^2.0.0",
@@ -60,17 +61,21 @@
60
61
  "eslint-plugin-jsonc": "^3.2.0",
61
62
  "eslint-plugin-n": "^18.1.0",
62
63
  "eslint-plugin-perfectionist": "^5.9.0",
64
+ "eslint-plugin-pnpm": "^1.6.1",
63
65
  "eslint-plugin-unicorn": "^65.0.1",
64
66
  "eslint-plugin-unused-imports": "^4.4.1",
65
67
  "eslint-plugin-vue": "^10.9.2",
68
+ "eslint-plugin-yml": "^3.4.0",
66
69
  "eslint-processor-vue-blocks": "^2.0.0",
67
70
  "globals": "^17.6.0",
68
71
  "typescript-eslint": "^8.60.1",
69
- "vue-eslint-parser": "^10.4.1"
72
+ "vue-eslint-parser": "^10.4.1",
73
+ "yaml-eslint-parser": "^2.0.0"
70
74
  },
71
75
  "devDependencies": {
72
76
  "@types/node": "^25.6.2",
73
77
  "@typescript/native-preview": "7.0.0-dev.20260509.2",
78
+ "@vitest/ui": "4.1.8",
74
79
  "concurrently": "^10.0.3",
75
80
  "eslint": "^10.4.1",
76
81
  "eslint-typegen": "^2.3.1",
@@ -87,6 +92,7 @@
87
92
  "build": "tsdown",
88
93
  "dev": "pnpm prebuild && concurrently \"tsdown --watch\" \"pnpm dev:inspector\"",
89
94
  "test": "vitest run",
95
+ "test:watch": "vitest --watch --ui",
90
96
  "typecheck": "tsc --noEmit",
91
97
  "lint": "eslint . --fix",
92
98
  "ready": "pnpm install && pnpm build && pnpm lint && pnpm typecheck && pnpm test"