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 🙏

© 2024 – Pkg Stats / Ryan Hefner

extract-md-headings

v0.2.7

Published

lightweight heading text extractor from markdown files

Downloads

314

Readme

This package exports a function that you can use to "extract" headings from any markdown file, with the .md or .mdx extensions.

Usage

To start using this package, you should install it from the npm registery with the command below, then you can proceed to use it in your project as you wish.

yarn add extract-md-headings

When you import the function and call it for the time, it returns an array of headings from your markdown file, and categorizes them based on the levels that they occupy in the file.

The function takes in one argument, which is the path to where your markdown file is located.

import { extractHeadings } from "extract-md-headings";

const headings = extractHeadings("file.md");

console.log(headings);

If You have a makrdown file with headings, let's take this article for example, when you call the function on the markdown file of this article, it returns an array in the form below. When you take a look at the response, you'll see that it returns three properties — slug, title, and level

[
  {
    slug: "not-every-code-snippet-you-see-on-twitter-is-accurate",
    title: "Not every code snippet you see on Twitter is accurate.",
    level: 3,
  },
  {
    slug: "listening-to-route-events-with-nextjs-userouter-hook",
    title: "Listening to route events with Next.js UseRouter hook",
    level: 3,
  },
  {
    slug: "making-the-loader-component-dynamic",
    title: "Making the loader component dynamic",
    level: 3,
  },
  { slug: "final-thoughts", title: "Final thoughts", level: 3 },
];

The essence of the level property is so you can utilize it when you are trying to create, say, a Table of Content component for your block and you want to group the headings in such a way that the lower heading titles become children of higher headins elements. This is to create more of a visual appeal BTW.

Module resolution

The packages supports both ECMAScript — esm — and commonJS (cjs) modules. so if peradventure you try to use the package by doing the following, below, and you get this error: "ReferenceError: exports is not defined in ES module scope"

import { extractHeadings } from "extract-md-headings";

One way to fix this would be to use this import statement instead of the one above

import { extractHeadings } from "extract-md-headings/dist/esm";

And if you're coming from Next.js, you may want to use a module transpiler like next-transpile-modules. Install the package and modify next.config.js to look like this

const withTM = require('next-transpile-modules')(['extract-md-headings']);

module.exports = withTM({
  ...
});

Examples

Take this package for a spin, and let me know what you've been able to build with it by contributing to the project.

Future examples will appear here.

With Next.js

These issue of module resolution can be avoided when you use the function in a Next.js app. Say you're trying to build a Table Of Content component, do not try using the function inside the component like the one below, and get the headings from getStaticProps()

import React from "react";
import { extractHeadings } from "extract-md-headings";

const TableOfContents = ({ filePath }) => {
  const headings = extractHeadings(filePath);

  return (
    <div>
      <p>On this page</p>
      <ul>
        {headings.map(({ slug, title }, index) => {
          return (
            <li key={index}>
              <a href={`#${slug}`}>{title}</a>
            </li>
          );
        })}
      </ul>
    </div>
  );
};

export default TableOfContents;

When you do something like, this, Next.js would throw an error similar to the one below

TypeError: fs__WEBPACK_IMPORTED_MODULE_0___default(...).readFileSync is not a function

This is because extract-md-headings uses the readFileSync method from the Node.js fs() module, and Next.js throws an error, because Node.js functions are mostly used for server-side operations.

In your case here, you're using the function in a client-side component. Hence, the error. To fix this, you modify <TableOfContent /> to exclude the function's invocation, and use a headings prop, or anything you feel like using.

Then we'd have something like the snippet below;

import React from "react";
import Head from "next/head";
import TableOfContents from "@components/TOC";
import { extractHeadings } from "extract-md-headings";

export default function Blog({
  post: {
    fileContent,
    frontmatter: { title },
  },
}) {
  return (
    <React.Fragment>
      <Head>
        <title>{title}</title>
      </Head>
      <TableOfContents headings={fileContent} />
    </React.Fragment>
  );
}

// destructuring params to get the unique slugs
export async function getStaticProps({ params }) {
  // fetch the particular file based on the slug,
  // and use the function to extract headings
  const { slug } = params;
  const mdxContent = extractHeadings(`./data/articles/${slug}.mdx`);

  return {
    props: {
      post: {
        frontmatter,
        source: mdxSource,
        fileContent: mdxContent,
      },
    },
  };
}

Contributing

See the contributing guide

License

MIT © 2023 kaf-lamed-beyt