159 lines
6.3 KiB
Plaintext
159 lines
6.3 KiB
Plaintext
@implements IDisposable
|
|
@rendermode InteractiveServer
|
|
@using Wave.Utilities
|
|
|
|
@inject IStringLocalizer<AdvancedMarkdownEditor> Localizer
|
|
|
|
<section class="grid grid-cols-1 lg:grid-cols-2 gap-x-8 gap-y-4">
|
|
<div class="flex">
|
|
<div class="join join-vertical min-h-96 h-full w-full">
|
|
<Toolbar>
|
|
<ToolbarSection>
|
|
<ToolbarButton onclick="window.insertBeforeSelection('# ', true);"
|
|
title="@Localizer["Tools_H1_Tooltip"]">
|
|
<strong>@Localizer["Tools_H1_Label"]</strong>
|
|
</ToolbarButton>
|
|
<ToolbarButton onclick="window.insertBeforeSelection('## ', true);"
|
|
title="@Localizer["Tools_H2_Tooltip"]">
|
|
<strong>@Localizer["Tools_H2_Label"]</strong>
|
|
</ToolbarButton>
|
|
<ToolbarButton onclick="window.insertBeforeSelection('### ', true);"
|
|
title="@Localizer["Tools_H3_Tooltip"]">
|
|
<strong>@Localizer["Tools_H3_Label"]</strong>
|
|
</ToolbarButton>
|
|
<ToolbarButton onclick="window.insertBeforeSelection('#### ', true);"
|
|
title="@Localizer["Tools_H4_Tooltip"]">
|
|
@Localizer["Tools_H4_Label"]
|
|
</ToolbarButton>
|
|
</ToolbarSection>
|
|
<ToolbarSection>
|
|
<ToolbarButton onclick="window.insertBeforeAndAfterSelection('**');"
|
|
title="@Localizer["Tools_Bold_Tooltip"]">
|
|
<strong>B</strong>
|
|
</ToolbarButton>
|
|
<ToolbarButton onclick="window.insertBeforeAndAfterSelection('*')"
|
|
title="@Localizer["Tools_Italic_Tooltip"]">
|
|
<em>I</em>
|
|
</ToolbarButton>
|
|
<ToolbarButton onclick="window.insertBeforeAndAfterSelection('++')"
|
|
title="@Localizer["Tools_Underline_Tooltip"]">
|
|
<u>U</u>
|
|
</ToolbarButton>
|
|
<ToolbarButton onclick="window.insertBeforeAndAfterSelection('~~')"
|
|
title="@Localizer["Tools_StrikeThrough_Tooltip"]">
|
|
<del>@Localizer["Tools_StrikeThrough_Label"]</del>
|
|
</ToolbarButton>
|
|
<ToolbarButton onclick="window.insertBeforeAndAfterSelection('==')"
|
|
title="@Localizer["Tools_Mark_Tooltip"]">
|
|
<mark>@Localizer["Tools_Mark_Label"]</mark>
|
|
</ToolbarButton>
|
|
<ToolbarButton onclick="window.insertBeforeSelection('> ', true)"
|
|
title="@Localizer["Tools_Cite_Tooltip"]">
|
|
| <em>@Localizer["Tools_Cite_Label"]</em>
|
|
</ToolbarButton>
|
|
</ToolbarSection>
|
|
<ToolbarSection>
|
|
<ToolbarButton onclick="window.insertBeforeSelection('1. ', true)">
|
|
1.
|
|
</ToolbarButton>
|
|
<ToolbarButton onclick="window.insertBeforeSelection('a. ', true)">
|
|
a.
|
|
</ToolbarButton>
|
|
<ToolbarButton onclick="window.insertBeforeSelection('A. ', true)">
|
|
A.
|
|
</ToolbarButton>
|
|
<ToolbarButton onclick="window.insertBeforeSelection('i. ', true)">
|
|
i.
|
|
</ToolbarButton>
|
|
<ToolbarButton onclick="window.insertBeforeSelection('I. ', true)">
|
|
I.
|
|
</ToolbarButton>
|
|
</ToolbarSection>
|
|
<ToolbarSection>
|
|
<ToolbarButton onclick="window.insertBeforeAndAfterSelection('`')"
|
|
title="@Localizer["Tools_CodeLine_Tooltip"]">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-4 h-4">
|
|
<path fill-rule="evenodd" d="M14.447 3.026a.75.75 0 0 1 .527.921l-4.5 16.5a.75.75 0 0 1-1.448-.394l4.5-16.5a.75.75 0 0 1 .921-.527ZM16.72 6.22a.75.75 0 0 1 1.06 0l5.25 5.25a.75.75 0 0 1 0 1.06l-5.25 5.25a.75.75 0 1 1-1.06-1.06L21.44 12l-4.72-4.72a.75.75 0 0 1 0-1.06Zm-9.44 0a.75.75 0 0 1 0 1.06L2.56 12l4.72 4.72a.75.75 0 0 1-1.06 1.06L.97 12.53a.75.75 0 0 1 0-1.06l5.25-5.25a.75.75 0 0 1 1.06 0Z" clip-rule="evenodd" />
|
|
</svg>
|
|
</ToolbarButton>
|
|
<ToolbarButton onclick="window.insertBeforeAndAfterSelection('\n```\n')"
|
|
title="@Localizer["Tools_CodeBlock_Tooltip"]">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-4 h-4">
|
|
<path fill-rule="evenodd" d="M3 6a3 3 0 0 1 3-3h12a3 3 0 0 1 3 3v12a3 3 0 0 1-3 3H6a3 3 0 0 1-3-3V6Zm14.25 6a.75.75 0 0 1-.22.53l-2.25 2.25a.75.75 0 1 1-1.06-1.06L15.44 12l-1.72-1.72a.75.75 0 1 1 1.06-1.06l2.25 2.25c.141.14.22.331.22.53Zm-10.28-.53a.75.75 0 0 0 0 1.06l2.25 2.25a.75.75 0 1 0 1.06-1.06L8.56 12l1.72-1.72a.75.75 0 1 0-1.06-1.06l-2.25 2.25Z" clip-rule="evenodd" />
|
|
</svg>
|
|
</ToolbarButton>
|
|
</ToolbarSection>
|
|
</Toolbar>
|
|
@ChildContent
|
|
</div>
|
|
</div>
|
|
<div class="bg-base-200 p-2">
|
|
@if (!string.IsNullOrWhiteSpace(Title)) {
|
|
<h2 class="text-2xl lg:text-4xl font-bold mb-6 hyphens-auto">@Title</h2>
|
|
}
|
|
@if (!string.IsNullOrWhiteSpace(Markdown)) {
|
|
<div class="prose prose-neutral max-w-none hyphens-auto text-justify">
|
|
@HtmlPreview
|
|
</div>
|
|
} else {
|
|
<div class="flex flex-col gap-4">
|
|
<div class="skeleton h-4 w-full"></div>
|
|
<div class="skeleton h-4 w-full"></div>
|
|
<div class="skeleton h-32 w-full"></div>
|
|
<div class="skeleton h-4 w-full"></div>
|
|
<div class="skeleton h-4 w-full"></div>
|
|
<div class="skeleton h-4 w-full"></div>
|
|
</div>
|
|
}
|
|
</div>
|
|
</section>
|
|
|
|
<SectionContent SectionName="scripts">
|
|
</SectionContent>
|
|
|
|
@code {
|
|
[Parameter]
|
|
public required Func<string?> MarkdownCallback { get; set; }
|
|
[Parameter]
|
|
public string? Title { get; set; }
|
|
[Parameter]
|
|
public required RenderFragment ChildContent { get; set; }
|
|
|
|
private string? Markdown { get; set; }
|
|
private MarkupString HtmlPreview { get; set; } = new();
|
|
|
|
private CancellationTokenSource? Token { get; set; }
|
|
private Timer? Timer { get; set; }
|
|
|
|
protected override void OnInitialized() {
|
|
Timer = new Timer(_ => {
|
|
UpdateHtml();
|
|
}, null, TimeSpan.FromMilliseconds(250), TimeSpan.FromSeconds(1));
|
|
}
|
|
|
|
private void UpdateHtml() {
|
|
try {
|
|
string? markdown = MarkdownCallback.Invoke();
|
|
if (string.IsNullOrWhiteSpace(markdown)) return;
|
|
|
|
Token?.Cancel();
|
|
Token = new CancellationTokenSource();
|
|
|
|
string html = MarkdownUtilities.Parse(markdown);
|
|
Markdown = markdown;
|
|
HtmlPreview = new MarkupString(html);
|
|
InvokeAsync(StateHasChanged);
|
|
} catch (Exception ex) {
|
|
Console.Error.WriteLine(ex);
|
|
} finally {
|
|
Token = null;
|
|
}
|
|
}
|
|
|
|
public void Dispose() {
|
|
Timer?.Dispose();
|
|
Timer = null;
|
|
}
|
|
|
|
}
|