using Ganss.XSS; using Markdig; using Markdig.Syntax; using Microsoft.AspNetCore.Components; using Blog3000.Shared; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.Http; using System.Threading.Tasks; namespace Blog3000.Client.Shared { public partial class MarkdownViewer: IDisposable { public delegate string ImgRefRewriterDelegate(string imgKey, string currentUrl); [Parameter] public string Markdown { get { return _markdown; } set { _markdown = value; MarkdownChanged?.Invoke(this, EventArgs.Empty); } } private string _markdown; [Parameter] public ImgRefRewriterDelegate ImgRefRewriter{ get; set; } [Inject] private IHtmlSanitizer htmlSanitizer { get; set; } private MarkupString HtmlContent { get; set; } private event EventHandler MarkdownChanged; public void Dispose() { MarkdownChanged -= MarkdownViewer_MarkdownChanged; } protected override async Task OnInitializedAsync() { await Task.Run(() => { }); HtmlContent = await FromMarkdown(Markdown); MarkdownChanged += MarkdownViewer_MarkdownChanged; } private async void MarkdownViewer_MarkdownChanged(object sender, EventArgs e) { HtmlContent = await FromMarkdown(Markdown); StateHasChanged(); } private async Task FromMarkdown(string markdown) { var mdPipeline = new MarkdownPipelineBuilder().UseAdvancedExtensions().Build(); var mdoc = Markdig.Markdown.Parse(markdown, mdPipeline); Dictionary imgGeysByUrls = null; if (ImgRefRewriter != null) { System.Diagnostics.Debug.WriteLine($"*** Rewriter active"); imgGeysByUrls ??= new Dictionary(); foreach (var r in mdoc.GetLinkReferenceDefinitions().Links) { System.Diagnostics.Debug.WriteLine($"Found {r.Key} => {r.Value.Url}"); if (r.Value != null && r.Value.Url != null) { imgGeysByUrls.Add(r.Value.Url, r.Key); } } } //var html = Markdig.Markdown.ToHtml(markdown, mdPipeline); var writer = new StringWriter(); var renderer = new Markdig.Renderers.HtmlRenderer(writer); if (ImgRefRewriter != null) { renderer.LinkRewriter += (a) => { string imgKey; if (imgGeysByUrls.TryGetValue(a, out imgKey)) { return ImgRefRewriter(imgKey, a); } return a; }; } mdPipeline.Setup(renderer); renderer.Render(mdoc); var html = writer.ToString(); //System.Diagnostics.Debug.WriteLine(html); html = htmlSanitizer.Sanitize(html); return new MarkupString(html); } } }