Markdown to HTML Conversion — marked, markdown-it, and Showdown
Convert Markdown to HTML in JavaScript using marked, markdown-it, and Showdown. Includes syntax highlighting with highlight.js, sanitizing output, custom renderers, and...
Use the tool
Markdown Preview
Live Markdown preview with GitHub-flavored syntax. Tables, task lists, code blocks, strikethrough. Side-by-side editor and rendered output.
Converting Markdown to HTML requires a parser library — the choice depends on whether you need speed, extensibility, security, or specific GFM features.
Use the Markdown Preview to render Markdown instantly in the browser.
marked — fast and simple
import { marked } from 'marked'; // npm install marked
const markdown = `# Hello World\n\nThis is **bold** and *italic*.`;
// Basic conversion:
const html = marked.parse(markdown);
// <h1>Hello World</h1><p>This is <strong>bold</strong> and <em>italic</em>.</p>
// Async version (if using extensions):
const html = await marked.parseInline(markdown);
markdown-it — extensible and safe
import MarkdownIt from 'markdown-it'; // npm install markdown-it
const md = new MarkdownIt({
html: false, // Disable raw HTML (safer)
xhtmlOut: false,
breaks: false, // \n becomes <br>
linkify: true, // Auto-link URLs
typographer: true, // Smart quotes, em-dashes
});
const html = md.render('# Hello\n\nSome **text**.');
// Enable GFM tables and strikethrough:
import mdTaskLists from 'markdown-it-task-lists';
import mdMark from 'markdown-it-mark'; // ==highlight==
md.use(mdTaskLists, { enabled: true });
md.use(mdMark);
Syntax highlighting with highlight.js
import MarkdownIt from 'markdown-it';
import hljs from 'highlight.js'; // npm install highlight.js
const md = new MarkdownIt({
highlight: function(code, lang) {
if (lang && hljs.getLanguage(lang)) {
try {
return '<pre><code class="hljs">' +
hljs.highlight(code, { language: lang, ignoreIllegals: true }).value +
'</code></pre>';
} catch {}
}
return '<pre><code class="hljs">' +
hljs.highlightAuto(code).value +
'</code></pre>';
},
});
// Add highlight.js CSS to your page:
// import 'highlight.js/styles/github.css';
Sanitizing HTML output (security)
Never render untrusted Markdown without sanitization — a user could inject <script> tags:
import { marked } from 'marked';
import DOMPurify from 'dompurify'; // npm install dompurify
// Client-side:
function safeMarkdown(markdown) {
const rawHtml = marked.parse(markdown);
return DOMPurify.sanitize(rawHtml, {
ALLOWED_TAGS: ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
'strong', 'em', 'code', 'pre', 'blockquote',
'ul', 'ol', 'li', 'a', 'img', 'table',
'thead', 'tbody', 'tr', 'th', 'td', 'hr', 'br'],
ALLOWED_ATTR: ['href', 'src', 'alt', 'class', 'title'],
});
}
// Server-side: use 'sanitize-html' instead of DOMPurify
import sanitizeHtml from 'sanitize-html'; // npm install sanitize-html
function safeMarkdownSSR(markdown) {
const rawHtml = marked.parse(markdown);
return sanitizeHtml(rawHtml, {
allowedTags: sanitizeHtml.defaults.allowedTags.concat(['img', 'h1', 'h2']),
allowedAttributes: { 'a': ['href', 'title'], 'img': ['src', 'alt'] },
});
}
Custom renderers in marked
import { marked } from 'marked';
// Override how specific elements render:
const renderer = {
// Add target="_blank" and rel to external links:
link(href, title, text) {
const isExternal = href.startsWith('http');
const attrs = isExternal
? ` target="_blank" rel="noopener noreferrer"`
: '';
return `<a href="${href}"${title ? ` title="${title}"` : ''}${attrs}>${text}</a>`;
},
// Add ID to headings for anchor links:
heading(text, level) {
const id = text.toLowerCase().replace(/[^a-z0-9]+/g, '-');
return `<h${level} id="${id}">${text}</h${level}>`;
},
// Lazy-load images:
image(href, title, text) {
return `<img src="${href}" alt="${text}" loading="lazy"${title ? ` title="${title}"` : ''}>`;
},
};
marked.use({ renderer });
React: render Markdown safely
import { marked } from 'marked';
import DOMPurify from 'dompurify';
function MarkdownRenderer({ content }) {
const html = DOMPurify.sanitize(marked.parse(content));
return <div dangerouslySetInnerHTML={{ __html: html }} />;
}
// Or use react-markdown (no dangerouslySetInnerHTML needed):
// npm install react-markdown
import ReactMarkdown from 'react-markdown';
function BlogPost({ content }) {
return <ReactMarkdown>{content}</ReactMarkdown>;
}
Node.js: convert markdown files
import { marked } from 'marked';
import { readFile, writeFile } from 'fs/promises';
import { glob } from 'glob';
async function convertAll() {
const files = await glob('content/**/*.md');
for (const file of files) {
const markdown = await readFile(file, 'utf-8');
const html = marked.parse(markdown);
const outFile = file.replace('.md', '.html');
await writeFile(outFile, `<!DOCTYPE html><html><body>${html}</body></html>`);
console.log(`Converted: ${file} → ${outFile}`);
}
}
convertAll();
Library comparison
| Library | Speed | GFM | Extensions | Size |
|---|---|---|---|---|
marked | Very fast | Yes | Limited | ~43KB |
markdown-it | Fast | With plugins | Excellent | ~60KB |
showdown | Moderate | Partial | Good | ~58KB |
unified/remark | Moderate | Yes | Excellent | Large |
micromark | Fastest | Yes | Composable | ~25KB |
Related tools
- Markdown Preview — render Markdown in the browser
- Markdown Code Blocks — fenced code block syntax
- Markdown for Documentation — docs site setup
Related posts
- Markdown Cheatsheet — Every Syntax Element with Examples — Markdown uses simple symbols for headings, bold, links, code, and tables. Here's…
- Markdown Code Blocks — Syntax Highlighting and Fenced Code — Markdown code blocks use triple backticks to display formatted code. Add a langu…
- Markdown Editor Online — Write and Preview Markdown Instantly — An online Markdown editor shows the rendered output as you type, so you don't ne…
- Markdown for Documentation — Structuring Technical Docs with Markdown — Markdown is the standard format for technical documentation. Here's how to struc…
- GitHub Markdown — Features Specific to GitHub Flavored Markdown — GitHub Flavored Markdown (GFM) extends standard Markdown with task lists, mentio…
Related tool
Markdown Preview
Live Markdown preview with GitHub-flavored syntax. Tables, task lists, code blocks, strikethrough. Side-by-side editor and rendered output.
Written by Mian Ali Khalid. Part of the Dev Productivity pillar.