Only Prettier (but not ESLint) formatting is applied to `.cjs` files
mxxk opened this issue · 7 comments
Versions:
prettier-eslint
version: 7.1.0node
version: v18.12.1npm
(oryarn
) version: 8.19.2
Have you followed the debugging tips?
Yes
Relevant code or config
example.cjs
:
module.exports = '\'none\'';`
example.js
:
export default '\'none\'';
What I did:
- Configured Prettier and ESLint to format strings using single quotes.
- Put the same literal string into
example.js
andexample.cjs
—'\'none\''
. - Ran
prettier-eslint --write
to format both files. - Ran
eslint .
to assert that the formatted files still comply with ESLint rules.
What happened:
prettier-eslint
left the string'\'none\''
inexample.js
as-is (expected).- However,
prettier-eslint
reformatted the same string inexample.cjs
to"'none'"
(unexpected). - Subsequently,
eslint
failed onexample.cjs
due to the double-quoted string.
$ npx prettier-eslint example.cjs example.js --write
success formatting 1 file with prettier-eslint
1 file was unchanged
$ npx eslint example.cjs example.js
/repo/example.cjs
1:16 error Strings must use singlequote quotes
✖ 1 problem (1 error, 0 warnings)
1 error and 0 warnings potentially fixable with the `--fix` option.
Reproduction repository:
https://github.com/mxxk-examples/prettier-eslint-issue-830
Problem description:
Though prettier-eslint
is expected to not make any formatting changes to either file, it reformats example.cjs
with a double-quoted string. This is inconsistent with ESLint configuration, which makes me suspect that only Prettier formatting is being applied to that file.
Aside 1: When Prettier and ESLint are run separately, the end result is correct
Since prettier-eslint
describes itself as
Formats your JavaScript using
prettier
followed byeslint --fix
I ran Prettier and ESLint separately to see what would happen. Interestingly, this does produce the expected result:
-
Run Prettier:
$ npx prettier --write example.cjs example.js example.cjs 22ms example.js 2ms
At this point, both files are reformatted to contain
"'none'"
, which is expected according to https://prettier.io/docs/en/options.html#quotes:- If the number of quotes outweighs the other quote, the quote which is less used will be used to format the string - Example:
"I'm double quoted"
results in"I'm double quoted"
and"This \"example\" is single quoted"
results in'This "example" is single quoted'
.
- If the number of quotes outweighs the other quote, the quote which is less used will be used to format the string - Example:
-
Run ESLint:
$ npx eslint --fix example.cjs example.js
ESLint reformats both files back to
'\'none\''
to comply with the ESLint rulequotes: ['error', 'single']
.
Aside 2: ESLint appears to ignore .cjs
files when run with .
When ESLint is run with .
as the target directory, it appears to completely ignore example.cjs
(due to the extension, I'm guessing):
$ npx prettier --write example.cjs example.js
example.cjs 22ms
example.js 2ms
$ npx eslint .
/repo/example.js
1:16 error Strings must use singlequote quotes
✖ 1 problem (1 error, 0 warnings)
1 error and 0 warnings potentially fixable with the `--fix` option.
The above output only flagged one problem with example.js
, but not example.cjs
:
$ npx eslint example.cjs
/repo/example.cjs
1:18 error Strings must use singlequote quotes
✖ 1 problem (1 error, 0 warnings)
1 error and 0 warnings potentially fixable with the `--fix` option.
Perhaps it is this discrepancy in ESLint which is causing this formatting problem to surface in prettier-eslint
, despite the explicit files being mentioned in the command-line (example.cjs
, example.js
).
Posting some more findings with regards to "Aside 2" above:
Aside 2: ESLint appears to ignore .cjs
files when run with .
After debugging via npx eslint . --debug
, this appears to be the effect of the --ext
CLI flag. Since .
is a directory target, the implicit --ext .js
takes effect and .cjs
files are ignored:
$ npx eslint . --debug
eslint:file-enumerator Didn't match: example.cjs
eslint:file-enumerator Yield: example.js
On the contrary, ESLint file targets are included unconditionally:
$ npx eslint example.cjs example.js --debug
eslint:file-enumerator File: /repo/example.cjs
eslint:file-enumerator File: /repo/example.js
Since --ext
has no direct configuration file equivalent (see eslint/eslint#2274 and eslint/eslint#11223), and the CLI docs state
- Default Value:
.js
and the files that match theoverrides
entries of your configuration.
a no-op overrides
item can be used to make ESLint consider .cjs
files:
module.exports = {
overrides: [
{ files: '*.cjs' },
],
};
This can be confirmed by rerunning eslint --debug
:
$ npx eslint . --debug
eslint:file-enumerator Yield: example.cjs
eslint:file-enumerator Yield: example.js
The prettier-eslint
issue persists, though...
I was hoping that the above change to ESLint configuration could serve as a workaround for the prettier-eslint
formatting inconsistency, but unfortunately the formatting inconsistency is still reproducible.
Stale issue
No issue activity due to lack of response from maintainers
This is still an issue, so mentioning @idahogurl @JounQin for visibility
@mxxk Try putting this in your ESLint config
extensions: '[.js',
'.jsx',
'.ts',
'.tsx',
'.cjs',
'.mjs',
'.vue']
Thanks @idahogurl, but if I understood your suggestion correctly, extensions
is not a valid top-level property in ESLint config (.eslintrc.*
). Using the repro example above,
$ npx eslint example.cjs example.js
Oops! Something went wrong! :(
ESLint: 8.31.0
Error: ESLint configuration in .eslintrc.cjs is invalid:
- Unexpected top-level property "extensions".
at ConfigValidator.validateConfigSchema (/repo/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2156:19)
at ConfigArrayFactory._normalizeConfigData (/repo/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2998:19)
at ConfigArrayFactory.loadInDirectory (/repo/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2866:33)
at CascadingConfigArrayFactory._loadConfigInAncestors (/repo/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3848:46)
at CascadingConfigArrayFactory.getConfigArrayForFile (/repo/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3769:18)
at FileEnumerator._iterateFilesWithFile (/repo/node_modules/eslint/lib/cli-engine/file-enumerator.js:368:43)
at FileEnumerator._iterateFiles (/repo/node_modules/eslint/lib/cli-engine/file-enumerator.js:349:25)
at FileEnumerator.iterateFiles (/repo/node_modules/eslint/lib/cli-engine/file-enumerator.js:299:59)
at iterateFiles.next (<anonymous>)
at CLIEngine.executeOnFiles (/repo/node_modules/eslint/lib/cli-engine/cli-engine.js:786:48)
Digging a little more, according to eslint/eslint#1674, eslint/eslint#2274, and eslint/eslint#10828, ESLint does not support a config file equivalent to passing --ext
to the ESLint CLI.