Add markdown table-of-contents parser
This commit is contained in:
parent
67abc3bb5e
commit
84c93a6371
89
bin/table_of_contents_markdown.awk
Executable file
89
bin/table_of_contents_markdown.awk
Executable 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]
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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: -->
|
|
||||||
|
|
Loading…
Reference in a new issue