@@ -6,18 +6,51 @@ import { getWorkspacePath } from "../../utils/path"
66import { t } from "../../i18n"
77
88export async function openImage ( dataUriOrPath : string , options ?: { values ?: { action ?: string } } ) {
9- // Check if it's a file path (absolute or relative)
9+ // Minimal handling for VS Code webview CDN URLs:
10+ // Example: https://file+.vscode-resource.vscode-cdn.net/file/<absolute_path_to_image>
11+ try {
12+ const u = vscode . Uri . parse ( dataUriOrPath )
13+ if ( u . scheme === "https" && u . authority . includes ( "vscode-cdn.net" ) ) {
14+ let fsPath = decodeURIComponent ( u . path || "" )
15+ // Strip the leading "/file/" prefix if present
16+ if ( fsPath . startsWith ( "/file/" ) ) {
17+ fsPath = fsPath . slice ( "/file/" . length )
18+ }
19+
20+ fsPath = path . normalize ( fsPath )
21+ if ( fsPath ) {
22+ const fileUri = vscode . Uri . file ( fsPath )
23+ await vscode . commands . executeCommand ( "vscode.open" , fileUri )
24+ return
25+ }
26+ }
27+ } catch {
28+ // fall through
29+ }
30+
31+ // Handle file:// URIs directly
32+ if ( dataUriOrPath . startsWith ( "file://" ) ) {
33+ try {
34+ const fileUri = vscode . Uri . parse ( dataUriOrPath )
35+
36+ await vscode . commands . executeCommand ( "vscode.open" , fileUri )
37+ } catch ( error ) {
38+ vscode . window . showErrorMessage ( t ( "common:errors.error_opening_image" , { error } ) )
39+ }
40+ return
41+ }
42+
43+ // Fallback: treat plain strings (absolute or relative) as file paths
1044 const isFilePath =
1145 ! dataUriOrPath . startsWith ( "data:" ) &&
1246 ! dataUriOrPath . startsWith ( "http:" ) &&
1347 ! dataUriOrPath . startsWith ( "https:" ) &&
1448 ! dataUriOrPath . startsWith ( "vscode-resource:" ) &&
15- ! dataUriOrPath . startsWith ( "file+.vscode-resource" )
49+ ! dataUriOrPath . startsWith ( "file+.vscode-resource" ) &&
50+ ! dataUriOrPath . startsWith ( "vscode-webview-resource:" )
1651
1752 if ( isFilePath ) {
18- // Handle file path - open directly in VSCode
1953 try {
20- // Resolve the path relative to workspace if needed
2154 let filePath = dataUriOrPath
2255 if ( ! path . isAbsolute ( filePath ) ) {
2356 const workspacePath = getWorkspacePath ( )
@@ -28,62 +61,57 @@ export async function openImage(dataUriOrPath: string, options?: { values?: { ac
2861
2962 const fileUri = vscode . Uri . file ( filePath )
3063
31- // Check if this is a copy action
3264 if ( options ?. values ?. action === "copy" ) {
3365 await vscode . env . clipboard . writeText ( filePath )
3466 vscode . window . showInformationMessage ( t ( "common:info.path_copied_to_clipboard" ) )
3567 return
3668 }
3769
38- // Open the image file directly
3970 await vscode . commands . executeCommand ( "vscode.open" , fileUri )
4071 } catch ( error ) {
4172 vscode . window . showErrorMessage ( t ( "common:errors.error_opening_image" , { error } ) )
4273 }
4374 return
4475 }
4576
77+ // Finally, handle base64 data URIs explicitly
4678 const matches = dataUriOrPath . match ( / ^ d a t a : i m a g e \/ ( [ a - z A - Z ] + ) ; b a s e 6 4 , ( .+ ) $ / )
4779 if ( ! matches ) {
48- vscode . window . showErrorMessage ( t ( "common:errors.invalid_data_uri" ) )
80+ // Do not show an "invalid data URI" error for non-data URIs; try opening as a generic URI
81+ try {
82+ const generic = vscode . Uri . parse ( dataUriOrPath )
83+ await vscode . commands . executeCommand ( "vscode.open" , generic )
84+ } catch {
85+ vscode . window . showErrorMessage ( t ( "common:errors.invalid_data_uri" ) )
86+ }
4987 return
5088 }
89+
5190 const [ , format , base64Data ] = matches
5291 const imageBuffer = Buffer . from ( base64Data , "base64" )
5392
54- // Default behavior: open the image
5593 const tempFilePath = path . join ( os . tmpdir ( ) , `temp_image_${ Date . now ( ) } .${ format } ` )
5694 try {
5795 await vscode . workspace . fs . writeFile ( vscode . Uri . file ( tempFilePath ) , imageBuffer )
58- // Check if this is a copy action
96+
5997 if ( options ?. values ?. action === "copy" ) {
6098 try {
61- // Read the image file
6299 const imageData = await vscode . workspace . fs . readFile ( vscode . Uri . file ( tempFilePath ) )
63-
64- // Convert to base64 for clipboard
65100 const base64Image = Buffer . from ( imageData ) . toString ( "base64" )
66101 const dataUri = `data:image/${ format } ;base64,${ base64Image } `
67-
68- // Use vscode.env.clipboard to copy the data URI
69- // Note: VSCode doesn't support copying binary image data directly to clipboard
70- // So we copy the data URI which can be pasted in many applications
71102 await vscode . env . clipboard . writeText ( dataUri )
72-
73103 vscode . window . showInformationMessage ( t ( "common:info.image_copied_to_clipboard" ) )
74104 } catch ( error ) {
75105 const errorMessage = error instanceof Error ? error . message : String ( error )
76106 vscode . window . showErrorMessage ( t ( "common:errors.error_copying_image" , { errorMessage } ) )
77107 } finally {
78- // Clean up temp file
79108 try {
80109 await vscode . workspace . fs . delete ( vscode . Uri . file ( tempFilePath ) )
81- } catch {
82- // Ignore cleanup errors
83- }
110+ } catch { }
84111 }
85112 return
86113 }
114+
87115 await vscode . commands . executeCommand ( "vscode.open" , vscode . Uri . file ( tempFilePath ) )
88116 } catch ( error ) {
89117 vscode . window . showErrorMessage ( t ( "common:errors.error_opening_image" , { error } ) )
0 commit comments