#!/usr/bin/awk -f
# Read gemtext and output html5
# v23
# each blank line after a blank line is an empty
# extra : convert --- to
# extra : lines starting with // are comments
#
# CHANGELOG:
# * add logo according to hyperlink protocol
# logo in
# * extra : lines starting with // are comments
# * removed since it is not xml
# * changed default for linklogo : disabled
# ''foo'' -> foo
# * removed ''code''
# * removed linklogos in
# * added anchors to headers
# * do everything in memory to allow top-printing toc
# * fix possible duplicate id
# * fix bug for closing if lists aren't followed by a blank line
# * fix xhtml validation if id start with number
# * fix
not vaild outside .
# * simpler link extension detection
# * removed toc
# * switch back to html5, no closing />
# * commented image insertion, just a link: click to see
# * anchors are now the header title
# * add title as description of link in anchors
# * add anchor class for css custom
# * restore toc
# * use
instead of empty
# * don't store html in memory, thus TOC is always in the end
# * TOC no longer in summary/details but in div
# * remove toc_title var
#
#
# options:
# -v anchors=0
# set to 1 to enable
#
# display anchor links in headers,
# with class "anchor" (for css)
# -v toc=5
# set to minimum of headers to display a table of content
# disable toc output with toc=0
# default = 6
# The table of content has id "toc" (for css)
# Add anywhere a link pointing to href="toc" to display it with the
# following CSS example:
# #toc{
# visibility:hidden;
# position:fixed;
# z-index:+1;
# width:100%;
# height:100%;
# visibility:hidden;
# }
# #toc:target { visibility:visible; }
#
BEGIN {
if (!toc) { toc = 6 } # default
if (!anchors) { anchors = 0 } # default
curlvl = 0
tocn = 0
toc_content = ""
}
function htmlescape(s) {
gsub(/&/,"\\&",s)
gsub(/,"\\<",s)
gsub(/>/,"\\>",s)
gsub(/"/,"\\"",s)
gsub(/'/,"\\'",s)
return s
}
function trim(s) {
sub(/^[[:blank:]]+/, "", s)
sub(/[[:blank:]]+$/, "", s)
return s
}
function toctoc() {
# print the toc
print ""
print toc_content
while (curlvl > 0) {
printf "\n\n";
curlvl--
}
print "
" # close toc
}
# commented line with //
/^\/\/[:blank:]?/ {
# remove leading spaces
comment = substr($0, length($1)+2)
printf("\n", comment);
next
}
# non empty line
/.+/ { blank = 0 }
# anything that is not a list
/^[^\*]/ {
if (ul == 1) {
ul = 0
printf("
\n");
}
}
# code block
/^```/ {
if (pre) { printf("\n") }
else { printf("") }
pre = (pre + 1) % 2 # toggle pre
next
}
pre {
printf("%s\n", htmlescape($0))
next
}
# empty line
/^$/ {
if (blank) { printf("
\n") }
blank = 1
next
}
/^\*/ {
if (ul == 0) { ul = 1; printf("\n") }
$1 = ""
printf("- %s
\n", htmlescape(trim($0)))
next
}
# links
/^=>/ {
href = htmlescape($2)
if ( NF > 2 ) {
title = substr($0, length($1)+ 1 + length($2)+1)
title = htmlescape(trim(title))
}
else { title = href }
href = trim(href)
lowerhref = tolower(href)
if ( lowerhref ~ /\.(jpg|jpeg|png|gif|svg)$/ ) {
printf("
\n",
href, href, title)
} else {
printf("%s
\n",
href, title)
}
next
}
# header
/^#{1,3}/ {
lvl = match($0, "[^#]") -1 # find if h3, h2 or h1
tocn++
headid = sprintf("_%d_%s",
tocn, gensub(/[^[:alnum:]]/, "", "g"))
t = substr($0, lvl+1)
t = htmlescape(trim(t))
headlink = sprintf("%s", headid, t, t)
if (toc) {
if (curlvl == lvl) {
toc_content = sprintf("%s\n- %s",
toc_content, headlink)
} else if (curlvl < lvl) {
while (curlvl < lvl) {
toc_content = sprintf("%s\n
\n- ", toc_content)
curlvl++
}
toc_content = sprintf("%s\n%s", toc_content, headlink)
} else if (curlvl > lvl) {
while (curlvl > lvl) {
toc_content = sprintf("%s
\n
",
toc_content)
curlvl--
}
toc_content = sprintf("%s \n- %s", toc_content, headlink)
}
}
if (anchors) {
header = sprintf("%s #",
t, headid, t)
} else {
header = sprintf("%s", t)
}
printf("%s\n",
lvl, headid, header, lvl)
next
}
/^>/ {
$1="";
printf("
%s
\n",\
htmlescape(trim($0)))
next
}
# horizontal rule
/^---/ { printf("
\n"); next }
# normal line
1 { printf("%s
\n", htmlescape($0)) }
END {
if (ul == 1) { printf("
\n") }
if (tocn > toc) { toctoc() }
}