eslint-plugin-oxlint
Version:
Turn off all rules already supported by oxlint
110 lines (93 loc) • 3.06 kB
text/typescript
import {
aliasPluginNames,
reactHookRulesInsideReactScope,
} from '../constants.js';
import {
OxlintConfig,
OxlintConfigOverride,
OxlintConfigRules,
} from './types.js';
import configByCategory from '../generated/configs-by-category.js';
import { isObject } from './utilities.js';
const allRulesObjects = Object.values(configByCategory).map(
(config) => config.rules
);
const allRules: string[] = allRulesObjects.flatMap((rulesObject) =>
Object.keys(rulesObject)
);
const getEsLintRuleName = (rule: string): string | undefined => {
// there is no plugin prefix, it can be all plugin
if (!rule.includes('/')) {
return allRules.find(
(search) => search.endsWith(`/${rule}`) || search === rule
);
}
// greedy works with `@next/next/no-img-element` as an example
const match = rule.match(/(^.*)\/(.*)/);
if (match === null) {
return undefined;
}
const pluginName = match[1];
const ruleName = match[2];
// map to the right eslint plugin
let esPluginName =
pluginName in aliasPluginNames ? aliasPluginNames[pluginName] : pluginName;
// special case for eslint-plugin-react-hooks
if (
esPluginName === 'react' &&
reactHookRulesInsideReactScope.includes(ruleName)
) {
esPluginName = 'react-hooks';
}
// extra check for eslint
const expectedRule =
esPluginName === '' ? ruleName : `${esPluginName}/${ruleName}`;
return allRules.find((rule) => rule == expectedRule);
};
/**
* checks if value is validSet, or if validSet is an array, check if value is first value of it
*/
const isValueInSet = (value: unknown, validSet: unknown[]) =>
validSet.includes(value) ||
(Array.isArray(value) && validSet.includes(value[0]));
/**
* check if the value is "off", 0, ["off", ...], or [0, ...]
*/
const isDeactivateValue = (value: unknown) => isValueInSet(value, ['off', 0]);
/**
* check if the value is "error", "warn", 1, 2, ["error", ...], ["warn", ...], [1, ...], or [2, ...]
*/
const isActiveValue = (value: unknown) =>
isValueInSet(value, ['error', 'warn', 1, 2]);
/**
* checks if the oxlint rule is activated/deactivated and append/remove it.
*/
export const handleRulesScope = (
oxlintRules: OxlintConfigRules,
rules: Record<string, 'off'>
): void => {
for (const rule in oxlintRules) {
const eslintName = getEsLintRuleName(rule);
if (eslintName === undefined) {
continue;
}
// is this rules not turned off
if (isActiveValue(oxlintRules[rule])) {
rules[eslintName] = 'off';
} else if (rule in rules && isDeactivateValue(oxlintRules[rule])) {
// rules extended by categories or plugins can be disabled manually
delete rules[eslintName];
}
}
};
/**
* tries to return the "rules" section from the config.
* it returns `undefined` when not found or invalid.
*/
export const readRulesFromConfig = (
config: OxlintConfig | OxlintConfigOverride
): OxlintConfigRules | undefined => {
return 'rules' in config && isObject(config.rules)
? (config.rules as OxlintConfigRules)
: undefined;
};