diff --git a/scripts/markdown_toclify.py b/scripts/updateDocumentToC.py
similarity index 54%
rename from scripts/markdown_toclify.py
rename to scripts/updateDocumentToC.py
index 8278e215..b1ab6dd2 100644
--- a/scripts/markdown_toclify.py
+++ b/scripts/updateDocumentToC.py
@@ -1,44 +1,51 @@
#!/usr/bin/env python
#
-# Sebastian Raschka 2014-2015
+# updateDocumentToC.py
#
-# Python script that inserts a table of contents
-# into markdown documents and creates the required
-# internal links.
+# Insert table of contents at top of Catch markdown documents.
#
-# For more information about how internal links
-# in HTML and Markdown documents work, please see
+# This script is distributed under the GNU General Public License v3.0
#
-# Creating a table of contents with internal links in
-# IPython Notebooks and Markdown documents:
-# http://sebastianraschka.com/Articles/2014_ipython_internal_links.html
-#
-# Updates for this script will be available at
+# It is based on markdown-toclify version 1.7.1 by Sebastian Raschka,
# https://github.com/rasbt/markdown-toclify
#
-# for more information about the usage:
-# markdown-toclify.py --help
-#
+
+from __future__ import print_function
+from scriptCommon import catchPath
import argparse
+import glob
+import os
import re
+import sys
+# Configuration:
-__version__ = '1.7.1'
+minTocEntries = 4
+
+headingExcludeDefault = [1,3,4,5] # use level 2 headers for at default
+headingExcludeRelease = [2,3,4,5] # use level 1 headers for release-notes.md
+
+documentsDefault = os.path.join(os.path.relpath(catchPath), 'docs/*.md')
+releaseNotesName = 'release-notes.md'
+
+contentTitle = '**Contents** '
+contentLineNo = 4
+contentLineNdx = contentLineNo - 1
+
+# End configuration
VALIDS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-&'
-
-def read_lines(in_file):
+def readLines(in_file):
"""Returns a list of lines from a input markdown file."""
with open(in_file, 'r') as inf:
in_contents = inf.read().split('\n')
return in_contents
-
-def remove_lines(lines, remove=('[[back to top]', ' tags."""
if not remove:
@@ -51,8 +58,22 @@ def remove_lines(lines, remove=('[[back to top]', ' anchor tags,
and the level of the headline as integer.
E.g.,
- >>> dashify_headline('### some header lvl3')
+ >>> dashifyHeadline('### some header lvl3')
('Some header lvl3', 'some-header-lvl3', 3)
"""
@@ -84,8 +105,7 @@ def dashify_headline(line):
return [stripped_wspace, dashified, level]
-
-def tag_and_collect(lines, id_tag=True, back_links=False, exclude_h=None):
+def tagAndCollect(lines, id_tag=True, back_links=False, exclude_h=None):
"""
Gets headlines from the markdown document and creates anchor tags.
@@ -118,9 +138,9 @@ def tag_and_collect(lines, id_tag=True, back_links=False, exclude_h=None):
saw_headline = False
orig_len = len(l)
- l = l.lstrip()
+ l_stripped = l.lstrip()
- if l.startswith(('# ', '## ', '### ', '#### ', '##### ', '###### ')):
+ if l_stripped.startswith(('# ', '## ', '### ', '#### ', '##### ', '###### ')):
# comply with new markdown standards
@@ -131,7 +151,7 @@ def tag_and_collect(lines, id_tag=True, back_links=False, exclude_h=None):
if len(l) - len(l.lstrip('#')) > 6:
continue
# headers can be indented by at most 3 spaces:
- if orig_len - len(l) > 3:
+ if orig_len - len(l_stripped) > 3:
continue
# ignore empty headers
@@ -139,7 +159,7 @@ def tag_and_collect(lines, id_tag=True, back_links=False, exclude_h=None):
continue
saw_headline = True
- dashified = dashify_headline(l)
+ dashified = dashifyHeadline(l)
if not exclude_h or not dashified[-1] in exclude_h:
if id_tag:
@@ -153,8 +173,7 @@ def tag_and_collect(lines, id_tag=True, back_links=False, exclude_h=None):
out_contents.append('[[back to top](#table-of-contents)]')
return out_contents, headlines
-
-def positioning_headlines(headlines):
+def positioningHeadlines(headlines):
"""
Strips unnecessary whitespaces/tabs if first header is not left-aligned
"""
@@ -168,11 +187,10 @@ def positioning_headlines(headlines):
row[-1] -= 1
return headlines
-
-def create_toc(headlines, hyperlink=True, top_link=False, no_toc_header=False):
+def createToc(headlines, hyperlink=True, top_link=False, no_toc_header=False):
"""
Creates the table of contents from the headline list
- that was returned by the tag_and_collect function.
+ that was returned by the tagAndCollect function.
Keyword Arguments:
headlines: list of lists
@@ -192,29 +210,28 @@ def create_toc(headlines, hyperlink=True, top_link=False, no_toc_header=False):
if not no_toc_header:
if top_link:
processed.append('\n')
- processed.append('# Table of Contents')
+ processed.append(contentTitle)
for line in headlines:
if hyperlink:
- item = '%s- [%s](#%s)' % ((line[2]-1)*' ', line[0], line[1])
+ item = '[%s](#%s) ' % (line[0], line[1])
else:
item = '%s- %s' % ((line[2]-1)*' ', line[0])
processed.append(item)
processed.append('\n')
return processed
-
-def build_markdown(toc_headlines, body, spacer=0, placeholder=None):
+def buildMarkdown(toc_headlines, body, spacer=0, placeholder=None):
"""
Returns a string with the Markdown output contents incl.
the table of contents.
Keyword arguments:
toc_headlines: lines for the table of contents
- as created by the create_toc function.
+ as created by the createToc function.
body: contents of the Markdown file including
ID-anchor tags as returned by the
- tag_and_collect function.
+ tagAndCollect function.
spacer: Adds vertical space after the table
of contents. Height in pixels.
placeholder: If a placeholder string is provided, the placeholder
@@ -228,17 +245,17 @@ def build_markdown(toc_headlines, body, spacer=0, placeholder=None):
else:
toc_markdown = "\n".join(toc_headlines)
- body_markdown = "\n".join(body).strip()
-
if placeholder:
+ body_markdown = "\n".join(body)
markdown = body_markdown.replace(placeholder, toc_markdown)
else:
- markdown = toc_markdown + body_markdown
+ body_markdown_p1 = "\n".join(body[:contentLineNdx ]) + '\n'
+ body_markdown_p2 = "\n".join(body[ contentLineNdx:])
+ markdown = body_markdown_p1 + toc_markdown + body_markdown_p2
return markdown
-
-def output_markdown(markdown_cont, output_file):
+def outputMarkdown(markdown_cont, output_file):
"""
Writes to an output file if `outfile` is a valid path.
@@ -247,11 +264,17 @@ def output_markdown(markdown_cont, output_file):
with open(output_file, 'w') as out:
out.write(markdown_cont)
-
-def markdown_toclify(input_file, output_file=None, github=False,
- back_to_top=False, nolink=False,
- no_toc_header=False, spacer=0, placeholder=None,
- exclude_h=None):
+def markdownToclify(
+ input_file,
+ output_file=None,
+ min_toc_len=2,
+ github=False,
+ back_to_top=False,
+ nolink=False,
+ no_toc_header=False,
+ spacer=0,
+ placeholder=None,
+ exclude_h=None):
""" Function to add table of contents to markdown files.
Parameters
@@ -262,6 +285,9 @@ def markdown_toclify(input_file, output_file=None, github=False,
output_file: str (defaul: None)
Path to the markdown output file.
+ min_toc_len: int (default: 2)
+ Miniumum number of entries to create a table of contents for.
+
github: bool (default: False)
Uses GitHub TOC syntax if True.
@@ -287,114 +313,134 @@ def markdown_toclify(input_file, output_file=None, github=False,
Returns
-----------
- cont: str
- Markdown contents including the TOC.
+ changed: Boolean
+ True if the file has been updated, False otherwise.
"""
- raw_contents = read_lines(input_file)
- cleaned_contents = remove_lines(raw_contents, remove=('[[back to top]', '= (3, 3):
+ os.replace(output_file, input_file)
+ else:
+ os.remove(input_file)
+ os.rename(output_file, input_file)
+
+ return 1
+
+def updateDocumentToC(paths, min_toc_len, verbose):
+ """Add or update table of contents to specified paths. Return number of changed files"""
+ n = 0
+ for g in paths:
+ for f in glob.glob(g):
+ if os.path.isfile(f):
+ n = n + updateSingleDocumentToC(input_file=f, min_toc_len=min_toc_len, verbose=verbose)
+ return n
+
+def updateDocumentToCMain():
+ """Add or update table of contents to specified paths."""
parser = argparse.ArgumentParser(
- description='Python script that inserts a table of contents\n'\
- 'into markdown documents and creates the required internal links.',
- epilog=""" Example:
- markdown-toclify.py ~/Desktop/input.md -o ~/Desktop/output.md
+ description='Add or update table of contents in markdown documents.',
+ epilog="""""",
+ formatter_class=argparse.RawTextHelpFormatter)
- For more information about how internal links in
- HTML and Markdown documents work
- please see:
- "Creating a table of contents with internal
- links in IPython Notebooks and Markdown documents"
- (http://sebastianraschka.com/Articles/2014_ipython_internal_links.html)
+ parser.add_argument(
+ 'Input',
+ metavar='file',
+ type=str,
+ nargs=argparse.REMAINDER,
+ help='files to process, at default: docs/*.md')
- Updates for this script will be available at
- https://github.com/rasbt/markdown-toclify
+ parser.add_argument(
+ '-v', '--verbose',
+ action='store_true',
+ help='report the name of the file being processed')
- """,
- formatter_class=argparse.RawTextHelpFormatter
- )
+ parser.add_argument(
+ '--min-toc-entries',
+ dest='minTocEntries',
+ default=minTocEntries,
+ type=int,
+ metavar='N',
+ help='the minimum number of entries to create a table of contents for [{deflt}]'.format(deflt=minTocEntries))
- parser.add_argument('InputFile',
- metavar='input.md',
- help='path to the Markdown input file')
- parser.add_argument('-o', '--output',
- metavar='output.md',
- default=None,
- help='path to the Markdown output file')
- parser.add_argument('-b', '--back_to_top',
- action='store_true',
- help='add [back to top] links.')
- parser.add_argument('-g', '--github',
- action='store_true',
- help='omits id-anchor tags (recommended for GitHub)')
- parser.add_argument('-s', '--spacer',
- default=0,
- type=int,
- metavar='pixels',
- help='add horizontal space (in pixels) after the table of contents')
- parser.add_argument('-n', '--nolink',
- action='store_true',
- help='create the table of contents without internal links')
- parser.add_argument('-e', '--exclude_h',
- type=str,
- default='',
- help='exclude eading levels, e.g., "2,3" to exclude all level 2 and 3 headings')
- parser.add_argument('--placeholder',
- type=str,
- help='inserts TOC at the placeholder string instead of inserting it on top of the document')
- parser.add_argument('--no_toc_header',
- action='store_true',
- help='suppresses the Table of Contents header')
- parser.add_argument('-v', '--version',
- action='version',
- version='%s' % __version__)
+ parser.add_argument(
+ '--remove-toc',
+ action='store_const',
+ dest='minTocEntries',
+ const=99,
+ help='remove all tables of contents')
args = parser.parse_args()
- if args.exclude_h:
- exclude_h = [int(i) for i in args.exclude_h.split(',')]
+ paths = args.Input if len(args.Input) > 0 else [documentsDefault]
+
+ changedFiles = updateDocumentToC(paths=paths, min_toc_len=args.minTocEntries, verbose=args.verbose)
+
+ if changedFiles > 0:
+ print( "Processed table of contents in " + str(changedFiles) + " file(s)" )
else:
- exclude_h = None
-
- cont = markdown_toclify(input_file=args.InputFile,
- output_file=args.output,
- github=args.github,
- back_to_top=args.back_to_top,
- nolink=args.nolink,
- no_toc_header=args.no_toc_header,
- spacer=args.spacer,
- placeholder=args.placeholder,
- exclude_h=exclude_h)
-
- if not args.output:
- print(cont)
+ print( "No table of contents added or updated" )
if __name__ == '__main__':
- commandline()
+ updateDocumentToCMain()
+
+# end of file