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

@datalackey/update-markdown-toc

v1.1.13

Published

Auto-generate Table of Contents for a Markdown file (or files, recursively from a top level folder)

Readme

@datalackey/update-markdown-toc

Introduction

A Node.js command-line documentation helper which automatically:

  • generates Table of Contents (TOC) blocks for Markdown files
  • operates on either a single file, or recursively finds all *.md files from a root path
  • regenerates TOCs from headings, targeting only regions explicitly marked with TOC markers
  • avoids gratuitous reformatting or changes of any kind outside of regions marked by the aforementioned TOC markers
  • avoids updating files when the generated TOC is already correct
  • provides a --check mode which flags Markdown files with stale TOCs (intended for CI)
  • generates TOC links with GitHub’s Markdown renderer.

Why not Some Other Markdown TOC Generator ?

Most Markdown TOC tools (e.g., markdown-toc, md-toc-cli) operate on a single file at a time, a mode which we also support. The primary distinguishing feature of our tool is its ability to recursively search for, check, and update all Markdown documents within an entire folder hierarchy, making it suitable for CI and large repositories.

Installation

Install as a development dependency (recommended):

npm install --save-dev @datalackey/update-markdown-toc

This installs the update-markdown-toc command into your project’s node_modules/.bin/ directory.

Usage

After installation, the update-markdown-toc command can be invoked in any of the following ways from the project root (or a subdirectory) where the package was installed. All examples below invoke the tool with the default README.md file as the TOC update target.

Using npx (recommended)

npx update-markdown-toc 

Using npm scripts

You may also add a script entry to your package.json:

{
  "scripts": {
    "docs:toc": "update-markdown-toc"
  }
}

Then run:

npm run docs:toc

Using a direct path (advanced)

./node_modules/.bin/update-markdown-toc 

Options

This section assumes the command is invoked using npx, an npm script, or another method that resolves the local update-markdown-toc binary.

update-markdown-toc [options] [file]

Options:
  -c, --check     <path-to-file-or-folder>  Do not write files; exit non-zero if TOC is stale
  -n, --no-external-link-check              Skip external HTTP/HTTPS link validation during --check
  -l, --link-timeout-ms <ms>                Per-request timeout for external link checks (default: 3000)
  -r, --recursive <path-to-folder>          Recursively process all .md files under the given folder
  -e, --exclude   <dir1,dir2,...>           Directory names to exclude during recursive traversal (overrides default)
  -v, --verbose                             Print status for every file processed
  -q, --quiet                               Suppress all non-error output
  -d, --debug                               Print debug diagnostics to stderr
  -h, --help                                Show this help message and exit

When using --check, if no file is specified, the tool defaults to README.md in the current working directory. This means the following two commands are equivalent:

npx update-markdown-toc --check
npx update-markdown-toc --check README.md

To check an entire documentation tree in CI, use --check --recursive <path>.

Configurable Exclusion List for Recursive Traversal

The --exclude option only applies when --recursive is specified. It accepts a comma-separated list of directory names (exact match, not glob patterns), and when provided, it replaces the default exclusion list.

By default, the recursive traversal excludes only: node_modules.

Examples:

Exclude node_modules and dist:

npx update-markdown-toc --recursive . --exclude node_modules,dist

Exclude only dist (this allows traversal into node_modules):

npx update-markdown-toc --recursive . --exclude dist

Disable exclusions entirely:

npx update-markdown-toc --recursive . --exclude ""

TOC Markers

The tool operates only on files containing both start and end markers, as shown below:

    <!-- TOC:START -->     <!-- TOC:END -->

Any existing content between the region start and end markers is lost. The new content will be the generated TOC that reflects the section headers marked with '#'s in the Markdown document.

Content outside the markers is preserved verbatim. If either marker is missing, the tool prints an error message and exits with a non-zero status code.

Usage Scenarios

As Part of code/test/debug Work Flow

To ensure that your code is built afresh, passes tests, and that your documentation TOCs are up to date, you could invoke the tool via something akin to the package.json below. Before commit and push, you would type: 'npm run build'

Your package.json might look like this:

{
  "scripts": {
    "clean": "rm -rf dist",
    "compile": "tsc -p tsconfig.json",
    "pretest": "npm run compile",
    "test": "jest",
    "docs:toc": "update-markdown-toc --recursive docs/",
    "bundle": "esbuild src/index.ts --bundle --platform=node --outdir=dist",
    "package": "npm run clean && npm run compile && npm run bundle",
    "build": "npm run docs:toc && npm run test && npm run package"
  }
}

Continuous Integration

The --check flag is designed primarily for continuous integration (CI).

In this mode, the tool:

  • never writes files
  • compares the existing TOC block against the generated TOC
  • exits with a non-zero status if any TOC is stale

Example:

npx update-markdown-toc --check --recursive docs/

Link Validation in Check Mode

When running with --check, the tool performs three tiers of link validation in these scopes:

  • table of contents links,
  • intra-document links, and
  • external links.

For full details on behavior, failure output, and performance considerations see [Common CLI Behavior — Check Mode](../CLI-BEHAVIOR.md#

To skip external link validation:

npx update-markdown-toc --check README.md --no-external-link-check

If a pull request modifies documentation headings but forgets to update TOCs or other links targeted for validation in a particular run, then the above command will fail the build, forcing the contributor to regenerate and commit with corrected TOC and other links.

Recursively Traversing a Folder Hierarchy to Process all files vs. Single File Processing

The tool supports two distinct operating modes with intentionally different error-handling semantics:

  • Single-file mode (--recursive not specified)
  • Recursive folder traversal mode (--recursive specified)

These modes are designed to support both strict validation and incremental adoption across real-world repositories. In the case of the latter mode, we assume some files may not yet have TOC markers, and that this is acceptable.

Refer to this document for information on these processing modes and a discussion of other behavioral commonalities that all focused-use plugins in this repository share.

Single-File Processing (Strict Mode)

When a single Markdown file is explicitly specified (or when the default README.md is used and --check not specified), the tool operates in strict mode. In this mode, any of the following conditions cause an immediate error and a non-zero exit code:

  • file does not exist, or cannot be read (e.g. due to permissions).
  • file does not contain both TOC delimiters (<!-- TOC:START --> and   <!-- TOC:END -->).
  • file is stale (i.e. the existing TOC differs from the generated TOC).
  • file contains TOC delimiters but no Markdown headings are found from which a TOC can be generated.

If either marker is missing, the tool prints an error message and exits with a non-zero status code.

Recursive Folder Traversal (Lenient Mode)

When operating in recursive mode, the tool traverses a directory tree and processes all *.md files it finds.

In this mode:

  • Files without TOC markers are skipped silently (unless --verbose is specified).
  • Files with valid TOC markers are processed normally.
  • Stale files are reported (unless --quiet is specified).
  • When running in --check mode, stale files cause a non-zero exit code after traversal completes.

Recursive mode is designed for gradual adoption across larger repositories, where not every Markdown file may yet contain TOC markers. Unlike single-file mode, recursive mode does not treat missing TOC markers as an error. This allows incremental rollout of TOC enforcement.

However, structural or filesystem errors still abort the run immediately. These include:

  • unreadable files (e.g., permission errors),
  • mismatched TOC delimiters,
  • malformed TOC marker pairs,
  • files containing TOC markers but no Markdown headings.

When such errors occur, the tool prints an error message and exits non-zero without continuing further traversal.

When combined with --verbose, skipped files (Markdown files without start/end region markers) are reported explicitly. For example:

update-markdown-toc --recursive docs/ --verbose



```bash
update-markdown-toc --recursive docs/ --verbose

yields example output:

Skipped (no markers): docs/legacy-notes.md
Updated: docs/guide.md
Up-to-date: docs/api.md

Design Goals and Philosophy

This tool was designed in accordance with the top-level Build Philosophy of this repository.

  • update mode (writes files: this should be run locally by developers, and should never run in CI. It is the default if --check not specified)
  • check mode (validates and exits non-zero if stale: mainly intended to be run in CI -- optional for local use)

The intended workflow is:

  1. Developers run the command locally in default mode (update mode, a.k.a. non --check mode) in their workspace
  2. Generated TOC content is reviewed and committed.
  3. CI runs in --check mode to ensure no drift exists.

Packaging, Publishing, and Inter-relationship with Other Plugins

This package is one component of a small ecosystem of JavaScript tooling plugins maintained as individual npm packages in this repository. The versioning and release of these packages is governed by a coordinated release policy, and the packages adhere to common design and architectural principles policies that are more completely described here.

Known Limitations

Fragment link validation with formatted headings

Fragment link validation uses AST-based heading extraction, which may produce different slugs than the TOC generator for headings containing inline formatting such as code spans or bold text (e.g. ## Install \foo``).

In practice this affects only headings with inline code, bold, or italic syntax. Plain-text headings are unaffected. A fix to unify both paths is planned for a future release.

Guidelines For Project Contributors

Contributors to the project should consult this document