Skip to content

Commit 54a902d

Browse files
committed
feat: preliminary TS plugin imeplementation
1 parent 8aba87f commit 54a902d

File tree

17 files changed

+528
-5
lines changed

17 files changed

+528
-5
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
module.exports = (api, options) => {
2+
api.render('./template')
3+
4+
api.extendPackage({
5+
scripts: {
6+
lint: 'vue-cli-service lint'
7+
}
8+
})
9+
10+
if (options.classComponent) {
11+
api.extendPackage({
12+
devDependencies: {
13+
'vue-class-component': '^6.0.0',
14+
'vue-property-decorator': '^6.0.0'
15+
}
16+
})
17+
}
18+
19+
// delete all js files that have a ts file of the same name
20+
// TODO compat with PWA and test plugins
21+
const jsRE = /\.js$/
22+
api.postProcessFiles(files => {
23+
for (const file in files) {
24+
if (jsRE.test(file) && files[file.replace(jsRE, '.ts')]) {
25+
delete files[file]
26+
}
27+
}
28+
})
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<%_ if (!rootOptions.router) { _%>
2+
<template>
3+
<div id="app">
4+
<img src="./assets/logo.png">
5+
<HelloWorld msg="Welcome to Your Vue.js App"/>
6+
</div>
7+
</template>
8+
9+
<script lang="ts">
10+
<%_ if (!options.classComponent) { _%>
11+
import Vue from 'vue';
12+
import HelloWorld from './components/HelloWorld.vue';
13+
14+
export default Vue.extend({
15+
name: 'app',
16+
components: {
17+
HelloWorld
18+
}
19+
});
20+
<%_ } else { _%>
21+
import { Component, Vue } from 'vue-property-decorator';
22+
import HelloWorld from './components/HelloWorld.vue';
23+
24+
@Component({
25+
components: {
26+
HelloWorld,
27+
},
28+
})
29+
export default class App extends Vue {}
30+
<%_ } _%>
31+
</script>
32+
<%_ } else { _%>
33+
<template>
34+
<div id="app">
35+
<div id="nav">
36+
<router-link to="/">Home</router-link> |
37+
<router-link to="/about">About</router-link>
38+
</div>
39+
<router-view/>
40+
</div>
41+
</template>
42+
<%_ } _%>
43+
44+
<style>
45+
#app {
46+
font-family: 'Avenir', Helvetica, Arial, sans-serif;
47+
-webkit-font-smoothing: antialiased;
48+
-moz-osx-font-smoothing: grayscale;
49+
text-align: center;
50+
color: #2c3e50;
51+
<%_ if (!rootOptions.router) { _%>
52+
margin-top: 60px;
53+
<%_ } _%>
54+
}
55+
<%_ if (rootOptions.router) { _%>
56+
57+
#nav {
58+
padding: 30px;
59+
}
60+
61+
#nav a {
62+
font-weight: bold;
63+
color: #2c3e50;
64+
}
65+
66+
#nav a.router-link-exact-active {
67+
color: #42b983;
68+
}
69+
<%_ } _%>
70+
</style>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<template>
2+
<div class="hello">
3+
<h1>{{ msg }}</h1>
4+
<h2>Essential Links</h2>
5+
<ul>
6+
<li><a href="https://vuejs.org" target="_blank">Core Docs</a></li>
7+
<li><a href="https://forum.vuejs.org" target="_blank">Forum</a></li>
8+
<li><a href="https://chat.vuejs.org" target="_blank">Community Chat</a></li>
9+
<li><a href="https://twitter.com/vuejs" target="_blank">Twitter</a></li>
10+
<br>
11+
<li><a href="http://vuejs-templates.github.io/webpack/" target="_blank">Docs for This Template</a></li>
12+
</ul>
13+
<h2>Ecosystem</h2>
14+
<ul>
15+
<li><a href="http://router.vuejs.org/" target="_blank">vue-router</a></li>
16+
<li><a href="http://vuex.vuejs.org/" target="_blank">vuex</a></li>
17+
<li><a href="http://vue-loader.vuejs.org/" target="_blank">vue-loader</a></li>
18+
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank">awesome-vue</a></li>
19+
</ul>
20+
</div>
21+
</template>
22+
23+
<script lang="ts">
24+
<%_ if (!options.classComponent) { _%>
25+
import Vue from 'vue';
26+
27+
export default Vue.extend({
28+
name: 'HelloWorld',
29+
props: {
30+
msg: String,
31+
},
32+
});
33+
<%_ } else { _%>
34+
import { Component, Prop, Vue } from 'vue-property-decorator';
35+
36+
@Component
37+
export default class HelloWorld extends Vue {
38+
@Prop() private msg: string;
39+
}
40+
<%_ } _%>
41+
</script>
42+
43+
<!-- Add "scoped" attribute to limit CSS to this component only -->
44+
<style scoped>
45+
h1, h2 {
46+
font-weight: normal;
47+
}
48+
ul {
49+
list-style-type: none;
50+
padding: 0;
51+
}
52+
li {
53+
display: inline-block;
54+
margin: 0 10px;
55+
}
56+
a {
57+
color: #42b983;
58+
}
59+
</style>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import Vue from 'vue';
2+
import App from './App.vue';
3+
<%_ if (rootOptions.router) { _%>
4+
import router from './router';
5+
<%_ } _%>
6+
<%_ if (rootOptions.vuex) { _%>
7+
import store from './store';
8+
<%_ } _%>
9+
10+
Vue.config.productionTip = false;
11+
12+
new Vue({
13+
<%_ if (rootOptions.router) { _%>
14+
router,
15+
<%_ } _%>
16+
<%_ if (rootOptions.vuex) { _%>
17+
store,
18+
<%_ } _%>
19+
render: h => h(App),
20+
}).$mount('#app');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<%_ if (rootOptions.router) { _%>
2+
import Vue from 'vue';
3+
import Router from 'vue-router';
4+
import Home from './views/Home.vue';
5+
import About from './views/About.vue';
6+
7+
Vue.use(Router);
8+
9+
export default new Router({
10+
routes: [
11+
{
12+
path: '/',
13+
name: 'home',
14+
component: Home
15+
},
16+
{
17+
path: '/about',
18+
name: 'about',
19+
component: About
20+
}
21+
]
22+
});
23+
<%_ } _%>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<%_ if (rootOptions.vuex) { _%>
2+
import Vue from 'vue';
3+
import Vuex from 'vuex';
4+
5+
Vue.use(Vuex);
6+
7+
export default new Vuex.Store({
8+
state: {
9+
10+
},
11+
mutations: {
12+
13+
},
14+
actions: {
15+
16+
}
17+
});
18+
<%_ } _%>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<%_ if (rootOptions.router) { _%>
2+
<template>
3+
<div class="about">
4+
<h1>This is an about page</h1>
5+
</div>
6+
</template>
7+
<%_ } _%>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<%_ if (rootOptions.router) { _%>
2+
<template>
3+
<div class="home">
4+
<img src="../assets/logo.png">
5+
<HelloWorld msg="Welcome to Your Vue.js App"/>
6+
</div>
7+
</template>
8+
9+
<script lang="ts">
10+
<%_ if (!options.classComponent) { _%>
11+
import Vue from 'vue';
12+
import HelloWorld from '@/components/HelloWorld.vue'; // @ is an alias to /src
13+
14+
export default Vue.extend({
15+
name: 'home',
16+
components: {
17+
HelloWorld,
18+
},
19+
});
20+
<%_ } else { _%>
21+
import { Component, Vue } from 'vue-property-decorator';
22+
import HelloWorld from '@/components/HelloWorld.vue'; // @ is an alias to /src
23+
24+
@Component({
25+
components: {
26+
HelloWorld,
27+
},
28+
})
29+
export default class Home extends Vue {}
30+
<%_ } _%>
31+
</script>
32+
<%_ } _%>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
declare module '*.vue' {
2+
import Vue from 'vue';
3+
export default Vue;
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"compilerOptions": {
3+
"target": "es5",
4+
"module": "es2015",
5+
"strict": true,
6+
"moduleResolution": "node",
7+
<%_ if (options.classComponent) { _%>
8+
"experimentalDecorators": true,
9+
"emitDecoratorMetadata": true,
10+
<%_ } _%>
11+
"sourceMap": true,
12+
"baseUrl": ".",
13+
"paths": {
14+
"@/*": [
15+
"src/*"
16+
]
17+
}
18+
},
19+
"include": [
20+
"src/**/*.ts",
21+
"src/**/*.vue"
22+
],
23+
"exclude": [
24+
"node_modules"
25+
]
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"defaultSeverity": "warning",
3+
"extends": [
4+
"tslint:recommended"
5+
],
6+
"rules": {
7+
"quotemark": [
8+
true,
9+
"single"
10+
],
11+
"indent": [
12+
true
13+
],
14+
"interface-name": [
15+
false
16+
],
17+
"arrow-parens": false,
18+
// Pending fix for shorthand property names.
19+
"object-literal-sort-keys": false
20+
}
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
module.exports = api => {
2+
api.chainWebpack(config => {
3+
config.entry('app')
4+
.clear()
5+
.add('./src/main.ts')
6+
7+
config.resolve
8+
.extensions
9+
.merge(['.ts', '.tsx'])
10+
11+
config.module
12+
.rule('ts')
13+
.test(/\.tsx?$/)
14+
.include
15+
.add(api.resolve('src'))
16+
.end()
17+
.use('ts-loader')
18+
.loader('ts-loader')
19+
.options({
20+
transpileOnly: true,
21+
appendTsSuffixTo: [/\.vue$/]
22+
})
23+
24+
config
25+
.plugin('fork-ts-checker')
26+
.use(require('fork-ts-checker-webpack-plugin'), [{
27+
vue: true,
28+
tslint: true,
29+
formatter: 'codeframe'
30+
}])
31+
})
32+
33+
api.registerCommand('lint', {
34+
descriptions: 'lint source files with TSLint',
35+
usage: 'vue-cli-service lint [options] [...files]',
36+
options: {
37+
'--format': 'specify formatter (default: codeframe)',
38+
'--no-fix': 'do not fix errors'
39+
},
40+
details: 'For more options, see https://palantir.github.io/tslint/usage/cli/'
41+
}, (args) => {
42+
const { run } = require('tslint/lib/runner')
43+
44+
return run({
45+
files: args._ && args._.length ? args._ : ['src/**/*.ts'],
46+
exclude: args.exclude || [],
47+
fix: !args['no-fix'],
48+
project: api.resolve('tsconfig.json'),
49+
config: api.resolve('tslint.json'),
50+
force: args.force,
51+
format: args.format,
52+
formattersDirectory: args['formatters-dir'],
53+
init: args.init,
54+
out: args.out,
55+
outputAbsolutePaths: args['output-absolute-paths'],
56+
rulesDirectory: args['rules-dir'],
57+
test: args.test,
58+
typeCheck: args['type-check']
59+
}, {
60+
log (m) { process.stdout.write(m) },
61+
error (m) { process.stdout.write(m) }
62+
}).then(code => {
63+
process.exitCode = code
64+
}).catch(err => {
65+
console.error(err)
66+
process.exitCode = 1
67+
})
68+
})
69+
}

0 commit comments

Comments
 (0)