-
Notifications
You must be signed in to change notification settings - Fork 0
/
md-toc.sh
executable file
·95 lines (76 loc) · 2.46 KB
/
md-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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#!/usr/bin/env bash
# pre-commit
############
# This is the script is supposed to work as a git hook.
#
# I use it to update the README.md file of this repo
# everytime I make a commit.
#
# It must be named as '.git/hooks/pre-commit'
#
# For more info about Git Hooks: https://githooks.com/
#
# meleu: october/2020
readonly REPO_DIR="$(git rev-parse --git-dir)/.."
readonly INVALID_CHARS="'[]/?!:\`.,()*\";{}+=<>~$|#@&–—"
# Generates a Table of Contents getting a markdown file as input.
#
# Inspiration for this script:
# https://medium.com/@acrodriguez/one-liner-to-generate-a-markdown-toc-f5292112fd14
#
# The list of invalid chars is probably incomplete, but is good enough for my
# needs.
# Got the list from:
# https://github.com/thlorenz/anchor-markdown-header/blob/56f77a232ab1915106ad1746b99333bf83ee32a2/anchor-markdown-header.js#L25
#
# The list of valid markdown extensions were obtained here:
# https://superuser.com/a/285878
toc() {
local inputFile="$1"
local codeBlock='false'
local line
local level
local title
local anchor
while IFS='' read -r line || [[ -n "$line" ]]; do
if [[ "$line" = '```'* ]]; then
[[ "$codeBlock" = 'false' ]] && codeBlock='true' || codeBlock='false'
continue
fi
[[ "$codeBlock" = 'true' ]] && continue
title="$(sed -E 's/^#+ //' <<< "$line")"
if [[ "$line" = '# '* ]]; then
echo "- [${title}](${inputFile})"
continue
fi
level="$(sed -E 's/^#(#+).*/\1/; s/#/ /g' <<< "$line")"
anchor="$(tr '[:upper:] ' '[:lower:]-' <<< "$title" | tr -d "$INVALID_CHARS")"
echo "${level}- [${title}](${inputFile}#${anchor})"
done <<< "$(grep -E '^(#{1,10} |```)' "$inputFile" | tr -d '\r')"
}
updateReadme() {
local readme="${REPO_DIR}/README.md"
local file
local level
local currentLevel
if [[ ! -f "${readme}" ]]; then
echo "${readme}: file not found. Aborting..." >&2
exit 1
fi
sed -i '1,/^## Table of Contents/!d' "${readme}"
echo >> "${readme}"
for file in */*.md; do
# create a subheading for the directory
currentLevel="${file%/*}"
if [[ "${currentLevel}" != "${level}" ]]; then
level="${currentLevel}"
echo -e "\n### ${level}" >> "${readme}"
fi
# create a dropdown list (viewable only on the GitHub repo view)
echo -e "<details><summary>${file##*/}</summary><br>\n" >> "${readme}"
toc "${file}" >> "${readme}"
echo -e "\n</details>\n\n" >> "${readme}"
done
git add "${readme}"
}
updateReadme "$@"