@@ -289,8 +289,14 @@ func DiffInlineWithUnicodeEscape(s template.HTML, locale translation.Locale) Dif
289289 return DiffInline {EscapeStatus : status , Content : content }
290290}
291291
292- // GetComputedInlineDiffFor computes inline diff for the given line.
293- func (diffSection * DiffSection ) GetComputedInlineDiffFor (diffLine * DiffLine , locale translation.Locale ) DiffInline {
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+
299+ func (diffSection * DiffSection ) getComputedInlineDiffForHunk (diffLine * DiffLine , locale translation.Locale ) DiffInline {
294300 if setting .Git .DisableDiffHighlight {
295301 return getLineContent (diffLine .Content [1 :], locale )
296302 }
@@ -301,6 +307,55 @@ func (diffSection *DiffSection) GetComputedInlineDiffFor(diffLine *DiffLine, loc
301307 diff2 string
302308 )
303309
310+ language := ""
311+ if diffSection .file != nil {
312+ language = diffSection .file .Language
313+ }
314+
315+ // try to find equivalent diff line. ignore, otherwise
316+ switch diffLine .Type {
317+ case DiffLineSection :
318+ return getLineContent (diffLine .Content [1 :], locale )
319+ case DiffLineAdd :
320+ compareDiffLine = diffSection .GetLine (DiffLineDel , diffLine .RightIdx )
321+ if compareDiffLine == nil {
322+ return DiffInlineWithHighlightCode (diffSection .FileName , language , diffLine .Content [1 :], locale )
323+ }
324+ diff1 = compareDiffLine .Content
325+ diff2 = diffLine .Content
326+ case DiffLineDel :
327+ compareDiffLine = diffSection .GetLine (DiffLineAdd , diffLine .LeftIdx )
328+ if compareDiffLine == nil {
329+ return DiffInlineWithHighlightCode (diffSection .FileName , language , diffLine .Content [1 :], locale )
330+ }
331+ diff1 = diffLine .Content
332+ diff2 = compareDiffLine .Content
333+ default :
334+ if strings .IndexByte (" +-" , diffLine .Content [0 ]) > - 1 {
335+ return DiffInlineWithHighlightCode (diffSection .FileName , language , diffLine .Content [1 :], locale )
336+ }
337+ return DiffInlineWithHighlightCode (diffSection .FileName , language , diffLine .Content , locale )
338+ }
339+
340+ hcd := newHighlightCodeDiff ()
341+ diffRecord := hcd .diffWithHighlight (diffSection .FileName , language , diff1 [1 :], diff2 [1 :])
342+ // it seems that Gitea doesn't need the line wrapper of Chroma, so do not add them back
343+ // if the line wrappers are still needed in the future, it can be added back by "diffToHTML(hcd.lineWrapperTags. ...)"
344+ diffHTML := diffToHTML (nil , diffRecord , diffLine .Type )
345+ return DiffInlineWithUnicodeEscape (template .HTML (diffHTML ), locale )
346+ }
347+
348+ func (diffSection * DiffSection ) getComputedInlineDiffForFullFile (diffLine * DiffLine , locale translation.Locale ) DiffInline {
349+ if setting .Git .DisableDiffHighlight {
350+ return getLineContent (diffLine .Content [1 :], locale )
351+ }
352+
353+ var (
354+ compareDiffLine * DiffLine
355+ diff1 template.HTML
356+ diff2 template.HTML
357+ )
358+
304359 // try to find equivalent diff line. ignore, otherwise
305360 switch diffLine .Type {
306361 case DiffLineSection :
@@ -309,35 +364,46 @@ func (diffSection *DiffSection) GetComputedInlineDiffFor(diffLine *DiffLine, loc
309364 compareDiffLine = diffSection .GetLine (DiffLineDel , diffLine .RightIdx )
310365 if compareDiffLine == nil {
311366 highlightedLine := diffSection .file .highlightedNewLines [diffLine .RightIdx - 1 ]
312- return DiffInlineWithUnicodeEscape (template . HTML ( highlightedLine ) , locale )
367+ return DiffInlineWithUnicodeEscape (highlightedLine , locale )
313368 }
314369 diff1 = diffSection .file .highlightedOldLines [compareDiffLine .LeftIdx - 1 ]
315370 diff2 = diffSection .file .highlightedNewLines [diffLine .RightIdx - 1 ]
316371 case DiffLineDel :
317372 compareDiffLine = diffSection .GetLine (DiffLineAdd , diffLine .LeftIdx )
318373 if compareDiffLine == nil {
319374 highlightedLine := diffSection .file .highlightedOldLines [diffLine .LeftIdx - 1 ]
320- return DiffInlineWithUnicodeEscape (template . HTML ( highlightedLine ) , locale )
375+ return DiffInlineWithUnicodeEscape (highlightedLine , locale )
321376 }
322377 diff1 = diffSection .file .highlightedOldLines [diffLine .LeftIdx - 1 ]
323378 diff2 = diffSection .file .highlightedNewLines [compareDiffLine .RightIdx - 1 ]
324379 default :
325380 if strings .IndexByte (" +-" , diffLine .Content [0 ]) > - 1 {
326381 highlightedContent := diffSection .file .highlightedNewLines [diffLine .RightIdx - 1 ]
327- return DiffInlineWithUnicodeEscape (template . HTML ( highlightedContent ) , locale )
382+ return DiffInlineWithUnicodeEscape (highlightedContent , locale )
328383 }
329384 highlightedContent := diffSection .file .highlightedOldLines [diffLine .LeftIdx - 1 ]
330- return DiffInlineWithUnicodeEscape (template . HTML ( highlightedContent ) , locale )
385+ return DiffInlineWithUnicodeEscape (highlightedContent , locale )
331386 }
332387
333388 hcd := newHighlightCodeDiff ()
334- diffRecord := hcd .diffWithHighlight (diff1 , diff2 )
389+ diffRecord := hcd .diffWithFullFileHighlight (diff1 , diff2 )
335390 // it seems that Gitea doesn't need the line wrapper of Chroma, so do not add them back
336391 // if the line wrappers are still needed in the future, it can be added back by "diffToHTML(hcd.lineWrapperTags. ...)"
337392 diffHTML := diffToHTML (nil , diffRecord , diffLine .Type )
338393 return DiffInlineWithUnicodeEscape (template .HTML (diffHTML ), locale )
339394}
340395
396+ // GetComputedInlineDiffFor computes inline diff for the given line.
397+ func (diffSection * DiffSection ) GetComputedInlineDiffFor (diffLine * DiffLine , locale translation.Locale ) DiffInline {
398+ if diffSection .file == nil {
399+ return diffSection .getComputedInlineDiffForHunk (diffLine , locale )
400+ }
401+ if diffSection .file .shouldHighlightEntireFile {
402+ return diffSection .getComputedInlineDiffForFullFile (diffLine , locale )
403+ }
404+ return diffSection .getComputedInlineDiffForHunk (diffLine , locale )
405+ }
406+
341407// DiffFile represents a file diff.
342408type DiffFile struct {
343409 Name string
@@ -367,8 +433,9 @@ type DiffFile struct {
367433 IsSubmodule bool // if IsSubmodule==true, then there must be a SubmoduleDiffInfo
368434 SubmoduleDiffInfo * SubmoduleDiffInfo
369435
370- highlightedOldLines []string
371- highlightedNewLines []string
436+ shouldHighlightEntireFile bool
437+ highlightedOldLines []template.HTML
438+ highlightedNewLines []template.HTML
372439}
373440
374441// GetType returns type of diff file.
@@ -433,6 +500,46 @@ func (diffFile *DiffFile) ModeTranslationKey(mode string) string {
433500 }
434501}
435502
503+ func (diffFile * DiffFile ) getLineCount (commit * git.Commit ) (int , error ) {
504+ blob , err := commit .GetBlobByPath (diffFile .GetDiffFileName ())
505+ if err != nil {
506+ return 0 , err
507+ }
508+ return blob .GetBlobLineCount ()
509+ }
510+
511+ func (diffFile * DiffFile ) determineHighlightStrategy (commit , beforeCommit * git.Commit ) {
512+ diffFile .shouldHighlightEntireFile = true
513+ if commit == nil {
514+ diffFile .shouldHighlightEntireFile = false
515+ }
516+
517+ currentLineCount , err := diffFile .getLineCount (commit )
518+ if err != nil {
519+ log .Debug ("could not retrieve line count for current commit file - reverting to hunk based highlighting" )
520+ diffFile .shouldHighlightEntireFile = false
521+ }
522+
523+ beforeLineCount := 0
524+ if beforeCommit != nil {
525+ // it's possible that the current commit is the first commit
526+ // this would make the before commit nil
527+ beforeLineCount , err = diffFile .getLineCount (beforeCommit )
528+ if err != nil {
529+ log .Debug ("could not retrieve line count for previous commit file - reverting to hunk based highlighting" )
530+ diffFile .shouldHighlightEntireFile = false
531+ }
532+ }
533+
534+ if beforeLineCount > int (setting .Git .MaxDiffHighlightFileSize ) || currentLineCount > int (setting .Git .MaxDiffHighlightFileSize ) {
535+ diffFile .shouldHighlightEntireFile = false
536+ }
537+
538+ if diffFile .shouldHighlightEntireFile {
539+ diffFile .highlightedOldLines , diffFile .highlightedNewLines = highlightEntireFile (commit , beforeCommit , diffFile )
540+ }
541+ }
542+
436543func getCommitFileLineCount (commit * git.Commit , filePath string ) int {
437544 blob , err := commit .GetBlobByPath (filePath )
438545 if err != nil {
@@ -1222,7 +1329,7 @@ func GetDiff(ctx context.Context, gitRepo *git.Repository, opts *DiffOptions, fi
12221329 }
12231330 diffFile .IsGenerated = isGenerated .Value ()
12241331
1225- diffFile .highlightedOldLines , diffFile . highlightedNewLines = highlightCode (commit , beforeCommit , diffFile )
1332+ diffFile .determineHighlightStrategy (commit , beforeCommit )
12261333
12271334 tailSection := diffFile .GetTailSection (gitRepo , beforeCommit , commit )
12281335 if tailSection != nil {
@@ -1244,9 +1351,9 @@ func GetDiff(ctx context.Context, gitRepo *git.Repository, opts *DiffOptions, fi
12441351 return diff , nil
12451352}
12461353
1247- func highlightCode (commit , beforeCommit * git.Commit , diffFile * DiffFile ) ([]string , []string ) {
1248- var oldLines []string
1249- var newLines []string
1354+ func highlightEntireFile (commit , beforeCommit * git.Commit , diffFile * DiffFile ) ([]template. HTML , []template. HTML ) {
1355+ var oldLines []template. HTML
1356+ var newLines []template. HTML
12501357
12511358 if beforeCommit != nil {
12521359 oldBlob , err := beforeCommit .GetBlobByPath (diffFile .Name )
@@ -1255,7 +1362,9 @@ func highlightCode(commit, beforeCommit *git.Commit, diffFile *DiffFile) ([]stri
12551362 highlightedOldContent , _ := highlight .Code (diffFile .Name , diffFile .Language , oldContent )
12561363
12571364 splitLines := strings .Split (string (highlightedOldContent ), "\n " )
1258- oldLines = append (oldLines , splitLines ... )
1365+ for _ , line := range splitLines {
1366+ oldLines = append (oldLines , template .HTML (line ))
1367+ }
12591368 }
12601369 }
12611370
@@ -1265,7 +1374,9 @@ func highlightCode(commit, beforeCommit *git.Commit, diffFile *DiffFile) ([]stri
12651374 highlightedNewContent , _ := highlight .Code (diffFile .Name , diffFile .Language , newContent )
12661375
12671376 splitLines := strings .Split (string (highlightedNewContent ), "\n " )
1268- newLines = append (newLines , splitLines ... )
1377+ for _ , line := range splitLines {
1378+ newLines = append (newLines , template .HTML (line ))
1379+ }
12691380 }
12701381
12711382 return oldLines , newLines
0 commit comments