all repos — flounder @ d47a986e83bfba489d6c7a5cf05c602f64254f74

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 blockquote bool
 21	var list bool
 22	var title string
 23	for _, l := range text {
 24		if _, ok := l.(gemini.LineQuote); ok {
 25			if !blockquote {
 26				blockquote = true
 27				fmt.Fprintf(&b, "<blockquote>\n")
 28			}
 29		} else if blockquote {
 30			blockquote = false
 31			fmt.Fprintf(&b, "</blockquote>\n")
 32		}
 33		if _, ok := l.(gemini.LineListItem); ok {
 34			if !list {
 35				list = true
 36				fmt.Fprint(&b, "<ul>\n")
 37			}
 38		} else if list {
 39			list = false
 40			fmt.Fprint(&b, "</ul>\n")
 41		}
 42		switch l.(type) {
 43		case gemini.LineLink:
 44			link := l.(gemini.LineLink)
 45			urlstring := html.EscapeString(link.URL)
 46			// u = ctx.URL.ResolveReference(u) ?
 47			u, err := url.Parse(urlstring)
 48			if err != nil {
 49				continue
 50			}
 51			if reqUrl != nil {
 52				u = reqUrl.ResolveReference(u)
 53			}
 54			if u.Scheme == "gemini" || (reqUrl != nil && u.Scheme == "") {
 55				if strings.HasSuffix(u.Host, c.Host) {
 56					u.Scheme = ""
 57					urlstring = html.EscapeString(u.String())
 58				} else {
 59					u.Path = fmt.Sprintf("/%s%s", u.Host, u.Path)
 60					u.Scheme = ""
 61					u.Host = "proxy." + c.Host
 62					urlstring = html.EscapeString(u.String())
 63				}
 64			}
 65			name := html.EscapeString(link.Name)
 66			if name == "" {
 67				name = urlstring
 68			}
 69			fmt.Fprintf(&b, "<p><a href='%s'>%s</a></p>\n", urlstring, name)
 70		case gemini.LinePreformattingToggle:
 71			pre = !pre
 72			if pre {
 73				altText := string(l.(gemini.LinePreformattingToggle))
 74				if altText != "" {
 75					altText = html.EscapeString(altText)
 76					fmt.Fprintf(&b, "<pre title='%s'>\n", altText)
 77				} else {
 78					fmt.Fprint(&b, "<pre>\n")
 79				}
 80			} else {
 81				fmt.Fprint(&b, "</pre>\n")
 82			}
 83		case gemini.LinePreformattedText:
 84			text := string(l.(gemini.LinePreformattedText))
 85			fmt.Fprintf(&b, "%s\n", html.EscapeString(text))
 86		case gemini.LineHeading1:
 87			text := string(l.(gemini.LineHeading1))
 88			fmt.Fprintf(&b, "<h1>%s</h1>\n", html.EscapeString(text))
 89			if title == "" {
 90				title = text
 91			} // TODO deal with repetition
 92		case gemini.LineHeading2:
 93			text := string(l.(gemini.LineHeading2))
 94			fmt.Fprintf(&b, "<h2>%s</h2>\n", html.EscapeString(text))
 95			if title == "" {
 96				title = text
 97			}
 98		case gemini.LineHeading3:
 99			text := string(l.(gemini.LineHeading3))
100			fmt.Fprintf(&b, "<h3>%s</h3>\n", html.EscapeString(text))
101			if title == "" {
102				title = text
103			}
104		case gemini.LineListItem:
105			text := string(l.(gemini.LineListItem))
106			fmt.Fprintf(&b, "<li>%s</li>\n", html.EscapeString(text))
107		case gemini.LineQuote:
108			text := string(l.(gemini.LineQuote))
109			fmt.Fprintf(&b, "<p>%s</p>\n", html.EscapeString(text))
110		case gemini.LineText:
111			text := string(l.(gemini.LineText))
112			if text == "" {
113				fmt.Fprint(&b, "<br>\n")
114			} else {
115				fmt.Fprintf(&b, "<p>%s</p>\n", html.EscapeString(text))
116			}
117		}
118	}
119	if pre {
120		fmt.Fprint(&b, "</pre>\n")
121	}
122	if list {
123		fmt.Fprint(&b, "</ul>\n")
124	}
125	if blockquote {
126		fmt.Fprint(&b, "</blockquote>\n")
127	}
128	return ConvertedGmiDoc{
129		b.String(),
130		title,
131	}
132}