diff --git a/generateTOC/README.md b/generateTOC/README.md index be66556a21e95af12ebc3095cdaf3b651d8b72b1..259de12fb8b46e015ad656902368c1d23c3a3905 100644 --- a/generateTOC/README.md +++ b/generateTOC/README.md @@ -1,25 +1,27 @@ # 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 diff --git a/generateTOC/generateTOC.py b/generateTOC/generateTOC.py index 4e29ace7fb08c0d52494795751a0f5ac2e58623c..ad08b438981f823d2abcaa2b44bd17cdb3a64b10 100644 --- a/generateTOC/generateTOC.py +++ b/generateTOC/generateTOC.py @@ -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,33 +78,39 @@ 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 += ' ' * (h[1] * args.indent) + f'[{h[0]}](#{prepareTOClink(h[0])}) \n' - to = re.sub('<[^<]+?>', '', to) + toc += ' ' * (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 (args.tocTags and line.strip() in tocTags) or line.strip() == '# Contents': - inToc = True - f.write(to) - continue + if not tocDone: + if (args.tocTags and line.strip() in tocTags) or line.strip() == '# Contents': + inToc = True + f.write(toc) + continue # Write the rest f.write(line) @@ -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')