Add webview sample

This commit is contained in:
Matt Bierner
2018-04-24 15:07:32 -07:00
parent f235a144c6
commit c8cbd892ac
10 changed files with 2693 additions and 0 deletions

View File

@ -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
View 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
View 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
View 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.

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 MiB

View 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

File diff suppressed because it is too large Load Diff

View 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"
}
}

View 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>`;
}
}

View File

@ -0,0 +1,17 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"outDir": "out",
"lib": [
"es6"
],
"sourceMap": true,
"rootDir": ".",
"strict": true
},
"exclude": [
"node_modules",
".vscode-test"
]
}