Files
xterm.js/bin/lint_changes.js
Daniel ImmsandCursor 59d1ec7bf0 Migrate linting from ESLint to Oxlint (Fixes #5690)
Replace the primary lint pipeline with oxlint and oxlint-tsgolint for type-aware TypeScript rules, preserving existing rule behavior from eslint.config.mjs via @oxlint/migrate and targeted jsPlugins (@stylistic/eslint-plugin, eslint-plugin-jsdoc as jsdoc-js, oxlint-plugin-eslint for no-restricted-syntax and object-curly-spacing).

Keep a hybrid ESLint pass (eslint.config.naming.mjs) only for @typescript-eslint/naming-convention until tsgolint implements it (oxc-project/tsgolint#186). Legacy eslint.config.mjs and eslint.config.typings.mjs remain for reference but are no longer used by npm scripts.

Add .oxlintrc.json for src/addons/demo/test and .oxlintrc.typings.json for typings/ (syntax-only, no --type-aware). Update lint, lint-fix, lint-api, and lint-changes to run oxlint first, then naming ESLint. Platform binaries install via oxlint-tsgolint optionalDependencies on Linux, macOS, and Windows.

Fixes https://github.com/xtermjs/xterm.js/issues/5690

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-31 09:48:32 -07:00

80 lines
1.9 KiB
JavaScript

/**
* Copyright (c) 2026 The xterm.js authors. All rights reserved.
* @license MIT
*/
// @ts-check
const { execSync, spawn } = require('child_process');
const path = require('path');
const extensions = ['.ts', '.mts'];
const fix = process.argv.includes('--fix');
// Get uncommitted changed files (staged + unstaged)
function getChangedFiles() {
try {
const output = execSync('git diff --name-only --diff-filter=ACMR HEAD', {
encoding: 'utf-8',
cwd: path.join(__dirname, '..')
});
return output.split('\n').filter(f => f && extensions.some(ext => f.endsWith(ext)));
} catch {
return [];
}
}
const files = getChangedFiles();
if (files.length === 0) {
console.log('No changed TypeScript files to lint.');
process.exit(0);
}
console.log(`Linting ${files.length} changed file(s)...`);
const cwd = path.join(__dirname, '..');
const isWin = process.platform === 'win32';
/**
* @param {string} command
* @param {string[]} args
* @returns {Promise<void>}
*/
function run(command, args) {
return new Promise(/** @type {(resolve: () => void, reject: (reason: Error) => void) => void} */ ((resolve, reject) => {
const child = spawn(command, args, {
stdio: 'inherit',
cwd,
shell: isWin
});
child.on('close', code => {
if (code === 0) {
resolve();
} else {
reject(new Error(`${command} exited with code ${code}`));
}
});
}));
}
async function main() {
const oxlintArgs = ['--type-aware', '--max-warnings', '0'];
if (fix) {
oxlintArgs.push('--fix');
}
oxlintArgs.push(...files);
const oxlint = isWin ? 'oxlint.cmd' : 'oxlint';
await run(oxlint, oxlintArgs);
const eslintArgs = ['--config', 'eslint.config.naming.mjs', '--max-warnings', '0', ...files];
const eslint = isWin ? 'eslint.cmd' : 'eslint';
await run(eslint, eslintArgs);
}
main().catch(err => {
console.error(err.message);
process.exit(1);
});