From 02d46461fccd6a7666696c9bacf18ba8f064bfb6 Mon Sep 17 00:00:00 2001 From: Evan Plaice Date: Thu, 26 Sep 2019 18:19:10 -0600 Subject: [PATCH 1/4] Fix: ES module compatibility (fixes #12319) In ES module packages w/ "type": "module" defined treat all .js files as ES modules. CommonJS files contained in an ES module package should use the .cjs extension. --- docs/user-guide/configuring.md | 3 +++ lib/cli-engine/config-array-factory.js | 2 ++ 2 files changed, 5 insertions(+) diff --git a/docs/user-guide/configuring.md b/docs/user-guide/configuring.md index 5022fc44d8e..c788a28cea7 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)** - same as `.eslintrc.js` but used with ES module packages * **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,12 +673,14 @@ 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` +**Note:** JavaScript (ESM) is for use with JavaScript packages that specify `"type":"module"` in `package.json`. ## Configuration Cascading and Hierarchy 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": From 647feca21edeec7471a96bbf2d8cb97988da7a40 Mon Sep 17 00:00:00 2001 From: Evan Plaice Date: Tue, 17 Dec 2019 21:24:53 -0700 Subject: [PATCH 2/4] Fix Documentation --- docs/user-guide/configuring.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/user-guide/configuring.md b/docs/user-guide/configuring.md index c788a28cea7..2a47a3e9e3d 100644 --- a/docs/user-guide/configuring.md +++ b/docs/user-guide/configuring.md @@ -664,7 +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)** - same as `.eslintrc.js` but used with ES module packages +* **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. @@ -680,8 +680,6 @@ If there are multiple configuration files in the same directory, ESLint will onl 1. `.eslintrc` 1. `package.json` -**Note:** JavaScript (ESM) is for use with JavaScript packages that specify `"type":"module"` in `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: From e4d8970ff06d733c512abbbf08d30dac3b5a886e Mon Sep 17 00:00:00 2001 From: Evan Plaice Date: Tue, 17 Dec 2019 22:15:05 -0700 Subject: [PATCH 3/4] Add Tests --- tests/fixtures/config-file/cjs/.eslintrc.cjs | 5 +++++ tests/lib/cli-engine/config-array-factory.js | 21 +++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 tests/fixtures/config-file/cjs/.eslintrc.cjs 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..12252dd9f01 100644 --- a/tests/lib/cli-engine/config-array-factory.js +++ b/tests/lib/cli-engine/config-array-factory.js @@ -171,12 +171,13 @@ 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", "package-json/package.json": "{ \"eslintConfig\": { \"settings\": { \"name\": \"package-json/package.json\" } } }", "yml/.eslintrc.yml": "settings:\n name: yml/.eslintrc.yml", - "yaml/.eslintrc.yaml": "settings:\n name: yaml/.eslintrc.yaml" + "yaml/.eslintrc.yaml": "settings:\n name: yaml/.eslintrc.yaml", }; const { ConfigArrayFactory } = defineConfigArrayFactoryWithInMemoryFileSystem({ cwd: () => tempDir, @@ -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: { From b78bfc3fbe6e8119a7f29cf152b25f6d89f34a7a Mon Sep 17 00:00:00 2001 From: Evan Plaice Date: Tue, 17 Dec 2019 22:21:19 -0700 Subject: [PATCH 4/4] Fix Lint Error --- tests/lib/cli-engine/config-array-factory.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/lib/cli-engine/config-array-factory.js b/tests/lib/cli-engine/config-array-factory.js index 12252dd9f01..1fb5661fb4d 100644 --- a/tests/lib/cli-engine/config-array-factory.js +++ b/tests/lib/cli-engine/config-array-factory.js @@ -177,7 +177,7 @@ describe("ConfigArrayFactory", () => { "legacy-yml/.eslintrc": "settings:\n name: legacy-yml/.eslintrc", "package-json/package.json": "{ \"eslintConfig\": { \"settings\": { \"name\": \"package-json/package.json\" } } }", "yml/.eslintrc.yml": "settings:\n name: yml/.eslintrc.yml", - "yaml/.eslintrc.yaml": "settings:\n name: yaml/.eslintrc.yaml", + "yaml/.eslintrc.yaml": "settings:\n name: yaml/.eslintrc.yaml" }; const { ConfigArrayFactory } = defineConfigArrayFactoryWithInMemoryFileSystem({ cwd: () => tempDir,