diff --git a/docs/core-plugins/typescript.md b/docs/core-plugins/typescript.md index c466d2f537..393c704051 100644 --- a/docs/core-plugins/typescript.md +++ b/docs/core-plugins/typescript.md @@ -12,10 +12,6 @@ Since `3.0.0-rc.6`, `typescript` is now a peer dependency of this package, so yo This plugin can be used alongside `@vue/cli-plugin-babel`. When used with Babel, this plugin will output ES2015 and delegate the rest to Babel for auto polyfill based on browser targets. -## Injected Commands - -If opted to use [TSLint](https://palantir.github.io/tslint/) during project creation, `vue-cli-service lint` will be injected. - ## Caching [cache-loader](https://github.com/webpack-contrib/cache-loader) is enabled by default and cache is stored in `/node_modules/.cache/ts-loader`. diff --git a/docs/ru/core-plugins/typescript.md b/docs/ru/core-plugins/typescript.md index 5ce2c61e8c..75e37302c1 100644 --- a/docs/ru/core-plugins/typescript.md +++ b/docs/ru/core-plugins/typescript.md @@ -12,10 +12,6 @@ TypeScript может быть сконфигурирован через `tsconf Этот плагин может использоваться вместе с `@vue/cli-plugin-babel`. При использовании вместе с Babel, этот плагин должен генерировать ES2015 и делегировать остальное Babel для автоматического добавления полифилов на основе целевых браузеров. -## Внедряемые команды - -При выборе [TSLint](https://palantir.github.io/tslint/) на этапе создания проекта, будет внедряться команда `vue-cli-service lint`. - ## Кэширование [cache-loader](https://github.com/webpack-contrib/cache-loader) используется по умолчанию, кэш хранится в `/node_modules/.cache/ts-loader`. diff --git a/packages/@vue/cli-plugin-e2e-cypress/__tests__/cypressPlugin.spec.js b/packages/@vue/cli-plugin-e2e-cypress/__tests__/cypressPlugin.spec.js index a666c2ab29..d3c505cbdc 100644 --- a/packages/@vue/cli-plugin-e2e-cypress/__tests__/cypressPlugin.spec.js +++ b/packages/@vue/cli-plugin-e2e-cypress/__tests__/cypressPlugin.spec.js @@ -30,7 +30,6 @@ test('should work with TS', async () => { plugins: { '@vue/cli-plugin-typescript': { 'classComponent': true, - 'tsLint': true, 'lintOn': ['save'] }, '@vue/cli-plugin-e2e-cypress': {} diff --git a/packages/@vue/cli-plugin-e2e-webdriverio/__tests__/wdioPlugin.spec.js b/packages/@vue/cli-plugin-e2e-webdriverio/__tests__/wdioPlugin.spec.js index 8019cc9f43..c68db254f8 100644 --- a/packages/@vue/cli-plugin-e2e-webdriverio/__tests__/wdioPlugin.spec.js +++ b/packages/@vue/cli-plugin-e2e-webdriverio/__tests__/wdioPlugin.spec.js @@ -28,7 +28,6 @@ test('should work with TS', async () => { plugins: { '@vue/cli-plugin-typescript': { 'classComponent': true, - 'tsLint': true, 'lintOn': ['save'] }, '@vue/cli-plugin-e2e-webdriverio': { diff --git a/packages/@vue/cli-plugin-typescript/README.md b/packages/@vue/cli-plugin-typescript/README.md index c466d2f537..393c704051 100644 --- a/packages/@vue/cli-plugin-typescript/README.md +++ b/packages/@vue/cli-plugin-typescript/README.md @@ -12,10 +12,6 @@ Since `3.0.0-rc.6`, `typescript` is now a peer dependency of this package, so yo This plugin can be used alongside `@vue/cli-plugin-babel`. When used with Babel, this plugin will output ES2015 and delegate the rest to Babel for auto polyfill based on browser targets. -## Injected Commands - -If opted to use [TSLint](https://palantir.github.io/tslint/) during project creation, `vue-cli-service lint` will be injected. - ## Caching [cache-loader](https://github.com/webpack-contrib/cache-loader) is enabled by default and cache is stored in `/node_modules/.cache/ts-loader`. diff --git a/packages/@vue/cli-plugin-typescript/__tests__/tsConvertLintFlags.spec.js b/packages/@vue/cli-plugin-typescript/__tests__/tsConvertLintFlags.spec.js deleted file mode 100644 index 322f525437..0000000000 --- a/packages/@vue/cli-plugin-typescript/__tests__/tsConvertLintFlags.spec.js +++ /dev/null @@ -1,19 +0,0 @@ -const fn = require('../lib/convertLintFlags') - -test('convert ESLint flags to TSLint flags', () => { - expect(fn(` -/* eslint-disable */ -/* eslint-disable no-console, foo-bar, haha */ -// eslint-disable-next-line -// eslint-disable-next-line no-console, foo-bar, haha -foo() // eslint-disable-line -foo() // eslint-disable-line no-console, foo-bar, haha - `)).toMatch(` -/* tslint:disable */ -/* tslint:disable:no-console, foo-bar, haha */ -// tslint:disable-next-line -// tslint:disable-next-line:no-console, foo-bar, haha -foo() // tslint:disable-line -foo() // tslint:disable-line:no-console, foo-bar, haha - `) -}) diff --git a/packages/@vue/cli-plugin-typescript/__tests__/tsGenerator.spec.js b/packages/@vue/cli-plugin-typescript/__tests__/tsGenerator.spec.js index 83cfc0a11e..1603917fd0 100644 --- a/packages/@vue/cli-plugin-typescript/__tests__/tsGenerator.spec.js +++ b/packages/@vue/cli-plugin-typescript/__tests__/tsGenerator.spec.js @@ -80,43 +80,6 @@ test('use with router', async () => { expect(files['src/views/Home.vue']).toMatch('
') }) -test('lint', async () => { - const { pkg, files } = await generateWithPlugin([ - { - id: 'ts', - apply: require('../generator'), - options: { - tsLint: true, - lintOn: ['save', 'commit'] - } - } - ]) - - expect(pkg.scripts.lint).toBe(`vue-cli-service lint`) - expect(pkg.devDependencies).toHaveProperty('lint-staged') - expect(pkg.gitHooks).toEqual({ 'pre-commit': 'lint-staged' }) - expect(pkg['lint-staged']).toEqual({ - '*.ts': ['vue-cli-service lint', 'git add'], - '*.vue': ['vue-cli-service lint', 'git add'] - }) - - expect(files['tslint.json']).toBeTruthy() -}) - -test('lint with no lintOnSave', async () => { - const { pkg } = await generateWithPlugin([ - { - id: 'ts', - apply: require('../generator'), - options: { - tsLint: true, - lintOn: ['commit'] - } - } - ]) - expect(pkg.vue).toEqual({ lintOnSave: false }) -}) - test('tsconfig.json should be valid json', async () => { const { files } = await generateWithPlugin([ { diff --git a/packages/@vue/cli-plugin-typescript/__tests__/tsPluginTSLint.spec.js b/packages/@vue/cli-plugin-typescript/__tests__/tsPluginTSLint.spec.js deleted file mode 100644 index cb82ea30fa..0000000000 --- a/packages/@vue/cli-plugin-typescript/__tests__/tsPluginTSLint.spec.js +++ /dev/null @@ -1,115 +0,0 @@ -jest.setTimeout(30000) - -const create = require('@vue/cli-test-utils/createTestProject') - -test('should work', async () => { - const project = await create('ts-tslint', { - plugins: { - '@vue/cli-plugin-typescript': { - tsLint: true - } - } - }) - const { read, write, run } = project - const main = await read('src/main.ts') - expect(main).toMatch(';') - const app = await read('src/App.vue') - expect(main).toMatch(';') - // remove semicolons - const updatedMain = main.replace(/;/g, '') - await write('src/main.ts', updatedMain) - // for Vue file, only remove semis in script section - const updatedApp = app.replace(//, $ => { - return $.replace(/;/g, '') - }) - await write('src/App.vue', updatedApp) - // lint - await run('vue-cli-service lint') - expect(await read('src/main.ts')).toMatch(';') - - const lintedApp = await read('src/App.vue') - expect(lintedApp).toMatch(';') - // test if tslint is fixing vue files properly - expect(lintedApp).toBe(app) -}) - -test('should not fix with --no-fix option', async () => { - const project = await create('ts-tslint-nofix', { - plugins: { - '@vue/cli-plugin-typescript': { - tsLint: true - } - } - }) - const { read, write, run } = project - const main = await read('src/main.ts') - expect(main).toMatch(';') - const app = await read('src/App.vue') - expect(main).toMatch(';') - // remove semicolons - const updatedMain = main.replace(/;/g, '') - await write('src/main.ts', updatedMain) - // for Vue file, only remove semis in script section - const updatedApp = app.replace(//, $ => { - return $.replace(/;/g, '') - }) - await write('src/App.vue', updatedApp) - - // lint with no fix should fail - try { - await run('vue-cli-service lint --no-fix') - } catch (e) { - expect(e.code).toBe(1) - expect(e.failed).toBeTruthy() - } - - // files should not have been fixed - expect(await read('src/main.ts')).not.toMatch(';') - expect((await read('src/App.vue')).match(//)[1]).not.toMatch(';') -}) - -test('should ignore issues in node_modules', async () => { - const project = await create('ts-lint-node_modules', { - plugins: { - '@vue/cli-plugin-typescript': { - tsLint: true - } - } - }) - - const { read, write, run } = project - const main = await read('src/main.ts') - - // update file to not match tslint spec and dump it into the node_modules directory - const updatedMain = main.replace(/;/g, '') - await write('node_modules/bad.ts', updatedMain) - - // lint - await run('vue-cli-service lint') - expect(await read('node_modules/bad.ts')).toMatch(updatedMain) -}) - -test('should be able to fix mixed line endings', async () => { - const project = await create('ts-lint-mixed-line-endings', { - plugins: { - '@vue/cli-plugin-typescript': { - tsLint: true - } - } - }) - - const { write, run } = project - - const b64 = 'PHRlbXBsYXRlPjwvdGVtcGxhdGU+DQoNCjxzY3JpcHQgbGFuZz0idHMiPg0KZXhwb3J0IGRlZmF1bHQgY2xhc3MgVGVzdCAgew0KICBnZXQgYXNzaWduZWUoKSB7DQogICAgdmFyIGl0ZW1zOnt0ZXh0OnN0cmluZzsgdmFsdWU6c3RyaW5nIHwgbnVtYmVyIHwgbnVsbH1bXSA9IFtdOw0KICAgIHJldHVybiBpdGVtczsNCiAgfQ0KDQp9DQo8L3NjcmlwdD4NCg0K' - const buf = Buffer.from(b64, 'base64') - - await write('src/bad.vue', buf) - - // Try twice to fix the file. - // For now, it will fail the first time, which corresponds to the behavior of tslint. - try { - await run('vue-cli-service lint -- src/bad.vue') - } catch (e) { } - - await run('vue-cli-service lint -- src/bad.vue') -}) diff --git a/packages/@vue/cli-plugin-typescript/generator/convert.js b/packages/@vue/cli-plugin-typescript/generator/convert.js index 37f93e8207..f056d4c3fd 100644 --- a/packages/@vue/cli-plugin-typescript/generator/convert.js +++ b/packages/@vue/cli-plugin-typescript/generator/convert.js @@ -1,12 +1,11 @@ -module.exports = (api, { tsLint = false, convertJsToTs = true } = {}) => { +module.exports = (api, { convertJsToTs = true } = {}) => { const jsRE = /\.js$/ let excludeRE = /^tests\/e2e\/|(\.config|rc)\.js$/ if (api.hasPlugin('e2e-webdriverio')) { excludeRE = /(\.config|rc)\.js$/ } - const convertLintFlags = require('../lib/convertLintFlags') - api.postProcessFiles(files => { + api.postProcessFiles((files) => { if (convertJsToTs) { // delete all js files that have a ts file of the same name // and simply rename other js files to ts @@ -14,10 +13,7 @@ module.exports = (api, { tsLint = false, convertJsToTs = true } = {}) => { if (jsRE.test(file) && !excludeRE.test(file)) { const tsFile = file.replace(jsRE, '.ts') if (!files[tsFile]) { - let content = files[file] - if (tsLint) { - content = convertLintFlags(content) - } + const content = files[file] files[tsFile] = content } delete files[file] @@ -26,10 +22,7 @@ module.exports = (api, { tsLint = false, convertJsToTs = true } = {}) => { } else { // rename only main file to main.ts const tsFile = api.entryFile.replace(jsRE, '.ts') - let content = files[api.entryFile] - if (tsLint) { - content = convertLintFlags(content) - } + const content = files[api.entryFile] files[tsFile] = content delete files[api.entryFile] } diff --git a/packages/@vue/cli-plugin-typescript/generator/index.js b/packages/@vue/cli-plugin-typescript/generator/index.js index 713bd33bfc..dc776d10b8 100644 --- a/packages/@vue/cli-plugin-typescript/generator/index.js +++ b/packages/@vue/cli-plugin-typescript/generator/index.js @@ -1,16 +1,11 @@ const pluginDevDeps = require('../package.json').devDependencies -module.exports = (api, { - classComponent, - tsLint, - lintOn = [], - skipLibCheck = true, - convertJsToTs, - allowJs -}, rootOptions, invoking) => { - if (typeof lintOn === 'string') { - lintOn = lintOn.split(',') - } +module.exports = ( + api, + { classComponent, skipLibCheck = true, convertJsToTs, allowJs }, + rootOptions, + invoking +) => { const isVue3 = rootOptions && rootOptions.vueVersion === '3' api.extendPackage({ @@ -36,42 +31,6 @@ module.exports = (api, { } } - if (tsLint) { - api.extendPackage({ - scripts: { - lint: 'vue-cli-service lint' - } - }) - - if (!lintOn.includes('save')) { - api.extendPackage({ - vue: { - lintOnSave: false - } - }) - } - - if (lintOn.includes('commit')) { - api.extendPackage({ - devDependencies: { - 'lint-staged': '^9.5.0' - }, - gitHooks: { - 'pre-commit': 'lint-staged' - }, - 'lint-staged': { - '*.ts': ['vue-cli-service lint', 'git add'], - '*.vue': ['vue-cli-service lint', 'git add'] - } - }) - } - - // lint and fix files on creation complete - api.onCreateComplete(() => { - return require('../lib/tslint')({}, api, true) - }) - } - // late invoke compat if (invoking) { if (api.hasPlugin('unit-mocha')) { @@ -110,5 +69,5 @@ module.exports = (api, { api.render((files) => delete files['src/shims-tsx.d.ts']) } - require('./convert')(api, { tsLint, convertJsToTs }) + require('./convert')(api, { convertJsToTs }) } diff --git a/packages/@vue/cli-plugin-typescript/generator/template/src/shims-tsx.d.ts b/packages/@vue/cli-plugin-typescript/generator/template/src/shims-tsx.d.ts index c656c68b87..64fc0a8a6d 100644 --- a/packages/@vue/cli-plugin-typescript/generator/template/src/shims-tsx.d.ts +++ b/packages/@vue/cli-plugin-typescript/generator/template/src/shims-tsx.d.ts @@ -2,9 +2,7 @@ import Vue, { VNode } from 'vue' declare global { namespace JSX { - // tslint:disable no-empty-interface interface Element extends VNode {} - // tslint:disable no-empty-interface interface ElementClass extends Vue {} interface IntrinsicElements { [elem: string]: any diff --git a/packages/@vue/cli-plugin-typescript/generator/template/tslint.json b/packages/@vue/cli-plugin-typescript/generator/template/tslint.json deleted file mode 100644 index 3ea36f9746..0000000000 --- a/packages/@vue/cli-plugin-typescript/generator/template/tslint.json +++ /dev/null @@ -1,21 +0,0 @@ -<%_ if (options.tsLint) { _%> -{ - "defaultSeverity": "warning", - "extends": [ - "tslint:recommended" - ], - "linterOptions": { - "exclude": [ - "node_modules/**" - ] - }, - "rules": { - "indent": [true, "spaces", 2], - "interface-name": false, - "no-consecutive-blank-lines": false, - "object-literal-sort-keys": false, - "ordered-imports": false, - "quotemark": [true, "single"] - } -} -<%_ } _%> diff --git a/packages/@vue/cli-plugin-typescript/index.js b/packages/@vue/cli-plugin-typescript/index.js index f0c7439451..bca26c9955 100644 --- a/packages/@vue/cli-plugin-typescript/index.js +++ b/packages/@vue/cli-plugin-typescript/index.js @@ -1,7 +1,6 @@ const path = require('path') module.exports = (api, projectOptions) => { - const fs = require('fs') const useThreads = process.env.NODE_ENV === 'production' && !!projectOptions.parallel const { semver, loadModule } = require('@vue/cli-shared-utils') @@ -106,7 +105,6 @@ module.exports = (api, projectOptions) => { .plugin('fork-ts-checker') .use(require('fork-ts-checker-webpack-plugin'), [{ vue: { enabled: true, compiler: 'vue-template-compiler' }, - tslint: projectOptions.lintOnSave !== false && fs.existsSync(api.resolve('tslint.json')), formatter: 'codeframe', // https://github.com/TypeStrong/ts-loader#happypackmode-boolean-defaultfalse checkSyntacticErrors: useThreads @@ -114,19 +112,4 @@ module.exports = (api, projectOptions) => { } } }) - - if (!api.hasPlugin('eslint')) { - api.registerCommand('lint', { - description: 'lint source files with TSLint', - usage: 'vue-cli-service lint [options] [...files]', - options: { - '--format [formatter]': 'specify formatter (default: codeFrame)', - '--no-fix': 'do not fix errors', - '--formatters-dir [dir]': 'formatter directory', - '--rules-dir [dir]': 'rules directory' - } - }, args => { - return require('./lib/tslint')(args, api) - }) - } } diff --git a/packages/@vue/cli-plugin-typescript/lib/convertLintFlags.js b/packages/@vue/cli-plugin-typescript/lib/convertLintFlags.js deleted file mode 100644 index 5dbf9f96d7..0000000000 --- a/packages/@vue/cli-plugin-typescript/lib/convertLintFlags.js +++ /dev/null @@ -1,11 +0,0 @@ -module.exports = function convertLintFlags (file) { - return file - .replace(/\/\*\s?eslint-(enable|disable)([^*]+)?\*\//g, (_, $1, $2) => { - if ($2) $2 = $2.trim() - return `/* tslint:${$1}${$2 ? `:${$2}` : ``} */` - }) - .replace(/\/\/\s?eslint-disable-(next-)?line(.+)?/g, (_, $1, $2) => { - if ($2) $2 = $2.trim() - return `// tslint:disable-${$1 || ''}line${$2 ? `:${$2}` : ``}` - }) -} diff --git a/packages/@vue/cli-plugin-typescript/lib/tslint.js b/packages/@vue/cli-plugin-typescript/lib/tslint.js deleted file mode 100644 index 5a514b63f9..0000000000 --- a/packages/@vue/cli-plugin-typescript/lib/tslint.js +++ /dev/null @@ -1,149 +0,0 @@ -const fs = require('fs') -const path = require('path') -const globby = require('globby') -const tslint = require('tslint') -const ts = require('typescript') -/* eslint-disable-next-line node/no-extraneous-require */ -const vueCompiler = require('vue-template-compiler') - -const isVueFile = file => /\.vue(\.ts)?$/.test(file) - -// hack to make tslint --fix work for *.vue files: -// we save the non-script parts to a cache right before -// linting the file, and patch fs.writeFileSync to combine the fixed script -// back with the non-script parts. -// this works because (luckily) tslint lints synchronously. -const vueFileCache = new Map() -const writeFileSync = fs.writeFileSync - -const patchWriteFile = () => { - fs.writeFileSync = (file, content, options) => { - if (isVueFile(file)) { - const parts = vueFileCache.get(path.normalize(file)) - if (parts) { - parts.content = content - const { before, after } = parts - content = `${before}\n${content.trim()}\n${after}` - } - } - return writeFileSync(file, content, options) - } -} - -const restoreWriteFile = () => { - fs.writeFileSync = writeFileSync -} - -const parseTSFromVueFile = file => { - // If the file has already been cached, don't read the file again. Use the cache instead. - if (vueFileCache.has(file)) { - return vueFileCache.get(file) - } - - const content = fs.readFileSync(file, 'utf-8') - const { script } = vueCompiler.parseComponent(content, { pad: 'line' }) - if (script && /^tsx?$/.test(script.lang)) { - vueFileCache.set(file, { - before: content.slice(0, script.start), - after: content.slice(script.end), - content: script.content - }) - return script - } -} - -// patch getSourceFile for *.vue files -// so that it returns the