Commit 2ebbfb8f authored by ankraft's avatar ankraft
Browse files

Added --outfile command line argument. Improved ToC insertion

parent 4f256c8d
Loading
Loading
Loading
Loading
+10 −5
Original line number Diff line number Diff line
# Generate TOC for Markdown files

The script will generate a TOC for a Markdown file, based on the headers in the file.
The script will generate a Table of Contents for a Markdown file, based on the headers in the file.

It generates and prints the TOC to the console, and optionally also inserts it into the original file.
For the latter, it will first create a backup copy of the file and then replace any section named "# Contents" with the new table of contents **in the original input document**.
For the latter, it will first create a backup copy of the file and then replace any section named "# Contents" with the new table of contents **in the original input document**. To keep the original document intact, it may be a good idea to first create a backup copy of the document and work on that copy.

Alternatively, one can specify an output file name with the `--outfile` option. The script will then create a new file.

###  Support for Table-of-Content Tags

Some renderers support special tags in the Markdown document to automatically insert a TOC. This script supports the following tags:
Various markdown renderers support special tags in the Markdown document to automatically insert a TOC. This script supports the following tags:

- `<!--TOC-->`
- `[TOC]`
- `[CONTENT]`

If the `--toctags` and `--add-content` options are specified, the script will replace these tags with the generated TOC in the original input document. To keep the original document intact, it may be a good idea to first create a backup copy of the document and work on that copy.
If the `--toctags` and `--add-content` options are specified, the script will replace these tags with the generated TOC in the original input document.



## Prerequisites

- Python 3.8 or higher
- Python 3.10 or higher

## Usage

@@ -46,5 +48,8 @@ options:
                        indent spaces for each level (default: 4)
  --level LEVELS, -l LEVELS
                        limit the TOC levels; 0 means no limit (default: 0)
 --outfile OUTFILE, -o OUTFILE
                        set the output file name; if not set, the input file will be
                        overwritten (default: None)
  --toc-tags, -t        replace special TOC tokens in the document (default: False)
```
 No newline at end of file
+19 −12
Original line number Diff line number Diff line
@@ -13,7 +13,7 @@ import argparse, os, re
from rich import print


tocTags:[str] = ['[TOC]', '[CONTENT]', '<!--TOC-->']
tocTags:list[str] = ['[TOC]', '[CONTENT]', '<!--TOC-->']
"""	TOC tags to replace in the document with the TOC. """

def backupFile(filename:str) -> None:
@@ -78,32 +78,38 @@ def processDocument(args:argparse.Namespace) -> None:
				headers.append((headline, level))
	
	# Prepare and Print the table of contents
	to = '# Contents\n\n'
	toc = '# Contents\n\n'
	for h in headers:
		to += '&nbsp;' * (h[1] * args.indent) + f'[{h[0]}](#{prepareTOClink(h[0])})  \n'
	to = re.sub('<[^<]+?>', '', to)
		toc += '&nbsp;' * (h[1] * args.indent) + f'[{h[0]}](#{prepareTOClink(h[0])})  \n'
	toc = re.sub('<[^<]+?>', '', toc)
	
	# Write the TOC to the console
	print(to)
	print(toc)

	# Add the TOC to the document
	# The TOC replaces the old TOC if it exists in the section "# Contents"
	if args.addContent:
		backupFile(args.document)
	# An outfile explicitly enables the TOC to be added to the document
	if args.addContent or args.outfile:
		outDocument = args.document if not args.outfile else args.outfile
		backupFile(outDocument)
		tocDone = False
		# Add the TOC to the document
		with open(args.document, 'w') as f:
		with open(outDocument, 'w') as f:
			inToc = False
			for line in document:
				# Skip the old TOC when writing
				if inToc:
					if not line.strip().startswith('#'):
						continue
					f.write('\n') # Add a newline
					inToc = False
					tocDone = True
				
				# Write the new TOC in the right place
				if not tocDone:
					if (args.tocTags and line.strip() in tocTags) or line.strip() == '# Contents':
						inToc = True
					f.write(to)
						f.write(toc)
						continue

				# Write the rest
@@ -136,6 +142,7 @@ if __name__ == '__main__':
	parser.add_argument('--contents', '-c', action='store_true', dest='contents', default = False, help = 'add link to "Contents" section in the generated TOC')
	parser.add_argument('--indent', '-i', action='store', dest='indent', type = nonNegativeInt, default = 4, metavar = '<indent>', help = 'indent spaces for each level')
	parser.add_argument('--level', '-l', action='store', dest='levels', type = nonNegativeInt, default = 0, help = 'limit the TOC levels; 0 means no limit')
	parser.add_argument('--outfile', '-o', action='store', dest='outfile', help = 'set the output file name; if not set, the input file will be overwritten')
	parser.add_argument('--toc-tags', '-t', action='store_true', dest='tocTags', default = False, help = 'replace special TOC tokens in the document')

	parser.add_argument('document', help = 'document to parse')