Skip to main content

Generate table of contents in Markdown files based on headings

Project description

mark-toc

EditorConfig-enabled pre-commit-enabled Python-3.10+ CodeStyle-ruff pre-commit-hook-included

A Python tool which creates a Table of Contents for a Markdown document using the headings in the document as in-document hypertext link references.

Contents

Installing

It is recommended to install mark-toc either:

Once you have uv installed, you can use it to install mark-toc as follows:

uv tool install mark-toc

How to Use

For a summary of all the available options:

uv tool run mark-toc --help

Or, with the uvx shortcut:

uvx mark-toc --help

Or, if you prefer to call the script directly:

/path/to/mark-toc --help

[!TIP]

There are a number of different ways to run tools that are delivered as Python modules. For the remainder of this document, we will use uvx mark-toc to mean whichever one you prefer for your Python installation and operating environment.

How Does It Work?

mark-toc uses jiggerypokery to interpret and create "pseudo-comments" in the document text which are not rendered in most flavors of Markdown, including GitHub-flavored Markdown.

[!IMPORTANT]

mark-toc only handles the "atx"-style headings beginning with #, not the "setext"-style using "underlines" with = or -.

To insert a table of contents in your document, add the following text, at the beginning of an otherwise blank line and surrounded by blank lines, in the spot where you want the table of contents to appear:

[toc]: #

This is the "table of contents token". For example:

# README

This is the README.

[toc]: #

## More Info

...

Alternatively, you can use a "begin table of contents token" with a matching "end table of contents token":

[begintoc]: #
...
[endtoc]: #

Anything between the "begin" and "end" tokens will be replaced with the generated table of contents.

How Does It Really Work?

The "table of contents token" and begin/end tokens use the link reference definitions feature of Markdown to insert a link definition that is not intended to be referred to anywhere in the document.

As the CommonMark Spec notes:

A link reference definition does not correspond to a structural element of a document. Instead, it defines a label which can be used in reference links and reference-style images elsewhere in the document.

A link consisting of only # is a valid HTML hyperlink target; it refers to an empty fragment in the current document.

Example

This README contains begin/end tokens and serves as an example. You may need to view the "raw" source to see them.

Generating the Table of Contents

Once the token is in your Markdown file, run this script to generate a new document which includes a table of contents in place of the token. For example:

uvx mark-toc INPUTFILE.md

The result is printed to the standard output.

You can rerun this tool using a resulting document as the input, and the existing table of contents will be replaced by a new one in the output.

Heading Levels

By default, mark-toc includes all headings (except for the one starting the table of contents itself) in the resulting table of contents, and it prints the Contents heading as a top-level heading:

# Contents

However, it is not uncommon for Markdown documents on GitHub (like this README, for example) to use a "top-level" heading as the title of the document, and only second-level headings or greater throughout the rest of the document.

You can control what level the Contents heading appears at using the --heading-level option:

uvx mark-toc --heading-level 2 INPUTFILE.md

This results in:

## Contents

You can also control the "lowest" level of headings included in the table of contents using --skip-level. For example, to skip top-level headings, use;

uvx mark-toc --skip-level 1 INPUTFILE.md

This will omit all headings that start with a single # character from the table of contents.

Combined, this looks like:

uvx mark-toc --heading-level 2 --skip-level 1

or:

uvx mark-toc -H 2 -S 1

You may want to leave less-important headings out of the table of contents. You can do this using --max-level and specifying the maximum level of heading that should appear. For example:

uvx mark-toc --max-level 3

The above includes heading levels 1, 2, and 3, and leaves out 4 or higher.

More Options

mark-toc has more options. There's built-in help:

uvx mark-toc --help

Pre-Commit Hook

mark-toc has built-in support for use with pre-commit as a pre-commit hook. Simply add the following repo and hook to the repos stanza in your .pre-commit-config.yaml:

  - repo: https://github.com/jmknoble/mark-toc
    rev: v0.5.0
    hooks:
      - id: mark-toc

This uses the --pre-commit option to modify Markdown files in place and emit a message when a file is changed.

You can add arguments to the hook using the args keyword; for example:

  - repo: https://github.com/jmknoble/mark-toc
    rev: v0.5.0
    hooks:
      - id: mark-toc
        args: ['--heading-level', '2', '--skip-level', '1']

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mark_toc-0.5.0.tar.gz (37.3 kB view details)

Uploaded Source

Built Distribution

mark_toc-0.5.0-py3-none-any.whl (17.5 kB view details)

Uploaded Python 3

File details

Details for the file mark_toc-0.5.0.tar.gz.

File metadata

  • Download URL: mark_toc-0.5.0.tar.gz
  • Upload date:
  • Size: 37.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.7

File hashes

Hashes for mark_toc-0.5.0.tar.gz
Algorithm Hash digest
SHA256 41f6fd8d792e117b4609e1d56a36bfe220623b5d5dc4f0c5a4ac428620f21a0f
MD5 b27c7fe2ad6727176c0576378ac32a2d
BLAKE2b-256 a6989ef1bdd6656a126da016d4d4f8746b1120c3eb4960397be9854e2e53f36c

See more details on using hashes here.

Provenance

The following attestation bundles were made for mark_toc-0.5.0.tar.gz:

Publisher: build.yaml on jmknoble/mark-toc

Attestations:

File details

Details for the file mark_toc-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: mark_toc-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 17.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.7

File hashes

Hashes for mark_toc-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 dc7bf6879692d867f8f19b081141053d5d3916b20365ab68812ad15c539f1ebc
MD5 87e88c26f43d57b101a3464f62b8ed68
BLAKE2b-256 f715ae2cecb76aa1a47c03b575248e5fce02a857ea8f8f1175e7108a32b4e516

See more details on using hashes here.

Provenance

The following attestation bundles were made for mark_toc-0.5.0-py3-none-any.whl:

Publisher: build.yaml on jmknoble/mark-toc

Attestations:

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page