Skip to content

Commit dd04add

Browse files
committed
feat: support using ESLint to lint TypeScript
1 parent 364fddf commit dd04add

File tree

20 files changed

+255
-49
lines changed

20 files changed

+255
-49
lines changed

__mocks__/inquirer.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,15 @@ exports.prompt = prompts => {
3939
expect(message).toMatch(a.message)
4040
}
4141

42+
const choices = typeof prompt.choices === 'function'
43+
? prompt.choices(answers)
44+
: prompt.choices
4245
if (a.choices) {
43-
expect(prompt.choices.length).toBe(a.choices.length)
46+
expect(choices.length).toBe(a.choices.length)
4447
a.choices.forEach((c, i) => {
4548
const expected = a.choices[i]
4649
if (expected) {
47-
expect(prompt.choices[i].name).toMatch(expected)
50+
expect(choices[i].name).toMatch(expected)
4851
}
4952
})
5053
}
@@ -56,12 +59,12 @@ exports.prompt = prompts => {
5659

5760
if (a.choose != null) {
5861
expect(prompt.type === 'list' || prompt.type === 'rawList').toBe(true)
59-
setValue(prompt.choices[a.choose].value)
62+
setValue(choices[a.choose].value)
6063
}
6164

6265
if (a.check != null) {
6366
expect(prompt.type).toBe('checkbox')
64-
setValue(a.check.map(i => prompt.choices[i].value))
67+
setValue(a.check.map(i => choices[i].value))
6568
}
6669

6770
if (a.confirm != null) {

packages/@vue/cli-plugin-eslint/__tests__/eslintGenerator.spec.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,30 @@ test('prettier', async () => {
6161
expect(pkg.devDependencies).toHaveProperty('@vue/eslint-config-prettier')
6262
})
6363

64+
test('typescript', async () => {
65+
const { pkg } = await generateWithPlugin([
66+
{
67+
id: 'eslint',
68+
apply: require('../generator'),
69+
options: {
70+
config: 'prettier'
71+
}
72+
},
73+
{
74+
id: 'typescript',
75+
apply: require('@vue/cli-plugin-typescript/generator'),
76+
options: {}
77+
}
78+
])
79+
80+
expect(pkg.scripts.lint).toBeTruthy()
81+
expect(pkg.eslintConfig).toEqual({
82+
extends: ['plugin:vue/essential', '@vue/prettier', '@vue/typescript']
83+
})
84+
expect(pkg.devDependencies).toHaveProperty('@vue/eslint-config-prettier')
85+
expect(pkg.devDependencies).toHaveProperty('@vue/eslint-config-typescript')
86+
})
87+
6488
test('lint on save', async () => {
6589
const { pkg } = await generateWithPlugin({
6690
id: 'eslint',
Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
1-
module.exports = {
2-
extensions: ['.js', '.vue'],
3-
parserOptions: {
4-
parser: require.resolve('babel-eslint')
5-
},
6-
globals: ['process'],
7-
rules: {
8-
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
9-
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
1+
module.exports = api => {
2+
const options = {
3+
extensions: ['.js', '.vue'],
4+
globals: ['process'],
5+
rules: {
6+
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
7+
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
8+
}
109
}
10+
11+
if (api.hasPlugin('typescript')) {
12+
options.extensions.push('.ts')
13+
} else {
14+
options.parserOptions = {
15+
parser: require.resolve('babel-eslint')
16+
}
17+
}
18+
19+
return options
1120
}

packages/@vue/cli-plugin-eslint/generator.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ module.exports = (api, { config, lintOn = [] }) => {
3333
pkg.eslintConfig.extends.push('eslint:recommended')
3434
}
3535

36+
// typescript support
37+
if (api.hasPlugin('typescript')) {
38+
pkg.eslintConfig.extends.push('@vue/typescript')
39+
Object.assign(pkg.devDependencies, {
40+
'@vue/eslint-config-typescript': '^3.0.0-alpha.9'
41+
})
42+
}
43+
3644
if (lintOn.includes('save')) {
3745
pkg.vue = {
3846
lintOnSave: true // eslint-loader configured in runtime plugin
@@ -71,7 +79,7 @@ module.exports = (api, { config, lintOn = [] }) => {
7179
// lint & fix after create to ensure files adhere to chosen config
7280
if (config && config !== 'base') {
7381
api.onCreateComplete(() => {
74-
require('./lint')(api.resolve('.'), { silent: true })
82+
require('./lint')({ silent: true }, api)
7583
})
7684
}
7785
}

packages/@vue/cli-plugin-eslint/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module.exports = (api, { lintOnSave }) => {
22
if (lintOnSave) {
3-
const options = require('./eslintOptions')
3+
const options = require('./eslintOptions')(api)
44
api.chainWebpack(webpackConfig => {
55
webpackConfig.module
66
.rule('eslint')
@@ -27,6 +27,6 @@ module.exports = (api, { lintOnSave }) => {
2727
},
2828
details: 'For more options, see https://eslint.org/docs/user-guide/command-line-interface#options'
2929
}, args => {
30-
require('./lint')(api.resolve('.'), args)
30+
require('./lint')(args, api)
3131
})
3232
}

packages/@vue/cli-plugin-eslint/lint.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
module.exports = function lint (cwd, args = {}) {
1+
module.exports = function lint (args = {}, api) {
2+
const cwd = api.resolve('.')
23
const { CLIEngine } = require('eslint')
3-
const options = require('./eslintOptions')
4+
const options = require('./eslintOptions')(api)
45
const { done } = require('@vue/cli-shared-utils')
56

67
const files = args._ && args._.length ? args._ : ['src', 'test']

packages/@vue/cli-plugin-typescript/__tests__/tsGenerator.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ test('lint', async () => {
6565
id: 'ts',
6666
apply: require('../generator'),
6767
options: {
68-
lint: true,
68+
tsLint: true,
6969
lintOn: ['save', 'commit']
7070
}
7171
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
jest.setTimeout(10000)
2+
3+
const create = require('@vue/cli-test-utils/createTestProject')
4+
5+
test('should work', async () => {
6+
const project = await create('ts-lint', {
7+
plugins: {
8+
'@vue/cli-plugin-eslint': {
9+
config: 'prettier'
10+
},
11+
'@vue/cli-plugin-typescript': {
12+
classComponent: true
13+
}
14+
}
15+
})
16+
const { read, write, run } = project
17+
const main = await read('src/main.ts')
18+
expect(main).toMatch(';')
19+
const app = await read('src/App.vue')
20+
expect(main).toMatch(';')
21+
// remove semicolons
22+
const updatedMain = main.replace(/;/g, '')
23+
await write('src/main.ts', updatedMain)
24+
// for Vue file, only remove semis in script section
25+
const updatedApp = app.replace(/<script(.|\n)*\/script>/, $ => {
26+
return $.replace(/;/g, '')
27+
})
28+
await write('src/App.vue', updatedApp)
29+
// lint
30+
await run('vue-cli-service lint')
31+
expect(await read('src/main.ts')).toMatch(';')
32+
33+
const lintedApp = await read('src/App.vue')
34+
expect(lintedApp).toMatch(';')
35+
// test if ESLint is fixing vue files properly
36+
expect(lintedApp).toBe(app)
37+
})

packages/@vue/cli-plugin-typescript/__tests__/tsPluginLint.spec.js renamed to packages/@vue/cli-plugin-typescript/__tests__/tsPluginTSLint.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ test('should work', async () => {
66
const project = await create('ts-lint', {
77
plugins: {
88
'@vue/cli-plugin-typescript': {
9-
lint: true
9+
tsLint: true
1010
}
1111
}
1212
})

packages/@vue/cli-plugin-typescript/generator/index.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module.exports = (api, {
22
classComponent,
3-
lint,
3+
tsLint,
44
lintOn = [],
55
experimentalCompileTsWithBabel
66
}) => {
@@ -46,7 +46,7 @@ module.exports = (api, {
4646
}
4747
}
4848

49-
if (lint) {
49+
if (tsLint && !api.hasPlugin('eslint')) {
5050
api.extendPackage({
5151
scripts: {
5252
lint: 'vue-cli-service lint'
@@ -98,8 +98,6 @@ module.exports = (api, {
9898
})
9999
}
100100

101-
// TODO cater to e2e test plugins
102-
103101
api.render('./template', {
104102
isTest: process.env.VUE_CLI_TEST || process.env.VUE_CLI_DEBUG,
105103
hasMocha,

0 commit comments

Comments
 (0)