npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

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.

Readme

Markdown Parser React

A flexible and feature-rich React component for rendering Markdown content with customizable styling, extensive formatting options, and robust typings.

markdown-parser-react

npm npm bundle size

downloads

stars

MIT LicenseCode Coverage

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-react

Basic 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/dynamic is 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!