Installing dependencies.
This commit is contained in:
+4
@@ -0,0 +1,4 @@
|
||||
# CHANGELOG
|
||||
|
||||
The changelog is automatically updated using [semantic-release](https://github.com/semantic-release/semantic-release).
|
||||
You can see it on the [releases page](../../releases).
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2016 Kent C. Dodds
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+358
@@ -0,0 +1,358 @@
|
||||
# prettier-eslint
|
||||
|
||||
Formats your JavaScript using [`prettier`][prettier] followed by [`eslint --fix`][eslint]
|
||||
|
||||
[![Build Status][build-badge]][build]
|
||||
[![Code Coverage][coverage-badge]][coverage]
|
||||
[![version][version-badge]][package] [![downloads][downloads-badge]][npm-stat]
|
||||
[![MIT License][license-badge]][license]
|
||||
|
||||
[](#contributors-)
|
||||
[![PRs Welcome][prs-badge]][prs] [![Donate][donate-badge]][donate]
|
||||
[![Code of Conduct][coc-badge]][coc] [![Roadmap][roadmap-badge]][roadmap]
|
||||
[![Examples][examples-badge]][examples]
|
||||
|
||||
[![Watch on GitHub][github-watch-badge]][github-watch]
|
||||
[![Star on GitHub][github-star-badge]][github-star]
|
||||
[![Tweet][twitter-badge]][twitter]
|
||||
|
||||
## The problem
|
||||
|
||||
The [`fix`][fix] feature of [`eslint`][eslint] is pretty great and can
|
||||
auto-format/fix much of your code according to your ESLint config.
|
||||
[`prettier`][prettier] is a more powerful automatic formatter. One of the nice
|
||||
things about prettier is how opinionated it is. Unfortunately, it's not
|
||||
opinionated enough and/or some opinions differ from my own. So after prettier
|
||||
formats the code, I start getting linting errors.
|
||||
|
||||
## This solution
|
||||
|
||||
This formats your code via `prettier`, and then passes the result of that to
|
||||
`eslint --fix`. This way you can get the benefits of `prettier`'s superior
|
||||
formatting capabilities, but also benefit from the configuration capabilities of
|
||||
`eslint`.
|
||||
|
||||
> For files with an extension of `.css`, `.less`, `.scss`, or `.json` this only
|
||||
> runs `prettier` since `eslint` cannot process those.
|
||||
|
||||
## Installation
|
||||
|
||||
This module is distributed via [npm][npm] which is bundled with [node][node] and
|
||||
should be installed as one of your project's `devDependencies`:
|
||||
|
||||
```
|
||||
npm install --save-dev prettier-eslint
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Example
|
||||
|
||||
```javascript
|
||||
const format = require("prettier-eslint");
|
||||
|
||||
// notice, no semicolon in the original text
|
||||
const sourceCode = "const {foo} = bar";
|
||||
|
||||
const options = {
|
||||
text: sourceCode,
|
||||
eslintConfig: {
|
||||
parserOptions: {
|
||||
ecmaVersion: 7,
|
||||
},
|
||||
rules: {
|
||||
semi: ["error", "never"],
|
||||
},
|
||||
},
|
||||
prettierOptions: {
|
||||
bracketSpacing: true,
|
||||
},
|
||||
fallbackPrettierOptions: {
|
||||
singleQuote: false,
|
||||
},
|
||||
};
|
||||
|
||||
const formatted = await format(options);
|
||||
|
||||
// notice no semicolon in the formatted text
|
||||
formatted; // const { foo } = bar
|
||||
```
|
||||
|
||||
### options
|
||||
|
||||
#### text (String)
|
||||
|
||||
The source code to format.
|
||||
|
||||
#### filePath (?String)
|
||||
|
||||
The path of the file being formatted can be used to override `eslintConfig`
|
||||
(eslint will be used to find the relevant config for the file).
|
||||
|
||||
#### eslintConfig (?Object)
|
||||
|
||||
The config to use for formatting with ESLint. Can be overridden with `filePath`.
|
||||
|
||||
#### prettierOptions (?Object)
|
||||
|
||||
The options to pass for formatting with `prettier`. If not provided,
|
||||
`prettier-eslint` will attempt to create the options based on the `eslintConfig`
|
||||
(whether that's provided or derived via `filePath`). You can also provide _some_
|
||||
of the options and have the remaining options derived via your eslint config.
|
||||
This is useful for options like `parser`.
|
||||
|
||||
**NOTE:** these options _override_ the eslint config. If you want the fallback
|
||||
options to be used only in the case that the rule cannot be inferred from
|
||||
eslint, see "fallbackPrettierOptions" below.
|
||||
|
||||
#### fallbackPrettierOptions (?Object)
|
||||
|
||||
The options to pass for formatting with `prettier` if `prettier-eslint` is not
|
||||
able to create the options based on the the `eslintConfig` (whether that's
|
||||
provided or derived via `filePath`). These options will only be used in the case
|
||||
that the corresponding eslint rule cannot be found and the prettier option has
|
||||
not been manually defined in `prettierOptions`. If the fallback is not given,
|
||||
`prettier-eslint` will just use the default `prettier` value in this scenario.
|
||||
|
||||
#### logLevel (?Enum: ['trace', 'debug', 'info', 'warn', 'error', 'silent'])
|
||||
|
||||
`prettier-eslint` does quite a bit of logging if you want it to. Pass this to
|
||||
set the number of logs you want to see. Default is `process.env.LOG_LEVEL || 'warn'`.
|
||||
|
||||
#### eslintPath (?String)
|
||||
|
||||
By default, `prettier-eslint` will try to find the relevant `eslint` (and
|
||||
`prettier`) module based on the `filePath`. If it cannot find one, then it will
|
||||
use the version that `prettier-eslint` has installed locally. If you'd like to
|
||||
specify a path to the `eslint` module you would like to have `prettier-eslint`
|
||||
use, then you can provide the full path to it with the `eslintPath` option.
|
||||
|
||||
#### prettierPath (?String)
|
||||
|
||||
This is basically the same as `eslintPath` except for the `prettier` module.
|
||||
|
||||
#### prettierLast (?Boolean)
|
||||
|
||||
By default, `prettier-eslint` will run `prettier` first, then `eslint --fix`.
|
||||
This is great if you want to use `prettier`, but override some of the styles you
|
||||
don't like using `eslint --fix`.
|
||||
|
||||
An alternative approach is to use different tools for different concerns. If you
|
||||
provide `prettierLast: true`, it will run `eslint --fix` first, then `prettier`.
|
||||
This allows you to use `eslint` to look for bugs and/or bad practices, and use
|
||||
`prettier` to enforce code style.
|
||||
|
||||
### throws
|
||||
|
||||
`prettier-eslint` will **only** propagate _parsing_ errors when either `prettier` or `eslint` fails. In addition to propagating the errors, it will also log a specific message indicating what it was doing at the time of the failure.
|
||||
|
||||
**Note:** `prettier-eslint` will not show any message regarding broken rules in either `prettier` or `eslint`.
|
||||
|
||||
## Technical details
|
||||
|
||||
> Code ➡️ prettier ➡️ eslint --fix ➡️ Formatted Code ✨
|
||||
|
||||
### inferring prettierOptions via eslintConfig
|
||||
|
||||
The `eslintConfig` and `prettierOptions` can each be provided as an argument. If
|
||||
the `eslintConfig` is not provided, then `prettier-eslint` will look for them
|
||||
based on the `fileName` (if no `fileName` is provided then it uses
|
||||
`process.cwd()`). Once `prettier-eslint` has found the `eslintConfig`, the
|
||||
`prettierOptions` are inferred from the `eslintConfig`. If some of the
|
||||
`prettierOptions` have already been provided, then `prettier-eslint` will only
|
||||
infer the remaining options. This inference happens in `src/utils.js`.
|
||||
|
||||
**An important thing to note** about this inference is that it may not support
|
||||
your specific eslint config. So you'll want to check `src/utils.js` to see how
|
||||
the inference is done for each option (what rule(s) are referenced, etc.) and
|
||||
[make a pull request][prs] if your configuration is supported.
|
||||
|
||||
**Defaults** if you have all of the relevant ESLint rules disabled (or have
|
||||
ESLint disabled entirely via `/* eslint-disable */` then prettier options will
|
||||
fall back to the `prettier` defaults:
|
||||
|
||||
```javascript
|
||||
{
|
||||
printWidth: 80,
|
||||
tabWidth: 2,
|
||||
singleQuote: false,
|
||||
trailingComma: 'none',
|
||||
bracketSpacing: true,
|
||||
semi: true,
|
||||
useTabs: false,
|
||||
// prettier-eslint doesn't currently support
|
||||
// inferring these two (Pull Requests welcome):
|
||||
parser: 'babylon',
|
||||
bracketSameLine: false,
|
||||
}
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### debugging issues
|
||||
|
||||
There is a lot of logging available with `prettier-eslint`. When debugging, you
|
||||
can use one of the
|
||||
[`logLevel`](#loglevel-enum-trace-debug-info-warn-error-silent)s to get a better
|
||||
idea of what's going on. If you're using `prettier-eslint-cli` then you can use
|
||||
the `--log-level trace`, if you're using [the Atom plugin][atom-plugin], then
|
||||
you can [open the developer tools][atom-dev-tools] and enter:
|
||||
`process.env.LOG_LEVEL = 'trace'` in the console, then run the format. You'll
|
||||
see a bunch of logs that should help you determine whether the problem is
|
||||
`prettier`, `eslint --fix`, how `prettier-eslint` infers your `prettier`
|
||||
options, or any number of other things. You will be asked to do this before
|
||||
filing issues, so please do :smile:
|
||||
|
||||
> NOTE: When you're doing this, it's recommended that you only run this on a
|
||||
> single file because there are a LOT of logs :)
|
||||
|
||||
### eslint-disable-line
|
||||
|
||||
While using `// eslint-disable-line`, sometimes you may get linting errors after
|
||||
the code has been processed by this module. That is because `prettier` changes
|
||||
this:
|
||||
|
||||
```js
|
||||
// prettier-ignore
|
||||
if (x) { // eslint-disable-line
|
||||
}
|
||||
```
|
||||
|
||||
to this:
|
||||
|
||||
```js
|
||||
if (x) {
|
||||
// eslint-disable-line
|
||||
}
|
||||
```
|
||||
|
||||
And the `eslint --fix` wont change it back. You can notice that `// eslint-disable-line` has moved to a new line. To work around this issue, you can
|
||||
use `//eslint-disable-next-line` instead of `// eslint-disable-line` like this:
|
||||
|
||||
```js
|
||||
// eslint-disable-next-line
|
||||
if (x) {
|
||||
}
|
||||
```
|
||||
|
||||
## Inspiration
|
||||
|
||||
- [`prettier`][prettier]
|
||||
- [`eslint`][eslint]
|
||||
|
||||
## Other Solutions
|
||||
|
||||
None that I'm aware of. Feel free to file a PR if you know of any other
|
||||
solutions.
|
||||
|
||||
## Related
|
||||
|
||||
- [`prettier-eslint-cli`](https://github.com/prettier/prettier-eslint-cli) -
|
||||
Command Line Interface
|
||||
- [`prettier-atom`][atom-plugin] - Atom plugin (check the "ESlint integration"
|
||||
checkbox in settings)
|
||||
- [`prettier-vscode`][vscode-plugin] - Visual Studio Code plugin (set
|
||||
`prettier.eslintIntegration: true` in settings)
|
||||
- [`eslint-plugin-prettier`](https://github.com/not-an-aardvark/eslint-plugin-prettier) -
|
||||
ESLint plugin. While prettier-eslint uses `eslint --fix` to change the output of `prettier`, eslint-plugin-prettier keeps the `prettier` output as-is and integrates it with the regular ESLint workflow.
|
||||
- [`prettier-eslint-webpack-plugin`](https://github.com/danielterwiel/prettier-eslint-webpack-plugin) -
|
||||
Prettier ESlint Webpack Plugin
|
||||
|
||||
## Contributors
|
||||
|
||||
Thanks goes to these people ([emoji key][emojis]):
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
||||
<!-- prettier-ignore-start -->
|
||||
<!-- markdownlint-disable -->
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="https://kentcdodds.com"><img src="https://avatars.githubusercontent.com/u/1500684?v=3?s=100" width="100px;" alt=""/><br /><sub><b>Kent C. Dodds</b></sub></a><br /><a href="https://github.com/prettier/prettier-eslint/commits?author=kentcdodds" title="Code">💻</a> <a href="https://github.com/prettier/prettier-eslint/commits?author=kentcdodds" title="Documentation">📖</a> <a href="#infra-kentcdodds" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/prettier/prettier-eslint/commits?author=kentcdodds" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="http://gyandeeps.com"><img src="https://avatars.githubusercontent.com/u/5554486?v=3?s=100" width="100px;" alt=""/><br /><sub><b>Gyandeep Singh</b></sub></a><br /><a href="https://github.com/prettier/prettier-eslint/pulls?q=is%3Apr+reviewed-by%3Agyandeeps" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center"><a href="https://github.com/exdeniz"><img src="https://avatars.githubusercontent.com/u/682584?v=3?s=100" width="100px;" alt=""/><br /><sub><b>Igor Pnev</b></sub></a><br /><a href="https://github.com/prettier/prettier-eslint/issues?q=author%3Aexdeniz" title="Bug reports">🐛</a></td>
|
||||
<td align="center"><a href="https://demoneaux.github.io/"><img src="https://avatars.githubusercontent.com/u/813865?v=3?s=100" width="100px;" alt=""/><br /><sub><b>Benjamin Tan</b></sub></a><br /><a href="#question-demoneaux" title="Answering Questions">💬</a> <a href="https://github.com/prettier/prettier-eslint/pulls?q=is%3Apr+reviewed-by%3Ademoneaux" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center"><a href="https://ericmccormick.io"><img src="https://avatars.githubusercontent.com/u/622118?v=3?s=100" width="100px;" alt=""/><br /><sub><b>Eric McCormick</b></sub></a><br /><a href="https://github.com/prettier/prettier-eslint/commits?author=edm00se" title="Code">💻</a> <a href="https://github.com/prettier/prettier-eslint/commits?author=edm00se" title="Documentation">📖</a> <a href="https://github.com/prettier/prettier-eslint/commits?author=edm00se" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/lydell"><img src="https://avatars.githubusercontent.com/u/2142817?v=3?s=100" width="100px;" alt=""/><br /><sub><b>Simon Lydell</b></sub></a><br /><a href="https://github.com/prettier/prettier-eslint/commits?author=lydell" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/tommck"><img src="https://avatars0.githubusercontent.com/u/981957?v=3?s=100" width="100px;" alt=""/><br /><sub><b>Tom McKearney</b></sub></a><br /><a href="https://github.com/prettier/prettier-eslint/commits?author=tommck" title="Documentation">📖</a> <a href="#example-tommck" title="Examples">💡</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/PAkerstrand"><img src="https://avatars.githubusercontent.com/u/463105?v=3?s=100" width="100px;" alt=""/><br /><sub><b>Patrik Åkerstrand</b></sub></a><br /><a href="https://github.com/prettier/prettier-eslint/commits?author=PAkerstrand" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://twitter.com/loklaan"><img src="https://avatars.githubusercontent.com/u/1560301?v=3?s=100" width="100px;" alt=""/><br /><sub><b>Lochlan Bunn</b></sub></a><br /><a href="https://github.com/prettier/prettier-eslint/commits?author=loklaan" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/danielterwiel"><img src="https://avatars.githubusercontent.com/u/25886902?v=3?s=100" width="100px;" alt=""/><br /><sub><b>Daniël Terwiel</b></sub></a><br /><a href="#plugin-danielterwiel" title="Plugin/utility libraries">🔌</a> <a href="#tool-danielterwiel" title="Tools">🔧</a></td>
|
||||
<td align="center"><a href="https://robinmalfait.com"><img src="https://avatars1.githubusercontent.com/u/1834413?v=3?s=100" width="100px;" alt=""/><br /><sub><b>Robin Malfait</b></sub></a><br /><a href="#tool-RobinMalfait" title="Tools">🔧</a></td>
|
||||
<td align="center"><a href="http://mgmcdermott.com"><img src="https://avatars0.githubusercontent.com/u/8161781?v=3?s=100" width="100px;" alt=""/><br /><sub><b>Michael McDermott</b></sub></a><br /><a href="https://github.com/prettier/prettier-eslint/commits?author=mgmcdermott" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://sheerun.net"><img src="https://avatars3.githubusercontent.com/u/292365?v=3?s=100" width="100px;" alt=""/><br /><sub><b>Adam Stankiewicz</b></sub></a><br /><a href="https://github.com/prettier/prettier-eslint/commits?author=sheerun" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://www.stephenjohnsorensen.com/"><img src="https://avatars3.githubusercontent.com/u/487068?v=3?s=100" width="100px;" alt=""/><br /><sub><b>Stephen John Sorensen</b></sub></a><br /><a href="https://github.com/prettier/prettier-eslint/commits?author=spudly" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/briandipalma"><img src="https://avatars2.githubusercontent.com/u/1597820?v=3?s=100" width="100px;" alt=""/><br /><sub><b>Brian Di Palma</b></sub></a><br /><a href="https://github.com/prettier/prettier-eslint/issues?q=author%3Abriandipalma" title="Bug reports">🐛</a> <a href="https://github.com/prettier/prettier-eslint/commits?author=briandipalma" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://robwise.github.io"><img src="https://avatars0.githubusercontent.com/u/6173488?v=3?s=100" width="100px;" alt=""/><br /><sub><b>Rob Wise</b></sub></a><br /><a href="https://github.com/prettier/prettier-eslint/commits?author=robwise" title="Documentation">📖</a> <a href="https://github.com/prettier/prettier-eslint/commits?author=robwise" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Belir"><img src="https://avatars0.githubusercontent.com/u/4818642?v=3?s=100" width="100px;" alt=""/><br /><sub><b>Patryk Peas</b></sub></a><br /><a href="https://github.com/prettier/prettier-eslint/issues?q=author%3ABelir" title="Bug reports">🐛</a> <a href="https://github.com/prettier/prettier-eslint/commits?author=Belir" title="Code">💻</a> <a href="https://github.com/prettier/prettier-eslint/commits?author=Belir" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="http://vauxlab.com"><img src="https://avatars2.githubusercontent.com/u/1193520?v=3?s=100" width="100px;" alt=""/><br /><sub><b>Thijs Koerselman</b></sub></a><br /><a href="https://github.com/prettier/prettier-eslint/issues?q=author%3A0x80" title="Bug reports">🐛</a> <a href="https://github.com/prettier/prettier-eslint/commits?author=0x80" title="Code">💻</a> <a href="https://github.com/prettier/prettier-eslint/commits?author=0x80" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/enriquecaballero"><img src="https://avatars3.githubusercontent.com/u/7918284?v=3?s=100" width="100px;" alt=""/><br /><sub><b>Enrique Caballero</b></sub></a><br /><a href="https://github.com/prettier/prettier-eslint/issues?q=author%3Aenriquecaballero" title="Bug reports">🐛</a> <a href="https://github.com/prettier/prettier-eslint/commits?author=enriquecaballero" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/lukaszmoroz"><img src="https://avatars2.githubusercontent.com/u/1408542?v=3?s=100" width="100px;" alt=""/><br /><sub><b>Łukasz Moroz</b></sub></a><br /><a href="https://github.com/prettier/prettier-eslint/issues?q=author%3Alukaszmoroz" title="Bug reports">🐛</a> <a href="https://github.com/prettier/prettier-eslint/commits?author=lukaszmoroz" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/zimme"><img src="https://avatars0.githubusercontent.com/u/1215414?v=3?s=100" width="100px;" alt=""/><br /><sub><b>Simon Fridlund</b></sub></a><br /><a href="#question-zimme" title="Answering Questions">💬</a> <a href="https://github.com/prettier/prettier-eslint/issues?q=author%3Azimme" title="Bug reports">🐛</a> <a href="https://github.com/prettier/prettier-eslint/commits?author=zimme" title="Code">💻</a> <a href="https://github.com/prettier/prettier-eslint/commits?author=zimme" title="Documentation">📖</a> <a href="#example-zimme" title="Examples">💡</a> <a href="#ideas-zimme" title="Ideas, Planning, & Feedback">🤔</a> <a href="#infra-zimme" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#plugin-zimme" title="Plugin/utility libraries">🔌</a> <a href="https://github.com/prettier/prettier-eslint/pulls?q=is%3Apr+reviewed-by%3Azimme" title="Reviewed Pull Requests">👀</a> <a href="#talk-zimme" title="Talks">📢</a> <a href="https://github.com/prettier/prettier-eslint/commits?author=zimme" title="Tests">⚠️</a> <a href="#tool-zimme" title="Tools">🔧</a> <a href="#tutorial-zimme" title="Tutorials">✅</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://oliverjash.me/"><img src="https://avatars1.githubusercontent.com/u/921609?v=3?s=100" width="100px;" alt=""/><br /><sub><b>Oliver Joseph Ash</b></sub></a><br /><a href="https://github.com/prettier/prettier-eslint/issues?q=author%3AOliverJAsh" title="Bug reports">🐛</a> <a href="https://github.com/prettier/prettier-eslint/commits?author=OliverJAsh" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://palf.co"><img src="https://avatars1.githubusercontent.com/u/3812133?v=3?s=100" width="100px;" alt=""/><br /><sub><b>Mark Palfreeman</b></sub></a><br /><a href="https://github.com/prettier/prettier-eslint/commits?author=markpalfreeman" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/alexmckenley"><img src="https://avatars1.githubusercontent.com/u/3639670?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Alex Taylor</b></sub></a><br /><a href="https://github.com/prettier/prettier-eslint/commits?author=alexmckenley" title="Code">💻</a> <a href="https://github.com/prettier/prettier-eslint/commits?author=alexmckenley" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/chinesedfan"><img src="https://avatars3.githubusercontent.com/u/1736154?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Xianming Zhong</b></sub></a><br /><a href="https://github.com/prettier/prettier-eslint/commits?author=chinesedfan" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/lewisl9029"><img src="https://avatars0.githubusercontent.com/u/6934200?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Lewis Liu</b></sub></a><br /><a href="https://github.com/prettier/prettier-eslint/commits?author=lewisl9029" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://hamidihamza.com"><img src="https://avatars0.githubusercontent.com/u/22576950?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Hamza Hamidi</b></sub></a><br /><a href="https://github.com/prettier/prettier-eslint/commits?author=hamzahamidi" title="Code">💻</a> <a href="#ideas-hamzahamidi" title="Ideas, Planning, & Feedback">🤔</a> <a href="#maintenance-hamzahamidi" title="Maintenance">🚧</a> <a href="#tool-hamzahamidi" title="Tools">🔧</a> <a href="https://github.com/prettier/prettier-eslint/pulls?q=is%3Apr+reviewed-by%3Ahamzahamidi" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center"><a href="https://github.com/iamrajiv"><img src="https://avatars0.githubusercontent.com/u/42106787?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rajiv Ranjan Singh</b></sub></a><br /><a href="https://github.com/prettier/prettier-eslint/commits?author=iamrajiv" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/cy6erskunk"><img src="https://avatars3.githubusercontent.com/u/754849?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Igor</b></sub></a><br /><a href="#maintenance-cy6erskunk" title="Maintenance">🚧</a></td>
|
||||
<td align="center"><a href="https://campcode.dev/"><img src="https://avatars.githubusercontent.com/u/10620169?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rebecca Vest</b></sub></a><br /><a href="https://github.com/prettier/prettier-eslint/commits?author=idahogurl" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/chrisbobbe"><img src="https://avatars.githubusercontent.com/u/22248748?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Chris Bobbe</b></sub></a><br /><a href="https://github.com/prettier/prettier-eslint/issues?q=author%3Achrisbobbe" title="Bug reports">🐛</a> <a href="https://github.com/prettier/prettier-eslint/commits?author=chrisbobbe" title="Code">💻</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- markdownlint-restore -->
|
||||
<!-- prettier-ignore-end -->
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
This project follows the [all-contributors][all-contributors] specification.
|
||||
Contributions of any kind welcome!
|
||||
|
||||
## LICENSE
|
||||
|
||||
MIT
|
||||
|
||||
[prettier]: https://github.com/jlongster/prettier
|
||||
[eslint]: http://eslint.org/
|
||||
[fix]: http://eslint.org/docs/user-guide/command-line-interface#fix
|
||||
[npm]: https://www.npmjs.com/
|
||||
[node]: https://nodejs.org
|
||||
[build-badge]: https://img.shields.io/travis/prettier/prettier-eslint.svg?style=flat-square
|
||||
[build]: https://travis-ci.org/prettier/prettier-eslint
|
||||
[coverage-badge]: https://img.shields.io/codecov/c/github/prettier/prettier-eslint.svg?style=flat-square
|
||||
[coverage]: https://codecov.io/github/prettier/prettier-eslint
|
||||
[version-badge]: https://img.shields.io/npm/v/prettier-eslint.svg?style=flat-square
|
||||
[package]: https://www.npmjs.com/package/prettier-eslint
|
||||
[downloads-badge]: https://img.shields.io/npm/dm/prettier-eslint.svg?style=flat-square
|
||||
[npm-stat]: http://npm-stat.com/charts.html?package=prettier-eslint&from=2016-04-01
|
||||
[license-badge]: https://img.shields.io/npm/l/prettier-eslint.svg?style=flat-square
|
||||
[license]: https://github.com/prettier/prettier-eslint/blob/master/other/LICENSE
|
||||
[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square
|
||||
[prs]: http://makeapullrequest.com
|
||||
[donate-badge]: https://img.shields.io/badge/$-support-green.svg?style=flat-square
|
||||
[donate]: https://www.paypal.me/zimme
|
||||
[coc-badge]: https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square
|
||||
[coc]: https://github.com/prettier/prettier-eslint/blob/master/other/CODE_OF_CONDUCT.md
|
||||
[roadmap-badge]: https://img.shields.io/badge/%F0%9F%93%94-roadmap-CD9523.svg?style=flat-square
|
||||
[roadmap]: https://github.com/prettier/prettier-eslint/blob/master/other/ROADMAP.md
|
||||
[examples-badge]: https://img.shields.io/badge/%F0%9F%92%A1-examples-8C8E93.svg?style=flat-square
|
||||
[examples]: https://github.com/prettier/prettier-eslint/blob/master/other/EXAMPLES.md
|
||||
[github-watch-badge]: https://img.shields.io/github/watchers/prettier/prettier-eslint.svg?style=social
|
||||
[github-watch]: https://github.com/prettier/prettier-eslint/watchers
|
||||
[github-star-badge]: https://img.shields.io/github/stars/prettier/prettier-eslint.svg?style=social
|
||||
[github-star]: https://github.com/prettier/prettier-eslint/stargazers
|
||||
[twitter]: https://twitter.com/intent/tweet?text=Check%20out%20prettier-eslint!%20https://github.com/prettier/prettier-eslint%20%F0%9F%91%8D
|
||||
[twitter-badge]: https://img.shields.io/twitter/url/https/github.com/prettier/prettier-eslint.svg?style=social
|
||||
[emojis]: https://github.com/kentcdodds/all-contributors#emoji-key
|
||||
[all-contributors]: https://github.com/kentcdodds/all-contributors
|
||||
[atom-plugin]: https://github.com/prettier/prettier-atom
|
||||
[atom-dev-tools]: https://discuss.atom.io/t/how-to-make-developer-tools-appear/16232
|
||||
[vscode-plugin]: https://github.com/esbenp/prettier-vscode
|
||||
+287
@@ -0,0 +1,287 @@
|
||||
"use strict";
|
||||
|
||||
var _fs = _interopRequireDefault(require("fs"));
|
||||
|
||||
var _path = _interopRequireDefault(require("path"));
|
||||
|
||||
var _requireRelative = _interopRequireDefault(require("require-relative"));
|
||||
|
||||
var _prettyFormat = _interopRequireDefault(require("pretty-format"));
|
||||
|
||||
var _commonTags = require("common-tags");
|
||||
|
||||
var _indentString = _interopRequireDefault(require("indent-string"));
|
||||
|
||||
var _loglevelColoredLevelPrefix = _interopRequireDefault(require("loglevel-colored-level-prefix"));
|
||||
|
||||
var _lodash = _interopRequireDefault(require("lodash.merge"));
|
||||
|
||||
var _utils = require("./utils");
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
/* eslint no-console:0, global-require:0, import/no-dynamic-require:0 */
|
||||
|
||||
/* eslint complexity: [1, 13] */
|
||||
const logger = (0, _loglevelColoredLevelPrefix.default)({
|
||||
prefix: 'prettier-eslint'
|
||||
}); // CommonJS + ES6 modules... is it worth it? Probably not...
|
||||
|
||||
module.exports = format;
|
||||
/**
|
||||
* Formats the text with prettier and then eslint based on the given options
|
||||
* @param {String} options.filePath - the path of the file being formatted
|
||||
* can be used in leu of `eslintConfig` (eslint will be used to find the
|
||||
* relevant config for the file). Will also be used to load the `text` if
|
||||
* `text` is not provided.
|
||||
* @param {String} options.text - the text (JavaScript code) to format
|
||||
* @param {String} options.eslintPath - the path to the eslint module to use.
|
||||
* Will default to require.resolve('eslint')
|
||||
* @param {String} options.prettierPath - the path to the prettier module.
|
||||
* Will default to require.resovlve('prettier')
|
||||
* @param {Object} options.eslintConfig - the config to use for formatting
|
||||
* with ESLint.
|
||||
* @param {Object} options.prettierOptions - the options to pass for
|
||||
* formatting with `prettier`. If not provided, prettier-eslint will attempt
|
||||
* to create the options based on the eslintConfig
|
||||
* @param {Object} options.fallbackPrettierOptions - the options to pass for
|
||||
* formatting with `prettier` if the given option is not inferrable from the
|
||||
* eslintConfig.
|
||||
* @param {String} options.logLevel - the level for the logs
|
||||
* (error, warn, info, debug, trace)
|
||||
* @param {Boolean} options.prettierLast - Run Prettier Last
|
||||
* @return {Promise<String>} - the formatted string
|
||||
*/
|
||||
|
||||
async function format(options) {
|
||||
const {
|
||||
logLevel = getDefaultLogLevel()
|
||||
} = options;
|
||||
logger.setLevel(logLevel);
|
||||
logger.trace('called format with options:', (0, _prettyFormat.default)(options));
|
||||
const {
|
||||
filePath,
|
||||
text = getTextFromFilePath(filePath),
|
||||
eslintPath = getModulePath(filePath, 'eslint'),
|
||||
prettierPath = getModulePath(filePath, 'prettier'),
|
||||
prettierLast,
|
||||
fallbackPrettierOptions
|
||||
} = options;
|
||||
const eslintConfig = (0, _lodash.default)({}, options.eslintConfig, await getESLintConfig(filePath, eslintPath, options.eslintConfig || {}));
|
||||
const prettierOptions = (0, _lodash.default)({}, filePath && {
|
||||
filepath: filePath
|
||||
}, getPrettierConfig(filePath, prettierPath), options.prettierOptions);
|
||||
const formattingOptions = (0, _utils.getOptionsForFormatting)(eslintConfig, prettierOptions, fallbackPrettierOptions, eslintPath);
|
||||
logger.debug('inferred options:', (0, _prettyFormat.default)({
|
||||
filePath,
|
||||
text,
|
||||
eslintPath,
|
||||
prettierPath,
|
||||
eslintConfig: formattingOptions.eslint,
|
||||
prettierOptions: formattingOptions.prettier,
|
||||
logLevel,
|
||||
prettierLast
|
||||
}));
|
||||
const eslintExtensions = eslintConfig.extensions || ['.js', '.jsx', '.ts', '.tsx', '.mjs', '.vue'];
|
||||
|
||||
const fileExtension = _path.default.extname(filePath || ''); // If we don't get filePath run eslint on text, otherwise only run eslint
|
||||
// if it's a configured extension or fall back to a "supported" file type.
|
||||
|
||||
|
||||
const onlyPrettier = filePath ? !eslintExtensions.includes(fileExtension) : false;
|
||||
const prettify = createPrettify(formattingOptions.prettier, prettierPath);
|
||||
|
||||
if (onlyPrettier) {
|
||||
return prettify(text);
|
||||
}
|
||||
|
||||
if (['.ts', '.tsx'].includes(fileExtension)) {
|
||||
formattingOptions.eslint.parser = formattingOptions.eslint.parser || require.resolve('@typescript-eslint/parser');
|
||||
}
|
||||
|
||||
if (['.vue'].includes(fileExtension)) {
|
||||
formattingOptions.eslint.parser = formattingOptions.eslint.parser || require.resolve('vue-eslint-parser');
|
||||
}
|
||||
|
||||
const eslintFix = await createEslintFix(formattingOptions.eslint, eslintPath);
|
||||
|
||||
if (prettierLast) {
|
||||
const eslintFixed = await eslintFix(text, filePath);
|
||||
return prettify(eslintFixed);
|
||||
}
|
||||
|
||||
return eslintFix(prettify(text), filePath);
|
||||
}
|
||||
|
||||
function createPrettify(formatOptions, prettierPath) {
|
||||
return function prettify(text) {
|
||||
logger.debug('calling prettier on text');
|
||||
logger.trace((0, _commonTags.stripIndent)`
|
||||
prettier input:
|
||||
|
||||
${(0, _indentString.default)(text, 2)}
|
||||
`);
|
||||
const prettier = (0, _utils.requireModule)(prettierPath, 'prettier');
|
||||
|
||||
try {
|
||||
logger.trace('calling prettier.format with the text and prettierOptions');
|
||||
const output = prettier.format(text, formatOptions);
|
||||
logger.trace('prettier: output === input', output === text);
|
||||
logger.trace((0, _commonTags.stripIndent)`
|
||||
prettier output:
|
||||
|
||||
${(0, _indentString.default)(output, 2)}
|
||||
`);
|
||||
return output;
|
||||
} catch (error) {
|
||||
logger.error('prettier formatting failed due to a prettier error');
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function createEslintFix(eslintConfig, eslintPath) {
|
||||
return async function eslintFix(text, filePath) {
|
||||
if (Array.isArray(eslintConfig.globals)) {
|
||||
const tempGlobals = {};
|
||||
eslintConfig.globals.forEach(g => {
|
||||
const [key, value] = g.split(':');
|
||||
tempGlobals[key] = value;
|
||||
});
|
||||
eslintConfig.globals = tempGlobals;
|
||||
}
|
||||
|
||||
eslintConfig.overrideConfig = {
|
||||
rules: eslintConfig.rules,
|
||||
parser: eslintConfig.parser,
|
||||
globals: eslintConfig.globals,
|
||||
parserOptions: eslintConfig.parserOptions,
|
||||
ignorePatterns: eslintConfig.ignorePatterns || eslintConfig.ignorePattern,
|
||||
plugins: eslintConfig.plugins,
|
||||
env: eslintConfig.env,
|
||||
settings: eslintConfig.settings,
|
||||
noInlineConfig: eslintConfig.noInlineConfig,
|
||||
...eslintConfig.overrideConfig
|
||||
};
|
||||
delete eslintConfig.rules;
|
||||
delete eslintConfig.parser;
|
||||
delete eslintConfig.parserOptions;
|
||||
delete eslintConfig.globals;
|
||||
delete eslintConfig.ignorePatterns;
|
||||
delete eslintConfig.ignorePattern;
|
||||
delete eslintConfig.plugins;
|
||||
delete eslintConfig.env;
|
||||
delete eslintConfig.noInlineConfig;
|
||||
delete eslintConfig.settings;
|
||||
const eslint = (0, _utils.getESLint)(eslintPath, eslintConfig);
|
||||
|
||||
try {
|
||||
logger.trace('calling cliEngine.executeOnText with the text');
|
||||
const report = await eslint.lintText(text, {
|
||||
filePath,
|
||||
warnIgnored: true
|
||||
});
|
||||
logger.trace('executeOnText returned the following report:', (0, _prettyFormat.default)(report)); // default the output to text because if there's nothing
|
||||
// to fix, eslint doesn't provide `output`
|
||||
|
||||
const [{
|
||||
output = text
|
||||
}] = await report;
|
||||
logger.trace('eslint --fix: output === input', output === text); // NOTE: We're ignoring linting errors/warnings here and
|
||||
// defaulting to the given text if there are any
|
||||
// because all we're trying to do is fix what we can.
|
||||
// We don't care about what we can't
|
||||
|
||||
logger.trace((0, _commonTags.stripIndent)`
|
||||
eslint --fix output:
|
||||
|
||||
${(0, _indentString.default)(output, 2)}
|
||||
`);
|
||||
return output;
|
||||
} catch (error) {
|
||||
logger.error('eslint fix failed due to an eslint error');
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function getTextFromFilePath(filePath) {
|
||||
try {
|
||||
logger.trace((0, _commonTags.oneLine)`
|
||||
attempting fs.readFileSync to get
|
||||
the text for file at "${filePath}"
|
||||
`);
|
||||
return _fs.default.readFileSync(filePath, 'utf8');
|
||||
} catch (error) {
|
||||
logger.error((0, _commonTags.oneLine)`
|
||||
failed to get the text to format
|
||||
from the given filePath: "${filePath}"
|
||||
`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
function getESLintApiOptions(eslintConfig) {
|
||||
// https://eslint.org/docs/developer-guide/nodejs-api
|
||||
// these options affect what calculateConfigForFile produces
|
||||
return {
|
||||
ignore: eslintConfig.ignore || true,
|
||||
ignorePath: eslintConfig.ignorePath || null,
|
||||
allowInlineConfig: eslintConfig.allowInlineConfig || true,
|
||||
baseConfig: eslintConfig.baseConfig || null,
|
||||
overrideConfig: eslintConfig.overrideConfig || null,
|
||||
overrideConfigFile: eslintConfig.overrideConfigFile || null,
|
||||
plugins: eslintConfig.plugins || null,
|
||||
resolvePluginsRelativeTo: eslintConfig.resolvePluginsRelativeTo || null,
|
||||
rulePaths: eslintConfig.rulePaths || [],
|
||||
useEslintrc: eslintConfig.useEslintrc || true
|
||||
};
|
||||
}
|
||||
|
||||
async function getESLintConfig(filePath, eslintPath, eslintOptions) {
|
||||
if (filePath) {
|
||||
eslintOptions.cwd = _path.default.dirname(filePath);
|
||||
}
|
||||
|
||||
logger.trace((0, _commonTags.oneLine)`
|
||||
creating ESLint CLI Engine to get the config for
|
||||
"${filePath || process.cwd()}"
|
||||
`);
|
||||
const eslint = (0, _utils.getESLint)(eslintPath, getESLintApiOptions(eslintOptions));
|
||||
|
||||
try {
|
||||
logger.debug(`getting eslint config for file at "${filePath}"`);
|
||||
const config = await eslint.calculateConfigForFile(filePath);
|
||||
logger.trace(`eslint config for "${filePath}" received`, (0, _prettyFormat.default)(config));
|
||||
return { ...eslintOptions,
|
||||
...config
|
||||
};
|
||||
} catch (error) {
|
||||
// is this noisy? Try setting options.disableLog to false
|
||||
logger.debug('Unable to find config');
|
||||
return {
|
||||
rules: {}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function getPrettierConfig(filePath, prettierPath) {
|
||||
const prettier = (0, _utils.requireModule)(prettierPath, 'prettier');
|
||||
return prettier.resolveConfig && prettier.resolveConfig.sync && prettier.resolveConfig.sync(filePath) || {};
|
||||
}
|
||||
|
||||
function getModulePath(filePath = __filename, moduleName) {
|
||||
try {
|
||||
return _requireRelative.default.resolve(moduleName, filePath);
|
||||
} catch (error) {
|
||||
logger.debug((0, _commonTags.oneLine)`
|
||||
There was a problem finding the ${moduleName}
|
||||
module. Using prettier-eslint's version.
|
||||
`, error.message, error.stack);
|
||||
return require.resolve(moduleName);
|
||||
}
|
||||
}
|
||||
|
||||
function getDefaultLogLevel() {
|
||||
return process.env.LOG_LEVEL || 'warn';
|
||||
}
|
||||
+391
@@ -0,0 +1,391 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.getESLint = getESLint;
|
||||
exports.getOptionsForFormatting = getOptionsForFormatting;
|
||||
exports.requireModule = requireModule;
|
||||
|
||||
var _commonTags = require("common-tags");
|
||||
|
||||
var _dlv = _interopRequireDefault(require("dlv"));
|
||||
|
||||
var _loglevelColoredLevelPrefix = _interopRequireDefault(require("loglevel-colored-level-prefix"));
|
||||
|
||||
var _eslint = require("eslint");
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
/* eslint import/no-dynamic-require:0 */
|
||||
const logger = (0, _loglevelColoredLevelPrefix.default)({
|
||||
prefix: 'prettier-eslint'
|
||||
});
|
||||
const RULE_DISABLED = {};
|
||||
const RULE_NOT_CONFIGURED = 'RULE_NOT_CONFIGURED';
|
||||
|
||||
const ruleValueExists = prettierRuleValue => prettierRuleValue !== RULE_NOT_CONFIGURED && prettierRuleValue !== RULE_DISABLED && typeof prettierRuleValue !== 'undefined';
|
||||
|
||||
const OPTION_GETTERS = {
|
||||
printWidth: {
|
||||
ruleValue: rules => getRuleValue(rules, 'max-len', 'code'),
|
||||
ruleValueToPrettierOption: getPrintWidth
|
||||
},
|
||||
tabWidth: {
|
||||
ruleValue: rules => {
|
||||
let value = getRuleValue(rules, 'indent');
|
||||
|
||||
if (value === 'tab') {
|
||||
value = getRuleValue(rules, 'max-len', 'tabWidth');
|
||||
}
|
||||
|
||||
return value;
|
||||
},
|
||||
ruleValueToPrettierOption: getTabWidth
|
||||
},
|
||||
singleQuote: {
|
||||
ruleValue: rules => getRuleValue(rules, 'quotes'),
|
||||
ruleValueToPrettierOption: getSingleQuote
|
||||
},
|
||||
trailingComma: {
|
||||
ruleValue: rules => getRuleValue(rules, 'comma-dangle', []),
|
||||
ruleValueToPrettierOption: getTrailingComma
|
||||
},
|
||||
bracketSpacing: {
|
||||
ruleValue: rules => getRuleValue(rules, 'object-curly-spacing'),
|
||||
ruleValueToPrettierOption: getBracketSpacing
|
||||
},
|
||||
semi: {
|
||||
ruleValue: rules => getRuleValue(rules, 'semi'),
|
||||
ruleValueToPrettierOption: getSemi
|
||||
},
|
||||
useTabs: {
|
||||
ruleValue: rules => getRuleValue(rules, 'indent'),
|
||||
ruleValueToPrettierOption: getUseTabs
|
||||
},
|
||||
bracketSameLine: {
|
||||
ruleValue: rules => getRuleValue(rules, 'react/jsx-closing-bracket-location', 'nonEmpty'),
|
||||
ruleValueToPrettierOption: getBracketSameLine
|
||||
},
|
||||
arrowParens: {
|
||||
ruleValue: rules => getRuleValue(rules, 'arrow-parens'),
|
||||
ruleValueToPrettierOption: getArrowParens
|
||||
}
|
||||
};
|
||||
/* eslint import/prefer-default-export:0 */
|
||||
|
||||
function getOptionsForFormatting(eslintConfig, prettierOptions = {}, fallbackPrettierOptions = {}) {
|
||||
const eslint = getRelevantESLintConfig(eslintConfig);
|
||||
const prettier = getPrettierOptionsFromESLintRules(eslintConfig, prettierOptions, fallbackPrettierOptions);
|
||||
return {
|
||||
eslint,
|
||||
prettier
|
||||
};
|
||||
}
|
||||
|
||||
function getRelevantESLintConfig(eslintConfig) {
|
||||
const linter = new _eslint.Linter();
|
||||
const rules = linter.getRules();
|
||||
logger.debug('turning off unfixable rules');
|
||||
const relevantRules = {};
|
||||
rules.forEach((rule, name) => {
|
||||
const {
|
||||
meta: {
|
||||
fixable
|
||||
}
|
||||
} = rule;
|
||||
|
||||
if (!fixable) {
|
||||
logger.trace('turning off rule:', JSON.stringify({
|
||||
[name]: rule
|
||||
}));
|
||||
rule = ['off'];
|
||||
relevantRules[name] = rule;
|
||||
}
|
||||
}, {});
|
||||
return {
|
||||
// defaults
|
||||
useEslintrc: false,
|
||||
...eslintConfig,
|
||||
// overrides
|
||||
rules: { ...eslintConfig.rules,
|
||||
...relevantRules
|
||||
},
|
||||
fix: true,
|
||||
globals: eslintConfig.globals || {}
|
||||
};
|
||||
}
|
||||
/**
|
||||
* This accepts an eslintConfig object and converts
|
||||
* it to the `prettier` options object
|
||||
*/
|
||||
|
||||
|
||||
function getPrettierOptionsFromESLintRules(eslintConfig, prettierOptions, fallbackPrettierOptions) {
|
||||
const {
|
||||
rules
|
||||
} = eslintConfig;
|
||||
const prettierPluginOptions = getRuleValue(rules, 'prettier/prettier', []);
|
||||
|
||||
if (ruleValueExists(prettierPluginOptions)) {
|
||||
prettierOptions = { ...prettierPluginOptions,
|
||||
...prettierOptions
|
||||
};
|
||||
}
|
||||
|
||||
return Object.keys(OPTION_GETTERS).reduce((options, key) => configureOptions(prettierOptions, fallbackPrettierOptions, key, options, rules), prettierOptions);
|
||||
} // If an ESLint rule that prettier can be configured with is enabled create a
|
||||
// prettier configuration object that reflects the ESLint rule configuration.
|
||||
|
||||
|
||||
function configureOptions(prettierOptions, fallbackPrettierOptions, key, options, rules) {
|
||||
const givenOption = prettierOptions[key];
|
||||
const optionIsGiven = givenOption !== undefined;
|
||||
|
||||
if (optionIsGiven) {
|
||||
options[key] = givenOption;
|
||||
} else {
|
||||
const {
|
||||
ruleValue,
|
||||
ruleValueToPrettierOption
|
||||
} = OPTION_GETTERS[key];
|
||||
const eslintRuleValue = ruleValue(rules);
|
||||
const option = ruleValueToPrettierOption(eslintRuleValue, fallbackPrettierOptions, rules);
|
||||
|
||||
if (option !== undefined) {
|
||||
options[key] = option;
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
function getPrintWidth(eslintValue, fallbacks) {
|
||||
return makePrettierOption('printWidth', eslintValue, fallbacks);
|
||||
}
|
||||
|
||||
function getTabWidth(eslintValue, fallbacks) {
|
||||
return makePrettierOption('tabWidth', eslintValue, fallbacks);
|
||||
}
|
||||
|
||||
function getSingleQuote(eslintValue, fallbacks) {
|
||||
let prettierValue;
|
||||
|
||||
if (eslintValue === 'single') {
|
||||
prettierValue = true;
|
||||
} else if (eslintValue === 'double') {
|
||||
prettierValue = false;
|
||||
} else if (eslintValue === 'backtick') {
|
||||
prettierValue = false;
|
||||
} else {
|
||||
prettierValue = eslintValue;
|
||||
}
|
||||
|
||||
return makePrettierOption('singleQuote', prettierValue, fallbacks);
|
||||
}
|
||||
|
||||
function getTrailingComma(eslintValue, fallbacks) {
|
||||
let prettierValue;
|
||||
|
||||
if (eslintValue === 'never') {
|
||||
prettierValue = 'none';
|
||||
} else if (typeof eslintValue === 'string' && eslintValue.indexOf('always') === 0) {
|
||||
prettierValue = 'es5';
|
||||
} else if (typeof eslintValue === 'object') {
|
||||
prettierValue = getValFromTrailingCommaConfig(eslintValue);
|
||||
} else {
|
||||
prettierValue = RULE_NOT_CONFIGURED;
|
||||
}
|
||||
|
||||
return makePrettierOption('trailingComma', prettierValue, fallbacks);
|
||||
}
|
||||
|
||||
function getValFromTrailingCommaConfig(objectConfig) {
|
||||
const {
|
||||
arrays = '',
|
||||
objects = '',
|
||||
functions = ''
|
||||
} = objectConfig;
|
||||
const fns = isAlways(functions);
|
||||
const es5 = [arrays, objects].some(isAlways);
|
||||
|
||||
if (fns) {
|
||||
return 'all';
|
||||
} else if (es5) {
|
||||
return 'es5';
|
||||
} else {
|
||||
return 'none';
|
||||
}
|
||||
}
|
||||
|
||||
function getBracketSpacing(eslintValue, fallbacks) {
|
||||
let prettierValue;
|
||||
|
||||
if (eslintValue === 'never') {
|
||||
prettierValue = false;
|
||||
} else if (eslintValue === 'always') {
|
||||
prettierValue = true;
|
||||
} else {
|
||||
prettierValue = eslintValue;
|
||||
}
|
||||
|
||||
return makePrettierOption('bracketSpacing', prettierValue, fallbacks);
|
||||
}
|
||||
|
||||
function getSemi(eslintValue, fallbacks) {
|
||||
let prettierValue;
|
||||
|
||||
if (eslintValue === 'never') {
|
||||
prettierValue = false;
|
||||
} else if (eslintValue === 'always') {
|
||||
prettierValue = true;
|
||||
} else {
|
||||
prettierValue = eslintValue;
|
||||
}
|
||||
|
||||
return makePrettierOption('semi', prettierValue, fallbacks);
|
||||
}
|
||||
|
||||
function getUseTabs(eslintValue, fallbacks) {
|
||||
let prettierValue;
|
||||
|
||||
if (eslintValue === 'tab') {
|
||||
prettierValue = true;
|
||||
} else {
|
||||
prettierValue = RULE_NOT_CONFIGURED;
|
||||
}
|
||||
|
||||
return makePrettierOption('useTabs', prettierValue, fallbacks);
|
||||
}
|
||||
|
||||
function getBracketSameLine(eslintValue, fallbacks) {
|
||||
let prettierValue;
|
||||
|
||||
if (eslintValue === 'after-props') {
|
||||
prettierValue = true;
|
||||
} else if (eslintValue === 'tag-aligned' || eslintValue === 'line-aligned' || eslintValue === 'props-aligned') {
|
||||
prettierValue = false;
|
||||
} else {
|
||||
prettierValue = eslintValue;
|
||||
}
|
||||
|
||||
return makePrettierOption('bracketSameLine', prettierValue, fallbacks);
|
||||
}
|
||||
|
||||
function getArrowParens(eslintValue, fallbacks) {
|
||||
let prettierValue;
|
||||
|
||||
if (eslintValue === 'as-needed') {
|
||||
prettierValue = 'avoid';
|
||||
} else {
|
||||
prettierValue = eslintValue;
|
||||
}
|
||||
|
||||
return makePrettierOption('arrowParens', prettierValue, fallbacks);
|
||||
}
|
||||
|
||||
function extractRuleValue(objPath, name, value) {
|
||||
// XXX: Ignore code coverage for the following else case
|
||||
// There are currently no eslint rules which we can infer prettier
|
||||
// options from, that have an object option which we don't know how
|
||||
// to infer from.
|
||||
// istanbul ignore else
|
||||
if (objPath) {
|
||||
logger.trace((0, _commonTags.oneLine)`
|
||||
Getting the value from object configuration of ${name}.
|
||||
delving into ${JSON.stringify(value)} with path "${objPath}"
|
||||
`);
|
||||
return (0, _dlv.default)(value, objPath, RULE_NOT_CONFIGURED);
|
||||
} // istanbul ignore next
|
||||
|
||||
|
||||
logger.debug((0, _commonTags.oneLine)`
|
||||
The ${name} rule is using an object configuration
|
||||
of ${JSON.stringify(value)} but prettier-eslint is
|
||||
not currently capable of getting the prettier value
|
||||
based on an object configuration for ${name}.
|
||||
Please file an issue (and make a pull request?)
|
||||
`); // istanbul ignore next
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getRuleValue(rules, name, objPath) {
|
||||
const ruleConfig = rules[name];
|
||||
|
||||
if (Array.isArray(ruleConfig)) {
|
||||
const [ruleSetting, value] = ruleConfig; // If `ruleSetting` is set to disable the ESLint rule don't use `value` as
|
||||
// it might be a value provided by an overriden config package e.g. airbnb
|
||||
// overriden by config-prettier. The airbnb values are provided even though
|
||||
// config-prettier disables the rule. Instead use fallback or prettier
|
||||
// default.
|
||||
|
||||
if (ruleSetting === 0 || ruleSetting === 'off') {
|
||||
return RULE_DISABLED;
|
||||
}
|
||||
|
||||
if (typeof value === 'object') {
|
||||
return extractRuleValue(objPath, name, value);
|
||||
} else {
|
||||
logger.trace((0, _commonTags.oneLine)`
|
||||
The ${name} rule is configured with a
|
||||
non-object value of ${value}. Using that value.
|
||||
`);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return RULE_NOT_CONFIGURED;
|
||||
}
|
||||
|
||||
function isAlways(val) {
|
||||
return val.indexOf('always') === 0;
|
||||
}
|
||||
|
||||
function makePrettierOption(prettierRuleName, prettierRuleValue, fallbacks) {
|
||||
if (ruleValueExists(prettierRuleValue)) {
|
||||
return prettierRuleValue;
|
||||
}
|
||||
|
||||
const fallback = fallbacks[prettierRuleName];
|
||||
|
||||
if (typeof fallback !== 'undefined') {
|
||||
logger.debug((0, _commonTags.oneLine)`
|
||||
The ${prettierRuleName} rule is not configured,
|
||||
using provided fallback of ${fallback}
|
||||
`);
|
||||
return fallback;
|
||||
}
|
||||
|
||||
logger.debug((0, _commonTags.oneLine)`
|
||||
The ${prettierRuleName} rule is not configured,
|
||||
let prettier decide
|
||||
`);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function requireModule(modulePath, name) {
|
||||
try {
|
||||
logger.trace(`requiring "${name}" module at "${modulePath}"`);
|
||||
return require(modulePath);
|
||||
} catch (error) {
|
||||
logger.error((0, _commonTags.oneLine)`
|
||||
There was trouble getting "${name}".
|
||||
Is "${modulePath}" a correct path to the "${name}" module?
|
||||
`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
function getESLint(eslintPath, eslintOptions) {
|
||||
const {
|
||||
ESLint
|
||||
} = requireModule(eslintPath, 'eslint');
|
||||
|
||||
try {
|
||||
return new ESLint(eslintOptions);
|
||||
} catch (error) {
|
||||
logger.error('There was trouble creating the ESLint CLIEngine.');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
{
|
||||
"name": "prettier-eslint",
|
||||
"version": "15.0.1",
|
||||
"description": "Formats your JavaScript using prettier followed by eslint --fix",
|
||||
"main": "dist/index.js",
|
||||
"types": "types/index.d.ts",
|
||||
"scripts": {
|
||||
"start": "nps",
|
||||
"test": "nps test",
|
||||
"precommit": "opt --in pre-commit --exec \"npm start validate\""
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"types"
|
||||
],
|
||||
"keywords": [],
|
||||
"author": "Kent C. Dodds <kent@doddsfamily.us> (http://kentcdodds.com/)",
|
||||
"maintainers": [
|
||||
"Simon Fridlund <simon@fridlund.email>"
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/eslint": "^8.4.2",
|
||||
"@types/prettier": "^2.6.0",
|
||||
"@typescript-eslint/parser": "^5.10.0",
|
||||
"common-tags": "^1.4.0",
|
||||
"dlv": "^1.1.0",
|
||||
"eslint": "^8.7.0",
|
||||
"indent-string": "^4.0.0",
|
||||
"lodash.merge": "^4.6.0",
|
||||
"loglevel-colored-level-prefix": "^1.0.0",
|
||||
"prettier": "^2.5.1",
|
||||
"pretty-format": "^23.0.1",
|
||||
"require-relative": "^0.8.7",
|
||||
"typescript": "^4.5.4",
|
||||
"vue-eslint-parser": "^8.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.4.4",
|
||||
"@babel/core": "^7.4.5",
|
||||
"@babel/preset-env": "^7.4.5",
|
||||
"acorn": "^6.1.1",
|
||||
"ajv": "^6.12.2",
|
||||
"all-contributors-cli": "^6.7.0",
|
||||
"babel-jest": "^25.0.0",
|
||||
"chalk": "^2.1.0",
|
||||
"eslint-config-kentcdodds": "^20.0.1",
|
||||
"husky": "^2.4.1",
|
||||
"jest": "^25.0.0",
|
||||
"jest-cli": "^25.0.0",
|
||||
"nps": "^5.7.1",
|
||||
"nps-utils": "^1.3.0",
|
||||
"opt-cli": "^1.5.2",
|
||||
"prettier-eslint-cli": "^5.0.0",
|
||||
"rimraf": "^2.5.4",
|
||||
"semantic-release": "^15.13.16",
|
||||
"strip-indent": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/prettier/prettier-eslint.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/prettier/prettier-eslint/issues"
|
||||
},
|
||||
"homepage": "https://github.com/prettier/prettier-eslint#readme"
|
||||
}
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
// Type definitions for prettier-eslint 12.0
|
||||
// Project: https://github.com/prettier/prettier-eslint
|
||||
|
||||
import * as eslint from "eslint";
|
||||
import * as prettier from "prettier";
|
||||
|
||||
declare namespace format {
|
||||
/**
|
||||
* Logging level for the traceback of the synchronous formatting process.
|
||||
*/
|
||||
type LogLevel = "error" | "warn" | "info" | "debug" | "trace";
|
||||
|
||||
/**
|
||||
* Options to format text with Prettier and ESLint.
|
||||
*/
|
||||
interface Options {
|
||||
/**
|
||||
* The config to use for formatting with ESLint.
|
||||
*/
|
||||
eslintConfig?: eslint.Linter.Config;
|
||||
/**
|
||||
* The path to the eslint module to use.
|
||||
* Will default to require.resolve('eslint')
|
||||
*/
|
||||
eslintPath?: string;
|
||||
/**
|
||||
* The options to pass for formatting with `prettier` if the given
|
||||
* option is not inferrable from the `eslintConfig`.
|
||||
*/
|
||||
fallbackPrettierOptions?: prettier.Options;
|
||||
/**
|
||||
* The path of the file being formatted can be used in lieu of
|
||||
* `eslintConfig` (eslint will be used to find the relevant
|
||||
* config for the file). Will also be used to load the `text` if
|
||||
* `text` is not provided.
|
||||
*/
|
||||
filePath?: string;
|
||||
/**
|
||||
* The level for the logs (`error`, `warn`, `info`, `debug`, `trace`).
|
||||
*/
|
||||
logLevel?: LogLevel;
|
||||
/**
|
||||
* The options to pass for formatting with `prettier`. If not provided,
|
||||
* prettier-eslint will attempt to create the options based on the
|
||||
* `eslintConfig` value.
|
||||
*/
|
||||
prettierOptions?: prettier.Options;
|
||||
/**
|
||||
* The path to the `prettier` module.
|
||||
* Will default to require.resovlve('prettier')
|
||||
*/
|
||||
prettierPath?: string;
|
||||
/**
|
||||
* Run Prettier last.
|
||||
*/
|
||||
prettierLast?: boolean;
|
||||
/**
|
||||
* The text (JavaScript code) to format.
|
||||
*/
|
||||
text: string;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the text with Prettier and then ESLint while obeying the user's
|
||||
* configuration.
|
||||
*
|
||||
* @param options Options to format text with Prettier and Eslint.
|
||||
* @param options.eslintConfig The config to use for formatting
|
||||
* with ESLint.
|
||||
* @param options.eslintPath The path to the eslint module to use.
|
||||
* Will default to require.resolve('eslint')
|
||||
* @param options.fallbackPrettierOptions The options to pass for
|
||||
* formatting with `prettier` if the given option is not inferrable from the
|
||||
* eslintConfig.
|
||||
* @param options.filePath The path of the file being formatted
|
||||
* can be used in lieu of `eslintConfig` (eslint will be used to find the
|
||||
* relevant config for the file). Will also be used to load the `text` if
|
||||
* `text` is not provided.
|
||||
* @param options.prettierOptions The options to pass for
|
||||
* formatting with `prettier`. If not provided, prettier-eslint will attempt
|
||||
* to create the options based on the `eslintConfig` value.
|
||||
* @param options.prettierLast Run Prettier last.
|
||||
* @param options.prettierPath The path to the prettier module.
|
||||
* Will default to require.resovlve('prettier')
|
||||
* @param options.logLevel The level for the logs (`error`, `warn`,
|
||||
* `info`, `debug`, `trace`).
|
||||
* @param options.text The text (JavaScript code) to format.
|
||||
* @return Auto-formatted text that is mostly compliant with the
|
||||
* supplied configuration. The auto-formatting is limited to the issues that
|
||||
* Prettier and ESLint can automatically fix.
|
||||
*/
|
||||
declare function format(options: format.Options): Promise<string>;
|
||||
|
||||
export = format;
|
||||
Reference in New Issue
Block a user