一起实现一个VSCode插件

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
  • 模板

    • 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
  • 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
      34
    • vue-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
      11
    • vue-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
      34
    • vue.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可以加入更多不同模板细粒度的文件夹,提高效率
最后更新时间: 2023/4/13 09:58:39