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

@domeadev/react-markdown

v0.0.2

Published

A lightweight, customizable React component for rendering Markdown content with TypeScript support and extensible rendering.

Readme

@domeadev/react-markdown

A lightweight, customizable React component for rendering Markdown content with TypeScript support and extensible rendering.

Features

  • 🚀 Fast and Lightweight: Built on top of marked for efficient parsing
  • 🎨 Fully Customizable: Override any element renderer with custom React components
  • 🔧 TypeScript Support: Full type safety with comprehensive TypeScript definitions
  • 🧩 Extensible: Support for custom extensions and element types
  • 📝 GFM Support: GitHub Flavored Markdown support out of the box
  • 📚 Storybook: Interactive examples and documentation

📖 Documentation & Examples

View Live Storybook Documentation →

Explore interactive examples, API documentation, and usage patterns in our Storybook deployment.

Installation

npm

npm install @domeadev/react-markdown

yarn

yarn add @domeadev/react-markdown

pnpm

pnpm add @domeadev/react-markdown

Quick Start

import { ReactMarkdown, useReactMarkdown } from "@domeadev/react-markdown";

function MyComponent() {
  const markdown = `
# Hello World

This is **bold** text and this is *italic* text.

- List item 1
- List item 2
- [ ] Todo item
- [x] Completed item

[Link to example](https://example.com)
  `;

  const { elements, renders } = useReactMarkdown(markdown);

  return <ReactMarkdown elements={elements} renders={renders} />;
}

API Reference

useReactMarkdown Hook

The main hook for parsing markdown content.

const { elements, renders } = useReactMarkdown(markdown, options);

Parameters

  • markdown (string): The markdown content to parse
  • options (optional): Configuration options

Options

interface ReactMarkdownOptions {
  /** Enable GitHub Flavored Markdown @default true */
  gfm?: boolean;
  /** Handle line breaks */
  breaks?: boolean;
  /** Custom extensions */
  extensions?: ReactMarkdownExtension[];
  /** Override default element renderers */
  renders?: Partial<DefaultElementRenders>;
}

ReactMarkdown Component

The main component for rendering parsed markdown elements.

<ReactMarkdown elements={elements} renders={renders} />

Props

  • elements: Parsed markdown elements from useReactMarkdown
  • renders: Element renderers (default + custom overrides)

Customizing Renderers

You can customize how any markdown element is rendered:

import { ReactMarkdown, useReactMarkdown } from "@domeadev/react-markdown";

function CustomMarkdown() {
  const markdown = "# Custom Heading\n\nThis is a **bold** paragraph.";

  const { elements } = useReactMarkdown(markdown, {
    renders: {
      // Custom heading renderer
      heading: ({ element, children }) => {
        const headingElement = element as MarkdownHeadingElement;
        return (
          <h1 className={`custom-h${headingElement.depth}`}>🎉 {children}</h1>
        );
      },
      // Custom paragraph renderer
      paragraph: ({ children }) => (
        <p className="custom-paragraph">{children}</p>
      ),
      // Custom strong (bold) renderer
      strong: ({ children }) => (
        <span className="font-bold text-blue-600">{children}</span>
      ),
    },
  });

  return <ReactMarkdown elements={elements} renders={renders} />;
}

Available Element Types

The following markdown elements are supported with default renderers:

| Element | Description | Custom Props | | -------------- | ----------------------- | -------------------------------------- | | heading | H1-H6 headings | depth: 1-6 | | paragraph | Paragraph text | - | | list | Ordered/unordered lists | ordered: boolean | | list_item | List items | task: boolean, checked?: boolean | | link | Links | href: string | | image | Images | src: string, alt: string | | code | Code blocks | lang?: string | | codespan | Inline code | - | | strong | Bold text | - | | emphasis | Italic text | - | | delete | Strikethrough text | - | | blockquote | Block quotes | - | | table | Tables | align: TableAlign[] | | table_header | Table header | - | | table_body | Table body | - | | table_row | Table row | - | | table_cell | Table cell | header: boolean, align: TableAlign | | br | Line break | - | | hr | Horizontal rule | - | | text | Plain text | - | | space | Whitespace | - |

Creating Extensions

You can create custom extensions to handle new markdown syntax:

import { ReactMarkdownExtension } from "@domeadev/react-markdown";

// Example: Custom mention extension
const mentionExtension: ReactMarkdownExtension = {
  name: "mention",
  level: "inline",
  start(src: string) {
    return src.indexOf("@");
  },
  tokenizer(src: string) {
    // Match @username pattern (letters, numbers, underscore, hyphen)
    const rule = /^@([a-zA-Z0-9_-]+)/;
    const match = rule.exec(src);

    if (match) {
      return {
        type: "mention",
        raw: match[0],
        username: match[1],
      };
    }
    return undefined;
  },
  parser: (token) => ({
    type: "mention",
    text: token.raw,
    username: token.username,
  }),
  render: ({ element }) => <span className="mention">@{element.username}</span>,
};

const { elements, renders } = useReactMarkdown(markdown, {
  extensions: [mentionExtension],
});

Advanced Usage

With Custom Styling

import { ReactMarkdown, useReactMarkdown } from "@domeadev/react-markdown";
import "./markdown-styles.css";

function StyledMarkdown({ content }: { content: string }) {
  const { elements, renders } = useReactMarkdown(content, {
    renders: {
      heading: ({ element, children }) => {
        const HeadingTag = `h${element.depth}` as keyof JSX.IntrinsicElements;
        return (
          <HeadingTag className={`heading-${element.depth} mb-4 font-bold`}>
            {children}
          </HeadingTag>
        );
      },
      code: ({ element }) => (
        <pre className="bg-gray-100 p-4 rounded-lg overflow-x-auto">
          <code className={`language-${element.lang || "text"}`}>
            {element.text}
          </code>
        </pre>
      ),
      link: ({ element, children }) => (
        <a
          href={element.href}
          className="text-blue-600 hover:text-blue-800 underline"
          target="_blank"
          rel="noopener noreferrer"
        >
          {children}
        </a>
      ),
    },
  });

  return (
    <div className="prose prose-lg max-w-none">
      <ReactMarkdown elements={elements} renders={renders} />
    </div>
  );
}

With Task Lists

function TaskListExample() {
  const todoMarkdown = `
## My Todo List

- [x] Complete the documentation
- [x] Add TypeScript support
- [ ] Write more tests
- [ ] Add more examples
  `;

  const { elements, renders } = useReactMarkdown(todoMarkdown, {
    renders: {
      list_item: ({ element, children }) => (
        <li className="flex items-center gap-2">
          {element.task && (
            <input
              type="checkbox"
              checked={element.checked}
              className="form-checkbox h-4 w-4 text-blue-600"
              readOnly
            />
          )}
          <span className={element.checked ? "line-through text-gray-500" : ""}>
            {children}
          </span>
        </li>
      ),
    },
  });

  return <ReactMarkdown elements={elements} renders={renders} />;
}

Development

Build

pnpm build

Test

pnpm test

Storybook Development

Start the development server:

pnpm storybook

Build Storybook for production:

pnpm build-storybook

The Storybook documentation is automatically deployed to GitHub Pages on every push to the main branch.

GitHub Pages Setup

For repository maintainers, the GitHub Pages deployment is handled automatically via GitHub Actions. To enable this:

  1. Go to your repository's SettingsPages
  2. Set Source to "GitHub Actions"
  3. The workflow will automatically deploy Storybook to https://[username].github.io/[repository-name]/

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT

Dependencies

Related Packages

  • @domeadev/react-elements-renderer - The underlying element rendering engine