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

react-table-of-content

v1.3.0

Published

Provides hooks and utility functions to create a custom and reusable autogenerated table of content for a React project, works really well with markdown content as well.

Downloads

14

Readme

React table of content

Provides hooks and utility functions to create a custom and reusable autogenerated table of content for a React project, works really well with markdown content as well.

NPM Downloads GitHub License NPM Version

Table of Contents

Features

  • Generates a table of content based on the headings in a React component.
  • Supports custom selectors for headings.
  • Supports custom dependencies to watch for changes.
  • Provides utility functions to add IDs to heading tags in HTML.
  • Provides utility functions to convert strings to dash case.
  • Provides utility functions to convert links in HTML to external links (open in new tab).
  • Lightweight and easy to use.
  • No dependencies.

Installation

npm install react-table-of-content

Usage

import React from "react";
import { useTableOfContent } from "react-table-of-content";

export const TableOfContent: React.FC<{}> = () => {
  const { headingLinks, contentIsActive } = useTableOfContent();

  //   return (
  //     <>JSX</>
  //   )
};

Example implementation

You can create a reusable component that generates a table of content for your page using the hook. See the example below.

import React from "react";
import { useTableOfContent } from "react-table-of-content";

export const TableOfContent: React.FC<{}> = () => {
  const { headingLinks, contentIsActive } = useTableOfContent({
    selectors: "article h1, article h2, article h3",
  });

  if (!headingLinks || headingLinks.length < 1) return null;

  return (
    <div>
      <h4 id="on-this-page">ON THIS PAGE</h4>
      <ul className="mt-4 space-y-2">
        {headingLinks.map((link) => {
          const isActive = contentIsActive(link.id);

          return (
            <li key={link.id}>
              <a
                className={`${
                  isActive ? "text-gray-800 font-semibold" : "text-gray-500"
                }
                ${["h3", "h4"].includes(link.tagName.toLowerCase()) && "pl-2"}
                ${["h5", "h6"].includes(link.tagName.toLowerCase()) && "pl-4"}
                hover:text-gray-700 transition-colors duration-200
                `}
                href={`#${link.id}`}
              >
                {link.title}
              </a>
            </li>
          );
        })}
      </ul>
    </div>
  );
};

You can then use the component in your page like so:

import React from "react";
import { TableOfContent } from "./TableOfContent";

export const App: React.FC = () => {
  return (
    <div className="flex">
      <div className="p-10 w-64">
        <div className="sticky top-8">
          <div className="mb-2">
            <img className="w-8 h-8" src="/favicon.png" alt="logo" />
          </div>
          <TableOfContent />
        </div>
      </div>
      <div className="flex-1">
        <Article />
      </div>
    </div>
  );
};

Below is an example of an article component that has headings.

import React from "react";

const Article = () => {
  const headingTags = ["h1", "h2", "h3", "h4", "h5", "h6"];
  const dummyText =
    "Lorem ipsum dolor sit amet consectetur adipisicing elit. Laborum vero accusamus alias cumque numquam atque eius ullam nobis at! Necessitatibus, corporis earum? Quidem, corporis blanditiis sapiente veritatis saepe debitis expedita!.";
  return (
    <article>
      <div className="container max-w-screen-xl">
        {headingTags.map((tag, index) => {
          const headingElement = createElement(
            tag,
            { key: index, id: `${tag}-heading` },
            `${tag.toUpperCase()} heading`
          );
          return (
            <section key={index}>
              {headingElement}
              {/* Returns something like this: <h1 id={`${tag}-heading`}>{tag.toUpperCase()} heading</h1> */}
              <p>{dummyText}</p>
            </section>
          );
        })}
      </div>
    </article>
  );
};

API

Hooks

useTableOfContent

The useTableOfContent hook generates a table of content for a React component based on the headings in the component.

Arguments

| Name | Type | Required | Default | Description | | ----------- | --------- | -------- | -------------- | ------------------------------------------------------------------------------ | | selectors | string | Optional | "h1, h2, h3" | A string of comma-separated selectors to use to generate the table of content. | | deps | unknown | Optional | undefined | An item to be used within the dependency array to watch for changes. |

Return value

An object with the following properties:

| Name | Type | Description | | ----------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | headingLinks | array | It contains an array of objects that have the following properties:id (string): The ID of the heading, title (string): The text content of the heading, tagName (string): The tag name of the heading. | | contentIsActive | function | A function that takes an ID of the headingLink and returns a boolean indicating whether the content with that ID is active. |

Utility functions

The package also exports utility functions that can be used to generate the table of content.

addIdToHeadingTags

The addIdToHeadingTags function adds an ID to each heading tag in a string of HTML.

Arguments

Accepts 1 argument of type string containing the HTML to add IDs to heading tags.

Return value

A string of HTML with IDs added to the heading tags.

Usage and example
import { addIdToHeadingTags } from "react-table-of-content";

const html = `
  <h1>Heading 1</h1>
  <p>Content 1</p>
  <h2>Heading 2</h2>
  <p>Content 2</p>
`;

const newHtml = addIdToHeadingTags(html);

console.log(newHtml);

// Output:
// <h1 id="heading-1">Heading 1</h1>
// <p>Content 1</p>
// <h2 id="heading-2">Heading 2</h2>
// <p>Content 2</p>

dashCase

It's a function that converts a string to dash case.

Arguments

Accepts 1 argument of type string to be transformed to a dash cased format.

Return value

A string in dash case.

Usage and example
import { dashCase } from "react-table-of-content";

const str = "This is a string";

const newStr = dashCase(str);

console.log(newStr);

// Output:
// this-is-a-string

makeLinksExternal

It's a function that converts all links in a string of HTML to external links.

Arguments

Accepts 1 argument of type string containing the HTML to convert links to external links.

Return value

A string of HTML with links converted to external links.

Usage and example
import { makeLinksExternal } from "react-table-of-content";

const html = `
  <a href="/about">About</a>
  <a href="/contact">Contact</a>
`;

const newHtml = makeLinksExternal(html);

console.log(newHtml);

// Output:
// <a href="/about" target="_blank" rel="noopener noreferrer">About</a>
// <a href="/contact" target="_blank" rel="noopener noreferrer">Contact</a>

readTime

It's a function that calculates the read time of a string of text.

Arguments

Accepts 1 argument of type string containing the text to calculate the read time.

Return value

An object with minutes property of type number in minutes and a readTime property describing the number in words e.g. "1 min read".

Usage and example
import { readTime } from "react-table-of-content";

const text =
  "This is a string of text that will be used to calculate the read time.";

const time = readTime(text);

console.log(time);

// Output:

// { minutes: 1, readTime: "1 min read" }

Testing

Unit and integration tests are written using Jest and React Testing Library. To run the tests, use the command below:

npm run test

You can mock the package in your tests like so:

jest.mock("react-table-of-content", () => ({
  addIdToHeadingTags: jest.fn((content) => content),
  useTableOfContent: jest.fn(() => ({
    headingLinks: [
      {
        id: "id",
        title: "title",
        tagName: "h1",
      },
    ],
    contentIsActive: jest.fn(() => true),
  })),
  makeLinksExternal: jest.fn((content) => content),
}));

License

MIT

Author

Precious OSSAI

Developer Website