From 54b333f2a2785985dec94ab32eaa386131241bd9 Mon Sep 17 00:00:00 2001 From: edgett Date: Sat, 20 Jul 2024 11:03:19 -0400 Subject: [PATCH] Improve markdown rendering performance. (#16) Co-authored-by: Edgett Hilimire --- .../Markdown/MarkdownSection.razor.cs | 84 +++++++++---------- .../Components/Markdown/ModelMarkdown.razor | 2 - PalmHill.Llama/LlamaExtensions.cs | 2 +- 3 files changed, 40 insertions(+), 48 deletions(-) diff --git a/PalmHill.BlazorChat/Client/Components/Markdown/MarkdownSection.razor.cs b/PalmHill.BlazorChat/Client/Components/Markdown/MarkdownSection.razor.cs index 7a91e53..61a29af 100644 --- a/PalmHill.BlazorChat/Client/Components/Markdown/MarkdownSection.razor.cs +++ b/PalmHill.BlazorChat/Client/Components/Markdown/MarkdownSection.razor.cs @@ -8,79 +8,73 @@ namespace PalmHill.BlazorChat.Client.Components.Markdown; public partial class MarkdownSection : FluentComponentBase { private string? _content; - private bool _raiseContentConverted; + private bool _contentChanged; + private static readonly MarkdownPipeline _markdownPipeline = new MarkdownPipelineBuilder().UseAdvancedExtensions().Build(); - /// - /// Gets or sets the Markdown content - /// [Parameter] public string? Content { get; set; } - /// - /// Event callback for when the Markdown content is converted to HTML. - /// + [Parameter] + public EventCallback ContentChanged { get; set; } + [Parameter] public EventCallback OnContentConverted { get; set; } - public string? InternalContent + public MarkupString HtmlContent { get; private set; } + + protected override void OnParametersSet() { - get => _content; - set + if (Content != _content) { - _content = value; - HtmlContent = ConvertToMarkupString(_content); - - - if (OnContentConverted.HasDelegate) - { - OnContentConverted.InvokeAsync(); - } - _raiseContentConverted = true; - StateHasChanged(); + _content = Content; + UpdateHtmlContent(); + _contentChanged = true; } } - public MarkupString HtmlContent { get; private set; } - - - protected override void OnInitialized() + protected override async Task OnAfterRenderAsync(bool firstRender) { - if (Content is null) - throw new ArgumentException("You need to provide either Content or FromAsset parameter"); - - InternalContent = Content; + if (_contentChanged) + { + _contentChanged = false; + await ContentChanged.InvokeAsync(_content); + await OnContentConverted.InvokeAsync(); + } } - protected override async Task OnAfterRenderAsync(bool firstRender) + public void SetContent(string content) { - if (_raiseContentConverted) + if (content != _content) { - _raiseContentConverted = false; - if (OnContentConverted.HasDelegate) - { - await OnContentConverted.InvokeAsync(); - } - + _content = content; + UpdateHtmlContent(); + _contentChanged = true; + StateHasChanged(); } } - public void RefreshContent() + private void UpdateHtmlContent() { - InternalContent = Content; + HtmlContent = ConvertToMarkupString(_content); } - private static MarkupString ConvertToMarkupString(string? value) { - if (!string.IsNullOrWhiteSpace(value)) + if (string.IsNullOrWhiteSpace(value)) { - // Convert markdown string to HTML - string? html = Markdig.Markdown.ToHtml(value, new MarkdownPipelineBuilder().UseAdvancedExtensions().Build()); + return new MarkupString(); + } - // Return sanitized HTML as a MarkupString that Blazor can render + try + { + string html = Markdig.Markdown.ToHtml(value, _markdownPipeline); return new MarkupString(html); } - - return new MarkupString(); + catch (Exception ex) + { + Console.Error.WriteLine($"Error converting Markdown to HTML: {ex.Message}"); + return new MarkupString($"

Error rendering Markdown: {ex.Message}

"); + } } + } \ No newline at end of file diff --git a/PalmHill.BlazorChat/Client/Components/Markdown/ModelMarkdown.razor b/PalmHill.BlazorChat/Client/Components/Markdown/ModelMarkdown.razor index b5df103..98e1848 100644 --- a/PalmHill.BlazorChat/Client/Components/Markdown/ModelMarkdown.razor +++ b/PalmHill.BlazorChat/Client/Components/Markdown/ModelMarkdown.razor @@ -27,8 +27,6 @@ { // Update the markdownToRender variable based on the new response _inferenceMarkdownToRender = WebSocketChatMessage?.Resonse ?? string.Empty; - mdSection?.RefreshContent(); - // Invoke a StateHasChanged to refresh the UI if needed StateHasChanged(); } diff --git a/PalmHill.Llama/LlamaExtensions.cs b/PalmHill.Llama/LlamaExtensions.cs index 329d91f..661dcfd 100644 --- a/PalmHill.Llama/LlamaExtensions.cs +++ b/PalmHill.Llama/LlamaExtensions.cs @@ -157,7 +157,7 @@ public static InjectedModel AddLlamaModel(this IHostApplicationBuilder builder, var modelExsists = System.IO.File.Exists(modelConfig.ModelPath); if (!modelExsists) { - throw new FileNotFoundException($"Model file does not exsist.", modelConfig.ModelPath); + throw new FileNotFoundException($"Model file does not exist.", modelConfig.ModelPath); } //Initlize Llama