+3
appview/pages/pages.go
+3
appview/pages/pages.go
···
527
Active string
528
EmailToDidOrHandle map[string]string
529
Pipeline *db.Pipeline
530
531
// singular because it's always going to be just one
532
VerifiedCommit commitverify.VerifiedCommits
···
859
Round int
860
Submission *db.PullSubmission
861
OrderedReactionKinds []db.ReactionKind
862
}
863
864
// this name is a mouthful
···
964
Base string
965
Head string
966
Diff *types.NiceDiff
967
968
Active string
969
}
···
527
Active string
528
EmailToDidOrHandle map[string]string
529
Pipeline *db.Pipeline
530
+
DiffOpts types.DiffOpts
531
532
// singular because it's always going to be just one
533
VerifiedCommit commitverify.VerifiedCommits
···
860
Round int
861
Submission *db.PullSubmission
862
OrderedReactionKinds []db.ReactionKind
863
+
DiffOpts types.DiffOpts
864
}
865
866
// this name is a mouthful
···
966
Base string
967
Head string
968
Diff *types.NiceDiff
969
+
DiffOpts types.DiffOpts
970
971
Active string
972
}
+1
-1
appview/pages/templates/repo/commit.html
+1
-1
appview/pages/templates/repo/commit.html
+1
-1
appview/pages/templates/repo/compare/compare.html
+1
-1
appview/pages/templates/repo/compare/compare.html
+118
-39
appview/pages/templates/repo/fragments/diff.html
+118
-39
appview/pages/templates/repo/fragments/diff.html
···
1
{{ define "repo/fragments/diff" }}
2
{{ $repo := index . 0 }}
3
{{ $diff := index . 1 }}
4
{{ $commit := $diff.Commit }}
5
{{ $diff := $diff.Diff }}
6
{{ $this := $commit.This }}
7
{{ $parent := $commit.Parent }}
8
···
85
This is a binary file and will not be displayed.
86
</p>
87
{{ else }}
88
-
{{ $name := .Name.New }}
89
-
<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">···</div>
90
-
{{- $oldStart := .OldPosition -}}
91
-
{{- $newStart := .NewPosition -}}
92
-
{{- $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 " -}}
93
-
{{- $linkStyle := "text-gray-400 dark:text-gray-500 hover:underline" -}}
94
-
{{- $lineNrSepStyle1 := "" -}}
95
-
{{- $lineNrSepStyle2 := "pr-2" -}}
96
-
{{- range .Lines -}}
97
-
{{- if eq .Op.String "+" -}}
98
-
<div class="bg-green-100 dark:bg-green-800/30 text-green-700 dark:text-green-400 flex min-w-full items-center">
99
-
<div class="{{$lineNrStyle}} {{$lineNrSepStyle1}}"><span aria-hidden="true" class="invisible">{{$newStart}}</span></div>
100
-
<div class="{{$lineNrStyle}} {{$lineNrSepStyle2}}" id="{{$name}}-N{{$newStart}}"><a class="{{$linkStyle}}" href="#{{$name}}-N{{$newStart}}">{{ $newStart }}</a></div>
101
-
<div class="w-5 flex-shrink-0 select-none text-center">{{ .Op.String }}</div>
102
-
<div class="px-2">{{ .Line }}</div>
103
-
</div>
104
-
{{- $newStart = add64 $newStart 1 -}}
105
-
{{- end -}}
106
-
{{- if eq .Op.String "-" -}}
107
-
<div class="bg-red-100 dark:bg-red-800/30 text-red-700 dark:text-red-400 flex min-w-full items-center">
108
-
<div class="{{$lineNrStyle}} {{$lineNrSepStyle1}}" id="{{$name}}-O{{$oldStart}}"><a class="{{$linkStyle}}" href="#{{$name}}-O{{$oldStart}}">{{ $oldStart }}</a></div>
109
-
<div class="{{$lineNrStyle}} {{$lineNrSepStyle2}}"><span aria-hidden="true" class="invisible">{{$oldStart}}</span></div>
110
-
<div class="w-5 flex-shrink-0 select-none text-center">{{ .Op.String }}</div>
111
-
<div class="px-2">{{ .Line }}</div>
112
-
</div>
113
-
{{- $oldStart = add64 $oldStart 1 -}}
114
-
{{- end -}}
115
-
{{- if eq .Op.String " " -}}
116
-
<div class="bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400 flex min-w-full items-center">
117
-
<div class="{{$lineNrStyle}} {{$lineNrSepStyle1}}" id="{{$name}}-O{{$oldStart}}"><a class="{{$linkStyle}}" href="#{{$name}}-O{{$oldStart}}">{{ $oldStart }}</a></div>
118
-
<div class="{{$lineNrStyle}} {{$lineNrSepStyle2}}" id="{{$name}}-N{{$newStart}}"><a class="{{$linkStyle}}" href="#{{$name}}-N{{$newStart}}">{{ $newStart }}</a></div>
119
-
<div class="w-5 flex-shrink-0 select-none text-center">{{ .Op.String }}</div>
120
-
<div class="px-2">{{ .Line }}</div>
121
-
</div>
122
-
{{- $newStart = add64 $newStart 1 -}}
123
-
{{- $oldStart = add64 $oldStart 1 -}}
124
-
{{- end -}}
125
-
{{- end -}}
126
-
{{- end -}}</div></div></pre>
127
{{- end -}}
128
</div>
129
···
136
{{ end }}
137
{{ end }}
138
139
{{ define "statPill" }}
140
<div class="flex items-center font-mono text-sm">
141
{{ if and .Insertions .Deletions }}
···
148
{{ end }}
149
</div>
150
{{ end }}
···
1
{{ define "repo/fragments/diff" }}
2
{{ $repo := index . 0 }}
3
{{ $diff := index . 1 }}
4
+
{{ $opts := index . 2 }}
5
+
6
{{ $commit := $diff.Commit }}
7
{{ $diff := $diff.Diff }}
8
+
{{ $isSplit := $opts.Split }}
9
{{ $this := $commit.This }}
10
{{ $parent := $commit.Parent }}
11
···
88
This is a binary file and will not be displayed.
89
</p>
90
{{ else }}
91
+
{{ if $isSplit }}
92
+
{{- template "repo/fragments/splitDiff" .Split -}}
93
+
{{ else }}
94
+
{{- template "repo/fragments/unifiedDiff" . -}}
95
+
{{ end }}
96
{{- end -}}
97
</div>
98
···
105
{{ end }}
106
{{ end }}
107
108
+
{{ define "unifiedDiffLines" }}
109
+
{{ $name := .Name.New }}
110
+
<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">···</div>
111
+
{{- $oldStart := .OldPosition -}}
112
+
{{- $newStart := .NewPosition -}}
113
+
{{- $lineNrStyle := "min-w-[3.5rem] flex-shrink-0 select-none text-right bg-white dark:bg-gray-800 target:bg-yellow-200 target:dark:bg-yellow-600" -}}
114
+
{{- $linkStyle := "text-gray-400 dark:text-gray-500 hover:underline" -}}
115
+
{{- $lineNrSepStyle1 := "" -}}
116
+
{{- $lineNrSepStyle2 := "pr-2 border-r border-gray-200 dark:border-gray-700" -}}
117
+
{{- $containerStyle := "flex min-w-full items-center target:border target:rounded-sm target:border-yellow-200 target:dark:border-yellow-700 scroll-mt-20" -}}
118
+
{{- $addStyle := "bg-green-100 dark:bg-green-800/30 text-green-700 dark:text-green-400 " -}}
119
+
{{- $delStyle := "bg-red-100 dark:bg-red-800/30 text-red-700 dark:text-red-400 " -}}
120
+
{{- $ctxStyle := "bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400" -}}
121
+
{{- $opStyle := "w-5 flex-shrink-0 select-none text-center" -}}
122
+
{{- range .Lines -}}
123
+
{{- if eq .Op.String "+" -}}
124
+
<div class="{{ $addStyle }} {{ $containerStyle }}" id="{{$name}}-N{{$newStart}}">
125
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle1}}"><span aria-hidden="true" class="invisible">{{$newStart}}</span></div>
126
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle2}}"><a class="{{$linkStyle}}" href="#{{$name}}-N{{$newStart}}">{{ $newStart }}</a></div>
127
+
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
128
+
<div class="px-2">{{ .Line }}</div>
129
+
</div>
130
+
{{- $newStart = add64 $newStart 1 -}}
131
+
{{- end -}}
132
+
{{- if eq .Op.String "-" -}}
133
+
<div class="{{ $delStyle }} {{ $containerStyle }}" id="{{$name}}-O{{$oldStart}}">
134
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle1}}"><a class="{{$linkStyle}}" href="#{{$name}}-O{{$oldStart}}">{{ $oldStart }}</a></div>
135
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle2}}"><span aria-hidden="true" class="invisible">{{$oldStart}}</span></div>
136
+
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
137
+
<div class="px-2">{{ .Line }}</div>
138
+
</div>
139
+
{{- $oldStart = add64 $oldStart 1 -}}
140
+
{{- end -}}
141
+
{{- if eq .Op.String " " -}}
142
+
<div class="{{ $ctxStyle }} {{ $containerStyle }}" id="{{$name}}-O{{$oldStart}}-N{{$newStart}}">
143
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle1}}"><a class="{{$linkStyle}}" href="#{{$name}}-O{{$oldStart}}-N{{$newStart}}">{{ $oldStart }}</a></div>
144
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle2}}"><a class="{{$linkStyle}}" href="#{{$name}}-O{{$oldStart}}-N{{$newStart}}">{{ $newStart }}</a></div>
145
+
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
146
+
<div class="px-2">{{ .Line }}</div>
147
+
</div>
148
+
{{- $newStart = add64 $newStart 1 -}}
149
+
{{- $oldStart = add64 $oldStart 1 -}}
150
+
{{- end -}}
151
+
{{- end -}}
152
+
{{- end -}}</div></div></pre>
153
+
{{ end }}
154
+
155
+
{{ define "splitDiffLines" }}
156
+
{{ $name := .Name.New }}
157
+
{{- $lineNrStyle := "min-w-[3.5rem] flex-shrink-0 select-none text-right bg-white dark:bg-gray-800" -}}
158
+
{{- $linkStyle := "text-gray-400 dark:text-gray-500 hover:underline" -}}
159
+
{{- $lineNrSepStyle := "pr-2 border-r border-gray-200 dark:border-gray-700" -}}
160
+
{{- $containerStyle := "flex min-w-full items-center target:border target:rounded-sm target:border-yellow-200 target:dark:border-yellow-700 scroll-mt-20" -}}
161
+
{{- $emptyStyle := "bg-gray-200/30 dark:bg-gray-700/30" -}}
162
+
{{- $addStyle := "bg-green-100 dark:bg-green-800/30 text-green-700 dark:text-green-400" -}}
163
+
{{- $delStyle := "bg-red-100 dark:bg-red-800/30 text-red-700 dark:text-red-400 " -}}
164
+
{{- $ctxStyle := "bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400" -}}
165
+
{{- $opStyle := "w-5 flex-shrink-0 select-none text-center" -}}
166
+
<div class="grid grid-cols-2 divide-x divide-gray-200 dark:divide-gray-700">
167
+
<pre class="overflow-x-auto col-span-1"><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">···</div>
168
+
{{- range .LeftLines -}}
169
+
{{- if .IsEmpty -}}
170
+
<div class="{{ $emptyStyle }} {{ $containerStyle }}">
171
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle}}"><span aria-hidden="true" class="invisible">{{.LineNumber}}</span></div>
172
+
<div class="{{ $opStyle }}"><span aria-hidden="true" class="invisible">{{ .Op.String }}</span></div>
173
+
<div class="px-2 invisible" aria-hidden="true">{{ .Content }}</div>
174
+
</div>
175
+
{{- else if eq .Op.String "-" -}}
176
+
<div class="{{ $delStyle }} {{ $containerStyle }}" id="{{$name}}-O{{.LineNumber}}">
177
+
<div class="{{ $lineNrStyle }} {{ $lineNrSepStyle }}"><a class="{{$linkStyle}}" href="#{{$name}}-O{{.LineNumber}}">{{ .LineNumber }}</a></div>
178
+
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
179
+
<div class="px-2">{{ .Content }}</div>
180
+
</div>
181
+
{{- else if eq .Op.String " " -}}
182
+
<div class="{{ $ctxStyle }} {{ $containerStyle }}" id="{{$name}}-O{{.LineNumber}}">
183
+
<div class="{{ $lineNrStyle }} {{ $lineNrSepStyle }}"><a class="{{$linkStyle}}" href="#{{$name}}-O{{.LineNumber}}">{{ .LineNumber }}</a></div>
184
+
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
185
+
<div class="px-2">{{ .Content }}</div>
186
+
</div>
187
+
{{- end -}}
188
+
{{- end -}}
189
+
{{- end -}}</div></div></pre>
190
+
191
+
<pre class="overflow-x-auto col-span-1"><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">···</div>
192
+
{{- range .RightLines -}}
193
+
{{- if .IsEmpty -}}
194
+
<div class="{{ $emptyStyle }} {{ $containerStyle }}">
195
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle}}"><span aria-hidden="true" class="invisible">{{.LineNumber}}</span></div>
196
+
<div class="{{ $opStyle }}"><span aria-hidden="true" class="invisible">{{ .Op.String }}</span></div>
197
+
<div class="px-2 invisible" aria-hidden="true">{{ .Content }}</div>
198
+
</div>
199
+
{{- else if eq .Op.String "+" -}}
200
+
<div class="{{ $addStyle }} {{ $containerStyle }}" id="{{$name}}-N{{.LineNumber}}">
201
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle}}"><a class="{{$linkStyle}}" href="#{{$name}}-N{{.LineNumber}}">{{ .LineNumber }}</a></div>
202
+
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
203
+
<div class="px-2" >{{ .Content }}</div>
204
+
</div>
205
+
{{- else if eq .Op.String " " -}}
206
+
<div class="{{ $ctxStyle }} {{ $containerStyle }}" id="{{$name}}-N{{.LineNumber}}">
207
+
<div class="{{$lineNrStyle}} {{$lineNrSepStyle}}"><a class="{{$linkStyle}}" href="#{{$name}}-N{{.LineNumber}}">{{ .LineNumber }}</a></div>
208
+
<div class="{{ $opStyle }}">{{ .Op.String }}</div>
209
+
<div class="px-2">{{ .Content }}</div>
210
+
</div>
211
+
{{- end -}}
212
+
{{- end -}}
213
+
{{- end -}}</div></div></pre>
214
+
</div>
215
+
{{ end }}
216
+
217
{{ define "statPill" }}
218
<div class="flex items-center font-mono text-sm">
219
{{ if and .Insertions .Deletions }}
···
226
{{ end }}
227
</div>
228
{{ end }}
229
+
+1
-1
appview/pages/templates/repo/fragments/diffChangedFiles.html
+1
-1
appview/pages/templates/repo/fragments/diffChangedFiles.html
···
2
{{ $stat := .Stat }}
3
{{ $fileTree := fileTree .ChangedFiles }}
4
<div class="col-span-1 md:col-span-2 mt-4">
5
-
<section class="sticky top-0 overflow-x-auto px-6 py-4 border border-gray-200 dark:border-gray-700 w-full mx-auto rounded bg-white dark:bg-gray-800 drop-shadow-sm">
6
<div class="diff-stat">
7
<div class="flex gap-2 items-center">
8
<strong class="text-sm uppercase dark:text-gray-200">Changed files</strong>
···
2
{{ $stat := .Stat }}
3
{{ $fileTree := fileTree .ChangedFiles }}
4
<div class="col-span-1 md:col-span-2 mt-4">
5
+
<section class="sticky top-0 overflow-x-auto text-sm px-6 py-2 border border-gray-200 dark:border-gray-700 w-full mx-auto md:min-h-screen rounded bg-white dark:bg-gray-800 drop-shadow-sm">
6
<div class="diff-stat">
7
<div class="flex gap-2 items-center">
8
<strong class="text-sm uppercase dark:text-gray-200">Changed files</strong>
+1
-1
appview/pages/templates/repo/fragments/interdiffFiles.html
+1
-1
appview/pages/templates/repo/fragments/interdiffFiles.html
···
1
{{ define "repo/fragments/interdiffFiles" }}
2
{{ $fileTree := fileTree .AffectedFiles }}
3
-
<section class="mt-4 p-6 border border-gray-200 dark:border-gray-700 w-full mx-auto rounded bg-white dark:bg-gray-800 drop-shadow-sm">
4
<div class="diff-stat">
5
<div class="flex gap-2 items-center">
6
<strong class="text-sm uppercase dark:text-gray-200">files</strong>
···
1
{{ define "repo/fragments/interdiffFiles" }}
2
{{ $fileTree := fileTree .AffectedFiles }}
3
+
<section class="mt-4 px-6 py-2 border border-gray-200 dark:border-gray-700 w-full mx-auto rounded bg-white dark:bg-gray-800 drop-shadow-sm md:min-h-screen text-sm">
4
<div class="diff-stat">
5
<div class="flex gap-2 items-center">
6
<strong class="text-sm uppercase dark:text-gray-200">files</strong>
+1
-1
appview/pages/templates/repo/pulls/patch.html
+1
-1
appview/pages/templates/repo/pulls/patch.html
-1
appview/pages/templates/repo/pulls/pull.html
-1
appview/pages/templates/repo/pulls/pull.html
+6
appview/pulls/pulls.go
+6
appview/pulls/pulls.go
···
355
return
356
}
357
358
+
var diffOpts types.DiffOpts
359
+
if d := r.URL.Query().Get("diff"); d == "split" {
360
+
diffOpts.Split = true
361
+
}
362
+
363
pull, ok := r.Context().Value("pull").(*db.Pull)
364
if !ok {
365
log.Println("failed to get pull")
···
400
Round: roundIdInt,
401
Submission: pull.Submissions[roundIdInt],
402
Diff: &diff,
403
+
DiffOpts: diffOpts,
404
})
405
406
}
+12
-1
appview/repo/repo.go
+12
-1
appview/repo/repo.go
···
268
protocol = "https"
269
}
270
271
if !plumbing.IsHash(ref) {
272
rp.pages.Error404(w)
273
return
···
321
EmailToDidOrHandle: emailToDidOrHandle(rp, emailToDidMap),
322
VerifiedCommit: vc,
323
Pipeline: pipeline,
324
})
325
-
return
326
}
327
328
func (rp *Repo) RepoTree(w http.ResponseWriter, r *http.Request) {
···
1269
return
1270
}
1271
1272
// if user is navigating to one of
1273
// /compare/{base}/{head}
1274
// /compare/{base}...{head}
···
1331
Base: base,
1332
Head: head,
1333
Diff: &diff,
1334
})
1335
1336
}
···
268
protocol = "https"
269
}
270
271
+
var diffOpts types.DiffOpts
272
+
if d := r.URL.Query().Get("diff"); d == "split" {
273
+
diffOpts.Split = true
274
+
}
275
+
276
if !plumbing.IsHash(ref) {
277
rp.pages.Error404(w)
278
return
···
326
EmailToDidOrHandle: emailToDidOrHandle(rp, emailToDidMap),
327
VerifiedCommit: vc,
328
Pipeline: pipeline,
329
+
DiffOpts: diffOpts,
330
})
331
}
332
333
func (rp *Repo) RepoTree(w http.ResponseWriter, r *http.Request) {
···
1274
return
1275
}
1276
1277
+
var diffOpts types.DiffOpts
1278
+
if d := r.URL.Query().Get("diff"); d == "split" {
1279
+
diffOpts.Split = true
1280
+
}
1281
+
1282
// if user is navigating to one of
1283
// /compare/{base}/{head}
1284
// /compare/{base}...{head}
···
1341
Base: base,
1342
Head: head,
1343
Diff: &diff,
1344
+
DiffOpts: diffOpts,
1345
})
1346
1347
}
+26
types/diff.go
+26
types/diff.go
···
5
"github.com/go-git/go-git/v5/plumbing/object"
6
)
7
8
+
type DiffOpts struct {
9
+
Split bool `json:"split"`
10
+
}
11
+
12
type TextFragment struct {
13
Header string `json:"comment"`
14
Lines []gitdiff.Line `json:"lines"`
···
81
82
return files
83
}
84
+
85
+
// used by html elements as a unique ID for hrefs
86
+
func (d *Diff) Id() string {
87
+
return d.Name.New
88
+
}
89
+
90
+
func (d *Diff) Split() *SplitDiff {
91
+
fragments := make([]SplitFragment, len(d.TextFragments))
92
+
for i, fragment := range d.TextFragments {
93
+
leftLines, rightLines := SeparateLines(&fragment)
94
+
fragments[i] = SplitFragment{
95
+
Header: fragment.Header(),
96
+
LeftLines: leftLines,
97
+
RightLines: rightLines,
98
+
}
99
+
}
100
+
101
+
return &SplitDiff{
102
+
Name: d.Id(),
103
+
TextFragments: fragments,
104
+
}
105
+
}