Expand/Collapse Files and Blob Excerpt while Reviewing/Comparing code (#8924)
* update #8659 fold/unfold code diffs * add fold button style * update #8659 implement expand up/down codes (blob excerpt) * fix golint errors * fix expand direction * remove debug message * update css style for blob exceprt * fix typo in comment * update style sheet with less * update expect diff (add SectionInfo) * update #8942 accept suggested change (fix typo) * close reader and check file type before get tail section * adjust button position and check file type before insert fold button * move index js to web_src * merge index.js with master * generate index.js * update js coding style
This commit is contained in:
parent
42ada741e3
commit
149a9df9e8
16 changed files with 460 additions and 36 deletions
|
@ -6,6 +6,7 @@
|
||||||
package git
|
package git
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
@ -50,6 +51,28 @@ func (b *Blob) GetBlobContent() (string, error) {
|
||||||
return string(buf), nil
|
return string(buf), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetBlobLineCount gets line count of lob as raw text
|
||||||
|
func (b *Blob) GetBlobLineCount() (int, error) {
|
||||||
|
reader, err := b.DataAsync()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
defer reader.Close()
|
||||||
|
buf := make([]byte, 32*1024)
|
||||||
|
count := 0
|
||||||
|
lineSep := []byte{'\n'}
|
||||||
|
for {
|
||||||
|
c, err := reader.Read(buf)
|
||||||
|
count += bytes.Count(buf[:c], lineSep)
|
||||||
|
switch {
|
||||||
|
case err == io.EOF:
|
||||||
|
return count, nil
|
||||||
|
case err != nil:
|
||||||
|
return count, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// GetBlobContentBase64 Reads the content of the blob with a base64 encode and returns the encoded string
|
// GetBlobContentBase64 Reads the content of the blob with a base64 encode and returns the encoded string
|
||||||
func (b *Blob) GetBlobContentBase64() (string, error) {
|
func (b *Blob) GetBlobContentBase64() (string, error) {
|
||||||
dataRc, err := b.DataAsync()
|
dataRc, err := b.DataAsync()
|
||||||
|
|
|
@ -55,6 +55,15 @@ func TestGetDiffPreview(t *testing.T) {
|
||||||
Type: 4,
|
Type: 4,
|
||||||
Content: "@@ -1,3 +1,4 @@",
|
Content: "@@ -1,3 +1,4 @@",
|
||||||
Comments: nil,
|
Comments: nil,
|
||||||
|
SectionInfo: &gitdiff.DiffLineSectionInfo{
|
||||||
|
Path: "README.md",
|
||||||
|
LastLeftIdx: 0,
|
||||||
|
LastRightIdx: 0,
|
||||||
|
LeftIdx: 1,
|
||||||
|
RightIdx: 1,
|
||||||
|
LeftHunkSize: 3,
|
||||||
|
RightHunkSize: 4,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
LeftIdx: 1,
|
LeftIdx: 1,
|
||||||
|
|
|
@ -898,6 +898,7 @@ tbody.commit-list{vertical-align:baseline}
|
||||||
.repo-buttons .disabled-repo-button a.button:hover{background:0 0!important;color:rgba(0,0,0,.6)!important;box-shadow:0 0 0 1px rgba(34,36,38,.15) inset!important}
|
.repo-buttons .disabled-repo-button a.button:hover{background:0 0!important;color:rgba(0,0,0,.6)!important;box-shadow:0 0 0 1px rgba(34,36,38,.15) inset!important}
|
||||||
.repo-buttons .ui.labeled.button>.label{border-left:0!important;margin:0!important}
|
.repo-buttons .ui.labeled.button>.label{border-left:0!important;margin:0!important}
|
||||||
.tag-code,.tag-code td{background-color:#f0f0f0!important;border-color:#d3cfcf!important;padding-top:8px;padding-bottom:8px}
|
.tag-code,.tag-code td{background-color:#f0f0f0!important;border-color:#d3cfcf!important;padding-top:8px;padding-bottom:8px}
|
||||||
|
td.blob-excerpt{background-color:#fafafa}
|
||||||
.issue-keyword{border-bottom:1px dotted #959da5;display:inline-block}
|
.issue-keyword{border-bottom:1px dotted #959da5;display:inline-block}
|
||||||
.file-header{display:flex;justify-content:space-between;align-items:center;padding:8px 12px!important}
|
.file-header{display:flex;justify-content:space-between;align-items:center;padding:8px 12px!important}
|
||||||
.file-info{display:flex;align-items:center}
|
.file-info{display:flex;align-items:center}
|
||||||
|
@ -1069,3 +1070,7 @@ tbody.commit-list{vertical-align:baseline}
|
||||||
.comment-code-cloud button.comment-form-reply{margin:.5em .5em .5em 4.5em}
|
.comment-code-cloud button.comment-form-reply{margin:.5em .5em .5em 4.5em}
|
||||||
.comment-code-cloud form.comment-form-reply{margin:0 0 0 4em}
|
.comment-code-cloud form.comment-form-reply{margin:0 0 0 4em}
|
||||||
.file-comment{font:12px 'SF Mono',Consolas,Menlo,'Liberation Mono',Monaco,'Lucida Console',monospace;color:rgba(0,0,0,.87)}
|
.file-comment{font:12px 'SF Mono',Consolas,Menlo,'Liberation Mono',Monaco,'Lucida Console',monospace;color:rgba(0,0,0,.87)}
|
||||||
|
.ui.fold-code{margin-right:1em;padding-left:5px;cursor:pointer;width:22px;font-size:12px}
|
||||||
|
.ui.fold-code:hover{color:#428bca}
|
||||||
|
.ui.blob-excerpt{display:block;line-height:20px;font-size:16px;cursor:pointer}
|
||||||
|
.ui.blob-excerpt:hover{color:#428bca}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -245,6 +245,7 @@ func Diff(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Data["CommitID"] = commitID
|
ctx.Data["CommitID"] = commitID
|
||||||
|
ctx.Data["AfterCommitID"] = commitID
|
||||||
ctx.Data["Username"] = userName
|
ctx.Data["Username"] = userName
|
||||||
ctx.Data["Reponame"] = repoName
|
ctx.Data["Reponame"] = repoName
|
||||||
|
|
||||||
|
|
|
@ -5,14 +5,18 @@
|
||||||
package repo
|
package repo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"html"
|
||||||
"path"
|
"path"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
|
"code.gitea.io/gitea/modules/highlight"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/services/gitdiff"
|
"code.gitea.io/gitea/services/gitdiff"
|
||||||
|
@ -20,6 +24,7 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
tplCompare base.TplName = "repo/diff/compare"
|
tplCompare base.TplName = "repo/diff/compare"
|
||||||
|
tplBlobExcerpt base.TplName = "repo/diff/blob_excerpt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// setPathsCompareContext sets context data for source and raw paths
|
// setPathsCompareContext sets context data for source and raw paths
|
||||||
|
@ -434,3 +439,109 @@ func CompareDiff(ctx *context.Context) {
|
||||||
|
|
||||||
ctx.HTML(200, tplCompare)
|
ctx.HTML(200, tplCompare)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExcerptBlob render blob excerpt contents
|
||||||
|
func ExcerptBlob(ctx *context.Context) {
|
||||||
|
commitID := ctx.Params("sha")
|
||||||
|
lastLeft := ctx.QueryInt("last_left")
|
||||||
|
lastRight := ctx.QueryInt("last_right")
|
||||||
|
idxLeft := ctx.QueryInt("left")
|
||||||
|
idxRight := ctx.QueryInt("right")
|
||||||
|
leftHunkSize := ctx.QueryInt("left_hunk_size")
|
||||||
|
rightHunkSize := ctx.QueryInt("right_hunk_size")
|
||||||
|
anchor := ctx.Query("anchor")
|
||||||
|
direction := ctx.Query("direction")
|
||||||
|
filePath := ctx.Query("path")
|
||||||
|
gitRepo := ctx.Repo.GitRepo
|
||||||
|
chunkSize := gitdiff.BlobExceprtChunkSize
|
||||||
|
commit, err := gitRepo.GetCommit(commitID)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(500, "GetCommit")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
section := &gitdiff.DiffSection{
|
||||||
|
Name: filePath,
|
||||||
|
}
|
||||||
|
if direction == "up" && (idxLeft-lastLeft) > chunkSize {
|
||||||
|
idxLeft -= chunkSize
|
||||||
|
idxRight -= chunkSize
|
||||||
|
leftHunkSize += chunkSize
|
||||||
|
rightHunkSize += chunkSize
|
||||||
|
section.Lines, err = getExcerptLines(commit, filePath, idxLeft-1, idxRight-1, chunkSize)
|
||||||
|
} else if direction == "down" && (idxLeft-lastLeft) > chunkSize {
|
||||||
|
section.Lines, err = getExcerptLines(commit, filePath, lastLeft, lastRight, chunkSize)
|
||||||
|
lastLeft += chunkSize
|
||||||
|
lastRight += chunkSize
|
||||||
|
} else {
|
||||||
|
section.Lines, err = getExcerptLines(commit, filePath, lastLeft, lastRight, idxRight-lastRight-1)
|
||||||
|
leftHunkSize = 0
|
||||||
|
rightHunkSize = 0
|
||||||
|
idxLeft = lastLeft
|
||||||
|
idxRight = lastRight
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(500, "getExcerptLines")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if idxRight > lastRight {
|
||||||
|
lineText := " "
|
||||||
|
if rightHunkSize > 0 || leftHunkSize > 0 {
|
||||||
|
lineText = fmt.Sprintf("@@ -%d,%d +%d,%d @@\n", idxLeft, leftHunkSize, idxRight, rightHunkSize)
|
||||||
|
}
|
||||||
|
lineText = html.EscapeString(lineText)
|
||||||
|
lineSection := &gitdiff.DiffLine{
|
||||||
|
Type: gitdiff.DiffLineSection,
|
||||||
|
Content: lineText,
|
||||||
|
SectionInfo: &gitdiff.DiffLineSectionInfo{
|
||||||
|
Path: filePath,
|
||||||
|
LastLeftIdx: lastLeft,
|
||||||
|
LastRightIdx: lastRight,
|
||||||
|
LeftIdx: idxLeft,
|
||||||
|
RightIdx: idxRight,
|
||||||
|
LeftHunkSize: leftHunkSize,
|
||||||
|
RightHunkSize: rightHunkSize,
|
||||||
|
}}
|
||||||
|
if direction == "up" {
|
||||||
|
section.Lines = append([]*gitdiff.DiffLine{lineSection}, section.Lines...)
|
||||||
|
} else if direction == "down" {
|
||||||
|
section.Lines = append(section.Lines, lineSection)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctx.Data["section"] = section
|
||||||
|
ctx.Data["fileName"] = filePath
|
||||||
|
ctx.Data["highlightClass"] = highlight.FileNameToHighlightClass(filepath.Base(filePath))
|
||||||
|
ctx.Data["AfterCommitID"] = commitID
|
||||||
|
ctx.Data["Anchor"] = anchor
|
||||||
|
ctx.HTML(200, tplBlobExcerpt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getExcerptLines(commit *git.Commit, filePath string, idxLeft int, idxRight int, chunkSize int) ([]*gitdiff.DiffLine, error) {
|
||||||
|
blob, err := commit.Tree.GetBlobByPath(filePath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
reader, err := blob.DataAsync()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer reader.Close()
|
||||||
|
scanner := bufio.NewScanner(reader)
|
||||||
|
var diffLines []*gitdiff.DiffLine
|
||||||
|
for line := 0; line < idxRight+chunkSize; line++ {
|
||||||
|
if ok := scanner.Scan(); !ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if line < idxRight {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
lineText := scanner.Text()
|
||||||
|
diffLine := &gitdiff.DiffLine{
|
||||||
|
LeftIdx: idxLeft + (line - idxRight) + 1,
|
||||||
|
RightIdx: line + 1,
|
||||||
|
Type: gitdiff.DiffLinePlain,
|
||||||
|
Content: " " + lineText,
|
||||||
|
}
|
||||||
|
diffLines = append(diffLines, diffLine)
|
||||||
|
}
|
||||||
|
return diffLines, nil
|
||||||
|
}
|
||||||
|
|
|
@ -552,6 +552,7 @@ func ViewPullFiles(ctx *context.Context) {
|
||||||
ctx.Data["Username"] = pull.MustHeadUserName()
|
ctx.Data["Username"] = pull.MustHeadUserName()
|
||||||
ctx.Data["Reponame"] = pull.HeadRepo.Name
|
ctx.Data["Reponame"] = pull.HeadRepo.Name
|
||||||
}
|
}
|
||||||
|
ctx.Data["AfterCommitID"] = endCommitID
|
||||||
|
|
||||||
diff, err := gitdiff.GetDiffRangeWithWhitespaceBehavior(diffRepoPath,
|
diff, err := gitdiff.GetDiffRangeWithWhitespaceBehavior(diffRepoPath,
|
||||||
startCommitID, endCommitID, setting.Git.MaxGitDiffLines,
|
startCommitID, endCommitID, setting.Git.MaxGitDiffLines,
|
||||||
|
|
|
@ -864,6 +864,10 @@ func RegisterRoutes(m *macaron.Macaron) {
|
||||||
m.Get("", repo.Branches)
|
m.Get("", repo.Branches)
|
||||||
}, repo.MustBeNotEmpty, context.RepoRef(), reqRepoCodeReader)
|
}, repo.MustBeNotEmpty, context.RepoRef(), reqRepoCodeReader)
|
||||||
|
|
||||||
|
m.Group("/blob_excerpt", func() {
|
||||||
|
m.Get("/:sha", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.ExcerptBlob)
|
||||||
|
}, repo.MustBeNotEmpty, context.RepoRef(), reqRepoCodeReader)
|
||||||
|
|
||||||
m.Group("/pulls/:index", func() {
|
m.Group("/pulls/:index", func() {
|
||||||
m.Get(".diff", repo.DownloadPullDiff)
|
m.Get(".diff", repo.DownloadPullDiff)
|
||||||
m.Get(".patch", repo.DownloadPullPatch)
|
m.Get(".patch", repo.DownloadPullPatch)
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"html/template"
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
@ -56,6 +57,18 @@ const (
|
||||||
DiffFileRename
|
DiffFileRename
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DiffLineExpandDirection represents the DiffLineSection expand direction
|
||||||
|
type DiffLineExpandDirection uint8
|
||||||
|
|
||||||
|
// DiffLineExpandDirection possible values.
|
||||||
|
const (
|
||||||
|
DiffLineExpandNone DiffLineExpandDirection = iota + 1
|
||||||
|
DiffLineExpandSingle
|
||||||
|
DiffLineExpandUpDown
|
||||||
|
DiffLineExpandUp
|
||||||
|
DiffLineExpandDown
|
||||||
|
)
|
||||||
|
|
||||||
// DiffLine represents a line difference in a DiffSection.
|
// DiffLine represents a line difference in a DiffSection.
|
||||||
type DiffLine struct {
|
type DiffLine struct {
|
||||||
LeftIdx int
|
LeftIdx int
|
||||||
|
@ -63,8 +76,23 @@ type DiffLine struct {
|
||||||
Type DiffLineType
|
Type DiffLineType
|
||||||
Content string
|
Content string
|
||||||
Comments []*models.Comment
|
Comments []*models.Comment
|
||||||
|
SectionInfo *DiffLineSectionInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DiffLineSectionInfo represents diff line section meta data
|
||||||
|
type DiffLineSectionInfo struct {
|
||||||
|
Path string
|
||||||
|
LastLeftIdx int
|
||||||
|
LastRightIdx int
|
||||||
|
LeftIdx int
|
||||||
|
RightIdx int
|
||||||
|
LeftHunkSize int
|
||||||
|
RightHunkSize int
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlobExceprtChunkSize represent max lines of excerpt
|
||||||
|
const BlobExceprtChunkSize = 20
|
||||||
|
|
||||||
// GetType returns the type of a DiffLine.
|
// GetType returns the type of a DiffLine.
|
||||||
func (d *DiffLine) GetType() int {
|
func (d *DiffLine) GetType() int {
|
||||||
return int(d.Type)
|
return int(d.Type)
|
||||||
|
@ -91,6 +119,71 @@ func (d *DiffLine) GetLineTypeMarker() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetBlobExcerptQuery builds query string to get blob excerpt
|
||||||
|
func (d *DiffLine) GetBlobExcerptQuery() string {
|
||||||
|
query := fmt.Sprintf(
|
||||||
|
"last_left=%d&last_right=%d&"+
|
||||||
|
"left=%d&right=%d&"+
|
||||||
|
"left_hunk_size=%d&right_hunk_size=%d&"+
|
||||||
|
"path=%s",
|
||||||
|
d.SectionInfo.LastLeftIdx, d.SectionInfo.LastRightIdx,
|
||||||
|
d.SectionInfo.LeftIdx, d.SectionInfo.RightIdx,
|
||||||
|
d.SectionInfo.LeftHunkSize, d.SectionInfo.RightHunkSize,
|
||||||
|
url.QueryEscape(d.SectionInfo.Path))
|
||||||
|
return query
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetExpandDirection gets DiffLineExpandDirection
|
||||||
|
func (d *DiffLine) GetExpandDirection() DiffLineExpandDirection {
|
||||||
|
if d.Type != DiffLineSection || d.SectionInfo == nil || d.SectionInfo.RightIdx-d.SectionInfo.LastRightIdx <= 1 {
|
||||||
|
return DiffLineExpandNone
|
||||||
|
}
|
||||||
|
if d.SectionInfo.LastLeftIdx <= 0 && d.SectionInfo.LastRightIdx <= 0 {
|
||||||
|
return DiffLineExpandUp
|
||||||
|
} else if d.SectionInfo.RightIdx-d.SectionInfo.LastRightIdx > BlobExceprtChunkSize && d.SectionInfo.RightHunkSize > 0 {
|
||||||
|
return DiffLineExpandUpDown
|
||||||
|
} else if d.SectionInfo.LeftHunkSize <= 0 && d.SectionInfo.RightHunkSize <= 0 {
|
||||||
|
return DiffLineExpandDown
|
||||||
|
}
|
||||||
|
return DiffLineExpandSingle
|
||||||
|
}
|
||||||
|
|
||||||
|
func getDiffLineSectionInfo(curFile *DiffFile, line string, lastLeftIdx, lastRightIdx int) *DiffLineSectionInfo {
|
||||||
|
var (
|
||||||
|
leftLine int
|
||||||
|
leftHunk int
|
||||||
|
rightLine int
|
||||||
|
righHunk int
|
||||||
|
)
|
||||||
|
ss := strings.Split(line, "@@")
|
||||||
|
ranges := strings.Split(ss[1][1:], " ")
|
||||||
|
leftRange := strings.Split(ranges[0], ",")
|
||||||
|
leftLine, _ = com.StrTo(leftRange[0][1:]).Int()
|
||||||
|
if len(leftRange) > 1 {
|
||||||
|
leftHunk, _ = com.StrTo(leftRange[1]).Int()
|
||||||
|
}
|
||||||
|
if len(ranges) > 1 {
|
||||||
|
rightRange := strings.Split(ranges[1], ",")
|
||||||
|
rightLine, _ = com.StrTo(rightRange[0]).Int()
|
||||||
|
if len(rightRange) > 1 {
|
||||||
|
righHunk, _ = com.StrTo(rightRange[1]).Int()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Warn("Parse line number failed: %v", line)
|
||||||
|
rightLine = leftLine
|
||||||
|
righHunk = leftHunk
|
||||||
|
}
|
||||||
|
return &DiffLineSectionInfo{
|
||||||
|
Path: curFile.Name,
|
||||||
|
LastLeftIdx: lastLeftIdx,
|
||||||
|
LastRightIdx: lastRightIdx,
|
||||||
|
LeftIdx: leftLine,
|
||||||
|
RightIdx: rightLine,
|
||||||
|
LeftHunkSize: leftHunk,
|
||||||
|
RightHunkSize: righHunk,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// escape a line's content or return <br> needed for copy/paste purposes
|
// escape a line's content or return <br> needed for copy/paste purposes
|
||||||
func getLineContent(content string) string {
|
func getLineContent(content string) string {
|
||||||
if len(content) > 0 {
|
if len(content) > 0 {
|
||||||
|
@ -248,6 +341,53 @@ func (diffFile *DiffFile) GetHighlightClass() string {
|
||||||
return highlight.FileNameToHighlightClass(diffFile.Name)
|
return highlight.FileNameToHighlightClass(diffFile.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTailSection creates a fake DiffLineSection if the last section is not the end of the file
|
||||||
|
func (diffFile *DiffFile) GetTailSection(gitRepo *git.Repository, leftCommitID, rightCommitID string) *DiffSection {
|
||||||
|
if diffFile.Type != DiffFileChange || diffFile.IsBin || diffFile.IsLFSFile {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
leftCommit, err := gitRepo.GetCommit(leftCommitID)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
rightCommit, err := gitRepo.GetCommit(rightCommitID)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
lastSection := diffFile.Sections[len(diffFile.Sections)-1]
|
||||||
|
lastLine := lastSection.Lines[len(lastSection.Lines)-1]
|
||||||
|
leftLineCount := getCommitFileLineCount(leftCommit, diffFile.Name)
|
||||||
|
rightLineCount := getCommitFileLineCount(rightCommit, diffFile.Name)
|
||||||
|
if leftLineCount <= lastLine.LeftIdx || rightLineCount <= lastLine.RightIdx {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
tailDiffLine := &DiffLine{
|
||||||
|
Type: DiffLineSection,
|
||||||
|
Content: " ",
|
||||||
|
SectionInfo: &DiffLineSectionInfo{
|
||||||
|
Path: diffFile.Name,
|
||||||
|
LastLeftIdx: lastLine.LeftIdx,
|
||||||
|
LastRightIdx: lastLine.RightIdx,
|
||||||
|
LeftIdx: leftLineCount,
|
||||||
|
RightIdx: rightLineCount,
|
||||||
|
}}
|
||||||
|
tailSection := &DiffSection{Lines: []*DiffLine{tailDiffLine}}
|
||||||
|
return tailSection
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCommitFileLineCount(commit *git.Commit, filePath string) int {
|
||||||
|
blob, err := commit.GetBlobByPath(filePath)
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
lineCount, err := blob.GetBlobLineCount()
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return lineCount
|
||||||
|
}
|
||||||
|
|
||||||
// Diff represents a difference between two git trees.
|
// Diff represents a difference between two git trees.
|
||||||
type Diff struct {
|
type Diff struct {
|
||||||
TotalAddition, TotalDeletion int
|
TotalAddition, TotalDeletion int
|
||||||
|
@ -510,19 +650,16 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D
|
||||||
case line[0] == '@':
|
case line[0] == '@':
|
||||||
curSection = &DiffSection{}
|
curSection = &DiffSection{}
|
||||||
curFile.Sections = append(curFile.Sections, curSection)
|
curFile.Sections = append(curFile.Sections, curSection)
|
||||||
ss := strings.Split(line, "@@")
|
lineSectionInfo := getDiffLineSectionInfo(curFile, line, leftLine-1, rightLine-1)
|
||||||
diffLine := &DiffLine{Type: DiffLineSection, Content: line}
|
diffLine := &DiffLine{
|
||||||
curSection.Lines = append(curSection.Lines, diffLine)
|
Type: DiffLineSection,
|
||||||
|
Content: line,
|
||||||
// Parse line number.
|
SectionInfo: lineSectionInfo,
|
||||||
ranges := strings.Split(ss[1][1:], " ")
|
|
||||||
leftLine, _ = com.StrTo(strings.Split(ranges[0], ",")[0][1:]).Int()
|
|
||||||
if len(ranges) > 1 {
|
|
||||||
rightLine, _ = com.StrTo(strings.Split(ranges[1], ",")[0]).Int()
|
|
||||||
} else {
|
|
||||||
log.Warn("Parse line number failed: %v", line)
|
|
||||||
rightLine = leftLine
|
|
||||||
}
|
}
|
||||||
|
curSection.Lines = append(curSection.Lines, diffLine)
|
||||||
|
// update line number.
|
||||||
|
leftLine = lineSectionInfo.LeftIdx
|
||||||
|
rightLine = lineSectionInfo.RightIdx
|
||||||
continue
|
continue
|
||||||
case line[0] == '+':
|
case line[0] == '+':
|
||||||
curFile.Addition++
|
curFile.Addition++
|
||||||
|
@ -599,6 +736,8 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
curFileLinesCount = 0
|
curFileLinesCount = 0
|
||||||
|
leftLine = 1
|
||||||
|
rightLine = 1
|
||||||
curFileLFSPrefix = false
|
curFileLFSPrefix = false
|
||||||
|
|
||||||
// Check file diff type and is submodule.
|
// Check file diff type and is submodule.
|
||||||
|
@ -701,6 +840,7 @@ func GetDiffRangeWithWhitespaceBehavior(repoPath, beforeCommitID, afterCommitID
|
||||||
diffArgs = append(diffArgs, actualBeforeCommitID)
|
diffArgs = append(diffArgs, actualBeforeCommitID)
|
||||||
diffArgs = append(diffArgs, afterCommitID)
|
diffArgs = append(diffArgs, afterCommitID)
|
||||||
cmd = exec.Command(git.GitExecutable, diffArgs...)
|
cmd = exec.Command(git.GitExecutable, diffArgs...)
|
||||||
|
beforeCommitID = actualBeforeCommitID
|
||||||
}
|
}
|
||||||
cmd.Dir = repoPath
|
cmd.Dir = repoPath
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
|
@ -721,6 +861,12 @@ func GetDiffRangeWithWhitespaceBehavior(repoPath, beforeCommitID, afterCommitID
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("ParsePatch: %v", err)
|
return nil, fmt.Errorf("ParsePatch: %v", err)
|
||||||
}
|
}
|
||||||
|
for _, diffFile := range diff.Files {
|
||||||
|
tailSection := diffFile.GetTailSection(gitRepo, beforeCommitID, afterCommitID)
|
||||||
|
if tailSection != nil {
|
||||||
|
diffFile.Sections = append(diffFile.Sections, tailSection)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err = cmd.Wait(); err != nil {
|
if err = cmd.Wait(); err != nil {
|
||||||
return nil, fmt.Errorf("Wait: %v", err)
|
return nil, fmt.Errorf("Wait: %v", err)
|
||||||
|
|
50
templates/repo/diff/blob_excerpt.tmpl
Normal file
50
templates/repo/diff/blob_excerpt.tmpl
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
{{if $.IsSplitStyle}}
|
||||||
|
{{range $k, $line := $.section.Lines}}
|
||||||
|
<tr class="{{DiffLineTypeToStr .GetType}}-code nl-{{$k}} ol-{{$k}}">
|
||||||
|
{{if eq .GetType 4}}
|
||||||
|
<td class="lines-num lines-num-old" data-line-num="{{if $line.LeftIdx}}{{$line.LeftIdx}}{{end}}">
|
||||||
|
{{if or (eq $line.GetExpandDirection 3) (eq $line.GetExpandDirection 5) }}
|
||||||
|
<i class="ui blob-excerpt fa fa-caret-down" data-url="{{$.RepoLink}}/blob_excerpt/{{$.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=split&direction=down" data-anchor="{{$.Anchor}}"></i>
|
||||||
|
{{end}}
|
||||||
|
{{if or (eq $line.GetExpandDirection 3) (eq $line.GetExpandDirection 4) }}
|
||||||
|
<i class="ui blob-excerpt fa fa-caret-up" data-url="{{$.RepoLink}}/blob_excerpt/{{$.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=split&direction=up" data-anchor="{{$.Anchor}}"></i>
|
||||||
|
{{end}}
|
||||||
|
{{if or (eq $line.GetExpandDirection 2)}}
|
||||||
|
<i class="ui blob-excerpt octicon octicon-fold" data-url="{{$.RepoLink}}/blob_excerpt/{{$.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=split&direction=" data-anchor="{{$.Anchor}}"></i>
|
||||||
|
{{end}}
|
||||||
|
</td>
|
||||||
|
<td colspan="5" class="lines-code lines-code-old "><span class="mono wrap{{if $.highlightClass}} language-{{$.highlightClass}}{{else}} nohighlight{{end}}">{{$.section.GetComputedInlineDiffFor $line}}</span></td>
|
||||||
|
{{else}}
|
||||||
|
<td class="lines-num lines-num-old" data-line-num="{{if $line.LeftIdx}}{{$line.LeftIdx}}{{end}}"><span rel="{{if $line.LeftIdx}}diff-{{Sha1 $.fileName}}L{{$line.LeftIdx}}{{end}}"></span></td>
|
||||||
|
<td class="blob-excerpt lines-type-marker lines-type-marker-old">{{if $line.LeftIdx}}<span class="mono" data-type-marker=""></span>{{end}}</td>
|
||||||
|
<td class="blob-excerpt lines-code lines-code-old halfwidth"><span class="mono wrap{{if $.highlightClass}} language-{{$.highlightClass}}{{else}} nohighlight{{end}}">{{if $line.LeftIdx}}{{$.section.GetComputedInlineDiffFor $line}}{{end}}</span></td>
|
||||||
|
<td class="lines-num lines-num-new" data-line-num="{{if $line.RightIdx}}{{$line.RightIdx}}{{end}}"><span rel="{{if $line.RightIdx}}diff-{{Sha1 $.fileName}}R{{$line.RightIdx}}{{end}}"></span></td>
|
||||||
|
<td class="blob-excerpt lines-type-marker lines-type-marker-new">{{if $line.RightIdx}}<span class="mono" data-type-marker=""></span>{{end}}</td>
|
||||||
|
<td class="blob-excerpt lines-code lines-code-new halfwidth"><span class="mono wrap{{if $.highlightClass}} language-{{$.highlightClass}}{{else}} nohighlight{{end}}">{{if $line.RightIdx}}{{$.section.GetComputedInlineDiffFor $line}}{{end}}</span></td>
|
||||||
|
{{end}}
|
||||||
|
</tr>
|
||||||
|
{{end}}
|
||||||
|
{{else}}
|
||||||
|
{{range $k, $line := $.section.Lines}}
|
||||||
|
<tr class="{{DiffLineTypeToStr .GetType}}-code nl-{{$k}} ol-{{$k}}">
|
||||||
|
{{if eq .GetType 4}}
|
||||||
|
<td colspan="2" class="lines-num">
|
||||||
|
{{if or (eq $line.GetExpandDirection 3) (eq $line.GetExpandDirection 4) }}
|
||||||
|
<i class="ui blob-excerpt fa fa-caret-up" data-url="{{$.RepoLink}}/blob_excerpt/{{$.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=unified&direction=up" data-anchor="{{$.Anchor}}"></i>
|
||||||
|
{{end}}
|
||||||
|
{{if or (eq $line.GetExpandDirection 3) (eq $line.GetExpandDirection 5) }}
|
||||||
|
<i class="ui blob-excerpt fa fa-caret-down" data-url="{{$.RepoLink}}/blob_excerpt/{{$.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=unified&direction=down" data-anchor="{{$.Anchor}}"></i>
|
||||||
|
{{end}}
|
||||||
|
{{if or (eq $line.GetExpandDirection 2)}}
|
||||||
|
<i class="ui blob-excerpt octicon octicon-fold" data-url="{{$.RepoLink}}/blob_excerpt/{{$.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=unified&direction=" data-anchor="{{$.Anchor}}"></i>
|
||||||
|
{{end}}
|
||||||
|
</td>
|
||||||
|
{{else}}
|
||||||
|
<td class="lines-num lines-num-old" data-line-num="{{if $line.LeftIdx}}{{$line.LeftIdx}}{{end}}"><span rel="{{if $line.LeftIdx}}diff-{{Sha1 $.fileName}}L{{$line.LeftIdx}}{{end}}"></span></td>
|
||||||
|
<td class="lines-num lines-num-new" data-line-num="{{if $line.RightIdx}}{{$line.RightIdx}}{{end}}"><span rel="{{if $line.RightIdx}}diff-{{Sha1 $.fileName}}R{{$line.RightIdx}}{{end}}"></span></td>
|
||||||
|
{{end}}
|
||||||
|
<td class="blob-excerpt lines-type-marker"><span class="mono" data-type-marker="{{$line.GetLineTypeMarker}}"></span></td>
|
||||||
|
<td class="blob-excerpt lines-code{{if (not $line.RightIdx)}} lines-code-old{{end}}"><span class="mono wrap{{if $.highlightClass}} language-{{$.highlightClass}}{{else}} nohighlight{{end}}">{{$.section.GetComputedInlineDiffFor $line}}</span></td>
|
||||||
|
</tr>
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
|
@ -81,6 +81,15 @@
|
||||||
{{else}}
|
{{else}}
|
||||||
<div class="diff-file-box diff-box file-content {{TabSizeClass $.Editorconfig $file.Name}}" id="diff-{{.Index}}">
|
<div class="diff-file-box diff-box file-content {{TabSizeClass $.Editorconfig $file.Name}}" id="diff-{{.Index}}">
|
||||||
<h4 class="ui top attached normal header">
|
<h4 class="ui top attached normal header">
|
||||||
|
{{$isImage := false}}
|
||||||
|
{{if $file.IsDeleted}}
|
||||||
|
{{$isImage = (call $.IsImageFileInBase $file.Name)}}
|
||||||
|
{{else}}
|
||||||
|
{{$isImage = (call $.IsImageFileInHead $file.Name)}}
|
||||||
|
{{end}}
|
||||||
|
{{if or (not $file.IsBin) $isImage}}
|
||||||
|
<i class="ui fold-code grey fa fa-chevron-down"></i>
|
||||||
|
{{end}}
|
||||||
<div class="diff-counter count">
|
<div class="diff-counter count">
|
||||||
{{if $file.IsBin}}
|
{{if $file.IsBin}}
|
||||||
{{$.i18n.Tr "repo.diff.bin"}}
|
{{$.i18n.Tr "repo.diff.bin"}}
|
||||||
|
@ -104,12 +113,6 @@
|
||||||
</h4>
|
</h4>
|
||||||
<div class="ui attached unstackable table segment">
|
<div class="ui attached unstackable table segment">
|
||||||
{{if ne $file.Type 4}}
|
{{if ne $file.Type 4}}
|
||||||
{{$isImage := false}}
|
|
||||||
{{if $file.IsDeleted}}
|
|
||||||
{{$isImage = (call $.IsImageFileInBase $file.Name)}}
|
|
||||||
{{else}}
|
|
||||||
{{$isImage = (call $.IsImageFileInHead $file.Name)}}
|
|
||||||
{{end}}
|
|
||||||
<div class="file-body file-code code-view code-diff {{if $.IsSplitStyle}}code-diff-split{{else}}code-diff-unified{{end}}">
|
<div class="file-body file-code code-view code-diff {{if $.IsSplitStyle}}code-diff-split{{else}}code-diff-unified{{end}}">
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -121,12 +124,27 @@
|
||||||
{{range $j, $section := $file.Sections}}
|
{{range $j, $section := $file.Sections}}
|
||||||
{{range $k, $line := $section.Lines}}
|
{{range $k, $line := $section.Lines}}
|
||||||
<tr class="{{DiffLineTypeToStr .GetType}}-code nl-{{$k}} ol-{{$k}}">
|
<tr class="{{DiffLineTypeToStr .GetType}}-code nl-{{$k}} ol-{{$k}}">
|
||||||
|
{{if eq .GetType 4}}
|
||||||
|
<td class="lines-num lines-num-old">
|
||||||
|
{{if or (eq $line.GetExpandDirection 3) (eq $line.GetExpandDirection 5) }}
|
||||||
|
<i class="ui blob-excerpt fa fa-caret-down" data-url="{{$.RepoLink}}/blob_excerpt/{{$.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=split&direction=down" data-anchor="diff-{{Sha1 $file.Name}}K{{$line.SectionInfo.RightIdx}}"></i>
|
||||||
|
{{end}}
|
||||||
|
{{if or (eq $line.GetExpandDirection 3) (eq $line.GetExpandDirection 4) }}
|
||||||
|
<i class="ui blob-excerpt fa fa-caret-up" data-url="{{$.RepoLink}}/blob_excerpt/{{$.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=split&direction=up" data-anchor="diff-{{Sha1 $file.Name}}K{{$line.SectionInfo.RightIdx}}"></i>
|
||||||
|
{{end}}
|
||||||
|
{{if or (eq $line.GetExpandDirection 2)}}
|
||||||
|
<i class="ui blob-excerpt octicon octicon-fold" data-url="{{$.RepoLink}}/blob_excerpt/{{$.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=split&direction=" data-anchor="diff-{{Sha1 $file.Name}}K{{$line.SectionInfo.RightIdx}}"></i>
|
||||||
|
{{end}}
|
||||||
|
</td>
|
||||||
|
<td colspan="5" class="lines-code lines-code-old "><span class="mono wrap{{if $highlightClass}} language-{{$highlightClass}}{{else}} nohighlight{{end}}">{{$section.GetComputedInlineDiffFor $line}}</span></td>
|
||||||
|
{{else}}
|
||||||
<td class="lines-num lines-num-old" data-line-num="{{if $line.LeftIdx}}{{$line.LeftIdx}}{{end}}"><span rel="{{if $line.LeftIdx}}diff-{{Sha1 $file.Name}}L{{$line.LeftIdx}}{{end}}"></span></td>
|
<td class="lines-num lines-num-old" data-line-num="{{if $line.LeftIdx}}{{$line.LeftIdx}}{{end}}"><span rel="{{if $line.LeftIdx}}diff-{{Sha1 $file.Name}}L{{$line.LeftIdx}}{{end}}"></span></td>
|
||||||
<td class="lines-type-marker lines-type-marker-old">{{if $line.LeftIdx}}<span class="mono" data-type-marker="{{$line.GetLineTypeMarker}}"></span>{{end}}</td>
|
<td class="lines-type-marker lines-type-marker-old">{{if $line.LeftIdx}}<span class="mono" data-type-marker="{{$line.GetLineTypeMarker}}"></span>{{end}}</td>
|
||||||
<td class="lines-code lines-code-old halfwidth">{{if and $.SignedUserID $line.CanComment $.PageIsPullFiles (not (eq .GetType 2))}}<a class="ui green button add-code-comment add-code-comment-left" data-path="{{$file.Name}}" data-side="left" data-idx="{{$line.LeftIdx}}">+</a>{{end}}<span class="mono wrap{{if $highlightClass}} language-{{$highlightClass}}{{else}} nohighlight{{end}}">{{if $line.LeftIdx}}{{$section.GetComputedInlineDiffFor $line}}{{end}}</span></td>
|
<td class="lines-code lines-code-old halfwidth">{{if and $.SignedUserID $line.CanComment $.PageIsPullFiles (not (eq .GetType 2))}}<a class="ui green button add-code-comment add-code-comment-left" data-path="{{$file.Name}}" data-side="left" data-idx="{{$line.LeftIdx}}">+</a>{{end}}<span class="mono wrap{{if $highlightClass}} language-{{$highlightClass}}{{else}} nohighlight{{end}}">{{if $line.LeftIdx}}{{$section.GetComputedInlineDiffFor $line}}{{end}}</span></td>
|
||||||
<td class="lines-num lines-num-new" data-line-num="{{if $line.RightIdx}}{{$line.RightIdx}}{{end}}"><span rel="{{if $line.RightIdx}}diff-{{Sha1 $file.Name}}R{{$line.RightIdx}}{{end}}"></span></td>
|
<td class="lines-num lines-num-new" data-line-num="{{if $line.RightIdx}}{{$line.RightIdx}}{{end}}"><span rel="{{if $line.RightIdx}}diff-{{Sha1 $file.Name}}R{{$line.RightIdx}}{{end}}"></span></td>
|
||||||
<td class="lines-type-marker lines-type-marker-new">{{if $line.RightIdx}}<span class="mono" data-type-marker="{{$line.GetLineTypeMarker}}"></span>{{end}}</td>
|
<td class="lines-type-marker lines-type-marker-new">{{if $line.RightIdx}}<span class="mono" data-type-marker="{{$line.GetLineTypeMarker}}"></span>{{end}}</td>
|
||||||
<td class="lines-code lines-code-new halfwidth">{{if and $.SignedUserID $line.CanComment $.PageIsPullFiles (not (eq .GetType 3))}}<a class="ui green button add-code-comment add-code-comment-right" data-path="{{$file.Name}}" data-side="right" data-idx="{{$line.RightIdx}}">+</a>{{end}}<span class="mono wrap{{if $highlightClass}} language-{{$highlightClass}}{{else}} nohighlight{{end}}">{{if $line.RightIdx}}{{$section.GetComputedInlineDiffFor $line}}{{end}}</span></td>
|
<td class="lines-code lines-code-new halfwidth">{{if and $.SignedUserID $line.CanComment $.PageIsPullFiles (not (eq .GetType 3))}}<a class="ui green button add-code-comment add-code-comment-right" data-path="{{$file.Name}}" data-side="right" data-idx="{{$line.RightIdx}}">+</a>{{end}}<span class="mono wrap{{if $highlightClass}} language-{{$highlightClass}}{{else}} nohighlight{{end}}">{{if $line.RightIdx}}{{$section.GetComputedInlineDiffFor $line}}{{end}}</span></td>
|
||||||
|
{{end}}
|
||||||
</tr>
|
</tr>
|
||||||
{{if gt (len $line.Comments) 0}}
|
{{if gt (len $line.Comments) 0}}
|
||||||
<tr class="add-code-comment">
|
<tr class="add-code-comment">
|
||||||
|
|
|
@ -5,7 +5,15 @@
|
||||||
<tr class="{{DiffLineTypeToStr .GetType}}-code nl-{{$k}} ol-{{$k}}">
|
<tr class="{{DiffLineTypeToStr .GetType}}-code nl-{{$k}} ol-{{$k}}">
|
||||||
{{if eq .GetType 4}}
|
{{if eq .GetType 4}}
|
||||||
<td colspan="2" class="lines-num">
|
<td colspan="2" class="lines-num">
|
||||||
{{/* {{if gt $j 0}}<span class="fold octicon octicon-fold"></span>{{end}} */}}
|
{{if or (eq $line.GetExpandDirection 3) (eq $line.GetExpandDirection 5) }}
|
||||||
|
<i class="ui blob-excerpt fa fa-caret-down" data-url="{{$.root.RepoLink}}/blob_excerpt/{{$.root.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=unified&direction=down" data-anchor="diff-{{Sha1 $file.Name}}K{{$line.SectionInfo.RightIdx}}"></i>
|
||||||
|
{{end}}
|
||||||
|
{{if or (eq $line.GetExpandDirection 3) (eq $line.GetExpandDirection 4) }}
|
||||||
|
<i class="ui blob-excerpt fa fa-caret-up" data-url="{{$.root.RepoLink}}/blob_excerpt/{{$.root.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=unified&direction=up" data-anchor="diff-{{Sha1 $file.Name}}K{{$line.SectionInfo.RightIdx}}"></i>
|
||||||
|
{{end}}
|
||||||
|
{{if or (eq $line.GetExpandDirection 2)}}
|
||||||
|
<i class="ui blob-excerpt octicon octicon-fold" data-url="{{$.root.RepoLink}}/blob_excerpt/{{$.root.AfterCommitID}}" data-query="{{$line.GetBlobExcerptQuery}}&style=unified&direction=" data-anchor="diff-{{Sha1 $file.Name}}K{{$line.SectionInfo.RightIdx}}"></i>
|
||||||
|
{{end}}
|
||||||
</td>
|
</td>
|
||||||
{{else}}
|
{{else}}
|
||||||
<td class="lines-num lines-num-old" data-line-num="{{if $line.LeftIdx}}{{$line.LeftIdx}}{{end}}"><span rel="{{if $line.LeftIdx}}diff-{{Sha1 $file.Name}}L{{$line.LeftIdx}}{{end}}"></span></td>
|
<td class="lines-num lines-num-old" data-line-num="{{if $line.LeftIdx}}{{$line.LeftIdx}}{{end}}"><span rel="{{if $line.LeftIdx}}diff-{{Sha1 $file.Name}}L{{$line.LeftIdx}}{{end}}"></span></td>
|
||||||
|
|
|
@ -1852,6 +1852,27 @@ function initCodeView() {
|
||||||
}
|
}
|
||||||
}).trigger('hashchange');
|
}).trigger('hashchange');
|
||||||
}
|
}
|
||||||
|
$('.ui.fold-code').on('click', (e) => {
|
||||||
|
const $foldButton = $(e.target);
|
||||||
|
if ($foldButton.hasClass('fa-chevron-down')) {
|
||||||
|
$(e.target).parent().next().slideUp('fast', () => {
|
||||||
|
$foldButton.removeClass('fa-chevron-down').addClass('fa-chevron-right');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
$(e.target).parent().next().slideDown('fast', () => {
|
||||||
|
$foldButton.removeClass('fa-chevron-right').addClass('fa-chevron-down');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
function insertBlobExcerpt(e) {
|
||||||
|
const $blob = $(e.target);
|
||||||
|
const $row = $blob.parent().parent();
|
||||||
|
$.get(`${$blob.data('url')}?${$blob.data('query')}&anchor=${$blob.data('anchor')}`, (blob) => {
|
||||||
|
$row.replaceWith(blob);
|
||||||
|
$(`[data-anchor="${$blob.data('anchor')}"]`).on('click', (e) => { insertBlobExcerpt(e); });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
$('.ui.blob-excerpt').on('click', (e) => { insertBlobExcerpt(e); });
|
||||||
}
|
}
|
||||||
|
|
||||||
function initU2FAuth() {
|
function initU2FAuth() {
|
||||||
|
|
|
@ -2438,6 +2438,10 @@ tbody.commit-list {
|
||||||
padding-bottom: 8px;
|
padding-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
td.blob-excerpt {
|
||||||
|
background-color: #fafafa;
|
||||||
|
}
|
||||||
|
|
||||||
.issue-keyword {
|
.issue-keyword {
|
||||||
border-bottom: 1px dotted #959da5;
|
border-bottom: 1px dotted #959da5;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|
|
@ -108,3 +108,26 @@
|
||||||
font: 12px @monospaced-fonts, monospace;
|
font: 12px @monospaced-fonts, monospace;
|
||||||
color: rgba(0, 0, 0, 0.87);
|
color: rgba(0, 0, 0, 0.87);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ui.fold-code {
|
||||||
|
margin-right: 1em;
|
||||||
|
padding-left: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
width: 22px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.fold-code:hover {
|
||||||
|
color: #428bca;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.blob-excerpt {
|
||||||
|
display: block;
|
||||||
|
line-height: 20px;
|
||||||
|
font-size: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.blob-excerpt:hover {
|
||||||
|
color: #428bca;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue