From f79d4f62dac9b51c0fa1ac2edeff34b25a5e8581 Mon Sep 17 00:00:00 2001 From: neverland Date: Wed, 13 May 2026 13:50:46 +0800 Subject: [PATCH] fix: support absolute eslintPath file paths --- src/getESLint.js | 25 +++++++++++++++++++++++-- test/eslint-path.test.js | 11 +++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/getESLint.js b/src/getESLint.js index 997aca0..fb4d63b 100644 --- a/src/getESLint.js +++ b/src/getESLint.js @@ -1,4 +1,5 @@ import { createRequire } from 'node:module'; +import path from 'node:path'; import { pathToFileURL } from 'node:url'; import { getESLintOptions } from './options.js'; @@ -62,6 +63,10 @@ async function getESLint(options) { * @returns {Promise>} */ async function loadESLintModule(specifier) { + if (isAbsolutePathSpecifier(specifier)) { + return loadResolvedModule(specifier); + } + try { // Prefer native ESM resolution for package specifiers so conditional // exports use the import-compatible entry. @@ -73,11 +78,27 @@ async function loadESLintModule(specifier) { // Fall back to CommonJS resolution only for legacy path-style eslintPath // values, such as directories that ESM import cannot resolve directly. - const resolvedPath = moduleRequire.resolve(specifier); - return normalizeModule(await import(pathToFileURL(resolvedPath).href)); + return loadResolvedModule(specifier); } } +/** + * @param {string} specifier + * @returns {Promise>} + */ +async function loadResolvedModule(specifier) { + const resolvedPath = moduleRequire.resolve(specifier); + return normalizeModule(await import(pathToFileURL(resolvedPath).href)); +} + +/** + * @param {string} specifier + * @returns {boolean} + */ +function isAbsolutePathSpecifier(specifier) { + return path.isAbsolute(specifier) || path.win32.isAbsolute(specifier); +} + /** * @param {unknown} error * @returns {boolean} diff --git a/test/eslint-path.test.js b/test/eslint-path.test.js index 181c004..7884d5b 100644 --- a/test/eslint-path.test.js +++ b/test/eslint-path.test.js @@ -15,6 +15,17 @@ describe('eslint path', () => { expect(stats.compilation.errors[0].message).toContain('Fake error'); }); + it('should use eslint from an absolute file path', async () => { + const eslintPath = join(import.meta.dirname, 'mock/eslint/index.js'); + + const { eslint } = await getESLint({ + eslintPath, + configType: 'flat', + }); + + expect(eslint).toBeTruthy(); + }); + it('should fail with a clear error when eslintPath does not export loadESLint', async () => { const eslintPath = join(import.meta.dirname, 'mock/eslint-no-load');