, and tags; the footer.
"""
# importing required libraries
import sys
import re
import html
# A dictionary that maps regex to match at the beginning of gmi lines
# to their corresponding HTML tag names. Used by
# convert_single_line().
tags_dict = {
r"^# (.*)": "h1",
r"^## (.*)": "h2",
r"^### (.*)": "h3",
r"^\* (.*)": "li",
r"^> (.*)": "blockquote",
r"^=>\s*(\S+)(\s+.*)?": "a"
}
# This function takes a string of gemtext as input and returns a
# string of HTML
def convert_single_line(gmi_line):
for pattern in tags_dict.keys():
match = re.match(pattern, gmi_line)
if match:
tag = tags_dict[pattern]
groups = match.groups()
if tag == "a":
href = re.sub("^gemini://", "https://", groups[0])
href = re.sub(r"\.gmi$", ".html", href)
if len(groups) > 1 and groups[1] is not None:
inner_text = groups[1].strip()
else:
inner_text = href
return f"<{tag} href='{href}'>{inner_text}{tag}>
"
else:
inner_text = html.escape(groups[0].strip())
return f"<{tag}>{inner_text}{tag}>"
gmi_line = html.escape(gmi_line)
return f"{gmi_line}
"
# Reads the contents of the input file line by line and outputs HTML.
# Renders text in preformat blocks (toggled by ```) as multiline
# tags.
def main(args):
with open(args[3]) as gmi, open(args[4], "w") as output:
# Write header
header = open(args[1])
output.write(header.read())
header.close()
# Parse gmitext
pre = False
listing = False
for line in gmi:
if line.startswith("```"):
pre = not pre
if pre:
line = line.rstrip()
if len(line) > 3:
line = html.escape(line[3:])
output.write(f"\n")
else:
output.write("\n")
else:
output.write("\n")
elif pre:
output.write(html.escape(line))
else:
line = line.rstrip()
if line.startswith("*") and not listing:
listing = True
output.write("\n")
if not line.startswith("*") and listing:
listing = False
output.write("
\n")
output_line = convert_single_line(line)
output.write(output_line+"\n")
# Write footer
footer = open(args[2])
output.write(footer.read())
footer.close()
# Main guard
if __name__ == "__main__":
main(sys.argv)