A => LICENSE +19 -0
@@ 1,19 @@
+Copyright (c) 2021 Adnan Maolood
+
+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, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+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.
A => go.mod +5 -0
@@ 1,5 @@
+module git.sr.ht/~adnano/geminitohtml
+
+go 1.15
+
+require git.sr.ht/~adnano/go-gemini v0.2.0
A => go.sum +9 -0
@@ 1,9 @@
+git.sr.ht/~adnano/go-gemini v0.2.0 h1:24rGvovyXhUX8X51EJq8JeHMxxbO362KzCBtz6QNH7o=
+git.sr.ht/~adnano/go-gemini v0.2.0/go.mod h1:hQ75Y0i5jSFL+FQ7AzWVAYr5LQsaFC7v3ZviNyj46dY=
+golang.org/x/net v0.0.0-20210119194325-5f4716e94777 h1:003p0dJM77cxMSyCPFphvZf/Y5/NXf5fzg6ufd1/Oew=
+golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
A => main.go +80 -0
@@ 1,80 @@
+// Command geminitohtml is a Gemini text to HTML converter.
+package main
+
+import (
+ "fmt"
+ "html"
+ "io"
+ "os"
+
+ "git.sr.ht/~adnano/go-gemini"
+)
+
+func main() {
+ hw := HTMLWriter{
+ out: os.Stdout,
+ }
+ gemini.ParseLines(os.Stdin, hw.Handle)
+ hw.Finish()
+}
+
+type HTMLWriter struct {
+ out io.Writer
+ pre bool
+ list bool
+}
+
+func (h *HTMLWriter) Handle(line gemini.Line) {
+ if _, ok := line.(gemini.LineListItem); ok {
+ if !h.list {
+ h.list = true
+ fmt.Fprint(h.out, "<ul>\n")
+ }
+ } else if h.list {
+ h.list = false
+ fmt.Fprint(h.out, "</ul>\n")
+ }
+ switch line := line.(type) {
+ case gemini.LineLink:
+ url := html.EscapeString(line.URL)
+ name := html.EscapeString(line.Name)
+ if name == "" {
+ name = url
+ }
+ fmt.Fprintf(h.out, "<p><a href='%s'>%s</a></p>\n", url, name)
+ case gemini.LinePreformattingToggle:
+ h.pre = !h.pre
+ if h.pre {
+ fmt.Fprint(h.out, "<pre>\n")
+ } else {
+ fmt.Fprint(h.out, "</pre>\n")
+ }
+ case gemini.LinePreformattedText:
+ fmt.Fprintf(h.out, "%s\n", html.EscapeString(string(line)))
+ case gemini.LineHeading1:
+ fmt.Fprintf(h.out, "<h1>%s</h1>\n", html.EscapeString(string(line)))
+ case gemini.LineHeading2:
+ fmt.Fprintf(h.out, "<h2>%s</h2>\n", html.EscapeString(string(line)))
+ case gemini.LineHeading3:
+ fmt.Fprintf(h.out, "<h3>%s</h3>\n", html.EscapeString(string(line)))
+ case gemini.LineListItem:
+ fmt.Fprintf(h.out, "<li>%s</li>\n", html.EscapeString(string(line)))
+ case gemini.LineQuote:
+ fmt.Fprintf(h.out, "<blockquote>%s</blockquote>\n", html.EscapeString(string(line)))
+ case gemini.LineText:
+ if line == "" {
+ fmt.Fprint(h.out, "<br>\n")
+ } else {
+ fmt.Fprintf(h.out, "<p>%s</p>\n", html.EscapeString(string(line)))
+ }
+ }
+}
+
+func (h *HTMLWriter) Finish() {
+ if h.pre {
+ fmt.Fprint(h.out, "</pre>\n")
+ }
+ if h.list {
+ fmt.Fprint(h.out, "</ul>\n")
+ }
+}