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

appview: blob: view raw file

Also improves the file/tree metadata.

Changed files
+74 -24
appview
pages
templates
state
+11 -7
appview/pages/templates/repo/blob.html
···
{{ $tot_chars := len (printf "%d" $tot_lines) }}
{{ $code_number_style := "text-gray-400 left-0 bg-white text-right mr-6 select-none inline-block w-12" }}
{{ $linkstyle := "no-underline hover:underline" }}
-
<div class="pb-2 text-base">
-
<div class="flex justify-between">
-
<div id="breadcrumbs">
+
<div class="pb-2 mb-3 text-base border-b border-gray-200">
+
<div class="flex flex-col md:flex-row md:justify-between gap-2">
+
<div id="breadcrumbs" class="overflow-x-auto whitespace-nowrap">
{{ range $idx, $value := .BreadCrumbs }}
{{ if ne $idx (sub (len $.BreadCrumbs) 1) }}
<a
···
{{ end }}
{{ end }}
</div>
-
<div id="file-info" class="text-gray-500 text-xs">
-
{{ .Lines }} lines
-
<span class="select-none px-2 [&:before]:content-['·']"></span>
-
{{ byteFmt .SizeHint }}
+
<div id="file-info" class="text-gray-500 text-xs md:text-sm flex flex-wrap items-center gap-1 md:gap-0">
+
<span>at <a href="/{{ .RepoInfo.FullName }}/tree/{{ .Ref }}">{{ .Ref }}</a></span>
+
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
+
<span>{{ .Lines }} lines</span>
+
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
+
<span>{{ byteFmt .SizeHint }}</span>
+
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
+
<a href="/{{ .RepoInfo.FullName }}/blob/raw/{{ .Ref }}/{{ .Path }}">view raw</a>
</div>
</div>
</div>
+18 -17
appview/pages/templates/repo/tree.html
···
{{ $containerstyle := "py-1" }}
{{ $linkstyle := "no-underline hover:underline" }}
-
<div class="pb-2 text-base">
+
<div class="pb-2 mb-3 text-base border-b border-gray-200">
<div class="flex justify-between">
<div id="breadcrumbs">
{{ range .BreadCrumbs }}
<a href="{{ index . 1}}" class="text-bold text-gray-500 {{ $linkstyle }}">{{ index . 0 }}</a> /
{{ end }}
</div>
-
<div id="dir-info">
-
<span class="text-gray-500 text-xs">
-
{{ $stats := .TreeStats }}
+
<div id="dir-info" class="text-gray-500 text-xs md:text-sm flex flex-wrap items-center gap-1 md:gap-0">
+
{{ $stats := .TreeStats }}
-
{{ if eq $stats.NumFolders 1 }}
-
{{ $stats.NumFolders }} folder
-
<span class="px-1 select-none">·</span>
-
{{ else if gt $stats.NumFolders 1 }}
-
{{ $stats.NumFolders }} folders
-
<span class="px-1 select-none">·</span>
-
{{ end }}
+
<span>at <a href="/{{ $.RepoInfo.FullName }}/tree/{{ $.Ref }}">{{ $.Ref }}</a></span>
+
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
+
{{ if eq $stats.NumFolders 1 }}
+
<span>{{ $stats.NumFolders }} folder</span>
+
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
+
{{ else if gt $stats.NumFolders 1 }}
+
<span>{{ $stats.NumFolders }} folders</span>
+
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
+
{{ end }}
+
+
{{ if eq $stats.NumFiles 1 }}
+
<span>{{ $stats.NumFiles }} file</span>
+
{{ else if gt $stats.NumFiles 1 }}
+
<span>{{ $stats.NumFiles }} files</span>
+
{{ end }}
-
{{ if eq $stats.NumFiles 1 }}
-
{{ $stats.NumFiles }} file
-
{{ else if gt $stats.NumFiles 1 }}
-
{{ $stats.NumFiles }} files
-
{{ end }}
-
</span>
</div>
</div>
</div>
+44
appview/state/repo.go
···
return
}
+
func (s *State) RepoBlobRaw(w http.ResponseWriter, r *http.Request) {
+
f, err := fullyResolvedRepo(r)
+
if err != nil {
+
log.Println("failed to get repo and knot", err)
+
return
+
}
+
+
ref := chi.URLParam(r, "ref")
+
filePath := chi.URLParam(r, "*")
+
+
protocol := "http"
+
if !s.config.Dev {
+
protocol = "https"
+
}
+
resp, err := http.Get(fmt.Sprintf("%s://%s/%s/%s/blob/%s/%s", protocol, f.Knot, f.OwnerDid(), f.RepoName, ref, filePath))
+
if err != nil {
+
log.Println("failed to reach knotserver", err)
+
return
+
}
+
+
body, err := io.ReadAll(resp.Body)
+
if err != nil {
+
log.Printf("Error reading response body: %v", err)
+
return
+
}
+
+
var result types.RepoBlobResponse
+
err = json.Unmarshal(body, &result)
+
if err != nil {
+
log.Println("failed to parse response:", err)
+
return
+
}
+
+
if result.IsBinary {
+
w.Header().Set("Content-Type", "application/octet-stream")
+
w.Write(body)
+
return
+
}
+
+
w.Header().Set("Content-Type", "text/plain")
+
w.Write([]byte(result.Contents))
+
return
+
}
+
func (s *State) AddCollaborator(w http.ResponseWriter, r *http.Request) {
f, err := fullyResolvedRepo(r)
if err != nil {
+1
appview/state/router.go
···
r.Get("/branches", s.RepoBranches)
r.Get("/tags", s.RepoTags)
r.Get("/blob/{ref}/*", s.RepoBlob)
+
r.Get("/blob/{ref}/raw/*", s.RepoBlobRaw)
r.Route("/issues", func(r chi.Router) {
r.Get("/", s.RepoIssues)