Utility to number headings and generate Table of contents for Markdown files.
Table of Contents
- Overview
- Usage
- 2.1. Summary
- 2.2. Producing output
- 2.3. Heading syntax
- 2.4. Table of contents
- 2.5. Heading levels
- 2.6. Removing the table of contents and numbering
- Installation
- Limtations
1. Overview
This utility adds heading numbers and a table of contents to a Markdown file.
It is used to make long Markdown files easier to navigate and read.
For example, it takes a Markdown file containing:
| Document title
| ==============
|
| ## Alpha
|
| ### Foo
|
| ### Bar
|
| ## Beta
|
| ## Gamma
And generates:
| Document title
| ==============
|
| ## Table of contents
|
| 1. Alpha
| - 1.1 Foo
| - 1.2 Bar
| 2. Beta
| 3. Gamma
|
| ## 1. Alpha
|
| ### 1.1 Foo
|
| ### 1.2 Bar
|
| ## 2. Beta
|
| ## 3. Gamma
Note: this README has been processed by the utility, to automatically generate the above Table of Contents and the numbered headings. The Markdown in the embedded examples start with extra "|" at the beginning of the lines, to prevent the utility from recognising their contents as headings for it to process.
This is a simplified example: the actual output also contains hyperlinks from the entries in the table of contents to the sections they refer to.
The utility can also update the numbering and table of contents. It can be re-run on its own output: which is useful if headings have been added, changed or removed.
It can also be used to strip out the table of contents and heading numbers. That is, to revert it back to the original input Markdown.
2. Usage
2.1. Summary
Usage: markdown_toc [options] {markdown-files}
Options:
-t | --top-level N lowest numbered heading level (default: 2)
-n | --num-level N highest heading level to number (default: 5)
-i | --toc-level N highest heading level to include in table of contents (default: 4)
-o | --output FILE write result to named output file (default: stdout)
-r | --replace replace input file with the result instead of to output
-s | --strip remove ToC and numbering, instead of adding/updating them
-v | --verbose output extra information when running
--version display version information and exit
-h | --help display this help and exit
2.2. Producing output
By default, the results are written to stdout:
$ markdown_toc.dart example.md
But the utility is usually invoked to replace the input file with the results:
$ markdown_toc.dart --replace example.md
Alternatively, a different output file can be specified:
$ markdown_toc.dart --output example-with-toc.md example.md
2.3. Heading syntax
The utility only processes headers that use the leading "#" Markdown syntax. It ignores headers that use the underline Markdown syntax.
2.4. Table of contents
The table of contents is inserted immediately before the first recognised heading.
2.5. Heading levels
2.5.1. Default processes level 2 headings and higher
If it processes level 2 headers and higher (the default), this allows the document's title to be formatted as a level 1 heading using the underline syntax. It will ignore the title (i.e. not number it and not include it in the table of contents) and insert the table of contents immediately before the first non-ignored heading.
And the default maximum numbered level is 5. Headings at level 6 and greater (i.e. those starting with Markdown "######") will not be numbered.
The maximum level to include in the table of contents is 4. Headings at level 5 and greater (i.e. those starting with Markdown "#####") will not be included in the table of contents (even if they are numbered).
For example,
| Title
| =====
|
| ## First
|
| ### Subsection
|
| ## Second
|
Will produce:
| Title
| =====
|
| ## Table of Contents
|
| ...
|
| ## 1. First
|
| ### 1.1. Subsection
|
| ## 2. Second
2.5.2. Changing the level of processed headings
The heading levels which are processed is changed using the
--top-level
, --num-level
and --toc-level
options.
For example, some Markdown files use a metadata block for the document title and level 1 headings used as normal headings.
| % The document's title
| % Author
| % Version 1.0.0
|
| # First
|
| ## Subsection
|
| # Second
Use the --top-level
option to include the level 1 headings:
$ markdown_toc --top-level 1 example.md
Produces:
| % The document's title
| % Author
| % Version 1.0.0
|
| # Table of contents
|
| ...
|
| # 1. First
|
| ## 1.1 Subsection
|
| # 2. Second
2.6. Removing the table of contents and numbering
Use the --strip
option to remove the information added by the utility.
$ markdown_toc.dart --strip example-with-toc.md
3. Installation
markdow_toc
is not meant to be used as a dependncy. Instead, it
should be installed.
There are a number of ways it can be installed.
3.1. Dart
When used to manage Markdown files in a Dart project, this utility can be made a development dependency of the project.
3.1.1. Dependency of a Dart project
This utility is intended to be included in a Dart project development dependency, so it can be used to add numbered headings and table of contents to long Markdown documents in the project.
In pubspec.yaml add:
dev_dependencies:
markdown_toc: ^1.1.0
Then run:
$ dart pub get
The utility should be run using the "dart run" command, to run the specific version of the utility that was installed by "dart pub get".
$ dart run markdown_toc --help
3.1.2. Global install
Alternatively, install it using "dart pub global activate" so it can be used on any Markdown files (not just those used to document Dart projects).
$ dart pub global activate markdown_toc
If the global directory is on the PATH, the utility can be run using:
$ markdown_toc --help
Or it can always be run with:
dart pub global run markdown_toc --help
3.1.3. Script runs anywhere Dart is available
Finally, the utility has been written to not use any pub packages. So it can be run anywhere; as long as the dart executable is available. There is no need for it to be inside a Dart project, nor to have an associated pubspec.yaml file.
Copy the markdown_toc.dart file to somewhere on the PATH:
$ cp markdown_toc.dart /usr/local/bin/markdown_toc
And then run it as a normal command:
$ markdown_toc --help
3.1.4. Compiled executable runs without needing Dart
Compile it to a self-contained executable. Which can be run anywhere, without needing the Dart executable.
dart compile exe bin/markdown_toc.dart
bin/markdown_toc --help
3.2. Binary
Binaries can be downloaded from the project's GitHub releases.
Copy the program to a location in your PATH.
4. Limtations
4.1. Fenced code blocks may be incorrectly treated as headings
The lines inside fenced code blocks (i.e. lines between lines starting with ```) are not treated as different. If they contain lines starting with "#" (with or without whitespace before it), they may be incorrectly processed as headings.
Since the --top-level
is usually set to 2 or higher. This problem
only occurs when lines inside the fenced code blocks start with two or
more "#", which may not occur.
A workaround is to modify the lines inside the fenced code blocks. For example, by adding a prefix to them so they don't start with the "#".