blog/content/posts/markdown-translator.md

2.7 KiB

title date draft category description
Markdown Transpiler Thingy 2020-07-21 false article Full Bash/GNU coreutils implementation in article

Markdown to HTML

A while back I made gensite a static site generator that was built with pandoc users in mind. Along with the main script I packaged another script translate.sh which is a (I think) full markdown to html translator.

It uses mostly coreutil things like perl, echo, sed, and grep so it's pretty portable to most systems. Oh and it's built with Bash; though I'm probably going to updated it to run with Dash, a very strict POSIX shell to make it even more compatible.

Oh yea did I mention its only 62 lines of actual code? Here's the full script in case you want it, or maybe want to add some new feature/syntax or whatevs.

Repo Link

#!/bin/bash

# Why? becausee a simple markdown to html converter is required for those that
# don't want to install pandoc that don't have it already

IFS=$'\n'
code=0
ul=0
paragraph() {
        # Replace ![](/file/path.png) with proper img tag links
        [ -z $1 ] && echo ''
        [ 1 = $code ] && echo $1 || \
        echo '<p>'$1'</p>' | sed -E 's/`(.*)`/<code>\1<\/code>/g;s/\!\[(.*)\]\((.*)\)/<img src="\2" alt="\1">/g;s/\[(.*)\]\((.*)\)/<a href="\2">\1<\/a>/g'
}

convert_links() {
        sed -E 's/\[(.*)\]\((.*)\)/<a href="\2">\1<\/a>/g' < /dev/stdin
}

header() {
        depth=$(echo $1 | grep '^##*' -o | tr -d '\n' | wc -m)
        line=${1:$depth}
        echo "<h$depth>$line</h$depth>" | convert_links
}

blockquote() {
        # remove starting > symbols before doing anything
        echo "<blockquote>${1:1}</blockquote>" | convert_links
}


fluff_trim() {
        perl -0777 -pe 's/<\/p>\n<p>//g;s/<p><\/p>//g' < /dev/stdin
}

code_chunk() {
        if [ 0 = $code ];then
                code=1
                echo '<pre><code>'
        else
                code=0
                echo '</pre></code>'
        fi
}

set_ul() {
        if [ 1 = $ul ];then
                ul=2
        fi
}

unordered_list() {
        case $ul in
                0)echo "<ul><li>${1:1}</li>";ul=1;;
                1)echo "<li>${1:1}</li>";ul=1;;
                2)echo "<li>${1:1}</li></ul>";ul=0;;
        esac
}

if [ -z $1 ];then
        echo Usage: $0 file.md
        exit 0
fi

while read line;do
        case $line in
                \#*) set_ul; header $line;;
                \>*) set_ul; blockquote $line;;
                \`\`\`) set_ul; code_chunk;;
                \**) unordered_list $line;;
                # TODO: ordered_lists
                *) set_ul; paragraph "$line";;
        esac
done < "$1" | fluff_trim | grep -v '^$'