MarkdownViewerPlusPlus
MarkdownViewerPlusPlus copied to clipboard
Local images are not shown
Hi,
Local images are not being shown inside the plugin
In the .md file I'm reading, two images are present in the code:


Both images are in the same directory of readme.md file, no need to absolute path or subdirectories Both images are PNG with 1192 x 836 resolution
When the .md is exported to html, the images appear correctly
<img src="01.png" alt="01" />
<img src="02.png" alt="02" />
use 
See the issues #30 and #23
The file:///
trick isn't a good idea unless you wanna restrict yourself and your md files to MarkdownViewer++. Forget about "Export to HTML".
I started using Visual Studio Code + markdownlint extension, because of this limitation.
I think that the issue is because of..
InvalidOperationException This instance represents a relative URI, and this property is valid only for absolute URIs.
https://docs.microsoft.com/en-us/dotnet/api/system.uri.scheme?view=net-6.0
.. and..
InvalidOperationException This instance represents a relative URI, and this property is valid only for absolute URIs.
https://docs.microsoft.com/en-us/dotnet/api/system.uri.localpath?view=net-6.0#system-uri-localpath
I haven't tested the following diff, but it seems that it should address all issues I think..
In MarkdownViewerRenderer.cs..
//Get some file information
string src = imageLoadEvent.Src;
Uri uri = new Uri(src);
string extension = Path.GetExtension(src);
+ if(uri.IsAbsoluteUri)
+ {
- //Check if local file or web resource
+ //Check if local file from absolute path or web resource
switch (uri.Scheme.ToLowerInvariant())
{
case "file":
//In case of a local file -> Try to load it directly
imageLoadEvent.Handled = true; //Tell the event it was handled, so no error border is drawn
ThreadPool.QueueUserWorkItem(state => LoadImageFromFile(src, imageLoadEvent));
break;
case "http":
case "https":
//For web resources check extension and parameter, to fetch from e.g. "badge" creating sources
if ((extension != null && extension.Equals(".svg", StringComparison.OrdinalIgnoreCase))
|| uri.ToString().Contains("svg="))
{
//In case of a web resource file -> Load async
using (WebClient webClient = new WebClient())
{
imageLoadEvent.Handled = true; //Tell the event it was handled, so no error border is drawn
webClient.DownloadDataCompleted += (downloadSender, downloadEvent) => { OnDownloadDataCompleted(downloadEvent, imageLoadEvent); };
webClient.DownloadDataAsync(uri);
}
}
break;
}
+}
+else
+{
+ //Local file from relative path -> Try to load it directly
+ imageLoadEvent.Handled = true; //Tell the event it was handled, so no error border is drawn
+ ThreadPool.QueueUserWorkItem(state => LoadImageFromFile(@"file:///" + this.FileInfo.FileDirectory + "/" + src, imageLoadEvent));
+}
.. and..
/// <summary>
///
/// </summary>
/// <param name="src"></param>
/// <param name="imageLoadEvent"></param>
protected void LoadImageFromFile(string src, HtmlImageLoadEventArgs imageLoadEvent)
{
try
{
Uri uri = new Uri(src);
//Try to load the file as Image from file
//Remove the scheme first
string srcWithoutScheme = src;
int i = srcWithoutScheme.IndexOf(':');
if (i > 0) srcWithoutScheme = srcWithoutScheme.Substring(i + 1).TrimStart('/');
- //If not absolute, add the current file path
- if (!Path.IsPathRooted(srcWithoutScheme))
- {
- uri = new Uri(@"file:///" + this.FileInfo.FileDirectory + "/" + srcWithoutScheme);
- }
//For SVG images: Convert to Bitmap
string extension = Path.GetExtension(src);
if (extension != null && extension.Equals(".svg", StringComparison.OrdinalIgnoreCase))
{
ConvertSvgToBitmap(SvgDocument.Open<SvgDocument>(uri.LocalPath), imageLoadEvent);
}
else
{
//Load uri, 8, 1
imageLoadEvent.Callback((Bitmap)Image.FromFile(uri.LocalPath, true));
}
}
catch { } //Not able to handle, refer back to orginal process
}
In my opinion NppMarkdownPanel is much better then MarkdownViewer++ (even javascript can be used). My comment on Github: (A Notepad++ Plugin to view a Markdown) - goto NppMarkdownPanel -> https://github.com/andrzejQ/NppMarkdownPanel
@andrzejQ for viewing markdown, there doesn't seem to be any major difference between MarkdownViewerPlusPlus and https://github.com/mohzy83/NppMarkdownPanel. Though NppMarkdownPanel doesn't have the issue that images don't load.
Hi, I can confirm that if I use a local image with relative path, such as:

I see that the NppMarkdownPanel plugin shows the image correctly, but MarkdownViewerPlusPlus failed to show the image.
Any idea to fix this issue in this plugin? Thanks.