75 lines
1.7 KiB
Bash
Executable file
75 lines
1.7 KiB
Bash
Executable file
#!/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
|