// 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 { /// /// Callback if extension blocks external images. /// public delegate void ImagesBlockedCallBack(); /// /// Markdig Extension to process html nodes in markdown AST. /// public class HTMLParsingExtension : IMarkdownExtension { /// /// Callback if extension blocks external images. /// private readonly ImagesBlockedCallBack imagesBlockedCallBack; /// /// Initializes a new instance of the class. /// /// Callback function if image is blocked by extension. /// Absolute path of markdown file. public HTMLParsingExtension(ImagesBlockedCallBack imagesBlockedCallBack, string baseUrl = "") { this.imagesBlockedCallBack = imagesBlockedCallBack; this.BaseUrl = baseUrl; } /// /// Gets or sets path to directory containing markdown file. /// public string BaseUrl { get; set; } /// public void Setup(MarkdownPipelineBuilder pipeline) { // Make sure we don't have a delegate twice pipeline.DocumentProcessed -= this.PipelineOnDocumentProcessed; pipeline.DocumentProcessed += this.PipelineOnDocumentProcessed; } /// public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer) { } /// /// Process nodes in markdown AST. /// /// Markdown Document. 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 (link.IsImage) { 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(); } } } } } } } }