|
2 | 2 | * @fileoverview An ESLint plugin for linting ESLint plugins
|
3 | 3 | * @author Teddy Katz
|
4 | 4 | */
|
| 5 | +import { createRequire } from 'node:module'; |
5 | 6 |
|
6 |
| -// ------------------------------------------------------------------------------ |
7 |
| -// Requirements |
8 |
| -// ------------------------------------------------------------------------------ |
| 7 | +import type { ESLint, Linter, Rule } from 'eslint'; |
9 | 8 |
|
10 |
| -import packageMetadata from '../package.json' with { type: 'json' }; |
11 | 9 | import consistentOutput from './rules/consistent-output.js';
|
12 | 10 | import fixerReturn from './rules/fixer-return.js';
|
13 | 11 | import metaPropertyOrdering from './rules/meta-property-ordering.js';
|
@@ -41,20 +39,56 @@ import requireMetaType from './rules/require-meta-type.js';
|
41 | 39 | import testCasePropertyOrdering from './rules/test-case-property-ordering.js';
|
42 | 40 | import testCaseShorthandStrings from './rules/test-case-shorthand-strings.js';
|
43 | 41 |
|
| 42 | +const require = createRequire(import.meta.url); |
| 43 | + |
| 44 | +const packageMetadata = require("../package.json") as { |
| 45 | + name: string; |
| 46 | + version: string; |
| 47 | +}; |
| 48 | + |
44 | 49 | const PLUGIN_NAME = packageMetadata.name.replace(/^eslint-plugin-/, '');
|
| 50 | +const CONFIG_NAMES = [ |
| 51 | + 'all', |
| 52 | + 'all-type-checked', |
| 53 | + 'recommended', |
| 54 | + 'rules', |
| 55 | + 'tests', |
| 56 | + 'rules-recommended', |
| 57 | + 'tests-recommended', |
| 58 | +] as const; |
| 59 | +type ConfigName = (typeof CONFIG_NAMES)[number]; |
45 | 60 |
|
46 |
| -const configFilters = { |
47 |
| - all: (rule) => !rule.meta.docs.requiresTypeChecking, |
| 61 | +const configFilters: Record<ConfigName, (rule: Rule.RuleModule) => boolean> = { |
| 62 | + all: (rule: Rule.RuleModule) => |
| 63 | + !( |
| 64 | + rule.meta?.docs && |
| 65 | + 'requiresTypeChecking' in rule.meta.docs && |
| 66 | + rule.meta.docs.requiresTypeChecking |
| 67 | + ), |
48 | 68 | 'all-type-checked': () => true,
|
49 |
| - recommended: (rule) => rule.meta.docs.recommended, |
50 |
| - rules: (rule) => rule.meta.docs.category === 'Rules', |
51 |
| - tests: (rule) => rule.meta.docs.category === 'Tests', |
52 |
| - 'rules-recommended': (rule) => |
| 69 | + recommended: (rule: Rule.RuleModule) => !!rule.meta?.docs?.recommended, |
| 70 | + rules: (rule: Rule.RuleModule) => rule.meta?.docs?.category === 'Rules', |
| 71 | + tests: (rule: Rule.RuleModule) => rule.meta?.docs?.category === 'Tests', |
| 72 | + 'rules-recommended': (rule: Rule.RuleModule) => |
53 | 73 | configFilters.recommended(rule) && configFilters.rules(rule),
|
54 |
| - 'tests-recommended': (rule) => |
| 74 | + 'tests-recommended': (rule: Rule.RuleModule) => |
55 | 75 | configFilters.recommended(rule) && configFilters.tests(rule),
|
56 | 76 | };
|
57 | 77 |
|
| 78 | +const createConfig = (configName: ConfigName): Linter.Config => ({ |
| 79 | + name: `${PLUGIN_NAME}/${configName}`, |
| 80 | + plugins: { |
| 81 | + get [PLUGIN_NAME](): ESLint.Plugin { |
| 82 | + return plugin; |
| 83 | + }, |
| 84 | + }, |
| 85 | + rules: Object.fromEntries( |
| 86 | + (Object.keys(allRules) as (keyof typeof allRules)[]) |
| 87 | + .filter((ruleName) => configFilters[configName](allRules[ruleName])) |
| 88 | + .map((ruleName) => [`${PLUGIN_NAME}/${ruleName}`, 'error']), |
| 89 | + ), |
| 90 | +}); |
| 91 | + |
58 | 92 | // ------------------------------------------------------------------------------
|
59 | 93 | // Plugin Definition
|
60 | 94 | // ------------------------------------------------------------------------------
|
@@ -93,34 +127,23 @@ const allRules = {
|
93 | 127 | 'require-meta-type': requireMetaType,
|
94 | 128 | 'test-case-property-ordering': testCasePropertyOrdering,
|
95 | 129 | 'test-case-shorthand-strings': testCaseShorthandStrings,
|
96 |
| -}; |
| 130 | +} satisfies Record<string, Rule.RuleModule>; |
97 | 131 |
|
98 |
| -/** @type {import("eslint").ESLint.Plugin} */ |
99 | 132 | const plugin = {
|
100 | 133 | meta: {
|
101 | 134 | name: packageMetadata.name,
|
102 | 135 | version: packageMetadata.version,
|
103 | 136 | },
|
104 | 137 | rules: allRules,
|
105 |
| - configs: {}, // assigned later |
106 |
| -}; |
107 |
| - |
108 |
| -// configs |
109 |
| -Object.assign( |
110 |
| - plugin.configs, |
111 |
| - Object.keys(configFilters).reduce((configs, configName) => { |
112 |
| - return Object.assign(configs, { |
113 |
| - [configName]: { |
114 |
| - name: `${PLUGIN_NAME}/${configName}`, |
115 |
| - plugins: { [PLUGIN_NAME]: plugin }, |
116 |
| - rules: Object.fromEntries( |
117 |
| - Object.keys(allRules) |
118 |
| - .filter((ruleName) => configFilters[configName](allRules[ruleName])) |
119 |
| - .map((ruleName) => [`${PLUGIN_NAME}/${ruleName}`, 'error']), |
120 |
| - ), |
121 |
| - }, |
122 |
| - }); |
123 |
| - }, {}), |
124 |
| -); |
| 138 | + configs: { |
| 139 | + all: createConfig('all'), |
| 140 | + 'all-type-checked': createConfig('all-type-checked'), |
| 141 | + recommended: createConfig('recommended'), |
| 142 | + rules: createConfig('rules'), |
| 143 | + tests: createConfig('tests'), |
| 144 | + 'rules-recommended': createConfig('rules-recommended'), |
| 145 | + 'tests-recommended': createConfig('tests-recommended'), |
| 146 | + }, |
| 147 | +} satisfies ESLint.Plugin; |
125 | 148 |
|
126 | 149 | export default plugin;
|
0 commit comments