Skip to content

Commit

Permalink
Update: support .eslintrc.cjs (refs eslint/rfcs#43) (#12321)
Browse files Browse the repository at this point in the history
* 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.

* Fix Documentation

* Add Tests

* Fix Lint Error
  • Loading branch information
evanplaice authored and kaicataldo committed Dec 19, 2019
1 parent 49c1658 commit acc0e47
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 1 deletion.
3 changes: 2 additions & 1 deletion docs/user-guide/configuring.md
Expand Up @@ -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.
Expand All @@ -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:
Expand Down
2 changes: 2 additions & 0 deletions lib/cli-engine/config-array-factory.js
Expand Up @@ -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",
Expand Down Expand Up @@ -279,6 +280,7 @@ function configMissingError(configName, importerName) {
function loadConfigFile(filePath) {
switch (path.extname(filePath)) {
case ".js":
case ".cjs":
return loadJSConfigFile(filePath);

case ".json":
Expand Down
5 changes: 5 additions & 0 deletions tests/fixtures/config-file/cjs/.eslintrc.cjs
@@ -0,0 +1,5 @@
module.exports = {
rules: {
semi: [2, "always"]
}
};
19 changes: 19 additions & 0 deletions tests/lib/cli-engine/config-array-factory.js
Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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: {
Expand Down

0 comments on commit acc0e47

Please sign in to comment.