forked from tangled.org/core
Monorepo for Tangled — https://tangled.org

implement cache busting for tw.css

- proper tabindex for login page form
- overflow for handles in profile page

authored by oppi.li and committed by Tangled 36fd5706 de928c06

Changed files
+39 -7
appview
pages
+1
appview/pages/funcmap.go
··· 168 } 169 return template.HTML(data) 170 }, 171 } 172 } 173
··· 168 } 169 return template.HTML(data) 170 }, 171 + "cssContentHash": CssContentHash, 172 } 173 } 174
+22 -1
appview/pages/pages.go
··· 2 3 import ( 4 "bytes" 5 "embed" 6 "fmt" 7 "html/template" 8 "io" ··· 730 731 func Cache(h http.Handler) http.Handler { 732 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 733 - if strings.HasSuffix(r.URL.Path, ".css") { 734 // on day for css files 735 w.Header().Set("Cache-Control", "public, max-age=86400") 736 } else { ··· 738 } 739 h.ServeHTTP(w, r) 740 }) 741 } 742 743 func (p *Pages) Error500(w io.Writer) error {
··· 2 3 import ( 4 "bytes" 5 + "crypto/sha256" 6 "embed" 7 + "encoding/hex" 8 "fmt" 9 "html/template" 10 "io" ··· 732 733 func Cache(h http.Handler) http.Handler { 734 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 735 + path := strings.Split(r.URL.Path, "?")[0] 736 + 737 + if strings.HasSuffix(path, ".css") { 738 // on day for css files 739 w.Header().Set("Cache-Control", "public, max-age=86400") 740 } else { ··· 742 } 743 h.ServeHTTP(w, r) 744 }) 745 + } 746 + 747 + func CssContentHash() string { 748 + cssFile, err := Files.Open("static/tw.css") 749 + if err != nil { 750 + log.Printf("Error opening CSS file: %v", err) 751 + return "" 752 + } 753 + defer cssFile.Close() 754 + 755 + hasher := sha256.New() 756 + if _, err := io.Copy(hasher, cssFile); err != nil { 757 + log.Printf("Error hashing CSS file: %v", err) 758 + return "" 759 + } 760 + 761 + return hex.EncodeToString(hasher.Sum(nil))[:8] // Use first 8 chars of hash 762 } 763 764 func (p *Pages) Error500(w io.Writer) error {
+1 -2
appview/pages/templates/layouts/base.html
··· 8 content="width=device-width, initial-scale=1.0" 9 /> 10 <script src="/static/htmx.min.js"></script> 11 - <link href="/static/tw.css" rel="stylesheet" type="text/css" /> 12 - 13 <title>{{ block "title" . }}{{ end }} · tangled</title> 14 {{ block "extrameta" . }}{{ end }} 15 </head>
··· 8 content="width=device-width, initial-scale=1.0" 9 /> 10 <script src="/static/htmx.min.js"></script> 11 + <link rel="stylesheet" href="/static/tw.css?{{ cssContentHash }}" type="text/css" /> 12 <title>{{ block "title" . }}{{ end }} · tangled</title> 13 {{ block "extrameta" . }}{{ end }} 14 </head>
+10 -2
appview/pages/templates/user/login.html
··· 8 content="width=device-width, initial-scale=1.0" 9 /> 10 <script src="/static/htmx.min.js"></script> 11 - <link rel="stylesheet" href="/static/tw.css" type="text/css" /> 12 <title>login</title> 13 </head> 14 <body class="flex items-center justify-center min-h-screen"> ··· 27 > 28 <div class="flex flex-col"> 29 <label for="handle">handle</label> 30 - <input type="text" id="handle" name="handle" required /> 31 <span class="text-xs text-gray-500 mt-1"> 32 You need to use your 33 <a href="https://bsky.app">Bluesky</a> handle to log ··· 41 type="password" 42 id="app_password" 43 name="app_password" 44 required 45 /> 46 <span class="text-xs text-gray-500 mt-1"> ··· 57 class="btn w-full my-2 mt-6" 58 type="submit" 59 id="login-button" 60 > 61 <span>login</span> 62 </button>
··· 8 content="width=device-width, initial-scale=1.0" 9 /> 10 <script src="/static/htmx.min.js"></script> 11 + <link rel="stylesheet" href="/static/tw.css?{{ cssContentHash }}" type="text/css" /> 12 <title>login</title> 13 </head> 14 <body class="flex items-center justify-center min-h-screen"> ··· 27 > 28 <div class="flex flex-col"> 29 <label for="handle">handle</label> 30 + <input 31 + type="text" 32 + id="handle" 33 + name="handle" 34 + tabindex="1" 35 + required 36 + /> 37 <span class="text-xs text-gray-500 mt-1"> 38 You need to use your 39 <a href="https://bsky.app">Bluesky</a> handle to log ··· 47 type="password" 48 id="app_password" 49 name="app_password" 50 + tabindex="2" 51 required 52 /> 53 <span class="text-xs text-gray-500 mt-1"> ··· 64 class="btn w-full my-2 mt-6" 65 type="submit" 66 id="login-button" 67 + tabindex="3" 68 > 69 <span>login</span> 70 </button>
+5 -2
appview/pages/templates/user/profile.html
··· 108 <img class="w-3/4 rounded-full p-2" src="{{ .AvatarUri }}" /> 109 {{ end }} 110 </div> 111 - <p class="text-xl font-bold text-center dark:text-white"> 112 - {{ truncateAt30 (didOrHandle .UserDid .UserHandle) }} 113 </p> 114 <div class="text-sm text-center dark:text-gray-300"> 115 <span>{{ .ProfileStats.Followers }} followers</span>
··· 108 <img class="w-3/4 rounded-full p-2" src="{{ .AvatarUri }}" /> 109 {{ end }} 110 </div> 111 + <p 112 + title="{{ didOrHandle .UserDid .UserHandle }}" 113 + class="text-lg font-bold text-center dark:text-white overflow-hidden text-ellipsis whitespace-nowrap max-w-full" 114 + > 115 + {{ didOrHandle .UserDid .UserHandle }} 116 </p> 117 <div class="text-sm text-center dark:text-gray-300"> 118 <span>{{ .ProfileStats.Followers }} followers</span>