microsoft / vscode-webview-ui-toolkit

A component library for building webview-based extensions in Visual Studio Code.
MIT License
2.02k stars 144 forks source link

How to load custom images? #536

Open drriguz opened 10 months ago

drriguz commented 10 months ago

Hi, I'm using toolkit with react+vite. I want to show an image in the webview, like this:

// the user.png is located on webview-ui/src/user.png
import userImg from "../user.png";
...
<img src={userImg} />

However, this does not work, and shows error message:

vscode-webview://1iav15db5tskk3lc073po39q8usqupebm0gshfqarponor92ka9s/assets/user.png:1     GET vscode-webview://1iav15db5tskk3lc073po39q8usqupebm0gshfqarponor92ka9s/assets/user.png net::ERR_ACCESS_DENIED

There's also a similar issue in stackoverflow.

I've tried to add csp rules, and also not work:


<meta http-equiv="Content-Security-Policy" content="default-src 'none';img-src ${webview.cspSource} https:; connect-src https://us-central1-aiplatform.googleapis.com; style-src ${webview.cspSource} 'nonce-${nonce}' ; font-src ${webview.cspSource}; script-src 'unsafe-eval' 'nonce-${nonce}';">

I find a blog says that it's needed to serve the image by a virtual server, and it seems that the css is actually loaded by a virtual https url:

https://file+.vscode-resource.vscode-cdn.net/Users/riguz/Documents/prompt-native/prompt-ide/webview-ui/build/assets/index.css

The uri could be build in extension using getUri:

const stylesUri = getUri(webview, this.context.extensionUri, [
            "webview-ui",
            "build",
            "assets",
            "index.css",
        ]);

However, this is not possible in webview-ui.

Can you suggest us how to use custom images (especially in react framework)?

drriguz commented 10 months ago

I think I figured out a workaround:

first, just use the image like any other normal react project, put the image in webview-ui/src/user.png:

App.css

.user-avatar {
    background-image: url(./user.png);
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
}

After that, the image should be able to display when run npm run start directly inside the webview-ui project. However, it won't work in extension. image

Then, override the css in extension html,

const userImage = getUri(webview, this.context.extensionUri, [
            "webview-ui",
            "build",
            "assets",
            "user.png",
        ]);
    <style nonce="${nonce}">
              .user-avatar {
                background-image: url("${userImage}");
                background-size: contain;
                background-repeat: no-repeat;
                background-position: center;
            }
          </style>

This would make sure that the image could be correctly displayed in extension. image

drriguz commented 10 months ago

Accroding to GPT, another way it to get the image uri via message. However, this is unnecessary complex, and need to maintain a state to store the uri.