44package repo
55
66import (
7+ "bytes"
78 "fmt"
8- gotemplate "html/template"
9+ "html/template"
910 "net/http"
1011 "net/url"
1112 "path"
@@ -25,18 +26,17 @@ import (
2526)
2627
2728type blameRow struct {
28- RowNumber int
29- Avatar gotemplate.HTML
30- RepoLink string
31- PartSha string
29+ RowNumber int
30+
31+ Avatar template.HTML
3232 PreviousSha string
3333 PreviousShaURL string
34- IsFirstCommit bool
3534 CommitURL string
3635 CommitMessage string
37- CommitSince gotemplate.HTML
38- Code gotemplate.HTML
39- EscapeStatus * charset.EscapeStatus
36+ CommitSince template.HTML
37+
38+ Code template.HTML
39+ EscapeStatus * charset.EscapeStatus
4040}
4141
4242// RefBlame render blame page
@@ -220,76 +220,64 @@ func processBlameParts(ctx *context.Context, blameParts []*git.BlamePart) map[st
220220 return commitNames
221221}
222222
223- func renderBlame (ctx * context.Context , blameParts []* git.BlamePart , commitNames map [string ]* user_model.UserCommit ) {
224- repoLink := ctx .Repo .RepoLink
223+ func renderBlameFillFirstBlameRow (repoLink string , avatarUtils * templates.AvatarUtils , part * git.BlamePart , commit * user_model.UserCommit , br * blameRow ) {
224+ if commit .User != nil {
225+ br .Avatar = avatarUtils .Avatar (commit .User , 18 )
226+ } else {
227+ br .Avatar = avatarUtils .AvatarByEmail (commit .Author .Email , commit .Author .Name , 18 )
228+ }
229+
230+ br .PreviousSha = part .PreviousSha
231+ br .PreviousShaURL = fmt .Sprintf ("%s/blame/commit/%s/%s" , repoLink , url .PathEscape (part .PreviousSha ), util .PathEscapeSegments (part .PreviousPath ))
232+ br .CommitURL = fmt .Sprintf ("%s/commit/%s" , repoLink , url .PathEscape (part .Sha ))
233+ br .CommitMessage = commit .CommitMessage
234+ br .CommitSince = templates .TimeSince (commit .Author .When )
235+ }
225236
237+ func renderBlame (ctx * context.Context , blameParts []* git.BlamePart , commitNames map [string ]* user_model.UserCommit ) {
226238 language , err := languagestats .GetFileLanguage (ctx , ctx .Repo .GitRepo , ctx .Repo .CommitID , ctx .Repo .TreePath )
227239 if err != nil {
228240 log .Error ("Unable to get file language for %-v:%s. Error: %v" , ctx .Repo .Repository , ctx .Repo .TreePath , err )
229241 }
230242
231- lines := make ([] string , 0 )
243+ buf := & bytes. Buffer {}
232244 rows := make ([]* blameRow , 0 )
233- escapeStatus := & charset.EscapeStatus {}
234-
235- var lexerName string
236-
237245 avatarUtils := templates .NewAvatarUtils (ctx )
238- i := 0
239- commitCnt := 0
246+ rowNumber := 0 // will be 1-based
240247 for _ , part := range blameParts {
241- for index , line := range part .Lines {
242- i ++
243- lines = append (lines , line )
244-
245- br := & blameRow {
246- RowNumber : i ,
247- }
248-
249- commit := commitNames [part .Sha ]
250- if index == 0 {
251- // Count commit number
252- commitCnt ++
253-
254- // User avatar image
255- commitSince := templates .TimeSince (commit .Author .When )
248+ for partLineIdx , line := range part .Lines {
249+ rowNumber ++
256250
257- var avatar string
258- if commit .User != nil {
259- avatar = string (avatarUtils .Avatar (commit .User , 18 ))
260- } else {
261- avatar = string (avatarUtils .AvatarByEmail (commit .Author .Email , commit .Author .Name , 18 , "tw-mr-2" ))
262- }
251+ br := & blameRow {RowNumber : rowNumber }
252+ rows = append (rows , br )
263253
264- br .Avatar = gotemplate .HTML (avatar )
265- br .RepoLink = repoLink
266- br .PartSha = part .Sha
267- br .PreviousSha = part .PreviousSha
268- br .PreviousShaURL = fmt .Sprintf ("%s/blame/commit/%s/%s" , repoLink , url .PathEscape (part .PreviousSha ), util .PathEscapeSegments (part .PreviousPath ))
269- br .CommitURL = fmt .Sprintf ("%s/commit/%s" , repoLink , url .PathEscape (part .Sha ))
270- br .CommitMessage = commit .CommitMessage
271- br .CommitSince = commitSince
254+ if int64 (buf .Len ()) < setting .UI .MaxDisplayFileSize {
255+ buf .WriteString (line )
256+ buf .WriteByte ('\n' )
272257 }
273258
274- if i != len ( lines ) - 1 {
275- line += " \n "
259+ if partLineIdx == 0 {
260+ renderBlameFillFirstBlameRow ( ctx . Repo . RepoLink , avatarUtils , part , commitNames [ part . Sha ], br )
276261 }
277- line , lexerNameForLine := highlight .Code (path .Base (ctx .Repo .TreePath ), language , line )
262+ }
263+ }
278264
279- // set lexer name to the first detected lexer. this is certainly suboptimal and
280- // we should instead highlight the whole file at once
281- if lexerName == "" {
282- lexerName = lexerNameForLine
283- }
265+ escapeStatus := & charset.EscapeStatus {}
284266
285- br .EscapeStatus , br .Code = charset .EscapeControlHTML (line , ctx .Locale )
286- rows = append (rows , br )
287- escapeStatus = escapeStatus .Or (br .EscapeStatus )
267+ bufContent := buf .Bytes ()
268+ bufContent = charset .ToUTF8 (bufContent , charset.ConvertOpts {})
269+ highlighted , lexerName := highlight .Code (path .Base (ctx .Repo .TreePath ), language , util .UnsafeBytesToString (bufContent ))
270+ unsafeLines := highlight .UnsafeSplitHighlightedLines (highlighted )
271+ for i , br := range rows {
272+ var line template.HTML
273+ if i < len (rows ) {
274+ line = template .HTML (util .UnsafeBytesToString (unsafeLines [i ]))
288275 }
276+ br .EscapeStatus , br .Code = charset .EscapeControlHTML (line , ctx .Locale )
277+ escapeStatus = escapeStatus .Or (br .EscapeStatus )
289278 }
290279
291280 ctx .Data ["EscapeStatus" ] = escapeStatus
292281 ctx .Data ["BlameRows" ] = rows
293- ctx .Data ["CommitCnt" ] = commitCnt
294282 ctx .Data ["LexerName" ] = lexerName
295283}
0 commit comments