-
Notifications
You must be signed in to change notification settings - Fork 2.4k
/
toc.sh
executable file
·74 lines (64 loc) · 1.68 KB
/
toc.sh
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
#!/usr/bin/env bash
set -Eeuo pipefail
self="$(basename "$0")"
usage() {
cat <<-EOU
usage: $self path/to/README.md
eg: $self README.md
WARNING: if README.md has the TOC-replacement comments,
README.md.bak will be clobbered and the TOC will be inserted
EOU
}
readme="${1:-}"
if ! shift || [ ! -f "$readme" ]; then usage >&2; exit 1; fi
toc="$(
gawk '
# ignore comments in code blocks, which are not headers but look like them
/^```/ { ignore = !ignore }
/^#/ && !ignore {
level = length($1)
$1 = ""
gsub(/^[[:space:]]|[[:space:]]$/, "")
++levelCounter[level]
for (i in levelCounter) {
if (i > level) {
levelCounter[i] = 0
}
}
prefix = levelCounter[level] ".\t"
for (i = 1; i < level; ++i) {
prefix = "\t" prefix
}
# https://github.com/thlorenz/anchor-markdown-header/blob/56f77a232ab1915106ad1746b99333bf83ee32a2/anchor-markdown-header.js#L20-L30
hash = tolower($0)
gsub(/ /, "-", hash)
gsub(/[\/?!:\[\]`.,()*"'"'"';{}+=<>~\$|#@&–—]/, "", hash)
gsub(/[。?!,、;:“”【】()〔〕[]﹃﹄“ ”‘’﹁﹂—…-~《》〈〉「」]/, "", hash)
printf "%s[%s](#%s)\n", prefix, $0, hash
}
' "$readme"
)"
toFile="${readme}.bak"
gawk -v toFile="$toFile" -v toc="$toc" '
BEGIN { printf "" > toFile }
/^<!-- AUTOGENERATED TOC -->$/ {
inToc = !inToc
seenToc = 1
if (inToc) {
print >> toFile
print "" >> toFile
print toc >> toFile
print "" >> toFile
print >> toFile
}
next
}
!inToc { print >> toFile }
END { if (!seenToc) { close(toFile); printf "" > toFile } }
' "$readme"
if [ -s "$toFile" ]; then
mv "$toFile" "$readme"
else
rm "$toFile"
echo "$toc"
fi