This repository has been archived by the owner on Jun 2, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathmd-toc.sh
61 lines (51 loc) · 1.82 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
#!/bin/bash
# md-toc.sh
############
# 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
# current 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 was obtained here:
# https://superuser.com/a/285878
#
# meleu - January/2019
INVALID_CHARS="'[]/?!:\`.,()*\";{}+=<>~$|#@&–—"
VALID_EXTENSIONS='markdown|mdown|mkdn|md|mkd|mdwn|mdtxt|mdtext|text|Rmd|txt'
USAGE="\nUsage:\n$0 markdownFile.md"
toc() {
local line
local level
local title
local anchor
while IFS='' read -r line || [[ -n "$line" ]]; do
level="$(echo "$line" | sed -E 's/^#(#+).*/\1/; s/#/ /g; s/^ //')"
title="$(echo "$line" | sed -E 's/^#+ //')"
anchor="$(echo "$title" | tr '[:upper:] ' '[:lower:]-' | tr -d "$INVALID_CHARS")"
echo "$level- [$title](#$anchor)"
done <<< "$(grep -E '^#{2,10} ' "$1" | tr -d '\r')"
}
validate_file() {
local mdfile="$1"
if [[ -z "$mdfile" ]]; then
echo "ERROR: missing input markdown file." >&2
return 1
elif [[ ! -f "$mdfile" ]]; then
echo "ERROR: \"$mdfile\": no such file." >&2
return 1
elif [[ ! "${mdfile##*.}" =~ ^($EXTENSIONS)$ ]]; then
echo "ERROR: \"$mdfile\": invalid file extension (is it a markdown formatted file?)." >&2
echo "Valid extensions: "$(echo "$VALID_EXTENSIONS" | tr '|' ' ')"" >&2
return 1
fi
}
main() {
local mdfile="$1"
validate_file "$mdfile" && toc "$mdfile" || echo -e "$USAGE"
}
[[ "$0" == "$BASH_SOURCE" ]] && main "$@"