VS Code 扩展开发如何保持用户视觉体验一致

简介: 本文介绍如何在 VS Code 插件的 webview 中加载本地的资源文件,并如何使用 VS Code 自身的 UI 来实现用户视觉体验的一致。

背景

最近想做一个 VS Code 的插件用来简便我使用 VS Code 来编辑 Markdown 博客的体验,在设计插件的过程中,因为需要在 webview 界面中使用到下拉框,想到为了节省插件大小,并考虑到用户体验一致性,故需要使用 VS Code 自身的 UI 库。

寻找蛛丝马迹:获取安装目录

因为我不清楚到底要如何去做,就先自己探索。先打开了 VS Code 的开发人员工具进行元素审查,看到是 workbench.desktop.main.css 这个文件。

审查html

<link rel="stylesheet" type="text/css" data-name="vs/workbench/workbench.desktop.main" href="vscode-file://vscode-app/d:/Program%20Files/Microsoft%20VS%20Code/resources/app/out/vs/workbench/workbench.desktop.main.css">

根据以上信息我们可以得知,其实际目录需要特殊的魔法去获取,因为引用的路径是安装目录的位置,不同电脑的肯定是不一样的。

这里我们就前往 VS Code 的仓库去扒拉源代码,最后虽然根据 vs/workbench/workbench.desktop.main 找到了一些线索,但是不堪大用啊,还是需要找到安装目录才行。几番折腾发现源码里获取软件版本信息 product.json 的方法,原来里面有环境变量啊。

const product = JSON.parse(fs.readFileSync(path.join(env.appRoot, 'product.json'), { encoding: 'utf-8' }));

那么,若在插件中要想获取到安装目录,直接使用下面的方法就好了:

const vscodeInstallPath = vscode.env.appRoot;

插件中获取

一波三折,并不顺利

首先在插件中,我们获取 html 内容后替换占位符信息如下:

const appRoot = vscode.Uri.file(vscode.env.appRoot);
this.view.webview.html = html.replace(/\[insert-vscode-root\]/g,`${appRoot}`);

通过替换 webview 页面的引用信息,实现动态的 workbench.desktop.main.css 资源引用后,不出意外的出了意外了:

出错

虽然看起来引用的路径是没有什么问题了,但是结果却令人糟心啊:

Not allowed to load local resource

期间我尝试了 vscode-file://vscode-app/ 协议直接拼接 appRootasWebviewUri 但是并没有成功获取到,都是网络错误。

asWebviewUri 看起来似乎有些靠谱,观察开发人员工具中的网络请求似乎很多都是这样类似的连接:

https://file+.vscode-resource.vscode-cdn.net/c%3A/Users/sangsq/AppData/Local/Programs/Microsoft%20VS%20Code/resources/app/out/vs/workbench/workbench.desktop.main.css

不过这个 net::ERR_ABORTED 401 却是让人高兴不起来,貌似权限问题。此时凌晨已至,夜寒露重,故搜索了一遍 Stackoverflow 后,便提了一个问题关机睡觉。

继续探索

在没有获得到答案后,还是要靠自己。认真看看官方文档,在扩展指南的加载本地内容中得到了一些答案。

出于安全原因,Webview 运行在隔离的环境中,无法直接访问本地资源。想从扩展加载图片、样式表或其他资源,或者从用户当前的工作区加载任何内容,必须使用 Webview.asWebviewUri 来转换为一个特殊的 URI 来使用。

前面已经提到我用过了 Webview.asWebviewUri 但是还有一些其他限制,默认情况下 Webview 只能访问以下位置的资源:

  • 扩展程序的安装目录
  • 用户当前的活动工作区

使用 WebviewOptions.localResourceRoots 可以允许访问其他本地资源。

createWebviewPanel 方法的第4个参数 webviewOptions.localResourceRoots 是一个只读数组,默认情况就是之前提的扩展程序的安装目录和用户当前的活动工作区。当然你也可以设置成空数组,这样就禁止访问任何本地资源。

这样在创建时稍作修改就可以了。

this.view = vscode.window.createWebviewPanel(
    "blogPreview",
    "Markdown Blog Preview",
    vscode.ViewColumn.Two,
    {
        enableScripts: true,
        localResourceRoots: [
            vscode.Uri.file(path.join(context.extensionPath, "html")),
            vscode.Uri.file(vscode.env.appRoot)
        ]
    }
);

在 html 内容中替换指定的字符串:

<link rel="stylesheet" type="text/css" href="[insert-vscode-css]">
const cssfile = vscode.Uri.file(path.join(vscode.env.appRoot,"out/vs/workbench/workbench.desktop.main.css"));
const cssurl = this.view.webview.asWebviewUri(cssfile);
this.view.webview.html = html.replace(/\[insert-vscode-css\]/g,`${cssurl}`);

最后成果

在 workbench 目录中还存在有其他可用资源,这里仅对 select 的效果做个演示。

未使用 VS Code 的 UI 时:

未使用

使用 VS Code 的 UI 时:

使用

另外在 Webview 的 html 显示中会被加入当前的样式和主题信息,需要自行进行适配调整。

<html lang="zh-CN" style="--vscode-font-family:………略,太多了………">
<body role="document" class="vscode-dark" data-vscode-theme-kind="vscode-dark" data-vscode-theme-name="Dark+ (default dark)" data-vscode-theme-id="Default Dark+">
相关文章
|
6月前
|
Web App开发 JavaScript iOS开发
[√]使用vscode开发油猴Tampermonkey脚本
[√]使用vscode开发油猴Tampermonkey脚本
307 0
|
6月前
|
IDE Go 开发工具
Go开发IDE全览:GoLand vs VSCode全面解析
Go开发IDE全览:GoLand vs VSCode全面解析
211 0
|
5月前
|
移动开发 前端开发 JavaScript
VSCode设置类似Webstorm那样可以用本地局域网IP地址访问自己开发的测试项目,vs code 前端如何以服务器模式打开?
VSCode设置类似Webstorm那样可以用本地局域网IP地址访问自己开发的测试项目,vs code 前端如何以服务器模式打开?
VSCode设置类似Webstorm那样可以用本地局域网IP地址访问自己开发的测试项目,vs code 前端如何以服务器模式打开?
|
6月前
Visual Studio Code开发常用的工具栏选项,查看源码技巧以及【vscode常用的快捷键】
Visual Studio Code开发常用的工具栏选项,查看源码技巧以及【vscode常用的快捷键】
259 0
|
2天前
|
API 开发工具 C++
【专栏:工具与技巧篇】使用代码编辑器(VS Code/Sublime Text)提升开发效率
【4月更文挑战第30天】在VS Code与Sublime Text两大流行代码编辑器中,开发者可借助其高效特性提升编程效率。VS Code拥有丰富的插件生态、内置Git集成、强大的调试工具、智能提示和多文件导航功能。Sublime Text则以其轻量级、快速响应、多光标编辑及自定义构建系统见长。学习编辑器的键盘快捷键、自定义配置、使用内置终端以及键绑定和宏,将助开发者进一步提高开发效率。选择适合自己的编辑器并不断适应新技术是提升开发工作流的关键。
|
9天前
|
Web App开发 XML 传感器
VSCode 开发Vue必备插件
VSCode 开发Vue必备插件
10 0
|
25天前
|
JavaScript
VSCode 开发 Vue 语法提示
VSCode 开发 Vue 语法提示
|
7月前
|
网络协议 Ubuntu Linux
VSCode使用Remote SSH远程连接Linux服务器【远程开发】
VSCode使用Remote SSH远程连接Linux服务器【远程开发】
|
2月前
|
Linux 网络安全 开发工具
嵌入式中利用VS Code 远程开发原理
嵌入式中利用VS Code 远程开发原理
30 0
|
2月前
|
网络协议 Ubuntu Linux
「远程开发」VSCode使用SSH远程linux服务器 - 公网远程连接
「远程开发」VSCode使用SSH远程linux服务器 - 公网远程连接
140 0