diff --git a/docs/user-guide/configuring.md b/docs/user-guide/configuring.md index 5022fc44d8e..2a47a3e9e3d 100644 --- a/docs/user-guide/configuring.md +++ b/docs/user-guide/configuring.md @@ -664,6 +664,7 @@ In each case, the settings in the configuration file override default settings. ESLint supports configuration files in several formats: * **JavaScript** - use `.eslintrc.js` and export an object containing your configuration. +* **JavaScript (ESM)** - use `.eslintrc.cjs` when running ESLint in JavaScript packages that specify `"type":"module"` in their `package.json`. Note that ESLint does not support ESM configuration at this time. * **YAML** - use `.eslintrc.yaml` or `.eslintrc.yml` to define the configuration structure. * **JSON** - use `.eslintrc.json` to define the configuration structure. ESLint's JSON files also allow JavaScript-style comments. * **Deprecated** - use `.eslintrc`, which can be either JSON or YAML. @@ -672,13 +673,13 @@ ESLint supports configuration files in several formats: If there are multiple configuration files in the same directory, ESLint will only use one. The priority order is: 1. `.eslintrc.js` +1. `.eslintrc.cjs` 1. `.eslintrc.yaml` 1. `.eslintrc.yml` 1. `.eslintrc.json` 1. `.eslintrc` 1. `package.json` - ## Configuration Cascading and Hierarchy When using `.eslintrc.*` and `package.json` files for configuration, you can take advantage of configuration cascading. For instance, suppose you have the following structure: diff --git a/lib/cli-engine/config-array-factory.js b/lib/cli-engine/config-array-factory.js index c444031bcb0..76c4ccd7021 100644 --- a/lib/cli-engine/config-array-factory.js +++ b/lib/cli-engine/config-array-factory.js @@ -62,6 +62,7 @@ const eslintRecommendedPath = path.resolve(__dirname, "../../conf/eslint-recomme const eslintAllPath = path.resolve(__dirname, "../../conf/eslint-all.js"); const configFilenames = [ ".eslintrc.js", + ".eslintrc.cjs", ".eslintrc.yaml", ".eslintrc.yml", ".eslintrc.json", @@ -279,6 +280,7 @@ function configMissingError(configName, importerName) { function loadConfigFile(filePath) { switch (path.extname(filePath)) { case ".js": + case ".cjs": return loadJSConfigFile(filePath); case ".json": diff --git a/tests/fixtures/config-file/cjs/.eslintrc.cjs b/tests/fixtures/config-file/cjs/.eslintrc.cjs new file mode 100644 index 00000000000..b3100591dcb --- /dev/null +++ b/tests/fixtures/config-file/cjs/.eslintrc.cjs @@ -0,0 +1,5 @@ +module.exports = { + rules: { + semi: [2, "always"] + } +}; diff --git a/tests/lib/cli-engine/config-array-factory.js b/tests/lib/cli-engine/config-array-factory.js index 4f3ade1e60a..1fb5661fb4d 100644 --- a/tests/lib/cli-engine/config-array-factory.js +++ b/tests/lib/cli-engine/config-array-factory.js @@ -171,6 +171,7 @@ describe("ConfigArrayFactory", () => { describe("'loadFile(filePath, options)' method should load a config file.", () => { const basicFiles = { "js/.eslintrc.js": "exports.settings = { name: 'js/.eslintrc.js' }", + "cjs/.eslintrc.cjs": "exports.settings = { name: 'cjs/.eslintrc.cjs' }", "json/.eslintrc.json": "{ \"settings\": { \"name\": \"json/.eslintrc.json\" } }", "legacy-json/.eslintrc": "{ \"settings\": { \"name\": \"legacy-json/.eslintrc\" } }", "legacy-yml/.eslintrc": "settings:\n name: legacy-yml/.eslintrc", @@ -288,6 +289,7 @@ describe("ConfigArrayFactory", () => { describe("'loadInDirectory(directoryPath, options)' method should load the config file of a directory.", () => { const basicFiles = { "js/.eslintrc.js": "exports.settings = { name: 'js/.eslintrc.js' }", + "cjs/.eslintrc.cjs": "exports.settings = { name: 'cjs/.eslintrc.cjs' }", "json/.eslintrc.json": "{ \"settings\": { \"name\": \"json/.eslintrc.json\" } }", "legacy-json/.eslintrc": "{ \"settings\": { \"name\": \"legacy-json/.eslintrc\" } }", "legacy-yml/.eslintrc": "settings:\n name: legacy-yml/.eslintrc", @@ -1497,6 +1499,7 @@ describe("ConfigArrayFactory", () => { "node_modules/eslint-plugin-invalid-parser/index.js": "exports.configs = { foo: { parser: 'nonexistent-parser' } }", "node_modules/eslint-plugin-invalid-config/index.js": "exports.configs = { foo: {} }", "js/.eslintrc.js": "module.exports = { rules: { semi: [2, 'always'] } };", + "cjs/.eslintrc.cjs": "module.exports = { rules: { semi: [2, 'always'] } };", "json/.eslintrc.json": "{ \"rules\": { \"quotes\": [2, \"double\"] } }", "package-json/package.json": "{ \"eslintConfig\": { \"env\": { \"es6\": true } } }", "yaml/.eslintrc.yaml": "env:\n browser: true" @@ -1747,6 +1750,22 @@ describe("ConfigArrayFactory", () => { }); }); + it("should load information from a JavaScript file with a .cjs extension", () => { + const { ConfigArrayFactory } = defineConfigArrayFactoryWithInMemoryFileSystem({ + files: { + "cjs/.eslintrc.cjs": "module.exports = { rules: { semi: [2, 'always'] } };" + } + }); + const factory = new ConfigArrayFactory(); + const config = load(factory, "cjs/.eslintrc.cjs"); + + assertConfig(config, { + rules: { + semi: [2, "always"] + } + }); + }); + it("should throw error when loading invalid JavaScript file", () => { const { ConfigArrayFactory } = defineConfigArrayFactoryWithInMemoryFileSystem({ files: {