refactor: simplify oxc eslint compatibility

This commit is contained in:
xingyu4j
2026-03-14 00:16:27 +08:00
parent 7b064e9f33
commit 913636ae44
11 changed files with 491 additions and 568 deletions

View File

@@ -1,13 +0,0 @@
import type { Linter } from 'eslint';
export async function disableds(): Promise<Linter.Config[]> {
return [
{
files: ['**/*.js', '**/*.mjs', '**/*.cjs'],
name: 'disables/js',
rules: {
'@typescript-eslint/explicit-module-boundary-types': 'off',
},
},
];
}

View File

@@ -1,6 +1,5 @@
export * from './command'; export * from './command';
export * from './comments'; export * from './comments';
export * from './disableds';
export * from './ignores'; export * from './ignores';
export * from './javascript'; export * from './javascript';
export * from './jsonc'; export * from './jsonc';

View File

@@ -4,7 +4,73 @@ import js from '@eslint/js';
import pluginUnusedImports from 'eslint-plugin-unused-imports'; import pluginUnusedImports from 'eslint-plugin-unused-imports';
import globals from 'globals'; import globals from 'globals';
const rulesCoveredByOxlint = new Set([
'constructor-super',
'for-direction',
'getter-return',
'no-async-promise-executor',
'no-case-declarations',
'no-class-assign',
'no-compare-neg-zero',
'no-cond-assign',
'no-const-assign',
'no-constant-binary-expression',
'no-constant-condition',
'no-debugger',
'no-delete-var',
'no-dupe-args',
'no-dupe-class-members',
'no-dupe-else-if',
'no-dupe-keys',
'no-duplicate-case',
'no-empty',
'no-empty-character-class',
'no-empty-pattern',
'no-empty-static-block',
'no-ex-assign',
'no-extra-boolean-cast',
'no-fallthrough',
'no-func-assign',
'no-global-assign',
'no-import-assign',
'no-invalid-regexp',
'no-irregular-whitespace',
'no-loss-of-precision',
'no-misleading-character-class',
'no-new-native-nonconstructor',
'no-nonoctal-decimal-escape',
'no-obj-calls',
'no-prototype-builtins',
'no-redeclare',
'no-regex-spaces',
'no-self-assign',
'no-setter-return',
'no-shadow-restricted-names',
'no-sparse-arrays',
'no-this-before-super',
'no-unreachable',
'no-unsafe-finally',
'no-unsafe-negation',
'no-unsafe-optional-chaining',
'no-unused-labels',
'no-unused-private-class-members',
'no-unused-vars',
'no-useless-backreference',
'no-useless-catch',
'no-useless-escape',
'no-with',
'require-yield',
'use-isnan',
'valid-typeof',
]);
export async function javascript(): Promise<Linter.Config[]> { export async function javascript(): Promise<Linter.Config[]> {
const recommendedRules = Object.fromEntries(
Object.entries(js.configs.recommended.rules).filter(
([ruleName]) => !rulesCoveredByOxlint.has(ruleName),
),
);
return [ return [
{ {
languageOptions: { languageOptions: {
@@ -33,11 +99,10 @@ export async function javascript(): Promise<Linter.Config[]> {
'unused-imports': pluginUnusedImports, 'unused-imports': pluginUnusedImports,
}, },
rules: { rules: {
...js.configs.recommended.rules, ...recommendedRules,
'dot-notation': ['error', { allowKeywords: true }], 'dot-notation': ['error', { allowKeywords: true }],
'keyword-spacing': 'off', 'keyword-spacing': 'off',
'no-control-regex': 'error', 'no-control-regex': 'error',
'no-dupe-args': 'error',
'no-empty-function': 'off', 'no-empty-function': 'off',
'no-restricted-properties': [ 'no-restricted-properties': [
'error', 'error',
@@ -73,15 +138,6 @@ export async function javascript(): Promise<Linter.Config[]> {
], ],
'no-undef': 'off', 'no-undef': 'off',
'no-unreachable-loop': 'error', 'no-unreachable-loop': 'error',
'no-unused-vars': [
'error',
{
args: 'none',
caughtErrors: 'none',
ignoreRestSiblings: true,
vars: 'all',
},
],
'space-before-function-paren': 'off', 'space-before-function-paren': 'off',
'unused-imports/no-unused-imports': 'error', 'unused-imports/no-unused-imports': 'error',

View File

@@ -2,11 +2,24 @@ import type { Linter } from 'eslint';
import { interopDefault } from '../util'; import { interopDefault } from '../util';
const rulesCoveredByOxlint = new Set([
'@typescript-eslint/ban-ts-comment',
'@typescript-eslint/no-non-null-assertion',
'@typescript-eslint/no-unused-expressions',
'@typescript-eslint/no-unused-vars',
'@typescript-eslint/triple-slash-reference',
]);
export async function typescript(): Promise<Linter.Config[]> { export async function typescript(): Promise<Linter.Config[]> {
const [pluginTs, parserTs] = await Promise.all([ const [pluginTs, parserTs] = await Promise.all([
interopDefault(import('@typescript-eslint/eslint-plugin')), interopDefault(import('@typescript-eslint/eslint-plugin')),
interopDefault(import('@typescript-eslint/parser')), interopDefault(import('@typescript-eslint/parser')),
] as const); ] as const);
const strictRules = Object.fromEntries(
Object.entries(pluginTs.configs.strict?.rules ?? {}).filter(
([ruleName]) => !rulesCoveredByOxlint.has(ruleName),
),
);
return [ return [
{ {
@@ -30,7 +43,7 @@ export async function typescript(): Promise<Linter.Config[]> {
}, },
rules: { rules: {
...pluginTs.configs['eslint-recommended']?.overrides?.[0]?.rules, ...pluginTs.configs['eslint-recommended']?.overrides?.[0]?.rules,
...pluginTs.configs.strict?.rules, ...strictRules,
// '@typescript-eslint/consistent-type-definitions': ['warn', 'interface'], // '@typescript-eslint/consistent-type-definitions': ['warn', 'interface'],
'@typescript-eslint/consistent-type-definitions': 'off', '@typescript-eslint/consistent-type-definitions': 'off',
'@typescript-eslint/explicit-function-return-type': 'off', '@typescript-eslint/explicit-function-return-type': 'off',

View File

@@ -2,8 +2,20 @@ import type { Linter } from 'eslint';
import { interopDefault } from '../util'; import { interopDefault } from '../util';
const rulesCoveredByOxlint = new Set([
'unicorn/consistent-function-scoping',
'unicorn/no-process-exit',
'unicorn/prefer-global-this',
'unicorn/prefer-module',
]);
export async function unicorn(): Promise<Linter.Config[]> { export async function unicorn(): Promise<Linter.Config[]> {
const pluginUnicorn = await interopDefault(import('eslint-plugin-unicorn')); const pluginUnicorn = await interopDefault(import('eslint-plugin-unicorn'));
const recommendedRules = Object.fromEntries(
Object.entries(pluginUnicorn.configs.recommended.rules ?? {}).filter(
([ruleName]) => !rulesCoveredByOxlint.has(ruleName),
),
);
return [ return [
{ {
@@ -11,11 +23,10 @@ export async function unicorn(): Promise<Linter.Config[]> {
unicorn: pluginUnicorn, unicorn: pluginUnicorn,
}, },
rules: { rules: {
...pluginUnicorn.configs.recommended.rules, ...recommendedRules,
'unicorn/better-regex': 'off', 'unicorn/better-regex': 'off',
'unicorn/consistent-destructuring': 'off', 'unicorn/consistent-destructuring': 'off',
'unicorn/consistent-function-scoping': 'off',
'unicorn/expiring-todo-comments': 'off', 'unicorn/expiring-todo-comments': 'off',
'unicorn/filename-case': 'off', 'unicorn/filename-case': 'off',
'unicorn/import-style': 'off', 'unicorn/import-style': 'off',
@@ -25,19 +36,9 @@ export async function unicorn(): Promise<Linter.Config[]> {
'unicorn/prefer-at': 'off', 'unicorn/prefer-at': 'off',
'unicorn/prefer-dom-node-text-content': 'off', 'unicorn/prefer-dom-node-text-content': 'off',
'unicorn/prefer-export-from': ['error', { ignoreUsedVariables: true }], 'unicorn/prefer-export-from': ['error', { ignoreUsedVariables: true }],
'unicorn/prefer-global-this': 'off',
'unicorn/prefer-top-level-await': 'off', 'unicorn/prefer-top-level-await': 'off',
'unicorn/prevent-abbreviations': 'off', 'unicorn/prevent-abbreviations': 'off',
}, },
}, },
{
files: [
'scripts/**/*.?([cm])[jt]s?(x)',
'internal/**/*.?([cm])[jt]s?(x)',
],
rules: {
'unicorn/no-process-exit': 'off',
},
},
]; ];
} }

View File

@@ -128,7 +128,6 @@ export async function vue(): Promise<Linter.Config[]> {
}, },
], ],
'vue/one-component-per-file': 'error', 'vue/one-component-per-file': 'error',
'vue/prefer-import-from-vue': 'error',
'vue/prefer-separate-static-class': 'error', 'vue/prefer-separate-static-class': 'error',
'vue/prefer-template': 'error', 'vue/prefer-template': 'error',
'vue/prop-name-casing': ['error', 'camelCase'], 'vue/prop-name-casing': ['error', 'camelCase'],

View File

@@ -21,14 +21,6 @@ const customConfig: Linter.Config[] = [
ignores: restrictedImportIgnores, ignores: restrictedImportIgnores,
rules: { rules: {
'perfectionist/sort-interfaces': 'off', 'perfectionist/sort-interfaces': 'off',
'perfectionist/sort-objects': 'off',
},
},
{
files: ['**/**.vue'],
ignores: restrictedImportIgnores,
rules: {
'perfectionist/sort-objects': 'off',
}, },
}, },
{ {
@@ -63,7 +55,6 @@ const customConfig: Linter.Config[] = [
], ],
}, },
], ],
'perfectionist/sort-interfaces': 'off',
}, },
}, },
{ {
@@ -137,9 +128,7 @@ const customConfig: Linter.Config[] = [
{ {
files: ['apps/backend-mock/**/**', 'docs/**/**'], files: ['apps/backend-mock/**/**', 'docs/**/**'],
rules: { rules: {
'@typescript-eslint/no-extraneous-class': 'off',
'no-console': 'off', 'no-console': 'off',
'unicorn/prefer-module': 'off',
}, },
}, },
{ {

View File

@@ -3,7 +3,6 @@ import type { Linter } from 'eslint';
import { import {
command, command,
comments, comments,
disableds,
ignores, ignores,
javascript, javascript,
jsonc, jsonc,
@@ -34,7 +33,6 @@ async function defineConfig(config: FlatConfig[] = []) {
ignores(), ignores(),
typescript(), typescript(),
jsonc(), jsonc(),
disableds(),
node(), node(),
perfectionist(), perfectionist(),
comments(), comments(),

View File

@@ -35,12 +35,12 @@ const emit = defineEmits<{
}>(); }>();
const PI: number = Math.PI; const PI: number = Math.PI;
enum CanvasOpr { const canvasOpr = {
// eslint-disable-next-line no-unused-vars clip: 'clip',
Clip = 'clip', fill: 'fill',
// eslint-disable-next-line no-unused-vars } as const;
Fill = 'fill',
} type CanvasOpr = (typeof canvasOpr)[keyof typeof canvasOpr];
const modalValue = defineModel<boolean>({ default: false }); const modalValue = defineModel<boolean>({ default: false });
@@ -189,8 +189,8 @@ function draw(ctx1: CanvasRenderingContext2D, ctx2: CanvasRenderingContext2D) {
3 * circleRadius, 3 * circleRadius,
canvasHeight - (squareLength + 2 * circleRadius), canvasHeight - (squareLength + 2 * circleRadius),
); );
drawPiece(ctx1, state.pieceX, state.pieceY, CanvasOpr.Fill); drawPiece(ctx1, state.pieceX, state.pieceY, canvasOpr.fill);
drawPiece(ctx2, state.pieceX, state.pieceY, CanvasOpr.Clip); drawPiece(ctx2, state.pieceX, state.pieceY, canvasOpr.clip);
} }
// 绘制拼图切块 // 绘制拼图切块
@@ -233,7 +233,8 @@ function drawPiece(
ctx.fillStyle = 'rgba(255, 255, 255, 0.7)'; ctx.fillStyle = 'rgba(255, 255, 255, 0.7)';
ctx.strokeStyle = 'rgba(255, 255, 255, 0.7)'; ctx.strokeStyle = 'rgba(255, 255, 255, 0.7)';
ctx.stroke(); ctx.stroke();
opr === CanvasOpr.Clip ? ctx.clip() : ctx.fill(); // oxlint-disable-next-line no-unused-expressions
opr === canvasOpr.clip ? ctx.clip() : ctx.fill();
ctx.globalCompositeOperation = 'destination-over'; ctx.globalCompositeOperation = 'destination-over';
} }

View File

@@ -997,16 +997,16 @@ const bodyDown = (ev: MouseEvent & TouchEvent) => {
ev.preventDefault(); ev.preventDefault();
} }
if (isDraggable.value) {
bodyDrag.value = true;
}
const pointerPosition = getPointerPosition(ev); const pointerPosition = getPointerPosition(ev);
if (!pointerPosition) { if (!pointerPosition) {
return; return;
} }
if (isDraggable.value) {
bodyDrag.value = true;
}
saveDimensionsBeforeMove(pointerPosition); saveDimensionsBeforeMove(pointerPosition);
if (parentLimitation.value) { if (parentLimitation.value) {

878
up-oxc.md

File diff suppressed because it is too large Load Diff