Code Monkey home page Code Monkey logo

blazormarkdowneditor's Introduction

Blazor Markdown Editor

This is a Markdown Editor component for Blazor WebAssembly and Blazor Server with .NET6. The component is based on EasyMDE version 2.18.0 to create the editor. For more documentation and help this component, visit the post I created here.

markdown-editor-blazor-logo

Try Markdown Editor online (upload is not enabled)

Usage

Add the Editor to your _Imports.razor

@using PSC.Blazor.Components.MarkdownEditor 
@using PSC.Blazor.Components.MarkdownEditor.EventsArgs

Then, in your index.html or host.html add those lines:

<link href="/_content/PSC.Blazor.Components.MarkdownEditor/css/easymde.min.css" rel="stylesheet" />

<script src="/_content/PSC.Blazor.Components.MarkdownEditor/js/easymde.min.js"></script>
<script src="/_content/PSC.Blazor.Components.MarkdownEditor/js/markdownEditor.js"></script>

Remember that jQuery is also required. The component cointains the EasyMDE script version 2.18.0. Obviously, you can add this script in your project but if you use the script in the component, you are sure it works fine and all functionalities are tested.

Add MarkdownEditor in a page

In a Razor page, we can add the component with these lines

<div class="col-md-12">
    <MarkdownEditor @bind-Value="@markdownValue" 
                    ValueHTMLChanged="@OnMarkdownValueHTMLChanged" />

    <hr />

    <h3>Result</h3>
    @((MarkupString)markdownHtml)
</div>

@code {
    string markdownValue = "# Markdown Editor\nThis is a test";
    string markdownHtml;

    Task OnMarkdownValueChanged(string value)
    {
        return Task.CompletedTask;
    }

    Task OnMarkdownValueHTMLChanged(string value)
    {
        markdownHtml = value;
        return Task.CompletedTask;
    }
}

The main different between value and ValueHTMLChanged is that Value return the text written in the editor as a string whereas ValueHTMLChanged returns the rendered HTML code for the text. The ValueHTMLChanged includes the code for displaying mermaid graphs in a SVG tag.

The result is a nice Markdown Editor like in the following screenshot. This is a screenshot from the demo in this repository.

markdown-editor-example

Add a custom toolbar

In your Markdown Editor add the following code

<MarkdownEditor @bind-Value="@markdownValue"
                ValueHTMLChanged="@OnMarkdownValueHTMLChanged"
                SpellChecker="false"
                CustomButtonClicked="@OnCustomButtonClicked">
    <Toolbar>
        <MarkdownToolbarButton Action="MarkdownAction.Bold" Icon="fa fa-bolt" Title="Bold" />
        <MarkdownToolbarButton Separator Name="Custom button" 
                               Value="@("Hello from your custom Toolbar Button")" 
                               Icon="fa fa-star" 
                               Title="A Custom Button" />
        <MarkdownToolbarButton Separator Name="https://github.com/erossini/BlazorMarkdownEditor" 
                               Icon="fa fab fa-github" Title="A Custom Link" />
    </Toolbar>
</MarkdownEditor>

@code {
    // omitted code...

    Task OnCustomButtonClicked(MarkdownButtonEventArgs eventArgs)
    {
        Console.WriteLine("OnCustomButtonClicked -> " + eventArgs.Value);
        buttonText += "OnCustomButtonClicked -> " + eventArgs.Value + "<br />";

        return Task.CompletedTask;
    }
}

In the tag MarkdownEditor, you add the new tab Toolbar that contains one or more MarkdownToolbarButton.

Each MarkdownToolbarButton can have one of the default Action (see table below) or a custom value for example a link to a website. If you want to display before a MarkdownToolbarButton a vertical line, add the property Separator in the MarkdownToolbarButton.

Change the content after the first init

In same cases, you want to refresh the content of the Markdown Editor after the first init, for example because your application has to read the value from an API and it takes time. For that, you have to add a ref to the MarkdownEditor and then use it to call SetValueAsync property, as in the following code

<MarkdownEditor @bind-Value="@markdownValue"
                ValueHTMLChanged="@OnMarkdownValueHTMLChanged"
                SpellChecker="false" @ref="Markdown1" />

@code {
    MarkdownEditor Markdown1;

    // omitted code...

    async Task ChangeText()
    {
        markdownValue = "Test!";
        await Markdown1.SetValueAsync(markdownValue);
    }
}

Add Mermaid render

In order to add more functionaties to the component, it includes the version of mermaid.js 10.2.1 that allows to add impressive diagrams and chart in the Markdown component like

  • Flowchart
  • Sequence Diagram
  • Class Diagram
  • State Diagram
  • Entity Relationship Diagram
  • User Journey
  • Gantt
  • Pie Chart
  • Quadrant Chart
  • Requirement Diagram
  • Gitgraph (Git) Diagram
  • C4C Diagram (Context) Diagram
  • Mindmaps
  • Timeline

To add this functionality to the Markdown Editor, it is enough to add in the index.html this script

<script src="/_content/PSC.Blazor.Components.MarkdownEditor/js/mermaid.min.js"></script>

The script will check if this library is called. If it is added to the page, the Markdown Editor automatically will add a button in the toolbar to insert the tag for mermaid. That tag is

    ```mermaid
    ```

An example of the mermaid graphs

A Sequence diagram is an interaction diagram that shows how processes operate with one another and in what order.

sequenceDiagram
    Alice->>John: Hello John, how are you?
    John-->>Alice: Great!
    Alice-)John: See you later!

Sequence diagram

A Gantt chart is useful for tracking the amount of time it would take before a project is finished, but it can also be used to graphically represent "non-working days", with a few tweaks.

gantt
    title A Gantt Diagram
    dateFormat  YYYY-MM-DD
    section Section
    A task           :a1, 2014-01-01, 30d
    Another task     :after a1  , 20d
    section Another
    Task in sec      :2014-01-12  , 12d
    another task      : 24d

Gantt chart

An entity–relationship model (or ER model) describes interrelated things of interest in a specific domain of knowledge. A basic ER model is composed of entity types (which classify the things of interest) and specifies relationships that can exist between entities (instances of those entity types).

erDiagram
    CUSTOMER ||--o{ ORDER : places
    ORDER ||--|{ LINE-ITEM : contains
    CUSTOMER }|..|{ DELIVERY-ADDRESS : uses

entity–relationship model

Add Highlight.js

This script is not included in the component but the component can detect if Highlight.js is loaded. In this case, the Markdown Editor renders also the code in one of the supported languages.

To enable this function, add the script to your project and then in the index.html add the following lines

<link rel="stylesheet" href="/path/to/styles/default.min.css">
<script src="/path/to/highlight.min.js"></script>

Known issue using Mermaid and Highlight.js

If both libraries are loaded in the index.html, the mermaid render will not work.

Alerts

In the Markdown, there are some missing tags to display some useful information on the page like a highlight note, a tip, a warning or an attention message. So, I added them in this Markdown Editor. An example of the result of this implementation is in the following screenshot.

Alerts

To add the message, click on the icons in the toolbar in the editor or add those commands:

Command Color Description
```att Red Display an attention message
```note Azure Add a note in the documentt
```tip Green Shows a tip message
```warn Orange This is a warning message

In the Markdown Editor component, there is a CSS for the them called alert.css and you can add it to the index.html with this line

<link href="/_content/PSC.Blazor.Components.MarkdownEditor/css/alert.css" rel="stylesheet" />

Documentation

The Markdown Editor for Blazor has a estensive collection of properties to map all the functionalities in the JavaScript version. In this repository, there are 2 projects:

  • MarkdownEditorDemo is a Blazor Web Assembly project that contains 2 pages: Index.razor where I show how to use the component with the basic functions and Upload.razor that shows how to cope with the image upload. To test the upload, the project MarkdownEditorDemo.Api must run
  • MarkdownEditorDemo.Api this is an ASP.NET Core WebApi (.NET6) how to implement a proper API for uploading images. For more details, I wrote a post about Uploading image with .NET.

Properties

Name Description Type Default
AutoSaveEnabled Gets or sets the setting for the auto save. Saves the text that's being written and will load it back in the future. It will forget the text when the form it's contained in is submitted. Recommended to choose a unique ID for the Markdown Editor. bool false
AutoSaveId Gets or sets the automatic save identifier. You must set a unique string identifier so that the component can autosave. Something that separates this from other instances of the component elsewhere on your website. string Default value
AutoSaveDelay Delay between saves, in milliseconds. Defaults to 10000 (10s). int 10000 (10s)
AutoSaveSubmitDelay Delay before assuming that submit of the form failed and saving the text, in milliseconds. int 5000 (5s)
AutoSaveText Text for autosave string Autosaved:
AutoSaveTimeFormatLocale Set the format for the datetime to display. For more info, see the JavaScript documentation DateTimeFormat instances string en-US
AutoSaveTimeFormatYear Set the format for the year string numeric
AutoSaveTimeFormatMonth Set the format for the month string long
AutoSaveTimeFormatDay Set the format for the day string 2-digit
AutoSaveTimeFormatHour Set the format for the hour string 2-digit
AutoSaveTimeFormatMinute Set the format for the minute string 2-digit
AutoDownloadFontAwesome If set to true, force downloads Font Awesome (used for icons). If set to false, prevents downloading. bool? null
CustomButtonClicked Occurs after the custom toolbar button is clicked. EventCallback
Direction rtl or ltr. Changes text direction to support right-to-left languages. Defaults to ltr. string ltr
ErrorMessages Errors displayed to the user, using the errorCallback option, where image_name, image_size and image_max_size will be replaced by their respective values, that can be used for customization or internationalization. MarkdownErrorMessages
HideIcons An array of icon names to hide. Can be used to hide specific icons shown by default without completely customizing the toolbar. string[] 'side-by-side', 'fullscreen'
ImageAccept A comma-separated list of mime-types used to check image type before upload (note: never trust client, always check file types at server-side). Defaults to image/png, image/jpeg, image/jpg, image.gif. string image/png, image/jpeg, image/jpg, image.gif
ImageCSRFToken CSRF token to include with AJAX call to upload image. For instance, used with Django backend. string
ImageMaxSize Maximum image size in bytes, checked before upload (note: never trust client, always check image size at server-side). Defaults to 1024 * 1024 * 2 (2Mb). long 1024 * 1024 * 2 (2Mb)
ImagePathAbsolute If set to true, will treat imageUrl from imageUploadFunction and filePath returned from imageUploadEndpoint as an absolute rather than relative path, i.e. not prepend window.location.origin to it. string
ImageTexts Texts displayed to the user (mainly on the status bar) for the import image feature, where image_name, image_size and image_max_size will be replaced by their respective values, that can be used for customization or internationalization. MarkdownImageTexts null
ImageUploadAuthenticationSchema If an authentication for the API is required, assign to this property the schema to use. Bearer is the common one. string empty
ImageUploadAuthenticationToken If an authentication for the API is required, assign to this property the token string empty
LineNumbers If set to true, enables line numbers in the editor. bool false
LineWrapping If set to false, disable line wrapping. Defaults to true. bool false
MaxHeight Sets fixed height for the composition area. minHeight option will be ignored. Should be a string containing a valid CSS value like "500px". Defaults to undefined. string
MaxUploadImageMessageSize Gets or sets the max message size when uploading the file. long 20 * 1024
MinHeight Sets the minimum height for the composition area, before it starts auto-growing. Should be a string containing a valid CSS value like "500px". Defaults to "300px". string 300px
NativeSpellChecker Enable (true) or disable (false) the spell check in the editor bool True
Placeholder If set, displays a custom placeholder message. string null
SegmentFetchTimeout Gets or sets the Segment Fetch Timeout when uploading the file. TimeSpan 1 min
ShowIcons An array of icon names to show. Can be used to show specific icons hidden by default without completely customizing the toolbar. string[] 'code', 'table'
SpellChecker Enable (true) or disable (false) the spell check in the editor bool True
TabSize If set, customize the tab size. Defaults to 2. int 2
Theme Override the theme. Defaults to easymde. string easymde
Toolbar [Optional] Gets or sets the content of the toolbar. RenderFragment
ToolbarTips If set to false, disable toolbar button tips. Defaults to true. bool true
UploadImage If set to true, enables the image upload functionality, which can be triggered by drag-drop, copy-paste and through the browse-file window (opened when the user clicks on the upload-image icon). Defaults to false. bool false
Value Gets or sets the markdown value. string null
ValueHTML Gets the HTML from the markdown value. string null

Events

Name Description Type
ErrorCallback A callback function used to define how to display an error message. Defaults to (errorMessage) => alert(errorMessage). Func<string, Task>
ImageUploadChanged Occurs every time the selected image has changed. Func<FileChangedEventArgs, Task>
ImageUploadEnded Occurs when an individual image upload has ended. Func<FileEndedEventArgs, Task>
ImageUploadEndpoint The endpoint where the images data will be sent, via an asynchronous POST request. The server is supposed to save this image, and return a json response. string
ImageUploadProgressed Notifies the progress of image being written to the destination stream. Func<FileProgressedEventArgs, Task>
ImageUploadStarted Occurs when an individual image upload has started. Func<FileStartedEventArgs, Task>
ValueChanged An event that occurs after the markdown value has changed. EventCallback
ValueHTMLChanged An event that occurs after the markdown value has changed and the new HTML code is available. EventCallback

Upload file

The Markdown Editor for Blazor can take care of uploading a file and add the relative Markdown code in the editor. For that, the property UploadImage has to set to true. Also, the upload API must be specified in the property ImageUploadEndpoint. In some cases, the API requires an authentication. The properties ImageUploadAuthenticationSchema and ImageUploadAuthenticationToken allow you to pass the correct schema and token to use in the call.

Those values will be added to the HttpClient POST request in the header. Only if both properties are not null, they will be added to the header.

markdown-editor-upload-image

If you want to understand better how to create the API for the upload, I have created a specific post on PureSourceCode.

Toolbar icons

Below are the built-in toolbar icons (only some of which are enabled by default), which can be reorganized however you like. "Name" is the name of the icon, referenced in the JS. "Action" is either a function or a URL to open. "Class" is the class given to the icon. "Tooltip" is the small tooltip that appears via the title="" attribute. Note that shortcut hints are added automatically and reflect the specified action if it has a key bind assigned to it (i.e. with the value of action set to bold and that of tooltip set to Bold, the final text the user will see would be "Bold (Ctrl-B)").

Additionally, you can add a separator between any icons by adding "|" to the toolbar array.

Name Action Tooltip
Class
bold toggleBold Bold
fa fa-bold
italic toggleItalic Italic
fa fa-italic
strikethrough toggleStrikethrough Strikethrough
fa fa-strikethrough
heading toggleHeadingSmaller Heading
fa fa-header
heading-smaller toggleHeadingSmaller Smaller Heading
fa fa-header
heading-bigger toggleHeadingBigger Bigger Heading
fa fa-lg fa-header
heading-1 toggleHeading1 Big Heading
fa fa-header header-1
heading-2 toggleHeading2 Medium Heading
fa fa-header header-2
heading-3 toggleHeading3 Small Heading
fa fa-header header-3
code toggleCodeBlock Code
fa fa-code
quote toggleBlockquote Quote
fa fa-quote-left
unordered-list toggleUnorderedList Generic List
fa fa-list-ul
ordered-list toggleOrderedList Numbered List
fa fa-list-ol
clean-block cleanBlock Clean block
fa fa-eraser
link drawLink Create Link
fa fa-link
image drawImage Insert Image
fa fa-picture-o
table drawTable Insert Table
fa fa-table
horizontal-rule drawHorizontalRule Insert Horizontal Line
fa fa-minus
preview togglePreview Toggle Preview
fa fa-eye no-disable
side-by-side toggleSideBySide Toggle Side by Side
fa fa-columns no-disable no-mobile
fullscreen toggleFullScreen Toggle Fullscreen
fa fa-arrows-alt no-disable no-mobile
guide This link Markdown Guide
fa fa-question-circle

Keyboard shortcuts

EasyMDE comes with an array of predefined keyboard shortcuts, but they can be altered with a configuration option. The list of default ones is as follows:

Shortcut (Windows / Linux) Shortcut (macOS) Action
Ctrl-' Cmd-' "toggleBlockquote"
Ctrl-B Cmd-B "toggleBold"
Ctrl-E Cmd-E "cleanBlock"
Ctrl-H Cmd-H "toggleHeadingSmaller"
Ctrl-I Cmd-I "toggleItalic"
Ctrl-K Cmd-K "drawLink"
Ctrl-L Cmd-L "toggleUnorderedList"
Ctrl-P Cmd-P "togglePreview"
Ctrl-Alt-C Cmd-Alt-C "toggleCodeBlock"
Ctrl-Alt-I Cmd-Alt-I "drawImage"
Ctrl-Alt-L Cmd-Alt-L "toggleOrderedList"
Shift-Ctrl-H Shift-Cmd-H "toggleHeadingBigger"
F9 F9 "toggleSideBySide"
F11 F11 "toggleFullScreen"

Licence and contribution

A lot of people sent me the same question. My components (MarkdownEditor, DataTable, SVG Icon and others that you find on my GitHub) are freeware.

I ask you to contribute to the project in one of the following ways:

  • sending your feedback
  • highlight bugs
  • ask for improvement
  • submit code and fixes
  • share the project
  • share my website PureSourceCode.com

If you don't know how to do it or you:

  • want to support this project
  • find very useful this project and it saves you a lot of time and work
  • like to sustain my work
  • want to pay my a beer
  • are using this component for commercial purpose and you want to set your conscience at rest and/or put a hand on one's heart 😂

then, you can buy one of the support licence I created. There are different prices. The amount is your decision. You find have a full list on PureSourceCode Shop

The contribution gives you:

  • dedicate email support
  • priority access to the support
  • fast bug fix
  • receive preview and beta of the components
  • help to fix your code with Visual Studio Live Share

Other Blazor components

Component name Forum Description
DataTable for Blazor Forum DataTable component for Blazor WebAssembly and Blazor Server
Markdown editor for Blazor Forum This is a Markdown Editor for use in Blazor. It contains a live preview as well as an embeded help guide for users.
Browser Detect for Blazor Forum Browser detect for Blazor WebAssembly and Blazor Server
CodeSnipper for Blazor Forum Add code snippet in your Blazor pages for 196 programming languages with 243 styles
Copy To Clipboard Forum Add a button to copy text in the clipbord
SVG Icons and flags for Blazor Forum Library with a lot of SVG icons and SVG flags to use in your Razor pages
Modal dialog for Blazor Forum Simple Modal Dialog for Blazor WebAssembly
PSC.Extensions Forum A lot of functions for .NET5 in a NuGet package that you can download for free. We collected in this package functions for everyday work to help you with claim, strings, enums, date and time, expressions...
Quill for Blazor Forum Quill Component is a custom reusable control that allows us to easily consume Quill and place multiple instances of it on a single page in our Blazor application
Segment for Blazor Forum This is a Segment component for Blazor Web Assembly and Blazor Server
Tabs for Blazor Forum This is a Tabs component for Blazor Web Assembly and Blazor Server
WorldMap for Blazor Forum Show world maps with your data

More examples and documentation

blazormarkdowneditor's People

Contributors

davidreneuw avatar erossini avatar jichao99 avatar wkeska avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

blazormarkdowneditor's Issues

How can we create HTMLString without loading MarkdownEditor

Discussed in #26

Originally posted by manish-karn April 11, 2024
How can we generate HTMLString without loading MarkdownEditor? like MarkDig.Markdown.ToHTML() , I could not find any api exist , any code sample will be great appreciated, it is possible to show MarkdownEditor and call ValueHTMLChanged and hide MarkdownEditor immediately, but that causes annoying flicking UI

Using image upload on Blazer Server causes a crash

When using Blazor MarkdownEditor in Blazor Server, if image upload is turned on(UploadImage="true" ImageUploadEndpoint="..."),drag or copy the image to upload, the page will have an error "Attempting to reconnect to the server".Here's the log in the chrome console:
[2022-06-19T06:07:42.805Z] Error: Connection disconnected with error 'Error: Server returned an error on close: Connection closed with an error.'.
log @ blazor.server.js:1
_stopConnection @ blazor.server.js:1
transport.onclose @ blazor.server.js:1
_close @ blazor.server.js:1
stop @ blazor.server.js:1
_stopInternal @ blazor.server.js:1
await in _stopInternal(异步)
stop @ blazor.server.js:1
_processIncomingData @ blazor.server.js:1
connection.onreceive @ blazor.server.js:1
o.onmessage @ blazor.server.js:1

Leads on fixing mermaid and highlightjs compatibility?

Any leads on how to make both mermaid and highlightjs work at the same time? Ive been building custom highlightjs builds to avoid mermaid codeblocks with no success.
Just interested in seeing if it is possible at all from your point of view

ImageMaxSize not working

when upload image file size is bigger than specified or default(2MB), the image file will still been uploaded.
tested on Blazor WebAssembly

<MarkdownEditor @ref="markdownEditor" @bind-Value="SelectedEvent.content"
ValueHTMLChanged="OnMarkdownValueHTMLChanged"
ImageUploadStarted="UploadImageStarted"
ImageUploadEndpoint=@markdownImageUploadEndpoint
ImagePathAbsolute="true"
UploadImage="true"/>

[question] License

I cannot see any licensing information regarding this package. Is BlazorMarkdownEditor free to use for commercial purposes?

Change license to MIT

This component is great but its license makes it challenging to include in other open source projects. Any specific reason this project is GPL?

OnInitializedAsync Value initialization

Hi!
First of all, amazing component.
Second,
I have 2 issues in 1.

  1. OnInitialized function will update the value but OnInitializedAsync will not when using async await for http client.
  2. there isn't any Toolbar documentation.

Adding a code sample for the issue:

`
<MarkdownEditor Value="@Value" Toolbar={????}/>

@code {
   [Parameter]
   public string Value { get; set; } = string.Empty;

   protected override async Task OnInitializedAsync()
   {
        // Will Not Work
        var Http = new HttpClient() { BaseAddress = new Uri(MyNavigationManager.BaseUri) };
        var tmp = await Http.GetStringAsync("md/ReleaseNotesTemplate.md");
        Value = tmp;
   }

   protected override void OnInitialized()
   {
      // Will Work
      Value = "# Sample Template For comments";
   }
}

`

Highlight.js with Mermaid Issue

Hello,

Have you made any progress regarding having mermaid and highlight.js work together?

Any guidance would be greatly appreciated,

Kind Regards,

Jason

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.