#
# gmi2html.awk -- AWK script to convert a file from text/gemini to text/html
#
# Copyright (c) 2021 Rodrigo S. Canibano (dracometallium)
# Copyright (c) 2021 Jeremy Potter (jwinnie)
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of this
# software and associated documentation files (the "Software"), to deal in the Software
# without restriction, including without limitation the rights to use, copy, modify,
# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# usage:
# $ awk -f gmi2html.awk \
# -v title=<title> \
# -v css=<css> \
# -v original=<original> < path/to/gmi > path/to/html
#
# parameters:
# <title>: the title of the document, used in the HTML <title>
# <css>: relative path to a CSS stylesheet
# <original>: URL of the original Gemini document, linked in the footer
# Begin HTML document
BEGIN {
printf "\
<!DOCTYPE html>\
<head>\
<meta charset=\"utf-8\">\
<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\
<link rel=\"stylesheet\" type=\"text/css\" href=\"%s\">\
<title>%s</title>\
</head>\
<body>", css, title
pre = 0
list = 0
}
# Escape left and right angle brackets
{
gsub(/</, "\\<")
gsub(/>/, "\\>")
}
# Detect beginning of code block
/^```/ && (pre == 0) {
pre = 1
printf "<pre><code>"
next
}
# Detect end of code block
/^```/ && (pre == 1) {
pre = 0
printf "</code></pre>"
next
}
# Output verbatim text inside of code block
(pre == 1) {
print $0
next
}
# Detect list item
/\* / {
# Detect if this is the first item in
# the list. If so, start a new <ul>.
if (list == 0) {
list = 1
printf "<ul>"
}
sub(/\* [ \t]*/, "")
printf "<li>%s</li>", $0
next
}
# Detect end of list
(list == 1) {
list = 0
printf "</ul>"
}
# Detect heading 3
/^###/ {
sub(/^#[#]*[ \t]*/, "")
printf "<h3>%s</h3>", $0
next
}
# Detect heading 2
/^##/ {
sub(/^#[#]*[ \t]*/, "")
printf "<h2>%s</h2>", $0
next
}
# Detect heading 1
/^#/ {
sub(/^#[#]*[ \t]*/, "")
printf "<h1>%s</h1>", $0
next
}
# Detect blockquote
/^>/ {
sub(/^>[ \t]*/, "")
printf "<blockquote>%s</blockquote>", $0
next
}
# Detect link
/^=>/ {
sub(/^=>[ \t]*/, "")
url = $0
sub(/[ \t].*$/, "", url)
text = $0
sub(url, "", text)
sub(/[ \t]*$/, "", text)
sub(/^[ \t]*/, "", text)
# If linking to a Gemini page, change the extension from
# .gmi to .html
if ((url !~ /^[a-zA-Z]*:\/\//) && ((url ~ /\.gmi$/) || (url ~ /\.gemini$/))) {
sub(/\.gmi$/, ".html", url)
sub(/\.gemini$/, ".html", url)
}
# Show URL if no link text is provided
if (text == "") {
text = url
}
printf "<p><a href=\"%s\">%s</a></p>", url, text
next
}
# For everything else, just use a <p> element
{
printf "<p>%s</p>", $0
}
# End HTML document
END {
# End all the remaining lists
if (list == 1) {
printf "</ul>"
}
# Add a footer pointing back to the original Gemini site,
# and advertising Gemini as a better protocol
printf "\
<hr>\
<footer>\
<small>\
Also available on <a href=\"gemini://%s\">Gemini</a>\
— a simpler, more secure World Wide Web.\
</small>\
</footer>\
</body>\
</html>", original
}