Add markdown table-of-contents parser

This commit is contained in:
Akemi Izuko 2023-12-23 20:13:59 -07:00
parent 94834de634
commit d37a759e3a
Signed by: akemi
GPG key ID: 8DE0764E1809E9FC
3 changed files with 114 additions and 3 deletions

View file

@ -0,0 +1,89 @@
#!/usr/bin/env -S awk -f
# Create a table of contents for a markdown file. Respects code blocks!
#
# ARGS (use these with -v[name]=[value] when calling):
# int heading : Indenting level for the "highest" heading. DEFAULT = 1
# int table_only : Only print the table of contents. DEFAULT = 0
#
# EXAMPLE RUN:
# $ table_of_contents_markdown.awk -vtable_only=1 -vheading=2 <<HERE
# # Main
# ## Hello
# ### Deep header
# ##### 2 deeper
# #### 1 deeper
# # Section
# #### No way
# HERE
#
# EXAMPLE OUTPUT:
# # Table of Contents
# 1. [Main](#main)
# - [Hello](#hello)
# * [Deep header](#deep-header)
# * [2 deeper](#2-deeper)
# * [1 deeper](#1-deeper)
# 2. [Section](#section)
# * [No way](#no-way)
# Converts a markdown heading to a pandoc style id
# Steps:
# 1. Convert to lowercase
# 2. Non-word? text is removed
# 3. Two or more hyphens in a row are converted to one
# 4. Spaces are converted to hyphens
# 5. If the same id has already been generated, a unique incrementing number
# is appended, starting at 1
#
# *Gitlab seems to preprend for step 5 instead
# *Github seems to skip step 4
function heading_to_id(heading, id) {
id = tolower(heading);
gsub(/[^-A-z0-9 ]/, "", id);
gsub(/-+/, "-", id);
gsub(/ +/, "-", id);
if (existing_ids[id]++)
id = sprintf("%d-%s", existing_ids[id]-1, id);
return id
}
BEGIN { if (heading == 0) heading = 1; }
/```/ { is_code_block = !is_code_block }
/^#+ [^ ].+$/ && !is_code_block {
match($0, /#+/);
heading_level = RLENGTH
s = substr($0, RSTART+RLENGTH+1);
s = sprintf("[%s](#%s)", s, heading_to_id(s))
if (heading_level <= heading) {
s = sprintf(" %d. %s", ++nb_heading, s);
} else if (heading_level == heading + 1) {
s = sprintf(" - %s", s);
} else {
s = " * "s
for (i = 0; i < heading_level - heading; i++) s = " "s;
}
table_of_contents[toc++] = s
}
{ file[lines++] = $0 }
END {
for (i = 0; i < heading; i++) printf "#";
print " Table of Contents"
for (t in table_of_contents)
print table_of_contents[t]
if (!table_only) {
print ""
for (line in file)
print file[line]
}
}

View file

@ -1,3 +1,11 @@
## Table of Contents
1. [Git + SSH = :rocket:](#git-ssh-rocket)
2. [Generating ssh keys for git remotes](#generating-ssh-keys-for-git-remotes)
3. [User keys](#user-keys)
4. [Deployment keys](#deployment-keys)
5. [Managing multiple remotes](#managing-multiple-remotes)
6. [Further reading](#further-reading)
# Git + SSH = :rocket: # Git + SSH = :rocket:
Most git remotes, codeberg and github for example, encourage the use of SSH Most git remotes, codeberg and github for example, encourage the use of SSH
keys. These are extra-secure ways to manage your project. There are generally keys. These are extra-secure ways to manage your project. There are generally

View file

@ -1,3 +1,20 @@
## Table of Contents
1. [Bash](#bash)
* [Process priority](#process-priority)
* [Job Control in Bash](#job-control-in-bash)
* [Vim editing for Bash](#vim-editing-for-bash)
* [Stop yourself from deleting files](#stop-yourself-from-deleting-files)
* [Reusing commands](#reusing-commands)
* [Automated interactive input](#automated-interactive-input)
* [Bash scripting](#bash-scripting)
* [Other Bash uses](#other-bash-uses)
2. [Ed for terminal file editing](#ed-for-terminal-file-editing)
3. [Awk the programming language](#awk-the-programming-language)
- [Built in variables](#built-in-variables)
- [Regular expression](#regular-expression)
- [Recipes](#recipes)
- [Advanced examples](#advanced-examples)
# Bash # Bash
###### Process priority ###### Process priority
Since the processor must decide priority, it uses a scale from -20 through 20 to Since the processor must decide priority, it uses a scale from -20 through 20 to
@ -317,6 +334,3 @@ to check if an element with the string's index has been initialized in the array
$ awk '!unique[$0]++' duplicates.txt > uniques.txt $ awk '!unique[$0]++' duplicates.txt > uniques.txt
Removes duplicate lines. This exploits awk's automatic initialization of Removes duplicate lines. This exploits awk's automatic initialization of
variables with falsey values, 0 here, then turns that index truthy with `++` variables with falsey values, 0 here, then turns that index truthy with `++`
<!-- ex: set ft=markdown tw=80: -->