如何在VS Code扩展的悬停提供程序中显示本地图片?
问题描述
开发VS Code扩展时,需要在自定义语言awscript的.aws文件中,实现悬停相对路径形式的图片路径(如../images/landscape.png)时,展示工作区内的对应本地图片。当前使用vscode-resource Scheme构建URI,验证路径正确但图片显示破碎图标,不清楚非WebView场景下的正确URI方案。
当前实现的TypeScript代码:
import * as vscode from 'vscode'; import * as path from 'path'; export function activateHoverProvider(context: vscode.ExtensionContext) { const hoverProvider = vscode.languages.registerHoverProvider({ scheme: 'file', language: 'awscript' }, { provideHover(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken) { const wordRange = document.getWordRangeAtPosition(position); if (!wordRange) { return; } const hoveredText = document.getText(wordRange); if (isValidImagePath(hoveredText)) { const documentPath = path.dirname(document.uri.fsPath); const imagePath = path.resolve(documentPath, hoveredText); const uri = vscode.Uri.file(imagePath).with({ scheme: 'vscode-resource' }); const markdown = new vscode.MarkdownString(``); markdown.isTrusted = true; return new vscode.Hover(markdown); } } }); context.subscriptions.push(hoverProvider); } function isValidImagePath(filePath: string): boolean { return filePath.endsWith('.png') || filePath.endsWith('.jpg') || filePath.endsWith('.gif'); }
解决方案
问题出在两个关键点:vscode-resource Scheme已被VS Code弃用,且默认的getWordRangeAtPosition无法正确捕获包含../、目录分隔符的完整图片路径。
1. 替换URI Scheme
VS Code 1.56+版本已废弃vscode-resource,在悬停等非WebView场景下,直接使用file Scheme的URI即可,同时确保MarkdownString的isTrusted属性设为true(允许加载本地资源)。
2. 正确捕获完整图片路径
默认的getWordRangeAtPosition会按VS Code的单词分隔规则截取文本,无法识别包含../、/的相对路径。需要用自定义正则表达式匹配完整的图片路径格式。
修改后的完整代码
import * as vscode from 'vscode'; import * as path from 'path'; import * as fs from 'fs'; export function activateHoverProvider(context: vscode.ExtensionContext) { const hoverProvider = vscode.languages.registerHoverProvider({ scheme: 'file', language: 'awscript' }, { provideHover(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken) { // 用正则匹配包含相对路径的完整图片路径 const pathRegex = /(\.\.\/|\/)?[\w\-\/]+\.(png|jpg|gif)/; const range = document.getWordRangeAtPosition(position, pathRegex); if (!range) { return; } const hoveredText = document.getText(range); if (isValidImagePath(hoveredText)) { const documentDir = path.dirname(document.uri.fsPath); const imageAbsolutePath = path.resolve(documentDir, hoveredText); // 验证图片文件是否存在 if (!fs.existsSync(imageAbsolutePath)) { return new vscode.Hover('图片文件不存在'); } // 构建file Scheme的URI const imageUri = vscode.Uri.file(imageAbsolutePath); const markdown = new vscode.MarkdownString(`})`); // 必须设为true,允许加载本地资源 markdown.isTrusted = true; return new vscode.Hover(markdown); } } }); context.subscriptions.push(hoverProvider); } function isValidImagePath(filePath: string): boolean { return /\.(png|jpg|gif)$/i.test(filePath); }
额外说明
- 正则表达式
/(\.\.\/|\/)?[\w\-\/]+\.(png|jpg|gif)/可匹配以下格式的路径:../images/landscape.png、./icon.jpg、assets/header.gif、logo.png。 - 添加
fs.existsSync检查可避免因路径错误显示破碎图标,同时给用户明确提示。 - 若工作区包含远程文件(如WSL、SSH),需改用
vscode.workspace.fs.stat异步检查文件存在性,避免同步IO阻塞。
内容的提问来源于stack exchange,提问作者vincent
相关产品推荐
相关产品推荐

