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

react-mdxutils

v1.5.3

Published

Utilities for MDX content, including anchor extraction.

Readme

react-mdxutils

npm version License: MIT

react-mdxutils is a lightweight and versatile utility package for extracting Table of Contents (TOC) items and a React hook to manage the active heading link based on scroll position.

See Live demo Demo Image

📦 Installation

You can install react-mdxutils using npm:

npm install react-mdxutils

✨ Features

  • Extract Table of Contents: Easily get a structured list of headings (and their slugs) from any MDX or Markdown string.
  • GitHub-compatible Slugs: Generates slugs that are compatible with how GitHub renders heading IDs.
  • Active Heading Tracking Hook: A React hook (useActiveHeading) to automatically highlight the current heading in view as the user scrolls, and manage a dynamic indicator.
  • TypeScript Support: Built with TypeScript for type safety and better developer experience.

🚀 Usage

react-mdxutils provides two main exports: a utility function (generateTocFromMdx) and a React hook (useActiveHeading).

1. generateTocFromMdx(mdxContent: string): TocItem[]

This function modify the generated toc using mdast-util-toc and returns an array of heading objects, suitable for building a perfect Table of Contents.

import { generateTocFromMdx } from "react-mdxutils";
const toc = generateTocFromMdx(mdxContent);

<ul className="leading-7">
  {toc.map((item, i: number) => {
    return (
      <Link href={`#${item.slug}`} key={i} className="">
        <li style={{ marginLeft: `${(item.level - 2) * 10}px` }}>
          {item.content}
        </li>
      </Link>
    );
  })}
</ul>;

How it Works Under the Hood:

generateTocFromMdx acts as a wrapper that orchestrates the robust parsing and slug generation process.

  • Core TOC Generation: It internally leverages mdast-util-toc to parse your MDX content into an Abstract Syntax Tree (AST) and then derive an initial, nested Table of Contents structure from it. This library is a well-established tool in the unified ecosystem for precisely this purpose.

  • Reliable Slug Generation: Critically, generateTocFromMdx ensures that the slug (the unique ID for each heading that enables anchor links) is generated consistently and reliably. It achieves this by utilizing github-slugger. This ensures that the generated slugs for your headings perfectly match the IDs that GitHub and other compliant Markdown renderers would produce, guaranteeing seamless deep-linking within your documentation. The function then flattens this enriched, nested TOC structure into the straightforward TocItem[] array you receive.

In essence, generateTocFromMdx takes care of the complexities of parsing and slugging, providing you with a ready-to-use, robust Table of Contents data structure.

2. useActiveHeading(content: string) React Hook

This hook tracks the currently visible heading in a scrollable area and updates an "active" state, which can be used to highlight the corresponding link in your Table of Contents. It also provides refs for the TOC links, an active indicator element, and the TOC container itself, enabling dynamic visual effects.

Example Usage in a React Component

import { generateTocFromMdx, useActiveHeading } from "react-mdxutils";

const toc = generateTocFromMdx(mdxContent);
const {
activeHeading,
handleActiveHeading,
headingListRefs,
activeIndicatorRef,
asideRef,
} = useActiveHeading(mdxContent);

<aside className="w-[300px] overflow-y-auto" ref={asideRef}>
<ul className="w-full leading-7 relative">
    {toc.map((item, i: number) => {
        return (
        <Link href={`#${item.slug}`} key={i} className="">
            <li
            ref={(el) => {
                headingListRefs.current[item.slug] = el;
            }}
            onClick={() => {
                handleActiveHeading(headingListRefs.current[item.slug] as HTMLElement, `#${item.slug}`);
            }}
            className={`one_line_ellipsis w-fit px-2 text-read_2 ${activeHeading === `#${item.slug}` ? "text-pm_purple-600 font-medium" : "text-text-color_2"}`}
            style={{ marginLeft: `${(item.level - 2) * 10}px` }}
            >
            {item.content}
            </li>
        </Link>
        );
    })}
    <div
        ref={activeIndicatorRef}
        className="absolute transition-all duration-200 h-[28px] bg-background-color_850C left-0 top-0 rounded-tiny -z-10"
    ></div>
</ul>
</aside>

How the useActiveHeading Hook Works:

  • activeHeading State: Stores the hash (e.g., #section-one) of the currently visible heading.

  • headingListRefs: A useRef object that maps heading slugs to their corresponding HTMLElement in the Table of Contents sidebar. This is crucial for correctly positioning the visual indicator and scrolling the sidebar.

  • activeIndicatorRef: A useRef for the actual DOM element that acts as the moving indicator.

  • asideRef: A useRef for the Table of Contents sidebar container. This reference is crucial for managing the sidebar's scroll position programmatically, ensuring that the currently active heading link remains visible and centered within the sidebar's viewport, without affecting the main page's scroll.

  • handleActiveHeading: A useCallback function that takes a DOM element (btn) and a hashLink. It sets the activeHeading state and uses requestAnimationFrame to smoothly animate the activeIndicatorRef's position and size to match the btn's dimensions.

Why content: string is a parameter for useActiveHeading:

The useActiveHeading hook takes content: string as a parameter to ensure its internal logic, specifically the Intersection Observer, is re-initialized and re-attached to the correct heading elements whenever your MDX or Markdown content changes.

Note: You can pass the generated TOC or even a simple content hash. The goal is to give useEffect something to watch for changes, so it knows when to: Reset observers Recalculate which headings to track.

🔠 Type Definitions

This package exports helpful TypeScript types you can use in your own code.

✅ Available Types

  • TocItem
import type { TocItem } from "react-mdxutils";

🤝 Contributing

Contributions are welcome! If you find a bug, have a feature request, or want to improve the code, please open an issue or submit a pull request on the GitHub repository.