-
Notifications
You must be signed in to change notification settings - Fork 7
/
mdtoc.py
executable file
·77 lines (60 loc) · 1.79 KB
/
mdtoc.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#!/usr/bin/env python
"""
Quick and dirty Python script to generate a (Markdown) table of contents
from a Markdown source file.
- Only supports the "# header", "## header", etc., style of Markdown header.
- The first "#" for a header must be in column 0.
- Skips any header with the text "Table of Contents" (regardless of case)
- Ignores fenced code blocks.
- Writes the table of contents to standard output.
You're responsible for copying and pasting the new table of contents into
the source Markdown document (for now).
"""
import sys
import os
import codecs
import re
if sys.version_info[0:2] < (3, 7):
sys.stderr.write("Requires Python 3.\n")
sys.exit(1)
if len(sys.argv) == 2:
max_level = 6
path = sys.argv[1]
elif len(sys.argv) == 3:
max_level = int(sys.argv[2])
path = sys.argv[1]
else:
print(
f"Usage: {os.path.basename(sys.argv[0])} markdown [maxlevel]", file=sys.stderr
)
sys.exit(1)
in_fenced_block = False
header_re = re.compile(r"^(#+)\s*(.*)\s*$")
for line in codecs.open(sys.argv[1], mode="r", encoding="utf-8").readlines():
if len(line.strip()) == 0:
continue
line = line.rstrip()
if line.startswith("```"):
in_fenced_block = not in_fenced_block
continue
if in_fenced_block:
continue
m = header_re.search(line)
if not m:
continue
level = len(m.group(1)) - 1
text = m.group(2).strip().replace("\\", "")
if text.lower() == "table of contents":
continue
if level > max_level:
continue
link_id = "".join(
[
c
for c in text.lower().replace(" ", "-")
if c not in ["\\", ".", ",", "`", "`", '"', "'"]
]
)
link = "#" + link_id
indent = " " * 4 * level
print(f"{indent}- [{text}]({link})")