99 lines
2.8 KiB
JavaScript
99 lines
2.8 KiB
JavaScript
import fs from "fs";
|
|
import {dirname, relative, resolve} from "path";
|
|
|
|
import {ESLint} from "eslint";
|
|
|
|
const projectRoot = process.cwd();
|
|
|
|
// Eslint mode: "Experimental" | "Legacy"
|
|
const LINT_MODE = "Experimental";
|
|
|
|
const removeIgnoredFilesNew = async (files) => {
|
|
try {
|
|
const eslint = new ESLint();
|
|
const cwd = process.cwd();
|
|
|
|
const relativePaths = files.map((file) => relative(cwd, file));
|
|
const isIgnored = await Promise.all(relativePaths.map((file) => eslint.isPathIgnored(file)));
|
|
|
|
return files.filter((_, i) => !isIgnored[i]).join(" ");
|
|
} catch (error) {
|
|
// eslint-disable-next-line no-console
|
|
console.error(error);
|
|
process.exit(1);
|
|
}
|
|
};
|
|
|
|
function findPackageRoot(file) {
|
|
let dir = dirname(file);
|
|
|
|
while (dir !== "/") {
|
|
if (fs.existsSync(`${dir}/package.json`)) return dir;
|
|
const parentDir = dirname(dir);
|
|
|
|
if (parentDir === dir) break;
|
|
dir = parentDir;
|
|
}
|
|
|
|
return projectRoot;
|
|
}
|
|
|
|
async function removeIgnoredFilesLegacy(files, eslint) {
|
|
const isIgnored = await Promise.all(files.map((file) => eslint.isPathIgnored(file)));
|
|
|
|
return files.filter((_, i) => !isIgnored[i]);
|
|
}
|
|
|
|
const lintStaged = {
|
|
"**/*.{cjs,mjs,js,ts,jsx,tsx}": async (files) => {
|
|
if (LINT_MODE === "Experimental") {
|
|
// use ESLint with experimental configuration file resolution
|
|
const filesToLint = await removeIgnoredFilesNew(files);
|
|
|
|
return [
|
|
`eslint --flag v10_config_lookup_from_file --max-warnings=0 --no-warn-ignored --fix ${filesToLint}`,
|
|
];
|
|
}
|
|
|
|
if (LINT_MODE === "Legacy") {
|
|
// Legacy with group files by package root and resolve ESLint config
|
|
const filesByPackage = new Map();
|
|
|
|
for (const file of files) {
|
|
const pkgRoot = findPackageRoot(file);
|
|
|
|
if (!filesByPackage.has(pkgRoot)) filesByPackage.set(pkgRoot, []);
|
|
filesByPackage.get(pkgRoot).push(file);
|
|
}
|
|
|
|
const commands = [];
|
|
|
|
for (const [pkgRoot, pkgFiles] of filesByPackage.entries()) {
|
|
// Check if the package has its own eslint.config.mjs
|
|
const configPath = fs.existsSync(resolve(pkgRoot, "eslint.config.mjs"))
|
|
? resolve(pkgRoot, "eslint.config.mjs")
|
|
: resolve(projectRoot, "eslint.config.mjs");
|
|
|
|
const eslint = new ESLint({cwd: pkgRoot, overrideConfigFile: configPath});
|
|
const filesToLint = await removeIgnoredFilesLegacy(pkgFiles, eslint);
|
|
|
|
if (filesToLint.length) {
|
|
commands.push(
|
|
`eslint --config ${configPath} --max-warnings=0 --fix ${filesToLint.join(" ")}`,
|
|
);
|
|
}
|
|
}
|
|
|
|
return commands;
|
|
}
|
|
|
|
return [];
|
|
},
|
|
|
|
"**/*.{html,css,scss,json,jsonc,md,mdx}": async (files) => {
|
|
return [`prettier --ignore-path .prettierignore --write ${files.join(" ")}`];
|
|
},
|
|
};
|
|
|
|
export default lintStaged;
|