4 files changed,
25 insertions(+),
36 deletions(-)
Author:
Oleksandr Smirnov
olexsmir@gmail.com
Committed at:
2026-03-11 13:25:19 +0200
Authored at:
2026-03-11 12:43:56 +0200
Change ID:
mwlplwnvytuluvpkryqxkomwqmzspuom
Parent:
afcecfc
M
internal/handlers/handlers.go
路路路 72 72 } 73 73 74 74 var templateFuncs = template.FuncMap{ 75 + "inc": func(n int) int { return n + 1 }, 75 76 "humanizeRelTime": func(t time.Time) string { return humanize.Time(t) }, 76 77 "humanizeTime": func(t time.Time) string { return t.Format("2006-01-02 15:04:05 MST") }, 77 78 "urlencode": func(s string) string { return url.PathEscape(s) },
M
internal/handlers/repo.go
路路路 163 163 type RepoFile struct { 164 164 Ref string 165 165 Desc string 166 - LineCount []int 166 + Lines []string 167 167 Breadcrumbs []Breadcrumb 168 168 Path string 169 169 IsImage bool 170 170 IsBinary bool 171 - Content string 172 171 Mime string 173 172 Size int64 174 173 } 路路路 211 210 212 211 p.Breadcrumbs = Breadcrumbs(treePath) 213 212 if !fc.IsImage && !fc.IsBinary { 214 - contentStr := fc.String() 215 - lc, err := countLines(strings.NewReader(contentStr)) 216 - if err != nil { 217 - slog.Error("failed to count line numbers", "err", err) 218 - } 219 - lines := make([]int, lc) 220 - for i := range lines { 221 - lines[i] = i + 1 222 - } 223 - p.Content = contentStr 224 - p.LineCount = lines // TODO: replace with strings.Count(, "\n") 213 + p.Lines = strings.Split(strings.TrimRight(fc.String(), "\n"), "\n") 225 214 } 226 215 227 216 h.templ(w, "repo_file", h.pageData(repo, p))
M
web/static/style.css
路路路 230 230 overflow-x: auto; 231 231 } 232 232 233 -.line-numbers { 234 - white-space: pre-line; 233 +.file-contents { 234 + width: 100%; 235 + padding: 0.3em 0 0.3em 0; 236 +} 237 + 238 +.line-number { 239 + width: 1%; 235 240 -moz-user-select: -moz-none; 236 241 -khtml-user-select: none; 237 242 -webkit-user-select: none; 238 243 -o-user-select: none; 239 - user-select: none; 240 - padding-right: 1ch; 241 244 } 242 245 243 -.file-content { 244 - padding-left: 1.5ch; 245 - overflow-y: hidden; 246 - overflow-x: auto; 246 +.line-number a:hover { border-bottom: none; } 247 +.line-number a { 248 + display: block; 249 + padding: 0 1rem; 250 + text-decoration: none; 247 251 } 252 + 253 +.line:has(a:target) { background-color: rgba(0,0,0,0.4); } 254 + 248 255 .image-viewer, .binary-viewer { padding: 1rem 0; } 249 256 .image-viewer img { 250 257 max-width: 100%; 251 258 height: auto; 252 -} 253 - 254 -.line-numbers pre, 255 -.file-content pre { 256 - margin: 0; 257 - line-height: 1.5; 258 259 } 259 260 260 261 /* commit */
M
web/templates/repo_file.html
路路路 29 29 <a class="link" href="/{{ .RepoName }}/raw/{{ .P.Ref }}/{{ .P.Path }}" download>[ Download ]</a> 30 30 </div> 31 31 {{ else }} 32 - <table> 32 + <table class="file-contents" tabindex="-1"> 33 33 <tbody> 34 - <tr> 35 - <td class="line-numbers"> 36 -<pre>{{- range .P.LineCount }} 37 -<a id="L{{ . }}" href="#L{{ . }}">{{ . }}</a> 38 -{{- end -}}</pre> 39 - </td> 40 - <td class="file-content"> 41 - <pre>{{- .P.Content -}}</pre> 34 + {{- range $i, $l := .P.Lines }} 35 + <tr class="line"> 36 + <td class="line-number"> 37 + <a id="L{{ inc $i }}" href="#L{{ inc $i }}" aria>{{ inc $i }}</a> 42 38 </td> 39 + <td><pre>{{ $l }}</pre></td> 43 40 </tr> 41 + {{- end -}} 44 42 </tbody> 45 43 </table> 46 44 {{ end }}