diff --git a/README.md b/README.md index b70f6be..59c1fcd 100644 --- a/README.md +++ b/README.md @@ -18,8 +18,8 @@ npm install umi-lint --save-dev ```diff "scripts": { -+ "lint": "umi-lint src/", -+ "precommit": "umi-lint --staged --stylelint --prettier --fix", ++ "lint": "umi-lint --eslint src/", ++ "precommit": "umi-lint --staged --eslint --stylelint --prettier --fix", } ``` @@ -30,10 +30,10 @@ npm install umi-lint --save-dev Usage: umi-lint [options] file.js [file.js] [dir] # 对指定路径 lint -umi-lint --prettier --stylelint src/ +umi-lint --prettier --eslint --stylelint src/ # 只对提交的代码进行 lint -umi-lint --staged --prettier --stylelint +umi-lint --staged --prettier --eslint --stylelint # 对于某些场景需要指定 lint 工具的子参数 umi-lint --eslint.debug --tslint.force -s.formatter=json -p.no-semi @@ -41,8 +41,8 @@ umi-lint --eslint.debug --tslint.force -s.formatter=json -p.no-semi Options: --staged, -S only lint git staged files [boolean] [default: false] --prettier, -p format code with prettier [boolean] [default: false] ---eslint, -e enable lint javascript [boolean] [default: true] ---tslint, -t enable lint typescript [boolean] [default: true] +--eslint, -e enable lint javascript [boolean] [default: false] +--tslint, -t enable lint typescript [boolean] [default: false] --stylelint, --style, -s enable lint style [boolean] [default: false] --fix, -f fix all eslint and stylelint auto-fixable problems [boolean] [default: false] --quiet, -q report errors only [boolean] [default: false] @@ -51,4 +51,16 @@ Options: ## 问题解决 +### 常见问题 + +#### Q: 没有配置文件 + +A: `umi-lint` 不包含配置,需要根据需求自己配置 `.eslintrc`、`.stylelintrc`、`.prettierrc` + +#### Q: 使用 eslint 来检查 typescript + +A: `umi-lint --eslint.ext='.tx,tsx'`, + +### 钉钉群 + diff --git a/package.json b/package.json index 10237d6..2741102 100644 --- a/package.json +++ b/package.json @@ -4,8 +4,8 @@ "description": "configless lint tool all in one", "bin": "bin/umi-lint.js", "scripts": { - "lint": "umi-lint bin/ src/", - "precommit": "umi-lint --staged --prettier --fix", + "lint": "umi-lint --eslint bin/ src/", + "precommit": "umi-lint --staged --eslint --prettier --fix", "test": "umi-test" }, "repository": { @@ -39,6 +39,8 @@ "tslint": "^5.12.1" }, "devDependencies": { + "@typescript-eslint/eslint-plugin": "^1.4.2", + "@typescript-eslint/parser": "^1.4.2", "coffee": "^5.2.1", "eslint-config-airbnb-base": "^13.1.0", "eslint-config-egg": "^7.1.0", diff --git a/src/index.js b/src/index.js index 3a4b803..067833d 100644 --- a/src/index.js +++ b/src/index.js @@ -4,7 +4,7 @@ const Command = require('common-bin'); const { sync: resolveBin } = require('resolve-bin'); const { join } = require('path'); const { writeFileSync } = require('fs'); -const { endsWithArray, getFiles, parseSubOptions } = require('./utils'); +const { endsWithArray, getFiles, parseSubOptions, getEslintExtensions } = require('./utils'); const debug = require('debug')('umi-lint'); class MainCommand extends Command { @@ -49,9 +49,11 @@ Usage: umi-lint [options] file.js [file.js] [dir] try { const jobs = []; // eslint can be disable - if (eslint !== false) { + if (eslint) { + const eslintOptions = parseSubOptions(eslint); + const eslintExtensions = getEslintExtensions(eslintOptions); // TODO, 效率可能不高, 先实现再验证 - const files = allFiles.filter(item => endsWithArray(item, ['.js', '.jsx'])); + const files = allFiles.filter(item => endsWithArray(item, eslintExtensions)); if (files.length > 0) { jobs.push( this.helper.forkNode( @@ -65,7 +67,7 @@ Usage: umi-lint [options] file.js [file.js] [dir] } } - if (tslint !== false) { + if (tslint) { const files = allFiles.filter(item => endsWithArray(item, ['.ts', '.tsx'])); if (files.length > 0) { jobs.push( @@ -127,6 +129,9 @@ Usage: umi-lint [options] file.js [file.js] [dir] const lintStaged = resolveBin('lint-staged'); const commonOpts = `${fix ? '--fix' : ''} ${quiet ? '--quiet' : ''}`; + const eslintOptions = parseSubOptions(eslint); + const eslintExtensions = getEslintExtensions(eslintOptions); + // generate dynamic configuration const lintstagedrc = { ...(prettier && { @@ -135,10 +140,13 @@ Usage: umi-lint [options] file.js [file.js] [dir] 'git add', ], }), - ...(eslint !== false && { - '*.{js,jsx}': [`eslint ${commonOpts} ${parseSubOptions(eslint).join(' ')}`, 'git add'], + ...(eslint && { + [`*.{${eslintExtensions.join(',')}}`]: [ + `eslint ${commonOpts} ${parseSubOptions(eslint).join(' ')}`, + 'git add', + ], }), - ...(tslint !== false && { + ...(tslint && { '*.{ts,tsx}': [`tslint ${commonOpts} ${parseSubOptions(tslint).join(' ')}`, 'git add'], }), ...(stylelint && { diff --git a/src/options.js b/src/options.js index 2f53da6..efcdc3f 100644 --- a/src/options.js +++ b/src/options.js @@ -16,13 +16,13 @@ module.exports = { eslint: { description: 'enabel lint javascript', boolean: true, - default: true, + default: false, alias: 'e', }, tslint: { description: 'enable lint typescript', boolean: true, - default: true, + default: false, alias: 't', }, stylelint: { diff --git a/src/utils.js b/src/utils.js index d671fe9..1eb1662 100644 --- a/src/utils.js +++ b/src/utils.js @@ -45,4 +45,11 @@ module.exports = { } return []; }, + getEslintExtensions: options => { + const index = options.indexOf('--ext'); + if (index !== -1) { + return options[index + 1].split(','); + } + return ['.js', '.jsx']; + }, }; diff --git a/test/fixture/lint/prettier/.prettierrc b/test/fixture/lint/prettier/.prettierrc index c6a1376..4cc6aa6 100644 --- a/test/fixture/lint/prettier/.prettierrc +++ b/test/fixture/lint/prettier/.prettierrc @@ -1,4 +1,5 @@ { "trailingComma": "es5", - "singleQuote": true + "singleQuote": true, + "printWidth": 100 } diff --git a/test/fixture/lint/ts/.eslintrc b/test/fixture/lint/ts/.eslintrc new file mode 100644 index 0000000..50e3f0c --- /dev/null +++ b/test/fixture/lint/ts/.eslintrc @@ -0,0 +1,3 @@ +{ + "extends": ["plugin:@typescript-eslint/recommended"] +} \ No newline at end of file diff --git a/test/lint.test.js b/test/lint.test.js index 396fc6a..d6a0f9c 100644 --- a/test/lint.test.js +++ b/test/lint.test.js @@ -1,82 +1,103 @@ -"use strict"; +'use strict'; -const path = require("path"); -const coffee = require("coffee"); +const path = require('path'); +const coffee = require('coffee'); -describe("test lint command", () => { - const umiLint = path.resolve("./bin/umi-lint"); - const cwd = path.join(__dirname, "fixture/lint/"); +describe('test lint command', () => { + const umiLint = path.resolve('./bin/umi-lint'); + const cwd = path.join(__dirname, 'fixture/lint/'); - it("lint js", done => { + it('lint js', done => { coffee - .fork(umiLint, ["./js"], { cwd }) + .fork(umiLint, ['./js', '--eslint'], { cwd }) // .debug() - .expect("stdout", /no-unused-vars/) - .expect("stdout", /✖ 2 problems \(1 error, 1 warning\)/) - .expect("code", 1) + .expect('stdout', /no-unused-vars/) + .expect('stdout', /✖ 2 problems \(1 error, 1 warning\)/) + .expect('code', 1) .end(done); }); - - it("lint js with sub options", done => { + + it('lint js with sub options', done => { coffee - .fork(umiLint, ["./js", "--eslint.quiet"], { cwd }) + .fork(umiLint, ['./js', '--eslint.quiet'], { cwd }) // .debug() - .expect("stdout", /✖ 1 problem \(1 error, 0 warnings\)/) - .expect("code", 1) + .expect('stdout', /✖ 1 problem \(1 error, 0 warnings\)/) + .expect('code', 1) .end(done); }); - it("lint ts", done => { + it('lint ts with eslint', done => { coffee - .fork(umiLint, ["./ts"], { cwd }) - // .debug() - .expect("stdout", /Type declaration of 'any' loses type-safety. Consider replacing it with a more precise type/) - .expect("stdout", /Calls to 'console.log' are not allowed/) - .expect("code", 2) - .end(done); + .fork(umiLint, ['./ts', '--eslint.ext', '.ts,tsx'], { cwd }) + // .debug() + .expect('stdout', /✖ 5 problems \(1 error, 4 warnings\)/) + .expect('code', 1) + .end(done); }); - it("lint ts with sub options", done => { + it('lint ts', done => { coffee - .fork(umiLint, ["./ts", "--t", "--tslint.force"], { cwd }) - // .debug() - .expect("code", 0) - .end(done); + .fork(umiLint, ['./ts', '--tslint'], { cwd }) + // .debug() + .expect( + 'stdout', + /Type declaration of 'any' loses type-safety. Consider replacing it with a more precise type/ + ) + .expect('stdout', /Calls to 'console.log' are not allowed/) + .expect('code', 2) + .end(done); + }); + + it('lint ts with sub options', done => { + coffee + .fork(umiLint, ['./ts', '--t', '--tslint.force'], { cwd }) + // .debug() + .expect('code', 0) + .end(done); }); - it("lint style", done => { + it('lint style', done => { coffee - .fork(umiLint, ["./style", "--stylelint"], { cwd }) - // .debug() - .expect("stdout", /✖ Unexpected missing generic font family font-family-no-missing-generic-family-keyword/) - .expect("code", 2) - .end(done); + .fork(umiLint, ['./style', '--stylelint'], { cwd }) + // .debug() + .expect( + 'stdout', + /✖ Unexpected missing generic font family font-family-no-missing-generic-family-keyword/ + ) + .expect('code', 2) + .end(done); }); - it("lint style with sub options", done => { + it('lint style with sub options', done => { coffee - .fork(umiLint, ["./style", "--stylelint", "-s.formatter", "json"], { cwd }) - // .debug() - .expect("stdout", /"text":"Unexpected missing generic font family/) - .expect("code", 2) - .end(done); + .fork(umiLint, ['./style', '--stylelint', '-s.formatter', 'json'], { cwd }) + // .debug() + .expect('stdout', /"text":"Unexpected missing generic font family/) + .expect('code', 2) + .end(done); }); - it("use prettier", done => { + it('use prettier', done => { coffee - .fork(umiLint, ["./prettier", "--prettier", "--eslint", false], { cwd, env: {FROM_TEST: true}}) - // .debug() - .expect("stdout", /const hello = 'aaa';/) - .expect("code", 0) - .end(done); + .fork(umiLint, ['./prettier', '--prettier', '--eslint', false], { + cwd, + env: { FROM_TEST: true }, + }) + // .debug() + .expect('stdout', /const hello = 'aaa';/) + .expect('code', 0) + .end(done); }); - it("use prettier with sub options", done => { + it('use prettier with sub options', done => { coffee - .fork(umiLint, ["./prettier", "--prettier", "--eslint", false, "-p.no-semi"], { cwd, env: {FROM_TEST: true}}) - // .debug() - .expect("stdout", /const hello = 'aaa'/) - .expect("code", 0) - .end(done); + .fork(umiLint, ['./prettier', '--prettier', '--eslint', false, '-p.no-semi'], { + cwd, + env: { FROM_TEST: true }, + }) + // .debug() + .expect('stdout', /const hello = 'aaa'/) + .expect('code', 0) + .end(done); }); });