// SPDX-License-Identifier: AGPL-3.0-or-later
package web
// Commit is a commit: the message and facts, the diff tools, the diff.
templ Commit(l Layout, p CommitPage) {
@Shell(l, commitRail(p)) {
{ p.Subject }
if p.Body != "" {
{ p.Body }
}
commit
{ p.SHA }
author
@personView(p.Author)
if p.Committer != nil {
committer
@personView(*p.Committer)
}
if p.Merge {
merge of
} else {
parent
}
if p.Root {
none (root commit)
}
for i, par := range p.Parents {
if i > 0 {
{ " + " }
}
{ par.Label }
}
if p.Merge {
{ " · diff against the first parent" }
}
this diff holds invisible characters (direction controls, zero-width characters). They are shown as
<U+XXXX> markers, never applied.
}
if p.Note != "" {
{ p.Note }
}
for _, f := range p.Files {
@DiffFileView(f, p.DiffView)
}
if len(p.Files) == 0 {
no changed files{ " " }
if p.Merge {
against the first parent.
} else {
in this commit.
}
}
}
}
// viewLink is a button of the diff tools. It is a link, so that the split
// layout works without JavaScript; with it, and when both layouts are in the
// page, a click only flips the layout.
templ viewLink(p DiffView, view, label, key, href string) {
{ label }
}
templ personView(pr Person) {
{ pr.Name }
if pr.WhenAt != "" {
{ " · " }{ " · " + pr.Abs }
}
}
templ commitRail(p CommitPage) {
files { itoa(len(p.Files)) }
@FileList(p.Files)
}
// FileList is the table of contents of a diff: status letter, path, +n -m
// and an ASCII bar. The row of the file in view is marked.
templ FileList(files []DiffFile) {
for _, f := range files {
}
}
// DiffFileView is one file of the diff: a (per-file collapse). The
// unified and the split tables are both in it; #diffs[data-diff] shows one.
// Every changed line keeps its +/- marker, so a change is never conveyed by
// colour alone.
templ DiffFileView(f DiffFile, p DiffView) {
{ f.Status }{ " " }{ f.Path }{ " " }+{ itoa(f.Add) }{ " " }-{ itoa(f.Del) }
if f.Note != "" {
{ " " }{ f.Note }
}
if len(f.Hunks) > 0 {
if p.ShowUnified {
for _, h := range f.Hunks {
{ h.Header }
for _, ln := range h.Lines {
@gutter(ln.Old, ln.OldHref)
@gutter(ln.New, ln.NewHref)
{ ln.Mark }
@codeLine(ln)
if len(ln.Notes) > 0 || ln.Form != nil {
@lineNotes(ln.Notes, ln.Form, "")
}
}
}
}
if p.ShowSplit {
for _, h := range f.Hunks {
{ h.Header }
for _, row := range h.Split {
@splitSide(row.L, true)
@splitSide(row.R, false)
if notes, form := row.Notes(), row.Form(); len(notes) > 0 || form != nil {
@lineNotes(notes, form, "-s")
}
}
}
}
} else {
if f.Note != "" {
{ f.Note }
} else {
no textual change.
}
}
}
// splitSide is one half of a row of the split view; a side without a line is
// an empty cell.
templ splitSide(ln *DiffLine, old bool) {
if ln == nil {
} else {
if old {
@gutter(ln.Old, ln.OldHref)
} else {
@gutter(ln.New, ln.NewHref)
}
{ ln.Mark }
@codeLine(*ln)
}
}
// gutter is a line number of the gutter. On a merge request that can be
// commented on, it links to the form that comments on that line.
templ gutter(n, href string) {
if href != "" {
{ n }
} else {
{ n }
}
}