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 return ConvertedGmiDoc{
126 b.String(),
127 title,
128 }
129}