Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

One config to rule them all #175

Merged
merged 4 commits into from Feb 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 9 additions & 10 deletions .eslintrc.base.js
Expand Up @@ -3,7 +3,7 @@
// This file is only used in `./.eslintrc.js` and in the tests – it’s not part
// of the eslint-config-prettier npm package.

const fs = require("fs");
const config = require(".");

module.exports = {
extends: [
Expand All @@ -15,13 +15,12 @@ module.exports = {
],
plugins: [
"prettier",
...fs
.readdirSync(__dirname)
.filter(
(file) =>
!file.startsWith(".") && file.endsWith(".js") && file !== "index.js"
)
.map((ruleFileName) => ruleFileName.replace(/\.js$/, "")),
...new Set(
Object.keys(config.rules)
.map((ruleName) => ruleName.split("/"))
.filter((parts) => parts.length > 1)
.map((parts) => parts[0])
),
],
parserOptions: {
parser: "babel-eslint",
Expand All @@ -38,10 +37,10 @@ module.exports = {
node: true,
},
rules: {
indent: "off",
"indent": "off",
"linebreak-style": "off",
"no-dupe-keys": "error",
strict: "error",
"strict": "error",
"prefer-spread": "off",
"require-jsdoc": "off",
"prettier/prettier": "error",
Expand Down
12 changes: 2 additions & 10 deletions .eslintrc.js
Expand Up @@ -6,16 +6,8 @@
// as an “eat your own dogfood” test. That feels like a good test, but
// complicates things a little sometimes.

const fs = require("fs");

module.exports = {
extends: [
"./.eslintrc.base.js",
...fs
.readdirSync(__dirname)
.filter((file) => !file.startsWith(".") && file.endsWith(".js"))
.map((ruleFileName) => `./${ruleFileName}`),
],
extends: ["./.eslintrc.base.js", "./index.js", "./prettier.js"],
rules: {
"prettier/prettier": "off",
},
Expand All @@ -32,7 +24,7 @@ module.exports = {
"The comma operator is confusing and a common mistake. Don’t use it!",
},
],
quotes: [
"quotes": [
"error",
"double",
{ avoidEscape: true, allowTemplateLiterals: false },
Expand Down
3 changes: 2 additions & 1 deletion .prettierrc.json
@@ -1,3 +1,4 @@
{
"proseWrap": "never"
"proseWrap": "never",
"quoteProps": "consistent"
}
22 changes: 0 additions & 22 deletions @typescript-eslint.js

This file was deleted.

54 changes: 8 additions & 46 deletions README.md
Expand Up @@ -57,7 +57,7 @@ Then, add eslint-config-prettier to the "extends" array in your `.eslintrc.*` fi
}
```

A few ESLint plugins are supported as well:
That’s it! Extending `"prettier"` turns off a bunch of core ESLint rules, as well as a few rules from these plugins:

- [@typescript-eslint/eslint-plugin]
- [eslint-plugin-babel]
Expand All @@ -68,40 +68,7 @@ A few ESLint plugins are supported as well:
- [eslint-plugin-unicorn]
- [eslint-plugin-vue]

Add extra exclusions for the plugins you use like so:

<!-- prettier-ignore -->
```json
{
"extends": [
"some-other-config-you-use",
"prettier",
"prettier/@typescript-eslint",
"prettier/babel",
"prettier/flowtype",
"prettier/prettier",
"prettier/react",
"prettier/standard",
"prettier/unicorn",
"prettier/vue"
]
}
```

If you extend a config which uses a plugin, it is recommended to add `"prettier/that-plugin"` (if available). For example, [eslint-config-airbnb] enables [eslint-plugin-react] rules, so `"prettier/react"` is needed:

<!-- prettier-ignore -->
```json
{
"extends": [
"airbnb",
"prettier",
"prettier/react"
]
}
```

If you’re unsure which plugins are used, you can usually find them in your `package.json`.
> Note: You might find guides on the Internet saying you should also extend stuff like `"prettier/react"`. Since version 8.0.0 of eslint-config-prettier, all you need to extend is `"prettier"`! That includes all plugins.

### Excluding deprecated rules

Expand Down Expand Up @@ -163,14 +130,16 @@ For maximum ease of use, the special rules are disabled by default (provided tha

**These rules might cause problems if using [eslint-plugin-prettier] and `--fix`.**

See [`arrow-body-style` and `prefer-arrow-callback` issue][eslint-plugin-prettier-autofix-issue] for details.
See the [`arrow-body-style` and `prefer-arrow-callback` issue][eslint-plugin-prettier-autofix-issue] for details.

There are a couple of ways to turn these rules off:

- Put `"prettier/prettier"` in your `"extends"`. (Yes, there’s both a _rule_ called `"prettier/prettier"` and a _config_ called `"prettier/prettier"`.)
- Use [eslint-plugin-prettier’s recommended config][eslint-plugin-prettier-recommended], which also turns off these two rules.
- Remove them from your config or turn them off manually.

It doesn’t matter which approach you use – they’re all the same.

Note: The CLI tool only reports these as problematic if the `"prettier/prettier"` _rule_ is enabled for the same file.

These rules are safe to use if you don’t use [eslint-plugin-prettier]. In other words, if you run `eslint --fix` and `prettier --write` as separate steps.
Expand Down Expand Up @@ -698,17 +667,11 @@ Have new rules been added since those versions? Have we missed any rules? Is the

If you’d like to add support for eslint-plugin-foobar, this is how you’d go about it:

First, create `foobar.js`:
First, add rules to `index.js`:

<!-- prettier-ignore -->
```js
"use strict";

module.exports = {
rules: {
"foobar/some-rule": "off"
}
};
"foobar/some-rule": "off"
```

Then, create `test-lint/foobar.js`:
Expand All @@ -729,7 +692,7 @@ Finally, you need to mention the plugin in several places:

- Add eslint-plugin-foobar to the "devDependencies" field in `package.json`.
- Make sure that at least one rule from eslint-plugin-foobar gets used in `.eslintrc.base.js`.
- Add it to the list of supported plugins and to the Contributing section in `README.md`.
- Add it to the lists of supported plugins and in this `README.md`.

When you’re done, run `npm test` to verify that you got it all right. It runs several other npm scripts:

Expand All @@ -751,7 +714,6 @@ When you’re done, run `npm test` to verify that you got it all right. It runs
[arrow-body-style]: https://eslint.org/docs/rules/arrow-body-style
[babel/quotes]: https://github.com/babel/eslint-plugin-babel#rules
[curly]: https://eslint.org/docs/rules/curly
[eslint-config-airbnb]: https://www.npmjs.com/package/eslint-config-airbnb
[eslint-plugin-babel]: https://github.com/babel/eslint-plugin-babel
[eslint-plugin-flowtype]: https://github.com/gajus/eslint-plugin-flowtype
[eslint-plugin-prettier-autofix-issue]: https://github.com/prettier/eslint-plugin-prettier#arrow-body-style-and-prefer-arrow-callback-issue
Expand Down
10 changes: 0 additions & 10 deletions babel.js

This file was deleted.

97 changes: 52 additions & 45 deletions bin/cli.js
Expand Up @@ -2,9 +2,9 @@

"use strict";

const fs = require("fs");
const path = require("path");
const validators = require("./validators");
const config = require("..");
const prettier = require("../prettier");

// Require locally installed eslint, for `npx eslint-config-prettier` support
// with no local eslint-config-prettier installation.
Expand All @@ -15,6 +15,9 @@ const { ESLint } = require(require.resolve("eslint", {
const SPECIAL_RULES_URL =
"https://github.com/prettier/eslint-config-prettier#special-rules";

const PRETTIER_RULES_URL =
"https://github.com/prettier/eslint-config-prettier#arrow-body-style-and-prefer-arrow-callback";

if (module === require.main) {
const args = process.argv.slice(2);

Expand All @@ -28,8 +31,8 @@ if (module === require.main) {
Promise.all(args.map((file) => eslint.calculateConfigForFile(file)))
.then((configs) => {
const rules = [].concat(
...configs.map((config, index) =>
Object.entries(config.rules).map((entry) => [...entry, args[index]])
...configs.map(({ rules }, index) =>
Object.entries(rules).map((entry) => [...entry, args[index]])
)
);
const result = processRules(rules);
Expand Down Expand Up @@ -68,24 +71,13 @@ https://github.com/prettier/eslint-config-prettier#cli-helper-tool
}

function processRules(configRules) {
// This used to look at "files" in package.json, but that is not reliable due
// to an npm bug. See:
// https://github.com/prettier/eslint-config-prettier/issues/57
const allRules = Object.assign(
Object.create(null),
...fs
.readdirSync(path.join(__dirname, ".."))
.filter((name) => !name.startsWith(".") && name.endsWith(".js"))
.map((ruleFileName) => require(`../${ruleFileName}`).rules)
);

const regularRules = filterRules(allRules, (_, value) => value === "off");
const regularRules = filterRules(config.rules, (_, value) => value === "off");
const optionsRules = filterRules(
allRules,
config.rules,
(ruleName, value) => value === 0 && ruleName in validators
);
const specialRules = filterRules(
allRules,
config.rules,
(ruleName, value) => value === 0 && !(ruleName in validators)
);

Expand All @@ -99,7 +91,7 @@ function processRules(configRules) {
.filter(Boolean);

const flaggedRules = enabledRules.filter(
({ ruleName }) => ruleName in allRules
({ ruleName }) => ruleName in config.rules
);

const regularFlaggedRuleNames = filterRuleNames(
Expand All @@ -109,37 +101,21 @@ function processRules(configRules) {
const optionsFlaggedRuleNames = filterRuleNames(
flaggedRules,
({ ruleName, ...rule }) =>
ruleName in optionsRules && !validators[ruleName](rule, enabledRules)
ruleName in optionsRules && !validators[ruleName](rule)
);
const specialFlaggedRuleNames = filterRuleNames(
flaggedRules,
({ ruleName }) => ruleName in specialRules
);

if (
regularFlaggedRuleNames.length === 0 &&
optionsFlaggedRuleNames.length === 0
) {
const baseMessage =
"No rules that are unnecessary or conflict with Prettier were found.";

const message =
specialFlaggedRuleNames.length === 0
? baseMessage
: [
baseMessage,
"",
"However, the following rules are enabled but cannot be automatically checked. See:",
SPECIAL_RULES_URL,
"",
printRuleNames(specialFlaggedRuleNames),
].join("\n");

return {
stdout: message,
code: 0,
};
}
const prettierFlaggedRuleNames = filterRuleNames(
enabledRules,
({ ruleName, source }) =>
ruleName in prettier.rules &&
enabledRules.some(
(rule) =>
rule.ruleName === "prettier/prettier" && rule.source === source
)
);

const regularMessage = [
"The following rules are unnecessary or might conflict with Prettier:",
Expand All @@ -161,10 +137,41 @@ function processRules(configRules) {
printRuleNames(specialFlaggedRuleNames),
].join("\n");

const prettierMessage = [
"The following rules can cause issues when using eslint-plugin-prettier at the same time.",
"Only enable them if you know what you are doing! See:",
PRETTIER_RULES_URL,
"",
printRuleNames(prettierFlaggedRuleNames),
].join("\n");

if (
regularFlaggedRuleNames.length === 0 &&
optionsFlaggedRuleNames.length === 0
) {
const message =
specialFlaggedRuleNames.length === 0 &&
prettierFlaggedRuleNames.length === 0
? "No rules that are unnecessary or conflict with Prettier were found."
: [
specialFlaggedRuleNames.length === 0 ? null : specialMessage,
prettierFlaggedRuleNames.length === 0 ? null : prettierMessage,
"Other than that, no rules that are unnecessary or conflict with Prettier were found.",
]
.filter(Boolean)
.join("\n\n");

return {
stdout: message,
code: 0,
};
}

const message = [
regularFlaggedRuleNames.length === 0 ? null : regularMessage,
optionsFlaggedRuleNames.length === 0 ? null : optionsMessage,
specialFlaggedRuleNames.length === 0 ? null : specialMessage,
prettierFlaggedRuleNames.length === 0 ? null : prettierMessage,
]
.filter(Boolean)
.join("\n\n");
Expand Down