#!/bin/sh # hell - HTML in shell tx() { : "${RAW:=false}" if "$RAW"; then printf '%b\n' "$*" return fi while [ "$#" -gt 0 ] && printf %s "$1" do [ "$#" -gt 1 ] && printf ' ' shift done printf '\n' } el() { # el NAME [ATTR=VALUE...] [-] [TEXT...] el="$1"; shift READ_IN=true text= attr= class= for word; do case "$word" in \\*) # words starting with backslashes are text text="$text${text:+ }${word#\\}" ;; class=*) # otherwise, 'class=' is a special case class="${class:-class=\"}${class:+ }${word#class=}" ;; *=*) # otherwise, words containing an equals are attr=value pairs anam="${word%=*}" aval="${word#*=}" aval="${aval%\"}" aval="${aval#\"}" attr="$attr${attr:+ }${anam}=\"${aval}\"" ;; -) # otherwise, '-' denotes stdin "$READ_IN" && while IFS= read -r line; do text="$text${text:+ }$line" # this is very ugly but it works done ;; /) # close-tag flag: don't look for text from stdin READ_IN=false ;; *) # otherwise, it's text text="$text${text:+ }$word" ;; esac done # close out the class string if [ -n "$class" ]; then class="$class\"" attr="$attr${attr:+ }$class" fi # if there's no text, try reading from stdin if [ -z "$text" ] && "$READ_IN"; then while IFS= read -r line; do text="$text${text:+ }$line" # this is very ugly but it works done fi # print the thing printf '<%s%s>%s' "$el" "${attr:+ }$attr" "$text" # if there's text, close the tag [ -n "$text" ] && printf '' "$el" printf '\n' }