diff --git a/meta.js b/meta.js index fee1755af4..6ab2ab4e65 100644 --- a/meta.js +++ b/meta.js @@ -91,6 +91,28 @@ module.exports = { "type": "confirm", "message": "Use TSLint to lint your TypeScript code?" }, + "tslintConfig": { + "when": "tslint", + "type": "list", + "message": "Pick a TSLint preset", + "choices": [ + { + "name": "Standard (https://github.com/blakeembrey/tslint-config-standard)", + "value": "standard", + "short": "Standard" + }, + { + "name": "AirBNB (https://github.com/progre/tslint-config-airbnb)", + "value": "airbnb", + "short": "AirBNB" + }, + { + "name": "none (configure it yourself)", + "value": "none", + "short": "none" + } + ] + }, "unit": { "type": "confirm", "message": "Setup unit tests with Karma + Mocha?" @@ -103,7 +125,7 @@ module.exports = { "filters": { ".eslintrc.js": "eslint", ".eslintignore": "eslint", - ".tslint.json": "tslint", + "tslint.json": "tslint", "tsconfig.json": "compiler == 'typescript'", "src/**/*.ts": "compiler == 'typescript'", "src/**/*.js": "compiler != 'typescript'", diff --git a/template/build/webpack.base.conf.js b/template/build/webpack.base.conf.js index 49b4b3669b..f2279f2d2d 100644 --- a/template/build/webpack.base.conf.js +++ b/template/build/webpack.base.conf.js @@ -52,7 +52,11 @@ module.exports = { test: /\.ts$/, enforce: 'pre', loader: 'tslint-loader', - include: [resolve('src'), resolve('test')] + include: [resolve('src'), resolve('test')], + options: { + formatter: 'grouped', + formattersDirectory: 'node_modules/custom-tslint-formatters/formatters' + } }, {{/tslint}} { diff --git a/template/package.json b/template/package.json index b96537118d..97c7616088 100644 --- a/template/package.json +++ b/template/package.json @@ -11,7 +11,7 @@ "e2e": "node test/e2e/runner.js"{{/e2e}}{{#if_or unit e2e}}, "test": "{{#unit}}npm run unit{{/unit}}{{#unit}}{{#e2e}} && {{/e2e}}{{/unit}}{{#e2e}}npm run e2e{{/e2e}}"{{/if_or}}{{#eslint}}, "eslint": "eslint --ext .js src{{#unit}} test/unit/specs{{/unit}}{{#e2e}} test/e2e/specs{{/e2e}}"{{/eslint}}{{#tslint}}, - "tslint": "tslint --ext .ts src{{#unit}} test/unit/specs{{/unit}}{{#e2e}} test/e2e/specs{{/e2e}}"{{/tslint}} + "tslint": "tslint -s node_modules/custom-tslint-formatters/formatters -t grouped src/**/*.ts{{#unit}} test/unit/**/*.ts{{/unit}}{{#e2e}} test/e2e/*.ts{{/e2e}}"{{/tslint}} }, "dependencies": { "vue": "^2.2.2"{{#if_eq compiler "typescript"}}, @@ -99,9 +99,18 @@ "optimize-css-assets-webpack-plugin": "^1.3.0", "ora": "^1.1.0", "rimraf": "^2.6.0", - {{#if_eq compiler "typescript"}} + {{#tslint}} "tslint": "^4.5.1", "tslint-loader": "^3.4.3", + "custom-tslint-formatters": "^2.1.0", + {{/tslint}} + {{#if_eq tslintConfig "standard"}} + "tslint-config-standard": "^4.0.0", + {{/if_eq}} + {{#if_eq tslintConfig "airbnb"}} + "tslint-config-airbnb": "^1.1.1", + {{/if_eq}} + {{#if_eq compiler "typescript"}} "typescript": "^2.2.1", {{/if_eq}} "url-loader": "^0.5.7", diff --git a/template/src/App.vue.ts b/template/src/App.vue.ts index 7f703bab88..c07139e70f 100644 --- a/template/src/App.vue.ts +++ b/template/src/App.vue.ts @@ -1,19 +1,15 @@ -import Vue from "vue"; -import Component from "vue-class-component"; -import WithRender from "./App.html?style=./App.css"; +import Vue from 'vue'{{#if_eq tslintConfig "airbnb"}};{{/if_eq}} +import Component from 'vue-class-component'{{#if_eq tslintConfig "airbnb"}};{{/if_eq}} +import WithRender from './App.html?style=./App.css'{{#if_eq tslintConfig "airbnb"}};{{/if_eq}} {{#unless router}} -import Hello from "./components/Hello.vue"; +import Hello from './components/Hello.vue'{{#if_eq tslintConfig "airbnb"}};{{/if_eq}} {{/unless}} @WithRender @Component{{#unless router}}({ - components: {Hello} + components: { Hello }{{#if_eq tslintConfig "airbnb"}},{{/if_eq}} }){{/unless}} export default class App extends Vue { - name = "app"; - - constructor() { - super(); - } + name = 'app'{{#if_eq tslintConfig "airbnb"}};{{/if_eq}} } diff --git a/template/src/components/Hello.vue.ts b/template/src/components/Hello.vue.ts index ce8787ba59..f2963ee56a 100644 --- a/template/src/components/Hello.vue.ts +++ b/template/src/components/Hello.vue.ts @@ -1,13 +1,9 @@ -import Vue from "vue"; -import Component from "vue-class-component"; -import WithRender from "./Hello.html?style=./Hello.css"; +import Vue from 'vue'{{#if_eq tslintConfig "airbnb"}};{{/if_eq}} +import Component from 'vue-class-component'{{#if_eq tslintConfig "airbnb"}};{{/if_eq}} +import WithRender from './Hello.html?style=./Hello.css'{{#if_eq tslintConfig "airbnb"}};{{/if_eq}} @WithRender @Component export default class Hello extends Vue { - msg = "Welcome to Your Vue.js App"; - - constructor() { - super(); - } + msg = 'Welcome to Your Vue.js App'{{#if_eq tslintConfig "airbnb"}};{{/if_eq}} } diff --git a/template/src/hooks.ts b/template/src/hooks.ts index 6766085395..918e36c5b1 100644 --- a/template/src/hooks.ts +++ b/template/src/hooks.ts @@ -1,14 +1,14 @@ // Use this file to register components custom hooks. // @see https://github.com/vuejs/vue-class-component#adding-custom-hooks {{#router}} -import Component from "vue-class-component"; +import Component from 'vue-class-component'{{#if_eq tslintConfig "airbnb"}};{{/if_eq}} {{/router}} {{#router}} // Register the router hooks with their names Component.registerHooks([ - "beforeRouteEnter", - "beforeRouteLeave", - "beforeRouteUpdate" -]); + 'beforeRouteEnter', + 'beforeRouteLeave', + 'beforeRouteUpdate'{{#if_eq tslintConfig "airbnb"}},{{/if_eq}} +]){{#if_eq tslintConfig "airbnb"}};{{/if_eq}} {{/router}} diff --git a/template/src/main.ts b/template/src/main.ts index 2f5f46c884..fe61b67234 100644 --- a/template/src/main.ts +++ b/template/src/main.ts @@ -1,29 +1,29 @@ -{{#if_eq build "standalone"}} +{{#if_eq build 'standalone'}} // The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. {{/if_eq}} -import Vue from "vue"; +import Vue from 'vue'{{#if_eq tslintConfig "airbnb"}};{{/if_eq}} -import "./hooks"; // This must be imported before any component +import './hooks'{{#if_eq tslintConfig "airbnb"}};{{/if_eq}} // This must be imported before any component -import App from "./App.vue"; +import App from './App.vue'{{#if_eq tslintConfig "airbnb"}};{{/if_eq}} {{#router}} -import router from "./router"; +import router from './router'{{#if_eq tslintConfig "airbnb"}};{{/if_eq}} {{/router}} -Vue.config.productionTip = false; +Vue.config.productionTip = false{{#if_eq tslintConfig "airbnb"}};{{/if_eq}} // tslint:disable-next-line:no-unused-new new Vue({ - el: "#app", + el: '#app', {{#router}} router, {{/router}} - {{#if_eq build "runtime"}} + {{#if_eq build 'runtime'}} render: (h) => h(App) {{/if_eq}} - {{#if_eq build "standalone"}} - template: "", - components: { App } + {{#if_eq build 'standalone'}} + template: '', + components: { App }{{#if_eq tslintConfig "airbnb"}},{{/if_eq}} {{/if_eq}} -}); +}){{#if_eq tslintConfig "airbnb"}};{{/if_eq}} diff --git a/template/src/router/index.ts b/template/src/router/index.ts index 787356994d..f94740b116 100644 --- a/template/src/router/index.ts +++ b/template/src/router/index.ts @@ -1,15 +1,15 @@ -import Vue from "vue"; -import Router from "vue-router"; -import Hello from "../components/Hello.vue"; +import Vue from 'vue'{{#if_eq tslintConfig "airbnb"}};{{/if_eq}} +import Router from 'vue-router'{{#if_eq tslintConfig "airbnb"}};{{/if_eq}} +import Hello from '../components/Hello.vue'{{#if_eq tslintConfig "airbnb"}};{{/if_eq}} -Vue.use(Router); +Vue.use(Router){{#if_eq tslintConfig "airbnb"}};{{/if_eq}} export default new Router({ routes: [ { - path: "/", - name: "Hello", - component: Hello - } - ] -}); + path: '/', + name: 'Hello', + component: Hello{{#if_eq tslintConfig "airbnb"}},{{/if_eq}} + }{{#if_eq tslintConfig "airbnb"}},{{/if_eq}} + ]{{#if_eq tslintConfig "airbnb"}},{{/if_eq}} +}){{#if_eq tslintConfig "airbnb"}};{{/if_eq}} diff --git a/template/src/typings.d.ts b/template/src/typings.d.ts index d25e22725d..337c6d9a62 100644 --- a/template/src/typings.d.ts +++ b/template/src/typings.d.ts @@ -1,31 +1,31 @@ // vue-template-loader (@see https://github.com/ktsn/vue-template-loader) /* tslint:disable:interface-name */ -declare module "*.html" { - import Vue from "vue"; +declare module '*.html' { + import Vue from 'vue' interface WithRender { - (options: Vue.ComponentOptions): Vue.ComponentOptions; - (component: V): V; + (options: Vue.ComponentOptions): Vue.ComponentOptions + (component: V): V } - const withRender: WithRender; - export = withRender; + const withRender: WithRender + export = withRender } -declare module "*.scss" { - import Vue from "vue"; +declare module '*.scss' { + import Vue from 'vue' interface WithRender { - (options: Vue.ComponentOptions): Vue.ComponentOptions; - (component: V): V; + (options: Vue.ComponentOptions): Vue.ComponentOptions + (component: V): V } - const withRender: WithRender; - export = withRender; + const withRender: WithRender + export = withRender } -declare module "*.css" { - import Vue from "vue"; +declare module '*.css' { + import Vue from 'vue' interface WithRender { - (options: Vue.ComponentOptions): Vue.ComponentOptions; - (component: V): V; + (options: Vue.ComponentOptions): Vue.ComponentOptions + (component: V): V } - const withRender: WithRender; - export = withRender; + const withRender: WithRender + export = withRender } diff --git a/template/test/unit/index.ts b/template/test/unit/index.ts index e2335bc8d2..453679c65f 100644 --- a/template/test/unit/index.ts +++ b/template/test/unit/index.ts @@ -1,16 +1,18 @@ -import Vue from "vue"; -Vue.config.productionTip = false; +import Vue from 'vue'{{#if_eq tslintConfig "airbnb"}};{{/if_eq}} +Vue.config.productionTip = false{{#if_eq tslintConfig "airbnb"}};{{/if_eq}} + +const crequire = (require as WebpackRequire){{#if_eq tslintConfig "airbnb"}};{{/if_eq}} // Polyfill fn.bind() for PhantomJS /* tslint:disable:no-var-requires */ -Function.prototype.bind = require("function-bind"); +Function.prototype.bind = require('function-bind'){{#if_eq tslintConfig "airbnb"}};{{/if_eq}} // require all test files (files that ends with .spec.js) -const testsContext = (require as WebpackRequire).context("./specs", true, /\.spec$/); -testsContext.keys().forEach(testsContext); +const testsContext = crequire.context('./specs', true, /\.spec$/){{#if_eq tslintConfig "airbnb"}};{{/if_eq}} +testsContext.keys().forEach(testsContext){{#if_eq tslintConfig "airbnb"}};{{/if_eq}} // require all src files except main.js and *.d.ts for coverage. // you can also change this to match only the subset of files that // you want coverage for. -const srcContext = (require as WebpackRequire).context("../../src", true, /^\.\/(?!(?:main|.*?\.d)(\.ts)?$)/); -srcContext.keys().forEach(srcContext); +const srcContext = crequire.context('../../src', true, /^\.\/(?!(?:main|.*?\.d)(\.ts)?$)/){{#if_eq tslintConfig "airbnb"}};{{/if_eq}} +srcContext.keys().forEach(srcContext){{#if_eq tslintConfig "airbnb"}};{{/if_eq}} diff --git a/template/test/unit/specs/Hello.spec.ts b/template/test/unit/specs/Hello.spec.ts index 2536c66495..63f6fd35f2 100644 --- a/template/test/unit/specs/Hello.spec.ts +++ b/template/test/unit/specs/Hello.spec.ts @@ -1,14 +1,14 @@ -import Vue from "vue"; +import Vue from 'vue'{{#if_eq eslintConfig 'airbnb'}};{{/if_eq}} -import { expect } from "chai"; +import { expect } from 'chai'{{#if_eq eslintConfig 'airbnb'}};{{/if_eq}} -import Hello from "@/components/Hello.vue"; +import Hello from '@/components/Hello.vue'{{#if_eq eslintConfig 'airbnb'}};{{/if_eq}} -describe("Hello component", () => { - it("should render correct contents", () => { - const hello = new Hello(); - const vm = hello.$mount(); - expect(vm.$el.querySelector(".hello h1").textContent) - .to.equal("Welcome to Your Vue.js App"); - }); -}); +describe('Hello component', () => { + it('should render correct contents', () => { + const hello = new Hello(){{#if_eq eslintConfig 'airbnb'}};{{/if_eq}} + const vm = hello.$mount(){{#if_eq eslintConfig 'airbnb'}};{{/if_eq}} + expect(vm.$el.querySelector('.hello h1').textContent) + .to.equal('Welcome to Your Vue.js App'){{#if_eq eslintConfig 'airbnb'}};{{/if_eq}} + }){{#if_eq eslintConfig 'airbnb'}};{{/if_eq}} +}){{#if_eq eslintConfig 'airbnb'}};{{/if_eq}} diff --git a/template/test/unit/tslint.json b/template/test/unit/tslint.json deleted file mode 100644 index 93b83e9b0b..0000000000 --- a/template/test/unit/tslint.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "tslint:recommended", - "rules": { - "member-access": false, - "object-literal-sort-keys": false, - "trailing-comma": false - } -} diff --git a/template/test/unit/typings.d.ts b/template/test/unit/typings.d.ts index 6fc2b57154..32f7f3f121 100644 --- a/template/test/unit/typings.d.ts +++ b/template/test/unit/typings.d.ts @@ -1,3 +1,3 @@ interface WebpackRequire extends NodeRequire { - context(file: string, flag?: boolean, exp?: RegExp): any; + context(file: string, flag?: boolean, exp?: RegExp): any{{#if_eq tslintConfig "airbnb"}};{{/if_eq}} } diff --git a/template/tslint.json b/template/tslint.json index 93b83e9b0b..ded6873a6e 100644 --- a/template/tslint.json +++ b/template/tslint.json @@ -1,8 +1,15 @@ { - "extends": "tslint:recommended", +{{#if_eq tslintConfig "none"}} + "rules": {} +{{/if_eq}} +{{#if_eq tslintConfig "standard"}} + "extends": "tslint-config-standard", + "rules": {} +{{/if_eq}} +{{#if_eq tslintConfig "airbnb"}} + "extends": "tslint-config-airbnb", "rules": { - "member-access": false, - "object-literal-sort-keys": false, - "trailing-comma": false + "import-name": false } +{{/if_eq}} } diff --git a/tests/default.expect b/tests/default.expect index 38db411257..f10ad7932c 100644 --- a/tests/default.expect +++ b/tests/default.expect @@ -19,6 +19,8 @@ expect "Pick an ESLint preset" send "\n" expect "Use TSLint to lint your TypeScript code?" send "\n" +expect "Pick a TSLint preset" +send "\n" expect "Setup unit tests with Karma + Mocha?" send "\n" expect "Setup e2e tests with Nightwatch?" diff --git a/tests/ts-airbnb.expect b/tests/ts-airbnb.expect new file mode 100644 index 0000000000..e0fb4de494 --- /dev/null +++ b/tests/ts-airbnb.expect @@ -0,0 +1,32 @@ +set testname [lindex $argv 0]; +spawn ../node_modules/.bin/vue init .. $testname + +expect "Project name" +send "\n" +expect "Project description" +send "\n" +expect "Author" +send "\n" +expect "Vue build" +send "\n" +expect "Install vue-router?" +send "\n" +expect "Which JavaScript compiler do you want to use?" +send "\n" +expect "Use ESLint to lint your JavaScript code?" +send "\n" +expect "Pick an ESLint preset" +send "\[B" +expect "AirBNB" +send "\n" +expect "Use TSLint to lint your TypeScript code?" +send "\n" +expect "Pick a TSLint preset" +send "\[B" +expect "AirBNB" +send "\n" +expect "Setup unit tests with Karma + Mocha?" +send "\n" +expect "Setup e2e tests with Nightwatch?" +send "\n" +expect eof diff --git a/tests/ts-airbnb.sh b/tests/ts-airbnb.sh new file mode 100644 index 0000000000..2a4413cf8c --- /dev/null +++ b/tests/ts-airbnb.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +testname=$1 + +if [[ -z $testname ]]; then + echo "No test name given" + exit -1; +fi + +if [[ "$testname" == *\/* ]] || [[ "$testname" == *\\* ]]; then + echo "Invalid test name" + exit -1; +fi + +rm -Rf "$testname" + +expect "$testname.expect" "$testname" + +echo "Testing $testname" +cd $testname +npm install +npm run eslint +npm run tslint +npm test +npm run build +cd .. diff --git a/tests/ts-no-router-airbnb.expect b/tests/ts-no-router-airbnb.expect new file mode 100644 index 0000000000..707af815ed --- /dev/null +++ b/tests/ts-no-router-airbnb.expect @@ -0,0 +1,33 @@ +set testname [lindex $argv 0]; +spawn ../node_modules/.bin/vue init .. $testname + +expect "Project name" +send "\n" +expect "Project description" +send "\n" +expect "Author" +send "\n" +expect "Vue build" +send "\n" +expect "Install vue-router?" +send "n" +send "\n" +expect "Which JavaScript compiler do you want to use?" +send "\n" +expect "Use ESLint to lint your JavaScript code?" +send "\n" +expect "Pick an ESLint preset" +send "\[B" +expect "AirBNB" +send "\n" +expect "Use TSLint to lint your TypeScript code?" +send "\n" +expect "Pick a TSLint preset" +send "\[B" +expect "AirBNB" +send "\n" +expect "Setup unit tests with Karma + Mocha?" +send "\n" +expect "Setup e2e tests with Nightwatch?" +send "\n" +expect eof diff --git a/tests/ts-no-router-airbnb.sh.issue9 b/tests/ts-no-router-airbnb.sh.issue9 new file mode 100644 index 0000000000..2a4413cf8c --- /dev/null +++ b/tests/ts-no-router-airbnb.sh.issue9 @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +testname=$1 + +if [[ -z $testname ]]; then + echo "No test name given" + exit -1; +fi + +if [[ "$testname" == *\/* ]] || [[ "$testname" == *\\* ]]; then + echo "Invalid test name" + exit -1; +fi + +rm -Rf "$testname" + +expect "$testname.expect" "$testname" + +echo "Testing $testname" +cd $testname +npm install +npm run eslint +npm run tslint +npm test +npm run build +cd ..