Monorepo for Tangled tangled.org

add file and folder into to tree/blob views

Changed files
+73 -15
appview
pages
knotserver
types
+22
appview/pages/pages.go
··· 71 return s 72 }, 73 "timeFmt": humanize.Time, 74 "length": func(v []string) int { 75 return len(v) 76 }, ··· 293 BaseTreeLink string 294 BaseBlobLink string 295 types.RepoTreeResponse 296 } 297 298 func (p *Pages) RepoTree(w io.Writer, params RepoTreeParams) error {
··· 71 return s 72 }, 73 "timeFmt": humanize.Time, 74 + "byteFmt": humanize.Bytes, 75 "length": func(v []string) int { 76 return len(v) 77 }, ··· 294 BaseTreeLink string 295 BaseBlobLink string 296 types.RepoTreeResponse 297 + } 298 + 299 + type RepoTreeStats struct { 300 + NumFolders uint64 301 + NumFiles uint64 302 + } 303 + 304 + func (r RepoTreeParams) TreeStats() RepoTreeStats { 305 + numFolders, numFiles := 0, 0 306 + for _, f := range r.Files { 307 + if !f.IsFile { 308 + numFolders += 1 309 + } else if f.IsFile { 310 + numFiles += 1 311 + } 312 + } 313 + 314 + return RepoTreeStats{ 315 + NumFolders: uint64(numFolders), 316 + NumFiles: uint64(numFiles), 317 + } 318 } 319 320 func (p *Pages) RepoTree(w io.Writer, params RepoTreeParams) error {
+1 -1
appview/pages/templates/layouts/base.html
··· 17 {{ template "layouts/topbar" . }} 18 {{ end }} 19 </header> 20 - <div class="container mx-auto px-10"> 21 <main class="content">{{ block "content" . }}{{ end }}</main> 22 <script src="/static/lucide.min.js"></script> 23 <script>
··· 17 {{ template "layouts/topbar" . }} 18 {{ end }} 19 </header> 20 + <div class="container mx-auto px-1"> 21 <main class="content">{{ block "content" . }}{{ end }}</main> 22 <script src="/static/lucide.min.js"></script> 23 <script>
+16 -5
appview/pages/templates/repo/blob.html
··· 5 {{ $code_number_style := "text-gray-400 left-0 bg-white text-right mr-2 select-none" }} 6 {{ $linkstyle := "no-underline hover:underline" }} 7 <div class="pb-2 text-base"> 8 - {{ range $idx, $value := .BreadCrumbs }} 9 - {{ if ne $idx (sub (len $.BreadCrumbs) 1) }} 10 <a href="{{ index . 1}}" class="text-bold text-gray-500 {{ $linkstyle }}">{{ index . 0 }}</a> / 11 - {{ else }} 12 <span class="text-bold text-gray-500">{{ index . 0 }}</span> 13 - {{ end }} 14 - {{ end }} 15 </div> 16 17
··· 5 {{ $code_number_style := "text-gray-400 left-0 bg-white text-right mr-2 select-none" }} 6 {{ $linkstyle := "no-underline hover:underline" }} 7 <div class="pb-2 text-base"> 8 + <div class="flex justify-between"> 9 + <div id="breadcrumbs"> 10 + {{ range $idx, $value := .BreadCrumbs }} 11 + {{ if ne $idx (sub (len $.BreadCrumbs) 1) }} 12 <a href="{{ index . 1}}" class="text-bold text-gray-500 {{ $linkstyle }}">{{ index . 0 }}</a> / 13 + {{ else }} 14 <span class="text-bold text-gray-500">{{ index . 0 }}</span> 15 + {{ end }} 16 + {{ end }} 17 + </div> 18 + <div id="file-info"> 19 + <span class="text-gray-500 text-xs"> 20 + {{ .Lines }} lines 21 + &nbsp;·&nbsp; 22 + {{ byteFmt .SizeHint }} 23 + </span> 24 + </div> 25 + </div> 26 </div> 27 28
+1 -1
appview/pages/templates/repo/index.html
··· 4 this repo is empty 5 {{ else }} 6 <div class="flex gap-4"> 7 - <div id="file-tree" class="w-1/2"> 8 {{ $containerstyle := "py-1" }} 9 {{ $linkstyle := "no-underline hover:underline" }} 10
··· 4 this repo is empty 5 {{ else }} 6 <div class="flex gap-4"> 7 + <div id="file-tree" class="w-3/5"> 8 {{ $containerstyle := "py-1" }} 9 {{ $linkstyle := "no-underline hover:underline" }} 10
+27 -6
appview/pages/templates/repo/tree.html
··· 5 {{ $linkstyle := "no-underline hover:underline" }} 6 7 <div class="pb-2 text-base"> 8 - {{ range .BreadCrumbs }} 9 - <a href="{{ index . 1}}" class="text-bold text-gray-500 {{ $linkstyle }}">{{ index . 0 }}</a> / 10 - {{ end }} 11 </div> 12 13 {{ range .Files }} ··· 19 <i class="w-3 h-3 fill-current" data-lucide="folder"></i>{{ .Name }} 20 </div> 21 </a> 22 </div> 23 - <time class="text-xs text-gray-500">{{ timeFmt .LastCommit.Author.When }}</time> 24 </div> 25 {{ end }} 26 {{ end }} ··· 28 {{ range .Files }} 29 {{ if .IsFile }} 30 <div class="{{ $containerstyle }}"> 31 - 32 <div class="flex justify-between items-center"> 33 <a href="/{{ $.BaseBlobLink }}/{{ .Name }}" class="{{ $linkstyle }}"> 34 <div class="flex items-center gap-2"> 35 <i class="w-3 h-3" data-lucide="file"></i>{{ .Name }} 36 </div> 37 </a> 38 - 39 <time class="text-xs text-gray-500">{{ timeFmt .LastCommit.Author.When }}</time> 40 </div> 41 </div>
··· 5 {{ $linkstyle := "no-underline hover:underline" }} 6 7 <div class="pb-2 text-base"> 8 + <div class="flex justify-between"> 9 + <div id="breadcrumbs"> 10 + {{ range .BreadCrumbs }} 11 + <a href="{{ index . 1}}" class="text-bold text-gray-500 {{ $linkstyle }}">{{ index . 0 }}</a> / 12 + {{ end }} 13 + </div> 14 + <div id="dir-info"> 15 + <span class="text-gray-500 text-xs"> 16 + {{ $stats := .TreeStats }} 17 + 18 + {{ if eq $stats.NumFolders 1 }} 19 + {{ $stats.NumFolders }} folder 20 + &nbsp;·&nbsp; 21 + {{ else if gt $stats.NumFolders 1 }} 22 + {{ $stats.NumFolders }} folders 23 + &nbsp;·&nbsp; 24 + {{ end }} 25 + 26 + {{ if eq $stats.NumFiles 1 }} 27 + {{ $stats.NumFiles }} file 28 + {{ else if gt $stats.NumFiles 1 }} 29 + {{ $stats.NumFiles }} files 30 + {{ end }} 31 + </span> 32 + </div> 33 + </div> 34 </div> 35 36 {{ range .Files }} ··· 42 <i class="w-3 h-3 fill-current" data-lucide="folder"></i>{{ .Name }} 43 </div> 44 </a> 45 + <time class="text-xs text-gray-500">{{ timeFmt .LastCommit.Author.When }}</time> 46 </div> 47 </div> 48 {{ end }} 49 {{ end }} ··· 51 {{ range .Files }} 52 {{ if .IsFile }} 53 <div class="{{ $containerstyle }}"> 54 <div class="flex justify-between items-center"> 55 <a href="/{{ $.BaseBlobLink }}/{{ .Name }}" class="{{ $linkstyle }}"> 56 <div class="flex items-center gap-2"> 57 <i class="w-3 h-3" data-lucide="file"></i>{{ .Name }} 58 </div> 59 </a> 60 <time class="text-xs text-gray-500">{{ timeFmt .LastCommit.Author.When }}</time> 61 </div> 62 </div>
+4 -1
knotserver/routes.go
··· 215 return 216 } 217 218 - safe := string(sanitize([]byte(contents))) 219 220 resp := types.RepoBlobResponse{ 221 Ref: ref, 222 Contents: string(safe), 223 Path: treePath, 224 IsBinary: isBinaryFile, 225 } 226 227 h.showFile(resp, w, l)
··· 215 return 216 } 217 218 + bytes := []byte(contents) 219 + safe := string(sanitize(bytes)) 220 + sizeHint := len(bytes) 221 222 resp := types.RepoBlobResponse{ 223 Ref: ref, 224 Contents: string(safe), 225 Path: treePath, 226 IsBinary: isBinaryFile, 227 + SizeHint: uint64(sizeHint), 228 } 229 230 h.showFile(resp, w, l)
+2 -1
types/repo.go
··· 69 Path string `json:"path,omitempty"` 70 IsBinary bool `json:"is_binary,omitempty"` 71 72 - Lines int `json:"lines,omitempty"` 73 }
··· 69 Path string `json:"path,omitempty"` 70 IsBinary bool `json:"is_binary,omitempty"` 71 72 + Lines int `json:"lines,omitempty"` 73 + SizeHint uint64 `json:"size_hint,omitempty"` 74 }