@mizdra/eslint-interactive
Advanced tools
Comparing version 0.1.0 to 0.2.0
import { ESLint, Rule } from 'eslint'; | ||
declare type CachedESLintOptions = { | ||
rulePaths?: string[]; | ||
extensions?: string[]; | ||
}; | ||
export declare class CachedESLint { | ||
@@ -6,3 +10,3 @@ readonly patterns: string[]; | ||
readonly defaultOptions: ESLint.Options; | ||
constructor(patterns: string[]); | ||
constructor(patterns: string[], options?: CachedESLintOptions); | ||
lint(): Promise<ESLint.LintResult[]>; | ||
@@ -13,2 +17,3 @@ printResults(results: ESLint.LintResult[]): void; | ||
} | ||
export {}; | ||
//# sourceMappingURL=cached-eslint.d.ts.map |
@@ -21,3 +21,3 @@ "use strict"; | ||
class CachedESLint { | ||
constructor(patterns) { | ||
constructor(patterns, options) { | ||
this.patterns = patterns; | ||
@@ -29,2 +29,4 @@ const linter = new eslint_1.Linter(); | ||
cacheLocation: path_1.join(os_1.tmpdir(), `eslint-interactive--${Date.now()}-${Math.random()}`), | ||
rulePaths: options === null || options === void 0 ? void 0 : options.rulePaths, | ||
extensions: options === null || options === void 0 ? void 0 : options.extensions, | ||
}; | ||
@@ -31,0 +33,0 @@ } |
@@ -15,7 +15,19 @@ "use strict"; | ||
async function run(options) { | ||
const argv = yargs_1.default(options.argv.slice(2)).argv; | ||
var _a, _b; | ||
const argv = yargs_1.default(options.argv.slice(2)) | ||
.usage('$0 [file.js] [dir]') | ||
.option('ruledir', { | ||
type: 'array', | ||
describe: 'Use additional rules from this directory', | ||
}) | ||
.option('ext', { | ||
type: 'array', | ||
describe: 'Specify JavaScript file extensions', | ||
}).argv; | ||
// NOTE: convert `string` type because yargs convert `'10'` (`string` type) into `10` (`number` type) | ||
// and `lintFiles` only accepts `string[]`. | ||
const patterns = argv._.map((pattern) => pattern.toString()); | ||
const eslint = new cached_eslint_1.CachedESLint(patterns); | ||
const rulePaths = (_a = argv.ruledir) === null || _a === void 0 ? void 0 : _a.map((rulePath) => rulePath.toString()); | ||
const extensions = (_b = argv.ext) === null || _b === void 0 ? void 0 : _b.map((extension) => extension.toString()).flatMap((extension) => extension.split(',')); | ||
const eslint = new cached_eslint_1.CachedESLint(patterns, { rulePaths, extensions }); | ||
// eslint-disable-next-line no-constant-condition | ||
@@ -22,0 +34,0 @@ while (true) { |
{ | ||
"name": "@mizdra/eslint-interactive", | ||
"description": "The CLI tool to run `eslint --fix` for each rule", | ||
"version": "0.1.0", | ||
"version": "0.2.0", | ||
"repository": "https://github.com/mizdra/eslint-interactive.git", | ||
@@ -11,3 +11,3 @@ "author": "mizdra <pp.mizdra@gmail.com>", | ||
"build": "tsc -p tsconfig.src.json", | ||
"dev": "tsc-watch -p tsconfig.src.json --onSuccess 'bin/eslint-interactive fixtures'", | ||
"dev": "tsc-watch -p tsconfig.src.json --onSuccess 'bin/eslint-interactive fixtures --ruledir fixtures/rules --ext .js,.mjs'", | ||
"check": "run-s -c check:*", | ||
@@ -14,0 +14,0 @@ "check:tsc": "run-s -c check:tsc:*", |
@@ -7,3 +7,3 @@ # eslint-interactive | ||
[You can see the demo movie here.](https://youtu.be/UKrm4v-jdbw) | ||
# :eyes: **[You can see the demo movie here.](https://youtu.be/UKrm4v-jdbw)** :eyes: | ||
@@ -14,17 +14,53 @@ [![Watch the video](https://img.youtube.com/vi/UKrm4v-jdbw/maxresdefault.jpg)](https://youtu.be/UKrm4v-jdbw) | ||
TODO | ||
The default ESLint output contains a lot of useful information for developers, such as the source of the error and hints for fixing it. While this works for many use cases, it does not work well in situations where many errors are reported. For example, when introducing ESLint into a project, or when making big changes to the `.eslintrc` of a project. In these situations, the output of ESLint can be quite large, making it difficult for developers to analyze the output. It is also difficult for the developer to fix errors because many types of errors are mixed up in the output. | ||
## What's the difference between [IanVS/eslint-nibble](https://github.com/IanVS/eslint-nibble)? | ||
In such an error-prone situation, I think two things are important: | ||
TODO | ||
- Show a summary of all errors so that the whole picture can be easily understood | ||
- Showing the details of each error will confuse developers. | ||
- Provide an efficient way to fix many errors | ||
- `eslint --fix` is one of the best ways to fix errors efficiently, but it auto-fixes all rule errors at once. | ||
- Depending on the rule, auto-fix may affect the behavior of the code, so auto-fix should be done with care. | ||
- Therefore, it is desirable to provide a way to auto-fix in smaller units than `eslint --fix`. | ||
So, I created a tool called `eslint-interactive` which wraps ESLint. This tool groups all errors by rule and outputs the number of errors per rule in a formatted format. In addition to the breakdown of _warnings_ and _errors_ per rule, it also outputs the number of fixable errors and other hints to help developers fix errors. You can also specify a number of rules to display raw ESLint error messages or to auto-fix. | ||
## What's the difference between [eslint-nibble](https://github.com/IanVS/eslint-nibble)? | ||
A tool similar to `eslint-interactive` is [eslint-nibble](https://github.com/IanVS/eslint-nibble). Both tools solve the same problem, but `eslint-interactive` has some features that `eslint-nibble` does not have. For example, `eslint-interactive` prints the number of fixable errors per rule, while `eslint-nibble` does not. Also, `eslint-interactive` has various tricks to speed up the cycle of auto-fixing per-rule, but `eslint-nibble` auto-fixes once and terminates the process every time, so it is not as fast as `eslint- interactive`. | ||
I think these features are very important to solve the aforementioned problem. At first, I thought of implementing these features in `eslint-nibble`, but it required a major rewrite of the code, so I implemented it as a new `eslint-interactive`. Although `eslint-interactive` is a tool independent of `eslint-nibble`, it is influenced by the ideas of `eslint-nibble` and inherits some of its code. That's why you can find the names of [@IanVS](https://github.com/IanVS) and others in [the license of `eslint-interactive`](https://github.com/mizdra/eslint-interactive/blob/master/LICENSE). | ||
Thanks, [@IanVS](https://github.com/IanVS). | ||
## Installation | ||
```bash | ||
$ npm i -g eslint @mizdra/eslint-interactive | ||
$ eslint-interactive --help | ||
$ # or npx | ||
$ npx -p eslint -p @mizdra/eslint-interactive eslint-interactive --help | ||
``` | ||
## Usage | ||
```bash | ||
$ npx -p eslint -p @mizdra/eslint-interactive eslint-interactive [file.js] [dir] | ||
$ # Show help | ||
$ eslint-interactive --help | ||
eslint-interactive [file.js] [dir] | ||
Options: | ||
--help Show help [boolean] | ||
--version Show version number [boolean] | ||
--ruledir Use additional rules from this directory [array] | ||
--ext Specify JavaScript file extensions [array] | ||
$ # Examples | ||
$ npx -p eslint -p @mizdra/eslint-interactive eslint-interactive src | ||
$ npx -p eslint -p @mizdra/eslint-interactive eslint-interactive src test | ||
$ npx -p eslint -p @mizdra/eslint-interactive eslint-interactive 'src/**/*.{ts,tsx,vue}' | ||
$ eslint-interactive src | ||
$ eslint-interactive src test | ||
$ eslint-interactive 'src/**/*.{ts,tsx,vue}' | ||
$ eslint-interactive src --ext .ts,.tsx,.vue | ||
$ eslint-interactive src --ruledir ./rules | ||
``` | ||
@@ -34,5 +70,2 @@ | ||
- [ ] Support `-c, --config path::String` option | ||
- [ ] Support `--ext [String]` option | ||
- [ ] Support `--rulesdir` option | ||
- [ ] Support `--no-pager` option | ||
@@ -39,0 +72,0 @@ - [ ] Print the url of rule's documentation |
@@ -16,2 +16,7 @@ import { tmpdir } from 'os'; | ||
type CachedESLintOptions = { | ||
rulePaths?: string[]; | ||
extensions?: string[]; | ||
}; | ||
export class CachedESLint { | ||
@@ -22,3 +27,3 @@ readonly patterns: string[]; | ||
constructor(patterns: string[]) { | ||
constructor(patterns: string[], options?: CachedESLintOptions) { | ||
this.patterns = patterns; | ||
@@ -30,2 +35,4 @@ const linter = new Linter(); | ||
cacheLocation: join(tmpdir(), `eslint-interactive--${Date.now()}-${Math.random()}`), | ||
rulePaths: options?.rulePaths, | ||
extensions: options?.extensions, | ||
}; | ||
@@ -32,0 +39,0 @@ } |
@@ -14,8 +14,22 @@ import chalk from 'chalk'; | ||
export async function run(options: Options) { | ||
const argv = yargs(options.argv.slice(2)).argv; | ||
const argv = yargs(options.argv.slice(2)) | ||
.usage('$0 [file.js] [dir]') | ||
.option('ruledir', { | ||
type: 'array', | ||
describe: 'Use additional rules from this directory', | ||
}) | ||
.option('ext', { | ||
type: 'array', | ||
describe: 'Specify JavaScript file extensions', | ||
}).argv; | ||
// NOTE: convert `string` type because yargs convert `'10'` (`string` type) into `10` (`number` type) | ||
// and `lintFiles` only accepts `string[]`. | ||
const patterns = argv._.map((pattern) => pattern.toString()); | ||
const rulePaths = argv.ruledir?.map((rulePath) => rulePath.toString()); | ||
const extensions = argv.ext | ||
?.map((extension) => extension.toString()) | ||
// map '.js,.ts' into ['.js', '.ts'] | ||
.flatMap((extension) => extension.split(',')); | ||
const eslint = new CachedESLint(patterns); | ||
const eslint = new CachedESLint(patterns, { rulePaths, extensions }); | ||
@@ -22,0 +36,0 @@ // eslint-disable-next-line no-constant-condition |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
113616
669
93