markdown-parser-react
v3.0.0
Published
A lightweight and configurable Markdown renderer for React and Next.js with syntax highlighting, definition lists, images, math and table support.
Maintainers
Readme
Markdown Parser React
A flexible and feature-rich React component for rendering Markdown content with customizable styling, extensive formatting options, and robust typings.

Features
Full Markdown syntax support
Token-based React Renderer (No
dangerouslySetInnerHTML)Customizable styling with CSS classes and inline styles
Advanced Component Overrides for any elements
HTML sanitization (enabled by default)
Accessibility support (WCAG compliant)
Responsive image handling
Syntax highlighting for code blocks
Task list support
Table support with alignment options
Custom link handling
Definition lists
Custom IDs for headers
Nested list support
Mathematical blocks (
$$) and inline math ($)GitHub-style Alerts (
> [!NOTE])Footnote support (
[^1])
Installation
Install Markdown Parser React using npm or yarn or pnpm:
npm install markdown-parser-react
# or
yarn add markdown-parser-react
# or
pnpm add markdown-parser-reactBasic Usage
The basic usage example demonstrates rendering a simple Markdown string:
import Markdown from "markdown-parser-react";
function MyComponent() {
return (
<Markdown
content={`# Hello World
This is **markdown** content.`}
/>
);
}Advanced Usage
In the advanced usage example, we see how you can configure the component with custom styling, classes, and additional features like task lists, code highlighting, and tables
import Markdown from "markdown-parser-react";
function BlogPost() {
const markdownContent = `
# Welcome to My Blog
> [!TIP]
> This is a modern markdown parser using React nodes!
This is a _formatted_ paragraph with a [link](https://example.com).
- [x] Task 1
- [ ] Task 2
\`\`\`javascript
const hello = "world";
console.log(hello);
\`\`\`
| Column 1 | Column 2 |
|----------|----------|
| Cell 1 | Cell 2 |
`;
return (
<Markdown
content={markdownContent}
options={{
customClasses: {
headings: "blog-heading",
paragraphs: "blog-paragraph",
},
customStyles: {
headings: {
color: "#2c3e50",
fontFamily: "Georgia, serif",
},
},
linkTarget: "_blank",
sanitizeHtml: true,
maxNestingLevel: 4,
}}
className="blog-content"
asArticle={true}
aria={{
label: "Blog post content",
describedBy: "blog-description",
}}
/>
);
}Usage with Next.js
If you're using Next.js, you may encounter the "Text content does not match server-rendered HTML" error.
To avoid this issue, you can use next/dynamic to dynamically import the Markdown component, ensuring that it is only rendered on the client-side.
Here's how to use Markdown with Next.js:
import dynamic from "next/dynamic";
const Markdown = dynamic(
() => import("markdown-parser-react").then((m) => m),
{ ssr: false }
);
interface MyComponentProps {
content: string;
options?: {
langPrefix?: string;
linkTarget?: string;
};
}
export const MyComponent: React.FC<MyComponentProps> = ({
content,
options,
}) => {
return (
<div>
<Markdown content={content} options={options} />
</div>
);
};By using the next/dynamic function and passing ssr: false, we ensure that the Markdown component is only rendered on the client-side, preventing the mismatch error between server-rendered and client-rendered HTML in Next.js projects.
[!NOTE]
Since the latest version uses a token-based React renderer, many hydration issues are naturally mitigated. However, if you use custom components that rely on browser APIs,
next/dynamicis still recommended.
Security & Performance: Token-based Rendering
Unlike many markdown parsers that rely on dangerouslySetInnerHTML, this package uses a token-based React renderer.
Safer: It directly creates React elements (
React.createElement), making it inherently immune to most XSS attack vectors that target raw HTML injection.Faster: By avoiding string-to-HTML parsing in the browser, it leverages React's virtual DOM more efficiently.
Highly Configurable: Since every node is a React component, you can intercept and modify any part of the rendering tree.
Configuration Options
Props
The MarkdownProps interface defines the properties that can be passed into the component. These props allow you to customize the behavior, appearance, and accessibility of the rendered Markdown.
Component Props
| Prop | Type | Description | Example |
| :-------------- | :-------------- | :------------------------------------------------- | :---------------------------- |
| content | string | The Markdown content to be rendered. | content="# Hello" |
| options | ParseOptions | Configuration options for the parser. | options={{ ... }} |
| className | string | Additional CSS class for the container. | className="markdown-body" |
| style | CSSProperties | Custom styles for the container. | style={{ padding: 20 }} |
| asArticle | boolean | Wrap in <article> instead of <div>. | asArticle={true} |
| id | string | Custom ID for the container. | id="post-content" |
| aria | object | Accessibility attributes (label, describedBy). | aria={{ label: 'Article' }} |
ParseOptions
The ParseOptions interface provides configuration for parsing and rendering the Markdown content. It gives you the ability to customize how the content is parsed and displayed, including applying custom classes, styles, and controlling link behavior.
| Option | Type | Description | Example |
| :-------------------- | :----------------- | :------------------------------- | :------------------------------ |
| langPrefix | string | Prefix for code block classes. | langPrefix="lang-" |
| customClasses | CustomClasses | Custom CSS classes for elements. | { headings: 'my-h' } |
| customStyles | CustomStyles | Custom CSS styles for elements. | { paragraphs: { margin: 0 } } |
| linkTarget | string | How links open (_blank, etc). | linkTarget="_self" |
| sanitizeHtml | boolean | Sanitize HTML input. | sanitizeHtml={false} |
| maxNestingLevel | number | Max list nesting depth. | maxNestingLevel={3} |
| components | CustomComponents | Element component overrides. | { h1: MyH1 } |
| onRenderMath | Function | Custom LaTeX/TeX renderer. | (tex, block) => <Math /> |
| onRenderCode | Function | Custom syntax highlighter. | (code, lang) => <High /> |
Supported Markdown Features
Basic Formatting
Headers (H1-H6)
Bold and Italic text
Strikethrough
Links
Images
Blockquotes with citations
Ordered and unordered lists
Code blocks with syntax highlighting
Extended Features
Task lists with checkboxes
Tables with alignment options
Definition lists
Custom header IDs
Math equations (Inline
$x$and Block$$x$$)GitHub-style Alerts (
> [!NOTE])Footnotes (
[^1])Superscript (
^...^)Subscript (
~...~)Highlighted text (
==...==)
Code Block Example
```javascript
function hello() {
console.log("Hello, world!");
}
```Table Example
| Left | Center | Right |
| :--- | :----: | ----: |
| L1 | C1 | R1 |Customization
You can customize how the Markdown content is displayed by adjusting the appearance of different elements like headings, paragraphs, links, and more. Below are the options for customizing the styles and classes.
Custom Classes
You can pass your classNames to customClasses config inside the options object passed as props to the component
| Element | Type | Description |
| :---------------- | :------- | :---------------------- |
| headings | string | Classes for H1-H6. |
| paragraphs | string | Classes for P. |
| lists | string | Classes for UL/OL/LI. |
| blockquotes | string | Classes for BLOCKQUOTE. |
| codeBlocks | string | Classes for PRE/CODE. |
| tables | string | Classes for TABLE. |
| links | string | Classes for A. |
| images | string | Classes for IMG. |
Custom Styles
You can pass your styles to the customStyles property inside the option object.
| Element | Type | Description |
| :---------------- | :-------------- | :---------------------- |
| headings | CSSProperties | Styles for H1-H6. |
| paragraphs | CSSProperties | Styles for P. |
| lists | CSSProperties | Styles for lists. |
| blockquotes | CSSProperties | Styles for blockquotes. |
| codeBlocks | CSSProperties | Styles for code blocks. |
| tables | CSSProperties | Styles for tables. |
| links | CSSProperties | Styles for links. |
| images | CSSProperties | Styles for images. |
Advanced Customization: Component Overrides
The components prop in options allows you to completely replace the default markdown elements with your own React components. This is perfect for integrating with UI libraries like Shadcn UI, MUI, or Radix UI.
<Markdown
content="# Hello World"
options={{
components: {
// Override H1 with a custom styled component
h1: ({ children }) => (
<h1 className="text-4xl font-black text-indigo-600 mb-4">{children}</h1>
),
// Use a custom Link component for internal navigation
a: ({ href, children }) => <CustomLink to={href}>{children}</CustomLink>,
// Customize image rendering
img: (props) => (
<img {...props} className="rounded-lg shadow-xl" loading="lazy" />
),
// Override mathematical rendering (e.g. using KaTeX)
math: ({ content, isBlock }) => (
<MyMathRenderer tex={content} block={isBlock} />
),
// Customize GitHub Alerts
alert: ({ type, children }) => (
<div
className={`alert alert-${type.toLowerCase()} p-4 border-l-4 my-4 bg-gray-50`}
>
<span className="font-bold uppercase mr-2">{type}:</span>
{children}
</div>
),
},
}}
/><Markdown
content={content}
options={{
onRenderCode: (code, language) => {
return <div className="p-4 bg-slate-900 text-white rounded">{code}</div>;
},
}}
/>Pro Examples
Here are some real-world examples of how to extend markdown-parser-react for your specific needs.
Mathematical Rendering (with KaTeX)
Integrate KaTeX for beautiful, high-performance mathematical typesetting.
import "katex/dist/katex.min.css";
import { InlineMath, BlockMath } from "react-katex";
<Markdown
content="The equation is $E=mc^2$"
options={{
onRenderMath: (content, isBlock) =>
isBlock ? <BlockMath math={content} /> : <InlineMath math={content} />,
}}
/>;Advanced Syntax Highlighting (with PrismJS)
Use PrismJS or react-syntax-highlighter for professional-grade code blocks.
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
import { oneDark } from "react-syntax-highlighter/dist/esm/styles/prism";
<Markdown
content={myCode}
options={{
onRenderCode: (code, language) => (
<SyntaxHighlighter language={language} style={oneDark}>
{code}
</SyntaxHighlighter>
),
}}
/>;Custom Alert Components
Theme-aware alerts with custom icons using the alert component override.
const CustomAlert = ({ type, children }) => {
const icons = {
NOTE: "📝",
TIP: "💡",
IMPORTANT: "📌",
WARNING: "⚠️",
CAUTION: "🛑",
};
return (
<div className={`my-alert alert-${type.toLowerCase()}`}>
<span className="icon">{icons[type] || icons.NOTE}</span>
<div className="content">{children}</div>
</div>
);
};
<Markdown
content={"> [!TIP]\n> Always use specific keys for lists!"}
options={{
components: {
alert: CustomAlert,
},
}}
/>;Managing Footnotes
By default, footnotes are rendered as links. You can capture them in a separate container for a traditional "bottom-of-page" feel.
/*
Markdown Input:
This is a statement[^1].
[^1]: This is the source.
*/
// In your CSS (Tailwind or standard CSS):
.footnote-ref {
vertical-align: super;
font-size: 0.75em;
color: #4f46e5; /* indigo-600 */
margin-left: 0.1rem;
text-decoration: none;
}
.footnote-ref:hover {
text-decoration: underline;
}
#footnotes {
border-top: 1px solid #e5e7eb; /* slate-200 */
margin-top: 3rem;
padding-top: 1.5rem;
font-size: 0.875em;
color: #4b5563; /* slate-600 */
}
Default Styling
The component comes with default styles that can be imported:
import { createGlobalStyle } from "styled-components";
import { defaultStyles } from "markdown-parser-react";
// In your global CSS or styled-components
const GlobalStyle = createGlobalStyle`
/* Inject base markdown styles */
${defaultStyles}
`;
export default GlobalStyle;Accessibility
The component follows WCAG guidelines and provides:
Semantic HTML structure
ARIA attributes support
Keyboard navigation for interactive elements
Screen reader-friendly content structure
Browser Support
Chrome (latest)
Firefox (latest)
Safari (latest)
Edge (latest)
IE11 (with appropriate polyfills)
Contributing
Contributions are welcome! Please read our contributing guidelines for more information.
Issues
If you encounter any issues or have suggestions for improvements, please report them on the GitHub Issues page
Work with Us
Code Media Labs is a multidisciplinary studio uniting Design, Media, Software, and Legal expertise to create thoughtful, future-ready digital experiences. We partner with brands to strengthen their identity, streamline operations, and unlock long-term growth through functional and innovative solutions.
License
This project is licensed under the MIT License. See the LICENSE file for details.
Happy Coding Everyone!
