mirror of
https://github.com/microsoft/vscode-extension-samples.git
synced 2026-04-27 16:55:44 +08:00
Add webview sample
This commit is contained in:
@ -11,6 +11,7 @@ list of self-contained, running extensions that show one or multiple concepts of
|
||||
* [Integrated Terminal](/terminal-sample/README.md)
|
||||
* [Vim](/vim-sample/README.md)
|
||||
* Experimental: [Tree Explorer](/tree-view-sample/README.md)
|
||||
* [Webview](/webview-sample/README.md)
|
||||
|
||||
# How to run locally
|
||||
|
||||
|
||||
35
webview-sample/.vscode/launch.json
vendored
Normal file
35
webview-sample/.vscode/launch.json
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
// A launch configuration that compiles the extension and then opens it inside a new window
|
||||
{
|
||||
"version": "0.1.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Launch Extension",
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"runtimeExecutable": "${execPath}",
|
||||
"args": [
|
||||
"/Users/matb/projects/vscode",
|
||||
"--extensionDevelopmentPath=${workspaceRoot}",
|
||||
"--enable-proposed-api=bierner.test-ext"
|
||||
],
|
||||
"stopOnEntry": false,
|
||||
"sourceMaps": true,
|
||||
"outDir": "${workspaceRoot}/out/src",
|
||||
"preLaunchTask": "npm"
|
||||
},
|
||||
{
|
||||
"name": "Launch Tests",
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"runtimeExecutable": "${execPath}",
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceRoot}",
|
||||
"--extensionTestsPath=${workspaceRoot}/out/test"
|
||||
],
|
||||
"stopOnEntry": false,
|
||||
"sourceMaps": true,
|
||||
"outDir": "${workspaceRoot}/out/test",
|
||||
"preLaunchTask": "npm"
|
||||
}
|
||||
]
|
||||
}
|
||||
28
webview-sample/.vscode/tasks.json
vendored
Normal file
28
webview-sample/.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
// Available variables which can be used inside of strings.
|
||||
// ${workspaceRoot}: the root folder of the team
|
||||
// ${file}: the current opened file
|
||||
// ${fileBasename}: the current opened file's basename
|
||||
// ${fileDirname}: the current opened file's dirname
|
||||
// ${fileExtname}: the current opened file's extension
|
||||
// ${cwd}: the current working directory of the spawned process
|
||||
// A task runner that calls a custom npm script that compiles the extension.
|
||||
{
|
||||
"version": "0.1.0",
|
||||
// we want to run npm
|
||||
"command": "npm",
|
||||
// the command is a shell script
|
||||
"isShellCommand": true,
|
||||
// show the output window only if unrecognized errors occur.
|
||||
"showOutput": "silent",
|
||||
// we run the custom script "compile" as defined in package.json
|
||||
"args": [
|
||||
"run",
|
||||
"compile",
|
||||
"--loglevel",
|
||||
"silent"
|
||||
],
|
||||
// The tsc compiler is started in watching mode
|
||||
"isWatching": true,
|
||||
// use the standard tsc in watch mode problem matcher to find compile problems in the output.
|
||||
"problemMatcher": "$tsc-watch"
|
||||
}
|
||||
20
webview-sample/README.md
Normal file
20
webview-sample/README.md
Normal file
@ -0,0 +1,20 @@
|
||||
# Cat Coding — A Webview API Sample
|
||||
|
||||
Demonstrates VS Code's [webview API](https://code.visualstudio.com/docs/extensions/webview). This includes:
|
||||
|
||||
- Creating and showing a basic webview.
|
||||
- Dynamically updating a webview's content.
|
||||
- Loading local content in a webview.
|
||||
- Running scripts in a webview.
|
||||
- Sending message from an extension to a webview.
|
||||
- Sending messages from a webview to an extension.
|
||||
- Webview life cycle and handling dipose.
|
||||
|
||||
## Running the example
|
||||
|
||||
- Open this example in VS Code 1.23+
|
||||
- `npm install`
|
||||
- `npm run compile`
|
||||
- `F5` to start debugging
|
||||
|
||||
Run the `Cat Coding: Start cat coding session` to create the webview.
|
||||
BIN
webview-sample/media/cat.gif
Normal file
BIN
webview-sample/media/cat.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.4 MiB |
30
webview-sample/media/main.js
Normal file
30
webview-sample/media/main.js
Normal file
@ -0,0 +1,30 @@
|
||||
// This script will be run within the webview itself
|
||||
// It cannot access VS Code apis directly.
|
||||
|
||||
const counter = document.getElementById('lines-of-code-counter');
|
||||
|
||||
let currentCount = 0;
|
||||
|
||||
setInterval(() => {
|
||||
counter.textContent = currentCount++;
|
||||
|
||||
// Alert the extension when the cat introduces a bug
|
||||
if (Math.random() < Math.min(0.001 * currentCount, 0.05)) {
|
||||
// Send a message back to the extension
|
||||
window.parent.postMessage({
|
||||
command: 'alert', text: '🐛 on line ' + currentCount },
|
||||
'*')
|
||||
}
|
||||
}, 100);
|
||||
|
||||
// Handle messages sent from the extension to the webview inside the webview
|
||||
window.addEventListener('message', event => {
|
||||
const message = event.data; // The json data the extension sent
|
||||
switch (message.command)
|
||||
{
|
||||
case 'refactor':
|
||||
currentCount = Math.ceil(currentCount * 0.5);
|
||||
counter.textContent = currentCount;
|
||||
break;
|
||||
}
|
||||
});
|
||||
2362
webview-sample/package-lock.json
generated
Normal file
2362
webview-sample/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
44
webview-sample/package.json
Normal file
44
webview-sample/package.json
Normal file
@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "cat-coding",
|
||||
"description": "Cat Coding - A Webview API Sample",
|
||||
"version": "0.0.1",
|
||||
"publisher": "ms-vscode",
|
||||
"engines": {
|
||||
"vscode": "^1.23.0"
|
||||
},
|
||||
"categories": [
|
||||
"Other"
|
||||
],
|
||||
"activationEvents": [
|
||||
"onCommand:catCoding.start",
|
||||
"onCommand:catCoding.doRefactor"
|
||||
],
|
||||
"main": "./out/src/extension",
|
||||
"contributes": {
|
||||
"commands": [
|
||||
{
|
||||
"command": "catCoding.start",
|
||||
"title": "Start cat coding session",
|
||||
"category": "Cat Coding"
|
||||
},
|
||||
{
|
||||
"command": "catCoding.doRefactor",
|
||||
"title": "Do some refactoring",
|
||||
"category": "Cat Coding"
|
||||
}
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"vscode:prepublish": "tsc -p ./",
|
||||
"compile": "tsc -watch -p ./",
|
||||
"postinstall": "node ./node_modules/vscode/bin/install"
|
||||
},
|
||||
"dependencies": {
|
||||
"vscode": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/mocha": "^2.2.48",
|
||||
"@types/node": "^9.4.6",
|
||||
"typescript": "^2.7.2"
|
||||
}
|
||||
}
|
||||
156
webview-sample/src/extension.ts
Normal file
156
webview-sample/src/extension.ts
Normal file
@ -0,0 +1,156 @@
|
||||
import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
|
||||
const cats = {
|
||||
'Coding Cat': 'https://media.giphy.com/media/JIX9t2j0ZTN9S/giphy.gif',
|
||||
'Compiling Cat': 'https://media.giphy.com/media/mlvseq9yvZhba/giphy.gif',
|
||||
'Testing Cat': 'https://media.giphy.com/media/3oriO0OEd9QIDdllqo/giphy.gif'
|
||||
};
|
||||
|
||||
export function activate(context: vscode.ExtensionContext) {
|
||||
context.subscriptions.push(vscode.commands.registerCommand('catCoding.start', () => {
|
||||
CatCodingPanel.createOrShow(context.extensionPath);
|
||||
}));
|
||||
|
||||
context.subscriptions.push(vscode.commands.registerCommand('catCoding.doRefactor', () => {
|
||||
if (CatCodingPanel.currentPanel) {
|
||||
CatCodingPanel.currentPanel.doRefactor();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Manages cat coding webview panels
|
||||
*/
|
||||
class CatCodingPanel {
|
||||
/**
|
||||
* Track the currently panel. Only allow a single panel to exist at a time.
|
||||
*/
|
||||
public static currentPanel: CatCodingPanel | undefined;
|
||||
|
||||
private static readonly viewType = 'catCoding';
|
||||
|
||||
private readonly _panel: vscode.WebviewPanel;
|
||||
private readonly _extensionPath: string;
|
||||
private _disposables: vscode.Disposable[] = [];
|
||||
|
||||
public static createOrShow(extensionPath: string) {
|
||||
const column = vscode.window.activeTextEditor ? vscode.window.activeTextEditor.viewColumn : undefined;
|
||||
|
||||
// If we already have a panel, show it.
|
||||
// Otherwise, create a new panel.
|
||||
if (CatCodingPanel.currentPanel) {
|
||||
CatCodingPanel.currentPanel._panel.reveal(column);
|
||||
} else {
|
||||
CatCodingPanel.currentPanel = new CatCodingPanel(extensionPath, column || vscode.ViewColumn.One);
|
||||
}
|
||||
}
|
||||
|
||||
private constructor(extensionPath: string, column: vscode.ViewColumn) {
|
||||
this._extensionPath = extensionPath;
|
||||
|
||||
// Create and show a new webview panel
|
||||
this._panel = vscode.window.createWebviewPanel(CatCodingPanel.viewType, "Cat Coding", column, {
|
||||
// Enable javascript in the webview
|
||||
enableScripts: true,
|
||||
|
||||
// And restric the webview to only loading content from our extension's `media` directory.
|
||||
localResourceRoots: [
|
||||
vscode.Uri.file(path.join(this._extensionPath, 'media'))
|
||||
]
|
||||
});
|
||||
|
||||
// Set the webview's initial html content
|
||||
this._update();
|
||||
|
||||
// Listen for when the panel is disposed
|
||||
// This happens when the user closes the panel or when the panel is closed programatically
|
||||
this._panel.onDidDispose(() => this.dispose(), null, this._disposables);
|
||||
|
||||
// Update the content based on view changes
|
||||
this._panel.onDidChangeViewState(e => {
|
||||
if (this._panel.visible) {
|
||||
this._update()
|
||||
}
|
||||
}, null, this._disposables);
|
||||
|
||||
// Handle messages from the webview
|
||||
this._panel.webview.onDidReceiveMessage(message => {
|
||||
switch (message.command) {
|
||||
case 'alert':
|
||||
vscode.window.showErrorMessage(message.text);
|
||||
return;
|
||||
}
|
||||
}, null, this._disposables);
|
||||
}
|
||||
|
||||
public doRefactor() {
|
||||
// Send a message to the webview webview.
|
||||
// You can send any JSON serializable data.
|
||||
this._panel.webview.postMessage({ command: 'refactor' });
|
||||
}
|
||||
|
||||
public dispose() {
|
||||
CatCodingPanel.currentPanel = undefined;
|
||||
|
||||
// Clean up our resources
|
||||
this._panel.dispose();
|
||||
|
||||
while (this._disposables.length) {
|
||||
const x = this._disposables.pop();
|
||||
if (x) {
|
||||
x.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _update() {
|
||||
// Vary the webview's content based on where it is located in the editor.
|
||||
switch (this._panel.viewColumn) {
|
||||
case vscode.ViewColumn.Two:
|
||||
this._updateForCat('Compiling Cat');
|
||||
return;
|
||||
|
||||
case vscode.ViewColumn.Three:
|
||||
this._updateForCat('Testing Cat');
|
||||
return;
|
||||
|
||||
case vscode.ViewColumn.One:
|
||||
default:
|
||||
this._updateForCat('Coding Cat');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private _updateForCat(catName: keyof typeof cats) {
|
||||
this._panel.title = catName;
|
||||
this._panel.webview.html = this._getHtmlForWebview(cats[catName]);
|
||||
}
|
||||
|
||||
private _getHtmlForWebview(catGif: string) {
|
||||
|
||||
// The main script use
|
||||
const scriptPathOnDisk = vscode.Uri.file(path.join(this._extensionPath, 'media', 'main.js'));
|
||||
|
||||
const scriptUri = scriptPathOnDisk.with({ scheme: 'vscode-resource' });
|
||||
|
||||
return `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
<!-- Use a content security policy to only allow -->
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src vscode-resource: https:; script-src vscode-resource:; style-src vscode-resource:;">
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Cat Coding</title>
|
||||
</head>
|
||||
<body>
|
||||
<img src="${catGif}" width="300" />
|
||||
<h1 id="lines-of-code-counter">0</h1>
|
||||
|
||||
<script src="${scriptUri}"></script>
|
||||
</body>
|
||||
</html>`;
|
||||
}
|
||||
}
|
||||
17
webview-sample/tsconfig.json
Normal file
17
webview-sample/tsconfig.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es6",
|
||||
"outDir": "out",
|
||||
"lib": [
|
||||
"es6"
|
||||
],
|
||||
"sourceMap": true,
|
||||
"rootDir": ".",
|
||||
"strict": true
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
".vscode-test"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user