a love letter to tangled (android, iOS, and a search API)
1package view
2
3import (
4 "embed"
5 "html/template"
6 "io/fs"
7 "net/http"
8)
9
10//go:embed templates static api-docs.json
11var content embed.FS
12
13var pageTemplates map[string]*template.Template
14
15func init() {
16 pageTemplates = make(map[string]*template.Template)
17
18 for _, name := range []string{
19 "index.html",
20 } {
21 pageTemplates[name] = template.Must(template.New("layout").ParseFS(content,
22 "templates/layout.html",
23 "templates/"+name,
24 ))
25 }
26
27 for _, name := range []string{
28 "docs/index.html",
29 "docs/search.html",
30 "docs/documents.html",
31 "docs/health.html",
32 "docs/actors.html",
33 "docs/issues.html",
34 "docs/pulls.html",
35 "docs/identity.html",
36 "docs/activity.html",
37 "docs/profiles.html",
38 "docs/xrpc.html",
39 } {
40 pageTemplates[name] = template.Must(template.New("layout").ParseFS(content,
41 "templates/layout.html",
42 "templates/partials/doc-entry.html",
43 "templates/"+name,
44 ))
45 }
46}
47
48// Handler returns an http.Handler that serves the site pages and static assets.
49func Handler() http.Handler {
50 mux := http.NewServeMux()
51
52 staticFS, _ := fs.Sub(content, "static")
53 mux.Handle("GET /static/", http.StripPrefix("/static/", http.FileServerFS(staticFS)))
54
55 mux.HandleFunc("GET /docs/search", renderDocPage("docs/search.html", "search"))
56 mux.HandleFunc("GET /docs/documents", renderDocPage("docs/documents.html", "documents"))
57 mux.HandleFunc("GET /docs/health", renderDocPage("docs/health.html", "health"))
58 mux.HandleFunc("GET /docs/actors", renderDocPage("docs/actors.html", "actors"))
59 mux.HandleFunc("GET /docs/issues", renderDocPage("docs/issues.html", "issues"))
60 mux.HandleFunc("GET /docs/pulls", renderDocPage("docs/pulls.html", "pulls"))
61 mux.HandleFunc("GET /docs/identity", renderDocPage("docs/identity.html", "identity"))
62 mux.HandleFunc("GET /docs/activity", renderDocPage("docs/activity.html", "activity"))
63 mux.HandleFunc("GET /docs/profiles", renderDocPage("docs/profiles.html", "profiles"))
64 mux.HandleFunc("GET /docs/xrpc", renderDocPage("docs/xrpc.html", "proxy"))
65 mux.HandleFunc("GET /docs", renderPage("docs/index.html"))
66 mux.HandleFunc("GET /{$}", renderPage("index.html"))
67
68 return mux
69}
70
71func renderPage(name string) http.HandlerFunc {
72 return func(w http.ResponseWriter, r *http.Request) {
73 tmpl, ok := pageTemplates[name]
74 if !ok {
75 http.NotFound(w, r)
76 return
77 }
78 w.Header().Set("Content-Type", "text/html; charset=utf-8")
79 if err := tmpl.ExecuteTemplate(w, "layout", nil); err != nil {
80 http.Error(w, "template error", http.StatusInternalServerError)
81 }
82 }
83}
84
85func renderDocPage(name, page string) http.HandlerFunc {
86 return func(w http.ResponseWriter, r *http.Request) {
87 tmpl, ok := pageTemplates[name]
88 if !ok {
89 http.NotFound(w, r)
90 return
91 }
92 w.Header().Set("Content-Type", "text/html; charset=utf-8")
93 if err := tmpl.ExecuteTemplate(w, "layout", PageDocs(page)); err != nil {
94 http.Error(w, "template error", http.StatusInternalServerError)
95 }
96 }
97}