using Ganss.Xss; using Markdig; using Markdig.Syntax; namespace XFESystem.Documents; /// The website's MarkdownService pipeline, independent of ASP.NET and host file access. public sealed class MarkdownRenderer { private readonly MarkdownPipeline _pipeline = new MarkdownPipelineBuilder() .UseAdvancedExtensions() .UseAutoIdentifiers() .Build(); public string RenderHtml(string? markdown) { if (string.IsNullOrEmpty(markdown)) return string.Empty; // A sanitizer per call avoids sharing its mutable parser across concurrent document previews. var sanitizer = new HtmlSanitizer(); sanitizer.AllowedTags.Remove("button"); sanitizer.AllowedTags.Remove("script"); sanitizer.AllowedTags.Remove("css"); sanitizer.AllowedAttributes.Add("id"); sanitizer.AllowedAttributes.Add("class"); sanitizer.AllowedAttributes.Remove("script"); return sanitizer.Sanitize(Markdown.ToHtml(markdown, _pipeline)); } public MarkdownDocument Parse(string? markdown) => Markdown.Parse(markdown ?? string.Empty, _pipeline); }