blog3000/Blog3000/Client/Shared/MarkdownViewer.razor.cs

121 lines
3.4 KiB
C#

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<MarkupString> FromMarkdown(string markdown)
{
var mdPipeline = new MarkdownPipelineBuilder().UseAdvancedExtensions().Build();
var mdoc = Markdig.Markdown.Parse(markdown, mdPipeline);
Dictionary<string, string> imgGeysByUrls = null;
if (ImgRefRewriter != null)
{
System.Diagnostics.Debug.WriteLine($"*** Rewriter active");
imgGeysByUrls ??= new Dictionary<string, string>();
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);
}
}
}