Reputation:
I'm trying to create a vscode extension and the goal is to display a webview with a extern html and css.
Loading and setting the html works but unfortunately the css won't get load.
Creating webview,loading html and setting :
var resultPanel = vscode.window.createWebviewPanel("test", "TestWebView", vscode.ViewColumn.One, {});
fs.readFile(path.join(context.extensionPath,'src','languageMenue.html'),(err,data) => {
if(err) {console.error(err)}
resultPanel.webview.html = data;
});
This works, inside the html the css get loaded like that :
<meta charset="UTF-8">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="theme.css">
The css is in the same folder as the html (inside the src folder of my the extension project)
What am I missing? Why the css won't get load?
Upvotes: 11
Views: 14438
Reputation: 33
I was struggling to figure things out so here's a more verbose solution using registerWebviewViewProvider which is setup slightly differently.
I want to point out that localResourceRoots should contain directories not specific files (Took me awhile to figure that out).
html:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="{{pathCSS}}">
</head>
<body>
typescript:
export function activate(context: vscode.ExtensionContext) {
const provider = new customViewProvider(context.extensionPath);
}
class customViewProvider implements vscode.WebviewViewProvider {
public static readonly viewType = "decomp_webview";
private _view?: vscode.WebviewView;
private extensionUri: string;
public webview: vscode.Webview | undefined;
constructor(
private readonly _extensionUri: string,
) {
this.extensionUri = _extensionUri;
}
public resolveWebviewView(
webviewView: vscode.WebviewView,
context: vscode.WebviewViewResolveContext,
_token: vscode.CancellationToken,
) {
this._view = webviewView;
console.log("PATH: "+this._extensionUri);
webviewView.webview.options = {
enableScripts: true,
localResourceRoots: [
vscode.Uri.file(path.join(this.extensionUri, "/src")),
]
};
let html = fs.readFileSync(vscode.Uri.file(path.join(this.extensionUri, "src/ui.html")).with({scheme: 'vscode-resource'}).fsPath, "utf-8");
const pathToCSS = vscode.Uri.file(path.join(this.extensionUri, 'src/ui.css'));
html = html.replace("{{pathCSS}}", String(webviewView.webview.asWebviewUri(pathCSS)));
console.log(html);
const updateWebview = () => {
webviewView.webview.html = html
};
setInterval(updateWebview, 1000);
Upvotes: 0
Reputation: 99
You have to replace the css filename in your html file with styleUri.toString()
, just binding with {{styleSrc}}
does not work.
const htmlPathOnDisk = vscode.Uri.file(path.join(this._extensionPath, '/res/html/index.html'));
var html = fs.readFileSync(htmlPathOnDisk.path).toString();
const stylePathOnDisk = vscode.Uri.file(path.join(this._extensionPath, '/res/css/styles.css'));
const styleUri = webview.asWebviewUri(stylePathOnDisk);
html = html.replace('filename_of_css_file_in_your_html_file.css', styleUri.toString());
// continue for any other resources, e.g. scripts
webview.html = html
Upvotes: 0
Reputation: 1228
To make this work you have to specify the absolute path where the css
file is stored.
i.e.
<link rel="stylesheet" type="text/css" href="/path/to/dir/of/theme.css">
Since vscode
suggests to use secure content policy
, the way to achieve dynamic loading of the path is like this:
<link rel="stylesheet" type="text/css" href="{{styleSrc}}">
where {{styleSrc}}
is binded as:
const styleSrc = vscode.Uri.file(path.join(vscode.context.extensionPath, '/path/to/dir/of/theme.css')).with({ scheme: 'vscode-resource' })
or with the asWebviewUri
API as:
const onDiskPath = vscode.Uri.file(path.join(vscode.context.extensionPath, '/path/to/dir/of/theme.css'))
const styleSrc = panel.webview.asWebviewUri(onDiskPath)
where panel
is the one created with vscode.window.createWebviewPanel(...)
For more info see: https://code.visualstudio.com/api/extension-guides/webview#loading-local-content
Upvotes: 5
Reputation: 2109
Please read this Controlling access to local resources
And note about localResourceRoots
as below code:
const panel = vscode.window.createWebviewPanel(
'catCoding',
'Cat Coding',
vscode.ViewColumn.One,
{
// Only allow the webview to access resources in our extension's media directory
localResourceRoots: [vscode.Uri.file(path.join(context.extensionPath, 'media'))]
}
);
You can edit the line to:
localResourceRoots: [vscode.Uri.file(path.join(context.extensionPath, 'your/relative/location/here/in/your/extension/path'))]
Upvotes: 10
Reputation: 1466
Read through the vscode webview guide: https://code.visualstudio.com/api/extension-guides/webview
Specifically pay close attention to the "Loading local content" section: https://code.visualstudio.com/api/extension-guides/webview#loading-local-content
There are special rules for how to load external content for security reasons.
Upvotes: 1