mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-10-17 23:38:00 +00:00
Temporarily added MudBlazor.Markdown to the solution
This is necessary due to issue https://github.com/MyNihongo/MudBlazor.Markdown/issues/247 I created a PR as well: https://github.com/MyNihongo/MudBlazor.Markdown/pull/246
This commit is contained in:
57 files changed
+11216
-1
No files matched your search
@@ -0,0 +1,152 @@
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
|
||||
namespace MudBlazor;
|
||||
|
||||
public partial class MudCodeHighlight : MudComponentBase, IDisposable
|
||||
{
|
||||
private ElementReference _ref;
|
||||
private CodeBlockTheme _theme;
|
||||
private IMudMarkdownThemeService? _themeService;
|
||||
private bool _isFirstThemeSet;
|
||||
|
||||
/// <summary>
|
||||
/// Code text to render
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string Text { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Language of the <see cref="Text"/>
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string Language { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Theme of the code block.<br/>
|
||||
/// Browse available themes here: https://highlightjs.org/static/demo/ <br/>
|
||||
/// Default is <see cref="CodeBlockTheme.Default"/>
|
||||
/// </summary>
|
||||
#if NET7_0
|
||||
#pragma warning disable BL0007
|
||||
#endif
|
||||
[Parameter]
|
||||
public CodeBlockTheme Theme
|
||||
{
|
||||
get => _theme;
|
||||
set
|
||||
{
|
||||
if (_theme == value)
|
||||
return;
|
||||
|
||||
_theme = value;
|
||||
Task.Run(SetThemeAsync);
|
||||
}
|
||||
}
|
||||
#if NET7_0
|
||||
#pragma warning restore BL0007
|
||||
#endif
|
||||
|
||||
[Inject]
|
||||
private IJSRuntime Js { get; init; } = default!;
|
||||
|
||||
[Inject]
|
||||
private IServiceProvider? ServiceProvider { get; init; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_themeService != null)
|
||||
_themeService.CodeBlockThemeChanged -= OnCodeBlockThemeChanged;
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected override bool ShouldRender() =>
|
||||
!string.IsNullOrEmpty(Text);
|
||||
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
{
|
||||
var i = 0;
|
||||
|
||||
builder.OpenElement(i++, "div");
|
||||
builder.AddAttribute(i++, "class", "snippet-clipboard-content overflow-auto");
|
||||
|
||||
// Copy button
|
||||
builder.OpenComponent<MudIconButton>(i++);
|
||||
builder.AddAttribute(i++, nameof(MudIconButton.Icon), Icons.Material.Rounded.ContentCopy);
|
||||
builder.AddAttribute(i++, nameof(MudIconButton.Variant), Variant.Filled);
|
||||
builder.AddAttribute(i++, nameof(MudIconButton.Color), Color.Primary);
|
||||
builder.AddAttribute(i++, nameof(MudIconButton.Size), Size.Medium);
|
||||
builder.AddAttribute(i++, nameof(MudIconButton.Class), "snippet-clipboard-copy-icon m-2");
|
||||
builder.AddAttribute(i++, nameof(MudIconButton.OnClick), EventCallback.Factory.Create<MouseEventArgs>(this, CopyTextToClipboardAsync));
|
||||
builder.CloseComponent();
|
||||
|
||||
// Code block
|
||||
builder.OpenElement(i++, "pre");
|
||||
builder.OpenElement(i++, "code");
|
||||
|
||||
if (!string.IsNullOrEmpty(Language))
|
||||
builder.AddAttribute(i++, "class", $"language-{Language}");
|
||||
|
||||
builder.AddElementReferenceCapture(i++, x => _ref = x);
|
||||
builder.AddContent(i++, Text);
|
||||
|
||||
builder.CloseElement();
|
||||
builder.CloseElement();
|
||||
builder.CloseElement();
|
||||
}
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
base.OnInitialized();
|
||||
|
||||
_themeService = ServiceProvider?.GetService<IMudMarkdownThemeService>();
|
||||
|
||||
if (_themeService != null)
|
||||
_themeService.CodeBlockThemeChanged += OnCodeBlockThemeChanged;
|
||||
}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (!firstRender)
|
||||
return;
|
||||
|
||||
await Js.InvokeVoidAsync("highlightCodeElement", _ref)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (!_isFirstThemeSet)
|
||||
{
|
||||
await SetThemeAsync()
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCodeBlockThemeChanged(object? sender, CodeBlockTheme e) =>
|
||||
Theme = e;
|
||||
|
||||
private async Task SetThemeAsync()
|
||||
{
|
||||
var stylesheetPath = Theme.GetStylesheetPath();
|
||||
|
||||
await Js.InvokeVoidAsync("setHighlightStylesheet", stylesheetPath)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
_isFirstThemeSet = true;
|
||||
}
|
||||
|
||||
private async Task CopyTextToClipboardAsync(MouseEventArgs args)
|
||||
{
|
||||
var ok = await Js.InvokeAsync<bool>("copyTextToClipboard", Text)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (ok)
|
||||
return;
|
||||
|
||||
var clipboardService = ServiceProvider?.GetService<IMudMarkdownClipboardService>();
|
||||
|
||||
if (clipboardService != null)
|
||||
{
|
||||
await clipboardService.CopyToClipboardAsync(Text)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
namespace MudBlazor;
|
||||
|
||||
internal sealed class MudLinkButton : MudComponentBase
|
||||
{
|
||||
private string Classname =>
|
||||
new CssBuilder("mud-typography mud-link")
|
||||
.AddClass($"mud-{Color.ToDescriptionString()}-text")
|
||||
.AddClass($"mud-link-underline-{Underline.ToDescriptionString()}")
|
||||
.AddClass($"mud-typography-{Typo.ToDescriptionString()}")
|
||||
.AddClass("mud-link-disabled", IsDisabled)
|
||||
.AddClass(Class)
|
||||
.Build();
|
||||
|
||||
/// <summary>
|
||||
/// The color of the component. It supports the theme colors.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Color Color { get; set; } = Color.Primary;
|
||||
|
||||
/// <summary>
|
||||
/// Typography variant to use.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Typo Typo { get; set; } = Typo.body1;
|
||||
|
||||
/// <summary>
|
||||
/// Controls when the link should have an underline.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Underline Underline { get; set; } = Underline.Hover;
|
||||
|
||||
/// <summary>
|
||||
/// If true, the navlink will be disabled.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool IsDisabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Child content of component.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public RenderFragment? ChildContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Command executed on click
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public ICommand? Command { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Parameter passed to the command
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public object? CommandParameter { get; set; }
|
||||
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
{
|
||||
var i = 0;
|
||||
|
||||
builder.OpenElement(i++, "span");
|
||||
builder.AddAttribute(i++, "class", Classname);
|
||||
builder.AddAttribute(i++, "style", Style);
|
||||
builder.AddAttribute(i++, "onclick", EventCallback.Factory.Create(this, OnClick));
|
||||
builder.AddContent(i++, ChildContent);
|
||||
builder.CloseElement();
|
||||
}
|
||||
|
||||
private void OnClick()
|
||||
{
|
||||
if (IsDisabled)
|
||||
return;
|
||||
|
||||
if (Command?.CanExecute(CommandParameter) ?? false)
|
||||
Command.Execute(CommandParameter);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
namespace MudBlazor;
|
||||
|
||||
/// <summary>
|
||||
/// For some reason MudExpansionPanels eternally tried to dispose all panels, therefore, RenderFragment was called infinitely<br/>
|
||||
/// Created this component in order to bypass that weird behaviour
|
||||
/// </summary>
|
||||
internal sealed class MudMarkdownDetails : ComponentBase
|
||||
{
|
||||
private int _elementIndex;
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment? TitleContent { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment? ChildContent { get; set; }
|
||||
|
||||
private bool IsExpanded { get; set; }
|
||||
|
||||
private string IconClasses => new CssBuilder("mud-expand-panel-icon")
|
||||
.AddClass("mud-transform", IsExpanded)
|
||||
.Build();
|
||||
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
{
|
||||
_elementIndex = 0;
|
||||
|
||||
builder.OpenElement(_elementIndex++, "div");
|
||||
builder.AddAttribute(_elementIndex++, "class", "mud-expand-panel mud-elevation-1 mud-expand-panel-border");
|
||||
|
||||
BuildTitle(builder);
|
||||
BuildContent(builder);
|
||||
|
||||
builder.CloseElement();
|
||||
}
|
||||
|
||||
private void BuildTitle(RenderTreeBuilder builder)
|
||||
{
|
||||
builder.OpenElement(_elementIndex++, "div");
|
||||
builder.AddAttribute(_elementIndex++, "class", "mud-expand-panel-header mud-ripple");
|
||||
builder.AddAttribute(_elementIndex++, "onclick", EventCallback.Factory.Create(this, OnHeaderClick));
|
||||
|
||||
// Text
|
||||
builder.OpenElement(_elementIndex++, "div");
|
||||
builder.AddAttribute(_elementIndex++, "class", "mud-expand-panel-text");
|
||||
builder.AddContent(_elementIndex++, TitleContent);
|
||||
builder.CloseElement();
|
||||
|
||||
// Collapse icon
|
||||
builder.OpenComponent<MudIcon>(_elementIndex++);
|
||||
builder.AddAttribute(_elementIndex++, nameof(MudIcon.Icon), Icons.Material.Filled.ExpandMore);
|
||||
builder.AddAttribute(_elementIndex++, "class", IconClasses);
|
||||
builder.CloseComponent();
|
||||
|
||||
builder.CloseElement();
|
||||
}
|
||||
|
||||
private void BuildContent(RenderTreeBuilder builder)
|
||||
{
|
||||
builder.OpenComponent<MudCollapse>(_elementIndex++);
|
||||
builder.AddAttribute(_elementIndex++, nameof(MudCollapse.Expanded), IsExpanded);
|
||||
|
||||
builder.AddAttribute(_elementIndex++, nameof(MudCollapse.ChildContent), (RenderFragment)(contentBuilder =>
|
||||
{
|
||||
contentBuilder.OpenElement(_elementIndex++, "div");
|
||||
contentBuilder.AddAttribute(_elementIndex++, "class", "mud-expand-panel-content");
|
||||
contentBuilder.AddContent(_elementIndex++, ChildContent);
|
||||
contentBuilder.CloseElement();
|
||||
}));
|
||||
|
||||
builder.CloseComponent();
|
||||
}
|
||||
|
||||
private void OnHeaderClick()
|
||||
{
|
||||
IsExpanded = !IsExpanded;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
namespace MudBlazor;
|
||||
|
||||
internal sealed class MudMathJax : ComponentBase
|
||||
{
|
||||
private const string ScriptId = "mudblazor-markdown-mathjax";
|
||||
|
||||
[Parameter]
|
||||
public string Delimiter { get; set; } = string.Empty;
|
||||
|
||||
[Parameter]
|
||||
public StringSlice Value { get; set; }
|
||||
|
||||
[Inject]
|
||||
private IJSRuntime Js { get; init; } = default!;
|
||||
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
{
|
||||
var elementIndex = 0;
|
||||
|
||||
var delimiter = GetDelimiter(Delimiter);
|
||||
|
||||
builder.AddContent(elementIndex++, delimiter.Start);
|
||||
builder.AddContent(elementIndex++, Value);
|
||||
builder.AddContent(elementIndex, delimiter.End);
|
||||
}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
await Js.InvokeVoidAsync("appendMathJaxScript", ScriptId)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await Js.InvokeVoidAsync("refreshMathJaxScript")
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static MathDelimiter GetDelimiter(in string delimiter) =>
|
||||
delimiter switch
|
||||
{
|
||||
"$" => new MathDelimiter("\\(", "\\)"),
|
||||
"$$" => new MathDelimiter(delimiter),
|
||||
_ => new MathDelimiter(delimiter)
|
||||
};
|
||||
|
||||
private readonly ref struct MathDelimiter
|
||||
{
|
||||
public MathDelimiter(string delimiter)
|
||||
{
|
||||
Start = End = delimiter;
|
||||
}
|
||||
|
||||
public MathDelimiter(string start, string end)
|
||||
{
|
||||
Start = start;
|
||||
End = end;
|
||||
}
|
||||
|
||||
public string Start { get; }
|
||||
|
||||
public string End { get; }
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user