💾 Archived View for anachronauts.club › cgi-bin › repos › cgi › gmikit.git › tree › trunk › html.go captured on 2021-12-05 at 23:47:19. Gemini links have been rewritten to link to archived content
-=-=-=-=-=-=-
1 package gmikit 2 3 import ( 4 "fmt" 5 "html/template" 6 "io" 7 "net/url" 8 ) 9 10 type UrlRewriter func(*url.URL) (*url.URL, string, error) 11 12 type element int 13 14 const ( 15 Clear element = iota 16 Pre 17 AltPre 18 Quoting 19 Para 20 List 21 ) 22 23 type HtmlWriter struct { 24 w io.Writer 25 Rewriter UrlRewriter 26 elem element 27 } 28 29 func NewHtmlWriter(w io.Writer, rewriter UrlRewriter) *HtmlWriter { 30 return &HtmlWriter{ 31 w: w, 32 Rewriter: rewriter, 33 elem: Clear, 34 } 35 } 36 37 func (h *HtmlWriter) Write(p []byte) (n int, err error) { 38 return h.w.Write(p) 39 } 40 41 func (h *HtmlWriter) Clear() error { 42 var err error 43 switch h.elem { 44 case Pre: 45 _, err = fmt.Fprintf(h.w, "</pre>\n") 46 case AltPre: 47 _, err = fmt.Fprintf(h.w, "</pre>\n</div>\n") 48 case Quoting: 49 _, err = fmt.Fprintf(h.w, "</blockquote>\n") 50 case Para: 51 _, err = fmt.Fprintf(h.w, "</p>\n") 52 case List: 53 _, err = fmt.Fprint(h.w, "</ul>\n") 54 } 55 if err != nil { 56 return err 57 } 58 h.elem = Clear 59 return nil 60 } 61 62 func (h *HtmlWriter) Begin() error { return nil } 63 64 func (h *HtmlWriter) End() error { 65 return h.Clear() 66 } 67 68 func (h *HtmlWriter) Text(text string) error { 69 if h.elem != Para { 70 err := h.Clear() 71 if err != nil { 72 return err 73 } 74 75 if _, err := fmt.Fprintf(h.w, "<p>"); err != nil { 76 return err 77 } 78 79 h.elem = Para 80 } 81 82 _, err := fmt.Fprintf(h.w, "%s\n", template.HTMLEscapeString(text)) 83 return err 84 } 85 86 var anchor = template.Must( 87 template.New("anchor").Parse( 88 "<a href=\"{{.Href}}\"" + 89 "{{ if .Class }} class=\"{{.Class}}\" {{- end }}>" + 90 "{{.Text}}</a><br/>\n")) 91 92 func (h *HtmlWriter) Link(target *url.URL, friendlyName string) error { 93 err := h.Clear() 94 if err != nil { 95 return err 96 } 97 98 class := target.Scheme 99 if h.Rewriter != nil { 100 target, class, err = h.Rewriter(target) 101 if err != nil { 102 return err 103 } 104 } 105 106 if friendlyName == "" { 107 friendlyName = target.String() 108 } 109 110 return anchor.Execute(h.w, struct { 111 Href *url.URL 112 Class string 113 Text string 114 }{ 115 Href: target, 116 Class: class, 117 Text: friendlyName, 118 }) 119 } 120 121 var altPre = template.Must( 122 template.New("altPre"). 123 Parse(`<div aria-label="{{.}}"> 124 <pre aria-hidden="true" alt="{{.}}"> 125 `)) 126 127 func (h *HtmlWriter) PreformattingToggle(altText string) error { 128 elem := h.elem 129 err := h.Clear() 130 if err != nil { 131 return err 132 } 133 134 if elem == Pre || elem == AltPre { 135 return nil 136 } 137 138 if altText == "" { 139 h.elem = Pre 140 _, err := fmt.Fprint(h.w, "<pre>\n") 141 return err 142 } else { 143 h.elem = AltPre 144 return altPre.Execute(h.w, altText) 145 } 146 } 147 148 func (h *HtmlWriter) PreformattedText(text string) error { 149 _, err := fmt.Fprintf(h.w, "%s\n", template.HTMLEscapeString(text)) 150 return err 151 } 152 153 var h1 = template.Must( 154 template.New("h1"). 155 Parse("<h1>{{.}}</h1>\n")) 156 157 func (h *HtmlWriter) Heading1(text string) error { 158 err := h.Clear() 159 if err != nil { 160 return err 161 } 162 163 return h1.Execute(h.w, text) 164 } 165 166 var h2 = template.Must( 167 template.New("h2"). 168 Parse("<h2>{{.}}</h2>\n")) 169 170 func (h *HtmlWriter) Heading2(text string) error { 171 err := h.Clear() 172 if err != nil { 173 return err 174 } 175 176 return h2.Execute(h.w, text) 177 } 178 179 var h3 = template.Must( 180 template.New("h3"). 181 Parse("<h3>{{.}}</h3>\n")) 182 183 func (h *HtmlWriter) Heading3(text string) error { 184 err := h.Clear() 185 if err != nil { 186 return err 187 } 188 189 return h3.Execute(h.w, text) 190 } 191 192 var li = template.Must( 193 template.New("li"). 194 Parse("<li>{{.}}</li>\n")) 195 196 func (h *HtmlWriter) UnorderedListItem(text string) error { 197 if h.elem != List { 198 err := h.Clear() 199 if err != nil { 200 return err 201 } 202 203 if _, err := fmt.Fprintf(h.w, "<ul>\n"); err != nil { 204 return err 205 } 206 h.elem = List 207 } 208 209 return li.Execute(h.w, text) 210 } 211 212 func (h *HtmlWriter) Quote(text string) error { 213 if h.elem != Quoting { 214 err := h.Clear() 215 if err != nil { 216 return err 217 } 218 219 if _, err := fmt.Fprintf(h.w, "<blockquote>"); err != nil { 220 return err 221 } 222 h.elem = Quoting 223 } 224 225 _, err := fmt.Fprintf(h.w, "%s\n", template.HTMLEscapeString(text)) 226 return err 227 } 228 229 func GmiToHtml(r io.Reader, w io.Writer) error { 230 return ParseLines(r, NewHtmlWriter(w, nil)) 231 }