
Syncfusion Angular Markdown Converter
- 170 installs
- Updated August 4, 2026
- syncfusion/angular-ui-components-skills
Use syncfusion-angular-markdown-converter for development tasks
About
syncfusion-angular-markdown-converter: A skill for development. This provides functionality for development workflows.
- syncfusion-angular-markdown-converter
Syncfusion Angular Markdown Converter by the numbers
- 170 all-time installs (skills.sh)
- +11 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #2,287 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/syncfusion/angular-ui-components-skills --skill syncfusion-angular-markdown-converterAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 170 |
|---|---|
| Last updated | August 4, 2026 |
| Repository | syncfusion/angular-ui-components-skills ↗ |
What it does
Use syncfusion-angular-markdown-converter for development tasks
Files
Implementing Syncfusion Angular Markdown Converter
The Syncfusion Angular Markdown Converter is a lightweight utility that transforms Markdown-formatted text into clean, semantic HTML. It is typically used alongside the Syncfusion Rich Text Editor (in Markdown mode) to provide a live preview of rendered content.
When to Use This Skill
- Convert Markdown text to HTML in an Angular application
- Display a live preview of Markdown content as the user types
- Configure conversion behavior (GFM support, line breaks, async mode, error suppression)
- Build a side-by-side Markdown editor and HTML preview layout
- Integrate
MarkdownConverter.toHtml()with the Syncfusion Rich Text Editor
Documentation and Navigation Guide
Getting Started
📄 Read: references/getting-started.md
- Angular CLI setup and project creation
- Installing
@syncfusion/ej2-markdown-converterand@syncfusion/ej2-angular-richtexteditor - CSS imports for the material3 theme
- Required module injection (MarkdownEditor, Image, Link, Toolbar, Table)
- Running the application
Convert Markdown to HTML — toHtml API
📄 Read: references/tohtml-api.md
MarkdownConverter.toHtml()method signature- Basic usage example (standalone, no editor required)
- Supported Markdown elements (headings, lists, tables, links, images, inline styles)
- Using the return value in Angular templates
Configurable Options
📄 Read: references/configurable-options.md
MarkdownConverterOptionsinterfaceasync— asynchronous conversion for large contentgfm— GitHub Flavored Markdown support (default: true)lineBreak— convert single line breaks to<br>(default: false)silence— suppress errors on invalid Markdown (default: false)- Full example passing options to
toHtml()
Rich Text Editor Integration
📄 Read: references/richtexteditor-integration.md
- Splitter-based side-by-side editor and preview layout
- Configuring
ejs-richtexteditorin MarkdowneditorMode - Real-time preview using
onChangeandupdateValue() - Toolbar configuration for Markdown editing
MarkdownFormatterfor custom Markdown syntax- Custom preview toggle button (fullPreview pattern)
- Mobile/device orientation handling with
Browser.isDevice
Quick Start
Install packages and wire up the converter in three steps:
1. Install packages:
npm install @syncfusion/ej2-markdown-converter
npm install @syncfusion/ej2-angular-richtexteditor2. Import CSS in `src/styles.css`:
@import '../node_modules/@syncfusion/ej2-base/styles/material3.css';
@import '../node_modules/@syncfusion/ej2-richtexteditor/styles/material3.css';3. Convert Markdown to HTML:
import { MarkdownConverter } from '@syncfusion/ej2-markdown-converter';
const markdown = '# Hello World\nThis is **Markdown** text.';
const html = MarkdownConverter.toHtml(markdown);
console.log(html);
// Output: <h1>Hello World</h1><p>This is <strong>Markdown</strong> text.</p>Common Patterns
Pattern 1: Standalone Conversion (No Editor)
When you only need to convert a Markdown string to HTML without an editor UI:
import { MarkdownConverter } from '@syncfusion/ej2-markdown-converter';
const html = MarkdownConverter.toHtml(markdownString);
document.getElementById('preview')!.innerHTML = html as string;Pattern 2: Live Preview on Keyup
Convert on every keystroke inside a Rich Text Editor textarea:
public markDownConversion(): void {
const textarea = this.editorObj.contentModule.getEditPanel() as HTMLTextAreaElement;
const previewEl = document.getElementById('html-view') as HTMLElement;
previewEl.innerHTML = MarkdownConverter.toHtml(textarea.value) as string;
}Pattern 3: Conversion with Options
Disable GFM and enable line-break conversion:
const html = MarkdownConverter.toHtml(markdownString, {
gfm: false,
lineBreak: true
});Pattern 4: Side-by-Side Preview with Splitter
For a full editor + preview experience, use the Syncfusion Splitter component alongside the Rich Text Editor in Markdown mode. The preview pane is updated via updateValue() on every change event. 📄 Read: references/richtexteditor-integration.md for the full implementation.
Key Props / API
| API | Type | Default | Purpose |
|---|---|---|---|
MarkdownConverter.toHtml(content, options?) | static method | — | Converts Markdown string to HTML |
options.async | boolean | false | Async conversion for large content |
options.gfm | boolean | true | GitHub Flavored Markdown support |
options.lineBreak | boolean | false | Single line breaks → <br> |
options.silence | boolean | false | Suppress errors on invalid Markdown |
Configurable Options for Markdown Converter
The MarkdownConverter.toHtml() method accepts an optional second argument — a MarkdownConverterOptions object — that controls how Markdown is parsed and rendered.
Method Signature with Options
MarkdownConverter.toHtml(markdownContent: string, options?: MarkdownConverterOptions): string;MarkdownConverterOptions Reference
| Option | Type | Default | Description |
|---|---|---|---|
async | boolean | false | Enables asynchronous conversion for large content processing |
gfm | boolean | true | Enables GitHub Flavored Markdown (tables, strikethrough, task lists) |
lineBreak | boolean | false | Converts single line breaks into <br> elements |
silence | boolean | false | Suppresses errors — skips invalid Markdown instead of throwing |
---
Option Details
async — Asynchronous Conversion
Default: false
When true, the conversion runs asynchronously, preventing the main thread from being blocked when processing large Markdown documents.
import { MarkdownConverter } from '@syncfusion/ej2-markdown-converter';
const html = MarkdownConverter.toHtml(largeMarkdownContent, { async: true });Use async: true when converting documents with thousands of lines where synchronous conversion might cause UI freezes.
---
gfm — GitHub Flavored Markdown
Default: true
GitHub Flavored Markdown extends standard Markdown with:
- Tables using pipe syntax (
| col1 | col2 |) - Strikethrough using
~~text~~ - Task lists using
- [ ]and- [x] - Fenced code blocks with language hints (
`typescript)
// GFM enabled (default) — tables and strikethrough work
const html = MarkdownConverter.toHtml('| A | B |\n|---|---|\n| 1 | 2 |');
// Output: <table><thead>...</thead><tbody>...</tbody></table>
// GFM disabled — table rendered as plain text
const html = MarkdownConverter.toHtml('| A | B |\n|---|---|\n| 1 | 2 |', { gfm: false });Disable gfm only when you need strict CommonMark compatibility or want to avoid GFM-specific parsing behavior.
---
lineBreak — Single Line Break Conversion
Default: false
By default, a single line break in Markdown is not converted to <br> — a blank line is needed to start a new paragraph (standard Markdown behavior). Setting lineBreak: true converts every single newline into a <br> tag.
const markdown = 'Line one\nLine two';
// lineBreak: false (default)
MarkdownConverter.toHtml(markdown);
// Output: <p>Line one Line two</p>
// lineBreak: true
MarkdownConverter.toHtml(markdown, { lineBreak: true });
// Output: <p>Line one<br>Line two</p>Use lineBreak: true when your users expect line-by-line formatting, such as in poetry or structured text input.
---
silence — Error Suppression
Default: false
When false, invalid or malformed Markdown may throw an error. When true, errors are suppressed and the converter skips the problematic segment rather than throwing.
// Without silence — may throw on malformed input
const html = MarkdownConverter.toHtml(potentiallyBadMarkdown);
// With silence — safely skip bad segments
const html = MarkdownConverter.toHtml(potentiallyBadMarkdown, { silence: true });Use silence: true when processing user-submitted Markdown where the input quality cannot be guaranteed.
---
Using Multiple Options Together
Options can be combined freely:
import { MarkdownConverter } from '@syncfusion/ej2-markdown-converter';
const markdownContent = `
# Report
Line one
Line two
| Header A | Header B |
|----------|----------|
| Cell 1 | Cell 2 |
`;
const html = MarkdownConverter.toHtml(markdownContent, {
async: false,
gfm: true,
lineBreak: true,
silence: true
});
console.log(html);Full Angular Component Example
import { Component } from '@angular/core';
import { MarkdownConverter } from '@syncfusion/ej2-markdown-converter';
import {
RichTextEditorModule,
ContentRender,
RichTextEditorComponent,
ToolbarService,
LinkService,
ImageService,
MarkdownEditorService,
TableService
} from '@syncfusion/ej2-angular-richtexteditor';
import { ViewChild } from '@angular/core';
@Component({
imports: [RichTextEditorModule],
standalone: true,
selector: 'app-root',
template: `
<ejs-richtexteditor
#rte
[editorMode]="'Markdown'"
(change)="onEditorChange()">
</ejs-richtexteditor>
<div id="preview"></div>
`,
providers: [ToolbarService, LinkService, ImageService, MarkdownEditorService, TableService]
})
export class AppComponent {
@ViewChild('rte') editorObj!: RichTextEditorComponent;
public onEditorChange(): void {
const textarea = (this.editorObj.contentModule as ContentRender)
.getEditPanel() as HTMLTextAreaElement;
const html = MarkdownConverter.toHtml(textarea.value, {
gfm: true,
lineBreak: false,
silence: true
});
(document.getElementById('preview') as HTMLElement).innerHTML = html as string;
}
}Getting Started with Syncfusion Angular Markdown Converter
Step-by-step setup for adding the Syncfusion Markdown Converter to an Angular application.
1. Set Up Angular Environment
Install the Angular CLI if not already installed:
npm install -g @angular/cli@21.0.1Create a new Angular application:
ng new my-appWhen prompted:
- Angular routing: your preference
- Stylesheet format: your preference
- Server-Side Rendering (SSR) / Static Site Generation (SSG): select No
Navigate into the project:
cd my-app2. Install Syncfusion Packages
Install both the Markdown Converter and the Rich Text Editor packages:
npm install @syncfusion/ej2-markdown-converter
npm install @syncfusion/ej2-angular-richtexteditorThe ej2-markdown-converter package provides the MarkdownConverter utility. The ej2-angular-richtexteditor package provides the ejs-richtexteditor component used to author Markdown content.
3. Add CSS References
Add the following imports to src/styles.css. These load the material3 theme for all required Syncfusion sub-packages:
@import '../node_modules/@syncfusion/ej2-base/styles/material3.css';
@import '../node_modules/@syncfusion/ej2-buttons/styles/material3.css';
@import '../node_modules/@syncfusion/ej2-inputs/styles/material3.css';
@import '../node_modules/@syncfusion/ej2-lists/styles/material3.css';
@import '../node_modules/@syncfusion/ej2-navigations/styles/material3.css';
@import '../node_modules/@syncfusion/ej2-popups/styles/material3.css';
@import '../node_modules/@syncfusion/ej2-splitbuttons/styles/material3.css';
@import '../node_modules/@syncfusion/ej2-richtexteditor/styles/material3.css';
@import '../node_modules/@syncfusion/ej2-layouts/styles/material3.css';Note: ej2-layouts is only required if you are using the Splitter component for a side-by-side preview layout.4. Module Injection
The Rich Text Editor in Markdown mode requires these modules to be injected via the providers array in your component or root NgModule:
| Module | Purpose |
|---|---|
ToolbarService | Enables the editor toolbar |
LinkService | Enables hyperlink support in Markdown |
ImageService | Enables image insertion |
MarkdownEditorService | Activates Markdown editing mode |
TableService | Enables table insertion |
import {
ToolbarService,
LinkService,
ImageService,
MarkdownEditorService,
TableService
} from '@syncfusion/ej2-angular-richtexteditor';
@Component({
// ...
providers: [ToolbarService, LinkService, ImageService, MarkdownEditorService, TableService]
})
export class AppComponent {}5. Basic AppComponent
A minimal working example using the standalone component API:
// src/app/app.component.ts
import { enableRipple, createElement } from '@syncfusion/ej2-base';
import { Component, ViewChild } from '@angular/core';
import {
RichTextEditorModule,
ToolbarSettingsModel,
ContentRender,
RichTextEditorComponent,
MarkdownFormatter,
ToolbarService,
LinkService,
ImageService,
MarkdownEditorService,
TableService
} from '@syncfusion/ej2-angular-richtexteditor';
import { MarkdownConverter } from '@syncfusion/ej2-markdown-converter';
enableRipple(true);
@Component({
imports: [RichTextEditorModule],
standalone: true,
selector: 'app-root',
template: `
<ejs-richtexteditor
id='mdCustom'
#mdCustom
[toolbarSettings]='tools'
[editorMode]='mode'
[formatter]='formatter'
(created)='onCreate()'
[value]='value'>
</ejs-richtexteditor>
`,
providers: [ToolbarService, LinkService, ImageService, MarkdownEditorService, TableService]
})
export class AppComponent {
@ViewChild('mdCustom')
public editorObj?: RichTextEditorComponent;
public textArea?: HTMLTextAreaElement;
public mdsource?: HTMLElement;
public tools: ToolbarSettingsModel = {
items: ['Bold', 'Italic', 'StrikeThrough', '|',
'Formats', 'OrderedList', 'UnorderedList', '|',
'CreateLink', 'Image', '|',
{
tooltipText: 'Preview',
template: '<button id="preview-code" class="e-tbar-btn e-control e-btn e-icon-btn">' +
'<span class="e-btn-icon e-icons e-md-preview"></span></button>'
}, 'Undo', 'Redo']
};
public mode: string = 'Markdown';
public formatter: MarkdownFormatter = new MarkdownFormatter({
listTags: { 'OL': '1., 2., 3.', 'UL': '+ ' },
formatTags: { 'Blockquote': '> ' },
selectionTags: { 'Bold': '__', 'Italic': '_' }
});
public value: string = 'Type **Markdown** here and click Preview to see the HTML output.';
public onCreate(): void {
this.textArea = (this.editorObj!.contentModule as ContentRender)
.getEditPanel() as HTMLTextAreaElement;
this.textArea.addEventListener('keyup', () => this.markDownConversion());
this.mdsource = document.getElementById('preview-code') as HTMLElement;
this.mdsource?.addEventListener('click', () => this.fullPreview());
}
public markDownConversion(): void {
if (this.mdsource?.classList.contains('e-active')) {
const id = this.editorObj?.getID() + 'html-view';
const htmlPreview = this.editorObj!.element.querySelector('#' + id) as HTMLElement;
htmlPreview.innerHTML = MarkdownConverter.toHtml(
(this.editorObj!.contentModule as ContentRender)
.getEditPanel() as unknown as string
) as string;
}
}
public fullPreview(): void {
const id = this.editorObj!.getID() + 'html-preview';
let htmlPreview = this.editorObj!.element.querySelector('#' + id) as HTMLElement;
if (this.mdsource!.classList.contains('e-active')) {
this.mdsource!.classList.remove('e-active');
this.textArea!.style.display = 'block';
htmlPreview.style.display = 'none';
} else {
this.mdsource!.classList.add('e-active');
if (!htmlPreview) {
htmlPreview = createElement('div', { className: 'e-content e-pre-source' });
htmlPreview.id = id;
this.textArea!.parentNode!.appendChild(htmlPreview);
}
this.textArea!.style.display = 'none';
htmlPreview.style.display = 'block';
htmlPreview.innerHTML = MarkdownConverter.toHtml(
((this.editorObj!.contentModule as ContentRender).getEditPanel() as HTMLTextAreaElement).value
) as string;
this.mdsource!.parentElement!.title = 'Code View';
}
}
}// src/main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));6. Run the Application
ng serve --openThe browser opens with the Markdown Editor. Click Preview in the toolbar to see the real-time HTML output of your Markdown content.
Common Setup Issues
- Missing CSS: If the editor renders unstyled, verify all
@importlines instyles.cssmatch the packages installed innode_modules/@syncfusion. - Module not found errors: Ensure both
@syncfusion/ej2-markdown-converterand@syncfusion/ej2-angular-richtexteditorare listed inpackage.jsondependencies. - Providers not injected: If the Markdown editor toolbar is missing, confirm all five services are in the
providersarray of your component.
Rich Text Editor Integration
Table of Contents
- Overview
- Splitter-Based Side-by-Side Layout
- Rich Text Editor in Markdown Mode
- Live Preview with updateValue()
- Toolbar Configuration
- Custom Markdown Formatter
- Custom Preview Toggle Button
- Device and Orientation Handling
- Full Working Example
---
Overview
The Syncfusion Markdown Converter is designed to work alongside the Syncfusion Rich Text Editor (ejs-richtexteditor) in Markdown editing mode. The typical integration pattern:
1. Set the Rich Text Editor's editorMode to 'Markdown' 2. Listen for editor changes (change, actionComplete, or keyup) 3. Call MarkdownConverter.toHtml() with the current textarea value 4. Inject the resulting HTML into a preview container
---
Splitter-Based Side-by-Side Layout
Use the Syncfusion Splitter (ejs-splitter) to display the editor and HTML preview side by side. Install the layouts package if not already present:
npm install @syncfusion/ej2-angular-layoutsTemplate structure:
<ejs-splitter id="splitter-rte-markdown-preview"
#splitterInstance
height="450px"
width="100%"
(resizing)="resizing()"
(created)="updateOrientation()">
<e-panes>
<!-- Left pane: Markdown editor -->
<e-pane size="50%" [resizable]="true" cssClass="pane1" min="40%">
<ng-template #content>
<ejs-richtexteditor
id="markdown"
#markdown
[value]="value"
height="447px"
[toolbarSettings]="tools"
[editorMode]="mode"
(created)="onCreate()"
(change)="onChange()"
(actionComplete)="updateValue()">
</ejs-richtexteditor>
</ng-template>
</e-pane>
<!-- Right pane: HTML preview -->
<e-pane cssClass="pane2" min="40%">
<ng-template #content>
<div class="heading right">
<h6 class="title"><b>Markdown Preview</b></h6>
<div class="splitter-default-content source-code pane2"
style="padding: 20px;"></div>
</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>Key splitter behaviors:
(resizing)="resizing()"— callseditorObj.refreshUI()so the editor reflows on drag(created)="updateOrientation()"— switches splitter to vertical on mobile devicesmin="40%"— prevents panes from collapsing entirely
---
Rich Text Editor in Markdown Mode
Set editorMode to 'Markdown' to switch the Rich Text Editor from WYSIWYG mode to plain-text Markdown editing:
import { EditorMode } from '@syncfusion/ej2-angular-richtexteditor';
public mode: EditorMode = 'Markdown';In the template:
<ejs-richtexteditor [editorMode]="mode" ...></ejs-richtexteditor>In Markdown mode, the editor's content panel is a plain <textarea>. Access it via:
import { ContentRender } from '@syncfusion/ej2-angular-richtexteditor';
const textarea = (this.editorObj.contentModule as ContentRender)
.getEditPanel() as HTMLTextAreaElement;---
Live Preview with updateValue()
The updateValue() method reads the current textarea content and pushes the converted HTML into the preview container. Call it from onChange and actionComplete events to keep the preview in sync:
public srcArea: HTMLElement | null = null;
public onCreate(): void {
// Wait for the editor to fully initialize before accessing the DOM
setTimeout(() => {
this.editorObj!.refreshUI();
this.textArea = (this.editorObj!.contentModule as ContentRender)
.getEditPanel() as HTMLTextAreaElement;
this.srcArea = document.querySelector('.source-code');
this.updateValue(); // Render initial content
}, 0);
}
public onChange(): void {
this.updateValue();
}
public updateValue(): void {
const textarea = (this.editorObj!.contentModule as ContentRender)
.getEditPanel() as HTMLTextAreaElement;
this.srcArea!.innerHTML = MarkdownConverter.toHtml(textarea.value) as string;
}Why `setTimeout(..., 0)`? The editor'scontentModuleand DOM elements are not ready synchronously inside thecreatedevent. A zero-delay timeout defers execution until after the current event loop cycle, guaranteeing the editor is fully rendered.
---
Toolbar Configuration
Configure the toolbar via toolbarSettings.items. For Markdown mode, use standard formatting items plus any custom toolbar buttons:
public tools: ToolbarSettingsModel = {
enableFloating: false,
items: [
'Bold', 'Italic', 'StrikeThrough', '|',
'Formats', 'Blockquote', 'OrderedList', 'UnorderedList', '|',
'CreateLink', 'Image', 'CreateTable', '|',
'Undo', 'Redo'
]
};enableFloating: false— disables floating toolbar behavior, which works better in a fixed splitter layout'Formats'— applies Markdown heading levels (H1–H6)'Blockquote'— wraps selected text in>syntax'CreateTable'— inserts a GFM table template
---
Custom Markdown Formatter
MarkdownFormatter lets you redefine the Markdown syntax that toolbar buttons produce. This is useful when you want non-standard Markdown (e.g., __bold__ instead of **bold**):
import { MarkdownFormatter } from '@syncfusion/ej2-angular-richtexteditor';
public formatter: MarkdownFormatter = new MarkdownFormatter({
listTags: {
'OL': '1., 2., 3.', // Numbered list prefix
'UL': '+ ' // Unordered list uses + instead of -
},
formatTags: {
'Blockquote': '> '
},
selectionTags: {
'Bold': '__', // Double underscore instead of **
'Italic': '_' // Single underscore instead of *
}
});Pass it to the editor:
<ejs-richtexteditor [formatter]="formatter" ...></ejs-richtexteditor>MarkdownConverter.toHtml()correctly handles the custom syntax produced byMarkdownFormatter— no extra configuration needed.
---
Custom Preview Toggle Button
To add a Preview toggle button to the toolbar (shows/hides the HTML preview in the same editor area):
Toolbar item definition:
{
tooltipText: 'Preview',
template: '<button id="preview-code" class="e-tbar-btn e-control e-btn e-icon-btn">' +
'<span class="e-btn-icon e-icons e-md-preview"></span></button>'
}Toggle logic:
public mdsource?: HTMLElement;
public onCreate(): void {
this.textArea = (this.editorObj!.contentModule as ContentRender)
.getEditPanel() as HTMLTextAreaElement;
this.textArea.addEventListener('keyup', () => this.markDownConversion());
this.mdsource = document.getElementById('preview-code') as HTMLElement;
this.mdsource?.addEventListener('click', () => this.fullPreview());
}
public markDownConversion(): void {
if (this.mdsource?.classList.contains('e-active')) {
const id = this.editorObj!.getID() + 'html-view';
const htmlPreview = this.editorObj!.element.querySelector('#' + id) as HTMLElement;
htmlPreview.innerHTML = MarkdownConverter.toHtml(this.textArea!.value) as string;
}
}
public fullPreview(): void {
const id = this.editorObj!.getID() + 'html-preview';
let htmlPreview = this.editorObj!.element.querySelector('#' + id) as HTMLElement;
if (this.mdsource!.classList.contains('e-active')) {
// Switch back to editor
this.mdsource!.classList.remove('e-active');
this.textArea!.style.display = 'block';
htmlPreview.style.display = 'none';
} else {
// Switch to preview
this.mdsource!.classList.add('e-active');
if (!htmlPreview) {
htmlPreview = createElement('div', { className: 'e-content e-pre-source' });
htmlPreview.id = id;
this.textArea!.parentNode!.appendChild(htmlPreview);
}
this.textArea!.style.display = 'none';
htmlPreview.style.display = 'block';
htmlPreview.innerHTML = MarkdownConverter.toHtml(this.textArea!.value) as string;
this.mdsource!.parentElement!.title = 'Code View';
}
}---
Device and Orientation Handling
On mobile devices, the horizontal splitter layout is too narrow. Switch to vertical orientation on device detection:
import { Browser } from '@syncfusion/ej2-base';
public updateOrientation(): void {
if (Browser.isDevice) {
(this.splitterObj as any).orientation = 'Vertical';
(document.body.querySelector('.heading') as HTMLElement).style.width = 'auto';
}
}Also call editorObj.refreshUI() on splitter resize to keep the editor correctly sized:
public resizing(): void {
this.editorObj!.refreshUI();
}---
Full Working Example
Complete app.component.ts using Splitter + Rich Text Editor + live Markdown preview:
import { enableRipple } from '@syncfusion/ej2-base';
import { Component, ViewChild } from '@angular/core';
import {
RichTextEditorModule,
ToolbarSettingsModel,
RichTextEditorComponent,
ContentRender,
ToolbarService,
LinkService,
ImageService,
MarkdownEditorService,
TableService,
EditorMode
} from '@syncfusion/ej2-angular-richtexteditor';
import { Browser } from '@syncfusion/ej2-base';
import { MarkdownConverter } from '@syncfusion/ej2-markdown-converter';
import { SplitterComponent, SplitterModule } from '@syncfusion/ej2-angular-layouts';
enableRipple(true);
@Component({
imports: [RichTextEditorModule, SplitterModule],
standalone: true,
selector: 'app-root',
template: `
<div class="sample-container markdown-preview">
<ejs-splitter id="splitter-rte-markdown-preview"
#splitterInstance
height="450px"
width="100%"
(resizing)="resizing()"
(created)="updateOrientation()">
<e-panes>
<e-pane size="50%" [resizable]="true" cssClass="pane1" min="40%">
<ng-template #content>
<div class="content">
<ejs-richtexteditor
id="markdown"
#markdown
[value]="value"
height="447px"
[toolbarSettings]="tools"
saveInterval="10"
[editorMode]="mode"
(created)="onCreate()"
(change)="onChange()"
(actionComplete)="updateValue()">
</ejs-richtexteditor>
</div>
</ng-template>
</e-pane>
<e-pane cssClass="pane2" min="40%">
<ng-template #content>
<div class="heading right">
<h6 class="title"><b>Markdown Preview</b></h6>
<div class="splitter-default-content source-code pane2"
style="padding: 20px;"></div>
</div>
</ng-template>
</e-pane>
</e-panes>
</ejs-splitter>
</div>
`,
providers: [ToolbarService, LinkService, ImageService, MarkdownEditorService, TableService]
})
export class AppComponent {
@ViewChild('markdown') public editorObj?: RichTextEditorComponent;
@ViewChild('splitterInstance') public splitterObj!: SplitterComponent;
public textArea?: HTMLTextAreaElement;
public srcArea: any;
public mode: EditorMode = 'Markdown';
public tools: ToolbarSettingsModel = {
enableFloating: false,
items: [
'Bold', 'Italic', 'StrikeThrough', '|',
'Formats', 'Blockquote', 'OrderedList', 'UnorderedList', '|',
'CreateLink', 'Image', 'CreateTable', '|',
'Undo', 'Redo'
]
};
public value: string =
'In Rich Text Editor, you click the toolbar buttons to format the words and the changes are visible immediately. ' +
'Markdown is not like that. When you format the word in Markdown format, you need to add Markdown syntax to the word ' +
'to indicate which words and phrases should look different from each other. ' +
'Rich Text Editor supports markdown editing when the editorMode set as **markdown** and using both ' +
'*keyboard interaction* and *toolbar action*, you can apply the formatting to text.';
public resizing(): void {
this.editorObj!.refreshUI();
}
public updateOrientation(): void {
if (Browser.isDevice) {
(this.splitterObj as any).orientation = 'Vertical';
(document.body.querySelector('.heading') as HTMLElement).style.width = 'auto';
}
}
public onCreate(): void {
setTimeout(() => {
this.editorObj!.refreshUI();
this.textArea = (this.editorObj!.contentModule as ContentRender)
.getEditPanel() as HTMLTextAreaElement;
this.srcArea = document.querySelector('.source-code');
this.updateValue();
}, 0);
}
public onChange(): void {
this.updateValue();
}
public updateValue(): void {
this.srcArea.innerHTML = MarkdownConverter.toHtml(
((this.editorObj!.contentModule as ContentRender)
.getEditPanel() as HTMLTextAreaElement).value
) as string;
}
}// src/main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));MarkdownConverter.toHtml() API
The toHtml method is the core API of the Syncfusion Markdown Converter. It converts a Markdown string into clean, semantic HTML.
Method Signature
MarkdownConverter.toHtml(
markdownContent: string,
options?: MarkdownConverterOptions
): string| Parameter | Type | Required | Description |
|---|---|---|---|
markdownContent | string | ✓ | The Markdown text to convert |
options | MarkdownConverterOptions | ✗ | Optional configuration (see configurable-options.md) |
Returns: string — the converted HTML markup.
Import
import { MarkdownConverter } from '@syncfusion/ej2-markdown-converter';Basic Usage
import { MarkdownConverter } from '@syncfusion/ej2-markdown-converter';
const markdownContent = '# Hello World\nThis is **Markdown** text.';
const htmlOutput = MarkdownConverter.toHtml(markdownContent);
console.log(htmlOutput);
// Output: <h1>Hello World</h1><p>This is <strong>Markdown</strong> text.</p>Supported Markdown Elements
toHtml handles all common Markdown syntax out of the box:
| Markdown Syntax | HTML Output |
|---|---|
# Heading 1 | <h1>Heading 1</h1> |
## Heading 2 | <h2>Heading 2</h2> |
**bold** | <strong>bold</strong> |
*italic* or _italic_ | <em>italic</em> |
~~strikethrough~~ | <del>strikethrough</del> |
[link](url) | <a href="url">link</a> |
 | <img alt="alt" src="src"> |
` inline code ` | <code>inline code</code> |
> blockquote | <blockquote>blockquote</blockquote> |
- item or + item | <ul><li>item</li></ul> |
1. item | <ol><li>item</li></ol> |
--- | <hr> |
| GFM tables | <table>...</table> |
Fenced code blocks ( ` ) | <pre><code>...</code></pre> |
GitHub Flavored Markdown (GFM) is enabled by default, which adds support for tables, strikethrough, and task lists. Disable it by passing { gfm: false } in options.Using the Return Value in Angular
Binding to innerHTML
The most common usage is setting the innerHTML of a preview element:
import { Component } from '@angular/core';
import { MarkdownConverter } from '@syncfusion/ej2-markdown-converter';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
@Component({
standalone: true,
selector: 'app-root',
template: `
<textarea (input)="onInput($event)"></textarea>
<div [innerHTML]="previewHtml"></div>
`
})
export class AppComponent {
public previewHtml: SafeHtml = '';
constructor(private sanitizer: DomSanitizer) {}
public onInput(event: Event): void {
const markdown = (event.target as HTMLTextAreaElement).value;
const html = MarkdownConverter.toHtml(markdown) as string;
this.previewHtml = this.sanitizer.bypassSecurityTrustHtml(html);
}
}Security note: When binding converted HTML to[innerHTML], use Angular'sDomSanitizer.bypassSecurityTrustHtml()only for trusted content. For user-generated content from unknown sources, sanitize the HTML output before binding.
Direct DOM Manipulation
When working with the Rich Text Editor, direct DOM assignment is typical:
const previewEl = document.getElementById('html-preview') as HTMLElement;
previewEl.innerHTML = MarkdownConverter.toHtml(markdownString) as string;Edge Cases
- Empty string:
toHtml('')returns an empty string — no error thrown. - Invalid Markdown: By default, the converter attempts best-effort conversion. Pass
{ silence: true }to suppress any errors on malformed input. - Large content: For large documents, pass
{ async: true }to avoid blocking the main thread. - Custom list syntax: If using
MarkdownFormatterwith custom list tags (e.g.,'+ 'for unordered), thetoHtmloutput reflects those custom tags correctly.