Add Markdown editor component

This commit is contained in:
Daniel J. Summers 2020-12-26 23:33:03 -05:00
parent 4ba5426068
commit 1e474395a9
4 changed files with 111 additions and 3 deletions

View File

@ -69,7 +69,7 @@ else if (profileForm != null)
<div class="col">
<div class="form-group">
<label for="bio">Professional Biography</label>
<InputTextArea id="bio" @bind-Value="@profileForm.Biography" class="form-control" />
<MarkdownEditor Id="bio" @bind-Text="@profileForm.Biography" />
<ValidationMessage For="@(() => profileForm.Biography)" />
</div>
</div>
@ -77,12 +77,13 @@ else if (profileForm != null)
<div class="form-row">
<div class="col">
<label for="experience">Experience</label>
<InputTextArea id="experience" @bind-Value="@profileForm.Experience" class="form-control" />
<MarkdownEditor Id="experience" @bind-Text="@profileForm.Experience" />
</div>
</div>
<div class="form-row">
<div class="col">
<button type="submit">Save</button>
<br>
<button type="submit" class="btn btn-outline-primary">Save</button>
</div>
</div>
</EditForm>

View File

@ -0,0 +1,15 @@
<nav class="nav nav-pills">
<a href="#" class="nav-link @MarkdownClass" @onclick="ShowMarkdown" @onclick:preventDefault>Markdown</a>
<a href="#" class="nav-link @PreviewClass" @onclick="ShowPreview" @onclick:preventDefault>Preview</a>
</nav>
@if (_showPreview)
{
<section class="preview">
@PreviewText
</section>
}
else
{
<textarea id="@Id" @bind="@PlainText" @bind:event="oninput" class="form-control" rows="10">
</textarea>
}

View File

@ -0,0 +1,88 @@
using Markdig;
using Microsoft.AspNetCore.Components;
namespace JobsJobsJobs.Client.Shared
{
/// <summary>
/// Code-behind for the Markdown Editor component
/// </summary>
public partial class MarkdownEditor : ComponentBase
{
/// <summary>
/// Pipeline with most extensions enabled
/// </summary>
private readonly MarkdownPipeline _pipeline = new MarkdownPipelineBuilder()
.UseSmartyPants().UseAdvancedExtensions().Build();
/// <summary>
/// Whether the preview should be shown
/// </summary>
private bool _showPreview = false;
/// <summary>
/// Backing field for the plain-text representation of this document
/// </summary>
private string _text = "";
/// <summary>
/// The plain-text (Markdown source)
/// </summary>
private string PlainText {
get => _text;
set
{
_text = value;
TextChanged.InvokeAsync(_text).ConfigureAwait(false).GetAwaiter().GetResult();
}
}
/// <summary>
/// The rendered HTML
/// </summary>
private MarkupString PreviewText => (MarkupString)Markdown.ToHtml(_text, _pipeline);
/// <summary>
/// CSS class for the "Markdown" tab (active if preview not shown)
/// </summary>
private string MarkdownClass => _showPreview ? "" : "active";
/// <summary>
/// CSS class for the "Preview" tab (active if preview shown)
/// </summary>
private string PreviewClass => _showPreview ? "active" : "";
/// <summary>
/// The ID used for the textarea; allows for a label to be assigned
/// </summary>
[Parameter]
public string Id { get; set; } = "";
/// <summary>
/// The text value of the Markdown
/// </summary>
[Parameter]
public string Text { get; set; } = "";
/// <summary>
/// Event fired when the text is changed
/// </summary>
[Parameter]
public EventCallback<string> TextChanged { get; set; }
protected override void OnInitialized()
{
base.OnInitialized();
_text = Text;
}
/// <summary>
/// Show the Markdown editor
/// </summary>
private void ShowMarkdown() => _showPreview = false;
/// <summary>
/// Show the Markdown preview
/// </summary>
private void ShowPreview() => _showPreview = true;
}
}

View File

@ -0,0 +1,4 @@
section.preview {
border: solid 1px darkgray;
border-radius: 2rem;
}