I am trying to design a VS Code extension using Typescript and Svelte. I want the extension to display a message when a button in the web view is clicked. For this, I have written the following Sidebar.svelte code:
<script lang="ts"> let text='';</script><style> .main-container{ height: 98vh; width: 100%; display: flex; flex-direction: column; } .output-container{ border: 1px solid black; border-radius: 10px; margin-bottom: 10px; padding: 10px; height: 100%; } .input-container{ bottom: 0; width: 100%; } input{ margin-bottom: 10px; }</style><div class="main-container"><div class="output-container"> Your text will appear here: {text}</div><div class="input-container"><input bind:value={text} placeholder="Enter text" /><button on:click={()=>{ tsvscode.postMessage({type:"onInfo",value:"ok"}); }}>Show info</button></div></div>
Here is SidebarProvider.ts that loads the webview and should be receiving the message on button click:
import * as vscode from "vscode";import { getNonce } from "./getNonce";import { apiUrl } from "./constants";export class SidebarProvider implements vscode.WebviewViewProvider { _view?: vscode.WebviewView; _doc?: vscode.TextDocument; constructor(private readonly _extensionUri: vscode.Uri) {} public resolveWebviewView(webviewView: vscode.WebviewView) { this._view = webviewView; webviewView.webview.options = { // Allow scripts in the webview enableScripts: true, localResourceRoots: [this._extensionUri], }; webviewView.webview.html = this._getHtmlForWebview(webviewView.webview); webviewView.webview.onDidReceiveMessage(async (data) => { switch (data.type) { case "onInfo": { if (!data.value) { return; } vscode.window.showInformationMessage(data.value); break; } case "onError": { if (!data.value) { return; } vscode.window.showErrorMessage(data.value); break; } } }); } public revive(panel: vscode.WebviewView) { this._view = panel; } private _getHtmlForWebview(webview: vscode.Webview) { const styleResetUri = webview.asWebviewUri( vscode.Uri.joinPath(this._extensionUri, "media", "reset.css") ); const scriptUri = webview.asWebviewUri( vscode.Uri.joinPath(this._extensionUri, "out", "compiled/sidebar.js") ); const styleMainUri = webview.asWebviewUri( vscode.Uri.joinPath(this._extensionUri, "out", "compiled/bundle.css") ); const styleVSCodeUri = webview.asWebviewUri( vscode.Uri.joinPath(this._extensionUri, "media", "vscode.css") ); // Use a nonce to only allow a specific script to be run. const nonce = getNonce(); return `<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><!-- Use a content security policy to only allow loading images from https or from our extension directory, and only allow scripts that have a specific nonce. --><meta http-equiv="Content-Security-Policy" content="img-src https: data:; style-src 'unsafe-inline' ${webview.cspSource}; script-src 'nonce-${nonce}';"><meta name="viewport" content="width=device-width, initial-scale=1.0"><link href="${styleResetUri}" rel="stylesheet"><link href="${styleVSCodeUri}" rel="stylesheet"><link href="${styleMainUri}" rel="stylesheet"><script nonce ="${getNonce}"> const tsvscode = acquireVsCodeApi(); </script></head><body><script nonce="${nonce}" src="${scriptUri}"></script></body></html>`; }}
To make tsvscode available to the svelte file, I made a globals.d.ts file with the following declaration:
import * as _vscode from "vscode";declare global { const tsvscode:{ postMessage: ({type: string, value:any})=>void; };}
But, I am getting the following error on the webview developer tools console on running this:
Uncaught ReferenceError: tsvscode is not defined at HTMLButtonElement.click_handler (sidebar.js:619:4)click_handler @ sidebar.js:619
and this warning on the console:
Plugin svelte: 'tsvscode' is not defined[0] webviews/components/Sidebar.svelte[0] 35: <input bind:value={text} placeholder="Enter text" />[0] 36: <button on:click={()=>{[0] 37: tsvscode.postMessage({type:"onInfo",value:"ok"});[0] ^[0] 38: }}>Show info</button>[0] 39: </div>
Can you please tell me what could be causing this error and how to resolve it?