mirror of
https://github.com/go-gitea/gitea.git
synced 2026-02-10 22:08:57 +00:00
Use full-file highlighting for diff sections (#36561)
* Fix #35252 * Fix #35999 * Improve diff rendering, don't add unnecessary "added"/"removed" tags for a full-line change * Also fix a "space trimming" bug in #36539 and add tests * Use chroma "SQL" lexer instead of "MySQL" to workaround a bug (35999)
This commit is contained in:
121
services/gitdiff/gitdiff_excerpt.go
Normal file
121
services/gitdiff/gitdiff_excerpt.go
Normal file
@@ -0,0 +1,121 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package gitdiff
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
)
|
||||
|
||||
type BlobExcerptOptions struct {
|
||||
LastLeft int
|
||||
LastRight int
|
||||
LeftIndex int
|
||||
RightIndex int
|
||||
LeftHunkSize int
|
||||
RightHunkSize int
|
||||
Direction string
|
||||
Language string
|
||||
}
|
||||
|
||||
func fillExcerptLines(section *DiffSection, filePath string, reader io.Reader, lang string, idxLeft, idxRight, chunkSize int) error {
|
||||
buf := &bytes.Buffer{}
|
||||
scanner := bufio.NewScanner(reader)
|
||||
var diffLines []*DiffLine
|
||||
for line := 0; line < idxRight+chunkSize; line++ {
|
||||
if ok := scanner.Scan(); !ok {
|
||||
break
|
||||
}
|
||||
lineText := scanner.Text()
|
||||
if buf.Len()+len(lineText) < int(setting.UI.MaxDisplayFileSize) {
|
||||
buf.WriteString(lineText)
|
||||
buf.WriteByte('\n')
|
||||
}
|
||||
if line < idxRight {
|
||||
continue
|
||||
}
|
||||
diffLine := &DiffLine{
|
||||
LeftIdx: idxLeft + (line - idxRight) + 1,
|
||||
RightIdx: line + 1,
|
||||
Type: DiffLinePlain,
|
||||
Content: " " + lineText,
|
||||
}
|
||||
diffLines = append(diffLines, diffLine)
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
return fmt.Errorf("fillExcerptLines scan: %w", err)
|
||||
}
|
||||
section.Lines = diffLines
|
||||
// DiffLinePlain always uses right lines
|
||||
section.highlightedRightLines.value = highlightCodeLines(filePath, lang, []*DiffSection{section}, false /* right */, buf.Bytes())
|
||||
return nil
|
||||
}
|
||||
|
||||
func BuildBlobExcerptDiffSection(filePath string, reader io.Reader, opts BlobExcerptOptions) (*DiffSection, error) {
|
||||
lastLeft, lastRight, idxLeft, idxRight := opts.LastLeft, opts.LastRight, opts.LeftIndex, opts.RightIndex
|
||||
leftHunkSize, rightHunkSize, direction := opts.LeftHunkSize, opts.RightHunkSize, opts.Direction
|
||||
language := opts.Language
|
||||
|
||||
chunkSize := BlobExcerptChunkSize
|
||||
section := &DiffSection{
|
||||
language: &diffVarMutable[string]{value: language},
|
||||
highlightedLeftLines: &diffVarMutable[map[int]template.HTML]{},
|
||||
highlightedRightLines: &diffVarMutable[map[int]template.HTML]{},
|
||||
FileName: filePath,
|
||||
}
|
||||
var err error
|
||||
if direction == "up" && (idxLeft-lastLeft) > chunkSize {
|
||||
idxLeft -= chunkSize
|
||||
idxRight -= chunkSize
|
||||
leftHunkSize += chunkSize
|
||||
rightHunkSize += chunkSize
|
||||
err = fillExcerptLines(section, filePath, reader, language, idxLeft-1, idxRight-1, chunkSize)
|
||||
} else if direction == "down" && (idxLeft-lastLeft) > chunkSize {
|
||||
err = fillExcerptLines(section, filePath, reader, language, lastLeft, lastRight, chunkSize)
|
||||
lastLeft += chunkSize
|
||||
lastRight += chunkSize
|
||||
} else {
|
||||
offset := -1
|
||||
if direction == "down" {
|
||||
offset = 0
|
||||
}
|
||||
err = fillExcerptLines(section, filePath, reader, language, lastLeft, lastRight, idxRight-lastRight+offset)
|
||||
leftHunkSize = 0
|
||||
rightHunkSize = 0
|
||||
idxLeft = lastLeft
|
||||
idxRight = lastRight
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newLineSection := &DiffLine{
|
||||
Type: DiffLineSection,
|
||||
SectionInfo: &DiffLineSectionInfo{
|
||||
language: &diffVarMutable[string]{value: opts.Language},
|
||||
Path: filePath,
|
||||
LastLeftIdx: lastLeft,
|
||||
LastRightIdx: lastRight,
|
||||
LeftIdx: idxLeft,
|
||||
RightIdx: idxRight,
|
||||
LeftHunkSize: leftHunkSize,
|
||||
RightHunkSize: rightHunkSize,
|
||||
},
|
||||
}
|
||||
if newLineSection.GetExpandDirection() != "" {
|
||||
newLineSection.Content = fmt.Sprintf("@@ -%d,%d +%d,%d @@\n", idxLeft, leftHunkSize, idxRight, rightHunkSize)
|
||||
switch direction {
|
||||
case "up":
|
||||
section.Lines = append([]*DiffLine{newLineSection}, section.Lines...)
|
||||
case "down":
|
||||
section.Lines = append(section.Lines, newLineSection)
|
||||
}
|
||||
}
|
||||
return section, nil
|
||||
}
|
||||
Reference in New Issue
Block a user