Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

eslint-plugin-oxlint

Package Overview
Dependencies
Maintainers
0
Versions
34
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

eslint-plugin-oxlint - npm Package Compare versions

Comparing version 0.11.0 to 0.11.1

dist/configs.cjs

23

package.json
{
"name": "eslint-plugin-oxlint",
"version": "0.11.0",
"version": "0.11.1",
"description": "Turn off all rules already supported by oxlint",
"type": "module",
"packageManager": "pnpm@9.12.2",
"types": "./dist/index.d.ts",
"packageManager": "pnpm@9.12.3",
"exports": {

@@ -15,12 +16,12 @@ ".": {

"./rules-by-category": {
"types": "./dist/rules-by-category.d.ts",
"import": "./dist/rules-by-category.mjs",
"require": "./dist/rules-by-category.cjs",
"default": "./dist/rules-by-category.mjs"
"types": "./dist/generated/rules-by-category.d.ts",
"import": "./dist/generated/rules-by-category.mjs",
"require": "./dist/generated/rules-by-category.cjs",
"default": "./dist/generated/rules-by-category.mjs"
},
"./rules-by-scope": {
"types": "./dist/rules-by-scope.d.ts",
"import": "./dist/rules-by-scope.mjs",
"require": "./dist/rules-by-scope.cjs",
"default": "./dist/rules-by-scope.mjs"
"types": "./dist/generated/rules-by-scope.d.ts",
"import": "./dist/generated/rules-by-scope.mjs",
"require": "./dist/generated/rules-by-scope.cjs",
"default": "./dist/generated/rules-by-scope.mjs"
}

@@ -67,3 +68,3 @@ },

"memfs": "^4.14.0",
"oxlint": "^0.11.0",
"oxlint": "^0.11.1",
"prettier": "^3.3.3",

@@ -70,0 +71,0 @@ "scule": "^1.3.0",

@@ -56,6 +56,6 @@ # eslint-plugin-oxlint

// eslint.config.js
import { buildFromOxlintConfigFile } from 'eslint-plugin-oxlint';
import oxlint from 'eslint-plugin-oxlint';
export default [
..., // other plugins
...buildFromOxlintConfigFile('./oxlint.json'),
...oxlint.buildFromOxlintConfigFile('./oxlint.json'),
];

@@ -68,6 +68,6 @@ ```

// eslint.config.js
import { buildFromOxlintConfig } from 'eslint-plugin-oxlint';
import oxlint from 'eslint-plugin-oxlint';
export default [
..., // other plugins
...buildFromOxlintConfig({
...oxlint.buildFromOxlintConfig({
categories: {

@@ -74,0 +74,0 @@ correctness: 'warn'

@@ -9,3 +9,3 @@ import { describe, expect, it } from 'vitest';

import type { Linter } from 'eslint';
import { typescriptRulesExtendEslintRules } from '../scripts/constants.js';
import { typescriptRulesExtendEslintRules } from './constants.js';

@@ -123,4 +123,67 @@ describe('buildFromOxlintConfig', () => {

});
expect('import/no-unused-modules' in rules).toBe(false);
expect(rules.length).toBe(1);
expect(rules[0].rules).not.toBeUndefined();
expect('import/no-unused-modules' in rules[0].rules!).toBe(false);
});
// look here: <https://github.com/oxc-project/oxc/blob/0b329516372a0353e9eb18e5bc0fbe63bce21fee/crates/oxc_linter/src/config/rules.rs#L285>
it('detects oxlint rules with plugin alias inside rules block', () => {
const configs = buildFromOxlintConfig({
rules: {
'eslint/eqeqeq': 'warn',
'typescript/no-unused-vars': 'warn',
'react_perf/jsx-no-new-array-as-prop': 'warn',
'nextjs/no-img-element': 'warn',
'jsx_a11y/alt-text': 'warn',
'react/rules-of-hooks': 'warn',
// 'deepscan/xxx': 'warn',
},
});
expect(configs.length).toBe(1);
expect(configs[0].rules).not.toBeUndefined();
expect('eqeqeq' in configs[0].rules!).toBe(true);
expect('@typescript-eslint/no-unused-vars' in configs[0].rules!).toBe(true);
expect('react-perf/jsx-no-new-array-as-prop' in configs[0].rules!).toBe(
true
);
expect('@next/next/no-img-element' in configs[0].rules!).toBe(true);
expect('jsx-a11y/alt-text' in configs[0].rules!).toBe(true);
expect('react-hooks/rules-of-hooks' in configs[0].rules!).toBe(true);
});
it('detects rules without plugin name', () => {
const configs = buildFromOxlintConfig({
rules: {
'no-unused-vars': 'warn',
'jsx-no-new-array-as-prop': 'warn',
'no-img-element': 'warn',
'no-array-reduce': 'warn',
},
});
expect(configs.length).toBe(1);
expect(configs[0].rules).not.toBeUndefined();
expect('@typescript-eslint/no-unused-vars' in configs[0].rules!).toBe(true);
expect('react-perf/jsx-no-new-array-as-prop' in configs[0].rules!).toBe(
true
);
expect('@next/next/no-img-element' in configs[0].rules!).toBe(true);
expect('unicorn/no-array-reduce' in configs[0].rules!).toBe(true);
});
it('skips unknown oxlint rules', () => {
const rules = buildFromOxlintConfig({
rules: {
unknown: 'warn',
'typescript/no-img-element': 'warn', // valid rule, but wrong plugin-name
},
});
expect(rules.length).toBe(1);
expect(rules[0].rules).not.toBeUndefined();
expect('unknown' in rules[0].rules!).toBe(false);
expect('@next/next/no-img-element' in rules[0].rules!).toBe(false);
});
});

@@ -148,3 +211,3 @@

// hello world
"no-await-loop": "error",
"no-await-in-loop": "error",
},

@@ -156,3 +219,3 @@ }`

expect(rules[0].rules).not.toBeUndefined();
expect('no-await-loop' in rules[0].rules!).toBe(true);
expect('no-await-in-loop' in rules[0].rules!).toBe(true);
});

@@ -159,0 +222,0 @@

import fs from 'node:fs';
import configByCategory from './configs-by-category.js';
import configByCategory from './generated/configs-by-category.js';
import type { Linter } from 'eslint';
import JSONCParser from 'jsonc-parser';
import {
aliasPluginNames,
reactHookRulesInsideReactScope,
} from './constants.js';
// these are the mappings from the scope in the rules.rs to the eslint scope
// only used for the scopes where the directory structure doesn't reflect the eslint scope
// such as `typescript` vs `@typescript-eslint` or others. Eslint as a scope is an exception,
// as eslint doesn't have a scope.
// There is a duplicate in scripts/constants.js, for clean builds we manage it in 2 files.
// In the future we can generate maybe this constant into src folder
const scopeMaps = {
eslint: '',
typescript: '@typescript-eslint',
};
const allRulesObjects = Object.values(configByCategory).map(
(config) => config.rules
);
const allRules: string[] = allRulesObjects.flatMap((rulesObject) =>
Object.keys(rulesObject)
);

@@ -37,2 +37,8 @@ type OxlintConfigPlugins = string[];

/**
* Detects it the value is an object
*/
const isObject = (value: unknown): boolean =>
typeof value === 'object' && value !== null && !Array.isArray(value);
/**
* tries to read the oxlint config file and returning its JSON content.

@@ -51,3 +57,3 @@ * if the file is not found or could not be parsed, undefined is returned.

if (typeof configContent !== 'object' || Array.isArray(configContent)) {
if (!isObject(configContent)) {
throw new TypeError('not an valid config file');

@@ -93,4 +99,4 @@ }

for (const plugin of plugins) {
// @ts-expect-error -- come on TS, we are checking if the plugin exists in the configByscopeMapsCategory
const pluginPrefix = plugin in scopeMaps ? scopeMaps[plugin] : plugin;
const pluginPrefix =
plugin in aliasPluginNames ? aliasPluginNames[plugin] : plugin;

@@ -109,2 +115,39 @@ // the rule has no prefix, so it is a eslint one

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);
};
/**

@@ -118,8 +161,17 @@ * checks if the oxlint rule is activated/deactivated and append/remove it.

for (const rule in oxlintRules) {
const eslintName = getEsLintRuleName(rule);
if (eslintName === undefined) {
console.warn(
`eslint-plugin-oxlint: could not find matching eslint rule for "${rule}"`
);
continue;
}
// is this rules not turned off
if (isActiveValue(oxlintRules[rule])) {
rules[rule] = 'off';
rules[eslintName] = 'off';
} else if (rule in rules && isDeactivateValue(oxlintRules[rule])) {
// rules extended by categories or plugins can be disabled manually
delete rules[rule];
delete rules[eslintName];
}

@@ -129,3 +181,8 @@ }

const isOffValue = (value: unknown) => value === 'off' || value === 0;
/**
* 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]));

@@ -135,15 +192,9 @@ /**

*/
const isDeactivateValue = (value: unknown): boolean => {
return isOffValue(value) || (Array.isArray(value) && isOffValue(value[0]));
};
const isDeactivateValue = (value: unknown) => isValueInSet(value, ['off', 0]);
const isOnValue = (value: unknown) =>
value === 'error' || value === 'warn' || value === 1 || value === 2;
/**
* check if the value is "error", "warn", 1, 2, ["error", ...], ["warn", ...], [1, ...], or [2, ...]
*/
const isActiveValue = (value: unknown): boolean => {
return isOnValue(value) || (Array.isArray(value) && isOnValue(value[0]));
};
const isActiveValue = (value: unknown) =>
isValueInSet(value, ['error', 'warn', 1, 2]);

@@ -169,5 +220,3 @@ /**

): OxlintConfigCategories | undefined => {
return 'categories' in config &&
typeof config.categories === 'object' &&
config.categories !== null
return 'categories' in config && isObject(config.categories)
? (config.categories as OxlintConfigCategories)

@@ -184,5 +233,3 @@ : undefined;

): OxlintConfigRules | undefined => {
return 'rules' in config &&
typeof config.rules === 'object' &&
config.rules !== null
return 'rules' in config && isObject(config.rules)
? (config.rules as OxlintConfigRules)

@@ -189,0 +236,0 @@ : undefined;

@@ -1,7 +0,3 @@

import * as ruleMapsByScope from './rules-by-scope.js';
import * as ruleMapsByCategory from './rules-by-category.js';
import configByScope from './configs-by-scope.js';
import configByCategory from './configs-by-category.js';
export {
import configs from './configs.js';
import {
buildFromOxlintConfig,

@@ -11,37 +7,6 @@ buildFromOxlintConfigFile,

type UnionToIntersection<U> = (
U extends unknown ? (x: U) => void : never
) extends (x: infer I) => void
? I
: never;
type RulesGroups = keyof typeof ruleMapsByScope;
type AllRules = (typeof ruleMapsByScope)[RulesGroups];
const allRules: UnionToIntersection<AllRules> = Object.assign(
{},
...Object.values(ruleMapsByScope)
);
export default {
configs: {
recommended: {
plugins: ['oxlint'],
rules: ruleMapsByCategory.correctnessRules,
},
all: {
plugins: ['oxlint'],
rules: allRules,
},
'flat/all': {
name: 'oxlint/all',
rules: allRules,
},
'flat/recommended': {
name: 'oxlint/recommended',
rules: ruleMapsByCategory.correctnessRules,
},
...configByScope,
...configByCategory,
},
configs,
buildFromOxlintConfig,
buildFromOxlintConfigFile,
};

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc