MarkdownEditor is a text area replacement for writing beautiful and understandable Markdown. It allows users who may be less experienced with Markdown to use familiar toolbar buttons and shortcuts, and renders the syntax while editing. Based on Easy MDE by Sparksuite, Inc, Jeroen Akkerman.
A lightweight, flexible and customizable Markdown editor with a configurable toolbar, side-by-side mode and RTL support. The paste, copy and cut events are sent to the server.
A popular use case is an editor inside a PrimeFaces dialog. This example is for both demonstration and testing.
Use the extender attribute to extend the underlying editor: the function below enables line numbers
and custom prompts for links and images (this is the widget, this.cfg its JSON configuration).
<div class="card">
<h5>Basic Usage</h5>
<p>A lightweight, flexible and customizable Markdown editor with a configurable toolbar, side-by-side mode and RTL support. The paste, copy and cut events are sent to the server.</p>
<h:form id="formBasicUsage">
<p:messages id="messages" showSummary="true" showDetail="true"/>
<h:panelGrid columns="2" id="pnlDetails" styleClass="p-4">
<p:outputLabel value="RTL:" for="@next" styleClass="mr-2"/>
<p:selectBooleanCheckbox id="chkRtl" value="#{markdownEditorController.rtl}" styleClass="mr-2">
<p:ajax update="txtMarkdown"/>
</p:selectBooleanCheckbox>
</h:panelGrid>
<pe:markdownEditor id="txtMarkdown" widgetVar="mdeBasic" value="#{markdownEditorController.markdown}"
maxHeight="300px" sideBySideFullscreen="false" required="true" mode="sidebyside"
dir="#{markdownEditorController.rtl ? 'rtl' : 'ltr'}"
toolbar="bold, italic, strikethrough, |, heading-1, heading-2, heading-3,|, code, quote, unordered-list, ordered-list,|, clean-block, link, image, table, horizontal-rule,|, preview, side-by-side, fullscreen, |, guide">
<p:ajax event="paste" listener="#{markdownEditorController.onPaste}" update="messages"/>
<p:ajax event="copy" listener="#{markdownEditorController.onCopy}" update="messages"/>
<p:ajax event="cut" listener="#{markdownEditorController.onCut}" update="messages"/>
</pe:markdownEditor>
<p:commandButton value="Submit" actionListener="#{markdownEditorController.submit}" update="txtMarkdown messages"
styleClass="mt-4"/>
</h:form>
</div>
<div class="card">
<h5>Dialog</h5>
<p>A popular use case is an editor inside a PrimeFaces dialog. This example is for both demonstration and testing.</p>
<h:form id="formDialog">
<h:panelGrid columns="6" id="pnlDetails" styleClass="p-4">
<p:commandButton value="Open Dialog" type="button" icon="pi pi-external-link" onclick="PF('dlgMarkdown').show()"/>
</h:panelGrid>
<p:dialog header="Header" widgetVar="dlgMarkdown" minHeight="40" width="60vw" showEffect="fade" closable="true" closeOnEscape="true" modal="true">
<pe:markdownEditor id="txtMarkdown" widgetVar="mdeDialog" value="#{markdownEditorController.markdown}"
maxHeight="200px" sideBySideFullscreen="false"
toolbar="bold, italic, |, guide">
</pe:markdownEditor>
</p:dialog>
</h:form>
</div>
<div class="card">
<h5>Extender</h5>
<p>
Use the <code>extender</code> attribute to extend the underlying editor: the function below enables line numbers
and custom prompts for links and images (<code>this</code> is the widget, <code>this.cfg</code> its JSON configuration).
</p>
<h:form id="formExtender">
<pe:markdownEditor id="txtMarkdown" widgetVar="mdeExtender" value="#{markdownEditorController.markdown}"
maxHeight="200px" toolbar="bold, italic, link, |, guide"
extender="editorExtender">
</pe:markdownEditor>
</h:form>
<script type="text/javascript">
function editorExtender() {
// this = widget
// this.cfg = JSON configuration
this.cfg.lineNumbers = true;
this.cfg.promptURLs = true;
this.cfg.promptTexts = {
image: "Custom prompt for URL:",
link: "Custom prompt for URL:",
};
};
</script>
</div>
package org.primefaces.extensions.showcase.controller.markdowneditor;
import java.io.Serial;
import java.io.Serializable;
import jakarta.annotation.PostConstruct;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.faces.event.AjaxBehaviorEvent;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Named;
@Named
@ViewScoped
public class MarkdownEditorController implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private String markdown;
private boolean rtl;
@PostConstruct
public void init() {
this.markdown = "Markdown editing with **inline** styling!";
this.rtl = false;
}
public void addMessage(String message) {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(message));
}
public void submit() {
addMessage(getMarkdown());
}
public void onPaste(AjaxBehaviorEvent e) {
addMessage("Paste event.");
}
public void onCopy(AjaxBehaviorEvent e) {
addMessage("Copy event.");
}
public void onCut(AjaxBehaviorEvent e) {
addMessage("Cut event.");
}
public String getMarkdown() {
return this.markdown;
}
public void setMarkdown(String markdown) {
this.markdown = markdown;
}
public boolean isRtl() {
return rtl;
}
public void setRtl(final boolean rtl) {
this.rtl = rtl;
}
}