markdown-it and marked are powerful engines designed to convert Markdown text into HTML, enabling rich content rendering in web applications. markdown-it is known for its extreme extensibility and plugin ecosystem, allowing developers to customize the parsing rules and output format deeply. marked focuses on speed and simplicity, offering a lightweight solution that works well out-of-the-box for standard CommonMark specifications. Conversely, remove-markdown and strip-markdown serve the opposite purpose: they strip Markdown syntax to produce plain text. remove-markdown is a legacy utility often used for simple sanitization, while strip-markdown offers a more modern, robust approach to extracting readable text from Markdown sources without the overhead of a full HTML parser.
When building content-driven frontend applications, you will inevitably face the need to process Markdown. Whether you are rendering a blog post, generating SEO meta descriptions, or sanitizing user input, the choice of library defines your security posture and performance characteristics. The ecosystem splits into two distinct categories: parsers that convert Markdown to HTML (markdown-it, marked) and strippers that convert Markdown to plain text (remove-markdown, strip-markdown). Let's dive into how these tools differ under the hood and when to use them.
Both markdown-it and marked turn Markdown into HTML, but they take very different architectural approaches. One prioritizes flexibility, while the other prioritizes speed and simplicity.
markdown-it: The Extensible Powerhousemarkdown-it is built with a plugin-first architecture. It does not just parse Markdown; it allows you to rewrite the parsing rules themselves. This makes it incredibly powerful for teams that need to support non-standard syntax or custom components.
If you need to add a specific feature, like a custom warning block or a specialized image handler, markdown-it lets you inject a plugin directly into the parsing chain.
import MarkdownIt from 'markdown-it';
// Initialize with options
const md = new MarkdownIt({
html: true, // Enable HTML tags in source
linkify: true, // Autoconvert URL-like text to links
typographer: true // Enable smartquotes and other typographic replacements
});
// Add a custom plugin for blockquotes
md.use((md) => {
md.core.ruler.push('replace_blockquote', (state) => {
// Custom logic to modify tokens
state.tokens.forEach(token => {
if (token.type === 'blockquote_open') {
token.attrPush(['class', 'custom-warning']);
}
});
});
});
const result = md.render('> This is a warning');
// Output: <blockquote class="custom-warning">...</blockquote>
When to use: Choose markdown-it when your requirements go beyond standard Markdown. If you are building a CMS where users expect custom shortcodes, or if you need to sanitize output with granular control over every token, this is your tool. The trade-off is a slightly larger bundle size and a steeper learning curve for writing plugins.
marked: The Speed Specialistmarked takes a different approach. It aims to be fast and compliant with the CommonMark specification without requiring complex configuration. It works great out of the box and is often the default choice for simple documentation viewers.
While it supports extensions, they are generally simpler to implement than markdown-it plugins, focusing on overriding specific renderers rather than altering the core parsing logic.
import { marked } from 'marked';
// Basic usage - fast and simple
const html = marked.parse('# Hello World');
// Customizing a renderer (e.g., adding target="_blank" to links)
const renderer = new marked.Renderer();
renderer.link = (href, title, text) => {
return `<a target="_blank" href="${href}">${text}</a>`;
};
const customHtml = marked.parse('[Link](https://example.com)', { renderer });
When to use: Choose marked for performance-critical applications where you need to parse large volumes of standard Markdown quickly. It is perfect for static site generators, README viewers, or any scenario where you don't need to invent new syntax. It is easier to set up but less flexible if you need to deviate from standard behavior.
Sometimes you don't want HTML at all. You might need plain text for a meta description, a social media preview, or a search index. Generating HTML just to strip it is inefficient and can introduce security risks if not handled carefully. This is where dedicated stripping libraries come in.
remove-markdown: The Legacy Utilityremove-markdown is a simple, synchronous function that uses regular expressions to strip Markdown syntax. It has been around for a long time and is widely known, but it shows its age in how it handles edge cases.
Because it relies on regex, it can struggle with complex nested structures or unusual formatting. It is best suited for quick scripts or legacy codebases where changing dependencies is risky.
import removeMd from 'remove-markdown';
const markdown = '# Header\n\nThis is **bold** and *italic*.';
const text = removeMd(markdown);
// Output: "Header\n\nThis is bold and italic."
When to use: Only choose remove-markdown if you are maintaining an older project that already depends on it, or if you need a zero-dependency solution for very simple strings. For new projects, its lack of active maintenance and regex-based limitations make it a risky choice for production data processing.
strip-markdown: The Modern Standardstrip-markdown is designed to be a more robust alternative. It handles the conversion from Markdown to plain text more reliably, often dealing with edge cases that regex-based solutions miss. It is actively maintained and focuses specifically on the "stripping" use case without the bloat of a full parser.
It provides a cleaner API and better guarantees about the output format, making it safer for generating user-facing previews.
import stripMarkdown from 'strip-markdown';
const markdown = '# Title\n\n- List item 1\n- List item 2\n\n[Link](url)';
// Returns a promise in some versions, or direct string depending on build
const text = await stripMarkdown(markdown);
// Output: "Title\n\nList item 1\nList item 2\nLink"
When to use: Choose strip-markdown for any new architecture that requires plain text extraction. Whether you are generating Open Graph descriptions, indexing content for search, or creating email summaries, this library offers better reliability and security than its older counterparts.
The choice between these packages often comes down to what you are trying to achieve: rich rendering or safe text extraction.
When using markdown-it or marked, remember that they output HTML. If your Markdown source comes from users, you must sanitize the output to prevent Cross-Site Scripting (XSS) attacks. Neither package sanitizes HTML by default.
// β οΈ DANGEROUS: User input with script tag
const userInput = '# Hello\n\n<script>alert("XSS")</script>';
// Both markdown-it and marked will render the script tag by default
const unsafeHtml = marked.parse(userInput);
// β
SAFE: Use a sanitizer like DOMPurify
import DOMPurify from 'dompurify';
const safeHtml = DOMPurify.sanitize(marked.parse(userInput));
markdown-it gives you more hooks to implement security rules during parsing, while marked relies on you to sanitize the final string. If security is your top priority and you need fine-grained control, markdown-it combined with a strict plugin set is often the architectural choice for enterprise systems.
Using strip-markdown or remove-markdown is inherently safer for text-only contexts because they never generate HTML. This eliminates the XSS vector entirely for that specific data flow. It is also faster because you skip the HTML serialization step.
If your goal is to show a "read more" preview in a card layout, do not render to HTML and then hide it. Strip the markdown first:
// β
Efficient pattern for previews
import stripMarkdown from 'strip-markdown';
async function getPreview(content, length = 100) {
const plainText = await stripMarkdown(content);
return plainText.substring(0, length) + '...';
}
You are building a blog where authors can use custom shortcodes like {% video %} and need strict security.
markdown-it{% video %} tag and render a secure React component. You can also enforce strict HTML filtering rules within the parser chain.You need to render standard README files quickly with zero configuration.
markedYour app generates Twitter/Facebook cards that need a plain text description from a blog post.
strip-markdownstrip-markdown gives you the exact string needed for the meta tag.You are fixing a bug in an old admin panel that displays simple bold/italic notes.
remove-markdownstrip-markdown might introduce unnecessary regression risk.| Feature | markdown-it | marked | remove-markdown | strip-markdown |
|---|---|---|---|---|
| Primary Goal | Render HTML (Extensible) | Render HTML (Fast) | Strip to Text (Legacy) | Strip to Text (Modern) |
| Architecture | Plugin-based Tokenizer | Direct Parser | Regex-based | Robust Parser/Regex |
| Customization | High (Rewrite rules) | Medium (Override renderers) | None | Low |
| Security | Requires Sanitization | Requires Sanitization | Safe (No HTML output) | Safe (No HTML output) |
| Best For | CMS, Custom Syntax | Docs, Standard Content | Legacy Maintenance | Meta Tags, Search Index |
Choosing the right tool depends on whether you need richness or simplicity.
If you need to render rich content with custom features, markdown-it is the architectural heavyweight that grows with your needs. If you just need to render standard docs fast, marked is the lean, efficient choice.
On the flipping side, if you need plain text, always prefer strip-markdown for new projects to ensure reliability and security. Reserve remove-markdown for maintaining older systems where changing the stack is not feasible.
Final Thought: Never mix these purposes. Do not use a stripping library to try and render HTML, and do not use a full HTML parser if you only need a text summary. Matching the tool to the specific data transformation requirement will keep your frontend architecture clean, secure, and performant.
Choose markdown-it if your project requires deep customization, such as adding custom syntax rules, integrating complex plugins, or controlling the exact HTML output structure. It is the best fit for large-scale content platforms where flexibility and extensibility are more critical than raw startup speed.
Choose marked if you need a fast, zero-configuration parser that strictly adheres to CommonMark standards without the complexity of a plugin system. It is ideal for lightweight applications, documentation sites, or scenarios where you just need to render standard Markdown quickly and reliably.
Choose remove-markdown only for legacy projects or extremely simple use cases where you need a quick, synchronous way to strip basic Markdown syntax from a string without installing heavy dependencies. Avoid it for new architectures due to its limited maintenance and lack of advanced edge-case handling.
Choose strip-markdown when you need a reliable, modern utility to convert Markdown into plain text for metadata generation, search indexing, or previews. It handles edge cases better than older alternatives and is preferred when you want to avoid the security risks and performance cost of generating intermediate HTML.
Markdown parser done right. Fast and easy to extend.
[!NOTE] If you are upgrading to v15, see the migration guide.
npm install markdown-it
For a quick look at dist/ folder contents, see https://unpkg.com/markdown-it/.
For browser you can use unpkg.com, esm.sh or any other CDN, which mirror npm
registry.
import MarkdownIt from 'markdown-it'
const md = new MarkdownIt()
const result = md.render('# markdown-it rulezz!')