Files
AI-Studio/app/MindWork AI Studio/Components/HighlightedMarkdown.cs
T

55 lines
2.3 KiB
C#

using AIStudio.Tools.CodeHighlighting;
using Microsoft.AspNetCore.Components.Rendering;
namespace AIStudio.Components;
/// <summary>
/// Renders Markdown the way MudMarkdown does, and highlights the code blocks of more languages than
/// the library does, such as Python or SQL.
/// </summary>
/// <remarks>
/// MudBlazor.Markdown highlights only a few languages itself, and its highlighter is internal.
/// MudMarkdown renders every code block through RenderCodeBlock, though, and lets us override that.
/// A block in one of the languages of CodeHighlighters becomes a HighlightedCodeBlock; any other block
/// stays as the library renders it. A block which names no language gets the one its code is written in,
/// see CodeLanguageDetector, the same as when it is saved as a file.
/// </remarks>
public class HighlightedMarkdown : MudMarkdown
{
/// <summary>
/// The text of a code block: its lines, each with the line break it came with.
/// </summary>
/// <param name="code">The code block, as Markdig read it.</param>
/// <returns>The text of the block.</returns>
internal static string TextOf(Markdig.Syntax.CodeBlock code) => code.Lines.ToString();
#region Overrides of MudMarkdown
/// <inheritdoc />
protected override void RenderCodeBlock(in RenderTreeBuilder builder, ref int elementIndex, in Markdig.Syntax.CodeBlock code, in string? info)
{
var text = TextOf(code);
var language = CodeLanguageDetector.FenceLanguageOf(info, text);
if (!CodeHighlighters.TryGetRules(language, out _))
{
//
// The copy button of the library confirms in the language of the app, as ours does:
//
this.Styling.CodeBlock.CopyButtonText = CodeBlockCopyButton.ConfirmationText;
base.RenderCodeBlock(builder, ref elementIndex, code, language);
return;
}
//
// Our frames are numbered by their place in this method, as Blazor asks for. The frames of
// the library keep the running count it hands through every render method instead:
//
builder.OpenComponent<HighlightedCodeBlock>(0);
builder.AddComponentParameter(1, nameof(HighlightedCodeBlock.Code), text);
builder.AddComponentParameter(2, nameof(HighlightedCodeBlock.Language), language);
builder.CloseComponent();
}
#endregion
}