Skip to content

Commit dca7d0f

Browse files
snitin315nzakas
andauthoredFeb 1, 2024
feat: Enable eslint.config.mjs and eslint.config.cjs (#18066)
* feat: Enable eslint.config.mjs and eslint.config.cjs * Update CLI description (cherry picked from commit 8792464) * docs: update documentation for eslint.config.mjs & eslint.config.cjs support --------- Co-authored-by: Nicholas C. Zakas <nicholas@humanwhocodes.com>

File tree

15 files changed

+190
-23
lines changed

15 files changed

+190
-23
lines changed
 

‎docs/src/use/configure/configuration-files-new.md

+8-20
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,13 @@ You can put your ESLint project configuration in a configuration file. You can i
1616

1717
## Configuration File
1818

19-
The ESLint configuration file is named `eslint.config.js`. It should be placed in the root directory of your project and export an array of [configuration objects](#configuration-objects). Here's an example:
19+
The ESLint configuration file may be named any of the following:
20+
21+
* `eslint.config.js`
22+
* `eslint.config.mjs`
23+
* `eslint.config.cjs`
24+
25+
It should be placed in the root directory of your project and export an array of [configuration objects](#configuration-objects). Here's an example:
2026

2127
```js
2228
export default [
@@ -44,24 +50,6 @@ module.exports = [
4450
];
4551
```
4652

47-
The configuration file can also export a promise that resolves to the configuration array. This can be useful for using ESM dependencies in CommonJS configuration files, as in this example:
48-
49-
```js
50-
module.exports = (async () => {
51-
52-
const someDependency = await import("some-esm-dependency");
53-
54-
return [
55-
// ... use `someDependency` here
56-
];
57-
58-
})();
59-
```
60-
61-
::: warning
62-
ESLint only automatically looks for a config file named `eslint.config.js` and does not look for `eslint.config.cjs` or `eslint.config.mjs`. If you'd like to specify a different config filename than the default, use the `--config` command line option.
63-
:::
64-
6553
## Configuration Objects
6654

6755
Each configuration object contains all of the information ESLint needs to execute on a set of files. Each configuration object is made up of these properties:
@@ -668,7 +656,7 @@ export default [
668656

669657
## Configuration File Resolution
670658

671-
When ESLint is run on the command line, it first checks the current working directory for `eslint.config.js`. If the file is not found, it looks to the next parent directory for the file. This search continues until either the file is found or the root directory is reached.
659+
When ESLint is run on the command line, it first checks the current working directory for `eslint.config.js`. If that file is found, then the search stops, otherwise it checks for `eslint.config.mjs`. If that file is found, then the search stops, otherwise it checks for `eslint.config.cjs`. If none of the files are not found, it checks the parent directory for each file. This search continues until either a config file is found or the root directory is reached.
672660

673661
You can prevent this search for `eslint.config.js` by setting the `ESLINT_USE_FLAT_CONFIG` environment variable to `true` and using the `-c` or `--config` option on the command line to specify an alternate configuration file, such as:
674662

‎lib/eslint/flat-eslint.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,11 @@ const LintResultCache = require("../cli-engine/lint-result-cache");
9191
// Helpers
9292
//------------------------------------------------------------------------------
9393

94-
const FLAT_CONFIG_FILENAME = "eslint.config.js";
94+
const FLAT_CONFIG_FILENAMES = [
95+
"eslint.config.js",
96+
"eslint.config.mjs",
97+
"eslint.config.cjs"
98+
];
9599
const debug = require("debug")("eslint:flat-eslint");
96100
const removedFormatters = new Set(["table", "codeframe"]);
97101
const privateMembers = new WeakMap();
@@ -248,7 +252,7 @@ function compareResultsByFilePath(a, b) {
248252
*/
249253
function findFlatConfigFile(cwd) {
250254
return findUp(
251-
FLAT_CONFIG_FILENAME,
255+
FLAT_CONFIG_FILENAMES,
252256
{ cwd }
253257
);
254258
}

‎lib/options.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ module.exports = function(usingFlatConfig) {
168168
alias: "c",
169169
type: "path::String",
170170
description: usingFlatConfig
171-
? "Use this configuration instead of eslint.config.js"
171+
? "Use this configuration instead of eslint.config.js, eslint.config.mjs, or eslint.config.cjs"
172172
: "Use this configuration, overriding .eslintrc.* config options if present"
173173
},
174174
envFlag,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
rules: {
3+
"no-undef": "warn"
4+
}
5+
};

‎tests/fixtures/cjs-config/foo.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
foo;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports= {
2+
rules: {
3+
"no-undef": "warn"
4+
}
5+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
rules: {
3+
"no-undef": "off"
4+
}
5+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export default {
2+
rules: {
3+
"no-undef": "error"
4+
}
5+
};
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
foo;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
rules: {
3+
"no-undef": "warn"
4+
}
5+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export default {
2+
rules: {
3+
"no-undef": "error"
4+
}
5+
};

‎tests/fixtures/mjs-cjs-config/foo.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
foo;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export default {
2+
rules: {
3+
"no-undef": "error"
4+
}
5+
};

‎tests/fixtures/mjs-config/foo.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
foo;

‎tests/lib/eslint/flat-eslint.js

+136
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,73 @@ describe("FlatESLint", () => {
821821
assert.strictEqual(results[0].messages[0].severity, 2);
822822
assert.strictEqual(results[0].messages[0].ruleId, "quotes");
823823
});
824+
825+
describe("Alternate config files", () => {
826+
827+
it("should find eslint.config.mjs when present", async () => {
828+
829+
const cwd = getFixturePath("mjs-config");
830+
831+
eslint = new FlatESLint({
832+
cwd
833+
});
834+
835+
const results = await eslint.lintText("foo");
836+
837+
assert.strictEqual(results.length, 1);
838+
assert.strictEqual(results[0].messages.length, 1);
839+
assert.strictEqual(results[0].messages[0].severity, 2);
840+
assert.strictEqual(results[0].messages[0].ruleId, "no-undef");
841+
842+
});
843+
844+
it("should find eslint.config.cjs when present", async () => {
845+
846+
const cwd = getFixturePath("cjs-config");
847+
848+
eslint = new FlatESLint({
849+
cwd
850+
});
851+
852+
const results = await eslint.lintText("foo");
853+
854+
assert.strictEqual(results.length, 1);
855+
assert.strictEqual(results[0].messages.length, 1);
856+
assert.strictEqual(results[0].messages[0].severity, 1);
857+
assert.strictEqual(results[0].messages[0].ruleId, "no-undef");
858+
859+
});
860+
861+
it("should favor eslint.config.js when eslint.config.mjs and eslint.config.cjs are present", async () => {
862+
863+
const cwd = getFixturePath("js-mjs-cjs-config");
864+
865+
eslint = new FlatESLint({
866+
cwd
867+
});
868+
869+
const results = await eslint.lintText("foo");
870+
871+
assert.strictEqual(results.length, 1);
872+
assert.strictEqual(results[0].messages.length, 0);
873+
});
874+
875+
it("should favor eslint.config.mjs when eslint.config.cjs is present", async () => {
876+
877+
const cwd = getFixturePath("mjs-cjs-config");
878+
879+
eslint = new FlatESLint({
880+
cwd
881+
});
882+
883+
const results = await eslint.lintText("foo");
884+
885+
assert.strictEqual(results.length, 1);
886+
assert.strictEqual(results[0].messages.length, 1);
887+
assert.strictEqual(results[0].messages[0].severity, 2);
888+
assert.strictEqual(results[0].messages[0].ruleId, "no-undef");
889+
});
890+
});
824891
});
825892

826893
describe("lintFiles()", () => {
@@ -4110,6 +4177,75 @@ describe("FlatESLint", () => {
41104177
await assert.rejects(() => eslint.lintFiles(777), /'patterns' must be a non-empty string or an array of non-empty strings/u);
41114178
await assert.rejects(() => eslint.lintFiles([null]), /'patterns' must be a non-empty string or an array of non-empty strings/u);
41124179
});
4180+
4181+
describe("Alternate config files", () => {
4182+
4183+
it("should find eslint.config.mjs when present", async () => {
4184+
4185+
const cwd = getFixturePath("mjs-config");
4186+
4187+
eslint = new FlatESLint({
4188+
cwd
4189+
});
4190+
4191+
const results = await eslint.lintFiles("foo.js");
4192+
4193+
assert.strictEqual(results.length, 1);
4194+
assert.strictEqual(results[0].messages.length, 1);
4195+
assert.strictEqual(results[0].messages[0].severity, 2);
4196+
assert.strictEqual(results[0].messages[0].ruleId, "no-undef");
4197+
4198+
});
4199+
4200+
it("should find eslint.config.cjs when present", async () => {
4201+
4202+
const cwd = getFixturePath("cjs-config");
4203+
4204+
eslint = new FlatESLint({
4205+
cwd
4206+
});
4207+
4208+
const results = await eslint.lintFiles("foo.js");
4209+
4210+
assert.strictEqual(results.length, 1);
4211+
assert.strictEqual(results[0].messages.length, 1);
4212+
assert.strictEqual(results[0].messages[0].severity, 1);
4213+
assert.strictEqual(results[0].messages[0].ruleId, "no-undef");
4214+
4215+
});
4216+
4217+
it("should favor eslint.config.js when eslint.config.mjs and eslint.config.cjs are present", async () => {
4218+
4219+
const cwd = getFixturePath("js-mjs-cjs-config");
4220+
4221+
eslint = new FlatESLint({
4222+
cwd
4223+
});
4224+
4225+
const results = await eslint.lintFiles("foo.js");
4226+
4227+
assert.strictEqual(results.length, 1);
4228+
assert.strictEqual(results[0].messages.length, 0);
4229+
});
4230+
4231+
it("should favor eslint.config.mjs when eslint.config.cjs is present", async () => {
4232+
4233+
const cwd = getFixturePath("mjs-cjs-config");
4234+
4235+
eslint = new FlatESLint({
4236+
cwd
4237+
});
4238+
4239+
const results = await eslint.lintFiles("foo.js");
4240+
4241+
assert.strictEqual(results.length, 1);
4242+
assert.strictEqual(results[0].messages.length, 1);
4243+
assert.strictEqual(results[0].messages[0].severity, 2);
4244+
assert.strictEqual(results[0].messages[0].ruleId, "no-undef");
4245+
});
4246+
});
4247+
4248+
41134249
});
41144250

41154251
describe("Fix Types", () => {

0 commit comments

Comments
 (0)
Please sign in to comment.