8

background

Presumably every skilled front-end trendsetter will often extract components from public components after becoming proficient in business, which can greatly improve development efficiency. However, after the public components are extracted, the daily development is to create the same folder, modify router , modify the properties of the form fields and prop , etc., repeatedly create the same folder, modify the file name repeatedly, and write router repeatedly, etc., but As different people in the group, the styles are inconsistent, so can you both standardize the style of the code and quickly create templates?

Such as our common template types

├─componentsName
│   ├─api
│   │  index.js
│        ├─components
│        │     list-table.vue
│        │     list-search.vue
│        │     index.js
│        ├─config
│        │     index.js
│   index.vue
│   route.js

vscode plugin

Through the study of the official document , we can find the way to extend the vscode plug-in to achieve this function.

  • environment install
npm i -g yo generator-code // 官方插件开发脚手架
yo code // 执行脚手架命令

According to the steps we choose to create New Extension

You can choose your favorite language Javascript or TypeScript , here the author chooses JavaScript

Similarly, we start from the international practice of Hello World and choose the corresponding configuration

Project structure

The project structure is relatively simple, the main files are package.json and extension.js .

{
    "name": "hello-world", // 插件名称
    "displayName": "Hello World",
    "description": "hello world",
    "version": "0.0.1", // 插件版本
    "engines": {
        "vscode": "^1.63.0" // vscode的版本
    },
    "categories": [
        "Other"
    ],
  // 扩展的激活事件
    "activationEvents": [
        "onCommand:hello-world.helloWorld"
    ],
  // 入口文件
    "main": "./extension.js",
  // vscode插件大部分功能配置都在这里配置
    "contributes": {
        "commands": [
            {
                "command": "hello-world.helloWorld",
                "title": "Hello World"
            }
        ]
    },
    "scripts": {
        "lint": "eslint .",
        "pretest": "npm run lint",
        "test": "node ./test/runTest.js"
    },
    "devDependencies": {
        "@types/vscode": "^1.63.0",
        "@types/glob": "^7.1.4",
        "@types/mocha": "^9.0.0",
        "@types/node": "14.x",
        "eslint": "^7.32.0",
        "glob": "^7.1.7",
        "mocha": "^9.1.1",
        "typescript": "^4.4.3",
        "@vscode/test-electron": "^1.6.2"
    }
}

extension.js content of the file is as follows

// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
const vscode = require('vscode');

// this method is called when your extension is activated
// your extension is activated the very first time the command is executed

/**
 * @param {vscode.ExtensionContext} context
 */
function activate(context) {

    // Use the console to output diagnostic information (console.log) and errors (console.error)
    // This line of code will only be executed once when your extension is activated
    console.log('Congratulations, your extension "hello-world" is now active!');

    // The command has been defined in the package.json file
    // Now provide the implementation of the command with  registerCommand
    // The commandId parameter must match the command field in package.json
    let disposable = vscode.commands.registerCommand('hello-world.helloWorld', function () {
        // The code you place here will be executed every time your command is executed

        // Display a message box to the user
        vscode.window.showInformationMessage('Hello World from Hello World!');
    });

    context.subscriptions.push(disposable);
}

// this method is called when your extension is deactivated
function deactivate() {}

module.exports = {
    activate,
    deactivate
}

1. Understand

  • main defines the main entrance of the entire plugin, so see here, according to our inertia, we can create a new folder src , and put extension.js the src folder.
  • contributes.commands registered a command named hello-world.helloWorld and implemented at src/extension.js .
  • After defining the command, you also need to add activationEvents to onCommand:hello-world.helloWorld .

2. Run and debug

After the new construction is completed, the project has already helped us configure the debugging parameters

We just need to click Run Extension and a new vscode window will open showing Extension Development Host

At this point, we press the shortcut key command + shift + P , enter Hello to see the plug-in we wrote, select our plug-in, and you can find the pop-up window Hello World from Hello World! in the lower right corner

3. Add shortcut keys and right-click menu

In our package.json , add the following code

"contributes": {
        "commands": [
            {
                "command": "hello-world.helloWorld",
                "title": "Hello World"
            }
        ],
    "keybindings": [
      {
        "command": "hello-world.helloWorld",
        "key": "ctrl+f10",
        "mac": "cmd+f10",
        "when": "editorFocus"
      }
    ],
    "menus": {
      "explorer/context": [
        {
          "command": "hello-world.helloWorld",
          "group": "navigation", // 菜单位于最上面
          "when": "explorerResourceIsFolder" // 只有是文件夹时才能唤起菜单
        }
      ]
    }
    },

Right-click in the folder area, you can see our menu commands, and you can also see the shortcut keys.

So far, we have completed a simple vscode plugin.

4. Retrofit

Modify the file directory as follows

├─node_modules
├─src
│   main.js
├─test
│ .eslintrc.json
│ .gitignore
│ .vscodeignore
│ jsconfig.json
│ package-lock.json
│ package.json
│    READEME.md
│ vsc-extension-quickstart.md

Modify package.json file

{
    "name": "hello-template",
    "displayName": "hello-template",
    "description": "hello world",
  "publisher": "retrychx",
    "version": "0.0.1",
    "engines": {
        "vscode": "^1.63.0"
    },
    "categories": [
        "Other"
    ],
    "activationEvents": [
        "onCommand:hello-template"
    ],
    "main": "./src/main.js",
    "contributes": {
        "commands": [
            {
                "command": "hello-template",
                "title": "Hello Template"
            }
        ],
    "keybindings": [
      {
        "command": "hello-template",
        "key": "ctrl+f10",
        "mac": "cmd+f10",
        "when": "editorFocus"
      }
    ],
    "menus": {
      "explorer/context": [
        {
          "command": "hello-template",
          "group": "navigation", 
          "when": "explorerResourceIsFolder"
        }
      ]
    }
    },
    "scripts": {
        "lint": "eslint .",
        "pretest": "npm run lint",
        "test": "node ./test/runTest.js"
    },
    "devDependencies": {
        "@types/vscode": "^1.63.0",
        "@types/glob": "^7.1.4",
        "@types/mocha": "^9.0.0",
        "@types/node": "14.x",
        "eslint": "^7.32.0",
        "glob": "^7.1.7",
        "mocha": "^9.1.1",
        "typescript": "^4.4.3",
        "@vscode/test-electron": "^1.6.2"
    }
}

Modify src/main.js file

// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
const vscode = require('vscode');

// this method is called when your extension is activated
// your extension is activated the very first time the command is executed

/**
 * @param {vscode.ExtensionContext} context
 */
function activate(context) {

    // Use the console to output diagnostic information (console.log) and errors (console.error)
    // This line of code will only be executed once when your extension is activated
    console.log('Congratulations, your extension "hello-world" is now active!');

    // The command has been defined in the package.json file
    // Now provide the implementation of the command with  registerCommand
    // The commandId parameter must match the command field in package.json
    let disposable = vscode.commands.registerCommand('hello-template', function () {
        // The code you place here will be executed every time your command is executed

        // Display a message box to the user
        vscode.window.showInformationMessage('test');
    });

    context.subscriptions.push(disposable);
}

// this method is called when your extension is deactivated
function deactivate() {}

module.exports = {
    activate,
    deactivate
}

At the registerCommand method, modify the command to be consistent with package.json in command , then debug and run our vscode , the shortcut key calls out our plugin, you can see our plugin name Hello Template , click, you can see the pop up window

5. Create a new template string

Below src/ , we create a new template.js file and declare the template we want to create in it.

  • route.js Template

Since two variables, route name and title, are required, two variables are declared

const routeTemplate = params => 
`
import List from './index'

export default [
  {
    path: '${params.path}',
    name: '${params.path}',
    meta: {
      title: '${params.title}'
    },
    component: List
  }
]
`
  • index.js Entry file template
const indexTemplate = 
`
<template>
  <div></div>
</template>

<script>
import { ListSearch, ListTable } from './components'
import * as API from './api/index'
import utils from '@/utils'
export default {
  components: { ListSearch, ListTable },
  data() {
    return {
      },
    }
  },
  mounted() {
  },
  methods: {
  },
}
</script>

<style>

</style>
`

According to the packaged components, different templates can be created in sequence: configTemplate , apiTemplate , comIndexTemplate , searchTemplate , tableTemplate , etc., to export the templates we need

const config = {
  routeTemplate: routeTemplate,
  indexTemplate: indexTemplate,
  configTemplate: configTemplate,
  apiTemplate: apiTemplate,
  comIndexTemplate: comIndexTemplate,
  searchTemplate: searchTemplate,
  tableTemplate: tableTemplate
}

module.exports = config

6. Introduce user variables

Since we need asynchronous processing, we introduce async

let disposable = vscode.commands.registerCommand('hello-template', async url => {
         // 设置输入框提示
     const options = {
      prompt: '请输入模板名称',
      placeHolder: '模板名称'
    }
    // 输入模板名称
    const templateName = await vscode.window.showInputBox(options)
    
    // 设置标题
    const optionsTitle = {
      prompt: '请输入标题名称',
      placeHolder: '标题名称'
    }
    // 输入模板名称
    const templateTitle = await vscode.window.showInputBox(optionsTitle)

    // 设置路径
    const optionsRoute = {
      prompt: '请输入路径名称',
      placeHolder: '路径名称'
    }
    // 输入路径名称
    const templateRoute = await vscode.window.showInputBox(optionsRoute)
    
    const params = {
      path: templateRoute,
      title: templateTitle
    }
    });

Running the debugger, we can see that our plugin is called, and we can see that the input box appears:

By entering the name, we can get the variable we want. Then we can call the two modules fs and path to write our own files.

Because of the order in which we create files and folders for guarantee.

First, we used existsSync and mkdirSync to create folders; then we used existsSync and writeFileSync to create files, and then finally, be a successful prompt:

vscode.window.showInformationMessage('模板创建成功')

At this point, we have completed all the coding. Then let's take a look at the final debugging results.

on the folder and summon our plugin command Hello Template

After entering the corresponding name, we can see that the template we want is created under the right-clicked folder.

We can save a lot of repetitive work.

7. Introduce new features

During the development process, the development documents and interfaces provided by the back-end are all connections from mock . At this time, I was wondering if I could parse the interface data of mock and automatically introduce interface annotations.

const request = require('request')

const YAPIURL = 'https://mock.shizhuang-inc.com/api/interface/get'
const param = 'token' // 个人的token

function getYapi(id) {
  const url = `${YAPIURL}?id=${id}&token=${param}`
  return new Promise(async (resolve, reject) => {  
    request(url, function(error, response,body) {
      debugger
      if(error) {
        reject(error)
      }
      const bodyToJson = JSON.parse(body)
      // 接口id不存在
      if(!bodyToJson.data) {
        reject(null)
      }
      resolve({
        title: bodyToJson.data.title,
        path: bodyToJson.data.path
      })
    })
  })
}

module.exports = {
  getYapi
}
  • Add right-click menu

Inside package.json

"menus": {
      "editor/context": [
        {
          "when": "resourceLangId == javascript", // 当文件为js文件的时候
          "command": "erp-addInterface",
          "group": "navigation"
        }
      ]
    }

In main.js , register for command event

let addDisposable = vscode.commands.registerCommand('erp-addInterface', async url => {
     // 设置输入框提示
     const options = {
      prompt: '请输入接口Id',
      placeHolder: '接口Id'
    }
    // 输入路径名称
    const apiTag = await vscode.window.showInputBox(options)
    if(!+apiTag) {
      vscode.window.showInformationMessage('输入正确的接口Id')
      return
    }
    try {
      const res = await api.getYapi(+apiTag)
      const apiName = res.path ? res.path.split('/').pop() : ''
      res.name = apiName

      const interfaceTemplate = config.interfaceTemplate(res)

      await fs.appendFileSync(url.path, interfaceTemplate, 'utf8')

      vscode.window.showInformationMessage('接口添加成功')
    } catch (error) {
      if(!error) {
        vscode.window.showInformationMessage('接口Id不存在')
        return
      }
      vscode.window.showInformationMessage(error)
    }
  • View the effect

Comments and interfaces can be generated, which is convenient and fast.

Pack

Whether it is local packaging or publishing to the application market, we have to use the tool vsce .

1. Installation

npm install vsce -g

2. Packaging

Packaged into vsix file

vsce package

The error is found as follows:

The error states that we want to modify README.md file, we modify the following files and execute the packaging again.

Follow the instructions and execute step by step, the packaging is successful, take a look at our project directory, and you can see our packaging files.

3. Post

Open the official website of Publishing Market , create your own publishing account, and then record your personal token to start publishing.

vsce publish

Enter your own account, and token and you can publish it. After a few minutes, you can see your project on the webpage

For example, the plug-in erp-template released by the author, you can see in the plug-in market search, our own plug-in

Well, at this point, the vscode plug-in development has been completed.

Summarize

This is just a development scenario that comes to mind. Relatively speaking, it just provides a development idea. During the development process, you can think more and do some interesting things.

text/migor

Pay attention to Dewu Technology and be the most fashionable technical person!


得物技术
846 声望1.5k 粉丝