forked from tangled.org/core
this repo has no description

appview: add stats and line-nr links to diffs

drive-by fix: style the separator between pull submissions

Changed files
+83 -57
appview
types
+59 -16
appview/pages/templates/fragments/diff.html
···
{{ $this := $commit.This }}
{{ $parent := $commit.Parent }}
+
<section class="mt-6 p-6 border border-gray-200 dark:border-gray-700 w-full mx-auto rounded bg-white dark:bg-gray-800 drop-shadow-sm">
+
<div class="diff-stat">
+
<div class="flex gap-2 items-center">
+
<strong class="text-sm uppercase dark:text-gray-200">Changed files</strong>
+
{{ block "statPill" $stat }} {{ end }}
+
</div>
+
<div class="overflow-x-auto">
+
{{ range $diff }}
+
<ul class="dark:text-gray-200">
+
{{ if .IsDelete }}
+
<li><a href="#file-{{ .Name.Old }}" class="dark:hover:text-gray-300">{{ .Name.Old }}</a></li>
+
{{ else }}
+
<li><a href="#file-{{ .Name.New }}" class="dark:hover:text-gray-300">{{ .Name.New }}</a></li>
+
{{ end }}
+
</ul>
+
{{ end }}
+
</div>
+
</div>
+
</section>
+
{{ $last := sub (len $diff) 1 }}
{{ range $idx, $hunk := $diff }}
{{ with $hunk }}
···
{{ else }}
<span class="bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300 {{ $markerstyle }}">MODIFIED</span>
{{ end }}
+
+
{{ block "statPill" .Stats }} {{ end }}
{{ if .IsDelete }}
<a class="dark:text-white whitespace-nowrap overflow-x-auto" {{if $this }}href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.Old }}"{{end}}>
···
<div class="transition-all duration-700 ease-in-out">
{{ if .IsDelete }}
-
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
-
This file has been deleted in this commit.
-
</p>
+
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
+
This file has been deleted.
+
</p>
+
{{ else if .IsCopy }}
+
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
+
This file has been copied.
+
</p>
+
{{ else if .IsRename }}
+
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
+
This file has been renamed.
+
</p>
+
{{ else if .IsBinary }}
+
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
+
This is a binary file and will not be displayed.
+
</p>
{{ else }}
-
{{ if .IsBinary }}
-
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
-
This is a binary file and will not be displayed.
-
</p>
-
{{ else }}
+
{{ $name := .Name.New }}
<pre class="overflow-x-auto"><div class="overflow-x-auto"><div class="min-w-full inline-block">{{- range .TextFragments -}}<div class="bg-gray-100 dark:bg-gray-700 text-gray-500 dark:text-gray-400 select-none text-center">&middot;&middot;&middot;</div>
{{- $oldStart := .OldPosition -}}
{{- $newStart := .NewPosition -}}
-
{{- $lineNrStyle := "min-w-[3rem] flex-shrink-0 select-none text-right" -}}
-
{{- $lineNrSepStyle1 := "text-gray-400 dark:text-gray-500 bg-white dark:bg-gray-800" -}}
-
{{- $lineNrSepStyle2 := "text-gray-400 dark:text-gray-500 bg-white dark:bg-gray-800 pr-2" -}}
+
{{- $lineNrStyle := "min-w-[3.5rem] flex-shrink-0 select-none text-right bg-white dark:bg-gray-800 scroll-mt-10 target:border target:border-amber-500 target:rounded " -}}
+
{{- $linkStyle := "text-gray-400 dark:text-gray-500 hover:underline" -}}
+
{{- $lineNrSepStyle1 := "" -}}
+
{{- $lineNrSepStyle2 := "pr-2" -}}
{{- range .Lines -}}
{{- if eq .Op.String "+" -}}
<div class="bg-green-100 dark:bg-green-800/30 text-green-700 dark:text-green-400 flex min-w-full items-center">
<div class="{{$lineNrStyle}} {{$lineNrSepStyle1}}"><span aria-hidden="true" class="invisible">{{$newStart}}</span></div>
-
<div class="{{$lineNrStyle}} {{$lineNrSepStyle2}}">{{ $newStart }}</div>
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle2}}" id="{{$name}}-N{{$newStart}}"><a class="{{$linkStyle}}" href="#{{$name}}-N{{$newStart}}">{{ $newStart }}</a></div>
<div class="w-5 flex-shrink-0 select-none text-center">{{ .Op.String }}</div>
<div class="px-2">{{ .Line }}</div>
</div>
···
{{- end -}}
{{- if eq .Op.String "-" -}}
<div class="bg-red-100 dark:bg-red-800/30 text-red-700 dark:text-red-400 flex min-w-full items-center">
-
<div class="{{$lineNrStyle}} {{$lineNrSepStyle1}}">{{ $oldStart }}</div>
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle1}}" id="{{$name}}-O{{$oldStart}}"><a class="{{$linkStyle}}" href="#{{$name}}-O{{$oldStart}}">{{ $oldStart }}</a></div>
<div class="{{$lineNrStyle}} {{$lineNrSepStyle2}}"><span aria-hidden="true" class="invisible">{{$oldStart}}</span></div>
<div class="w-5 flex-shrink-0 select-none text-center">{{ .Op.String }}</div>
<div class="px-2">{{ .Line }}</div>
···
{{- end -}}
{{- if eq .Op.String " " -}}
<div class="bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400 flex min-w-full items-center">
-
<div class="{{$lineNrStyle}} {{$lineNrSepStyle1}}">{{ $oldStart }}</div>
-
<div class="{{$lineNrStyle}} {{$lineNrSepStyle2}}">{{ $newStart }}</div>
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle1}}" id="{{$name}}-O{{$oldStart}}"><a class="{{$linkStyle}}" href="#{{$name}}-O{{$oldStart}}">{{ $oldStart }}</a></div>
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle2}}" id="{{$name}}-N{{$newStart}}"><a class="{{$linkStyle}}" href="#{{$name}}-N{{$newStart}}">{{ $newStart }}</a></div>
<div class="w-5 flex-shrink-0 select-none text-center">{{ .Op.String }}</div>
<div class="px-2">{{ .Line }}</div>
</div>
···
{{- end -}}
{{- end -}}</div></div></pre>
{{- end -}}
-
{{ end }}
</div>
</details>
···
{{ end }}
{{ end }}
{{ end }}
+
+
{{ define "statPill" }}
+
<div class="flex items-center font-mono text-sm">
+
{{ if and .Insertions .Deletions }}
+
<span class="rounded-l p-1 select-none bg-green-100 text-green-700 dark:bg-green-800/50 dark:text-green-400">+{{ .Insertions }}</span>
+
<span class="rounded-r p-1 select-none bg-red-100 text-red-700 dark:bg-red-800/50 dark:text-red-400">-{{ .Deletions }}</span>
+
{{ else if .Insertions }}
+
<span class="rounded p-1 select-none bg-green-100 text-green-700 dark:bg-green-800/50 dark:text-green-400">+{{ .Insertions }}</span>
+
{{ else if .Deletions }}
+
<span class="rounded p-1 select-none bg-red-100 text-red-700 dark:bg-red-800/50 dark:text-red-400">-{{ .Deletions }}</span>
+
{{ end }}
+
</div>
+
{{ end }}
+1 -20
appview/pages/templates/repo/commit.html
···
{{ $repo := .RepoInfo.FullName }}
{{ $commit := .Diff.Commit }}
-
{{ $stat := .Diff.Stat }}
-
{{ $diff := .Diff.Diff }}
<section class="commit dark:text-white">
<div id="commit-message">
···
<div>
<p class="pb-2">{{ index $messageParts 0 }}</p>
{{ if gt (len $messageParts) 1 }}
-
<p class="mt-1 cursor-text pb-2 text-sm">{{ nl2br (unwrapText (index $messageParts 1)) }}</p>
+
<p class="mt-1 cursor-text pb-2 text-sm">{{ nl2br (index $messageParts 1) }}</p>
{{ end }}
</div>
</div>
···
{{ end }}
<span class="px-1 select-none before:content-['\00B7']"></span>
{{ timeFmt $commit.Author.When }}
-
<span class="px-1 select-none before:content-['\00B7']"></span>
-
<span>{{ $stat.FilesChanged }}</span> files <span class="font-mono">(+{{ $stat.Insertions }}, -{{ $stat.Deletions }})</span>
<span class="px-1 select-none before:content-['\00B7']"></span>
</p>
···
</p>
</div>
-
<div class="diff-stat">
-
<br>
-
<strong class="text-sm uppercase mb-4 dark:text-gray-200">Changed files</strong>
-
<div class="overflow-x-auto">
-
{{ range $diff }}
-
<ul class="dark:text-gray-200">
-
{{ if .IsDelete }}
-
<li><a href="#file-{{ .Name.Old }}" class="dark:hover:text-gray-300">{{ .Name.Old }}</a></li>
-
{{ else }}
-
<li><a href="#file-{{ .Name.New }}" class="dark:hover:text-gray-300">{{ .Name.New }}</a></li>
-
{{ end }}
-
</ul>
-
{{ end }}
-
</div>
-
</div>
</section>
{{end}}
+1 -1
appview/pages/templates/repo/index.html
···
<p
class="hidden mt-1 text-sm cursor-text pb-2 dark:text-gray-300"
>
-
{{ nl2br (unwrapText (index $messageParts 1)) }}
+
{{ nl2br (index $messageParts 1) }}
</p>
{{ end }}
</div>
+1 -1
appview/pages/templates/repo/issues/issues.html
···
<div class="flex justify-between items-center">
<p>
filtering
-
<select class="border px-1 bg-white border-gray-200 dark:bg-gray-800 dark:border-gray-700" onchange="window.location.href = '/{{ .RepoInfo.FullName }}/issues?state=' + this.value">
+
<select class="border p-1 bg-white border-gray-200 dark:bg-gray-800 dark:border-gray-700" onchange="window.location.href = '/{{ .RepoInfo.FullName }}/issues?state=' + this.value">
<option value="open" {{ if .FilteringByOpen }}selected{{ end }}>open ({{ .RepoInfo.Stats.IssueCount.Open }})</option>
<option value="closed" {{ if not .FilteringByOpen }}selected{{ end }}>closed ({{ .RepoInfo.Stats.IssueCount.Closed }})</option>
</select>
+1 -1
appview/pages/templates/repo/log.html
···
<p
class="hidden mt-1 text-sm cursor-text pb-2 dark:text-gray-300"
>
-
{{ nl2br (unwrapText (index $messageParts 1)) }}
+
{{ nl2br (index $messageParts 1) }}
</p>
{{ end }}
</div>
-13
appview/pages/templates/repo/pulls/patch.html
···
{{ end }}
</section>
-
<div id="diff-stat">
-
<br>
-
<strong class="text-sm uppercase mb-4">Changed files</strong>
-
{{ range .Diff.Diff }}
-
<ul>
-
{{ if .IsDelete }}
-
<li><a href="#file-{{ .Name.Old }}">{{ .Name.Old }}</a></li>
-
{{ else }}
-
<li><a href="#file-{{ .Name.New }}">{{ .Name.New }}</a></li>
-
{{ end }}
-
</ul>
-
{{ end }}
-
</div>
</div>
<section>
+1 -1
appview/pages/templates/repo/pulls/pull.html
···
{{ end }}
</div>
</details>
-
<hr class="md:hidden"/>
+
<hr class="md:hidden border-t border-gray-300 dark:border-gray-600"/>
{{ end }}
{{ end }}
{{ end }}
+1 -1
appview/pages/templates/repo/pulls/pulls.html
···
<p class="dark:text-white">
filtering
<select
-
class="border px-1 bg-white dark:bg-gray-800 border-gray-200 dark:border-gray-600 dark:text-white"
+
class="border p-1 bg-white dark:bg-gray-800 border-gray-200 dark:border-gray-600 dark:text-white"
onchange="window.location.href = '/{{ .RepoInfo.FullName }}/pulls?state=' + this.value"
>
<option value="open" {{ if .FilteringBy.IsOpen }}selected{{ end }}>
+4 -3
appview/pages/templates/repo/tree.html
···
{{ $stats := .TreeStats }}
<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>
+
<span>{{ $stats.NumFolders }} folder</span>
{{ else if gt $stats.NumFolders 1 }}
+
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
<span>{{ $stats.NumFolders }} folders</span>
-
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
{{ end }}
{{ if eq $stats.NumFiles 1 }}
+
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
<span>{{ $stats.NumFiles }} file</span>
{{ else if gt $stats.NumFiles 1 }}
+
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
<span>{{ $stats.NumFiles }} files</span>
{{ end }}
+14
types/diff.go
···
IsRename bool `json:"is_rename"`
}
+
type DiffStat struct {
+
Insertions int64
+
Deletions int64
+
}
+
+
func (d *Diff) Stats() DiffStat {
+
var stats DiffStat
+
for _, f := range d.TextFragments {
+
stats.Insertions += f.LinesAdded
+
stats.Deletions += f.LinesDeleted
+
}
+
return stats
+
}
+
// A nicer git diff representation.
type NiceDiff struct {
Commit struct {