using System.Diagnostics; using System.Text; using Markdig; using OliverBooth.Common.Data.Web; using OliverBooth.Common.Services; using OliverBooth.Extensions.Markdig.Markdown.Template; namespace OliverBooth.Markdown.Template; /// /// Represents a custom template renderer which renders the {{Snippet}} template. /// internal sealed class CodeSnippetTemplateRenderer : CustomTemplateRenderer { private readonly ICodeSnippetService _codeSnippetService; private readonly Lazy _markdownPipeline; private readonly IProgrammingLanguageService _programmingLanguageService; /// /// Initializes a new instance of the class. /// /// The service provider. public CodeSnippetTemplateRenderer(IServiceProvider serviceProvider) : base(serviceProvider) { // lazily evaluate to avoid circular dependency problem causing tremendous stack overflow _markdownPipeline = new Lazy(serviceProvider.GetRequiredService); _codeSnippetService = serviceProvider.GetRequiredService(); _programmingLanguageService = serviceProvider.GetRequiredService(); } /// public override string Render(TemplateInline template) { Debug.Assert(template.Name == "Snippet"); Trace.Assert(template.Name == "Snippet"); IReadOnlyList argumentList = template.ArgumentList; if (argumentList.Count < 1) { return DefaultRender(template); } if (!int.TryParse(argumentList[0], out int snippetId)) { return DefaultRender(template); } var identifier = Guid.NewGuid(); var snippets = new List(); IReadOnlyList languages = argumentList.Count > 1 ? argumentList[1].Split(';') : _codeSnippetService.GetLanguagesForSnippet(snippetId); foreach (string language in languages) { if (_codeSnippetService.TryGetCodeSnippetForLanguage(snippetId, language, out ICodeSnippet? snippet)) { snippets.Add(snippet); } } if (snippets.Count == 1) { ICodeSnippet snippet = snippets[0]; return RenderHtml(snippet); } var builder = new StringBuilder(); builder.AppendLine($""" "); builder.AppendLine($"""
"""); for (var index = 0; index < snippets.Count; index++) { string classList = ""; if (index == 0) { classList = " show active"; } var snippet = snippets[index]; string html = RenderHtml(snippet); builder.AppendLine($"""
"""); builder.AppendLine(html); builder.AppendLine("
"); } builder.AppendLine("
"); return builder.ToString(); } private string RenderHtml(ICodeSnippet snippet) { return Markdig.Markdown.ToHtml($"```{snippet.Language}\n{snippet.Content}\n```", _markdownPipeline.Value); } private static string DefaultRender(TemplateInline template) { return template.ArgumentList.Count == 0 ? $"{{{{{template.Name}}}}}" : $"{{{{{template.Name}|{string.Join('|', template.ArgumentList)}}}}}"; } }