feat: add language statistics to repo page #208

Changed files
+109 -30
appview
pages
templates
layouts
repo
repo
knotserver
types
+1 -1
appview/pages/pages.go
···
Raw bool
EmailToDidOrHandle map[string]string
VerifiedCommits map[string]bool
-
Languages *types.RepoLanguageResponse
+
Languages []types.RepoLanguageDetails
types.RepoIndexResponse
}
+39 -1
appview/repo/repo.go
···
// non-fatal
}
+
languageFileCount := 0
+
for _, details := range repoLanguages.Languages {
+
languageFileCount += details.Count
+
}
+
+
var languageStats []types.RepoLanguageDetails
+
var otherLanguageStat *types.RepoLanguageDetails
+
otherPercentage := 0
+
+
for fileType, details := range repoLanguages.Languages {
+
percentage := (float32(details.Count) / float32(languageFileCount)) * 100
+
+
if percentage <= 0.1 {
+
otherPercentage += int(percentage)
+
continue
+
}
+
+
// Exclude languages
+
if fileType == "Text" {
+
otherPercentage += int(percentage)
+
continue
+
}
+
+
if fileType == "Other" {
+
otherLanguageStat = &types.RepoLanguageDetails{Name: fileType, Percentage: percentage, Color: details.Color}
+
} else {
+
languageStats = append(languageStats, types.RepoLanguageDetails{Name: fileType, Percentage: percentage, Color: details.Color})
+
}
+
}
+
+
sort.Slice(languageStats, func(i, j int) bool {
+
return languageStats[i].Percentage > languageStats[j].Percentage
+
})
+
+
if otherLanguageStat != nil {
+
languageStats = append(languageStats, *otherLanguageStat)
+
}
+
rp.pages.RepoIndexPage(w, pages.RepoIndexParams{
LoggedInUser: user,
RepoInfo: repoInfo,
···
BranchesTrunc: branchesTrunc,
EmailToDidOrHandle: emailToDidOrHandle(rp, emailToDidMap),
VerifiedCommits: vc,
-
Languages: repoLanguages,
+
Languages: languageStats,
})
return
}
+14 -4
knotserver/routes.go
···
return
}
-
languageFileCount := make(map[string]int)
+
languageFileCount := make(map[string]types.RepoLanguageFile)
err = recurseEntireTree(r.Context(), gr, func(absPath string) {
lang, safe := enry.GetLanguageByExtension(absPath)
···
content, _ := gr.FileContentN(absPath, 1024)
if !safe {
lang = enry.GetLanguage(absPath, content)
+
if len(lang) == 0 {
+
lang = "Other"
+
}
} else {
lang, _ = enry.GetLanguageByContent(absPath, content)
if len(lang) == 0 {
-
return
+
lang = "Other"
}
}
}
+
color := enry.GetColor(lang)
+
v, ok := languageFileCount[lang]
if ok {
-
languageFileCount[lang] = v + 1
+
v.Count += 1
+
languageFileCount[lang] = v
} else {
-
languageFileCount[lang] = 1
+
languageFileCount[lang] = types.RepoLanguageFile{
+
Name: lang,
+
Color: color,
+
Count: 1,
+
}
}
}, "")
if err != nil {
+13 -1
types/repo.go
···
Status ForkStatus `json:"status"`
}
+
type RepoLanguageFile struct {
+
Name string
+
Count int
+
Color string
+
}
+
+
type RepoLanguageDetails struct {
+
Name string
+
Percentage float32
+
Color string
+
}
+
type RepoLanguageResponse struct {
// Language: Percentage
-
Languages map[string]int `json:"languages"`
+
Languages map[string]RepoLanguageFile `json:"languages"`
}
+31 -23
appview/pages/templates/layouts/repobase.html
···
{{ define "title" }}{{ .RepoInfo.FullName }}{{ end }}
{{ define "content" }}
-
<section id="repo-header" class="mb-4 py-2 px-6 dark:text-white">
-
{{ if .RepoInfo.Source }}
-
<p class="text-sm">
-
<div class="flex items-center">
-
{{ i "git-fork" "w-3 h-3 mr-1"}}
-
forked from
-
{{ $sourceOwner := didOrHandle .RepoInfo.Source.Did .RepoInfo.SourceHandle }}
-
<a class="ml-1 underline" href="/{{ $sourceOwner }}/{{ .RepoInfo.Source.Name }}">{{ $sourceOwner }}/{{ .RepoInfo.Source.Name }}</a>
-
</div>
-
</p>
-
{{ end }}
-
<div class="text-lg flex items-center justify-between">
-
<div>
-
<a href="/{{ .RepoInfo.OwnerWithAt }}">{{ .RepoInfo.OwnerWithAt }}</a>
-
<span class="select-none">/</span>
-
<a href="/{{ .RepoInfo.FullName }}" class="font-bold">{{ .RepoInfo.Name }}</a>
-
</div>
+
<section id="repo-header" class="mb-4 py-2 px-6 dark:text-white">
+
{{ if .RepoInfo.Source }}
+
<p class="text-sm">
+
<div class="flex items-center">
+
{{ i "git-fork" "w-3 h-3 mr-1"}}
+
forked from
+
{{ $sourceOwner := didOrHandle .RepoInfo.Source.Did .RepoInfo.SourceHandle }}
+
<a class="ml-1 underline" href="/{{ $sourceOwner }}/{{ .RepoInfo.Source.Name }}">{{ $sourceOwner }}/{{ .RepoInfo.Source.Name }}</a>
+
</div>
+
</p>
+
{{ end }}
+
<div class="text-lg flex items-center justify-between">
+
<div>
+
<a href="/{{ .RepoInfo.OwnerWithAt }}">{{ .RepoInfo.OwnerWithAt }}</a>
+
<span class="select-none">/</span>
+
<a href="/{{ .RepoInfo.FullName }}" class="font-bold">{{ .RepoInfo.Name }}</a>
+
</div>
-
{{ template "repo/fragments/repoActions" .RepoInfo }}
-
</div>
-
{{ template "repo/fragments/repoDescription" . }}
-
</section>
-
<section class="min-h-screen flex flex-col drop-shadow-sm">
+
{{ template "repo/fragments/repoActions" .RepoInfo }}
+
</div>
+
{{ template "repo/fragments/repoDescription" . }}
+
</section>
+
+
<section
+
class="min-h-screen w-full flex flex-col drop-shadow-sm"
+
>
<nav class="w-full pl-4 overflow-auto">
<div class="flex z-60">
{{ $activeTabStyles := "-mb-px bg-white dark:bg-gray-800" }}
···
{{ end }}
</div>
</nav>
+
<div
+
class="bg-white dark:bg-gray-800 rounded-t overflow-hidden relative w-full drop-shadow-sm"
+
>
+
{{ block "repoLanguages" . }}{{ end }}
+
</div>
<section
-
class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto drop-shadow-sm dark:text-white"
+
class="bg-white dark:bg-gray-800 p-6 rounded-b relative w-full drop-shadow-sm dark:text-white"
>
{{ block "repoContent" . }}{{ end }}
</section>
+11
appview/pages/templates/repo/index.html
···
{{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo) }}
{{ end }}
+
{{ define "repoLanguages" }}
+
<div class="flex gap-[3px]">
+
{{ range $value := .Languages }}
+
<div
+
title="{{ $value.Name }} {{ printf "%.1f" $value.Percentage }}%"
+
class="h-2"
+
style="background-color: {{ $value.Color }}; width: {{ $value.Percentage }}%"
+
></div>
+
{{ end }}
+
</div>
+
{{ end }}
{{ define "repoContent" }}
<main>