前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >VS Code 扩展开发如何保持用户视觉体验一致

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

作者头像
桑榆肖物
发布2023-01-03 17:22:52
2.1K0
发布2023-01-03 17:22:52
举报
文章被收录于专栏:桑榆肖物桑榆肖物

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

背景

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

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

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

审查html

代码语言:javascript
复制
<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 的方法,原来里面有环境变量啊。

代码语言:javascript
复制
const product = JSON.parse(fs.readFileSync(path.join(env.appRoot, 'product.json'), { encoding: 'utf-8' }));

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

代码语言:javascript
复制
const vscodeInstallPath = vscode.env.appRoot;

插件中获取

一波三折,并不顺利

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

代码语言:javascript
复制
const appRoot = vscode.Uri.file(vscode.env.appRoot);
this.view.webview.html = html.replace(/\[insert-vscode-root\]/g,`${appRoot}`);

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

出错

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

代码语言:javascript
复制
Not allowed to load local resource

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

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

代码语言:javascript
复制
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 后,便提了一个问题关机睡觉。

继续探索

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

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

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

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

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

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

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

代码语言:javascript
复制
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 内容中替换指定的字符串:

代码语言:javascript
复制
<link rel="stylesheet" type="text/css" href="[insert-vscode-css]">
代码语言:javascript
复制
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 显示中会被加入当前的样式和主题信息,需要自行进行适配调整。

代码语言:javascript
复制
<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+">

References

[1] 加载本地内容: https://code.visualstudio.com/api/extension-guides/webview#loading-local-content

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-12-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 桑榆肖物 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 寻找蛛丝马迹:获取安装目录
  • 一波三折,并不顺利
  • 继续探索
  • 最后成果
    • References
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档