About me: My name is Solène Rapenne, pronouns she/her. I like learning and sharing knowledge. Hobbies: '(BSD OpenBSD Qubes OS Lisp cmdline gaming security QubesOS internet-stuff). I love percent and lambda characters. OpenBSD developer solene@. No AI is involved in this blog.

Contact me: solene at dataswamp dot org or @solene@bsd.network (mastodon).

I'm a freelance OpenBSD, FreeBSD, Linux and Qubes OS consultant, this includes DevOps, DevSecOps, technical writing or documentation work. If you enjoy this blog, you can sponsor my open source work financially so I can write this blog and contribute to Free Software as my daily job.

Minimalistic markdown subset to html converter using awk

Written by Solène, on 26 August 2019.
Tags: #unix #awk

Comments on Fediverse/Mastodon

Hello

As on my blog I use different markup languages I would like to use a simpler markup language not requiring an extra package. To do so, I wrote an awk script handling titles, paragraphs and code blocks the same way markdown does.

16 December 2019 UPDATE: adc sent me a patch to add ordered and unordered list. Code below contain the addition.

It is very easy to use, like: awk -f mmd file.mmd > output.html

The script is the following:

BEGIN {
	in_code=0
	in_list_unordered=0
	in_list_ordered=0
	in_paragraph=0
}
    
{
	# escape < > characters
	gsub(/</,"\<",$0);
	gsub(/>/,"\>",$0);
    
	# close code blocks
	if(! match($0,/^    /)) {
		if(in_code) {
			in_code=0
			printf "</code></pre>\n"
		}
	}
    
	# close unordered list
	if(! match($0,/^- /)) {
		if(in_list_unordered) {
			in_list_unordered=0
			printf "</ul>\n"
		}
	}
    
	# close ordered list
	if(! match($0,/^[0-9]+\. /)) {
		if(in_list_ordered) {
			in_list_ordered=0
			printf "</ol>\n"
		}
	}
    
	# display titles
	if(match($0,/^#/)) {
		if(match($0,/^(#+)/)) {
			printf "<h%i>%s</h%i>\n", RLENGTH, substr($0,index($0,$2)), RLENGTH
		}
    
	# display code blocks
	} else if(match($0,/^    /)) {
		if(in_code==0) {
			in_code=1
			printf "<pre><code>"
			print substr($0,5)
		} else {
			print substr($0,5)
		}
    
	# display unordered lists
	} else if(match($0,/^- /)) {
		if(in_list_unordered==0) {
			in_list_unordered=1
			printf "<ul>\n"
			printf "<li>%s</li>\n", substr($0,3)
		} else {
			printf "<li>%s</li>\n", substr($0,3)
		}
    
	# display ordered lists
	} else if(match($0,/^[0-9]+\. /)) {
		n=index($0," ")+1
		if(in_list_ordered==0) {
			in_list_ordered=1
			printf "<ol>\n"
			printf "<li>%s</li>\n", substr($0,n)
		} else {
			printf "<li>%s</li>\n", substr($0,n)
		}
    
	# close p if current line is empty
	} else {
		if(length($0) == 0 && in_paragraph == 1 && in_code == 0) {
			in_paragraph=0
			printf "</p>"
		} # we are still in a paragraph
		if(length($0) != 0 && in_paragraph == 1) {
			print
		} # open a p tag if previous line is empty
		if(length(previous_line)==0 && in_paragraph==0) {
			in_paragraph=1
			printf "<p>%s\n", $0
		}
	}
	previous_line = $0
}
    
END {
	if(in_code==1) {
		printf "</code></pre>\n"
	}
	if(in_list_unordered==1) {
		printf "</ul>\n"
	}
	if(in_list_ordered==1) {
		printf "</ol>\n"
	}
	if(in_paragraph==1) {
		printf "</p>\n"
	}
}