Skip to content

Commit 1955475

Browse files
committed
initial pass at fixing multiline comment highlighting in git diffs
1 parent b684f51 commit 1955475

File tree

2 files changed

+49
-41
lines changed

2 files changed

+49
-41
lines changed

services/gitdiff/gitdiff.go

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -289,13 +289,6 @@ func DiffInlineWithUnicodeEscape(s template.HTML, locale translation.Locale) Dif
289289
return DiffInline{EscapeStatus: status, Content: content}
290290
}
291291

292-
// DiffInlineWithHighlightCode makes a DiffInline with code highlight and hidden unicode characters escaped
293-
func DiffInlineWithHighlightCode(fileName, language, code string, locale translation.Locale) DiffInline {
294-
highlighted, _ := highlight.Code(fileName, language, code)
295-
status, content := charset.EscapeControlHTML(highlighted, locale)
296-
return DiffInline{EscapeStatus: status, Content: content}
297-
}
298-
299292
// GetComputedInlineDiffFor computes inline diff for the given line.
300293
func (diffSection *DiffSection) GetComputedInlineDiffFor(diffLine *DiffLine, locale translation.Locale) DiffInline {
301294
if setting.Git.DisableDiffHighlight {
@@ -308,41 +301,40 @@ func (diffSection *DiffSection) GetComputedInlineDiffFor(diffLine *DiffLine, loc
308301
diff2 string
309302
)
310303

311-
language := ""
312-
if diffSection.file != nil {
313-
language = diffSection.file.Language
314-
}
315-
316304
// try to find equivalent diff line. ignore, otherwise
317305
switch diffLine.Type {
318306
case DiffLineSection:
319307
return getLineContent(diffLine.Content[1:], locale)
320308
case DiffLineAdd:
321309
compareDiffLine = diffSection.GetLine(DiffLineDel, diffLine.RightIdx)
322310
if compareDiffLine == nil {
323-
return DiffInlineWithHighlightCode(diffSection.FileName, language, diffLine.Content[1:], locale)
311+
highlightedLine := diffSection.file.HighlightedNewLines[diffLine.RightIdx-1]
312+
return DiffInlineWithUnicodeEscape(template.HTML(highlightedLine), locale)
324313
}
325-
diff1 = compareDiffLine.Content
326-
diff2 = diffLine.Content
314+
diff1 = diffSection.file.HighlightedOldLines[compareDiffLine.LeftIdx-1]
315+
diff2 = diffSection.file.HighlightedNewLines[diffLine.RightIdx-1]
327316
case DiffLineDel:
328317
compareDiffLine = diffSection.GetLine(DiffLineAdd, diffLine.LeftIdx)
329318
if compareDiffLine == nil {
330-
return DiffInlineWithHighlightCode(diffSection.FileName, language, diffLine.Content[1:], locale)
319+
highlightedLine := diffSection.file.HighlightedOldLines[diffLine.LeftIdx-1]
320+
return DiffInlineWithUnicodeEscape(template.HTML(highlightedLine), locale)
331321
}
332-
diff1 = diffLine.Content
333-
diff2 = compareDiffLine.Content
322+
diff1 = diffSection.file.HighlightedOldLines[diffLine.LeftIdx-1]
323+
diff2 = diffSection.file.HighlightedNewLines[compareDiffLine.RightIdx-1]
334324
default:
335325
if strings.IndexByte(" +-", diffLine.Content[0]) > -1 {
336-
return DiffInlineWithHighlightCode(diffSection.FileName, language, diffLine.Content[1:], locale)
326+
highlightedContent := diffSection.file.HighlightedNewLines[diffLine.RightIdx-1]
327+
return DiffInlineWithUnicodeEscape(template.HTML(highlightedContent), locale)
337328
}
338-
return DiffInlineWithHighlightCode(diffSection.FileName, language, diffLine.Content, locale)
329+
highlightedContent := diffSection.file.HighlightedOldLines[diffLine.LeftIdx-1]
330+
return DiffInlineWithUnicodeEscape(template.HTML(highlightedContent), locale)
339331
}
340332

341333
hcd := newHighlightCodeDiff()
342-
diffRecord := hcd.diffWithHighlight(diffSection.FileName, language, diff1[1:], diff2[1:])
334+
diffRecord := hcd.diffWithHighlight(diffSection.FileName, diffSection.file.Language, diff1, diff2)
343335
// it seems that Gitea doesn't need the line wrapper of Chroma, so do not add them back
344336
// if the line wrappers are still needed in the future, it can be added back by "diffToHTML(hcd.lineWrapperTags. ...)"
345-
diffHTML := diffToHTML(nil, diffRecord, diffLine.Type)
337+
diffHTML := html.UnescapeString(diffToHTML(nil, diffRecord, diffLine.Type))
346338
return DiffInlineWithUnicodeEscape(template.HTML(diffHTML), locale)
347339
}
348340

@@ -374,6 +366,9 @@ type DiffFile struct {
374366

375367
IsSubmodule bool // if IsSubmodule==true, then there must be a SubmoduleDiffInfo
376368
SubmoduleDiffInfo *SubmoduleDiffInfo
369+
370+
HighlightedOldLines []string
371+
HighlightedNewLines []string
377372
}
378373

379374
// GetType returns type of diff file.
@@ -1227,6 +1222,8 @@ func GetDiff(ctx context.Context, gitRepo *git.Repository, opts *DiffOptions, fi
12271222
}
12281223
diffFile.IsGenerated = isGenerated.Value()
12291224

1225+
highlightCode(commit, beforeCommit, diffFile)
1226+
12301227
tailSection := diffFile.GetTailSection(gitRepo, beforeCommit, commit)
12311228
if tailSection != nil {
12321229
diffFile.Sections = append(diffFile.Sections, tailSection)
@@ -1247,6 +1244,34 @@ func GetDiff(ctx context.Context, gitRepo *git.Repository, opts *DiffOptions, fi
12471244
return diff, nil
12481245
}
12491246

1247+
func highlightCode(commit *git.Commit, beforeCommit *git.Commit, diffFile *DiffFile) {
1248+
if beforeCommit != nil {
1249+
oldBlob, err := beforeCommit.GetBlobByPath(diffFile.Name)
1250+
if err == nil {
1251+
oldContent, _ := oldBlob.GetBlobContent(oldBlob.Size())
1252+
highlightedOldContent, _ := highlight.Code(diffFile.Name, diffFile.Language, oldContent)
1253+
1254+
oldLines := strings.Split(string(highlightedOldContent), "\n")
1255+
diffFile.HighlightedOldLines = make([]string, len(oldLines))
1256+
for i, line := range oldLines {
1257+
diffFile.HighlightedOldLines[i] = line
1258+
}
1259+
}
1260+
}
1261+
1262+
newBlob, err := commit.GetBlobByPath(diffFile.Name)
1263+
if err == nil {
1264+
newContent, _ := newBlob.GetBlobContent(newBlob.Size())
1265+
highlightedNewContent, _ := highlight.Code(diffFile.Name, diffFile.Language, newContent)
1266+
1267+
newLines := strings.Split(string(highlightedNewContent), "\n")
1268+
diffFile.HighlightedNewLines = make([]string, len(newLines))
1269+
for i, line := range newLines {
1270+
diffFile.HighlightedNewLines[i] = line
1271+
}
1272+
}
1273+
}
1274+
12501275
type PullDiffStats struct {
12511276
NumFiles, TotalAddition, TotalDeletion int
12521277
}

services/gitdiff/highlightdiff.go

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ package gitdiff
66
import (
77
"strings"
88

9-
"code.gitea.io/gitea/modules/highlight"
10-
119
"github.com/sergi/go-diff/diffmatchpatch"
1210
)
1311

@@ -90,11 +88,8 @@ func (hcd *highlightCodeDiff) diffWithHighlight(filename, language, codeA, codeB
9088
hcd.collectUsedRunes(codeA)
9189
hcd.collectUsedRunes(codeB)
9290

93-
highlightCodeA, _ := highlight.Code(filename, language, codeA)
94-
highlightCodeB, _ := highlight.Code(filename, language, codeB)
95-
96-
convertedCodeA := hcd.convertToPlaceholders(string(highlightCodeA))
97-
convertedCodeB := hcd.convertToPlaceholders(string(highlightCodeB))
91+
convertedCodeA := hcd.convertToPlaceholders(codeA)
92+
convertedCodeB := hcd.convertToPlaceholders(codeB)
9893

9994
diffs := diffMatchPatch.DiffMain(convertedCodeA, convertedCodeB, true)
10095
diffs = diffMatchPatch.DiffCleanupEfficiency(diffs)
@@ -206,17 +201,5 @@ func (hcd *highlightCodeDiff) recoverOneDiff(diff *diffmatchpatch.Diff) {
206201
sb.WriteString(tokenToRecover)
207202
}
208203

209-
if len(tagStack) > 0 {
210-
// close all opening tags
211-
for i := len(tagStack) - 1; i >= 0; i-- {
212-
tagToClose := tagStack[i]
213-
// get the closing tag "</span>" from "<span class=...>" or "<span>"
214-
pos := strings.IndexAny(tagToClose, " >")
215-
if pos != -1 {
216-
sb.WriteString("</" + tagToClose[1:pos] + ">")
217-
} // else: impossible. every tag was pushed into the stack by the code above and is valid HTML opening tag
218-
}
219-
}
220-
221204
diff.Text = sb.String()
222205
}

0 commit comments

Comments
 (0)