Objective of this paper: To build a VS Code plug-in that supports embedded web pages, to realize automatic generation of front-end form Code of Vue project, and to realize the freedom of touch as soon as possible.

Results show

Without further ado, let’s take a look at the final work:


After watching the GIF is not refreshing so didiao, let’s get started ~~

Step 1

First of all, we need an open source visual designer for drag-and-drop design. We searched GitHub and code cloud, and we already have a lot of finished products, including various form-create, form-Design, vue-Form, form-Generator, etc.

Second, filter from the above designer support code generation, of course, if there is no code generation can be implemented, after all, is not open source?

VForm GitHub is an open source VForm designer. Haha… It looks familiar, but it’s a little bit more functional

Step 2

Install VS Code Plug-in Development suite:

npm install -g yo generator-code
Copy the code

After successful installation, run Yo Code to generate a new plug-in project:

Use a simple and pleasant name — Quick-coder, add a simple description, and select the other options as needed.

Take a look at the generated plug-in project:

There are only two files to focus on here: extension.js and package.json

Extension.js, plug-in extension point description file package.json, project properties, dependency packages, and plug-in configuration file

The second step is over, and the third step is to implement the plug-in coding.

Step 3

Modify package.json to add startup commands for the plug-in, which can be launched from the command panel and the left explorer.

"contributes": {
    "commands": [{
        "command": "extension.openVFormMaker"."title": "Open VForm Designer"}]."menus": {
        "explorer/context": [{
            "command": "extension.openVFormMaker"."group": "navigation"}}},Copy the code

Modify the extension.js plug-in enablement method with just one line:

function activate(context) {
    require('./src/vform-loader')(context)
}

Copy the code

At this point, we haven’t explained how the entire code generator plug-in works, but now it’s time to tell. We want a WebView panel to open when the plug-in starts, the WebView panel to load the VForm web page via URL configuration parameters, and VS Code to postMessage when the VForm generates Code, which VS Code is responsible for saving as a local file. The key code to implement the above requirements is in the vform-loader.js file.

Here are two more trivia questions to answer:

  1. Can WebView load remote web pages directly? The answer is no, you can only load local HTML files.
  1. So the question is, right? How does a WebView load the HTML of a remote web page? The answer is simply to embed iframe in the local HTML file. Iframe is versatile – YYDS!

With these small cases solved, let’s take a look at the soul code of the plug-in.

src\view\index.html

<! DOCTYPEhtml>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width,initial-scale=0,maximum-scale=0,user-scalable=yes,shrink-to-fit=no"
    />
    <title>Quick Coder</title>
  </head>

  <body>
    <iframe id="frame" width="100%" height="100%" frameborder="0"></iframe>
    <script>
      window.onload = function () {
        const vscode = acquireVsCodeApi();
        const cmds = {
          setSrc: function (message) {
            var frame = document.getElementById("frame");
            frame.src = message.data.src;
          },
          writeFile: function (message) {
            vscode.postMessage(message);
          },
          openUrl: function (message) {
            vscode.postMessage(message);
          },
          setStorageItem: function (message) { vscode.postMessage(message); }};window.addEventListener("message".(event) = > {
          const message = event.data;
          if (message && message.cmd) cmds[message.cmd](message);
        });
      };
    </script>
  </body>
</html>

Copy the code

src\vform-loader.js

const vscode = require('vscode')
const fs = require('fs')
const path = require('path')
const open = require('open')
const DB_PATH = path.join(__dirname,'./data/db.json')

function getExtensionFileAbsolutePath(context, relativePath) {
    return path.join(context.extensionPath, relativePath)
}

/** * Reads HTML content from an HTML file that can be loaded by the Webview *@param {*} Context *@param {*} TemplatePath the HTML file relative to the plug-in root directory */
function getWebViewContent(context, templatePath) {
    const resourcePath = getExtensionFileAbsolutePath(context, templatePath)
    const dirPath = path.dirname(resourcePath)
    let html = fs.readFileSync(resourcePath, 'utf-8')
    // vscode does not support direct loading of local resources, so it needs to be replaced with its own path format. Here we simply replace the style and JS path
    html = html.replace(/(.(m, $1, $2) = > {
        return $1 + vscode.Uri.file(path.resolve(dirPath, $2)).with({ scheme: 'vscode-resource' }).toString() + '"'
    })
    return html
}

const methods = {
    writeFile: function (message, vscode, dirPath) {
        let { fileName, code } = message.data
        let filePath = path.join(dirPath, fileName)
        fs.writeFileSync(filePath, code)
        vscode.window.showInformationMessage(` file${fileName}Create success ')},openUrl: function (message, vscode, dirPath) {
        open(message.data.url)
    },
    setStorageItem: function(message, vscode, dirPath) {
        const { key, val } = message.data
        const str = fs.readFileSync(DB_PATH).toString()
        let json = {}
        if (str) {
            json = JSON.parse(str)
        }
        json[key] = val
        fs.writeFileSync(DB_PATH, JSON.stringify(json))
    },
}

module.exports = function (context) {
    context.subscriptions.push(vscode.commands.registerCommand('extension.openVFormMaker'.(uri) = > {
        if (uri) {
            let dirPath = uri.fsPath,
                stat = fs.lstatSync(dirPath)
            if (stat.isFile()) dirPath = path.dirname(dirPath)

            let pclintBar = vscode.window.createStatusBarItem()
            pclintBar.text = 'Target folder:${dirPath}`
            pclintBar.show()

            const panel = vscode.window.createWebviewPanel(
                'vFormMaker'.VForm Form Designer,
                vscode.ViewColumn.One,
                {
                    enableScripts: true.// Enable JS, disabled by default
                    retainContextWhenHidden: true.// WebView remains in state when hidden to avoid being reset
                }
            )
            panel.onDidChangeViewState(e= > {
                if (panel.visible) {
                    pclintBar.show()
                } else {
                    pclintBar.hide()
                }
            })
            panel.webview.html = getWebViewContent(context, 'src/view/index.html')
            panel.webview.postMessage({
                cmd: 'setSrc'.data: {
                    src: vscode.workspace.getConfiguration().get('VFormMaker.url') + '&t=' + new Date(),
                    db: JSON.parse(fs.readFileSync(DB_PATH).toString() || '{}')
                }
            })
            panel.webview.onDidReceiveMessage(message= > {
                if (message.cmd && message.data) {
                    let method = methods[message.cmd]
                    if (method) method(message, vscode, dirPath)
                } else {
                    vscode.window.showInformationMessage('No method corresponding to the message')}},undefined, context.subscriptions)
            panel.onDidDispose(e= > {
                pclintBar.dispose()
            })
        } else {
            vscode.window.showInformationMessage('Cannot get folder path')}}}))Copy the code

OK~ grey often good, give a big hand to see here πŸ‘πŸ‘πŸ‘, soon to see the effect of the plugin!!

Finally modify package.json file contributes attribute, add URL parameter configuration, complete!!

"contributes": {
    "configuration": {
        "type": "object"."title": "VForm Designer Configuration"."properties": {
            "VFormMaker.url": {
                "type": "string"."default": "Http://120.92.142.115/? vscode=1"."description": "VForm Designer remote URL"}}},Copy the code

Press F5 in VS Code to debug the plugin and enjoy your work 😀😀~~~

Step 4 / Package and publish

Install the vsCE packaging tool

npm install -g vsce
Copy the code

Run the vsce package command in the plug-in project to generate a.vsix file (you will be prompted to modify the readme. md file to add an introduction and instructions for the plug-in).

vsce package
Copy the code

Sign up for a VS Marketplace account, upload a.vsix file, and make it available to all VS Code users: VS Marketplace

The latter/Finally

As a brief review, we embedded VForm remote web pages through WebView, realizing common Vue form front-end code generation (support Vue2 also support Vue3 oh) expected requirements, because VForm itself is an open source project, and has good scalability, interested big people can freely extend VForm functions. Further realization of el-table and other components of the front-end code automatic generation, as soon as possible to achieve fish free 🍺🍺🍺

The last

For those who feel a little tired of writing their own plug-ins, you can search vform-Maker or vformAdmin directly in the VS Code extension

Finally, attach the VForm link of GitHub, the world’s largest gay dating website: Gitee