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.6+ CodeStyle-black 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 sinle # character from the table of contents.

Combined, this looks lik:

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

or:

uvx mark-toc -H 2 -S 1

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.4.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.4.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.4.0.tar.gz (35.0 kB view hashes)

Uploaded Source

Built Distribution

mark_toc-0.4.0-py3-none-any.whl (17.3 kB view hashes)

Uploaded Python 3

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