vscode-page is a light-weight page micro framework for vscode webview, it could accelerate Vs Code Extension Webview development.
- abstract the communication between html page and WebviewPanel, developers can focus on business logic.
- built-in template engine, with handlebars.js.
- message mapping, a simple way to organize page logic and view.
- baseUrl support, relative paths can be used in html page.
npm install vscode-page
vscode-page simplifies Webview development with following steps:
- define messages between html page and vscode.WebviewPanel.
- develop html page and js functions inside that page.
- define MessageMappings.
- register a command to create (or show) WebviewPanel with the MessageMappings defined in step 3.
The whole architecture is shown below:
Also, there is a demo project to show its usage. Before check it, please read the following first.
As described in vscode extension guide, html page and WebviewPanel can post messages each other. To standardize this communication, vscode-page defines two message formats.
The message json format :
- command, an indexed value for a command handler defined in a MessageMapping.
- parameters (optional), an json argument passed to that command handler.
Here is an example:
{
"command": "showExtension",
"parameters": {
"repo": repo,
"extId": extId,
"installed": installed
}
}
The message json format :
- command, if ending with "Response", it is a response of the prefix. Such as "showExtensionResponse" is response of "showExtension".
- contents (optional), a content array. Each item has following keys:
- id, element id in a html page.
- body, innerHtml (generated by the template defined in a MessageMapping) of the element pointed by id.
- result (optional), return value of the "${command}" handler.
Here is an example:
{
"command": "showExtensionResponse",
"contents": [
{ "id": "title", "body": "Repo / Extension" },
{
"id": "content",
"body": "...."
}
]
}
In order to initialize correctly, for each html page, please insert the following two lines in <head>:
<base href="{{base}}" />
<script type="text/javascript">
"{{init}}"
</script>
Here is the explaination:
- {{base}} will be replaced by "path.join(context.extensionPath, root)", then relative paths can be used in that page.
- {{init}} will be replaced by initEventListener function definition, which defines an EventListener receiving messages from WebviewPanel.
Then it can be invoked to add an event listener to html page as below:
initEventListener();
The default implementation will only process messages ending with "Response" and use contents as innerHtml of selected elements.
For other messages, a customized function can be passed to initEventListener as below:
initEventListener(message => {...});
The message has following key:
- result, return value of a command handler.
A MessageMapping defines:
- command, the value of "command" field in message posted by js function.
- handler, a function for the command above, its signature is below and the parameters is the value of "parameters" in the same message from js function.
(parameters?: any) => Promise<any>;
- templates (optional), a template array for views of response of the command. Each item has the following keys:
- id, element id in html page.
- content, a inline handlebars template, it is optional.
- contentUrl, a url to an external handlebars template, it is optional.
- forward (optional), similar to request-forward pattern in web development, a MessageMapping the request flow will go.
NOTE:
- either "content" or "contentUrl" MUST be shown in a MessageMapping, not both.
- both of "templates" and "forward" are optional, but if being used, only one of them can be shown in a MessageMapping.
Here is a MessageMappings example: home.ts
To create or show a WebviewPanel, invoke function createOrShowPage like beblow (from extension.ts in example):
createOrShowPage(
'name',
'ext.home',
'Sample Page',
'pages',
'home.html',
context,
messageMappings
);
The signature of createOrShowPage:
export function createOrShowPage(
name: string,
viewType: string,
title: string,
base: string,
page: string,
context: vscode.ExtensionContext,
messageMappings: MesssageMaping[]
);
Each argument:
- name, a named index of the WebviewPanel created.
- viewType and title, both of them will be passed to vscode.window.createWebviewPanel.
- base, a relative path to <base> in html page.
- page, a path to html file.
- context, vscode.ExtensionContext.
- messageMappings, MesssageMaping array defined, check examples in home.ts.
vscode-page is a tool for vscode extension development and uses handlebars.js as its template engine.
So, please install vscode and handlebars first.
For local debugging, please run the following command under the directory of vscode-page project:
npm link
Then, in the project using vscode-page, please run the following command:
npm link vscode-page
NOTE:
The linked package in application will use its own node_modules, so if you defined your own handlebars helper in application, vscode-page can not find it.
app
|- node_modules
|- vscode-page <-- project linked by "npm link"
| ├─ node_modules
| | |- handlebars.js <-- used by vscode-page
|
|- handlebars.js <-- you defined helper in it
I can not find an easy way to fix it, only find the following steps. If you have any good idea, please let me know.
- "npm pack" in vscode-page project.
- "npm install local-package" in your application.
Please visit issues page to submit new issues or check known issues.
First release.
vscode-page is released under the Apache License 2.0 license.