一起实现一个VSCode插件
Smoothness 2023/4/7 VSCodeVSCode Plugin
本文带你一起实现一个VSCode
插件
# 仓库地址 (opens new window)
# smoothing-generator
项目介绍 搭配Smoothing-cli实现的VSCode插件,可以直接生成完整的模块
项目目录
# 开始
项目创建
- 运行
npm install -g yo smoothing-generator
1
- 运行
配置
- 这里主要是
package.json
的配置 - main 定义了整个插件的主入口,,可以新建 src 文件夹,将 extension.ts 已到 src 文件夹下面。
contributes.commands
注册了名为smoothing.generator-module
的命令,并在src/extension.ts
实现。- 最后在
activationEvents
中加入要注册的插件名onCommand:smoothing.generator-module
{ "name": "smoothing-generator", "displayName": "smoothing-generator", "description": "An extension to accelerate the process of developing applications with Vue, aimed at everyone using the Vue-Template.", "version": "0.0.3", "engines": { "vscode": "^1.74.0" }, "categories": [ "Snippets", "Programming Languages", "Other" ], "activationEvents": [ "onCommand:smoothing.generator-module" ], "keywords": [ "vue-modules" ], "repository": { "type": "git", "url": "https://github.com/GGupzHH/smoothing-generator.git" }, "author": "Smoothness", "publisher": "smoothness", "bugs": { "url": "https://github.com/GGupzHH/smoothing-generator/issues" }, "main": "./out/extension.js", "contributes": { "snippets": [ { "language": "vue", "path": "./snippets/vue.snippets.json" }, { "language": "typescript", "path": "./snippets/pinia.snippets.json" }, { "language": "typescript", "path": "./snippets/vue-ts.snippets.json" }, { "language": "html", "path": "./snippets/vue-pug.snippets.json" } ], "commands": [ { "command": "smoothing.generator-module", "title": "Smo: Create Module Template" } ], "menus": { "explorer/context": [ { "command": "smoothing.generator-module", "group": "blocGroup@1", "when": "explorerResourceIsFolder" } ] } }, "scripts": { "vscode:prepublish": "yarn run compile", "compile": "tsc -p ./", "watch": "tsc -watch -p ./", "pretest": "yarn run compile && yarn run lint", "lint": "eslint src --ext ts", "test": "node ./out/test/runTest.js" }, "devDependencies": { "@types/glob": "^8.0.0", "@types/mocha": "^10.0.1", "@types/node": "16.x", "@types/vscode": "^1.74.0", "@typescript-eslint/eslint-plugin": "^5.45.0", "@typescript-eslint/parser": "^5.45.0", "@vscode/test-electron": "^2.2.0", "eslint": "^8.28.0", "glob": "^8.0.3", "mocha": "^10.1.0", "typescript": "^4.9.3" }, "dependencies": { "@types/lodash": "^4.14.191", "@types/mkdirp": "^0.5.2", "change-case": "^3.1.0", "lodash": "^4.17.19", "mkdirp": "^0.5.1" } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93- 这里主要是
实现
- extension.ts
// The module 'vscode' contains the VS Code extensibility API // Import the module and reference it with the alias vscode in your code below import * as vscode from 'vscode'; import { commands } from './commands'; // This method is called when your extension is activated // Your extension is activated the very first time the command is executed export function activate(context: vscode.ExtensionContext) { // 注册指令 context.subscriptions.push( vscode.commands.registerCommand( 'smoothing.generator-module', commands.newGetxGetBuilderPage ) ); } // This method is called when your extension is deactivated export function deactivate() {}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- extension.ts
模板
- generator.module.template.ts
import * as changeCase from "change-case"; import { existsSync, lstatSync, writeFile } from "fs"; /** * pascalCaseName: The first letter is uppercase module name * snakeCaseName: The module name * targetPath: The module path */ // api function apiTemplate(pageName: string, targetDirectory: string) { const pascalCaseName = changeCase.pascalCase(pageName.toLowerCase()); const snakeCaseName = changeCase.snakeCase(pageName.toLowerCase()); const targetPath = `${targetDirectory}/${pascalCaseName}/api/api.ts`; const template = ` import request from '@/utils/request' const ${snakeCaseName}Api = { getDemoTestListID(id: string) { return request.get(\`/api/\${ id }/list\`) } } export default ${snakeCaseName}Api `; return new Promise(async (resolve, reject) => { writeFile(targetPath, template, "utf8", (error) => { if (error) { reject(error); return; } resolve; }); }); } // page function pageTemplate(pageName: string, targetDirectory: string) { const pascalCaseName = changeCase.pascalCase(pageName.toLowerCase()); const snakeCaseName = changeCase.snakeCase(pageName.toLowerCase()); const targetPath = `${targetDirectory}/${pascalCaseName}/pages/${snakeCaseName}.vue`; const template = ` <template> </template> <script lang="ts"> import { defineComponent, getCurrentInstance } from 'vue' export default defineComponent({ name: '${pascalCaseName}' }) </script> <script setup lang="ts"> const proxy = getCurrentInstance()?.proxy </script> <style scoped lang="scss"> </style> `; return new Promise(async (resolve, reject) => { writeFile(targetPath, template, "utf8", (error) => { if (error) { reject(error); return; } resolve; }); }); } // store function storeTemplate(pageName: string, targetDirectory: string) { const pascalCaseName = changeCase.pascalCase(pageName.toLowerCase()); const snakeCaseName = changeCase.snakeCase(pageName.toLowerCase()); const targetPath = `${targetDirectory}/${pascalCaseName}/store/index.ts`; const template = ` import { defineStore } from 'pinia' import ${snakeCaseName}Api from 'modules/${pascalCaseName}/api' export const use${pascalCaseName} = defineStore('${pascalCaseName}', { state: () => { return { id: 'absdb' } }, actions: { async getDemoTestList() { const res = await ${snakeCaseName}Api.getDemoTestListID(this.id) return this.filterResponse(res) } } }) `; return new Promise(async (resolve, reject) => { writeFile(targetPath, template, "utf8", (error) => { if (error) { reject(error); return; } resolve; }); }); } export default { apiTemplate, pageTemplate, storeTemplate };
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
- generator.module.template.ts
snippets
pinia.snippets.json
{ "smoothing generator Pinia Template": { "prefix": "smo-pinia-init", "body": [ "import { defineStore } from 'pinia'", "import $1AllApi from '@/modules/$1/api/index'", "export const use$1 = defineStore('$1', {", "\tstate: () => {", "\t\treturn {", "\t\t\t", "\t\t}", "\t},", "\tactions: {", "\t\tasync getProjectList(params: any) {", "\t\t\tconst res = await $1AllApi.getProjectList(params)", "\t\t\treturn this.filterResponse(res)", "\t\t},", "\t}", "})", "", "export type Iuse$1 = ReturnType<typeof use$1>" ] }, "smoothing generator Pinia Actions": { "prefix": "smo-pinia-actions", "body": [ "async $1($2: $3) {", "\tconst result = await $4($2)", "\treturn this.filterResponse(result)", "}," ] } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34vue-pug.snippets.json
{ "Vue v-for": { "prefix": "vfor", "body": [ "<${1:div} v-for=\"${2:item} in ${2:item}s\" :key=\"${2:item}.id\">", "\t{{ ${2:item} }}", "</${1:div}>" ], "description": "vfor statement" } }
1
2
3
4
5
6
7
8
9
10
11vue-ts.snippets.json
{ "smoothing generator handleFunction": { "prefix": "smo-handleFunction", "body": [ "const handle$1 = () => {", "}" ], "description": "Create Handle Function" }, "smoothing generator init Vue-Router": { "prefix": "smo-init-router", "body": [ "const router = useRouter()" ], "description": "Create Vue Router" }, "smoothing generator init Vue-Route": { "prefix": "smo-init-route", "body": [ "const route = useRoute()" ], "description": "Create Vue Route" }, "smoothing generator init Pinia-store": { "prefix": "smo-init-store", "body": [ "const storeUse$1 = use$1()" ], "description": "Create Pinia Store" } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34vue.snippets.json
{ "smoothing generator Vue2 Template": { "prefix": "smo-vue-2", "body": [ "<template>", "\t<div>\n", "\t</div>", "</template>\n", "<script>", "export default {", "\tname: '$1',", "\tdata() {", "\t\treturn {\n", "\t\t};", "\t},", "\tcreated() {\n", "\t},", "\tmounted() {\n", "\t},", "\tmethods: {\n", "\t}", "};", "</script>\n", "<style scoped lang=\"${1:scss}\">\n", "</style>\n" ], "description": "Create vue2 template" }, "smoothing generator Vue3 Template": { "prefix": "smo-vue-3", "body": [ "<template>", "</template>", "<script lang=\"ts\">", "import {", "\tdefineComponent,", "} from 'vue'", "export default defineComponent({", "\tname: '$1',", "\tcomponents: {},", "\tprops: {},", "\tsetup () {", "\t\treturn {", "\t\t}", "\t}", "})", "</script>", "<style lang=\"scss\" scoped>", "</style>" ], "description": "Create vue3 setup template" }, "smoothing generator Vue3 Template setup syntactic sugar": { "prefix": "smo-vue-3-s-t", "body": [ "<template>", "", "</template>", "", "<script lang=\"ts\">", "import {", "\tdefineComponent,", "\tgetCurrentInstance", "} from 'vue'", "export default defineComponent({", "\tname: '$1'", "})", "</script>", "", "<script setup lang=\"ts\">", "const proxy = getCurrentInstance()?.proxy", "</script>", "", "<style scoped lang=\"scss\">", "", "</style>" ], "description": "Create vue3 setup sugar template" } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
打包
安装
vsce
npm install vsce -g
1打包
vsce package
1
发布
# 使用
- 安装
- 直接搜索
smoothing-generator
安装即可
- 直接搜索
- 使用
- 在目标文件夹右键
- 找到选项
Smo: Create Module Template
- 输入模块名称即可
# 想法
- 搭配
smoothing-cli
可以加入更多不同模板细粒度的文件夹,提高效率