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:
tsommer committed 2024-05-03 22:59:46 +02:00
1 parent 6f9326a827
commit c84184e5d1
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; }
}
}