💾 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

View Raw

More Information

-=-=-=-=-=-=-

gmikit.git

git @ anachronauts.club

summary

tree

log

refs

gmikit.git/html.go | 3 KB

view raw

  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 }