A Blazor wrapper around EasyMDE with:
- Two-way binding (
@bind-Value) - Strongly-typed EasyMDE options (no
object-typed option surface) - Strongly-typed
Toolbar,Status, andReadOnlyunions - Optional key interception (fast-path in JavaScript; only calls .NET for registered keys)
- Optional ability to block specific keys (e.g., prevent
Enterfrom inserting a newline)
- Keep the C# API strongly typed (simple primitives/enums/unions)
- Keep the JavaScript surface minimal
- Support Blazor Server and Blazor WebAssembly
- Avoid editor churn and event loops (programmatic
Valueupdates don’t re-trigger input handlers)
In your Blazor application, load the bundled EasyMDE stylesheet and script files:
<link rel="stylesheet" href="_content/EasyMDE.Blazor/lib/easymde/easymde.min.css" />
<script src="_content/EasyMDE.Blazor/lib/easymde/easymde.min.js"></script>@using EasyMDE.Blazor
<EasyMdeEditor @bind-Value="Markdown" />
@code {
private string? Markdown = "# Hello";
}<EasyMdeEditor @bind-Value="Markdown" Options="Options" />
@code {
private string? Markdown;
private readonly EasyMdeOptions Options = new()
{
Placeholder = "Write markdown...",
MinHeight = "300px",
Toolbar = EasyMdeToolbar.Custom(new ToolbarItem[]
{
ToolbarItem.BuiltIn(ToolbarButton.Bold),
ToolbarItem.BuiltIn(ToolbarButton.Italic),
ToolbarItem.Separator,
ToolbarItem.BuiltIn(ToolbarButton.Preview),
ToolbarItem.BuiltIn(ToolbarButton.Fullscreen),
}),
Status = EasyMdeStatus.Custom(new StatusItem[]
{
StatusItem.BuiltIn(StatusElement.Lines),
StatusItem.BuiltIn(StatusElement.Words),
StatusItem.BuiltIn(StatusElement.Cursor),
}),
ReadOnly = EasyMdeReadOnly.Disabled
};
}ReadOnly = EasyMdeReadOnly.Disabled; // editable (readOnly: false)
ReadOnly = EasyMdeReadOnly.Enabled; // readOnly: true
ReadOnly = EasyMdeReadOnly.NoCursor; // readOnly: "nocursor"To avoid sending every keystroke to .NET (especially on Blazor Server), the wrapper supports pre-registered key filters.
- JS listens to
keydown - If the key is not registered, nothing happens (fast-path)
- If the key is registered:
BlockInJs = trueblocks synchronously with no .NET callNotifyDotNet = truecalls.NET(no blocking guarantee, just notification)AskDotNet = truecalls.NETfor an allow/deny decision (see notes below)
<EasyMdeEditor @bind-Value="Markdown"
InterceptKeys="Keys" />
@code {
private string? Markdown;
private readonly EasyMdeKeyRegistration[] Keys =
[
new()
{
Key = "Enter",
BlockInJs = true
}
];
}<EasyMdeEditor @bind-Value="Markdown"
InterceptKeys="Keys"
OnKey="HandleKey" />
@code {
private string? Markdown;
private readonly EasyMdeKeyRegistration[] Keys =
[
new() { Key = "s", Ctrl = true, NotifyDotNet = true }
];
private ValueTask<bool> HandleKey(EasyMdeKeyEvent e)
{
if (e.Ctrl && (e.Key is "s" or "S"))
{
// trigger save
}
return ValueTask.FromResult(true);
}
}MIT