From c0e7a23d26994ebadadf4c78a6741b8dcac70d2a Mon Sep 17 00:00:00 2001 From: Christopher Quadflieg Date: Thu, 9 Jan 2020 18:09:02 +0100 Subject: [PATCH 1/9] chore: remove linter option tslint --- .../@vue/cli-plugin-typescript/prompts.js | 5 -- .../__tests__/typescript.spec.js | 48 +------------------ packages/@vue/cli/lib/promptModules/linter.js | 13 +---- .../@vue/cli/lib/promptModules/typescript.js | 4 -- 4 files changed, 3 insertions(+), 67 deletions(-) diff --git a/packages/@vue/cli-plugin-typescript/prompts.js b/packages/@vue/cli-plugin-typescript/prompts.js index 24f66401fc..7c106bf662 100644 --- a/packages/@vue/cli-plugin-typescript/prompts.js +++ b/packages/@vue/cli-plugin-typescript/prompts.js @@ -15,11 +15,6 @@ const prompts = module.exports = [ type: `confirm`, message: 'Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)?' }, - { - name: `lint`, - type: `confirm`, - message: `Use TSLint?` - }, { name: `lintOn`, type: `checkbox`, diff --git a/packages/@vue/cli/lib/promptModules/__tests__/typescript.spec.js b/packages/@vue/cli/lib/promptModules/__tests__/typescript.spec.js index 43f50d9405..b76208ec1e 100644 --- a/packages/@vue/cli/lib/promptModules/__tests__/typescript.spec.js +++ b/packages/@vue/cli/lib/promptModules/__tests__/typescript.spec.js @@ -6,52 +6,6 @@ const assertPromptModule = require('@vue/cli-test-utils/assertPromptModule') const moduleToTest = require('../typescript') const linterModule = require('../linter') -test('with TSLint', async () => { - const expectedPrompts = [ - { - message: 'features', - choices: ['TypeScript', 'Linter'], - check: [0, 1] - }, - { - message: 'Use class-style component', - confirm: true - }, - { - message: 'Use Babel', - confirm: true - }, - { - message: 'Pick a linter / formatter', - choices: ['ESLint with error prevention only', 'Airbnb', 'Standard', 'Prettier', 'TSLint (deprecated)'], - choose: [4] - }, - { - message: 'Pick additional lint features', - choices: ['on save', 'on commit'], - check: [0, 1] - } - ] - - const expectedOptions = { - plugins: { - '@vue/cli-plugin-typescript': { - classComponent: true, - tsLint: true, - lintOn: ['save', 'commit'], - useTsWithBabel: true - } - } - } - - await assertPromptModule( - [moduleToTest, linterModule], - expectedPrompts, - expectedOptions, - { pluginsOnly: true } - ) -}) - test('with ESLint', async () => { const expectedPrompts = [ { @@ -69,7 +23,7 @@ test('with ESLint', async () => { }, { message: 'Pick a linter / formatter', - choices: ['ESLint with error prevention only', 'Airbnb', 'Standard', 'Prettier', 'TSLint (deprecated)'], + choices: ['ESLint with error prevention only', 'Airbnb', 'Standard', 'Prettier'], choose: [1] }, { diff --git a/packages/@vue/cli/lib/promptModules/linter.js b/packages/@vue/cli/lib/promptModules/linter.js index 69dfbc794a..b78755a847 100644 --- a/packages/@vue/cli/lib/promptModules/linter.js +++ b/packages/@vue/cli/lib/promptModules/linter.js @@ -37,16 +37,7 @@ module.exports = cli => { name: 'ESLint + Prettier', value: 'prettier', short: 'Prettier' - }, - ...( - answers.features.includes('ts') - ? [{ - name: `TSLint (deprecated)`, - value: 'tslint', - short: 'TSLint' - }] - : [] - ) + } ] }) @@ -69,7 +60,7 @@ module.exports = cli => { }) cli.onPromptComplete((answers, options) => { - if (answers.features.includes('linter') && answers.eslintConfig !== 'tslint') { + if (answers.features.includes('linter')) { options.plugins['@vue/cli-plugin-eslint'] = { config: answers.eslintConfig, lintOn: answers.lintOn diff --git a/packages/@vue/cli/lib/promptModules/typescript.js b/packages/@vue/cli/lib/promptModules/typescript.js index 9e9ceafb3f..f8b0e1e163 100644 --- a/packages/@vue/cli/lib/promptModules/typescript.js +++ b/packages/@vue/cli/lib/promptModules/typescript.js @@ -32,10 +32,6 @@ module.exports = cli => { const tsOptions = { classComponent: answers.tsClassComponent } - if (answers.eslintConfig === 'tslint') { - tsOptions.tsLint = true - tsOptions.lintOn = answers.lintOn - } if (answers.useTsWithBabel) { tsOptions.useTsWithBabel = true } From b05f7e4dfe0a71361aa4d2c484a5adde371b6daa Mon Sep 17 00:00:00 2001 From: Christopher Quadflieg Date: Thu, 9 Jan 2020 18:46:19 +0100 Subject: [PATCH 2/9] chore: remove tslint specific code --- .../__tests__/cypressPlugin.spec.js | 1 - .../__tests__/tsConvertLintFlags.spec.js | 19 -- .../__tests__/tsGenerator.spec.js | 6 +- .../__tests__/tsPluginTSLint.spec.js | 115 ------------ .../generator/convert.js | 40 ++--- .../cli-plugin-typescript/generator/index.js | 110 ++++-------- .../generator/template/src/shims-tsx.d.ts | 2 - .../generator/template/tslint.json | 21 --- packages/@vue/cli-plugin-typescript/index.js | 169 +++++++++--------- .../lib/convertLintFlags.js | 11 -- .../@vue/cli-plugin-typescript/lib/tslint.js | 149 --------------- 11 files changed, 135 insertions(+), 508 deletions(-) delete mode 100644 packages/@vue/cli-plugin-typescript/__tests__/tsConvertLintFlags.spec.js delete mode 100644 packages/@vue/cli-plugin-typescript/__tests__/tsPluginTSLint.spec.js delete mode 100644 packages/@vue/cli-plugin-typescript/generator/template/tslint.json delete mode 100644 packages/@vue/cli-plugin-typescript/lib/convertLintFlags.js delete mode 100644 packages/@vue/cli-plugin-typescript/lib/tslint.js 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-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..59c4d6c9d0 100644 --- a/packages/@vue/cli-plugin-typescript/__tests__/tsGenerator.spec.js +++ b/packages/@vue/cli-plugin-typescript/__tests__/tsGenerator.spec.js @@ -81,12 +81,11 @@ test('use with router', async () => { }) test('lint', async () => { - const { pkg, files } = await generateWithPlugin([ + const { pkg } = await generateWithPlugin([ { id: 'ts', apply: require('../generator'), options: { - tsLint: true, lintOn: ['save', 'commit'] } } @@ -99,8 +98,6 @@ test('lint', async () => { '*.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 () => { @@ -109,7 +106,6 @@ test('lint with no lintOnSave', async () => { id: 'ts', apply: require('../generator'), options: { - tsLint: true, lintOn: ['commit'] } } 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..e480dc6bfa 100644 --- a/packages/@vue/cli-plugin-typescript/generator/convert.js +++ b/packages/@vue/cli-plugin-typescript/generator/convert.js @@ -1,37 +1,31 @@ -module.exports = (api, { tsLint = false, convertJsToTs = true } = {}) => { - const jsRE = /\.js$/ - let excludeRE = /^tests\/e2e\/|(\.config|rc)\.js$/ +module.exports = (api, { convertJsToTs = true } = {}) => { + const jsRE = /\.js$/; + let excludeRE = /^tests\/e2e\/|(\.config|rc)\.js$/; - if (api.hasPlugin('e2e-webdriverio')) { - excludeRE = /(\.config|rc)\.js$/ + if (api.hasPlugin("e2e-webdriverio")) { + excludeRE = /(\.config|rc)\.js$/; } - const convertLintFlags = require('../lib/convertLintFlags') - api.postProcessFiles(files => { + const convertLintFlags = require("../lib/convertLintFlags"); + 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 for (const file in files) { if (jsRE.test(file) && !excludeRE.test(file)) { - const tsFile = file.replace(jsRE, '.ts') + const tsFile = file.replace(jsRE, ".ts"); if (!files[tsFile]) { - let content = files[file] - if (tsLint) { - content = convertLintFlags(content) - } - files[tsFile] = content + const content = files[file]; + files[tsFile] = content; } - delete files[file] + delete files[file]; } } } 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) - } - files[tsFile] = content - delete files[api.entryFile] + const tsFile = api.entryFile.replace(jsRE, ".ts"); + 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..b601bbb70c 100644 --- a/packages/@vue/cli-plugin-typescript/generator/index.js +++ b/packages/@vue/cli-plugin-typescript/generator/index.js @@ -1,114 +1,76 @@ -const pluginDevDeps = require('../package.json').devDependencies +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, lintOn = [], skipLibCheck = true, convertJsToTs, allowJs }, + rootOptions, + invoking +) => { + if (typeof lintOn === "string") { + lintOn = lintOn.split(","); } - const isVue3 = rootOptions && rootOptions.vueVersion === '3' + const isVue3 = rootOptions && rootOptions.vueVersion === "3"; api.extendPackage({ devDependencies: { - typescript: pluginDevDeps.typescript - } - }) + typescript: pluginDevDeps.typescript, + }, + }); if (classComponent) { if (isVue3) { api.extendPackage({ dependencies: { - 'vue-class-component': '^8.0.0-0' - } - }) + "vue-class-component": "^8.0.0-0", + }, + }); } else { api.extendPackage({ dependencies: { - 'vue-class-component': pluginDevDeps['vue-class-component'], - 'vue-property-decorator': pluginDevDeps['vue-property-decorator'] - } - }) - } - } - - 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' + "vue-class-component": pluginDevDeps["vue-class-component"], + "vue-property-decorator": pluginDevDeps["vue-property-decorator"], }, - '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')) { + if (api.hasPlugin("unit-mocha")) { // eslint-disable-next-line node/no-extraneous-require - require('@vue/cli-plugin-unit-mocha/generator').applyTS(api) + require("@vue/cli-plugin-unit-mocha/generator").applyTS(api); } - if (api.hasPlugin('unit-jest')) { + if (api.hasPlugin("unit-jest")) { // eslint-disable-next-line node/no-extraneous-require - require('@vue/cli-plugin-unit-jest/generator').applyTS(api) + require("@vue/cli-plugin-unit-jest/generator").applyTS(api); } - if (api.hasPlugin('eslint')) { + if (api.hasPlugin("eslint")) { // eslint-disable-next-line node/no-extraneous-require - require('@vue/cli-plugin-eslint/generator').applyTS(api) + require("@vue/cli-plugin-eslint/generator").applyTS(api); } - if (api.hasPlugin('e2e-webdriverio')) { + if (api.hasPlugin("e2e-webdriverio")) { // eslint-disable-next-line node/no-extraneous-require - require('@vue/cli-plugin-e2e-webdriverio/generator').applyTS(api) + require("@vue/cli-plugin-e2e-webdriverio/generator").applyTS(api); } } - api.render('./template', { + api.render("./template", { skipLibCheck, - hasMocha: api.hasPlugin('unit-mocha'), - hasJest: api.hasPlugin('unit-jest'), - hasWebDriverIO: api.hasPlugin('e2e-webdriverio') - }) + hasMocha: api.hasPlugin("unit-mocha"), + hasJest: api.hasPlugin("unit-jest"), + hasWebDriverIO: api.hasPlugin("e2e-webdriverio"), + }); if (isVue3) { - api.render('./template-vue3') + api.render("./template-vue3"); // In Vue 3, TSX interface is defined in https://github.com/vuejs/vue-next/blob/master/packages/runtime-dom/types/jsx.d.ts // So no need to manually add a shim. - api.render((files) => delete files['src/shims-tsx.d.ts']) + api.render((files) => delete files["src/shims-tsx.d.ts"]); } - require('./convert')(api, { tsLint, convertJsToTs }) -} + require("./convert")(api, { tsLint, 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..a8cc78937d 100644 --- a/packages/@vue/cli-plugin-typescript/index.js +++ b/packages/@vue/cli-plugin-typescript/index.js @@ -1,132 +1,125 @@ -const path = require('path') +const path = require("path"); module.exports = (api, projectOptions) => { - const fs = require('fs') - const useThreads = process.env.NODE_ENV === 'production' && !!projectOptions.parallel + const useThreads = + process.env.NODE_ENV === "production" && !!projectOptions.parallel; - const { semver, loadModule } = require('@vue/cli-shared-utils') - const vue = loadModule('vue', api.service.context) - const isVue3 = (vue && semver.major(vue.version) === 3) + const { semver, loadModule } = require("@vue/cli-shared-utils"); + const vue = loadModule("vue", api.service.context); + const isVue3 = vue && semver.major(vue.version) === 3; - api.chainWebpack(config => { - config.resolveLoader.modules.prepend(path.join(__dirname, 'node_modules')) + api.chainWebpack((config) => { + config.resolveLoader.modules.prepend(path.join(__dirname, "node_modules")); if (!projectOptions.pages) { - config.entry('app') - .clear() - .add('./src/main.ts') + config.entry("app").clear().add("./src/main.ts"); } - config.resolve - .extensions - .prepend('.ts') - .prepend('.tsx') + config.resolve.extensions.prepend(".ts").prepend(".tsx"); - const tsRule = config.module.rule('ts').test(/\.ts$/) - const tsxRule = config.module.rule('tsx').test(/\.tsx$/) + const tsRule = config.module.rule("ts").test(/\.ts$/); + const tsxRule = config.module.rule("tsx").test(/\.tsx$/); // add a loader to both *.ts & vue const addLoader = ({ name, loader, options }) => { - tsRule.use(name).loader(loader).options(options) - tsxRule.use(name).loader(loader).options(options) - } + tsRule.use(name).loader(loader).options(options); + tsxRule.use(name).loader(loader).options(options); + }; addLoader({ - name: 'cache-loader', - loader: require.resolve('cache-loader'), - options: api.genCacheConfig('ts-loader', { - 'ts-loader': require('ts-loader/package.json').version, - 'typescript': require('typescript/package.json').version, - modern: !!process.env.VUE_CLI_MODERN_BUILD - }, 'tsconfig.json') - }) + name: "cache-loader", + loader: require.resolve("cache-loader"), + options: api.genCacheConfig( + "ts-loader", + { + "ts-loader": require("ts-loader/package.json").version, + typescript: require("typescript/package.json").version, + modern: !!process.env.VUE_CLI_MODERN_BUILD, + }, + "tsconfig.json" + ), + }); if (useThreads) { addLoader({ - name: 'thread-loader', - loader: require.resolve('thread-loader'), + name: "thread-loader", + loader: require.resolve("thread-loader"), options: - typeof projectOptions.parallel === 'number' + typeof projectOptions.parallel === "number" ? { workers: projectOptions.parallel } - : {} - }) + : {}, + }); } - if (api.hasPlugin('babel')) { + if (api.hasPlugin("babel")) { addLoader({ // TODO: I guess the intent is to require the `babel-loader` provided by the Babel vue // plugin, but that means we now rely on the hoisting. It should instead be queried // against the plugin itself, or through a peer dependency. - name: 'babel-loader', + name: "babel-loader", // eslint-disable-next-line node/no-extraneous-require - loader: require.resolve('babel-loader') - }) + loader: require.resolve("babel-loader"), + }); } addLoader({ - name: 'ts-loader', - loader: require.resolve('ts-loader'), + name: "ts-loader", + loader: require.resolve("ts-loader"), options: { transpileOnly: true, - appendTsSuffixTo: ['\\.vue$'], + appendTsSuffixTo: ["\\.vue$"], // https://github.com/TypeStrong/ts-loader#happypackmode-boolean-defaultfalse - happyPackMode: useThreads - } - }) + happyPackMode: useThreads, + }, + }); // make sure to append TSX suffix - tsxRule.use('ts-loader').loader(require.resolve('ts-loader')).tap(options => { - options = Object.assign({}, options) - delete options.appendTsSuffixTo - options.appendTsxSuffixTo = ['\\.vue$'] - return options - }) + tsxRule + .use("ts-loader") + .loader(require.resolve("ts-loader")) + .tap((options) => { + options = Object.assign({}, options); + delete options.appendTsSuffixTo; + options.appendTsxSuffixTo = ["\\.vue$"]; + return options; + }); // this plugin does not play well with jest + cypress setup (tsPluginE2e.spec.js) somehow // so temporarily disabled for vue-cli tests if (!process.env.VUE_CLI_TEST) { if (isVue3) { config - .plugin('fork-ts-checker') - .use(require('fork-ts-checker-webpack-plugin-v5'), [{ - typescript: { - extensions: { - vue: { - enabled: true, - compiler: '@vue/compiler-sfc' - } + .plugin("fork-ts-checker") + .use(require("fork-ts-checker-webpack-plugin-v5"), [ + { + typescript: { + extensions: { + vue: { + enabled: true, + compiler: "@vue/compiler-sfc", + }, + }, + diagnosticOptions: { + semantic: true, + // https://github.com/TypeStrong/ts-loader#happypackmode + syntactic: useThreads, + }, }, - diagnosticOptions: { - semantic: true, - // https://github.com/TypeStrong/ts-loader#happypackmode - syntactic: useThreads - } - } - }]) + }, + ]); } else { config - .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', + .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 - }]) + checkSyntacticErrors: useThreads, + }, + ]); } } - }) - - 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