all repos — flounder @ 427348063f7b9c9eaab913ff30459b2ae957866b

A small site builder for the Gemini protocol

gmi2html.go (view raw)

  1package main
  2
  3import (
  4	"fmt"
  5	"html"
  6	"net/url"
  7	"strings"
  8
  9	"git.sr.ht/~adnano/go-gemini"
 10)
 11
 12type ConvertedGmiDoc struct {
 13	Content string
 14	Title   string
 15}
 16
 17func textToHTML(reqUrl *url.URL, text gemini.Text) ConvertedGmiDoc {
 18	var b strings.Builder
 19	var pre bool
 20	var list bool
 21	var title string
 22	for _, l := range text {
 23		if _, ok := l.(gemini.LineListItem); ok {
 24			if !list {
 25				list = true
 26				fmt.Fprint(&b, "<ul>\n")
 27			}
 28		} else if list {
 29			list = false
 30			fmt.Fprint(&b, "</ul>\n")
 31		}
 32		switch l.(type) {
 33		case gemini.LineLink:
 34			link := l.(gemini.LineLink)
 35			urlstring := html.EscapeString(link.URL)
 36			// u = ctx.URL.ResolveReference(u) ?
 37			u, err := url.Parse(urlstring)
 38			if err != nil {
 39				continue
 40			}
 41			if reqUrl != nil {
 42				u = reqUrl.ResolveReference(u)
 43			}
 44			if u.Scheme == "gemini" || (reqUrl != nil && u.Scheme == "") {
 45				if strings.HasSuffix(u.Host, c.Host) {
 46					u.Scheme = ""
 47					urlstring = html.EscapeString(u.String())
 48				} else {
 49					u.Path = fmt.Sprintf("/%s%s", u.Host, u.Path)
 50					u.Scheme = ""
 51					u.Host = "proxy." + c.Host
 52					urlstring = html.EscapeString(u.String())
 53				}
 54			}
 55			name := html.EscapeString(link.Name)
 56			if name == "" {
 57				name = urlstring
 58			}
 59			fmt.Fprintf(&b, "<p><a href='%s'>%s</a></p>\n", urlstring, name)
 60		case gemini.LinePreformattingToggle:
 61			pre = !pre
 62			if pre {
 63				altText := string(l.(gemini.LinePreformattingToggle))
 64				if altText != "" {
 65					altText = html.EscapeString(altText)
 66					fmt.Fprintf(&b, "<pre title='%s'>\n", altText)
 67				} else {
 68					fmt.Fprint(&b, "<pre>\n")
 69				}
 70			} else {
 71				fmt.Fprint(&b, "</pre>\n")
 72			}
 73		case gemini.LinePreformattedText:
 74			text := string(l.(gemini.LinePreformattedText))
 75			fmt.Fprintf(&b, "%s\n", html.EscapeString(text))
 76		case gemini.LineHeading1:
 77			text := string(l.(gemini.LineHeading1))
 78			fmt.Fprintf(&b, "<h1>%s</h1>\n", html.EscapeString(text))
 79			if title == "" {
 80				title = text
 81			} // TODO deal with repetition
 82		case gemini.LineHeading2:
 83			text := string(l.(gemini.LineHeading2))
 84			fmt.Fprintf(&b, "<h2>%s</h2>\n", html.EscapeString(text))
 85			if title == "" {
 86				title = text
 87			}
 88		case gemini.LineHeading3:
 89			text := string(l.(gemini.LineHeading3))
 90			fmt.Fprintf(&b, "<h3>%s</h3>\n", html.EscapeString(text))
 91			if title == "" {
 92				title = text
 93			}
 94		case gemini.LineListItem:
 95			text := string(l.(gemini.LineListItem))
 96			fmt.Fprintf(&b, "<li>%s</li>\n", html.EscapeString(text))
 97		case gemini.LineQuote:
 98			text := string(l.(gemini.LineQuote))
 99			fmt.Fprintf(&b, "<blockquote>%s</blockquote>\n", html.EscapeString(text))
100		case gemini.LineText:
101			text := string(l.(gemini.LineText))
102			if text == "" {
103				fmt.Fprint(&b, "<br>\n")
104			} else {
105				fmt.Fprintf(&b, "<p>%s</p>\n", html.EscapeString(text))
106			}
107		}
108	}
109	if pre {
110		fmt.Fprint(&b, "</pre>\n")
111	}
112	if list {
113		fmt.Fprint(&b, "</ul>\n")
114	}
115	return ConvertedGmiDoc{
116		b.String(),
117		title,
118	}
119}