Skip to content

Commit

Permalink
Display infobar for blocked relative image path (#1695)
Browse files Browse the repository at this point in the history
* Updated Parsing extension to show infobar when relative URL isblocked and updated corresponding tests

* Updated Controller to display infobar when html img tag is embedded in markdown
  • Loading branch information
dsrivastavv committed Mar 26, 2020
1 parent 15cefc6 commit c2e219b
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 132 deletions.
186 changes: 86 additions & 100 deletions src/modules/previewpane/MarkDownPreviewHandler/HTMLParsingExtension.cs
Original file line number Diff line number Diff line change
@@ -1,117 +1,103 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.IO;
using Markdig;
using Markdig.Extensions.Figures;
using Markdig.Extensions.Tables;
using Markdig.Renderers;
using Markdig.Renderers.Html;
using Markdig.Syntax;
using Markdig.Syntax.Inlines;

namespace MarkdownPreviewHandler
{
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.IO;
using Markdig;
using Markdig.Extensions.Figures;
using Markdig.Extensions.Tables;
using Markdig.Renderers;
using Markdig.Renderers.Html;
using Markdig.Syntax;
using Markdig.Syntax.Inlines;

namespace MarkdownPreviewHandler
{
/// <summary>
/// Callback if extension blocks external images.
/// </summary>
public delegate void ImagesBlockedCallBack();

/// <summary>
/// Markdig Extension to process html nodes in markdown AST.
/// </summary>
public class HTMLParsingExtension : IMarkdownExtension
{
/// <summary>
/// Markdig Extension to process html nodes in markdown AST.
/// </summary>
public class HTMLParsingExtension : IMarkdownExtension
{
/// <summary>
/// Callback if extension blocks external images.
/// </summary>
private readonly ImagesBlockedCallBack imagesBlockedCallBack;

/// </summary>
private readonly ImagesBlockedCallBack imagesBlockedCallBack;

/// <summary>
/// Initializes a new instance of the <see cref="HTMLParsingExtension"/> class.
/// </summary>
/// <param name="imagesBlockedCallBack">Callback function if image is blocked by extension.</param>
/// <param name="baseUrl">Absolute path of markdown file.</param>
public HTMLParsingExtension(ImagesBlockedCallBack imagesBlockedCallBack, string baseUrl = "")
{
this.imagesBlockedCallBack = imagesBlockedCallBack;
this.BaseUrl = baseUrl;
}
/// <param name="baseUrl">Absolute path of markdown file.</param>
public HTMLParsingExtension(ImagesBlockedCallBack imagesBlockedCallBack, string baseUrl = "")
{
this.imagesBlockedCallBack = imagesBlockedCallBack;
this.BaseUrl = baseUrl;
}

/// <summary>
/// Gets or sets path to directory containing markdown file.
/// </summary>
public string BaseUrl { get; set; }
/// <summary>
/// Gets or sets path to directory containing markdown file.
/// </summary>
public string BaseUrl { get; set; }

/// <inheritdoc/>
public void Setup(MarkdownPipelineBuilder pipeline)
{
// Make sure we don't have a delegate twice
pipeline.DocumentProcessed -= this.PipelineOnDocumentProcessed;
pipeline.DocumentProcessed += this.PipelineOnDocumentProcessed;
}

/// <inheritdoc/>
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
}

/// <inheritdoc/>
public void Setup(MarkdownPipelineBuilder pipeline)
{
// Make sure we don't have a delegate twice
pipeline.DocumentProcessed -= this.PipelineOnDocumentProcessed;
pipeline.DocumentProcessed += this.PipelineOnDocumentProcessed;
}

/// <inheritdoc/>
public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer)
{
}

/// <summary>
/// Process nodes in markdown AST.
/// </summary>
/// <param name="document">Markdown Document.</param>
public void PipelineOnDocumentProcessed(MarkdownDocument document)
{
foreach (var node in document.Descendants())
/// <summary>
/// Process nodes in markdown AST.
/// </summary>
/// <param name="document">Markdown Document.</param>
public void PipelineOnDocumentProcessed(MarkdownDocument document)
{
foreach (var node in document.Descendants())
{
if (node is Block)
{
if (node is Table)
{
node.GetAttributes().AddClass("table table-striped table-bordered");
}
else if (node is QuoteBlock)
{
node.GetAttributes().AddClass("blockquote");
}
else if (node is Figure)
{
node.GetAttributes().AddClass("figure");
}
else if (node is FigureCaption)
{
node.GetAttributes().AddClass("figure-caption");
}
}
else if (node is Inline)
{
if (node is LinkInline link)
{
if (node is Block)
{
if (node is Table)
{
node.GetAttributes().AddClass("table table-striped table-bordered");
}
else if (node is QuoteBlock)
{
node.GetAttributes().AddClass("blockquote");
}
else if (node is Figure)
{
node.GetAttributes().AddClass("figure");
}
else if (node is FigureCaption)
{
node.GetAttributes().AddClass("figure-caption");
}
}
else if (node is Inline)
{
if (node is LinkInline link)
{
if (link.IsImage)
{
link.Url = "#";
link.GetAttributes().AddClass("img-fluid");
}

if (!Uri.TryCreate(link.Url, UriKind.Absolute, out _))
{
link.Url = link.Url.TrimStart('/', '\\');
this.BaseUrl = this.BaseUrl.TrimEnd('/', '\\');
Uri uriLink = new Uri(Path.Combine(this.BaseUrl, link.Url));
link.Url = uriLink.ToString();
}
else
{
if (link.IsImage)
{
link.Url = "#";
this.imagesBlockedCallBack();
}
}
}
}
}
}
}
}
this.imagesBlockedCallBack();
}
}
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using Common;
using Markdig;
Expand Down Expand Up @@ -83,6 +84,12 @@ public override void DoPreview<T>(T dataSource)
string fileText = File.ReadAllText(filePath);
this.extension.BaseUrl = Path.GetDirectoryName(filePath);
Regex rgx = new Regex(@"<[ ]*img.*>");
if (rgx.IsMatch(fileText))
{
this.infoBarDisplayed = true;
}
MarkdownPipeline pipeline = this.pipelineBuilder.Build();
string parsedMarkdown = Markdown.ToHtml(fileText, pipeline);
sb.AppendFormat("{0}{1}{2}", this.htmlHeader, parsedMarkdown, this.htmlFooter);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public void Extension_UpdatesBlockQuotesClass_WhenUsed()
}

[TestMethod]
public void Extension_UpdatesFigureClassAndRelativeUrltoAbsolute_WhenUsed()
public void Extension_UpdatesFigureClassAndBlocksRelativeUrl_WhenUsed()
{
// arrange
String mdString = "![text](a.jpg \"Figure\")";
Expand All @@ -58,37 +58,7 @@ public void Extension_UpdatesFigureClassAndRelativeUrltoAbsolute_WhenUsed()
String html = Markdown.ToHtml(mdString, markdownPipeline);

// Assert
Assert.AreEqual(html, "<p><img src=\"file:///C:/Users/a.jpg\" class=\"img-fluid\" alt=\"text\" title=\"Figure\" /></p>\n");
}

[TestMethod]
public void Extension_CreatesCorrectAbsoluteLinkByTrimmingForwardSlash_WhenUsed()
{
// arrange
String mdString = "![text](\\document\\a.jpg \"Figure\")";
HTMLParsingExtension htmlParsingExtension = new HTMLParsingExtension(() => { }, "C:\\Users\\");
MarkdownPipeline markdownPipeline = BuidPipeline(htmlParsingExtension);

// Act
String html = Markdown.ToHtml(mdString, markdownPipeline);

// Assert
Assert.AreEqual(html, "<p><img src=\"file:///C:/Users/document/a.jpg\" class=\"img-fluid\" alt=\"text\" title=\"Figure\" /></p>\n");
}

[TestMethod]
public void Extension_CreatesCorrectAbsoluteLinkByTrimmingBackwardSlash_WhenUsed()
{
// arrange
String mdString = "![text](/document/a.jpg \"Figure\")";
HTMLParsingExtension htmlParsingExtension = new HTMLParsingExtension(() => { }, "C:/Users/");
MarkdownPipeline markdownPipeline = BuidPipeline(htmlParsingExtension);

// Act
String html = Markdown.ToHtml(mdString, markdownPipeline);

// Assert
Assert.AreEqual(html, "<p><img src=\"file:///C:/Users/document/a.jpg\" class=\"img-fluid\" alt=\"text\" title=\"Figure\" /></p>\n");
Assert.AreEqual(html, "<p><img src=\"#\" class=\"img-fluid\" alt=\"text\" title=\"Figure\" /></p>\n");
}

[TestMethod]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
## Something
<img src="./a.jpg" \>
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,20 @@ public void MarkdownPreviewHandlerControl__AddsInfoBarToFormIfExternalImageLinkP
Assert.IsInstanceOfType(markdownPreviewHandlerControl.Controls[1], typeof(RichTextBox));
}

[TestMethod]
public void MarkdownPreviewHandlerControl__AddsInfoBarToFormIfHTMLImageTagIsPresent_WhenDoPreviewIsCalled()
{
// Arrange
MarkdownPreviewHandlerControl markdownPreviewHandlerControl = new MarkdownPreviewHandlerControl();

// Act
markdownPreviewHandlerControl.DoPreview<string>("HelperFiles/MarkdownWithHTMLImageTag.txt");

// Assert
Assert.AreEqual(markdownPreviewHandlerControl.Controls.Count, 2);
Assert.IsInstanceOfType(markdownPreviewHandlerControl.Controls[1], typeof(RichTextBox));
}

[TestMethod]
public void MarkdownPreviewHandlerControl__DoesNotAddInfoBarToFormIfExternalImageLinkNotPresent_WhenDoPreviewIsCalled()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@
<Content Include="HelperFiles\MarkdownWithExternalImage.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="HelperFiles\MarkdownWithHTMLImageTag.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="HelperFiles\MarkdownWithscript.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
Expand Down

0 comments on commit c2e219b

Please sign in to comment.