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>
80 lines
1.9 KiB
JavaScript
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);
|
|
});
|