From d450e3bfb8468c617f14ad12dd98fb697ff10580 Mon Sep 17 00:00:00 2001
From: tslil clingman <>
Date: Wed, 21 Apr 2021 14:52:08 -0400
Subject: compiling l-3.space for the web
---
gmi2html.py | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 131 insertions(+)
create mode 100644 gmi2html.py
(limited to 'gmi2html.py')
diff --git a/gmi2html.py b/gmi2html.py
new file mode 100644
index 0000000..e102380
--- /dev/null
+++ b/gmi2html.py
@@ -0,0 +1,131 @@
+#!/usr/bin/env python3
+
+# Convert gemtext to HTML, accepting HTML header and footer files
+
+# Copyright 2021 huntingb
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, version 3 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see https://www.gnu.org/licenses/.
+
+# Original code found at:
+# https://github.com/huntingb/gemtext-html-converter
+
+# Modified by tslil clingman, April 2021 in the following ways
+# - added HTML escaping of all non-pre lines
+# - added header and footer file input
+# - added generation of
for list items
+# - fixed stripping of lines, no longer occurs in pre blocks, and
+# otherwise is rstrip only
+# - replace := syntax with something my version of python3 accepts
+# - modified description below
+
+"""
+HUNTER'S SIMPLE GEMTEXT TO HTML CONVERTER
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+A simple script that converts gemtext to HTML.
+
+Takes four arguments from stdin. The first two arguments are the names
+of files which will be used as a header and footer for the generated
+output, in that order.
+
+The next argument is the name of of a gemtext file, and the last
+argument is the name of the desired output file.
+
+The output file consists of, in order: the header; the lines of
+gemtext in the input file converted to their HTML equivalents: ,
+, ,
, , , , 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)
--
cgit v1.3.1