flounder

A simple gemini site builder
git clone git://git.alexwennerberg.com/flounder
Log | Files | Refs | README | LICENSE

gmi2html.go (3494B) - raw


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