~gitpocket/gitpocket

feat(basin): fluid code view with column rule and versioned stylesheets

commit
70552738d04a7e04cd665da28071746038f5ed47 browse tree
parent
42135f1cbae513b3742fdbfa98112ffb4d2fda33
author
james <j@cpl0.zip>
signature
none
date
2026-11-12 05:38 UTC

3 files changed, +32 −10

static/style.css modified

@@ -41,7 +41,11 @@ nav.tabs a{padding:.25rem .9rem}
4141 nav.tabs a.active{background:#fff;color:var(--fg)}
4242 .repohead .desc{margin:0 0 .4rem;color:var(--muted)}
4343 .repohead+main{margin-top:1rem}
44-.repohead+main.file{margin-top:0;padding-top:.6rem;max-width:none;margin-left:0;margin-right:0}
44+.repohead+main{margin-top:0;padding-top:.6rem}
45+body.fluid .inner,body.fluid nav.site,body.fluid main{max-width:none;margin:0}
46+body.fluid .filebar{margin-bottom:0}
47+body.fluid main.file{padding-top:.2rem}
48+.summary{padding-top:.4rem}
4549 .summary{margin-top:.2rem;display:grid;grid-template-columns:4fr 1.5fr 2.6fr;gap:2rem;margin-bottom:1.5rem;align-items:start}
4650 .summary .event{background:var(--soft);padding:.4rem .5rem .5rem;margin-bottom:.6rem}
4751 .summary .event .row{display:flex;justify-content:space-between;gap:1rem}
@@ -125,7 +129,9 @@ table.tree .size{color:var(--muted);text-align:right}
125129 table.tree .last{max-width:30rem;overflow:hidden;text-overflow:ellipsis;width:100%}
126130 table.tree .when{text-align:right}
127131 table.refs td,table.keys td{padding:.3rem 1rem .3rem 0;border-bottom:1px solid var(--line)}
128-.code{margin:0 -1rem;line-height:1.45}
132+.code{margin:0 -1rem;line-height:1.45;min-height:70vh}
133+.code .lntd:last-child{position:relative}
134+.code .lntd:last-child::after{content:"";position:absolute;top:0;bottom:0;left:calc(80ch + 1rem);border-left:1px solid var(--bar)}
129135 table.blob,.code table{width:100%}
130136 table.blob td,table.hunk td,.code td{padding:0 .5rem;white-space:pre;vertical-align:top}
131137 td.n{text-align:right;color:var(--muted);user-select:none;width:1%}
@@ -135,11 +141,12 @@ td.l{white-space:pre-wrap;overflow-wrap:anywhere;width:100%}
135141 tr:target td{background:#fff8c5}
136142 .code pre,.code .chroma{background:#fff;border:0;padding:0;margin:0}
137143 .code .lntable{margin-top:0}
138-.code .lntd:first-child{width:1%;user-select:none;border-right:1px solid var(--bar);padding-top:.4rem}
144+.code .lntd:first-child{width:1%;user-select:none;border-right:1px solid var(--bar);padding-top:.4rem;vertical-align:top}
139145 .code .lntd:last-child{padding-top:.4rem}
140-.code .lnlinks{text-decoration:none}
141-.code .lnlinks:hover{text-decoration:underline}
142-.code .lnt,.code .ln{color:var(--link);margin-right:0;padding:0 .5rem 0 .6rem}
146+.code .lntd:first-child{min-height:70vh}
147+.code .lnlinks{text-decoration:underline}
148+.code .lnt{padding-right:.5rem}
149+.code .lnt,.code .ln{color:var(--link);margin-right:0;padding:0 .5rem 0 .4rem}
143150 .code .lntd a{color:var(--link);text-decoration:none}
144151 .code .lntd:last-child{padding-left:.6rem}
145152 .code .line:target,.code .line:target .cl{background:#fff8c5}

templates/layout.html modified

@@ -4,14 +4,14 @@
44 <meta charset="utf-8">
55 <meta name="viewport" content="width=device-width, initial-scale=1">
66 <title>{{.Title}}</title>
7-<link rel="stylesheet" href="/static/style.css">
8-<link rel="stylesheet" href="/static/highlight.css">
7+<link rel="stylesheet" href="/static/style.css?v={{.Version}}">
8+<link rel="stylesheet" href="/static/highlight.css?v={{.Version}}">
99 {{if .Math}}<link rel="stylesheet" href="/static/katex/katex.min.css">
1010 <script defer src="/static/katex/katex.min.js"></script>
1111 <script defer src="/static/katex/auto-render.min.js"></script>
1212 <script>document.addEventListener("DOMContentLoaded",function(){renderMathInElement(document.body,{delimiters:[{left:"\\(",right:"\\)",display:false},{left:"\\[",right:"\\]",display:true}],throwOnError:false})})</script>{{end}}
1313 </head>
14-<body>
14+<body{{if .Fluid}} class="fluid"{{end}}>
1515 <header>
1616 <nav class="site">
1717 <a class="brand" href="/">{{.Host}}</a>

web.go modified

@@ -2,7 +2,9 @@ package main
22
33 import (
44 "bytes"
5+ "crypto/sha256"
56 "embed"
7+ "encoding/hex"
68 "fmt"
79 "html/template"
810 "io"
@@ -33,6 +35,7 @@ var templateFS embed.FS
3335 var staticFS embed.FS
3436
3537 type Server struct {
38+ version string
3639 limiter *limiter
3740 store *Store
3841 root string
@@ -45,6 +48,8 @@ type Server struct {
4548 }
4649
4750 type page struct {
51+ Version string
52+ Fluid bool
4853 Title string
4954 User *User
5055 Host string
@@ -89,12 +94,21 @@ func newServer(store *Store, root, host string, open bool, sshUser string) *Serv
8994 s.policy = bluemonday.UGCPolicy()
9095 s.policy.AllowAttrs("class").Matching(regexp.MustCompile(`^[a-z]{1,8}( [a-z]{1,8})*$`)).OnElements("span", "pre", "code")
9196 s.writeSigners()
97+ sum := sha256.New()
98+ css, _ := staticFS.ReadFile("static/style.css")
99+ sum.Write(css)
100+ sum.Write(highlightCSS())
101+ s.version = hex.EncodeToString(sum.Sum(nil))[:12]
92102 return s
93103 }
94104
95105 func (s *Server) render(w http.ResponseWriter, r *http.Request, name string, p page) {
96106 p.Host = s.host
97107 p.SSHUser = s.sshUser
108+ p.Version = s.version
109+ if d, ok := p.Data.(map[string]any); ok && d["File"] == true {
110+ p.Fluid = true
111+ }
98112 if p.User == nil {
99113 p.User = s.current(r)
100114 }
@@ -770,7 +784,7 @@ func (s *Server) tree(w http.ResponseWriter, r *http.Request, repo Repo, spec st
770784 if filePath == "" {
771785 crumbs = nil
772786 }
773- data := map[string]any{"Page": rp, "Path": filePath, "Crumbs": crumbs, "File": true}
787+ data := map[string]any{"Page": rp, "Path": filePath, "Crumbs": crumbs}
774788 if last, _ := g.Log(rp.Commit, 1, filePath); len(last) > 0 {
775789 data["LastCommit"] = last[0]
776790 }
@@ -801,6 +815,7 @@ func (s *Server) tree(w http.ResponseWriter, r *http.Request, repo Repo, spec st
801815 return
802816 }
803817 }
818+ data["File"] = true
804819 if size > maxRender {
805820 data["Large"] = true
806821 } else if isBinary(content) {